diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile new file mode 100644 index 0000000000000..9ae47b93759a4 --- /dev/null +++ b/.devcontainer/Dockerfile @@ -0,0 +1,2 @@ +ARG BASEIMAGE=mcr.microsoft.com/devcontainers/typescript-node:22@sha256:9791f4aa527774bc370c6bd2f6705ce5a686f1e6f204badd8dfaacce28c631ae +FROM ${BASEIMAGE} diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 0000000000000..b297f9a2d8cc1 --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,20 @@ +{ + "name": "Immich devcontainers", + "build": { + "dockerfile": "Dockerfile", + "args": { + "BASEIMAGE": "mcr.microsoft.com/devcontainers/typescript-node:22" + } + }, + "customizations": { + "vscode": { + "extensions": [ + "svelte.svelte-vscode" + ] + } + }, + "forwardPorts": [], + "postCreateCommand": "make install-all", + "remoteUser": "node" +} + diff --git a/.github/workflows/cli.yml b/.github/workflows/cli.yml index 7052fa6ef97c6..e3b2d68435146 100644 --- a/.github/workflows/cli.yml +++ b/.github/workflows/cli.yml @@ -59,7 +59,7 @@ jobs: uses: docker/setup-qemu-action@v3.2.0 - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3.7.1 + uses: docker/setup-buildx-action@v3.8.0 - name: Login to GitHub Container Registry uses: docker/login-action@v3 @@ -88,7 +88,7 @@ jobs: type=raw,value=latest,enable=${{ github.event_name == 'release' }} - name: Build and push image - uses: docker/build-push-action@v6.9.0 + uses: docker/build-push-action@v6.10.0 with: file: cli/Dockerfile platforms: linux/amd64,linux/arm64 diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 034fbe0008a62..2fac92c4e84ae 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -125,7 +125,7 @@ jobs: uses: docker/setup-qemu-action@v3.2.0 - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3.7.1 + uses: docker/setup-buildx-action@v3.8.0 - name: Login to Docker Hub # Only push to Docker Hub when making a release @@ -174,7 +174,7 @@ jobs: fi - name: Build and push image - uses: docker/build-push-action@v6.9.0 + uses: docker/build-push-action@v6.10.0 with: context: ${{ env.context }} file: ${{ env.file }} @@ -216,7 +216,7 @@ jobs: uses: docker/setup-qemu-action@v3.2.0 - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3.7.1 + uses: docker/setup-buildx-action@v3.8.0 - name: Login to Docker Hub # Only push to Docker Hub when making a release @@ -265,7 +265,7 @@ jobs: fi - name: Build and push image - uses: docker/build-push-action@v6.9.0 + uses: docker/build-push-action@v6.10.0 with: context: ${{ env.context }} file: ${{ env.file }} diff --git a/.github/workflows/pr-require-conventional-commit.yml b/.github/workflows/pr-require-conventional-commit.yml index 4899031249d27..d4bd44ec4303c 100644 --- a/.github/workflows/pr-require-conventional-commit.yml +++ b/.github/workflows/pr-require-conventional-commit.yml @@ -9,7 +9,7 @@ jobs: runs-on: ubuntu-latest steps: - name: PR Conventional Commit Validation - uses: ytanikin/PRConventionalCommits@1.2.0 + uses: ytanikin/PRConventionalCommits@1.3.0 with: task_types: '["feat","fix","docs","test","ci","refactor","perf","chore","revert"]' add_label: 'false' diff --git a/.vscode/settings.json b/.vscode/settings.json index a8661326a0998..49dbf3944cfca 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -41,4 +41,4 @@ "explorer.fileNesting.patterns": { "*.ts": "${capture}.spec.ts,${capture}.mock.ts" } -} +} \ No newline at end of file diff --git a/Makefile b/Makefile index 2096cf86df09c..0899d82d24e5a 100644 --- a/Makefile +++ b/Makefile @@ -39,7 +39,7 @@ attach-server: renovate: LOG_LEVEL=debug npx renovate --platform=local --repository-cache=reset -MODULES = e2e server web cli sdk +MODULES = e2e server web cli sdk docs audit-%: npm --prefix $(subst sdk,open-api/typescript-sdk,$*) audit fix @@ -48,11 +48,9 @@ install-%: build-cli: build-sdk build-web: build-sdk build-%: install-% - npm --prefix $(subst sdk,open-api/typescript-sdk,$*) run | grep 'build' >/dev/null \ - && npm --prefix $(subst sdk,open-api/typescript-sdk,$*) run build || true + npm --prefix $(subst sdk,open-api/typescript-sdk,$*) run build format-%: - npm --prefix $(subst sdk,open-api/typescript-sdk,$*) run | grep 'format:fix' >/dev/null \ - && npm --prefix $(subst sdk,open-api/typescript-sdk,$*) run format:fix || true + npm --prefix $* run format:fix lint-%: npm --prefix $* run lint:fix check-%: @@ -79,14 +77,14 @@ test-medium: test-medium-dev: docker exec -it immich_server /bin/sh -c "npm run test:medium" -build-all: $(foreach M,$(MODULES),build-$M) ; +build-all: $(foreach M,$(filter-out e2e,$(MODULES)),build-$M) ; install-all: $(foreach M,$(MODULES),install-$M) ; -check-all: $(foreach M,$(MODULES),check-$M) ; -lint-all: $(foreach M,$(MODULES),lint-$M) ; -format-all: $(foreach M,$(MODULES),format-$M) ; +check-all: $(foreach M,$(filter-out sdk cli docs,$(MODULES)),check-$M) ; +lint-all: $(foreach M,$(filter-out sdk docs,$(MODULES)),lint-$M) ; +format-all: $(foreach M,$(filter-out sdk,$(MODULES)),format-$M) ; audit-all: $(foreach M,$(MODULES),audit-$M) ; hygiene-all: lint-all format-all check-all sql audit-all; -test-all: $(foreach M,$(MODULES),test-$M) ; +test-all: $(foreach M,$(filter-out sdk docs,$(MODULES)),test-$M) ; clean: find . -name "node_modules" -type d -prune -exec rm -rf '{}' + diff --git a/cli/.nvmrc b/cli/.nvmrc index 7af24b7ddbde0..1d9b7831ba9d9 100644 --- a/cli/.nvmrc +++ b/cli/.nvmrc @@ -1 +1 @@ -22.11.0 +22.12.0 diff --git a/cli/Dockerfile b/cli/Dockerfile index b112382cbb2fe..31dd8576e2eaf 100644 --- a/cli/Dockerfile +++ b/cli/Dockerfile @@ -1,4 +1,4 @@ -FROM node:22.10.0-alpine3.20@sha256:fc95a044b87e95507c60c1f8c829e5d98ddf46401034932499db370c494ef0ff AS core +FROM node:22.12.0-alpine3.20@sha256:96cc8323e25c8cc6ddcb8b965e135cfd57846e8003ec0d7bcec16c5fd5f6d39f AS core WORKDIR /usr/src/open-api/typescript-sdk COPY open-api/typescript-sdk/package*.json open-api/typescript-sdk/tsconfig*.json ./ diff --git a/cli/package-lock.json b/cli/package-lock.json index 7f691935dad04..af339110d0457 100644 --- a/cli/package-lock.json +++ b/cli/package-lock.json @@ -1,12 +1,12 @@ { "name": "@immich/cli", - "version": "2.2.28", + "version": "2.2.37", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@immich/cli", - "version": "2.2.28", + "version": "2.2.37", "license": "GNU Affero General Public License version 3", "dependencies": { "fast-glob": "^3.3.2", @@ -24,17 +24,17 @@ "@types/cli-progress": "^3.11.0", "@types/lodash-es": "^4.17.12", "@types/mock-fs": "^4.13.1", - "@types/node": "^22.8.1", - "@typescript-eslint/eslint-plugin": "^8.0.0", - "@typescript-eslint/parser": "^8.0.0", + "@types/node": "^22.10.2", + "@typescript-eslint/eslint-plugin": "^8.15.0", + "@typescript-eslint/parser": "^8.15.0", "@vitest/coverage-v8": "^2.0.5", "byte-size": "^9.0.0", "cli-progress": "^3.12.0", "commander": "^12.0.0", - "eslint": "^9.0.0", + "eslint": "^9.14.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-prettier": "^5.1.3", - "eslint-plugin-unicorn": "^55.0.0", + "eslint-plugin-unicorn": "^56.0.1", "globals": "^15.9.0", "mock-fs": "^5.2.0", "prettier": "^3.2.5", @@ -52,14 +52,14 @@ }, "../open-api/typescript-sdk": { "name": "@immich/sdk", - "version": "1.119.1", + "version": "1.123.0", "dev": true, "license": "GNU Affero General Public License version 3", "dependencies": { "@oazapfts/runtime": "^1.0.2" }, "devDependencies": { - "@types/node": "^22.8.1", + "@types/node": "^22.10.2", "typescript": "^5.3.3" } }, @@ -173,19 +173,21 @@ } }, "node_modules/@babel/helper-string-parser": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz", - "integrity": "sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", + "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz", - "integrity": "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", + "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } @@ -276,12 +278,13 @@ } }, "node_modules/@babel/parser": { - "version": "7.25.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.3.tgz", - "integrity": "sha512-iLTJKDbJ4hMvFPgQwwsVoxtHyWpKKPBrxkANrSYewDPaPpT5py5yeVkgPIJ7XYXhndxJpaA3PyALSXQ7u8e/Dw==", + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.2.tgz", + "integrity": "sha512-DWMCZH9WA4Maitz2q21SRKHo9QXZxkDsbNZoVD62gusNtNBBqDg9i7uOhASfTfIGNzW+O+r7+jAlM8dwphcJKQ==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/types": "^7.25.2" + "@babel/types": "^7.26.0" }, "bin": { "parser": "bin/babel-parser.js" @@ -291,14 +294,14 @@ } }, "node_modules/@babel/types": { - "version": "7.25.2", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.2.tgz", - "integrity": "sha512-YTnYtra7W9e6/oAZEHj0bJehPRUlLH9/fbpT5LfB0NhQXyALCRkRs3zH9v07IYhkgpqX6Z78FnuccZr/l4Fs4Q==", + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.0.tgz", + "integrity": "sha512-Z/yiTPj+lDVnF7lWeKCIJzaIkI0vYO87dMpZ4bg4TDrFe4XXLFWL1TbXU27gBP3QccxV9mZICCrnjnYlJjXHOA==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-string-parser": "^7.24.8", - "@babel/helper-validator-identifier": "^7.24.7", - "to-fast-properties": "^2.0.0" + "@babel/helper-string-parser": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -717,9 +720,9 @@ } }, "node_modules/@eslint-community/regexpp": { - "version": "4.11.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.0.tgz", - "integrity": "sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A==", + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", + "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", "dev": true, "license": "MIT", "engines": { @@ -776,9 +779,9 @@ } }, "node_modules/@eslint/eslintrc": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.1.0.tgz", - "integrity": "sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.2.0.tgz", + "integrity": "sha512-grOjVNN8P3hjJn/eIETF1wwd12DdnwFDoyceUJLYYdkpbwq3nLi+4fqrTAONx7XDALqlL220wC/RHSC/QTI/0w==", "dev": true, "license": "MIT", "dependencies": { @@ -804,6 +807,7 @@ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -827,6 +831,7 @@ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" }, @@ -835,9 +840,9 @@ } }, "node_modules/@eslint/js": { - "version": "9.13.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.13.0.tgz", - "integrity": "sha512-IFLyoY4d72Z5y/6o/BazFBezupzI/taV8sGumxTAVw3lXG9A6md1Dc34T9s1FoD/an9pJH8RHbAxsaEbBed9lA==", + "version": "9.15.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.15.0.tgz", + "integrity": "sha512-tMTqrY+EzbXmKJR5ToI8lxu7jaN5EdmrBFJpQk5JmSlyLsx6o4t27r883K5xsLuCYCpfKBCGswMSWXsM+jB7lg==", "dev": true, "license": "MIT", "engines": { @@ -855,9 +860,9 @@ } }, "node_modules/@eslint/plugin-kit": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.0.tgz", - "integrity": "sha512-vH9PiIMMwvhCx31Af3HiGzsVNULDbyVkHXwlemn/B0TFj/00ho3y55efXrUZTfQipxoHC5u4xq6zblww1zm1Ig==", + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.3.tgz", + "integrity": "sha512-2b/g5hRmpbb1o4GnTZax9N9m0FXzz9OV42ZzI4rDDMDuHUqigAiQCEWChBWCY4ztAGVRjoWT19v0yMmc5/L5kA==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -868,9 +873,9 @@ } }, "node_modules/@humanfs/core": { - "version": "0.19.0", - "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.0.tgz", - "integrity": "sha512-2cbWIHbZVEweE853g8jymffCA+NCMiuqeECeBBLm8dg2oFdjuGJhgN4UAbI+6v0CKbbhvtXA4qV8YR5Ji86nmw==", + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", + "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", "dev": true, "license": "Apache-2.0", "engines": { @@ -878,19 +883,33 @@ } }, "node_modules/@humanfs/node": { - "version": "0.16.5", - "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.5.tgz", - "integrity": "sha512-KSPA4umqSG4LHYRodq31VDwKAvaTF4xmVlzM8Aeh4PlU1JQ3IG0wiA8C25d3RQ9nJyM3mBHyI53K06VVL/oFFg==", + "version": "0.16.6", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.6.tgz", + "integrity": "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@humanfs/core": "^0.19.0", + "@humanfs/core": "^0.19.1", "@humanwhocodes/retry": "^0.3.0" }, "engines": { "node": ">=18.18.0" } }, + "node_modules/@humanfs/node/node_modules/@humanwhocodes/retry": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz", + "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, "node_modules/@humanwhocodes/module-importer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", @@ -905,9 +924,9 @@ } }, "node_modules/@humanwhocodes/retry": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz", - "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==", + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.1.tgz", + "integrity": "sha512-c7hNEllBlenFTHBky65mhq8WD2kbN9Q6gk0bTk8lSBvc554jpXSkST1iePudpt7+A/AQvuHs9EMqjHDXMY1lrA==", "dev": true, "license": "Apache-2.0", "engines": { @@ -1378,13 +1397,13 @@ } }, "node_modules/@types/node": { - "version": "22.8.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.8.5.tgz", - "integrity": "sha512-5iYk6AMPtsMbkZqCO1UGF9W5L38twq11S2pYWkybGHH2ogPUvXWNlQqJBzuEZWKj/WRH+QTeiv6ySWqJtvIEgA==", + "version": "22.10.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.2.tgz", + "integrity": "sha512-Xxr6BBRCAOQixvonOye19wnzyDiUtTeqldOOmj3CkeblonbccA12PFwlufvRdrpjXxqnmUaeiU5EOA+7s5diUQ==", "dev": true, "license": "MIT", "dependencies": { - "undici-types": "~6.19.8" + "undici-types": "~6.20.0" } }, "node_modules/@types/normalize-package-data": { @@ -1394,17 +1413,17 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.11.0.tgz", - "integrity": "sha512-KhGn2LjW1PJT2A/GfDpiyOfS4a8xHQv2myUagTM5+zsormOmBlYsnQ6pobJ8XxJmh6hnHwa2Mbe3fPrDJoDhbA==", + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.15.0.tgz", + "integrity": "sha512-+zkm9AR1Ds9uLWN3fkoeXgFppaQ+uEVtfOV62dDmsy9QCNqlRHWNEck4yarvRNrvRcHQLGfqBNui3cimoz8XAg==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.11.0", - "@typescript-eslint/type-utils": "8.11.0", - "@typescript-eslint/utils": "8.11.0", - "@typescript-eslint/visitor-keys": "8.11.0", + "@typescript-eslint/scope-manager": "8.15.0", + "@typescript-eslint/type-utils": "8.15.0", + "@typescript-eslint/utils": "8.15.0", + "@typescript-eslint/visitor-keys": "8.15.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", @@ -1428,16 +1447,16 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.11.0.tgz", - "integrity": "sha512-lmt73NeHdy1Q/2ul295Qy3uninSqi6wQI18XwSpm8w0ZbQXUpjCAWP1Vlv/obudoBiIjJVjlztjQ+d/Md98Yxg==", + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.15.0.tgz", + "integrity": "sha512-7n59qFpghG4uazrF9qtGKBZXn7Oz4sOMm8dwNWDQY96Xlm2oX67eipqcblDj+oY1lLCbf1oltMZFpUso66Kl1A==", "dev": true, "license": "BSD-2-Clause", "dependencies": { - "@typescript-eslint/scope-manager": "8.11.0", - "@typescript-eslint/types": "8.11.0", - "@typescript-eslint/typescript-estree": "8.11.0", - "@typescript-eslint/visitor-keys": "8.11.0", + "@typescript-eslint/scope-manager": "8.15.0", + "@typescript-eslint/types": "8.15.0", + "@typescript-eslint/typescript-estree": "8.15.0", + "@typescript-eslint/visitor-keys": "8.15.0", "debug": "^4.3.4" }, "engines": { @@ -1457,14 +1476,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.11.0.tgz", - "integrity": "sha512-Uholz7tWhXmA4r6epo+vaeV7yjdKy5QFCERMjs1kMVsLRKIrSdM6o21W2He9ftp5PP6aWOVpD5zvrvuHZC0bMQ==", + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.15.0.tgz", + "integrity": "sha512-QRGy8ADi4J7ii95xz4UoiymmmMd/zuy9azCaamnZ3FM8T5fZcex8UfJcjkiEZjJSztKfEBe3dZ5T/5RHAmw2mA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.11.0", - "@typescript-eslint/visitor-keys": "8.11.0" + "@typescript-eslint/types": "8.15.0", + "@typescript-eslint/visitor-keys": "8.15.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1475,14 +1494,14 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.11.0.tgz", - "integrity": "sha512-ItiMfJS6pQU0NIKAaybBKkuVzo6IdnAhPFZA/2Mba/uBjuPQPet/8+zh5GtLHwmuFRShZx+8lhIs7/QeDHflOg==", + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.15.0.tgz", + "integrity": "sha512-UU6uwXDoI3JGSXmcdnP5d8Fffa2KayOhUUqr/AiBnG1Gl7+7ut/oyagVeSkh7bxQ0zSXV9ptRh/4N15nkCqnpw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "8.11.0", - "@typescript-eslint/utils": "8.11.0", + "@typescript-eslint/typescript-estree": "8.15.0", + "@typescript-eslint/utils": "8.15.0", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" }, @@ -1493,6 +1512,9 @@ "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0" + }, "peerDependenciesMeta": { "typescript": { "optional": true @@ -1500,9 +1522,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.11.0.tgz", - "integrity": "sha512-tn6sNMHf6EBAYMvmPUaKaVeYvhUsrE6x+bXQTxjQRp360h1giATU0WvgeEys1spbvb5R+VpNOZ+XJmjD8wOUHw==", + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.15.0.tgz", + "integrity": "sha512-n3Gt8Y/KyJNe0S3yDCD2RVKrHBC4gTUcLTebVBXacPy091E6tNspFLKRXlk3hwT4G55nfr1n2AdFqi/XMxzmPQ==", "dev": true, "license": "MIT", "engines": { @@ -1514,14 +1536,14 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.11.0.tgz", - "integrity": "sha512-yHC3s1z1RCHoCz5t06gf7jH24rr3vns08XXhfEqzYpd6Hll3z/3g23JRi0jM8A47UFKNc3u/y5KIMx8Ynbjohg==", + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.15.0.tgz", + "integrity": "sha512-1eMp2JgNec/niZsR7ioFBlsh/Fk0oJbhaqO0jRyQBMgkz7RrFfkqF9lYYmBoGBaSiLnu8TAPQTwoTUiSTUW9dg==", "dev": true, "license": "BSD-2-Clause", "dependencies": { - "@typescript-eslint/types": "8.11.0", - "@typescript-eslint/visitor-keys": "8.11.0", + "@typescript-eslint/types": "8.15.0", + "@typescript-eslint/visitor-keys": "8.15.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -1543,16 +1565,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.11.0.tgz", - "integrity": "sha512-CYiX6WZcbXNJV7UNB4PLDIBtSdRmRI/nb0FMyqHPTQD1rMjA0foPLaPUV39C/MxkTd/QKSeX+Gb34PPsDVC35g==", + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.15.0.tgz", + "integrity": "sha512-k82RI9yGhr0QM3Dnq+egEpz9qB6Un+WLYhmoNcvl8ltMEededhh7otBVVIDDsEEttauwdY/hQoSsOv13lxrFzQ==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.11.0", - "@typescript-eslint/types": "8.11.0", - "@typescript-eslint/typescript-estree": "8.11.0" + "@typescript-eslint/scope-manager": "8.15.0", + "@typescript-eslint/types": "8.15.0", + "@typescript-eslint/typescript-estree": "8.15.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1563,17 +1585,22 @@ }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.11.0.tgz", - "integrity": "sha512-EaewX6lxSjRJnc+99+dqzTeoDZUfyrA52d2/HRrkI830kgovWsmIiTfmr0NZorzqic7ga+1bS60lRBUgR3n/Bw==", + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.15.0.tgz", + "integrity": "sha512-h8vYOulWec9LhpwfAdZf2bjr8xIp0KNKnpgqSz0qqYYKAW/QZKw3ktRndbiAtUz4acH4QLQavwZBYCc0wulA/Q==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.11.0", - "eslint-visitor-keys": "^3.4.3" + "@typescript-eslint/types": "8.15.0", + "eslint-visitor-keys": "^4.2.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1583,23 +1610,36 @@ "url": "https://opencollective.com/typescript-eslint" } }, + "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", + "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, "node_modules/@vitest/coverage-v8": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-2.1.3.tgz", - "integrity": "sha512-2OJ3c7UPoFSmBZwqD2VEkUw6A/tzPF0LmW0ZZhhB8PFxuc+9IBG/FaSM+RLEenc7ljzFvGN+G0nGQoZnh7sy2A==", + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-2.1.5.tgz", + "integrity": "sha512-/RoopB7XGW7UEkUndRXF87A9CwkoZAJW01pj8/3pgmDVsjMH2IKy6H1A38po9tmUlwhSyYs0az82rbKd9Yaynw==", "dev": true, "license": "MIT", "dependencies": { "@ampproject/remapping": "^2.3.0", "@bcoe/v8-coverage": "^0.2.3", - "debug": "^4.3.6", + "debug": "^4.3.7", "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.11", - "magicast": "^0.3.4", - "std-env": "^3.7.0", + "magic-string": "^0.30.12", + "magicast": "^0.3.5", + "std-env": "^3.8.0", "test-exclude": "^7.0.1", "tinyrainbow": "^1.2.0" }, @@ -1607,8 +1647,8 @@ "url": "https://opencollective.com/vitest" }, "peerDependencies": { - "@vitest/browser": "2.1.3", - "vitest": "2.1.3" + "@vitest/browser": "2.1.5", + "vitest": "2.1.5" }, "peerDependenciesMeta": { "@vitest/browser": { @@ -1617,15 +1657,15 @@ } }, "node_modules/@vitest/expect": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-2.1.3.tgz", - "integrity": "sha512-SNBoPubeCJhZ48agjXruCI57DvxcsivVDdWz+SSsmjTT4QN/DfHk3zB/xKsJqMs26bLZ/pNRLnCf0j679i0uWQ==", + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-2.1.5.tgz", + "integrity": "sha512-nZSBTW1XIdpZvEJyoP/Sy8fUg0b8od7ZpGDkTUcfJ7wz/VoZAFzFfLyxVxGFhUjJzhYqSbIpfMtl/+k/dpWa3Q==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/spy": "2.1.3", - "@vitest/utils": "2.1.3", - "chai": "^5.1.1", + "@vitest/spy": "2.1.5", + "@vitest/utils": "2.1.5", + "chai": "^5.1.2", "tinyrainbow": "^1.2.0" }, "funding": { @@ -1633,22 +1673,21 @@ } }, "node_modules/@vitest/mocker": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-2.1.3.tgz", - "integrity": "sha512-eSpdY/eJDuOvuTA3ASzCjdithHa+GIF1L4PqtEELl6Qa3XafdMLBpBlZCIUCX2J+Q6sNmjmxtosAG62fK4BlqQ==", + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-2.1.5.tgz", + "integrity": "sha512-XYW6l3UuBmitWqSUXTNXcVBUCRytDogBsWuNXQijc00dtnU/9OqpXWp4OJroVrad/gLIomAq9aW8yWDBtMthhQ==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/spy": "2.1.3", + "@vitest/spy": "2.1.5", "estree-walker": "^3.0.3", - "magic-string": "^0.30.11" + "magic-string": "^0.30.12" }, "funding": { "url": "https://opencollective.com/vitest" }, "peerDependencies": { - "@vitest/spy": "2.1.3", - "msw": "^2.3.5", + "msw": "^2.4.9", "vite": "^5.0.0" }, "peerDependenciesMeta": { @@ -1661,9 +1700,9 @@ } }, "node_modules/@vitest/pretty-format": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-2.1.3.tgz", - "integrity": "sha512-XH1XdtoLZCpqV59KRbPrIhFCOO0hErxrQCMcvnQete3Vibb9UeIOX02uFPfVn3Z9ZXsq78etlfyhnkmIZSzIwQ==", + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-2.1.5.tgz", + "integrity": "sha512-4ZOwtk2bqG5Y6xRGHcveZVr+6txkH7M2e+nPFd6guSoN638v/1XQ0K06eOpi0ptVU/2tW/pIU4IoPotY/GZ9fw==", "dev": true, "license": "MIT", "dependencies": { @@ -1674,13 +1713,13 @@ } }, "node_modules/@vitest/runner": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-2.1.3.tgz", - "integrity": "sha512-JGzpWqmFJ4fq5ZKHtVO3Xuy1iF2rHGV4d/pdzgkYHm1+gOzNZtqjvyiaDGJytRyMU54qkxpNzCx+PErzJ1/JqQ==", + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-2.1.5.tgz", + "integrity": "sha512-pKHKy3uaUdh7X6p1pxOkgkVAFW7r2I818vHDthYLvUyjRfkKOU6P45PztOch4DZarWQne+VOaIMwA/erSSpB9g==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/utils": "2.1.3", + "@vitest/utils": "2.1.5", "pathe": "^1.1.2" }, "funding": { @@ -1688,14 +1727,14 @@ } }, "node_modules/@vitest/snapshot": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-2.1.3.tgz", - "integrity": "sha512-qWC2mWc7VAXmjAkEKxrScWHWFyCQx/cmiZtuGqMi+WwqQJ2iURsVY4ZfAK6dVo6K2smKRU6l3BPwqEBvhnpQGg==", + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-2.1.5.tgz", + "integrity": "sha512-zmYw47mhfdfnYbuhkQvkkzYroXUumrwWDGlMjpdUr4jBd3HZiV2w7CQHj+z7AAS4VOtWxI4Zt4bWt4/sKcoIjg==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "2.1.3", - "magic-string": "^0.30.11", + "@vitest/pretty-format": "2.1.5", + "magic-string": "^0.30.12", "pathe": "^1.1.2" }, "funding": { @@ -1703,27 +1742,27 @@ } }, "node_modules/@vitest/spy": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-2.1.3.tgz", - "integrity": "sha512-Nb2UzbcUswzeSP7JksMDaqsI43Sj5+Kry6ry6jQJT4b5gAK+NS9NED6mDb8FlMRCX8m5guaHCDZmqYMMWRy5nQ==", + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-2.1.5.tgz", + "integrity": "sha512-aWZF3P0r3w6DiYTVskOYuhBc7EMc3jvn1TkBg8ttylFFRqNN2XGD7V5a4aQdk6QiUzZQ4klNBSpCLJgWNdIiNw==", "dev": true, "license": "MIT", "dependencies": { - "tinyspy": "^3.0.0" + "tinyspy": "^3.0.2" }, "funding": { "url": "https://opencollective.com/vitest" } }, "node_modules/@vitest/utils": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-2.1.3.tgz", - "integrity": "sha512-xpiVfDSg1RrYT0tX6czgerkpcKFmFOF/gCr30+Mve5V2kewCy4Prn1/NDMSRwaSmT7PRaOF83wu+bEtsY1wrvA==", + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-2.1.5.tgz", + "integrity": "sha512-yfj6Yrp0Vesw2cwJbP+cl04OC+IHFsuQsrsJBL9pyGeQXE56v1UAOQco+SR55Vf1nQzfV0QJg1Qum7AaWUwwYg==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "2.1.3", - "loupe": "^3.1.1", + "@vitest/pretty-format": "2.1.5", + "loupe": "^3.1.2", "tinyrainbow": "^1.2.0" }, "funding": { @@ -1731,9 +1770,9 @@ } }, "node_modules/acorn": { - "version": "8.12.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", - "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", + "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", "dev": true, "license": "MIT", "bin": { @@ -1837,9 +1876,9 @@ } }, "node_modules/browserslist": { - "version": "4.23.0", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz", - "integrity": "sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==", + "version": "4.24.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.3.tgz", + "integrity": "sha512-1CPmv8iobE2fyRMV97dAcMVegvvWKxmq94hkLiAkUGwKVTyDLw33K+ZxiFrREKmmps4rIw6grcCFCnTMSZ/YiA==", "dev": true, "funding": [ { @@ -1855,11 +1894,12 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "dependencies": { - "caniuse-lite": "^1.0.30001587", - "electron-to-chromium": "^1.4.668", - "node-releases": "^2.0.14", - "update-browserslist-db": "^1.0.13" + "caniuse-lite": "^1.0.30001688", + "electron-to-chromium": "^1.5.73", + "node-releases": "^2.0.19", + "update-browserslist-db": "^1.1.1" }, "bin": { "browserslist": "cli.js" @@ -1910,9 +1950,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001597", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001597.tgz", - "integrity": "sha512-7LjJvmQU6Sj7bL0j5b5WY/3n7utXUJvAe1lxhsHDbLmwX9mdL86Yjtr+5SRCyf8qME4M7pU2hswj0FpyBVCv9w==", + "version": "1.0.30001689", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001689.tgz", + "integrity": "sha512-CmeR2VBycfa+5/jOfnp/NpWPGd06nf1XYiefUvhXFfZE4GkRc9jv+eGPS4nT558WS/8lYCzV8SlANCIPvbWP1g==", "dev": true, "funding": [ { @@ -1927,12 +1967,13 @@ "type": "github", "url": "https://github.com/sponsors/ai" } - ] + ], + "license": "CC-BY-4.0" }, "node_modules/chai": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/chai/-/chai-5.1.1.tgz", - "integrity": "sha512-pT1ZgP8rPNqUgieVaEY+ryQr6Q4HXNg8Ei9UnLUrjN4IA7dvQC5JB+/kxVcPNDHyBcc/26CXPkbNzq3qwrOEKA==", + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/chai/-/chai-5.1.2.tgz", + "integrity": "sha512-aGtmf24DW6MLHHG5gCx4zaI3uBq3KRtxeVs0DjFH6Z0rDNbsvTxFASFvdj79pxjxZ8/5u3PIiN3IwEIQkiiuPw==", "dev": true, "license": "MIT", "dependencies": { @@ -2052,15 +2093,17 @@ "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/core-js-compat": { - "version": "3.37.1", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.37.1.tgz", - "integrity": "sha512-9TNiImhKvQqSUkOvk/mMRZzOANTiEVC7WaBNhHcKM7x+/5E1l5NvsysR19zuDQScE8k+kfQXWRN3AtS/eOSHpg==", + "version": "3.39.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.39.0.tgz", + "integrity": "sha512-VgEUx3VwlExr5no0tXlBt+silBvhTryPwCXRI2Id1PN8WTKu7MreethvddqOubrYxkFdv/RnYrqlv1sFNAUelw==", "dev": true, + "license": "MIT", "dependencies": { - "browserslist": "^4.23.0" + "browserslist": "^4.24.2" }, "funding": { "type": "opencollective", @@ -2068,10 +2111,11 @@ } }, "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "dev": true, + "license": "MIT", "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -2082,12 +2126,13 @@ } }, "node_modules/debug": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", - "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", "dev": true, + "license": "MIT", "dependencies": { - "ms": "2.1.2" + "ms": "^2.1.3" }, "engines": { "node": ">=6.0" @@ -2121,10 +2166,11 @@ "dev": true }, "node_modules/electron-to-chromium": { - "version": "1.4.705", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.705.tgz", - "integrity": "sha512-LKqhpwJCLhYId2VVwEzFXWrqQI5n5zBppz1W9ehhTlfYU8CUUW6kClbN8LHF/v7flMgRdETS772nqywJ+ckVAw==", - "dev": true + "version": "1.5.74", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.74.tgz", + "integrity": "sha512-ck3//9RC+6oss/1Bh9tiAVFy5vfSKbRHAFh7Z3/eTRkEqJeWgymloShB17Vg3Z4nmDNp35vAd1BZ6CMW4Wt6Iw==", + "dev": true, + "license": "ISC" }, "node_modules/emoji-regex": { "version": "8.0.0", @@ -2141,6 +2187,13 @@ "is-arrayish": "^0.2.1" } }, + "node_modules/es-module-lexer": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.5.4.tgz", + "integrity": "sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==", + "dev": true, + "license": "MIT" + }, "node_modules/esbuild": { "version": "0.21.5", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", @@ -2181,10 +2234,11 @@ } }, "node_modules/escalade": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", - "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -2202,22 +2256,22 @@ } }, "node_modules/eslint": { - "version": "9.13.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.13.0.tgz", - "integrity": "sha512-EYZK6SX6zjFHST/HRytOdA/zE72Cq/bfw45LSyuwrdvcclb/gqV8RRQxywOBEWO2+WDpva6UZa4CcDeJKzUCFA==", + "version": "9.14.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.14.0.tgz", + "integrity": "sha512-c2FHsVBr87lnUtjP4Yhvk4yEhKrQavGafRA/Se1ouse8PfbfC/Qh9Mxa00yWsZRlqeUB9raXip0aiiUZkgnr9g==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.11.0", + "@eslint-community/regexpp": "^4.12.1", "@eslint/config-array": "^0.18.0", "@eslint/core": "^0.7.0", "@eslint/eslintrc": "^3.1.0", - "@eslint/js": "9.13.0", + "@eslint/js": "9.14.0", "@eslint/plugin-kit": "^0.2.0", - "@humanfs/node": "^0.16.5", + "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", - "@humanwhocodes/retry": "^0.3.1", + "@humanwhocodes/retry": "^0.4.0", "@types/estree": "^1.0.6", "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", @@ -2225,9 +2279,9 @@ "cross-spawn": "^7.0.2", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^8.1.0", - "eslint-visitor-keys": "^4.1.0", - "espree": "^10.2.0", + "eslint-scope": "^8.2.0", + "eslint-visitor-keys": "^4.2.0", + "espree": "^10.3.0", "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", @@ -2306,19 +2360,19 @@ } }, "node_modules/eslint-plugin-unicorn": { - "version": "55.0.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-unicorn/-/eslint-plugin-unicorn-55.0.0.tgz", - "integrity": "sha512-n3AKiVpY2/uDcGrS3+QsYDkjPfaOrNrsfQxU9nt5nitd9KuvVXrfAvgCO9DYPSfap+Gqjw9EOrXIsBp5tlHZjA==", + "version": "56.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-unicorn/-/eslint-plugin-unicorn-56.0.1.tgz", + "integrity": "sha512-FwVV0Uwf8XPfVnKSGpMg7NtlZh0G0gBarCaFcMUOoqPxXryxdYxTRRv4kH6B9TFCVIrjRXG+emcxIk2ayZilog==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-validator-identifier": "^7.24.5", + "@babel/helper-validator-identifier": "^7.24.7", "@eslint-community/eslint-utils": "^4.4.0", "ci-info": "^4.0.0", "clean-regexp": "^1.0.0", - "core-js-compat": "^3.37.0", - "esquery": "^1.5.0", - "globals": "^15.7.0", + "core-js-compat": "^3.38.1", + "esquery": "^1.6.0", + "globals": "^15.9.0", "indent-string": "^4.0.0", "is-builtin-module": "^3.2.1", "jsesc": "^3.0.2", @@ -2326,7 +2380,7 @@ "read-pkg-up": "^7.0.1", "regexp-tree": "^0.1.27", "regjsparser": "^0.10.0", - "semver": "^7.6.1", + "semver": "^7.6.3", "strip-indent": "^3.0.0" }, "engines": { @@ -2340,9 +2394,9 @@ } }, "node_modules/eslint-scope": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.1.0.tgz", - "integrity": "sha512-14dSvlhaVhKKsa9Fx1l8A17s7ah7Ef7wCakJ10LYk6+GYmP9yDti2oq2SEwcyndt6knfcZyhyxwY3i9yL78EQw==", + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.2.0.tgz", + "integrity": "sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A==", "dev": true, "license": "BSD-2-Clause", "dependencies": { @@ -2368,6 +2422,16 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/eslint/node_modules/@eslint/js": { + "version": "9.14.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.14.0.tgz", + "integrity": "sha512-pFoEtFWCPyDOl+C6Ift+wC7Ro89otjigCf5vcuWqWgqNSQbRrpjSvdeE6ofLz4dHmyxD5f7gIdGT4+p36L6Twg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, "node_modules/eslint/node_modules/@types/estree": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", @@ -2413,15 +2477,15 @@ } }, "node_modules/espree": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-10.2.0.tgz", - "integrity": "sha512-upbkBJbckcCNBDBDXEbuhjbP68n+scUd3k/U2EkyM9nw+I/jPiL4cLF/Al06CF96wRltFda16sxDFrxsI1v0/g==", + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.3.0.tgz", + "integrity": "sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==", "dev": true, "license": "BSD-2-Clause", "dependencies": { - "acorn": "^8.12.0", + "acorn": "^8.14.0", "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^4.1.0" + "eslint-visitor-keys": "^4.2.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2431,9 +2495,9 @@ } }, "node_modules/espree/node_modules/eslint-visitor-keys": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.1.0.tgz", - "integrity": "sha512-Q7lok0mqMUSf5a/AdAZkA5a/gHcO6snwQClVNNvFKCAVlxXucdU8pKydU5ZVZjBx5xr37vGbFFWtLQYreLzrZg==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", + "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", "dev": true, "license": "Apache-2.0", "engines": { @@ -2444,10 +2508,11 @@ } }, "node_modules/esquery": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", - "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "estraverse": "^5.1.0" }, @@ -2496,6 +2561,16 @@ "node": ">=0.10.0" } }, + "node_modules/expect-type": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.1.0.tgz", + "integrity": "sha512-bFi65yM+xZgk+u/KRIpekdSYkTB5W1pEf0Lt8Q8Msh7b+eQ7LXVtIB1Bkm4fvclDEL1b2CZkMhv2mOeF8tMdkA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -2688,9 +2763,9 @@ } }, "node_modules/globals": { - "version": "15.11.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-15.11.0.tgz", - "integrity": "sha512-yeyNSjdbyVaWurlwCpcA6XNBrHTMIeDdj0/hnvX/OLJ9ekOXYbLsLinH/MucQyGvNnXhidTdNhTtJaffL2sMfw==", + "version": "15.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-15.12.0.tgz", + "integrity": "sha512-1+gLErljJFhbOVyaetcwJiJ4+eLe45S2E7P5UiZ9xGfeq3ATQf5DOv9G7MH3gGbKQLkzmNh2DxfZwLdw+j6oTQ==", "dev": true, "license": "MIT", "engines": { @@ -3052,22 +3127,24 @@ "dev": true }, "node_modules/magic-string": { - "version": "0.30.11", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.11.tgz", - "integrity": "sha512-+Wri9p0QHMy+545hKww7YAu5NyzF8iomPL/RQazugQ9+Ez4Ic3mERMd8ZTX5rfK944j+560ZJi8iAwgak1Ac7A==", + "version": "0.30.12", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.12.tgz", + "integrity": "sha512-Ea8I3sQMVXr8JhN4z+H/d8zwo+tYDgHE9+5G4Wnrwhs0gaK9fXTKx0Tw5Xwsd/bCPTTZNRAdpyzvoeORe9LYpw==", "dev": true, + "license": "MIT", "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0" } }, "node_modules/magicast": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/magicast/-/magicast-0.3.4.tgz", - "integrity": "sha512-TyDF/Pn36bBji9rWKHlZe+PZb6Mx5V8IHCSxk7X4aljM4e/vyDvZZYwHewdVaqiA0nb3ghfHU/6AUpDxWoER2Q==", + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/magicast/-/magicast-0.3.5.tgz", + "integrity": "sha512-L0WhttDl+2BOsybvEOLK7fW3UA0OQ0IQ2d6Zl2x/a6vVRs3bAY0ECOSHHeL5jD+SbOpOCUEi0y1DgHEn9Qn1AQ==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/parser": "^7.24.4", - "@babel/types": "^7.24.0", + "@babel/parser": "^7.25.4", + "@babel/types": "^7.25.4", "source-map-js": "^1.2.0" } }, @@ -3141,9 +3218,9 @@ } }, "node_modules/mock-fs": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/mock-fs/-/mock-fs-5.4.0.tgz", - "integrity": "sha512-3ROPnEMgBOkusBMYQUW2rnT3wZwsgfOKzJDLvx/TZ7FL1WmWvwSwn3j4aDR5fLDGtgcc1WF0Z1y0di7c9L4FKw==", + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/mock-fs/-/mock-fs-5.4.1.tgz", + "integrity": "sha512-sz/Q8K1gXXXHR+qr0GZg2ysxCRr323kuN10O7CtQjraJsFDJ4SJ+0I5MzALz7aRp9lHk8Cc/YdsT95h9Ka1aFw==", "dev": true, "license": "MIT", "engines": { @@ -3151,10 +3228,11 @@ } }, "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" }, "node_modules/nanoid": { "version": "3.3.7", @@ -3181,10 +3259,11 @@ "dev": true }, "node_modules/node-releases": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", - "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", - "dev": true + "version": "2.0.19", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", + "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==", + "dev": true, + "license": "MIT" }, "node_modules/normalize-package-data": { "version": "2.5.0", @@ -3720,10 +3799,11 @@ } }, "node_modules/semver": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", - "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", "dev": true, + "license": "ISC", "bin": { "semver": "bin/semver.js" }, @@ -3819,10 +3899,11 @@ "dev": true }, "node_modules/std-env": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.7.0.tgz", - "integrity": "sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg==", - "dev": true + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.8.0.tgz", + "integrity": "sha512-Bc3YwwCB+OzldMxOXJIIvC6cPRWr/LxOp48CdQTOkPyk/t4JWWJbrilwBd7RJzKV8QW7tJkcgAmeuLLJugl5/w==", + "dev": true, + "license": "MIT" }, "node_modules/string-width": { "version": "4.2.3", @@ -3961,7 +4042,8 @@ "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/tinybench": { "version": "2.9.0", @@ -3971,17 +4053,18 @@ "license": "MIT" }, "node_modules/tinyexec": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.0.tgz", - "integrity": "sha512-tVGE0mVJPGb0chKhqmsoosjsS+qUnJVGJpZgsHYQcGoPlG3B51R3PouqTgEGH2Dc9jjFyOqOpix6ZHNMXp1FZg==", + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.1.tgz", + "integrity": "sha512-WiCJLEECkO18gwqIp6+hJg0//p23HXp4S+gGtAKu3mI2F2/sXC4FvHvXvB0zJVVaTPhx1/tOwdbRsa1sOBIKqQ==", "dev": true, "license": "MIT" }, "node_modules/tinypool": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.0.0.tgz", - "integrity": "sha512-KIKExllK7jp3uvrNtvRBYBWBOAXSX8ZvoaD8T+7KB/QHIuoJW3Pmr60zucywjAlMb5TeXUkcs/MWeWLu0qvuAQ==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.0.1.tgz", + "integrity": "sha512-URZYihUbRPcGv95En+sz6MfghfIc2OJ1sv/RmhWZLouPY0/8Vo80viwPvg3dlaS9fuq7fQMEfgRRK7BBZThBEA==", "dev": true, + "license": "MIT", "engines": { "node": "^18.0.0 || >=20.0.0" } @@ -4005,15 +4088,6 @@ "node": ">=14.0.0" } }, - "node_modules/to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", - "dev": true, - "engines": { - "node": ">=4" - } - }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -4090,16 +4164,16 @@ } }, "node_modules/undici-types": { - "version": "6.19.8", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", - "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", + "version": "6.20.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", + "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", "dev": true, "license": "MIT" }, "node_modules/update-browserslist-db": { - "version": "1.0.13", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", - "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz", + "integrity": "sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==", "dev": true, "funding": [ { @@ -4115,9 +4189,10 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "dependencies": { - "escalade": "^3.1.1", - "picocolors": "^1.0.0" + "escalade": "^3.2.0", + "picocolors": "^1.1.0" }, "bin": { "update-browserslist-db": "cli.js" @@ -4146,9 +4221,9 @@ } }, "node_modules/vite": { - "version": "5.4.10", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.10.tgz", - "integrity": "sha512-1hvaPshuPUtxeQ0hsVH3Mud0ZanOLwVTneA1EgbAM5LhaZEqyPWGRQ7BtaMvUrTDeEaC8pxtj6a6jku3x4z6SQ==", + "version": "5.4.11", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.11.tgz", + "integrity": "sha512-c7jFQRklXua0mTzneGW9QVyxFjUgwcihC4bXEtujIo2ouWCe1Ajt/amn2PCxYnhYfd5k09JX3SB7OYWFKYqj8Q==", "dev": true, "license": "MIT", "dependencies": { @@ -4206,14 +4281,15 @@ } }, "node_modules/vite-node": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-2.1.3.tgz", - "integrity": "sha512-I1JadzO+xYX887S39Do+paRePCKoiDrWRRjp9kkG5he0t7RXNvPAJPCQSJqbGN4uCrFFeS3Kj3sLqY8NMYBEdA==", + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-2.1.5.tgz", + "integrity": "sha512-rd0QIgx74q4S1Rd56XIiL2cYEdyWn13cunYBIuqh9mpmQr7gGS0IxXoP8R6OaZtNQQLyXSWbd4rXKYUbhFpK5w==", "dev": true, "license": "MIT", "dependencies": { "cac": "^6.7.14", - "debug": "^4.3.6", + "debug": "^4.3.7", + "es-module-lexer": "^1.5.4", "pathe": "^1.1.2", "vite": "^5.0.0" }, @@ -4228,9 +4304,9 @@ } }, "node_modules/vite-tsconfig-paths": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/vite-tsconfig-paths/-/vite-tsconfig-paths-5.0.1.tgz", - "integrity": "sha512-yqwv+LstU7NwPeNqajZzLEBVpUFU6Dugtb2P84FXuvaoYA+/70l9MHE+GYfYAycVyPSDYZ7mjOFuYBRqlEpTig==", + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/vite-tsconfig-paths/-/vite-tsconfig-paths-5.1.2.tgz", + "integrity": "sha512-gEIbKfJzSEv0yR3XS2QEocKetONoWkbROj6hGx0FHM18qKUojhvcokQsxQx5nMkelZq2n37zbSGCJn+FSODSjA==", "dev": true, "license": "MIT", "dependencies": { @@ -4248,30 +4324,31 @@ } }, "node_modules/vitest": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-2.1.3.tgz", - "integrity": "sha512-Zrxbg/WiIvUP2uEzelDNTXmEMJXuzJ1kCpbDvaKByFA9MNeO95V+7r/3ti0qzJzrxdyuUw5VduN7k+D3VmVOSA==", + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-2.1.5.tgz", + "integrity": "sha512-P4ljsdpuzRTPI/kbND2sDZ4VmieerR2c9szEZpjc+98Z9ebvnXmM5+0tHEKqYZumXqlvnmfWsjeFOjXVriDG7A==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/expect": "2.1.3", - "@vitest/mocker": "2.1.3", - "@vitest/pretty-format": "^2.1.3", - "@vitest/runner": "2.1.3", - "@vitest/snapshot": "2.1.3", - "@vitest/spy": "2.1.3", - "@vitest/utils": "2.1.3", - "chai": "^5.1.1", - "debug": "^4.3.6", - "magic-string": "^0.30.11", + "@vitest/expect": "2.1.5", + "@vitest/mocker": "2.1.5", + "@vitest/pretty-format": "^2.1.5", + "@vitest/runner": "2.1.5", + "@vitest/snapshot": "2.1.5", + "@vitest/spy": "2.1.5", + "@vitest/utils": "2.1.5", + "chai": "^5.1.2", + "debug": "^4.3.7", + "expect-type": "^1.1.0", + "magic-string": "^0.30.12", "pathe": "^1.1.2", - "std-env": "^3.7.0", + "std-env": "^3.8.0", "tinybench": "^2.9.0", - "tinyexec": "^0.3.0", - "tinypool": "^1.0.0", + "tinyexec": "^0.3.1", + "tinypool": "^1.0.1", "tinyrainbow": "^1.2.0", "vite": "^5.0.0", - "vite-node": "2.1.3", + "vite-node": "2.1.5", "why-is-node-running": "^2.3.0" }, "bin": { @@ -4286,8 +4363,8 @@ "peerDependencies": { "@edge-runtime/vm": "*", "@types/node": "^18.0.0 || >=20.0.0", - "@vitest/browser": "2.1.3", - "@vitest/ui": "2.1.3", + "@vitest/browser": "2.1.5", + "@vitest/ui": "2.1.5", "happy-dom": "*", "jsdom": "*" }, @@ -4313,9 +4390,9 @@ } }, "node_modules/vitest-fetch-mock": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/vitest-fetch-mock/-/vitest-fetch-mock-0.4.1.tgz", - "integrity": "sha512-Y6VEV2AgJps1t9NUdhID/vUwarAuhOkPHShfoEruIlQr5+O31hgJ4YmZpU8kVWD3KQjEyZqPeMibWehd7rMq+A==", + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/vitest-fetch-mock/-/vitest-fetch-mock-0.4.2.tgz", + "integrity": "sha512-MuN/TCAvvUs9sLMdOPKqdXEUOD0E5cNW/LN7Tro3KkrLBsvUaH7iQWcznNUU4ml+GqX6ZbNguDmFQ2tliKqhCg==", "dev": true, "license": "MIT", "engines": { diff --git a/cli/package.json b/cli/package.json index 7e1eaa8d1ceb9..bdfaa0f528a3e 100644 --- a/cli/package.json +++ b/cli/package.json @@ -1,6 +1,6 @@ { "name": "@immich/cli", - "version": "2.2.28", + "version": "2.2.37", "description": "Command Line Interface (CLI) for Immich", "type": "module", "exports": "./dist/index.js", @@ -20,17 +20,17 @@ "@types/cli-progress": "^3.11.0", "@types/lodash-es": "^4.17.12", "@types/mock-fs": "^4.13.1", - "@types/node": "^22.8.1", - "@typescript-eslint/eslint-plugin": "^8.0.0", - "@typescript-eslint/parser": "^8.0.0", + "@types/node": "^22.10.2", + "@typescript-eslint/eslint-plugin": "^8.15.0", + "@typescript-eslint/parser": "^8.15.0", "@vitest/coverage-v8": "^2.0.5", "byte-size": "^9.0.0", "cli-progress": "^3.12.0", "commander": "^12.0.0", - "eslint": "^9.0.0", + "eslint": "^9.14.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-prettier": "^5.1.3", - "eslint-plugin-unicorn": "^55.0.0", + "eslint-plugin-unicorn": "^56.0.1", "globals": "^15.9.0", "mock-fs": "^5.2.0", "prettier": "^3.2.5", @@ -67,6 +67,6 @@ "lodash-es": "^4.17.21" }, "volta": { - "node": "22.11.0" + "node": "22.12.0" } } diff --git a/cli/src/commands/asset.ts b/cli/src/commands/asset.ts index 9c1a503cda1a0..4cf6742f24669 100644 --- a/cli/src/commands/asset.ts +++ b/cli/src/commands/asset.ts @@ -1,5 +1,6 @@ import { Action, + AssetBulkUploadCheckItem, AssetBulkUploadCheckResult, AssetMediaResponseDto, AssetMediaStatus, @@ -11,7 +12,7 @@ import { getSupportedMediaTypes, } from '@immich/sdk'; import byteSize from 'byte-size'; -import { Presets, SingleBar } from 'cli-progress'; +import { MultiBar, Presets, SingleBar } from 'cli-progress'; import { chunk } from 'lodash-es'; import { Stats, createReadStream } from 'node:fs'; import { stat, unlink } from 'node:fs/promises'; @@ -90,23 +91,23 @@ export const checkForDuplicates = async (files: string[], { concurrency, skipHas return { newFiles: files, duplicates: [] }; } - const progressBar = new SingleBar( - { format: 'Checking files | {bar} | {percentage}% | ETA: {eta}s | {value}/{total} assets' }, + const multiBar = new MultiBar( + { format: '{message} | {bar} | {percentage}% | ETA: {eta}s | {value}/{total} assets' }, Presets.shades_classic, ); - progressBar.start(files.length, 0); + const hashProgressBar = multiBar.create(files.length, 0, { message: 'Hashing files ' }); + const checkProgressBar = multiBar.create(files.length, 0, { message: 'Checking for duplicates' }); const newFiles: string[] = []; const duplicates: Asset[] = []; - const queue = new Queue( - async (filepaths: string[]) => { - const dto = await Promise.all( - filepaths.map(async (filepath) => ({ id: filepath, checksum: await sha1(filepath) })), - ); - const response = await checkBulkUpload({ assetBulkUploadCheckDto: { assets: dto } }); + const checkBulkUploadQueue = new Queue( + async (assets: AssetBulkUploadCheckItem[]) => { + const response = await checkBulkUpload({ assetBulkUploadCheckDto: { assets } }); + const results = response.results as AssetBulkUploadCheckResults; + for (const { id: filepath, assetId, action } of results) { if (action === Action.Accept) { newFiles.push(filepath); @@ -115,19 +116,46 @@ export const checkForDuplicates = async (files: string[], { concurrency, skipHas duplicates.push({ id: assetId as string, filepath }); } } - progressBar.increment(filepaths.length); + + checkProgressBar.increment(assets.length); + }, + { concurrency, retry: 3 }, + ); + + const results: { id: string; checksum: string }[] = []; + let checkBulkUploadRequests: AssetBulkUploadCheckItem[] = []; + + const queue = new Queue( + async (filepath: string): Promise => { + const dto = { id: filepath, checksum: await sha1(filepath) }; + + results.push(dto); + checkBulkUploadRequests.push(dto); + if (checkBulkUploadRequests.length === 5000) { + const batch = checkBulkUploadRequests; + checkBulkUploadRequests = []; + void checkBulkUploadQueue.push(batch); + } + + hashProgressBar.increment(); return results; }, { concurrency, retry: 3 }, ); - for (const items of chunk(files, concurrency)) { - await queue.push(items); + for (const item of files) { + void queue.push(item); } await queue.drained(); - progressBar.stop(); + if (checkBulkUploadRequests.length > 0) { + void checkBulkUploadQueue.push(checkBulkUploadRequests); + } + + await checkBulkUploadQueue.drained(); + + multiBar.stop(); console.log(`Found ${newFiles.length} new files and ${duplicates.length} duplicate${s(duplicates.length)}`); @@ -201,8 +229,8 @@ export const uploadFiles = async (files: string[], { dryRun, concurrency }: Uplo { concurrency, retry: 3 }, ); - for (const filepath of files) { - await queue.push(filepath); + for (const item of files) { + void queue.push(item); } await queue.drained(); diff --git a/cli/src/queue.ts b/cli/src/queue.ts index c700028a158a9..0b6d6281461cc 100644 --- a/cli/src/queue.ts +++ b/cli/src/queue.ts @@ -72,8 +72,8 @@ export class Queue { * @returns Promise - The returned Promise will be resolved when all tasks in the queue have been processed by a worker. * This promise could be ignored as it will not lead to a `unhandledRejection`. */ - async drained(): Promise { - await this.queue.drain(); + drained(): Promise { + return this.queue.drained(); } /** diff --git a/deployment/modules/cloudflare/docs-release/.terraform.lock.hcl b/deployment/modules/cloudflare/docs-release/.terraform.lock.hcl index 995f5d5b69f64..00222921f1f9b 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.45.0" - constraints = "4.45.0" + version = "4.48.0" + constraints = "4.48.0" hashes = [ - "h1:/CGpnYMkLRDmqn4iAsh/jg7ELZ6QExUw03VdjKZyK5M=", - "h1:82C/ryqwQvxhBINYOOyF5ZzPW/k4zJ/RYT13eCdPgEc=", - "h1:8Wu1D7ZwbLGdHakLRAzoAJ5VqZ8I14qzkPv1OGNfIlg=", - "h1:CVq0CAibeueOuiNk0UQtwZvMLMof33n1BgskFPOymrk=", - "h1:FSS5Kq+L+CX1zARy8PhaF8edBFNgsLtds4Uo8MwJiK8=", - "h1:L4qsorLII7f8xSFmv6JOoWfLWDunWQEpK964Bxk7mtM=", - "h1:StO3PV5PDskSCnhoHhWHOPxu6hbzJUQggfLgOSkvhwg=", - "h1:Tjo+Er9ets5YrTRIdP9LBmi4p89nL/W+A7r8a1MM9nI=", - "h1:XIwT+AWvks1LTytePM9zls+O8ItxoqCfPOgHwuH9ivQ=", - "h1:aOXn/zuM1+5GGy/SSRx8q4EYCSTFE9Tr0twHPIf5/KE=", - "h1:lb+YcuZ4guYd8zE51vgSnDsRAD9IV00Z15l1i1X52s8=", - "h1:pYwNXGjfXA2rUEmotGMLWgmavT9D2rdHnV3TpuIK3ko=", - "h1:q1qrnPq6KkljwBrugCwzb7f0SVP4Lzkfh+EOLARY9V8=", - "h1:v9sL4cZLTV5Gu2004DDyy7209gT0JmudBCAD0WCr/JE=", - "zh:00be2a6adc76615a368491c7a026098103b6286deb31e3cfb037365dd39f095f", - "zh:05bd072e6119f7a5abff05c6064001f745473119a956586cf77ae843cf55d666", - "zh:228bbe61345c4e8e0bc6b698b4b9652abff65662ee72ede2aecb4c3efb91b243", - "zh:2948aeefe71ba041c94082cf931ecc95510d93af0a61d0a287880f5b9d24b11a", - "zh:5dfc2c5e95843ca54957212ee3ecb7ff06f2cf60bfd6ca278b5249fd70ac18f5", - "zh:69922cb45559b0b0544b9c2d31ed2d0fac9121faa75bc2f523484785b45d8e2b", + "h1:0IKUOR32xEI1suS5QCOjfxjQ2mRd058btXk8hVnaOJ4=", + "h1:3YG6vu/bFPcYOeLdSUZhiAWiWKaFlOAR34z2o8cbE9k=", + "h1:FvGy06/i9AMtVkSIUnCrXNv5xF6jqBqMH8oPVLyeeAg=", + "h1:GXH7nIF0ocMqebbA41+fSGIYfM+VAM/PvTe7fJr8UrQ=", + "h1:H0ll0ph4404vFE868W3qJ3zhOyy4jbXrOMtdkViEZsU=", + "h1:SX42e3k73IcFcrQlZ2e/Veqt2tvCMy6fwlo5yNUktCE=", + "h1:Uu/gjBc99GefdPdSrlBwU75DWU0ZcwGcrd3ZFyTeL0s=", + "h1:VZw0uN41PWRmNlhg7Ze0Eh7cdoklX1oZbfNAXNYnU1I=", + "h1:cMdV7ql6PsFa4qtb0EoZSctvTaTqV7yplBSDwcLRCLc=", + "h1:ePGvSurmlqOCkD761vkhRmz7bsK36/EnIvx2Xy8TdXo=", + "h1:fOYufF+1bzw2N3aHLpkLB6E8VbZ4ysXDODYQOlwhwd4=", + "h1:qe8RbnWq0T4xhqjn9QcbO6YW5YDx47P+eJ0NUMIfwCc=", + "h1:tRD2av6PafHDP/b9jDQsG5/aX+lHeKxpbIEHYYLBVUc=", + "h1:zyl6Gvx/CFpwYW8pFFDesfO8Lxv+a6CopyAsIMhp54s=", + "zh:04c0a49c2b23140b2f21cfd0d52f9798d70d3bdae3831613e156aabe519bbc6c", + "zh:185f21b4834ba63e8df1f84aa34639d8a7e126429a4007bb5f9ad82f2602a997", + "zh:234724f52cb4c0c3f7313d3b2697caef26d921d134f26ae14801e7afac522f7b", + "zh:38a56fcd1b3e40706af995611c977816543b53f1e55fe2720944aae2b6828fcb", + "zh:419938f5430fc78eff933470aefbf94a460a478f867cf7761a3dea177b4eb153", + "zh:4b46d92bfde1deab7de7ba1a6bbf4ba7c711e4fd925341ddf09d4cc28dae03d8", + "zh:537acd4a31c752f1bae305ba7190f60b71ad1a459f22d464f3f914336c9e919f", + "zh:5ff36b005aad07697dd0b30d4f0c35dbcdc30dc52b41722552060792fa87ce04", + "zh:635c5ee419daea098060f794d9d7d999275301181e49562c4e4c08f043076937", + "zh:859277c330d61f91abe9e799389467ca11b77131bf34bedbef52f8da68b2bb49", "zh:890df766e9b839623b1f0437355032a3c006226a6c200cd911e15ee1a9014e9f", - "zh:9d83a0cbf72327286f7dbd63cd4af89059c648163fe6ed21b1df768e0518d445", - "zh:a8e1982945822c7d7aaa6ba8602c7247d1a3fad15d612f30eb323491a637bf8d", - "zh:c6d41ebd69ddb23e3dad49a0ebf1da5a9c7d8706a4f55d953115d371f407928b", - "zh:d03e5442b12846c2737f099d30cd23d9f85a0c6d65437ccb44819f9a6c4e1d7f", - "zh:d446f2e1186b35037aea03b0e27d8b032d2f069f194f84b3f0e2907b3a79a955", - "zh:e4d7549a4c856524e01f3dd4d69f57119ea205f7a0fa38dcfe154475b4ae9258", - "zh:e64b8915cb9686f85e77115bd674f2faf4f29880688067d7d0f1376566fdb3b0", - "zh:f046efdc55e6385cdd69baaa06a929bef9fe6809d373b0d2d6c7df8f8c23eddc", + "zh:927dfdb8d9aef37ead03fceaa29e87ba076a3dd24e19b6cefdbb0efe9987ff8c", + "zh:bbf2226f07f6b1e721877328e69ded4b64f9c196634d2e2429e3cfabbe41e532", + "zh:daeed873d6f38604232b46ee4a5830c85d195b967f8dbcafe2fcffa98daf9c5f", + "zh:f8f2fc4646c1ba44085612fa7f4dbb7cbcead43b4e661f2b98ddfb4f68afc758", ] } diff --git a/deployment/modules/cloudflare/docs-release/config.tf b/deployment/modules/cloudflare/docs-release/config.tf index 85e095f195a12..c5397ea410a07 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.45.0" + version = "4.48.0" } } } diff --git a/deployment/modules/cloudflare/docs/.terraform.lock.hcl b/deployment/modules/cloudflare/docs/.terraform.lock.hcl index 995f5d5b69f64..00222921f1f9b 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.45.0" - constraints = "4.45.0" + version = "4.48.0" + constraints = "4.48.0" hashes = [ - "h1:/CGpnYMkLRDmqn4iAsh/jg7ELZ6QExUw03VdjKZyK5M=", - "h1:82C/ryqwQvxhBINYOOyF5ZzPW/k4zJ/RYT13eCdPgEc=", - "h1:8Wu1D7ZwbLGdHakLRAzoAJ5VqZ8I14qzkPv1OGNfIlg=", - "h1:CVq0CAibeueOuiNk0UQtwZvMLMof33n1BgskFPOymrk=", - "h1:FSS5Kq+L+CX1zARy8PhaF8edBFNgsLtds4Uo8MwJiK8=", - "h1:L4qsorLII7f8xSFmv6JOoWfLWDunWQEpK964Bxk7mtM=", - "h1:StO3PV5PDskSCnhoHhWHOPxu6hbzJUQggfLgOSkvhwg=", - "h1:Tjo+Er9ets5YrTRIdP9LBmi4p89nL/W+A7r8a1MM9nI=", - "h1:XIwT+AWvks1LTytePM9zls+O8ItxoqCfPOgHwuH9ivQ=", - "h1:aOXn/zuM1+5GGy/SSRx8q4EYCSTFE9Tr0twHPIf5/KE=", - "h1:lb+YcuZ4guYd8zE51vgSnDsRAD9IV00Z15l1i1X52s8=", - "h1:pYwNXGjfXA2rUEmotGMLWgmavT9D2rdHnV3TpuIK3ko=", - "h1:q1qrnPq6KkljwBrugCwzb7f0SVP4Lzkfh+EOLARY9V8=", - "h1:v9sL4cZLTV5Gu2004DDyy7209gT0JmudBCAD0WCr/JE=", - "zh:00be2a6adc76615a368491c7a026098103b6286deb31e3cfb037365dd39f095f", - "zh:05bd072e6119f7a5abff05c6064001f745473119a956586cf77ae843cf55d666", - "zh:228bbe61345c4e8e0bc6b698b4b9652abff65662ee72ede2aecb4c3efb91b243", - "zh:2948aeefe71ba041c94082cf931ecc95510d93af0a61d0a287880f5b9d24b11a", - "zh:5dfc2c5e95843ca54957212ee3ecb7ff06f2cf60bfd6ca278b5249fd70ac18f5", - "zh:69922cb45559b0b0544b9c2d31ed2d0fac9121faa75bc2f523484785b45d8e2b", + "h1:0IKUOR32xEI1suS5QCOjfxjQ2mRd058btXk8hVnaOJ4=", + "h1:3YG6vu/bFPcYOeLdSUZhiAWiWKaFlOAR34z2o8cbE9k=", + "h1:FvGy06/i9AMtVkSIUnCrXNv5xF6jqBqMH8oPVLyeeAg=", + "h1:GXH7nIF0ocMqebbA41+fSGIYfM+VAM/PvTe7fJr8UrQ=", + "h1:H0ll0ph4404vFE868W3qJ3zhOyy4jbXrOMtdkViEZsU=", + "h1:SX42e3k73IcFcrQlZ2e/Veqt2tvCMy6fwlo5yNUktCE=", + "h1:Uu/gjBc99GefdPdSrlBwU75DWU0ZcwGcrd3ZFyTeL0s=", + "h1:VZw0uN41PWRmNlhg7Ze0Eh7cdoklX1oZbfNAXNYnU1I=", + "h1:cMdV7ql6PsFa4qtb0EoZSctvTaTqV7yplBSDwcLRCLc=", + "h1:ePGvSurmlqOCkD761vkhRmz7bsK36/EnIvx2Xy8TdXo=", + "h1:fOYufF+1bzw2N3aHLpkLB6E8VbZ4ysXDODYQOlwhwd4=", + "h1:qe8RbnWq0T4xhqjn9QcbO6YW5YDx47P+eJ0NUMIfwCc=", + "h1:tRD2av6PafHDP/b9jDQsG5/aX+lHeKxpbIEHYYLBVUc=", + "h1:zyl6Gvx/CFpwYW8pFFDesfO8Lxv+a6CopyAsIMhp54s=", + "zh:04c0a49c2b23140b2f21cfd0d52f9798d70d3bdae3831613e156aabe519bbc6c", + "zh:185f21b4834ba63e8df1f84aa34639d8a7e126429a4007bb5f9ad82f2602a997", + "zh:234724f52cb4c0c3f7313d3b2697caef26d921d134f26ae14801e7afac522f7b", + "zh:38a56fcd1b3e40706af995611c977816543b53f1e55fe2720944aae2b6828fcb", + "zh:419938f5430fc78eff933470aefbf94a460a478f867cf7761a3dea177b4eb153", + "zh:4b46d92bfde1deab7de7ba1a6bbf4ba7c711e4fd925341ddf09d4cc28dae03d8", + "zh:537acd4a31c752f1bae305ba7190f60b71ad1a459f22d464f3f914336c9e919f", + "zh:5ff36b005aad07697dd0b30d4f0c35dbcdc30dc52b41722552060792fa87ce04", + "zh:635c5ee419daea098060f794d9d7d999275301181e49562c4e4c08f043076937", + "zh:859277c330d61f91abe9e799389467ca11b77131bf34bedbef52f8da68b2bb49", "zh:890df766e9b839623b1f0437355032a3c006226a6c200cd911e15ee1a9014e9f", - "zh:9d83a0cbf72327286f7dbd63cd4af89059c648163fe6ed21b1df768e0518d445", - "zh:a8e1982945822c7d7aaa6ba8602c7247d1a3fad15d612f30eb323491a637bf8d", - "zh:c6d41ebd69ddb23e3dad49a0ebf1da5a9c7d8706a4f55d953115d371f407928b", - "zh:d03e5442b12846c2737f099d30cd23d9f85a0c6d65437ccb44819f9a6c4e1d7f", - "zh:d446f2e1186b35037aea03b0e27d8b032d2f069f194f84b3f0e2907b3a79a955", - "zh:e4d7549a4c856524e01f3dd4d69f57119ea205f7a0fa38dcfe154475b4ae9258", - "zh:e64b8915cb9686f85e77115bd674f2faf4f29880688067d7d0f1376566fdb3b0", - "zh:f046efdc55e6385cdd69baaa06a929bef9fe6809d373b0d2d6c7df8f8c23eddc", + "zh:927dfdb8d9aef37ead03fceaa29e87ba076a3dd24e19b6cefdbb0efe9987ff8c", + "zh:bbf2226f07f6b1e721877328e69ded4b64f9c196634d2e2429e3cfabbe41e532", + "zh:daeed873d6f38604232b46ee4a5830c85d195b967f8dbcafe2fcffa98daf9c5f", + "zh:f8f2fc4646c1ba44085612fa7f4dbb7cbcead43b4e661f2b98ddfb4f68afc758", ] } diff --git a/deployment/modules/cloudflare/docs/config.tf b/deployment/modules/cloudflare/docs/config.tf index 85e095f195a12..c5397ea410a07 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.45.0" + version = "4.48.0" } } } diff --git a/docker/docker-compose.dev.yml b/docker/docker-compose.dev.yml index 26e58f18d7524..5da5bd3f913e9 100644 --- a/docker/docker-compose.dev.yml +++ b/docker/docker-compose.dev.yml @@ -47,6 +47,7 @@ services: ports: - 9230:9230 - 9231:9231 + - 2283:2283 depends_on: - redis - database @@ -56,13 +57,15 @@ services: 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 build: context: ../web command: ['/usr/src/app/bin/immich-web'] env_file: - .env ports: - - 2283:3000 + - 3000:3000 - 24678:24678 volumes: - ../web:/usr/src/app @@ -103,7 +106,7 @@ services: redis: container_name: immich_redis - image: redis:6.2-alpine@sha256:2ba50e1ac3a0ea17b736ce9db2b0a9f6f8b85d4c27d5f5accc6a416d8f42c6d5 + image: redis:6.2-alpine@sha256:eaba718fecd1196d88533de7ba49bf903ad33664a92debb24660a922ecd9cac8 healthcheck: test: redis-cli ping || exit 1 @@ -122,26 +125,23 @@ services: ports: - 5432:5432 healthcheck: - test: pg_isready --dbname='${DB_DATABASE_NAME}' --username='${DB_USERNAME}' || exit 1; Chksum="$$(psql --dbname='${DB_DATABASE_NAME}' --username='${DB_USERNAME}' --tuples-only --no-align --command='SELECT COALESCE(SUM(checksum_failures), 0) FROM pg_stat_database')"; echo "checksum failure count is $$Chksum"; [ "$$Chksum" = '0' ] || exit 1 + test: >- + pg_isready --dbname="$${POSTGRES_DB}" --username="$${POSTGRES_USER}" || exit 1; + Chksum="$$(psql --dbname="$${POSTGRES_DB}" --username="$${POSTGRES_USER}" --tuples-only --no-align + --command='SELECT COALESCE(SUM(checksum_failures), 0) FROM pg_stat_database')"; + echo "checksum failure count is $$Chksum"; + [ "$$Chksum" = '0' ] || exit 1 interval: 5m start_interval: 30s start_period: 5m - command: - [ - 'postgres', - '-c', - 'shared_preload_libraries=vectors.so', - '-c', - 'search_path="$$user", public, vectors', - '-c', - 'logging_collector=on', - '-c', - 'max_wal_size=2GB', - '-c', - 'shared_buffers=512MB', - '-c', - 'wal_compression=on', - ] + command: >- + postgres + -c shared_preload_libraries=vectors.so + -c 'search_path="$$user", public, vectors' + -c logging_collector=on + -c max_wal_size=2GB + -c shared_buffers=512MB + -c wal_compression=on # set IMMICH_TELEMETRY_INCLUDE=all in .env to enable metrics # immich-prometheus: diff --git a/docker/docker-compose.prod.yml b/docker/docker-compose.prod.yml index 48d4328c854b6..85213900790d9 100644 --- a/docker/docker-compose.prod.yml +++ b/docker/docker-compose.prod.yml @@ -47,7 +47,7 @@ services: redis: container_name: immich_redis - image: redis:6.2-alpine@sha256:2ba50e1ac3a0ea17b736ce9db2b0a9f6f8b85d4c27d5f5accc6a416d8f42c6d5 + image: redis:6.2-alpine@sha256:eaba718fecd1196d88533de7ba49bf903ad33664a92debb24660a922ecd9cac8 healthcheck: test: redis-cli ping || exit 1 restart: always @@ -67,26 +67,23 @@ services: ports: - 5432:5432 healthcheck: - test: pg_isready --dbname='${DB_DATABASE_NAME}' --username='${DB_USERNAME}' || exit 1; Chksum="$$(psql --dbname='${DB_DATABASE_NAME}' --username='${DB_USERNAME}' --tuples-only --no-align --command='SELECT COALESCE(SUM(checksum_failures), 0) FROM pg_stat_database')"; echo "checksum failure count is $$Chksum"; [ "$$Chksum" = '0' ] || exit 1 + test: >- + pg_isready --dbname="$${POSTGRES_DB}" --username="$${POSTGRES_USER}" || exit 1; + Chksum="$$(psql --dbname="$${POSTGRES_DB}" --username="$${POSTGRES_USER}" --tuples-only --no-align + --command='SELECT COALESCE(SUM(checksum_failures), 0) FROM pg_stat_database')"; + echo "checksum failure count is $$Chksum"; + [ "$$Chksum" = '0' ] || exit 1 interval: 5m start_interval: 30s start_period: 5m - command: - [ - 'postgres', - '-c', - 'shared_preload_libraries=vectors.so', - '-c', - 'search_path="$$user", public, vectors', - '-c', - 'logging_collector=on', - '-c', - 'max_wal_size=2GB', - '-c', - 'shared_buffers=512MB', - '-c', - 'wal_compression=on', - ] + command: >- + postgres + -c shared_preload_libraries=vectors.so + -c 'search_path="$$user", public, vectors' + -c logging_collector=on + -c max_wal_size=2GB + -c shared_buffers=512MB + -c wal_compression=on restart: always # set IMMICH_TELEMETRY_INCLUDE=all in .env to enable metrics @@ -94,7 +91,7 @@ services: container_name: immich_prometheus ports: - 9090:9090 - image: prom/prometheus@sha256:378f4e03703557d1c6419e6caccf922f96e6d88a530f7431d66a4c4f4b1000fe + image: prom/prometheus@sha256:565ee86501224ebbb98fc10b332fa54440b100469924003359edf49cbce374bd volumes: - ./prometheus.yml:/etc/prometheus/prometheus.yml - prometheus-data:/prometheus @@ -106,7 +103,7 @@ services: command: ['./run.sh', '-disable-reporting'] ports: - 3000:3000 - image: grafana/grafana:11.3.0-ubuntu@sha256:51587e148ac0214d7938e7f3fe8512182e4eb6141892a3ffb88bba1901b49285 + image: grafana/grafana:11.4.0-ubuntu@sha256:afccec22ba0e4815cca1d2bf3836e414322390dc78d77f1851976ffa8d61051c volumes: - grafana-data:/var/lib/grafana diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index 979343364c12f..4b8453ce58b0c 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -48,7 +48,7 @@ services: redis: container_name: immich_redis - image: docker.io/redis:6.2-alpine@sha256:2ba50e1ac3a0ea17b736ce9db2b0a9f6f8b85d4c27d5f5accc6a416d8f42c6d5 + image: docker.io/redis:6.2-alpine@sha256:eaba718fecd1196d88533de7ba49bf903ad33664a92debb24660a922ecd9cac8 healthcheck: test: redis-cli ping || exit 1 restart: always @@ -65,26 +65,23 @@ services: # Do not edit the next line. If you want to change the database storage location on your system, edit the value of DB_DATA_LOCATION in the .env file - ${DB_DATA_LOCATION}:/var/lib/postgresql/data healthcheck: - test: pg_isready --dbname='${DB_DATABASE_NAME}' --username='${DB_USERNAME}' || exit 1; Chksum="$$(psql --dbname='${DB_DATABASE_NAME}' --username='${DB_USERNAME}' --tuples-only --no-align --command='SELECT COALESCE(SUM(checksum_failures), 0) FROM pg_stat_database')"; echo "checksum failure count is $$Chksum"; [ "$$Chksum" = '0' ] || exit 1 + test: >- + pg_isready --dbname="$${POSTGRES_DB}" --username="$${POSTGRES_USER}" || exit 1; + Chksum="$$(psql --dbname="$${POSTGRES_DB}" --username="$${POSTGRES_USER}" --tuples-only --no-align + --command='SELECT COALESCE(SUM(checksum_failures), 0) FROM pg_stat_database')"; + echo "checksum failure count is $$Chksum"; + [ "$$Chksum" = '0' ] || exit 1 interval: 5m start_interval: 30s start_period: 5m - command: - [ - 'postgres', - '-c', - 'shared_preload_libraries=vectors.so', - '-c', - 'search_path="$$user", public, vectors', - '-c', - 'logging_collector=on', - '-c', - 'max_wal_size=2GB', - '-c', - 'shared_buffers=512MB', - '-c', - 'wal_compression=on', - ] + command: >- + postgres + -c shared_preload_libraries=vectors.so + -c 'search_path="$$user", public, vectors' + -c logging_collector=on + -c max_wal_size=2GB + -c shared_buffers=512MB + -c wal_compression=on restart: always volumes: diff --git a/docs/.nvmrc b/docs/.nvmrc index 7af24b7ddbde0..1d9b7831ba9d9 100644 --- a/docs/.nvmrc +++ b/docs/.nvmrc @@ -1 +1 @@ -22.11.0 +22.12.0 diff --git a/docs/docs/FAQ.mdx b/docs/docs/FAQ.mdx index b328d3a047099..006c515558498 100644 --- a/docs/docs/FAQ.mdx +++ b/docs/docs/FAQ.mdx @@ -69,7 +69,8 @@ However, Immich will delete original files that have been trashed when the trash ### Why do my file names appear as a random string in the file manager? -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. +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. ### Can I add my existing photo library? @@ -82,11 +83,20 @@ Template changes will only apply to _new_ assets. To retroactively apply the tem ### Why are only photos and not videos being uploaded to Immich? -This often happens when using a reverse proxy (such as Nginx or Cloudflare tunnel) in front of Immich. Make sure to set your reverse proxy to allow large `POST` requests. In `nginx`, set `client_max_body_size 50000M;` or similar. 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. +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. +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. + +If you are using Cloudflare Tunnel, please know that they set a maxiumum filesize of 100 MB that cannot be changed. +At times, files larger than this may work, potentially up to 1 GB. However, the official limit is 100 MB. +If you are having issues, we recommend switching to a different network deployment. ### Why are some photos stored in the file system with the wrong date? -There are a few different scenarios that can lead to this situation. The solution is to rerun the storage migration job. The job is only automatically run once per asset after upload. If metadata extraction originally failed, the jobs were cleared/canceled, etc., the job may not have run automatically the first time. +There are a few different scenarios that can lead to this situation. The solution is to rerun the storage migration job. +The job is only automatically run once per asset after upload. If metadata extraction originally failed, the jobs were cleared/canceled, etc., +the job may not have run automatically the first time. ### How can I hide photos from the timeline? @@ -116,7 +126,8 @@ Also, there are additional jobs for person (face) thumbnails. ### Why do files from WhatsApp not appear with the correct date? -Files sent on WhatsApp are saved without metadata on the file. Therefore, Immich has no way of knowing the original date of the file when files are uploaded from WhatsApp, not the order of arrival on the device. [See #3527](https://github.com/immich-app/immich/issues/3527). +Files sent on WhatsApp are saved without metadata on the file. Therefore, Immich has no way of knowing the original date of the file when files are uploaded from WhatsApp, +not the order of arrival on the device. [See #9116](https://github.com/immich-app/immich/discussions/9116). ### What happens if an asset exists in more than one account? @@ -308,7 +319,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 on your reverse proxy. +You need to [enable WebSockets](/docs/administration/reverse-proxy/) on your reverse proxy. --- @@ -339,7 +350,7 @@ The non-root user/group needs read/write access to the volume mounts, including The Docker Compose top level volume element does not support non-root access, all of the above volumes must be local volume mounts. ::: -For a further hardened system, you can add the following block to every container except for `immich_postgres`. +For a further hardened system, you can add the following block to every container.
docker-compose.yml @@ -388,22 +399,21 @@ If the error says the worker is exiting, then this is normal. This is a feature There are a few reasons why this can happen. -If the error mentions SIGKILL or error code 137, it most likely means the service is running out of memory. Consider either increasing the server's RAM or moving the service to a server with more RAM. - -If it mentions SIGILL (note the lack of a K) or error code 132, it most likely means your server's CPU is incompatible. This is unlikely to occur on version 1.92.0 or later. Consider upgrading if your version of Immich is below that. +If the error mentions SIGKILL or error code 137, it most likely means the service is running out of memory. +Consider either increasing the server's RAM or moving the service to a server with more RAM. -If your version of Immich is below 1.92.0 and the crash occurs after logs about tracing or exporting a model, consider either upgrading or disabling the Tag Objects job. +If it mentions SIGILL (note the lack of a K) or error code 132, it most likely means your server's CPU is incompatible with Immich. ## Database ### 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/environment-variables#supported-filesystems) for more details. +NTFS and ex/FAT/32 filesystems are not supported. See [here](/docs/install/requirements#special-requirements-for-windows-users) for more details. ### How can I verify the integrity of my database? -If you installed Immich using v1.104.0 or later, you likely have database checksums enabled by default. You can check this by running the following command. +Database checksums are enabled by default for new installations since v1.104.0. You can check if they are enabled by running the following command. A result of `on` means that checksums are enabled.
@@ -419,7 +429,7 @@ docker exec -it immich_postgres psql --dbname=immich --username= --
-If checksums are enabled, you can check the status of the database with the following command. A normal result is all zeroes. +If checksums are enabled, you can check the status of the database with the following command. A normal result is all `0`s.
Check for database corruption diff --git a/docs/docs/administration/backup-and-restore.md b/docs/docs/administration/backup-and-restore.md index 70f393e6e10fa..1f8d489728ee0 100644 --- a/docs/docs/administration/backup-and-restore.md +++ b/docs/docs/administration/backup-and-restore.md @@ -15,8 +15,6 @@ Immich saves [file paths in the database](https://github.com/immich-app/immich/d Refer to the official [postgres documentation](https://www.postgresql.org/docs/current/backup.html) for details about backing up and restoring a postgres database. ::: -The recommended way to backup and restore the Immich database is to use the `pg_dumpall` command. When restoring, you need to delete the `DB_DATA_LOCATION` folder (if it exists) to reset the database. - :::caution It is not recommended to directly backup the `DB_DATA_LOCATION` folder. Doing so while the database is running can lead to a corrupted backup that cannot be restored. ::: @@ -60,72 +58,34 @@ docker compose up -d # Start remainder of Immich apps ```powershell title='Backup' -docker exec -t immich_postgres pg_dumpall --clean --if-exists --username=postgres | Set-Content -Encoding utf8 "C:\path\to\backup\dump.sql" +[System.IO.File]::WriteAllLines("C:\absolute\path\to\backup\dump.sql", (docker exec -t immich_postgres pg_dumpall --clean --if-exists --username=postgres)) ``` ```powershell title='Restore' docker compose down -v # CAUTION! Deletes all Immich data to start from scratch ## Uncomment the next line and replace DB_DATA_LOCATION with your Postgres path to permanently reset the Postgres database # Remove-Item -Recurse -Force DB_DATA_LOCATION # CAUTION! Deletes all Immich data to start from scratch +## You should mount the backup (as a volume, example: - 'C:\path\to\backup\dump.sql':/dump.sql) into the immich_postgres container using the docker-compose.yml docker compose pull # Update to latest version of Immich (if desired) docker compose create # Create Docker containers for Immich apps without running them docker start immich_postgres # Start Postgres server sleep 10 # Wait for Postgres server to start up +docker exec -it immich_postgres bash # Enter the Docker shell and run the following command # Check the database user if you deviated from the default -gc "C:\path\to\backup\dump.sql" | docker exec -i immich_postgres psql --username=postgres # Restore Backup +cat "/dump.sql" \ +| sed "s/SELECT pg_catalog.set_config('search_path', '', false);/SELECT pg_catalog.set_config('search_path', 'public, pg_catalog', true);/g" \ +| psql --username=postgres # Restore Backup +exit # Exit the Docker shell docker compose up -d # Start remainder of Immich apps ``` -Note that for the database restore to proceed properly, it requires a completely fresh install (i.e. the Immich server has never run since creating the Docker containers). If the Immich app has run, Postgres conflicts may be encountered upon database restoration (relation already exists, violated foreign key constraints, multiple primary keys, etc.). +Note that for the database restore to proceed properly, it requires a completely fresh install (i.e. the Immich server has never run since creating the Docker containers). If the Immich app has run, Postgres conflicts may be encountered upon database restoration (relation already exists, violated foreign key constraints, multiple primary keys, etc.), in which case you need to delete the `DB_DATA_LOCATION` folder to reset the database. :::tip -Some deployment methods make it difficult to start the database without also starting the server or microservices. In these cases, you may set the environmental variable `DB_SKIP_MIGRATIONS=true` before starting the services. This will prevent the server from running migrations that interfere with the restore process. Note that both the server and microservices must have this variable set to prevent the migrations from running. Be sure to remove this variable and restart the services after the database is restored. -::: - -### Automatic Database Backups - -The database dumps can also be automated (using [this image](https://github.com/prodrigestivill/docker-postgres-backup-local)) by editing the docker compose file to match the following: - -```yaml -services: - ... - backup: - container_name: immich_db_dumper - image: prodrigestivill/postgres-backup-local:14 - restart: always - env_file: - - .env - environment: - POSTGRES_HOST: database - POSTGRES_CLUSTER: 'TRUE' - POSTGRES_USER: ${DB_USERNAME} - POSTGRES_PASSWORD: ${DB_PASSWORD} - POSTGRES_DB: ${DB_DATABASE_NAME} - SCHEDULE: "@daily" - POSTGRES_EXTRA_OPTS: '--clean --if-exists' - BACKUP_DIR: /db_dumps - volumes: - - ./db_dumps:/db_dumps - depends_on: - - database -``` - -Then you can restore with the same command but pointed at the latest dump. - -```bash title='Automated Restore' -# Be sure to check the username if you changed it from default -gunzip < db_dumps/last/immich-latest.sql.gz \ -| sed "s/SELECT pg_catalog.set_config('search_path', '', false);/SELECT pg_catalog.set_config('search_path', 'public, pg_catalog', true);/g" \ -| docker exec -i immich_postgres psql --username=postgres -``` - -:::note -If you see the error `ERROR: type "earth" does not exist`, or you have problems with Reverse Geocoding after a restore, add the following `sed` fragment to your restore command. - -Example: `gunzip < "/path/to/backup/dump.sql.gz" | sed "s/SELECT pg_catalog.set_config('search_path', '', false);/SELECT pg_catalog.set_config('search_path', 'public, pg_catalog', true);/g" | docker exec -i immich_postgres psql --username=postgres` +Some deployment methods make it difficult to start the database without also starting the server. In these cases, you may set the environment variable `DB_SKIP_MIGRATIONS=true` before starting the services. This will prevent the server from running migrations that interfere with the restore process. Be sure to remove this variable and restart the services after the database is restored. ::: ## Filesystem diff --git a/docs/docs/administration/email-notification.mdx b/docs/docs/administration/email-notification.mdx index 93b1051053069..2f244f33521a7 100644 --- a/docs/docs/administration/email-notification.mdx +++ b/docs/docs/administration/email-notification.mdx @@ -19,3 +19,9 @@ You can use [this guide](/docs/guides/smtp-gmail) to use Gmail's SMTP server. Users can manage their email notification settings from their account settings page on the web. They can choose to turn email notifications on or off for the following events: + +## Notification templates + +You can override the default notification text with custom templates in HTML format. You can use tags to show dynamic tags in your templates. + + diff --git a/docs/docs/administration/img/user-notifications-templates.png b/docs/docs/administration/img/user-notifications-templates.png new file mode 100644 index 0000000000000..150d39b7a6a2a Binary files /dev/null and b/docs/docs/administration/img/user-notifications-templates.png differ diff --git a/docs/docs/administration/system-integrity.md b/docs/docs/administration/system-integrity.md index 5440e42489d83..2b373134a9a4a 100644 --- a/docs/docs/administration/system-integrity.md +++ b/docs/docs/administration/system-integrity.md @@ -3,7 +3,7 @@ ## Folder checks :::info -The folders considered for these checks include: `upload/`, `library/`, `thumbs/`, `encoded-video/`, `profile/` +The folders considered for these checks include: `upload/`, `library/`, `thumbs/`, `encoded-video/`, `profile/`, `backups/` ::: When Immich starts, it performs a series of checks in order to validate that it can read and write files to the volume mounts used by the storage system. If it cannot perform all the required operations, it will fail to start. The checks include: @@ -40,7 +40,9 @@ The above error messages show that the server has previously (successfully) writ ### Ignoring the checks -The checks are designed to catch common problems that we have seen users have in the past, but if you want to disable them you can set the following environment variable: +:::warning +The checks are designed to catch common problems that we have seen users have in the past, and often indicate there's something wrong that you should solve. If you know what you're doing and you want to disable them you can set the following environment variable: +::: ``` IMMICH_IGNORE_MOUNT_CHECK_ERRORS=true diff --git a/docs/docs/administration/system-settings.md b/docs/docs/administration/system-settings.md index 9f35ed1010e2f..d6c219a168287 100644 --- a/docs/docs/administration/system-settings.md +++ b/docs/docs/administration/system-settings.md @@ -157,6 +157,10 @@ Immich supports [Reverse Geocoding](/docs/features/reverse-geocoding) using data SMTP server setup, for user creation notifications, new albums, etc. More information can be found [here](/docs/administration/email-notification) +## Notification Templates + +Override the default notifications text with notification templates. More information can be found [here](/docs/administration/email-notification) + ## Server Settings ### External Domain @@ -205,4 +209,68 @@ When this option is enabled the `immich-server` will periodically make requests ## Video Transcoding Settings -The system administrator can define parameters according to which video files will be converted to different formats (depending on the settings). The settings can be changed in depth, to learn more about the terminology used here, refer to FFmpeg documentation for [H.264](https://trac.ffmpeg.org/wiki/Encode/H.264) codec, [HEVC](https://trac.ffmpeg.org/wiki/Encode/H.265) codec and [VP9](https://trac.ffmpeg.org/wiki/Encode/VP9) codec. +The system administrator can configure which video files will be converted to different formats. The settings can be changed in depth, to learn more about the terminology used here, refer to FFmpeg documentation for [H.264](https://trac.ffmpeg.org/wiki/Encode/H.264) codec, [HEVC](https://trac.ffmpeg.org/wiki/Encode/H.265) codec and [VP9](https://trac.ffmpeg.org/wiki/Encode/VP9) codec. + +Which streams of a video file will be transcoded is determined by the [Transcode Policy](#ffmpeg.transcode). Streams that are transcoded use the following settings (config file name in brackets). Streams that are not transcoded are untouched and preserve their original settings. + +### Accepted containers (`ffmpeg.acceptedContainers`) {#ffmpeg.acceptedContainers} + +If the video asset's container format is not in this list, it will be remuxed to MP4 even if no streams need to be transcoded. + +The default set of accepted container formats is `mov`, `ogg` and `webm`. + +### Preset (`ffmpeg.preset`) {#ffmpeg.preset} + +The amount of "compute effort" to put into transcoding. These use [the preset names from h264](https://trac.ffmpeg.org/wiki/Encode/H.264#Preset) and will be converted to appropriate values for encoders that configure effort in different ways. + +The default value is `ultrafast`. + +### Audio codec (`ffmpeg.targetAudioCodec`) {#ffmpeg.targetAudioCodec} + +Which audio codec to use when the audio stream is being transcoded. Can be one of `mp3`, `aac`, `libopus`. + +The default value is `aac`. + +### Video Codec (`ffmpeg.targetVideoCodec`) {#ffmpeg.targetVideoCodec} + +Which video codec to use when the video stream is being transcoded. Can be one of `h264`, `hevc`, `vp9` or `av1`. + +The default value is `h264`. + +### Target resolution (`ffmpeg.targetResolution`) {#ffmpeg.targetResolution} + +When transcoding a video stream, downscale the largest dimension to this value while preserving aspect ratio. Videos are never upscaled. + +The default value is `720`. + +### Transcode policy (`ffmpeg.transcode`) {#ffmpeg.transcode} + +The transcoding policy configures which streams of a video asset will be transcoded. The transcoding decision is made independently for video streams and audio streams. This means that if a video stream needs to be transcoded, but an audio stream does not, then the video stream will be transcoded while the audio stream will be copied. If the transcoding policy does not require any stream to be transcoded and does not require the video to be remuxed, then no separate video file will be created. + +The default policy is `required`. + +#### All videos (`all`) {#ffmpeg.transcode-all} + +Videos are always transcoded. This ensures consistency during video playback. + +#### Don't transcode any videos (`disabled`) {#ffmpeg.transcode-disabled} + +Videos are never transcoded. This saves space and resources on the server, but may prevent playback on devices that don't support the source format (especially web browsers) or result in high bandwidth usage when playing high-bitrate files. + +#### Only videos not in an accepted format (`required`) {#ffmpeg.transcode-required} + +Video streams are transcoded when any of the following conditions are met: + +- The video is HDR. +- The video is not in the yuv420p pixel format. +- The video codec is not in `acceptedVideoCodecs`. + +Audio is transcoded if the audio codec is not in `acceptedAudioCodecs`. + +#### Videos higher than max bitrate or not in an accepted format (`bitrate`) {#ffmpeg.transcode-bitrate} + +In addition to the conditions in `required`, video streams are also transcoded if their bitrate is over `maxBitrate`. + +#### Videos higher than target resolution or not in an accepted format (`optimal`) {#ffmpeg.transcode-optimal} + +In addition to the conditions in `required`, video streams are also transcoded if the horizontal **and** vertical dimensions are higher than [`targetResolution`](#ffmpeg.targetResolution). diff --git a/docs/docs/developer/pr-checklist.md b/docs/docs/developer/pr-checklist.md index d2e7fbee4044f..58581e669a1b9 100644 --- a/docs/docs/developer/pr-checklist.md +++ b/docs/docs/developer/pr-checklist.md @@ -1,5 +1,9 @@ # PR Checklist +A minimal devcontainer is supplied with this repository. All commands can be executed directly inside this container to avoid tedious installation of the environment. +:::warning +The provided devcontainer isn't complete at the moment. At least all dockerized steps in the Makefile won't work (`make dev`, ....). Feel free to contribute! +::: When contributing code through a pull request, please check the following: ## Web Checks @@ -7,6 +11,7 @@ When contributing code through a pull request, please check the following: - [ ] `npm run lint` (linting via ESLint) - [ ] `npm run format` (formatting via Prettier) - [ ] `npm run check:svelte` (Type checking via SvelteKit) +- [ ] `npm run check:typescript` (check typescript) - [ ] `npm test` (unit tests) ## Documentation diff --git a/docs/docs/developer/setup.md b/docs/docs/developer/setup.md index 32e79849efdcf..9dbaf157b5d49 100644 --- a/docs/docs/developer/setup.md +++ b/docs/docs/developer/setup.md @@ -39,13 +39,16 @@ All the services are packaged to run as with single Docker Compose command. make dev # required Makefile installed on the system. ``` -5. Access the dev instance in your browser at http://localhost:2283, or connect via the mobile app. +5. Access the dev instance in your browser at http://localhost:3000, or connect via the mobile app. All the services will be started with hot-reloading enabled for a quick feedback loop. -You can access the web from `http://your-machine-ip:2283` or `http://localhost:2283` and access the server from the mobile app at `http://your-machine-ip:2283/api` +You can access the web from `http://your-machine-ip:3000` or `http://localhost:3000` and access the server from the mobile app at `http://your-machine-ip:3000/api` -**Note:** the "web" development container runs with uid 1000. If that uid does not have read/write permissions on the mounted volumes, you may encounter errors +**Notes:** + +- The "web" development container runs with uid 1000. If that uid does not have read/write permissions on the mounted volumes, you may encounter errors +- In case of rootless docker setup, you need to use root within the container, otherwise you will encounter read/write permission related errors, see comments in `docker/docker-compose.dev.yml`. #### Connect web to a remote backend @@ -76,7 +79,7 @@ Setting these in the IDE give a better developer experience, auto-formatting cod ### Dart Code Metrics -The mobile app uses DCM (Dart Code Metrics) for linting and metrics calculation. Please refer to the [Getting Started](https://dcm.dev/docs/getting-started/#installation) page for more information on setting up DCM +The mobile app uses DCM (Dart Code Metrics) for linting and metrics calculation. Please refer to the [Getting Started](https://dcm.dev/docs/) page for more information on setting up DCM Note: Activating the license is not required. diff --git a/docs/docs/features/facial-recognition.md b/docs/docs/features/facial-recognition.md index 4ea7a331e0b45..e775eb084bbbe 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 leran how the tune the result in this [Guide](/docs/guides/better-facial-clusters) +You can learn how the tune the result in this [Guide](/docs/guides/better-facial-clusters) ::: ### Facial recognition model diff --git a/docs/docs/features/hardware-transcoding.md b/docs/docs/features/hardware-transcoding.md index 4f059281f35f0..a561bafa8030d 100644 --- a/docs/docs/features/hardware-transcoding.md +++ b/docs/docs/features/hardware-transcoding.md @@ -1,7 +1,7 @@ # Hardware Transcoding [Experimental] This feature allows you to use a GPU to accelerate transcoding and reduce CPU load. -Note that hardware transcoding is much less efficient for file sizes. +Note that hardware transcoding produces significantly larger videos than software transcoding with similar settings, typically with lower quality. Using slow presets and preferring more efficient codecs can narrow this gap. As this is a new feature, it is still experimental and may not work on all systems. :::info diff --git a/docs/docs/features/img/mobile-upload-open-photo.png b/docs/docs/features/img/mobile-upload-open-photo.png new file mode 100644 index 0000000000000..4e51826fd7bf5 Binary files /dev/null and b/docs/docs/features/img/mobile-upload-open-photo.png differ diff --git a/docs/docs/features/img/mobile-upload-selected-photos.png b/docs/docs/features/img/mobile-upload-selected-photos.png new file mode 100644 index 0000000000000..61360842c32c1 Binary files /dev/null and b/docs/docs/features/img/mobile-upload-selected-photos.png differ diff --git a/docs/docs/features/mobile-app.mdx b/docs/docs/features/mobile-app.mdx index 11185fcaf1e42..3b7f2bb9e2bcf 100644 --- a/docs/docs/features/mobile-app.mdx +++ b/docs/docs/features/mobile-app.mdx @@ -1,6 +1,9 @@ +import Icon from '@mdi/react'; +import { mdiCloudOffOutline, mdiCloudCheckOutline } from '@mdi/js'; import MobileAppDownload from '/docs/partials/_mobile-app-download.md'; import MobileAppLogin from '/docs/partials/_mobile-app-login.md'; import MobileAppBackup from '/docs/partials/_mobile-app-backup.md'; +import { cloudDonePath, cloudOffPath } from '@site/src/components/svg-paths'; # Mobile App @@ -28,6 +31,30 @@ The beta release channel allows users to test upcoming changes before they are o You can enable automatic backup on supported devices. For more information see [Automatic Backup](/docs/features/automatic-backup.md). ::: +## Sync only selected photos + +If you have a large number of photos on the device, and you would prefer not to backup all the photos, then it might be prudent to only backup selected photos from device to the Immich server. + +First, you need to enable the Storage Indicator in your app's settings. Navigate to **Settings -> Photo Grid** and enable **"Show Storage indicator on asset tiles"**; this makes it easy to distinguish local-only assets and synced assets. +:::note +This will enable a small cloud icon on the bottom right corner of the asset tile, indicating that the asset is synced to the server: + +1. - Local-only asset; not synced to the server +2. - Asset is synced to the server ::: + +Now make sure that the local album is selected in the backup screen (steps 1-2 above). You can find these albums listed in **Library -> On this device**. To selectively upload photos from these albums, simply select the local-only photos and tap on "Upload" button in the dynamic bottom menu. + + + + ## Album Sync You can sync or mirror an album from your phone to the Immich server on your account. For example, if you select Recents, Camera and Videos album for backup, the corresponding album with the same name will be created on the server. Once the assets from those albums are uploaded, they will be put into the target albums automatically. diff --git a/docs/docs/guides/custom-locations.md b/docs/docs/guides/custom-locations.md index b364cccf837d2..514008611d11f 100644 --- a/docs/docs/guides/custom-locations.md +++ b/docs/docs/guides/custom-locations.md @@ -1,15 +1,15 @@ # Files Custom Locations -This guide explains storing generated and raw files with docker's volume mount in different locations. +This guide explains how to store generated and raw files with docker's volume mount in different locations. :::caution Backup It is important to remember to update the backup settings after following the guide to back up the new backup paths if using automatic backup tools, especially `profile/`. ::: -In our `.env` file, we will define variables that will help us in the future when we want to move to a more advanced server in the future +In our `.env` file, we will define variables that will help us in the future when we want to move to a more advanced server ```diff title=".env" -# You can find documentation for all the supported env variables [here](/docs/install/environment-variables) +# You can find documentation for all the supported environment variables [here](/docs/install/environment-variables) # Custom location where your uploaded, thumbnails, and transcoded video files are stored - UPLOAD_LOCATION=./library @@ -17,10 +17,11 @@ In our `.env` file, we will define variables that will help us in the future whe + THUMB_LOCATION=/custom/path/immich/thumbs + ENCODED_VIDEO_LOCATION=/custom/path/immich/encoded-video + PROFILE_LOCATION=/custom/path/immich/profile ++ BACKUP_LOCATION=/custom/path/immich/backups ... ``` -After defining the locations for these files, we will edit the `docker-compose.yml` file accordingly and add the new variables to the `immich-server` container. +After defining the locations of these files, we will edit the `docker-compose.yml` file accordingly and add the new variables to the `immich-server` container. ```diff title="docker-compose.yml" services: @@ -30,6 +31,7 @@ services: + - ${THUMB_LOCATION}:/usr/src/app/upload/thumbs + - ${ENCODED_VIDEO_LOCATION}:/usr/src/app/upload/encoded-video + - ${PROFILE_LOCATION}:/usr/src/app/upload/profile ++ - ${BACKUP_LOCATION}:/usr/src/app/upload/backups - /etc/localtime:/etc/localtime:ro ``` @@ -41,12 +43,11 @@ docker compose up -d :::note Because of the underlying properties of docker bind mounts, it is not recommended to mount the `upload/` and `library/` folders as separate bind mounts if they are on the same device. -For this reason, we mount the HDD or network storage to `/usr/src/app/upload` and then mount the folders we want quick access to below this folder. +For this reason, we mount the HDD or the network storage (NAS) to `/usr/src/app/upload` and then mount the folders we want to access under that folder. -The `thumbs/` folder contains both the small thumbnails shown in the timeline, and the larger previews shown when clicking into an image. These cannot be split up. +The `thumbs/` folder contains both the small thumbnails displayed in the timeline and the larger previews shown when clicking into an image. These cannot be separated. -The storage metrics of the Immich server will track the storage available at `UPLOAD_LOCATION`, -so the administrator should setup some kind of monitoring to make sure the SSD does not run out of space. The `profile/` folder is much smaller, typically less than 1 MB. +The storage metrics of the Immich server will track available storage at `UPLOAD_LOCATION`, so the administrator must set up some sort of monitoring to ensure the storage does not run out of space. The `profile/` folder is much smaller, usually less than 1 MB. ::: Thanks to [Jrasm91](https://github.com/immich-app/immich/discussions/2110#discussioncomment-5477767) for writing the guide. diff --git a/docs/docs/guides/database-queries.md b/docs/docs/guides/database-queries.md index 2b4f27cfceaa5..0e58d84f90c01 100644 --- a/docs/docs/guides/database-queries.md +++ b/docs/docs/guides/database-queries.md @@ -98,6 +98,10 @@ SELECT * FROM "move_history"; SELECT * FROM "users"; ``` +```sql title="Get owner info from asset ID" +SELECT "users".* FROM "users" JOIN "assets" ON "users"."id" = "assets"."ownerId" WHERE "assets"."id" = 'fa310b01-2f26-4b7a-9042-d578226e021f'; +``` + ## System Config ```sql title="Custom settings" diff --git a/docs/docs/guides/remote-machine-learning.md b/docs/docs/guides/remote-machine-learning.md index 4dbb72a408f16..1abf7d4e54d15 100644 --- a/docs/docs/guides/remote-machine-learning.md +++ b/docs/docs/guides/remote-machine-learning.md @@ -1,18 +1,20 @@ # 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 (e.g. your laptop or desktop computer): - -- Set the URL in Machine Learning Settings on the Admin Settings page to point to the designated ML system, e.g. `http://workstation:3003`. -- Copy the following `docker-compose.yml` to your ML system. - - If using [hardware acceleration](/docs/features/ml-hardware-acceleration), the [hwaccel.ml.yml](https://github.com/immich-app/immich/releases/latest/download/hwaccel.ml.yml) file also needs to be added -- Start the container by running `docker compose up -d`. +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. :::info -Smart Search and Face Detection will use this feature, but Facial Recognition is handled in the server. +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. ::: :::danger -When using remote machine learning, the thumbnails are sent to the remote machine learning container. Use this option carefully when running this on a public computer or a paid processing cloud. +Image previews are sent to the remote machine learning container. Use this option carefully when running this on a public computer or a paid processing cloud. Additionally, as an internal service, the machine learning container has no security measures whatsoever. Please be mindful of where it's deployed and who can access it. +::: + +1. Ensure the remote server has Docker installed +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) ::: ```yaml @@ -37,8 +39,26 @@ volumes: model-cache: ``` -Please note that version mismatches between both hosts may cause instabilities and bugs, so make sure to always perform updates together. +3. Start the remote machine learning container by running `docker compose up -d` + +:::info +Version mismatches between both hosts may cause bugs and instability, so remember to update this container as well when updating the local Immich instance. +::: + +4. Navigate to the [Machine Learning Settings](https://my.immich.app/admin/system-settings?isOpen=machine-learning) +5. Click _Add URL_ +6. Fill the new field with the URL to the remote machine learning container, e.g. `http://ip:port` + +## Forcing remote processing + +Adding a new URL to the settings is recommended over replacing the existing URL. This is because it will allow machine learning tasks to be processed successfully when the remote server is down by falling back to the local machine learning container. If you do not want machine learning tasks to be processed locally when the remote server is not available, you can instead replace the existing URL and only provide the remote container's URL. If doing this, you can remove the `immich-machine-learning` section of the local `docker-compose.yml` file to save resources, as this service will never be used. + +Do note that this will mean that Smart Search and Face Detection jobs will fail to be processed when the remote instance is not available. This in turn means that tasks dependent on these features—Duplicate Detection and Facial Recognition—will not run for affected assets. If this occurs, you must manually click the _Missing_ button next to Smart Search and Face Detection in the [Job Status](http://my.immich.app/admin/jobs-status) page for the jobs to be retried. + +## Load balancing + +While several URLs can be provided in the settings, they are tried sequentially; there is no attempt to distribute load across multiple containers. It is recommended to use a dedicated load balancer for such use-cases and specify it as the only URL. Among other things, it may enable the use of different APIs on the same server by running multiple containers with different configurations. For example, one might run an OpenVINO container in addition to a CUDA container, or run a standard release container to maximize both CPU and GPU utilization. -:::caution -As an internal service, the machine learning container has no security measures whatsoever. Please be mindful of where it's deployed and who can access it. +:::tip +The machine learning container can be shared among several Immich instances regardless of the models a particular instance uses. However, using different models will lead to higher peak memory usage. ::: diff --git a/docs/docs/guides/template-backup-script.md b/docs/docs/guides/template-backup-script.md index a0cd890a49745..dd0b94ebb13a0 100644 --- a/docs/docs/guides/template-backup-script.md +++ b/docs/docs/guides/template-backup-script.md @@ -6,6 +6,15 @@ 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 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. + +If you are using this script, it is therefore safe to turn off the built-in automatic database backups from your admin panel to save storage space. +::: + ### Prerequisites - Borg needs to be installed on your server as well as the remote machine. You can find instructions to install Borg [here](https://borgbackup.readthedocs.io/en/latest/installation.html). diff --git a/docs/docs/install/config-file.md b/docs/docs/install/config-file.md index ed902f39cfd1e..f5d2680658393 100644 --- a/docs/docs/install/config-file.md +++ b/docs/docs/install/config-file.md @@ -26,7 +26,6 @@ The default configuration looks like this: "bframes": -1, "refs": 0, "gopSize": 0, - "npl": 0, "temporalAQ": false, "cqMode": "auto", "twoPass": false, @@ -36,6 +35,13 @@ The default configuration looks like this: "accel": "disabled", "accelDecode": false }, + "backup": { + "database": { + "enabled": true, + "cronExpression": "0 02 * * *", + "keepLastAmount": 14 + } + }, "job": { "backgroundTask": { "concurrency": 5 @@ -77,7 +83,7 @@ The default configuration looks like this: }, "machineLearning": { "enabled": true, - "url": "http://immich-machine-learning:3003", + "urls": ["http://immich-machine-learning:3003"], "clip": { "enabled": true, "modelName": "ViT-B-32__openai" diff --git a/docs/docs/install/docker-compose.mdx b/docs/docs/install/docker-compose.mdx index b73d51b4d240a..e3d5dd686427d 100644 --- a/docs/docs/install/docker-compose.mdx +++ b/docs/docs/install/docker-compose.mdx @@ -7,10 +7,9 @@ import ExampleEnv from '!!raw-loader!../../../docker/example.env'; # Docker Compose [Recommended] -Docker Compose is the recommended method to run Immich in production. Below are the steps to deploy Immich with Docker Compose. -Immich requires Docker Compose version 2.x. +Docker Compose is the recommended method to run Immich in production. Below are the steps to deploy Immich with Docker Compose. -### Step 1 - Download the required files +## Step 1 - Download the required files Create a directory of your choice (e.g. `./immich-app`) to hold the `docker-compose.yml` and `.env` files. @@ -19,7 +18,7 @@ mkdir ./immich-app cd ./immich-app ``` -Download [`docker-compose.yml`][compose-file] and [`example.env`][env-file], either by running the following commands: +Download [`docker-compose.yml`][compose-file] and [`example.env`][env-file] by running the following commands: ```bash title="Get docker-compose.yml file" wget -O docker-compose.yml https://github.com/immich-app/immich/releases/latest/download/docker-compose.yml @@ -29,6 +28,11 @@ wget -O docker-compose.yml https://github.com/immich-app/immich/releases/latest/ wget -O .env https://github.com/immich-app/immich/releases/latest/download/example.env ``` +You can alternatively download these two files from your browser and move them to the directory that you created, in which case ensure that you rename `example.env` to `.env`. + +:::info Optional Features +If you intend to use hardware acceleration for transcoding or machine learning (ML), you can download now the config files you'll need, in the same way: + ```bash title="(Optional) Get hwaccel.transcoding.yml file" wget -O hwaccel.transcoding.yml https://github.com/immich-app/immich/releases/latest/download/hwaccel.transcoding.yml ``` @@ -37,15 +41,9 @@ wget -O hwaccel.transcoding.yml https://github.com/immich-app/immich/releases/la wget -O hwaccel.ml.yml https://github.com/immich-app/immich/releases/latest/download/hwaccel.ml.yml ``` -or by downloading from your browser and moving the files to the directory that you created. - -Note: If you downloaded the files from your browser, also ensure that you rename `example.env` to `.env`. - -:::info -Optionally, you can enable hardware acceleration for machine learning and transcoding. See the [Hardware Transcoding](/docs/features/hardware-transcoding.md) and [Hardware-Accelerated Machine Learning](/docs/features/ml-hardware-acceleration.md) guides for info on how to set these up. ::: -### Step 2 - Populate the .env file with custom values +## Step 2 - Populate the .env file with custom values
@@ -54,31 +52,37 @@ Optionally, you can enable hardware acceleration for machine learning and transc {ExampleEnv}
-- Populate custom database information if necessary. -- Populate `UPLOAD_LOCATION` with your preferred location for storing backup assets. +- Populate `UPLOAD_LOCATION` with your preferred location for storing backup assets. It should be a new directory on the server with enough free space. - Consider changing `DB_PASSWORD` to a custom value. Postgres is not publically exposed, so this password is only used for local authentication. - To avoid issues with Docker parsing this value, it is best to use only the characters `A-Za-z0-9`. + To avoid issues with Docker parsing this value, it is best to use only the characters `A-Za-z0-9`. `pwgen` is a handy utility for this. - Set your timezone by uncommenting the `TZ=` line. +- Populate custom database information if necessary. + +:::info Optional Features +You can edit `docker-compose.yml` to add external libraries or enable hardware acceleration now by following [their guides](#setting-up-optional-features). +::: -### Step 3 - Start the containers +## Step 3 - Start the containers -From the directory you created in Step 1, (which should now contain your customized `docker-compose.yml` and `.env` files) run `docker compose up -d`. +From the directory you created in Step 1 (which should now contain your customized `docker-compose.yml` and `.env` files), run this command: ```bash title="Start the containers using docker compose command" docker compose up -d ``` +This starts immich as a background service (per the `-d` flag), ensuring it restarts after system reboots or crashes (per the `restart` fields in `docker-compose.yml`). + :::info Docker version -If you get an error `unknown shorthand flag: 'd' in -d`, you are probably running the wrong Docker version. (This happens, for example, with the docker.io package in Ubuntu 22.04.3 LTS.) You can correct the problem by `apt remove`ing Ubuntu's docker.io package and installing docker and docker-compose via [Docker's official repository][docker-repo]. +If you get an error `unknown shorthand flag: 'd' in -d`, you are probably running the wrong Docker version. (This happens, for example, with the docker.io package in Ubuntu 22.04.3 LTS.) You can correct the problem by following the complete [Docker Engine install](https://docs.docker.com/engine/install/) procedure for your distribution, crucially the "Uninstall old versions" and "Install using the apt/rpm repository" sections. These replace the distro's Docker packages with Docker's official ones. -Note that the correct command really is `docker compose`, not `docker-compose`. If you try the latter on vanilla Ubuntu 22.04 it will fail in a different way: +Note that the correct command really is `docker compose`, not `docker-compose`. If you try the latter on vanilla Ubuntu 22.04, it will fail in a different way: ``` The Compose file './docker-compose.yml' is invalid because: 'name' does not match any of the regexes: '^x-' ``` -See the previous paragraph about installing from the official docker repository. +See the previous paragraph about installing from the official Docker repository. ::: :::info Health check start interval @@ -93,7 +97,17 @@ For more information on how to use the application, please refer to the [Post In Downloading container images might require you to authenticate to the GitHub Container Registry ([steps here][container-auth]). ::: -### Step 4 - Upgrading +## Next Steps + +### Setting Up Optional Features + +You can set up the following now: + +- [External Libraries](/docs/features/libraries.md) +- [Hardware Transcoding](/docs/features/hardware-transcoding.md) +- [Hardware-Accelerated Machine Learning](/docs/features/ml-hardware-acceleration.md) + +### Upgrading :::danger Breaking Changes It is important to follow breaking updates to avoid problems. You can see versions that had breaking changes [here][breaking]. @@ -101,12 +115,18 @@ It is important to follow breaking updates to avoid problems. You can see versio If `IMMICH_VERSION` is set, it will need to be updated to the latest or desired version. -When a new version of Immich is [released][releases], the application can be upgraded with the following commands, run in the directory with the `docker-compose.yml` file: +When a new version of Immich is [released][releases], the application can be upgraded and restarted with the following commands, run in the directory with the `docker-compose.yml` file: -```bash title="Upgrade Immich" +```bash title="Upgrade and restart Immich" docker compose pull && docker compose up -d ``` +To clean up disk space, the old version's obsolete container images can be deleted with the following command: + +```bash title="Delete all obsolete container images" +docker image prune +``` + :::caution Automatic Updates Immich is currently under heavy development, which means you can expect [breaking changes][breaking] and bugs. Therefore, we recommend reading the release notes prior to updating and to take special care when using automated tools like [Watchtower][watchtower]. ::: @@ -117,4 +137,3 @@ Immich is currently under heavy development, which means you can expect [breakin [breaking]: https://github.com/immich-app/immich/discussions?discussions_q=label%3Achangelog%3Abreaking-change+sort%3Adate_created [container-auth]: https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-container-registry#authenticating-to-the-container-registry [releases]: https://github.com/immich-app/immich/releases -[docker-repo]: https://docs.docker.com/engine/install/ubuntu/#install-using-the-repository diff --git a/docs/docs/install/img/truenas01.png b/docs/docs/install/img/truenas01.png index 81b0430a75ac2..e648ab3734e9d 100644 Binary files a/docs/docs/install/img/truenas01.png and b/docs/docs/install/img/truenas01.png differ diff --git a/docs/docs/install/img/truenas02.png b/docs/docs/install/img/truenas02.png index ae7d41e62425f..66f0dec7fa49c 100644 Binary files a/docs/docs/install/img/truenas02.png and b/docs/docs/install/img/truenas02.png differ diff --git a/docs/docs/install/img/truenas03.png b/docs/docs/install/img/truenas03.png index 90ff25b7ac916..d9970f5aebe90 100644 Binary files a/docs/docs/install/img/truenas03.png and b/docs/docs/install/img/truenas03.png differ diff --git a/docs/docs/install/img/truenas04.png b/docs/docs/install/img/truenas04.png index 281d02350a8cd..45fa87e5e5e72 100644 Binary files a/docs/docs/install/img/truenas04.png and b/docs/docs/install/img/truenas04.png differ diff --git a/docs/docs/install/img/truenas05.png b/docs/docs/install/img/truenas05.png index 919b008030736..0f9d6a835aeb1 100644 Binary files a/docs/docs/install/img/truenas05.png and b/docs/docs/install/img/truenas05.png differ diff --git a/docs/docs/install/img/truenas06.png b/docs/docs/install/img/truenas06.png index 26cf06738a634..3daf250e36706 100644 Binary files a/docs/docs/install/img/truenas06.png and b/docs/docs/install/img/truenas06.png differ diff --git a/docs/docs/install/img/truenas07.png b/docs/docs/install/img/truenas07.png index 17943e5c8155e..946c1401ac7dd 100644 Binary files a/docs/docs/install/img/truenas07.png and b/docs/docs/install/img/truenas07.png differ diff --git a/docs/docs/install/img/truenas08.png b/docs/docs/install/img/truenas08.png index 4c5a90be6befb..4ace8b49ca0b9 100644 Binary files a/docs/docs/install/img/truenas08.png and b/docs/docs/install/img/truenas08.png differ diff --git a/docs/docs/install/img/truenas09.png b/docs/docs/install/img/truenas09.png index 647c7295b420c..41830fe9e6046 100644 Binary files a/docs/docs/install/img/truenas09.png and b/docs/docs/install/img/truenas09.png differ diff --git a/docs/docs/install/img/truenas10.png b/docs/docs/install/img/truenas10.png new file mode 100644 index 0000000000000..730685c309f99 Binary files /dev/null and b/docs/docs/install/img/truenas10.png differ diff --git a/docs/docs/install/img/truenas11.png b/docs/docs/install/img/truenas11.png new file mode 100644 index 0000000000000..88c166aed3810 Binary files /dev/null and b/docs/docs/install/img/truenas11.png differ diff --git a/docs/docs/install/img/truenas12.png b/docs/docs/install/img/truenas12.png new file mode 100644 index 0000000000000..a107a85f24c76 Binary files /dev/null and b/docs/docs/install/img/truenas12.png differ diff --git a/docs/docs/install/requirements.md b/docs/docs/install/requirements.md index b96705203aa8f..ffb89c5c1331f 100644 --- a/docs/docs/install/requirements.md +++ b/docs/docs/install/requirements.md @@ -8,30 +8,43 @@ Hardware and software requirements for Immich: ## Software -- [Docker](https://docs.docker.com/get-docker/) -- [Docker Compose](https://docs.docker.com/compose/install/) +Immich requires [**Docker**](https://docs.docker.com/get-started/get-docker/) with the **Docker Compose plugin**: + +- **Docker Engine**: This CLI variant is suitable for Linux servers (or Windows via WSL2). +- **Docker Desktop**: This GUI variant is suitable for Linux desktop (or Windows or macOS). + +The Compose plugin will be installed by both Docker Engine and Desktop by following the linked installation guides; it can also be [separately installed](https://docs.docker.com/compose/install/). :::note -Immich requires the command `docker compose` - the similarly named `docker-compose` is [deprecated](https://docs.docker.com/compose/migrate/) and is no longer compatible with Immich. +Immich requires the command `docker compose`; the similarly named `docker-compose` is [deprecated](https://docs.docker.com/compose/migrate/) and is no longer supported by Immich. ::: ## Hardware - **OS**: Recommended Linux operating system (Ubuntu, Debian, etc). - - Windows is supported with [Docker Desktop on Windows](https://docs.docker.com/desktop/install/windows-install/) or [WSL 2](https://docs.docker.com/desktop/wsl/). - - macOS is supported with [Docker Desktop on Mac](https://docs.docker.com/desktop/install/mac-install/). + - Non-Linux OSes tend to provide a poor Docker experience and are strongly discouraged. + Our ability to assist with setup or troubleshooting on non-Linux OSes will be severely reduced. + If you still want to try to use a non-Linux OS, you can set it up as follows: + - Windows: [Docker Desktop on Windows](https://docs.docker.com/desktop/install/windows-install/) or [WSL 2](https://docs.docker.com/desktop/wsl/). + - macOS: [Docker Desktop on Mac](https://docs.docker.com/desktop/install/mac-install/). - **RAM**: Minimum 4GB, recommended 6GB. - **CPU**: Minimum 2 cores, recommended 4 cores. - **Storage**: Recommended Unix-compatible filesystem (EXT4, ZFS, APFS, etc.) with support for user/group ownership and permissions. - - This can present an issue for Windows users. See below for details and an alternative setup. - The generation of thumbnails and transcoded video can increase the size of the photo library by 10-20% on average. - - Network shares are supported for the storage of image and video assets only. It is not recommended to use a network share for your database location due to performance and possible data loss issues. + +:::tip +Good performance and a stable connection to the Postgres database is critical to a smooth Immich experience. +The Postgres database files are typically between 1-3 GB in size. +For this reason, the Postgres database (`DB_DATA_LOCATION`) should ideally use local SSD storage, and never a network share of any kind. +Additionally, if Docker resource limits are used, the Postgres database requires at least 2GB of RAM. +Windows users may run into issues with non-Unix-compatible filesystems, see below for more details. +::: ### Special requirements for Windows users
Database storage on Windows systems - + The Immich Postgres database (`DB_DATA_LOCATION`) must be located on a filesystem that supports user/group ownership and permissions (EXT2/3/4, ZFS, APFS, BTRFS, XFS, etc.). It will not work on any filesystem formatted in NTFS or ex/FAT/32. It will not work in WSL (Windows Subsystem for Linux) when using a mounted host directory (commonly under `/mnt`). diff --git a/docs/docs/install/truenas.md b/docs/docs/install/truenas.md index ffb559ed1216b..f35e9aa37a874 100644 --- a/docs/docs/install/truenas.md +++ b/docs/docs/install/truenas.md @@ -7,7 +7,9 @@ sidebar_position: 80 :::note This is a community contribution and not officially supported by the Immich team, but included here for convenience. -**Please report issues to the corresponding [Github Repository](https://github.com/truenas/charts/tree/master/community/immich).** +Community support can be found in the dedicated channel on the [Discord Server](https://discord.immich.app/). + +**Please report app issues to the corresponding [Github Repository](https://github.com/truenas/charts/tree/master/community/immich).** ::: Immich can easily be installed on TrueNAS SCALE via the **Community** train application. @@ -20,18 +22,26 @@ TrueNAS SCALE makes installing and updating Immich easy, but you must use the Im The Immich app in TrueNAS SCALE installs, completes the initial configuration, then starts the Immich web portal. When updates become available, SCALE alerts and provides easy updates. -Before installing the Immich app in SCALE, review the [Environment Variables](/docs/install/environment-variables.md) documentation to see if you want to configure any during installation. -You can configure environment variables at any time after deploying the application. +Before installing the Immich app in SCALE, review the [Environment Variables](#environment-variables) documentation to see if you want to configure any during installation. +You may also configure environment variables at any time after deploying the application. + +### Setting up Storage Datasets -You can allow SCALE to create the datasets Immich requires automatically during app installation. -Or before beginning app installation, [create the datasets](https://www.truenas.com/docs/scale/scaletutorials/storage/datasets/datasetsscale/) to use in the **Storage Configuration** section during installation. -Immich requires seven datasets: **library**, **pgBackup**, **pgData**, **profile**, **thumbs**, **uploads**, and **video**. -You can organize these as one parent with seven child datasets, for example `mnt/tank/immich/library`, `mnt/tank/immich/pgBackup`, and so on. +Before beginning app installation, [create the datasets](https://www.truenas.com/docs/scale/scaletutorials/storage/datasets/datasetsscale/) to use in the **Storage Configuration** section during installation. +Immich requires seven datasets: `library`, `upload`, `thumbs`, `profile`, `video`, `backups`, and `pgData`. +You can organize these as one parent with seven child datasets, for example `/mnt/tank/immich/library`, `/mnt/tank/immich/upload`, and so on. + + :::info Permissions The **pgData** dataset must be owned by the user `netdata` (UID 999) for postgres to start. The other datasets must be owned by the user `root` (UID 0) or a group that includes the user `root` (UID 0) for immich to have the necessary permissions. -The **library** dataset must have [ACL mode](https://www.truenas.com/docs/core/coretutorials/storage/pools/permissions/#access-control-lists) 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 **uploads** to **library**, immich performs `chmod` internally and needs to be allowed to execute the command. +If the **library** dataset uses ACL it must have [ACL mode](https://www.truenas.com/docs/core/coretutorials/storage/pools/permissions/#access-control-lists) 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**, immich performs `chmod` internally and needs to be allowed to execute the command. [More info.](https://github.com/immich-app/immich/pull/13017) ::: ## Installing the Immich Application @@ -47,6 +57,8 @@ className="border rounded-xl" Click on the widget to open the **Immich** application details screen. +

+
+ Application configuration settings are presented in several sections, each explained below. To find specific fields click in the **Search Input Fields** search field, scroll down to a particular section or click on the section heading on the navigation area in the upper-right corner. +### Application Name and Version + Install Immich Screen -Accept the default values in **Application Name** and **Version**. - -Accept the default value in **Timezone** or change to match your local timezone. -**Timezone** is only used by the Immich `exiftool` microservice if it cannot be determined from the image metadata. - -Accept the default port in **Web Port**. - -Immich requires seven storage datasets. -You can allow SCALE to create them for you, or use the dataset(s) created in [First Steps](#first-steps). -Select the storage options you want to use for **Immich Uploads Storage**, **Immich Library Storage**, **Immich Thumbs Storage**, **Immich Profile Storage**, **Immich Video Storage**, **Immich Postgres Data Storage**, **Immich Postgres Backup Storage**. -Select **ixVolume (dataset created automatically by the system)** in **Type** to let SCALE create the dataset or select **Host Path** to use the existing datasets created on the system. +Accept the default value or enter a name in **Application Name** field. +In most cases use the default name, but if adding a second deployment of the application you must change this name. -Accept the defaults in Resources or change the CPU and memory limits to suit your use case. +Accept the default version number in **Version**. +When a new version becomes available, the application has an update badge. +The **Installed Applications** screen shows the option to update applications. -Click **Install**. -The system opens the **Installed Applications** screen with the Immich app in the **Deploying** state. -When the installation completes it changes to **Running**. +### Immich Configuration -Click **Web Portal** on the **Application Info** widget to open the Immich web interface to set up your account and begin uploading photos. +Accept the default value in **Timezone** or change to match your local timezone. +**Timezone** is only used by the Immich `exiftool` microservice if it cannot be determined from the image metadata. -:::tip -For more information on how to use the application once installed, please refer to the [Post Install](/docs/install/post-install.mdx) guide. -::: +Untick **Enable Machine Learning** if you will not use face recognition, image search, and smart duplicate detection. -## Editing Environment Variables +Accept the default option or select the **Machine Learning Image Type** for your hardware based on the [Hardware-Accelerated Machine Learning Supported Backends](/docs/features/ml-hardware-acceleration.md#supported-backends). -Go to the **Installed Applications** screen and select Immich from the list of installed applications. -Click **Edit** on the **Application Info** widget to open the **Edit Immich** screen. -The settings on the edit screen are the same as on the install screen. -You cannot edit **Storage Configuration** paths after the initial app install. +Immich's default is `postgres` but you should consider setting the **Database Password** to a custom value using only the characters `A-Za-z0-9`. -Click **Update** to save changes. -TrueNAS automatically updates, recreates, and redeploys the Immich container with the updated environment variables. +The **Redis Password** should be set to a custom value using only the characters `A-Za-z0-9`. -## Updating the App +Accept the **Log Level** default of **Log**. -When updates become available, SCALE alerts and provides easy updates. -To update the app to the latest version, click **Update** on the **Application Info** widget from the **Installed Applications** screen. +Leave **Hugging Face Endpoint** blank. (This is for downloading ML models from a different source.) -Update opens an update window for the application that includes two selectable options, Images (to be updated) and Changelog. Click on the down arrow to see the options available for each. +Leave **Additional Environment Variables** blank or see [Environment Variables](#environment-variables) to set before installing. -Click **Upgrade** to begin the process and open a counter dialog that shows the upgrade progress. When complete, the update badge and buttons disappear and the application Update state on the Installed screen changes from Update Available to Up to date. +### Network Configuration -## Understanding Immich Settings in TrueNAS SCALE + -Accept the default value or enter a name in **Application Name** field. -In most cases use the default name, but if adding a second deployment of the application you must change this name. +Accept the default port `30041` in **WebUI Port** or enter a custom port number. +:::info Allowed Port Numbers +Only numbers within the range 9000-65535 may be used on SCALE versions below TrueNAS Scale 24.10 Electric Eel. -Accept the default version number in **Version**. -When a new version becomes available, the application has an update badge. -The **Installed Applications** screen shows the option to update applications. +Regardless of version, to avoid port conflicts, don't use [ports on this list](https://www.truenas.com/docs/references/defaultports/). +::: -### Immich Configuration Settings +### Storage Configuration -You can accept the defaults in the **Immich Configuration** settings, or enter the settings you want to use. +Immich requires seven storage datasets. -Accept the default setting in **Timezone** or change to match your local timezone. -**Timezone** is only used by the Immich `exiftool` microservice if it cannot be determined from the image metadata. +:::note Default Setting (Not recommended) +The default setting for datasets is **ixVolume (dataset created automatically by the system)** but this results in your data being harder to access manually and can result in data loss if you delete the immich app. (Not recommended) +::: -You can enter a **Public Login Message** to display on the login page, or leave it blank. +For each Storage option select **Host Path (Path that already exists on the system)** and then select the matching dataset [created before installing the app](#setting-up-storage-datasets): **Immich Library Storage**: `library`, **Immich Uploads Storage**: `upload`, **Immich Thumbs Storage**: `thumbs`, **Immich Profile Storage**: `profile`, **Immich Video Storage**: `video`, **Immich Backups Storage**: `backups`, **Postgres Data Storage**: `pgData`. -### Networking Settings + +The image above has example values. -Accept the default port numbers in **Web Port**. -The SCALE Immich app listens on port **30041**. +
-Refer to the TrueNAS [default port list](https://www.truenas.com/docs/references/defaultports/) for a list of assigned port numbers. -To change the port numbers, enter a number within the range 9000-65535. +### Additional Storage [(External Libraries)](/docs/features/libraries) -### Storage Settings +You may configure [External Libraries](/docs/features/libraries) by mounting them using **Additional Storage**. +The **Mount Path** is the loaction you will need to copy and paste into the External Library settings within Immich. +The **Host Path** is the location on the TrueNAS SCALE server where your external library is located. + + -You can install Immich using the default setting **ixVolume (dataset created automatically by the system)** or use the host path option with datasets [created before installing the app](#first-steps). +### Resources Configuration -Select **Host Path (Path that already exists on the system)** to browse to and select the datasets. +Accept the default **CPU** limit of `2` threads or specify the number of threads (CPUs with Multi-/Hyper-threading have 2 threads per core). + +Accept the default **Memory** limit of `4096` MB or specify the number of MB of RAM. If you're using Machine Learning you should probably set this above 8000 MB. + +:::info Older SCALE Versions +Before TrueNAS SCALE version 24.10 Electric Eel: + +The **CPU** value was specified in a different format with a default of `4000m` which is 4 threads. + +The **Memory** value was specified in a different format with a default of `8Gi` which is 8 GiB of RAM. The value was specified in bytes or a number with a measurement suffix. Examples: `129M`, `123Mi`, `1000000000` +::: + +Enable **GPU Configuration** options if you have a GPU that you will use for [Hardware Transcoding](/docs/features/hardware-transcoding) and/or [Hardware-Accelerated Machine Learning](/docs/features/ml-hardware-acceleration.md). More info: [GPU Passtrough Docs for TrueNAS Apps](https://www.truenas.com/docs/truenasapps/#gpu-passthrough) + +### Install + +Finally, click **Install**. +The system opens the **Installed Applications** screen with the Immich app in the **Deploying** state. +When the installation completes it changes to **Running**. -### Resource Configuration Settings +Click **Web Portal** on the **Application Info** widget to open the Immich web interface to set up your account and begin uploading photos. + +:::tip +For more information on how to use the application once installed, please refer to the [Post Install](/docs/install/post-install.mdx) guide. +::: + +## Edit App Settings -Accept the default values in **Resources Configuration** or enter new CPU and memory values -By default, this application is limited to use no more than 4 CPU cores and 8 Gigabytes available memory. The application might use considerably less system resources. +- Go to the **Installed Applications** screen and select Immich from the list of installed applications. +- Click **Edit** on the **Application Info** widget to open the **Edit Immich** screen. +- Change any settings you would like to change. + - The settings on the edit screen are the same as on the install screen. +- Click **Update** at the very bottom of the page to save changes. + - TrueNAS automatically updates, recreates, and redeploys the Immich container with the updated settings. + +## Environment Variables + +You can set [Environment Variables](/docs/install/environment-variables) by clicking **Add** on the **Additional Environment Variables** option and filling in the **Name** and **Value**. -To customize the CPU and memory allocated to the container Immich uses, enter new CPU values as a plain integer value followed by the suffix m (milli). -Default is 4000m. +:::info +Some Environment Variables are not available for the TrueNAS SCALE app. This is mainly because they can be configured through GUI options in the [Edit Immich screen](#edit-app-settings). + +Some examples are: `IMMICH_VERSION`, `UPLOAD_LOCATION`, `DB_DATA_LOCATION`, `TZ`, `IMMICH_LOG_LEVEL`, `DB_PASSWORD`, `REDIS_PASSWORD`. +::: -Accept the default value 8Gi allocated memory or enter a new limit in bytes. -Enter a plain integer followed by the measurement suffix, for example 129M or 123Mi. +## Updating the App -Systems with compatible GPU(s) display devices in **GPU Configuration**. -See [Managing GPUs](https://www.truenas.com/docs/scale/scaletutorials/systemsettings/advanced/managegpuscale/) for more information about allocating isolated GPU devices in TrueNAS SCALE. +When updates become available, SCALE alerts and provides easy updates. +To update the app to the latest version: + +- Go to the **Installed Applications** screen and select Immich from the list of installed applications. +- Click **Update** on the **Application Info** widget from the **Installed Applications** screen. +- This opens an update window with some options + - You may select an Image update too. + - You may view the Changelog. +- Click **Upgrade** to begin the process and open a counter dialog that shows the upgrade progress. + - When complete, the update badge and buttons disappear and the application Update state on the Installed screen changes from Update Available to Up to date. diff --git a/docs/docs/overview/quick-start.mdx b/docs/docs/overview/quick-start.mdx index e352757a0f67e..9c7ca8bd08c76 100644 --- a/docs/docs/overview/quick-start.mdx +++ b/docs/docs/overview/quick-start.mdx @@ -14,13 +14,7 @@ Check the [requirements page](/docs/install/requirements) to get started. ## Install and Launch via Docker Compose -Follow the [Docker Compose (Recommended)](/docs/install/docker-compose) instructions -to install the server. - -- Where random passwords are required, `pwgen` is a handy utility. -- `UPLOAD_LOCATION` should be set to some new directory on the server - with enough free space. -- You may ignore "Step 4 - Upgrading". +Follow the [Docker Compose (Recommended)](/docs/install/docker-compose) instructions to install the server. ## Try the Web UI @@ -56,6 +50,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). You can select the **Jobs** tab to see Immich processing your photos. diff --git a/docs/docs/partials/_mobile-app-backup.md b/docs/docs/partials/_mobile-app-backup.md index 9929d0e36ebec..059f5947542ba 100644 --- a/docs/docs/partials/_mobile-app-backup.md +++ b/docs/docs/partials/_mobile-app-backup.md @@ -1,9 +1,9 @@ -Navigate to the backup screen by clicking on the cloud icon in the top right corner of the screen. +1. Navigate to the backup screen by clicking on the cloud icon in the top right corner of the screen. -You can select which album(s) you want to back up to the Immich server from the backup screen. +2. You can select which album(s) you want to back up to the Immich server from the backup screen. -Scroll down to the bottom and press "**Start Backup**" to start the backup process. +3. Scroll down to the bottom and press "**Start Backup**" to start the backup process. This will upload all the assets in the selected albums. diff --git a/docs/package-lock.json b/docs/package-lock.json index 38e376c7e6507..ca80d15fd0026 100644 --- a/docs/package-lock.json +++ b/docs/package-lock.json @@ -8,8 +8,8 @@ "name": "documentation", "version": "0.0.0", "dependencies": { - "@docusaurus/core": "^3.2.1", - "@docusaurus/preset-classic": "^3.2.1", + "@docusaurus/core": "~3.5.2", + "@docusaurus/preset-classic": "~3.5.2", "@mdi/js": "^7.3.67", "@mdi/react": "^1.6.1", "@mdx-js/react": "^3.0.0", @@ -27,7 +27,7 @@ "url": "^0.11.0" }, "devDependencies": { - "@docusaurus/module-type-aliases": "^3.1.0", + "@docusaurus/module-type-aliases": "~3.5.2", "@tsconfig/docusaurus": "^2.0.2", "prettier": "^3.2.4", "typescript": "^5.1.6" diff --git a/docs/package.json b/docs/package.json index a102c6d0d5f4e..e739cd68c74c5 100644 --- a/docs/package.json +++ b/docs/package.json @@ -16,8 +16,8 @@ "write-heading-ids": "docusaurus write-heading-ids" }, "dependencies": { - "@docusaurus/core": "^3.2.1", - "@docusaurus/preset-classic": "^3.2.1", + "@docusaurus/core": "~3.5.2", + "@docusaurus/preset-classic": "~3.5.2", "@mdi/js": "^7.3.67", "@mdi/react": "^1.6.1", "@mdx-js/react": "^3.0.0", @@ -35,8 +35,7 @@ "url": "^0.11.0" }, "devDependencies": { - "@docusaurus/module-type-aliases": "^3.1.0", - "@tsconfig/docusaurus": "^2.0.2", + "@docusaurus/module-type-aliases": "~3.5.2", "prettier": "^3.2.4", "typescript": "^5.1.6" }, @@ -56,6 +55,6 @@ "node": ">=20" }, "volta": { - "node": "22.11.0" + "node": "22.12.0" } } diff --git a/docs/src/components/community-guides.tsx b/docs/src/components/community-guides.tsx index 7f4206c97baf1..17fe56231754e 100644 --- a/docs/src/components/community-guides.tsx +++ b/docs/src/components/community-guides.tsx @@ -35,19 +35,24 @@ const guides: CommunityGuidesProps[] = [ }, { title: 'Google Photos import + albums', - description: 'Import your Google Photos files into Immich and add your albums', + description: 'Import your Google Photos files into Immich and add your albums.', url: 'https://github.com/immich-app/immich/discussions/1340', }, { title: 'Access Immich with custom domain', - description: 'Access your local Immich installation over the internet using your own domain', + description: 'Access your local Immich installation over the internet using your own domain.', url: 'https://github.com/ppr88/immich-guides/blob/main/open-immich-custom-domain.md', }, { title: 'Nginx caching map server', - description: 'Increase privacy by using nginx as a caching proxy in front of a map tile server', + description: 'Increase privacy by using nginx as a caching proxy in front of a map tile server.', url: 'https://github.com/pcouy/pcouy.github.io/blob/main/_posts/2024-08-30-proxying-a-map-tile-server-for-increased-privacy.md', }, + { + title: 'fail2ban setup instructions', + description: 'How to configure an existing fail2ban installation to block incorrect login attempts.', + url: 'https://github.com/immich-app/immich/discussions/3243#discussioncomment-6681948', + }, ]; function CommunityGuide({ title, description, url }: CommunityGuidesProps): JSX.Element { diff --git a/docs/src/components/community-projects.tsx b/docs/src/components/community-projects.tsx index 3a034e3a04cfd..2dbab979f2ce9 100644 --- a/docs/src/components/community-projects.tsx +++ b/docs/src/components/community-projects.tsx @@ -83,6 +83,17 @@ const projects: CommunityProjectProps[] = [ description: 'Power tools for organizing your immich library.', url: 'https://github.com/varun-raj/immich-power-tools', }, + { + title: 'Immich Public Proxy', + description: + 'Share your Immich photos and albums in a safe way without exposing your Immich instance to the public.', + url: 'https://github.com/alangrainger/immich-public-proxy', + }, + { + title: 'Immich Kodi', + description: 'Unofficial Kodi plugin for Immich.', + url: 'https://github.com/vladd11/immich-kodi', + }, ]; function CommunityProject({ title, description, url }: CommunityProjectProps): JSX.Element { diff --git a/docs/src/components/timeline.tsx b/docs/src/components/timeline.tsx index 374d2d88fab19..32b15edb5960b 100644 --- a/docs/src/components/timeline.tsx +++ b/docs/src/components/timeline.tsx @@ -49,7 +49,7 @@ export function Timeline({ items }: Props): JSX.Element {
{cardIcon === 'immich' ? ( - + ) : ( )} diff --git a/docs/src/pages/roadmap.tsx b/docs/src/pages/roadmap.tsx index 1f07e45122749..7de51f7513935 100644 --- a/docs/src/pages/roadmap.tsx +++ b/docs/src/pages/roadmap.tsx @@ -74,12 +74,14 @@ import { mdiFaceRecognition, mdiVideo, mdiWeb, + mdiDatabaseOutline, } from '@mdi/js'; import Layout from '@theme/Layout'; import React from 'react'; import { Item, Timeline } from '../components/timeline'; const releases = { + '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), @@ -151,6 +153,9 @@ const weirdTags = { '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 }; @@ -177,27 +182,19 @@ const withRelease = ({ const roadmap: Item[] = [ { done: false, - icon: mdiLockOutline, - iconColor: 'sandybrown', - title: 'Private/locked photos', - description: 'Private assets with extra protections', - getDateLabel: () => 'Planned for 2024', - }, - { - done: false, - icon: mdiRocketLaunch, - iconColor: 'indianred', - title: 'Stable release', - description: 'Immich goes stable', - getDateLabel: () => 'Planned for 2024', + icon: mdiFlash, + iconColor: 'gold', + title: 'Workflows', + description: 'Automate tasks with workflows', + 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 2024', + icon: mdiTableKey, + iconColor: 'gray', + title: 'Fine grained access controls', + description: 'Granular access controls for users and api keys', + getDateLabel: () => 'Planned for 2025', }, { done: false, @@ -205,22 +202,30 @@ const roadmap: Item[] = [ iconColor: 'rebeccapurple', title: 'Basic editor', description: 'Basic photo editing capabilities', - getDateLabel: () => 'Planned for 2024', + getDateLabel: () => 'Planned for 2025', }, { done: false, - icon: mdiFlash, - iconColor: 'gold', - title: 'Workflows', - description: 'Automate tasks with workflows', + icon: mdiRocketLaunch, + iconColor: 'indianred', + title: 'Stable release', + description: 'Immich goes stable', + getDateLabel: () => 'Planned for early 2025', + }, + { + done: false, + icon: mdiLockOutline, + iconColor: 'sandybrown', + title: 'Private/locked photos', + description: 'Private assets with extra protections', getDateLabel: () => 'Planned for 2024', }, { done: false, - icon: mdiTableKey, - iconColor: 'gray', - title: 'Fine grained access controls', - description: 'Granular access controls for users and api keys', + icon: mdiCloudUploadOutline, + iconColor: 'cornflowerblue', + title: 'Better background backups', + description: 'Rework background backups to be more reliable', getDateLabel: () => 'Planned for 2024', }, { @@ -234,6 +239,20 @@ const roadmap: Item[] = [ ]; const milestones: Item[] = [ + withRelease({ + icon: mdiDatabaseOutline, + iconColor: 'brown', + title: 'Automatic database backups', + description: 'Database backups 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', @@ -853,14 +872,12 @@ const milestones: Item[] = [ export default function MilestonePage(): JSX.Element { return ( - +

- Roadmap + {title}

-

- A list of future plans and goals, as well as past achievements and milestones. -

+

{description}

diff --git a/docs/static/archived-versions.json b/docs/static/archived-versions.json index ac1594e81aaa5..562098f76f4a4 100644 --- a/docs/static/archived-versions.json +++ b/docs/static/archived-versions.json @@ -1,4 +1,40 @@ [ + { + "label": "v1.123.0", + "url": "https://v1.123.0.archive.immich.app" + }, + { + "label": "v1.122.3", + "url": "https://v1.122.3.archive.immich.app" + }, + { + "label": "v1.122.2", + "url": "https://v1.122.2.archive.immich.app" + }, + { + "label": "v1.122.1", + "url": "https://v1.122.1.archive.immich.app" + }, + { + "label": "v1.122.0", + "url": "https://v1.122.0.archive.immich.app" + }, + { + "label": "v1.121.0", + "url": "https://v1.121.0.archive.immich.app" + }, + { + "label": "v1.120.2", + "url": "https://v1.120.2.archive.immich.app" + }, + { + "label": "v1.120.1", + "url": "https://v1.120.1.archive.immich.app" + }, + { + "label": "v1.120.0", + "url": "https://v1.120.0.archive.immich.app" + }, { "label": "v1.119.1", "url": "https://v1.119.1.archive.immich.app" diff --git a/e2e/.nvmrc b/e2e/.nvmrc index 7af24b7ddbde0..1d9b7831ba9d9 100644 --- a/e2e/.nvmrc +++ b/e2e/.nvmrc @@ -1 +1 @@ -22.11.0 +22.12.0 diff --git a/e2e/docker-compose.yml b/e2e/docker-compose.yml index f8f41eac4679e..d9117b1b4aef3 100644 --- a/e2e/docker-compose.yml +++ b/e2e/docker-compose.yml @@ -34,7 +34,7 @@ services: - 2285:2285 redis: - image: redis:6.2-alpine@sha256:2ba50e1ac3a0ea17b736ce9db2b0a9f6f8b85d4c27d5f5accc6a416d8f42c6d5 + image: redis:6.2-alpine@sha256:eaba718fecd1196d88533de7ba49bf903ad33664a92debb24660a922ecd9cac8 database: image: tensorchord/pgvecto-rs:pg14-v0.2.0@sha256:90724186f0a3517cf6914295b5ab410db9ce23190a2d9d0b9dd6463e3fa298f0 diff --git a/e2e/package-lock.json b/e2e/package-lock.json index 24f3bfdeee7c8..5af61ee6f910e 100644 --- a/e2e/package-lock.json +++ b/e2e/package-lock.json @@ -1,12 +1,12 @@ { "name": "immich-e2e", - "version": "1.119.1", + "version": "1.123.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "immich-e2e", - "version": "1.119.1", + "version": "1.123.0", "license": "GNU Affero General Public License version 3", "devDependencies": { "@eslint/eslintrc": "^3.1.0", @@ -15,18 +15,18 @@ "@immich/sdk": "file:../open-api/typescript-sdk", "@playwright/test": "^1.44.1", "@types/luxon": "^3.4.2", - "@types/node": "^22.8.1", + "@types/node": "^22.10.2", "@types/oidc-provider": "^8.5.1", "@types/pg": "^8.11.0", "@types/pngjs": "^6.0.4", "@types/supertest": "^6.0.2", - "@typescript-eslint/eslint-plugin": "^8.0.0", - "@typescript-eslint/parser": "^8.0.0", + "@typescript-eslint/eslint-plugin": "^8.15.0", + "@typescript-eslint/parser": "^8.15.0", "@vitest/coverage-v8": "^2.0.5", - "eslint": "^9.0.0", + "eslint": "^9.14.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-prettier": "^5.1.3", - "eslint-plugin-unicorn": "^55.0.0", + "eslint-plugin-unicorn": "^56.0.1", "exiftool-vendored": "^28.3.1", "globals": "^15.9.0", "jose": "^5.6.3", @@ -45,7 +45,7 @@ }, "../cli": { "name": "@immich/cli", - "version": "2.2.28", + "version": "2.2.37", "dev": true, "license": "GNU Affero General Public License version 3", "dependencies": { @@ -64,17 +64,17 @@ "@types/cli-progress": "^3.11.0", "@types/lodash-es": "^4.17.12", "@types/mock-fs": "^4.13.1", - "@types/node": "^22.8.1", - "@typescript-eslint/eslint-plugin": "^8.0.0", - "@typescript-eslint/parser": "^8.0.0", + "@types/node": "^22.10.2", + "@typescript-eslint/eslint-plugin": "^8.15.0", + "@typescript-eslint/parser": "^8.15.0", "@vitest/coverage-v8": "^2.0.5", "byte-size": "^9.0.0", "cli-progress": "^3.12.0", "commander": "^12.0.0", - "eslint": "^9.0.0", + "eslint": "^9.14.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-prettier": "^5.1.3", - "eslint-plugin-unicorn": "^55.0.0", + "eslint-plugin-unicorn": "^56.0.1", "globals": "^15.9.0", "mock-fs": "^5.2.0", "prettier": "^3.2.5", @@ -92,14 +92,14 @@ }, "../open-api/typescript-sdk": { "name": "@immich/sdk", - "version": "1.119.1", + "version": "1.123.0", "dev": true, "license": "GNU Affero General Public License version 3", "dependencies": { "@oazapfts/runtime": "^1.0.2" }, "devDependencies": { - "@types/node": "^22.8.1", + "@types/node": "^22.10.2", "typescript": "^5.3.3" } }, @@ -210,19 +210,21 @@ } }, "node_modules/@babel/helper-string-parser": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz", - "integrity": "sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", + "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz", - "integrity": "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", + "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } @@ -319,12 +321,13 @@ } }, "node_modules/@babel/parser": { - "version": "7.25.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.3.tgz", - "integrity": "sha512-iLTJKDbJ4hMvFPgQwwsVoxtHyWpKKPBrxkANrSYewDPaPpT5py5yeVkgPIJ7XYXhndxJpaA3PyALSXQ7u8e/Dw==", + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.2.tgz", + "integrity": "sha512-DWMCZH9WA4Maitz2q21SRKHo9QXZxkDsbNZoVD62gusNtNBBqDg9i7uOhASfTfIGNzW+O+r7+jAlM8dwphcJKQ==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/types": "^7.25.2" + "@babel/types": "^7.26.0" }, "bin": { "parser": "bin/babel-parser.js" @@ -334,14 +337,14 @@ } }, "node_modules/@babel/types": { - "version": "7.25.2", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.2.tgz", - "integrity": "sha512-YTnYtra7W9e6/oAZEHj0bJehPRUlLH9/fbpT5LfB0NhQXyALCRkRs3zH9v07IYhkgpqX6Z78FnuccZr/l4Fs4Q==", + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.0.tgz", + "integrity": "sha512-Z/yiTPj+lDVnF7lWeKCIJzaIkI0vYO87dMpZ4bg4TDrFe4XXLFWL1TbXU27gBP3QccxV9mZICCrnjnYlJjXHOA==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-string-parser": "^7.24.8", - "@babel/helper-validator-identifier": "^7.24.7", - "to-fast-properties": "^2.0.0" + "@babel/helper-string-parser": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -760,9 +763,9 @@ } }, "node_modules/@eslint-community/regexpp": { - "version": "4.11.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.0.tgz", - "integrity": "sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A==", + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", + "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", "dev": true, "license": "MIT", "engines": { @@ -795,9 +798,9 @@ } }, "node_modules/@eslint/eslintrc": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.1.0.tgz", - "integrity": "sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.2.0.tgz", + "integrity": "sha512-grOjVNN8P3hjJn/eIETF1wwd12DdnwFDoyceUJLYYdkpbwq3nLi+4fqrTAONx7XDALqlL220wC/RHSC/QTI/0w==", "dev": true, "license": "MIT", "dependencies": { @@ -832,9 +835,9 @@ } }, "node_modules/@eslint/js": { - "version": "9.13.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.13.0.tgz", - "integrity": "sha512-IFLyoY4d72Z5y/6o/BazFBezupzI/taV8sGumxTAVw3lXG9A6md1Dc34T9s1FoD/an9pJH8RHbAxsaEbBed9lA==", + "version": "9.15.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.15.0.tgz", + "integrity": "sha512-tMTqrY+EzbXmKJR5ToI8lxu7jaN5EdmrBFJpQk5JmSlyLsx6o4t27r883K5xsLuCYCpfKBCGswMSWXsM+jB7lg==", "dev": true, "license": "MIT", "engines": { @@ -852,9 +855,9 @@ } }, "node_modules/@eslint/plugin-kit": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.0.tgz", - "integrity": "sha512-vH9PiIMMwvhCx31Af3HiGzsVNULDbyVkHXwlemn/B0TFj/00ho3y55efXrUZTfQipxoHC5u4xq6zblww1zm1Ig==", + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.3.tgz", + "integrity": "sha512-2b/g5hRmpbb1o4GnTZax9N9m0FXzz9OV42ZzI4rDDMDuHUqigAiQCEWChBWCY4ztAGVRjoWT19v0yMmc5/L5kA==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -865,9 +868,9 @@ } }, "node_modules/@humanfs/core": { - "version": "0.19.0", - "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.0.tgz", - "integrity": "sha512-2cbWIHbZVEweE853g8jymffCA+NCMiuqeECeBBLm8dg2oFdjuGJhgN4UAbI+6v0CKbbhvtXA4qV8YR5Ji86nmw==", + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", + "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", "dev": true, "license": "Apache-2.0", "engines": { @@ -875,19 +878,33 @@ } }, "node_modules/@humanfs/node": { - "version": "0.16.5", - "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.5.tgz", - "integrity": "sha512-KSPA4umqSG4LHYRodq31VDwKAvaTF4xmVlzM8Aeh4PlU1JQ3IG0wiA8C25d3RQ9nJyM3mBHyI53K06VVL/oFFg==", + "version": "0.16.6", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.6.tgz", + "integrity": "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@humanfs/core": "^0.19.0", + "@humanfs/core": "^0.19.1", "@humanwhocodes/retry": "^0.3.0" }, "engines": { "node": ">=18.18.0" } }, + "node_modules/@humanfs/node/node_modules/@humanwhocodes/retry": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz", + "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, "node_modules/@humanwhocodes/module-importer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", @@ -902,9 +919,9 @@ } }, "node_modules/@humanwhocodes/retry": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz", - "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==", + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.1.tgz", + "integrity": "sha512-c7hNEllBlenFTHBky65mhq8WD2kbN9Q6gk0bTk8lSBvc554jpXSkST1iePudpt7+A/AQvuHs9EMqjHDXMY1lrA==", "dev": true, "license": "Apache-2.0", "engines": { @@ -1186,13 +1203,13 @@ } }, "node_modules/@playwright/test": { - "version": "1.48.1", - "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.48.1.tgz", - "integrity": "sha512-s9RtWoxkOLmRJdw3oFvhFbs9OJS0BzrLUc8Hf6l2UdCNd1rqeEyD4BhCJkvzeEoD1FsK4mirsWwGerhVmYKtZg==", + "version": "1.48.2", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.48.2.tgz", + "integrity": "sha512-54w1xCWfXuax7dz4W2M9uw0gDyh+ti/0K/MxcCUxChFh37kkdxPdfZDw5QBbuPUJHr1CiHJ1hXgSs+GgeQc5Zw==", "dev": true, "license": "Apache-2.0", "dependencies": { - "playwright": "1.48.1" + "playwright": "1.48.2" }, "bin": { "playwright": "cli.js" @@ -1202,9 +1219,9 @@ } }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.24.0.tgz", - "integrity": "sha512-Q6HJd7Y6xdB48x8ZNVDOqsbh2uByBhgK8PiQgPhwkIw/HC/YX5Ghq2mQY5sRMZWHb3VsFkWooUVOZHKr7DmDIA==", + "version": "4.27.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.27.3.tgz", + "integrity": "sha512-EzxVSkIvCFxUd4Mgm4xR9YXrcp976qVaHnqom/Tgm+vU79k4vV4eYTjmRvGfeoW8m9LVcsAy/lGjcgVegKEhLQ==", "cpu": [ "arm" ], @@ -1216,9 +1233,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.24.0.tgz", - "integrity": "sha512-ijLnS1qFId8xhKjT81uBHuuJp2lU4x2yxa4ctFPtG+MqEE6+C5f/+X/bStmxapgmwLwiL3ih122xv8kVARNAZA==", + "version": "4.27.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.27.3.tgz", + "integrity": "sha512-LJc5pDf1wjlt9o/Giaw9Ofl+k/vLUaYsE2zeQGH85giX2F+wn/Cg8b3c5CDP3qmVmeO5NzwVUzQQxwZvC2eQKw==", "cpu": [ "arm64" ], @@ -1230,9 +1247,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.24.0.tgz", - "integrity": "sha512-bIv+X9xeSs1XCk6DVvkO+S/z8/2AMt/2lMqdQbMrmVpgFvXlmde9mLcbQpztXm1tajC3raFDqegsH18HQPMYtA==", + "version": "4.27.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.27.3.tgz", + "integrity": "sha512-OuRysZ1Mt7wpWJ+aYKblVbJWtVn3Cy52h8nLuNSzTqSesYw1EuN6wKp5NW/4eSre3mp12gqFRXOKTcN3AI3LqA==", "cpu": [ "arm64" ], @@ -1244,9 +1261,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.24.0.tgz", - "integrity": "sha512-X6/nOwoFN7RT2svEQWUsW/5C/fYMBe4fnLK9DQk4SX4mgVBiTA9h64kjUYPvGQ0F/9xwJ5U5UfTbl6BEjaQdBQ==", + "version": "4.27.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.27.3.tgz", + "integrity": "sha512-xW//zjJMlJs2sOrCmXdB4d0uiilZsOdlGQIC/jjmMWT47lkLLoB1nsNhPUcnoqyi5YR6I4h+FjBpILxbEy8JRg==", "cpu": [ "x64" ], @@ -1257,10 +1274,38 @@ "darwin" ] }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.27.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.27.3.tgz", + "integrity": "sha512-58E0tIcwZ+12nK1WiLzHOD8I0d0kdrY/+o7yFVPRHuVGY3twBwzwDdTIBGRxLmyjciMYl1B/U515GJy+yn46qw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.27.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.27.3.tgz", + "integrity": "sha512-78fohrpcVwTLxg1ZzBMlwEimoAJmY6B+5TsyAZ3Vok7YabRBUvjYTsRXPTjGEvv/mfgVBepbW28OlMEz4w8wGA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.24.0.tgz", - "integrity": "sha512-0KXvIJQMOImLCVCz9uvvdPgfyWo93aHHp8ui3FrtOP57svqrF/roSSR5pjqL2hcMp0ljeGlU4q9o/rQaAQ3AYA==", + "version": "4.27.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.27.3.tgz", + "integrity": "sha512-h2Ay79YFXyQi+QZKo3ISZDyKaVD7uUvukEHTOft7kh00WF9mxAaxZsNs3o/eukbeKuH35jBvQqrT61fzKfAB/Q==", "cpu": [ "arm" ], @@ -1272,9 +1317,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.24.0.tgz", - "integrity": "sha512-it2BW6kKFVh8xk/BnHfakEeoLPv8STIISekpoF+nBgWM4d55CZKc7T4Dx1pEbTnYm/xEKMgy1MNtYuoA8RFIWw==", + "version": "4.27.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.27.3.tgz", + "integrity": "sha512-Sv2GWmrJfRY57urktVLQ0VKZjNZGogVtASAgosDZ1aUB+ykPxSi3X1nWORL5Jk0sTIIwQiPH7iE3BMi9zGWfkg==", "cpu": [ "arm" ], @@ -1286,9 +1331,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.24.0.tgz", - "integrity": "sha512-i0xTLXjqap2eRfulFVlSnM5dEbTVque/3Pi4g2y7cxrs7+a9De42z4XxKLYJ7+OhE3IgxvfQM7vQc43bwTgPwA==", + "version": "4.27.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.27.3.tgz", + "integrity": "sha512-FPoJBLsPW2bDNWjSrwNuTPUt30VnfM8GPGRoLCYKZpPx0xiIEdFip3dH6CqgoT0RnoGXptaNziM0WlKgBc+OWQ==", "cpu": [ "arm64" ], @@ -1300,9 +1345,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.24.0.tgz", - "integrity": "sha512-9E6MKUJhDuDh604Qco5yP/3qn3y7SLXYuiC0Rpr89aMScS2UAmK1wHP2b7KAa1nSjWJc/f/Lc0Wl1L47qjiyQw==", + "version": "4.27.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.27.3.tgz", + "integrity": "sha512-TKxiOvBorYq4sUpA0JT+Fkh+l+G9DScnG5Dqx7wiiqVMiRSkzTclP35pE6eQQYjP4Gc8yEkJGea6rz4qyWhp3g==", "cpu": [ "arm64" ], @@ -1314,9 +1359,9 @@ ] }, "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.24.0.tgz", - "integrity": "sha512-2XFFPJ2XMEiF5Zi2EBf4h73oR1V/lycirxZxHZNc93SqDN/IWhYYSYj8I9381ikUFXZrz2v7r2tOVk2NBwxrWw==", + "version": "4.27.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.27.3.tgz", + "integrity": "sha512-v2M/mPvVUKVOKITa0oCFksnQQ/TqGrT+yD0184/cWHIu0LoIuYHwox0Pm3ccXEz8cEQDLk6FPKd1CCm+PlsISw==", "cpu": [ "ppc64" ], @@ -1328,9 +1373,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.24.0.tgz", - "integrity": "sha512-M3Dg4hlwuntUCdzU7KjYqbbd+BLq3JMAOhCKdBE3TcMGMZbKkDdJ5ivNdehOssMCIokNHFOsv7DO4rlEOfyKpg==", + "version": "4.27.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.27.3.tgz", + "integrity": "sha512-LdrI4Yocb1a/tFVkzmOE5WyYRgEBOyEhWYJe4gsDWDiwnjYKjNs7PS6SGlTDB7maOHF4kxevsuNBl2iOcj3b4A==", "cpu": [ "riscv64" ], @@ -1342,9 +1387,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.24.0.tgz", - "integrity": "sha512-mjBaoo4ocxJppTorZVKWFpy1bfFj9FeCMJqzlMQGjpNPY9JwQi7OuS1axzNIk0nMX6jSgy6ZURDZ2w0QW6D56g==", + "version": "4.27.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.27.3.tgz", + "integrity": "sha512-d4wVu6SXij/jyiwPvI6C4KxdGzuZOvJ6y9VfrcleHTwo68fl8vZC5ZYHsCVPUi4tndCfMlFniWgwonQ5CUpQcA==", "cpu": [ "s390x" ], @@ -1356,9 +1401,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.24.0.tgz", - "integrity": "sha512-ZXFk7M72R0YYFN5q13niV0B7G8/5dcQ9JDp8keJSfr3GoZeXEoMHP/HlvqROA3OMbMdfr19IjCeNAnPUG93b6A==", + "version": "4.27.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.27.3.tgz", + "integrity": "sha512-/6bn6pp1fsCGEY5n3yajmzZQAh+mW4QPItbiWxs69zskBzJuheb3tNynEjL+mKOsUSFK11X4LYF2BwwXnzWleA==", "cpu": [ "x64" ], @@ -1370,9 +1415,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.24.0.tgz", - "integrity": "sha512-w1i+L7kAXZNdYl+vFvzSZy8Y1arS7vMgIy8wusXJzRrPyof5LAb02KGr1PD2EkRcl73kHulIID0M501lN+vobQ==", + "version": "4.27.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.27.3.tgz", + "integrity": "sha512-nBXOfJds8OzUT1qUreT/en3eyOXd2EH5b0wr2bVB5999qHdGKkzGzIyKYaKj02lXk6wpN71ltLIaQpu58YFBoQ==", "cpu": [ "x64" ], @@ -1384,9 +1429,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.24.0.tgz", - "integrity": "sha512-VXBrnPWgBpVDCVY6XF3LEW0pOU51KbaHhccHw6AS6vBWIC60eqsH19DAeeObl+g8nKAz04QFdl/Cefta0xQtUQ==", + "version": "4.27.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.27.3.tgz", + "integrity": "sha512-ogfbEVQgIZOz5WPWXF2HVb6En+kWzScuxJo/WdQTqEgeyGkaa2ui5sQav9Zkr7bnNCLK48uxmmK0TySm22eiuw==", "cpu": [ "arm64" ], @@ -1398,9 +1443,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.24.0.tgz", - "integrity": "sha512-xrNcGDU0OxVcPTH/8n/ShH4UevZxKIO6HJFK0e15XItZP2UcaiLFd5kiX7hJnqCbSztUF8Qot+JWBC/QXRPYWQ==", + "version": "4.27.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.27.3.tgz", + "integrity": "sha512-ecE36ZBMLINqiTtSNQ1vzWc5pXLQHlf/oqGp/bSbi7iedcjcNb6QbCBNG73Euyy2C+l/fn8qKWEwxr+0SSfs3w==", "cpu": [ "ia32" ], @@ -1412,9 +1457,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.24.0.tgz", - "integrity": "sha512-fbMkAF7fufku0N2dE5TBXcNlg0pt0cJue4xBRE2Qc5Vqikxr4VCgKj/ht6SMdFcOacVA9rqF70APJ8RN/4vMJw==", + "version": "4.27.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.27.3.tgz", + "integrity": "sha512-vliZLrDmYKyaUoMzEbMTg2JkerfBjn03KmAw9CykO0Zzkzoyd7o3iZNam/TpyWNjNT+Cz2iO3P9Smv2wgrR+Eg==", "cpu": [ "x64" ], @@ -1613,13 +1658,13 @@ "dev": true }, "node_modules/@types/node": { - "version": "22.8.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.8.5.tgz", - "integrity": "sha512-5iYk6AMPtsMbkZqCO1UGF9W5L38twq11S2pYWkybGHH2ogPUvXWNlQqJBzuEZWKj/WRH+QTeiv6ySWqJtvIEgA==", + "version": "22.10.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.2.tgz", + "integrity": "sha512-Xxr6BBRCAOQixvonOye19wnzyDiUtTeqldOOmj3CkeblonbccA12PFwlufvRdrpjXxqnmUaeiU5EOA+7s5diUQ==", "dev": true, "license": "MIT", "dependencies": { - "undici-types": "~6.19.8" + "undici-types": "~6.20.0" } }, "node_modules/@types/normalize-package-data": { @@ -1777,17 +1822,17 @@ } }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.11.0.tgz", - "integrity": "sha512-KhGn2LjW1PJT2A/GfDpiyOfS4a8xHQv2myUagTM5+zsormOmBlYsnQ6pobJ8XxJmh6hnHwa2Mbe3fPrDJoDhbA==", + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.15.0.tgz", + "integrity": "sha512-+zkm9AR1Ds9uLWN3fkoeXgFppaQ+uEVtfOV62dDmsy9QCNqlRHWNEck4yarvRNrvRcHQLGfqBNui3cimoz8XAg==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.11.0", - "@typescript-eslint/type-utils": "8.11.0", - "@typescript-eslint/utils": "8.11.0", - "@typescript-eslint/visitor-keys": "8.11.0", + "@typescript-eslint/scope-manager": "8.15.0", + "@typescript-eslint/type-utils": "8.15.0", + "@typescript-eslint/utils": "8.15.0", + "@typescript-eslint/visitor-keys": "8.15.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", @@ -1811,16 +1856,16 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.11.0.tgz", - "integrity": "sha512-lmt73NeHdy1Q/2ul295Qy3uninSqi6wQI18XwSpm8w0ZbQXUpjCAWP1Vlv/obudoBiIjJVjlztjQ+d/Md98Yxg==", + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.15.0.tgz", + "integrity": "sha512-7n59qFpghG4uazrF9qtGKBZXn7Oz4sOMm8dwNWDQY96Xlm2oX67eipqcblDj+oY1lLCbf1oltMZFpUso66Kl1A==", "dev": true, "license": "BSD-2-Clause", "dependencies": { - "@typescript-eslint/scope-manager": "8.11.0", - "@typescript-eslint/types": "8.11.0", - "@typescript-eslint/typescript-estree": "8.11.0", - "@typescript-eslint/visitor-keys": "8.11.0", + "@typescript-eslint/scope-manager": "8.15.0", + "@typescript-eslint/types": "8.15.0", + "@typescript-eslint/typescript-estree": "8.15.0", + "@typescript-eslint/visitor-keys": "8.15.0", "debug": "^4.3.4" }, "engines": { @@ -1840,14 +1885,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.11.0.tgz", - "integrity": "sha512-Uholz7tWhXmA4r6epo+vaeV7yjdKy5QFCERMjs1kMVsLRKIrSdM6o21W2He9ftp5PP6aWOVpD5zvrvuHZC0bMQ==", + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.15.0.tgz", + "integrity": "sha512-QRGy8ADi4J7ii95xz4UoiymmmMd/zuy9azCaamnZ3FM8T5fZcex8UfJcjkiEZjJSztKfEBe3dZ5T/5RHAmw2mA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.11.0", - "@typescript-eslint/visitor-keys": "8.11.0" + "@typescript-eslint/types": "8.15.0", + "@typescript-eslint/visitor-keys": "8.15.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1858,14 +1903,14 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.11.0.tgz", - "integrity": "sha512-ItiMfJS6pQU0NIKAaybBKkuVzo6IdnAhPFZA/2Mba/uBjuPQPet/8+zh5GtLHwmuFRShZx+8lhIs7/QeDHflOg==", + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.15.0.tgz", + "integrity": "sha512-UU6uwXDoI3JGSXmcdnP5d8Fffa2KayOhUUqr/AiBnG1Gl7+7ut/oyagVeSkh7bxQ0zSXV9ptRh/4N15nkCqnpw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "8.11.0", - "@typescript-eslint/utils": "8.11.0", + "@typescript-eslint/typescript-estree": "8.15.0", + "@typescript-eslint/utils": "8.15.0", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" }, @@ -1876,6 +1921,9 @@ "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0" + }, "peerDependenciesMeta": { "typescript": { "optional": true @@ -1883,9 +1931,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.11.0.tgz", - "integrity": "sha512-tn6sNMHf6EBAYMvmPUaKaVeYvhUsrE6x+bXQTxjQRp360h1giATU0WvgeEys1spbvb5R+VpNOZ+XJmjD8wOUHw==", + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.15.0.tgz", + "integrity": "sha512-n3Gt8Y/KyJNe0S3yDCD2RVKrHBC4gTUcLTebVBXacPy091E6tNspFLKRXlk3hwT4G55nfr1n2AdFqi/XMxzmPQ==", "dev": true, "license": "MIT", "engines": { @@ -1897,14 +1945,14 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.11.0.tgz", - "integrity": "sha512-yHC3s1z1RCHoCz5t06gf7jH24rr3vns08XXhfEqzYpd6Hll3z/3g23JRi0jM8A47UFKNc3u/y5KIMx8Ynbjohg==", + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.15.0.tgz", + "integrity": "sha512-1eMp2JgNec/niZsR7ioFBlsh/Fk0oJbhaqO0jRyQBMgkz7RrFfkqF9lYYmBoGBaSiLnu8TAPQTwoTUiSTUW9dg==", "dev": true, "license": "BSD-2-Clause", "dependencies": { - "@typescript-eslint/types": "8.11.0", - "@typescript-eslint/visitor-keys": "8.11.0", + "@typescript-eslint/types": "8.15.0", + "@typescript-eslint/visitor-keys": "8.15.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -1952,16 +2000,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.11.0.tgz", - "integrity": "sha512-CYiX6WZcbXNJV7UNB4PLDIBtSdRmRI/nb0FMyqHPTQD1rMjA0foPLaPUV39C/MxkTd/QKSeX+Gb34PPsDVC35g==", + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.15.0.tgz", + "integrity": "sha512-k82RI9yGhr0QM3Dnq+egEpz9qB6Un+WLYhmoNcvl8ltMEededhh7otBVVIDDsEEttauwdY/hQoSsOv13lxrFzQ==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.11.0", - "@typescript-eslint/types": "8.11.0", - "@typescript-eslint/typescript-estree": "8.11.0" + "@typescript-eslint/scope-manager": "8.15.0", + "@typescript-eslint/types": "8.15.0", + "@typescript-eslint/typescript-estree": "8.15.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1972,17 +2020,22 @@ }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.11.0.tgz", - "integrity": "sha512-EaewX6lxSjRJnc+99+dqzTeoDZUfyrA52d2/HRrkI830kgovWsmIiTfmr0NZorzqic7ga+1bS60lRBUgR3n/Bw==", + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.15.0.tgz", + "integrity": "sha512-h8vYOulWec9LhpwfAdZf2bjr8xIp0KNKnpgqSz0qqYYKAW/QZKw3ktRndbiAtUz4acH4QLQavwZBYCc0wulA/Q==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.11.0", - "eslint-visitor-keys": "^3.4.3" + "@typescript-eslint/types": "8.15.0", + "eslint-visitor-keys": "^4.2.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1992,23 +2045,36 @@ "url": "https://opencollective.com/typescript-eslint" } }, + "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", + "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, "node_modules/@vitest/coverage-v8": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-2.1.3.tgz", - "integrity": "sha512-2OJ3c7UPoFSmBZwqD2VEkUw6A/tzPF0LmW0ZZhhB8PFxuc+9IBG/FaSM+RLEenc7ljzFvGN+G0nGQoZnh7sy2A==", + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-2.1.5.tgz", + "integrity": "sha512-/RoopB7XGW7UEkUndRXF87A9CwkoZAJW01pj8/3pgmDVsjMH2IKy6H1A38po9tmUlwhSyYs0az82rbKd9Yaynw==", "dev": true, "license": "MIT", "dependencies": { "@ampproject/remapping": "^2.3.0", "@bcoe/v8-coverage": "^0.2.3", - "debug": "^4.3.6", + "debug": "^4.3.7", "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.11", - "magicast": "^0.3.4", - "std-env": "^3.7.0", + "magic-string": "^0.30.12", + "magicast": "^0.3.5", + "std-env": "^3.8.0", "test-exclude": "^7.0.1", "tinyrainbow": "^1.2.0" }, @@ -2016,8 +2082,8 @@ "url": "https://opencollective.com/vitest" }, "peerDependencies": { - "@vitest/browser": "2.1.3", - "vitest": "2.1.3" + "@vitest/browser": "2.1.5", + "vitest": "2.1.5" }, "peerDependenciesMeta": { "@vitest/browser": { @@ -2026,15 +2092,15 @@ } }, "node_modules/@vitest/expect": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-2.1.3.tgz", - "integrity": "sha512-SNBoPubeCJhZ48agjXruCI57DvxcsivVDdWz+SSsmjTT4QN/DfHk3zB/xKsJqMs26bLZ/pNRLnCf0j679i0uWQ==", + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-2.1.5.tgz", + "integrity": "sha512-nZSBTW1XIdpZvEJyoP/Sy8fUg0b8od7ZpGDkTUcfJ7wz/VoZAFzFfLyxVxGFhUjJzhYqSbIpfMtl/+k/dpWa3Q==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/spy": "2.1.3", - "@vitest/utils": "2.1.3", - "chai": "^5.1.1", + "@vitest/spy": "2.1.5", + "@vitest/utils": "2.1.5", + "chai": "^5.1.2", "tinyrainbow": "^1.2.0" }, "funding": { @@ -2042,22 +2108,21 @@ } }, "node_modules/@vitest/mocker": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-2.1.3.tgz", - "integrity": "sha512-eSpdY/eJDuOvuTA3ASzCjdithHa+GIF1L4PqtEELl6Qa3XafdMLBpBlZCIUCX2J+Q6sNmjmxtosAG62fK4BlqQ==", + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-2.1.5.tgz", + "integrity": "sha512-XYW6l3UuBmitWqSUXTNXcVBUCRytDogBsWuNXQijc00dtnU/9OqpXWp4OJroVrad/gLIomAq9aW8yWDBtMthhQ==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/spy": "2.1.3", + "@vitest/spy": "2.1.5", "estree-walker": "^3.0.3", - "magic-string": "^0.30.11" + "magic-string": "^0.30.12" }, "funding": { "url": "https://opencollective.com/vitest" }, "peerDependencies": { - "@vitest/spy": "2.1.3", - "msw": "^2.3.5", + "msw": "^2.4.9", "vite": "^5.0.0" }, "peerDependenciesMeta": { @@ -2070,9 +2135,9 @@ } }, "node_modules/@vitest/pretty-format": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-2.1.3.tgz", - "integrity": "sha512-XH1XdtoLZCpqV59KRbPrIhFCOO0hErxrQCMcvnQete3Vibb9UeIOX02uFPfVn3Z9ZXsq78etlfyhnkmIZSzIwQ==", + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-2.1.5.tgz", + "integrity": "sha512-4ZOwtk2bqG5Y6xRGHcveZVr+6txkH7M2e+nPFd6guSoN638v/1XQ0K06eOpi0ptVU/2tW/pIU4IoPotY/GZ9fw==", "dev": true, "license": "MIT", "dependencies": { @@ -2083,13 +2148,13 @@ } }, "node_modules/@vitest/runner": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-2.1.3.tgz", - "integrity": "sha512-JGzpWqmFJ4fq5ZKHtVO3Xuy1iF2rHGV4d/pdzgkYHm1+gOzNZtqjvyiaDGJytRyMU54qkxpNzCx+PErzJ1/JqQ==", + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-2.1.5.tgz", + "integrity": "sha512-pKHKy3uaUdh7X6p1pxOkgkVAFW7r2I818vHDthYLvUyjRfkKOU6P45PztOch4DZarWQne+VOaIMwA/erSSpB9g==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/utils": "2.1.3", + "@vitest/utils": "2.1.5", "pathe": "^1.1.2" }, "funding": { @@ -2097,14 +2162,14 @@ } }, "node_modules/@vitest/snapshot": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-2.1.3.tgz", - "integrity": "sha512-qWC2mWc7VAXmjAkEKxrScWHWFyCQx/cmiZtuGqMi+WwqQJ2iURsVY4ZfAK6dVo6K2smKRU6l3BPwqEBvhnpQGg==", + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-2.1.5.tgz", + "integrity": "sha512-zmYw47mhfdfnYbuhkQvkkzYroXUumrwWDGlMjpdUr4jBd3HZiV2w7CQHj+z7AAS4VOtWxI4Zt4bWt4/sKcoIjg==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "2.1.3", - "magic-string": "^0.30.11", + "@vitest/pretty-format": "2.1.5", + "magic-string": "^0.30.12", "pathe": "^1.1.2" }, "funding": { @@ -2112,27 +2177,27 @@ } }, "node_modules/@vitest/spy": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-2.1.3.tgz", - "integrity": "sha512-Nb2UzbcUswzeSP7JksMDaqsI43Sj5+Kry6ry6jQJT4b5gAK+NS9NED6mDb8FlMRCX8m5guaHCDZmqYMMWRy5nQ==", + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-2.1.5.tgz", + "integrity": "sha512-aWZF3P0r3w6DiYTVskOYuhBc7EMc3jvn1TkBg8ttylFFRqNN2XGD7V5a4aQdk6QiUzZQ4klNBSpCLJgWNdIiNw==", "dev": true, "license": "MIT", "dependencies": { - "tinyspy": "^3.0.0" + "tinyspy": "^3.0.2" }, "funding": { "url": "https://opencollective.com/vitest" } }, "node_modules/@vitest/utils": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-2.1.3.tgz", - "integrity": "sha512-xpiVfDSg1RrYT0tX6czgerkpcKFmFOF/gCr30+Mve5V2kewCy4Prn1/NDMSRwaSmT7PRaOF83wu+bEtsY1wrvA==", + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-2.1.5.tgz", + "integrity": "sha512-yfj6Yrp0Vesw2cwJbP+cl04OC+IHFsuQsrsJBL9pyGeQXE56v1UAOQco+SR55Vf1nQzfV0QJg1Qum7AaWUwwYg==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "2.1.3", - "loupe": "^3.1.1", + "@vitest/pretty-format": "2.1.5", + "loupe": "^3.1.2", "tinyrainbow": "^1.2.0" }, "funding": { @@ -2159,9 +2224,9 @@ } }, "node_modules/acorn": { - "version": "8.12.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", - "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", + "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", "dev": true, "license": "MIT", "bin": { @@ -2316,9 +2381,9 @@ } }, "node_modules/browserslist": { - "version": "4.23.0", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz", - "integrity": "sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==", + "version": "4.24.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.3.tgz", + "integrity": "sha512-1CPmv8iobE2fyRMV97dAcMVegvvWKxmq94hkLiAkUGwKVTyDLw33K+ZxiFrREKmmps4rIw6grcCFCnTMSZ/YiA==", "dev": true, "funding": [ { @@ -2334,11 +2399,12 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "dependencies": { - "caniuse-lite": "^1.0.30001587", - "electron-to-chromium": "^1.4.668", - "node-releases": "^2.0.14", - "update-browserslist-db": "^1.0.13" + "caniuse-lite": "^1.0.30001688", + "electron-to-chromium": "^1.5.73", + "node-releases": "^2.0.19", + "update-browserslist-db": "^1.1.1" }, "bin": { "browserslist": "cli.js" @@ -2459,9 +2525,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001591", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001591.tgz", - "integrity": "sha512-PCzRMei/vXjJyL5mJtzNiUCKP59dm8Apqc3PH8gJkMnMXZGox93RbE76jHsmLwmIo6/3nsYIpJtx0O7u5PqFuQ==", + "version": "1.0.30001689", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001689.tgz", + "integrity": "sha512-CmeR2VBycfa+5/jOfnp/NpWPGd06nf1XYiefUvhXFfZE4GkRc9jv+eGPS4nT558WS/8lYCzV8SlANCIPvbWP1g==", "dev": true, "funding": [ { @@ -2476,12 +2542,13 @@ "type": "github", "url": "https://github.com/sponsors/ai" } - ] + ], + "license": "CC-BY-4.0" }, "node_modules/chai": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/chai/-/chai-5.1.1.tgz", - "integrity": "sha512-pT1ZgP8rPNqUgieVaEY+ryQr6Q4HXNg8Ei9UnLUrjN4IA7dvQC5JB+/kxVcPNDHyBcc/26CXPkbNzq3qwrOEKA==", + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/chai/-/chai-5.1.2.tgz", + "integrity": "sha512-aGtmf24DW6MLHHG5gCx4zaI3uBq3KRtxeVs0DjFH6Z0rDNbsvTxFASFvdj79pxjxZ8/5u3PIiN3IwEIQkiiuPw==", "dev": true, "license": "MIT", "dependencies": { @@ -2692,12 +2759,13 @@ } }, "node_modules/core-js-compat": { - "version": "3.37.1", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.37.1.tgz", - "integrity": "sha512-9TNiImhKvQqSUkOvk/mMRZzOANTiEVC7WaBNhHcKM7x+/5E1l5NvsysR19zuDQScE8k+kfQXWRN3AtS/eOSHpg==", + "version": "3.39.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.39.0.tgz", + "integrity": "sha512-VgEUx3VwlExr5no0tXlBt+silBvhTryPwCXRI2Id1PN8WTKu7MreethvddqOubrYxkFdv/RnYrqlv1sFNAUelw==", "dev": true, + "license": "MIT", "dependencies": { - "browserslist": "^4.23.0" + "browserslist": "^4.24.2" }, "funding": { "type": "opencollective", @@ -2705,10 +2773,11 @@ } }, "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "dev": true, + "license": "MIT", "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -2877,10 +2946,11 @@ "dev": true }, "node_modules/electron-to-chromium": { - "version": "1.4.687", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.687.tgz", - "integrity": "sha512-Ic85cOuXSP6h7KM0AIJ2hpJ98Bo4hyTUjc4yjMbkvD+8yTxEhfK9+8exT2KKYsSjnCn2tGsKVSZwE7ZgTORQCw==", - "dev": true + "version": "1.5.74", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.74.tgz", + "integrity": "sha512-ck3//9RC+6oss/1Bh9tiAVFy5vfSKbRHAFh7Z3/eTRkEqJeWgymloShB17Vg3Z4nmDNp35vAd1BZ6CMW4Wt6Iw==", + "dev": true, + "license": "ISC" }, "node_modules/emoji-regex": { "version": "8.0.0", @@ -2950,6 +3020,13 @@ "node": ">= 0.4" } }, + "node_modules/es-module-lexer": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.5.4.tgz", + "integrity": "sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==", + "dev": true, + "license": "MIT" + }, "node_modules/esbuild": { "version": "0.21.5", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", @@ -2990,10 +3067,11 @@ } }, "node_modules/escalade": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", - "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -3017,22 +3095,22 @@ } }, "node_modules/eslint": { - "version": "9.13.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.13.0.tgz", - "integrity": "sha512-EYZK6SX6zjFHST/HRytOdA/zE72Cq/bfw45LSyuwrdvcclb/gqV8RRQxywOBEWO2+WDpva6UZa4CcDeJKzUCFA==", + "version": "9.14.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.14.0.tgz", + "integrity": "sha512-c2FHsVBr87lnUtjP4Yhvk4yEhKrQavGafRA/Se1ouse8PfbfC/Qh9Mxa00yWsZRlqeUB9raXip0aiiUZkgnr9g==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.11.0", + "@eslint-community/regexpp": "^4.12.1", "@eslint/config-array": "^0.18.0", "@eslint/core": "^0.7.0", "@eslint/eslintrc": "^3.1.0", - "@eslint/js": "9.13.0", + "@eslint/js": "9.14.0", "@eslint/plugin-kit": "^0.2.0", - "@humanfs/node": "^0.16.5", + "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", - "@humanwhocodes/retry": "^0.3.1", + "@humanwhocodes/retry": "^0.4.0", "@types/estree": "^1.0.6", "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", @@ -3040,9 +3118,9 @@ "cross-spawn": "^7.0.2", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^8.1.0", - "eslint-visitor-keys": "^4.1.0", - "espree": "^10.2.0", + "eslint-scope": "^8.2.0", + "eslint-visitor-keys": "^4.2.0", + "espree": "^10.3.0", "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", @@ -3121,19 +3199,19 @@ } }, "node_modules/eslint-plugin-unicorn": { - "version": "55.0.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-unicorn/-/eslint-plugin-unicorn-55.0.0.tgz", - "integrity": "sha512-n3AKiVpY2/uDcGrS3+QsYDkjPfaOrNrsfQxU9nt5nitd9KuvVXrfAvgCO9DYPSfap+Gqjw9EOrXIsBp5tlHZjA==", + "version": "56.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-unicorn/-/eslint-plugin-unicorn-56.0.1.tgz", + "integrity": "sha512-FwVV0Uwf8XPfVnKSGpMg7NtlZh0G0gBarCaFcMUOoqPxXryxdYxTRRv4kH6B9TFCVIrjRXG+emcxIk2ayZilog==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-validator-identifier": "^7.24.5", + "@babel/helper-validator-identifier": "^7.24.7", "@eslint-community/eslint-utils": "^4.4.0", "ci-info": "^4.0.0", "clean-regexp": "^1.0.0", - "core-js-compat": "^3.37.0", - "esquery": "^1.5.0", - "globals": "^15.7.0", + "core-js-compat": "^3.38.1", + "esquery": "^1.6.0", + "globals": "^15.9.0", "indent-string": "^4.0.0", "is-builtin-module": "^3.2.1", "jsesc": "^3.0.2", @@ -3141,7 +3219,7 @@ "read-pkg-up": "^7.0.1", "regexp-tree": "^0.1.27", "regjsparser": "^0.10.0", - "semver": "^7.6.1", + "semver": "^7.6.3", "strip-indent": "^3.0.0" }, "engines": { @@ -3155,9 +3233,9 @@ } }, "node_modules/eslint-scope": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.1.0.tgz", - "integrity": "sha512-14dSvlhaVhKKsa9Fx1l8A17s7ah7Ef7wCakJ10LYk6+GYmP9yDti2oq2SEwcyndt6knfcZyhyxwY3i9yL78EQw==", + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.2.0.tgz", + "integrity": "sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A==", "dev": true, "license": "BSD-2-Clause", "dependencies": { @@ -3183,6 +3261,16 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/eslint/node_modules/@eslint/js": { + "version": "9.14.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.14.0.tgz", + "integrity": "sha512-pFoEtFWCPyDOl+C6Ift+wC7Ro89otjigCf5vcuWqWgqNSQbRrpjSvdeE6ofLz4dHmyxD5f7gIdGT4+p36L6Twg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, "node_modules/eslint/node_modules/eslint-visitor-keys": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", @@ -3197,15 +3285,15 @@ } }, "node_modules/espree": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-10.2.0.tgz", - "integrity": "sha512-upbkBJbckcCNBDBDXEbuhjbP68n+scUd3k/U2EkyM9nw+I/jPiL4cLF/Al06CF96wRltFda16sxDFrxsI1v0/g==", + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.3.0.tgz", + "integrity": "sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==", "dev": true, "license": "BSD-2-Clause", "dependencies": { - "acorn": "^8.12.0", + "acorn": "^8.14.0", "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^4.1.0" + "eslint-visitor-keys": "^4.2.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3215,9 +3303,9 @@ } }, "node_modules/espree/node_modules/eslint-visitor-keys": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.1.0.tgz", - "integrity": "sha512-Q7lok0mqMUSf5a/AdAZkA5a/gHcO6snwQClVNNvFKCAVlxXucdU8pKydU5ZVZjBx5xr37vGbFFWtLQYreLzrZg==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", + "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", "dev": true, "license": "Apache-2.0", "engines": { @@ -3228,10 +3316,11 @@ } }, "node_modules/esquery": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", - "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "estraverse": "^5.1.0" }, @@ -3294,9 +3383,9 @@ } }, "node_modules/exiftool-vendored": { - "version": "28.6.0", - "resolved": "https://registry.npmjs.org/exiftool-vendored/-/exiftool-vendored-28.6.0.tgz", - "integrity": "sha512-Cx8/8ov1tKEacHhsi7FNYdisIhKq/SeQfprYSpYzwBuJwkPmCV8w7tTIvUJRQX9rvopXhBA4eBf1FPXqTZW5vA==", + "version": "28.8.0", + "resolved": "https://registry.npmjs.org/exiftool-vendored/-/exiftool-vendored-28.8.0.tgz", + "integrity": "sha512-R7tirJLr9fWuH9JS/KFFLB+O7jNGKuPXGxREc6YybYangEudGb+X8ERsYXk9AifMiAWh/2agNfbgkbcQcF+MxA==", "dev": true, "license": "MIT", "dependencies": { @@ -3307,14 +3396,14 @@ "luxon": "^3.5.0" }, "optionalDependencies": { - "exiftool-vendored.exe": "12.97.0", - "exiftool-vendored.pl": "12.97.0" + "exiftool-vendored.exe": "13.0.0", + "exiftool-vendored.pl": "13.0.1" } }, "node_modules/exiftool-vendored.exe": { - "version": "12.97.0", - "resolved": "https://registry.npmjs.org/exiftool-vendored.exe/-/exiftool-vendored.exe-12.97.0.tgz", - "integrity": "sha512-+HxyFigEJOtwRjP7PhEslhZKuVW2V0hvmHPHtbVtNKGfAUGcfc95xNTjASQfKJvc+9ZuvzdEBPkEQmyA/ZYdIw==", + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/exiftool-vendored.exe/-/exiftool-vendored.exe-13.0.0.tgz", + "integrity": "sha512-4zAMuFGgxZkOoyQIzZMHv1HlvgyJK3AkNqjAgm8A8V0UmOZO7yv3pH49cDV1OduzFJqgs6yQ6eG4OGydhKtxlg==", "dev": true, "license": "MIT", "optional": true, @@ -3323,9 +3412,9 @@ ] }, "node_modules/exiftool-vendored.pl": { - "version": "12.97.0", - "resolved": "https://registry.npmjs.org/exiftool-vendored.pl/-/exiftool-vendored.pl-12.97.0.tgz", - "integrity": "sha512-mXe9JEH3csfyPWcC7+H6IpfaokDMMr4S45n7MtiobGPdeeh+kFnf1SQ9cxg4sF403P6IKVeYYPbzgKMlpro9eQ==", + "version": "13.0.1", + "resolved": "https://registry.npmjs.org/exiftool-vendored.pl/-/exiftool-vendored.pl-13.0.1.tgz", + "integrity": "sha512-+BRRzjselpWudKR0ltAW5SUt9T82D+gzQN8DdOQUgnSVWWp7oLCeTGBRptbQz+436Ihn/mPzmo/xnf0cv/Qw1A==", "dev": true, "license": "MIT", "optional": true, @@ -3333,6 +3422,16 @@ "!win32" ] }, + "node_modules/expect-type": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.1.0.tgz", + "integrity": "sha512-bFi65yM+xZgk+u/KRIpekdSYkTB5W1pEf0Lt8Q8Msh7b+eQ7LXVtIB1Bkm4fvclDEL1b2CZkMhv2mOeF8tMdkA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -3659,9 +3758,9 @@ } }, "node_modules/globals": { - "version": "15.11.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-15.11.0.tgz", - "integrity": "sha512-yeyNSjdbyVaWurlwCpcA6XNBrHTMIeDdj0/hnvX/OLJ9ekOXYbLsLinH/MucQyGvNnXhidTdNhTtJaffL2sMfw==", + "version": "15.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-15.12.0.tgz", + "integrity": "sha512-1+gLErljJFhbOVyaetcwJiJ4+eLe45S2E7P5UiZ9xGfeq3ATQf5DOv9G7MH3gGbKQLkzmNh2DxfZwLdw+j6oTQ==", "dev": true, "license": "MIT", "engines": { @@ -4414,22 +4513,24 @@ } }, "node_modules/magic-string": { - "version": "0.30.11", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.11.tgz", - "integrity": "sha512-+Wri9p0QHMy+545hKww7YAu5NyzF8iomPL/RQazugQ9+Ez4Ic3mERMd8ZTX5rfK944j+560ZJi8iAwgak1Ac7A==", + "version": "0.30.12", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.12.tgz", + "integrity": "sha512-Ea8I3sQMVXr8JhN4z+H/d8zwo+tYDgHE9+5G4Wnrwhs0gaK9fXTKx0Tw5Xwsd/bCPTTZNRAdpyzvoeORe9LYpw==", "dev": true, + "license": "MIT", "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0" } }, "node_modules/magicast": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/magicast/-/magicast-0.3.4.tgz", - "integrity": "sha512-TyDF/Pn36bBji9rWKHlZe+PZb6Mx5V8IHCSxk7X4aljM4e/vyDvZZYwHewdVaqiA0nb3ghfHU/6AUpDxWoER2Q==", + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/magicast/-/magicast-0.3.5.tgz", + "integrity": "sha512-L0WhttDl+2BOsybvEOLK7fW3UA0OQ0IQ2d6Zl2x/a6vVRs3bAY0ECOSHHeL5jD+SbOpOCUEi0y1DgHEn9Qn1AQ==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/parser": "^7.24.4", - "@babel/types": "^7.24.0", + "@babel/parser": "^7.25.4", + "@babel/types": "^7.25.4", "source-map-js": "^1.2.0" } }, @@ -4610,9 +4711,9 @@ "license": "MIT" }, "node_modules/nanoid": { - "version": "3.3.7", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", - "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.0.8.tgz", + "integrity": "sha512-TcJPw+9RV9dibz1hHUzlLVy8N4X9TnwirAjrU08Juo6BNKggzVfP2ZJ/3ZUSq15Xl5i85i+Z89XBO90pB2PghQ==", "dev": true, "funding": [ { @@ -4622,10 +4723,10 @@ ], "license": "MIT", "bin": { - "nanoid": "bin/nanoid.cjs" + "nanoid": "bin/nanoid.js" }, "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + "node": "^18 || >=20" } }, "node_modules/natural-compare": { @@ -4670,10 +4771,11 @@ } }, "node_modules/node-releases": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", - "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", - "dev": true + "version": "2.0.19", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", + "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==", + "dev": true, + "license": "MIT" }, "node_modules/nopt": { "version": "5.0.0", @@ -4769,9 +4871,9 @@ "dev": true }, "node_modules/oidc-provider": { - "version": "8.5.2", - "resolved": "https://registry.npmjs.org/oidc-provider/-/oidc-provider-8.5.2.tgz", - "integrity": "sha512-WhMIQ61KMgABvrYZJDuefOWFpX34DWgg+U4juKARplGhNUSNfHgJh6i6Mp+PTO08ZDk/oj1Ci7ScU6CAI/wgcg==", + "version": "8.5.3", + "resolved": "https://registry.npmjs.org/oidc-provider/-/oidc-provider-8.5.3.tgz", + "integrity": "sha512-eSHoHiPxdJ7Ar+hgaogeBVdGgjtIPp6GXFuzuTYdQ4rhhWC6jFapa0GQ49zk0M6I6OnqTYU3dU8j/QDaLu5BaA==", "dev": true, "license": "MIT", "dependencies": { @@ -4780,10 +4882,10 @@ "debug": "^4.3.7", "eta": "^3.5.0", "got": "^13.0.0", - "jose": "^5.9.4", + "jose": "^5.9.6", "jsesc": "^3.0.2", "koa": "^2.15.3", - "nanoid": "^5.0.7", + "nanoid": "^5.0.8", "object-hash": "^3.0.0", "oidc-token-hash": "^5.0.3", "quick-lru": "^7.0.0", @@ -4793,25 +4895,6 @@ "url": "https://github.com/sponsors/panva" } }, - "node_modules/oidc-provider/node_modules/nanoid": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.0.8.tgz", - "integrity": "sha512-TcJPw+9RV9dibz1hHUzlLVy8N4X9TnwirAjrU08Juo6BNKggzVfP2ZJ/3ZUSq15Xl5i85i+Z89XBO90pB2PghQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "bin": { - "nanoid": "bin/nanoid.js" - }, - "engines": { - "node": "^18 || >=20" - } - }, "node_modules/oidc-token-hash": { "version": "5.0.3", "resolved": "https://registry.npmjs.org/oidc-token-hash/-/oidc-token-hash-5.0.3.tgz", @@ -5145,9 +5228,9 @@ } }, "node_modules/picocolors": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.0.tgz", - "integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", "dev": true, "license": "ISC" }, @@ -5165,13 +5248,13 @@ } }, "node_modules/playwright": { - "version": "1.48.1", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.48.1.tgz", - "integrity": "sha512-j8CiHW/V6HxmbntOfyB4+T/uk08tBy6ph0MpBXwuoofkSnLmlfdYNNkFTYD6ofzzlSqLA1fwH4vwvVFvJgLN0w==", + "version": "1.48.2", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.48.2.tgz", + "integrity": "sha512-NjYvYgp4BPmiwfe31j4gHLa3J7bD2WiBz8Lk2RoSsmX38SVIARZ18VYjxLjAcDsAhA+F4iSEXTSGgjua0rrlgQ==", "dev": true, "license": "Apache-2.0", "dependencies": { - "playwright-core": "1.48.1" + "playwright-core": "1.48.2" }, "bin": { "playwright": "cli.js" @@ -5184,9 +5267,9 @@ } }, "node_modules/playwright-core": { - "version": "1.48.1", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.48.1.tgz", - "integrity": "sha512-Yw/t4VAFX/bBr1OzwCuOMZkY1Cnb4z/doAFSwf4huqAGWmf9eMNjmK7NiOljCdLmxeRYcGPPmcDgU0zOlzP0YA==", + "version": "1.48.2", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.48.2.tgz", + "integrity": "sha512-sjjw+qrLFlriJo64du+EK0kJgZzoQPsabGF4lBvsid+3CNIZIYLgnMj9V6JY5VhM2Peh20DJWIVpVljLLnlawA==", "dev": true, "license": "Apache-2.0", "bin": { @@ -5215,9 +5298,9 @@ } }, "node_modules/postcss": { - "version": "8.4.47", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.47.tgz", - "integrity": "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==", + "version": "8.4.49", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.49.tgz", + "integrity": "sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==", "dev": true, "funding": [ { @@ -5236,13 +5319,32 @@ "license": "MIT", "dependencies": { "nanoid": "^3.3.7", - "picocolors": "^1.1.0", + "picocolors": "^1.1.1", "source-map-js": "^1.2.1" }, "engines": { "node": "^10 || ^12 || >=14" } }, + "node_modules/postcss/node_modules/nanoid": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, "node_modules/postgres-array": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz", @@ -5635,9 +5737,9 @@ } }, "node_modules/rollup": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.24.0.tgz", - "integrity": "sha512-DOmrlGSXNk1DM0ljiQA+i+o0rSLhtii1je5wgk60j49d1jHT5YYttBv1iWOnYSTG+fZZESUOSNiAl89SIet+Cg==", + "version": "4.27.3", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.27.3.tgz", + "integrity": "sha512-SLsCOnlmGt9VoZ9Ek8yBK8tAdmPHeppkw+Xa7yDlCEhDTvwYei03JlWo1fdc7YTfLZ4tD8riJCUyAgTbszk1fQ==", "dev": true, "license": "MIT", "dependencies": { @@ -5651,22 +5753,24 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.24.0", - "@rollup/rollup-android-arm64": "4.24.0", - "@rollup/rollup-darwin-arm64": "4.24.0", - "@rollup/rollup-darwin-x64": "4.24.0", - "@rollup/rollup-linux-arm-gnueabihf": "4.24.0", - "@rollup/rollup-linux-arm-musleabihf": "4.24.0", - "@rollup/rollup-linux-arm64-gnu": "4.24.0", - "@rollup/rollup-linux-arm64-musl": "4.24.0", - "@rollup/rollup-linux-powerpc64le-gnu": "4.24.0", - "@rollup/rollup-linux-riscv64-gnu": "4.24.0", - "@rollup/rollup-linux-s390x-gnu": "4.24.0", - "@rollup/rollup-linux-x64-gnu": "4.24.0", - "@rollup/rollup-linux-x64-musl": "4.24.0", - "@rollup/rollup-win32-arm64-msvc": "4.24.0", - "@rollup/rollup-win32-ia32-msvc": "4.24.0", - "@rollup/rollup-win32-x64-msvc": "4.24.0", + "@rollup/rollup-android-arm-eabi": "4.27.3", + "@rollup/rollup-android-arm64": "4.27.3", + "@rollup/rollup-darwin-arm64": "4.27.3", + "@rollup/rollup-darwin-x64": "4.27.3", + "@rollup/rollup-freebsd-arm64": "4.27.3", + "@rollup/rollup-freebsd-x64": "4.27.3", + "@rollup/rollup-linux-arm-gnueabihf": "4.27.3", + "@rollup/rollup-linux-arm-musleabihf": "4.27.3", + "@rollup/rollup-linux-arm64-gnu": "4.27.3", + "@rollup/rollup-linux-arm64-musl": "4.27.3", + "@rollup/rollup-linux-powerpc64le-gnu": "4.27.3", + "@rollup/rollup-linux-riscv64-gnu": "4.27.3", + "@rollup/rollup-linux-s390x-gnu": "4.27.3", + "@rollup/rollup-linux-x64-gnu": "4.27.3", + "@rollup/rollup-linux-x64-musl": "4.27.3", + "@rollup/rollup-win32-arm64-msvc": "4.27.3", + "@rollup/rollup-win32-ia32-msvc": "4.27.3", + "@rollup/rollup-win32-x64-msvc": "4.27.3", "fsevents": "~2.3.2" } }, @@ -5722,10 +5826,11 @@ "license": "MIT" }, "node_modules/semver": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", - "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", "dev": true, + "license": "ISC", "bin": { "semver": "bin/semver.js" }, @@ -5915,10 +6020,11 @@ } }, "node_modules/std-env": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.7.0.tgz", - "integrity": "sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg==", - "dev": true + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.8.0.tgz", + "integrity": "sha512-Bc3YwwCB+OzldMxOXJIIvC6cPRWr/LxOp48CdQTOkPyk/t4JWWJbrilwBd7RJzKV8QW7tJkcgAmeuLLJugl5/w==", + "dev": true, + "license": "MIT" }, "node_modules/string_decoder": { "version": "1.3.0", @@ -6170,7 +6276,8 @@ "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/tinybench": { "version": "2.9.0", @@ -6180,17 +6287,18 @@ "license": "MIT" }, "node_modules/tinyexec": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.0.tgz", - "integrity": "sha512-tVGE0mVJPGb0chKhqmsoosjsS+qUnJVGJpZgsHYQcGoPlG3B51R3PouqTgEGH2Dc9jjFyOqOpix6ZHNMXp1FZg==", + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.1.tgz", + "integrity": "sha512-WiCJLEECkO18gwqIp6+hJg0//p23HXp4S+gGtAKu3mI2F2/sXC4FvHvXvB0zJVVaTPhx1/tOwdbRsa1sOBIKqQ==", "dev": true, "license": "MIT" }, "node_modules/tinypool": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.0.0.tgz", - "integrity": "sha512-KIKExllK7jp3uvrNtvRBYBWBOAXSX8ZvoaD8T+7KB/QHIuoJW3Pmr60zucywjAlMb5TeXUkcs/MWeWLu0qvuAQ==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.0.1.tgz", + "integrity": "sha512-URZYihUbRPcGv95En+sz6MfghfIc2OJ1sv/RmhWZLouPY0/8Vo80viwPvg3dlaS9fuq7fQMEfgRRK7BBZThBEA==", "dev": true, + "license": "MIT", "engines": { "node": "^18.0.0 || >=20.0.0" } @@ -6214,15 +6322,6 @@ "node": ">=14.0.0" } }, - "node_modules/to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", - "dev": true, - "engines": { - "node": ">=4" - } - }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -6318,9 +6417,9 @@ } }, "node_modules/undici-types": { - "version": "6.19.8", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", - "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", + "version": "6.20.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", + "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", "dev": true, "license": "MIT" }, @@ -6334,9 +6433,9 @@ } }, "node_modules/update-browserslist-db": { - "version": "1.0.13", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", - "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz", + "integrity": "sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==", "dev": true, "funding": [ { @@ -6352,9 +6451,10 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "dependencies": { - "escalade": "^3.1.1", - "picocolors": "^1.0.0" + "escalade": "^3.2.0", + "picocolors": "^1.1.0" }, "bin": { "update-browserslist-db": "cli.js" @@ -6412,9 +6512,9 @@ } }, "node_modules/vite": { - "version": "5.4.9", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.9.tgz", - "integrity": "sha512-20OVpJHh0PAM0oSOELa5GaZNWeDjcAvQjGXy2Uyr+Tp+/D2/Hdz6NLgpJLsarPTA2QJ6v8mX2P1ZfbsSKvdMkg==", + "version": "5.4.11", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.11.tgz", + "integrity": "sha512-c7jFQRklXua0mTzneGW9QVyxFjUgwcihC4bXEtujIo2ouWCe1Ajt/amn2PCxYnhYfd5k09JX3SB7OYWFKYqj8Q==", "dev": true, "license": "MIT", "dependencies": { @@ -6472,14 +6572,15 @@ } }, "node_modules/vite-node": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-2.1.3.tgz", - "integrity": "sha512-I1JadzO+xYX887S39Do+paRePCKoiDrWRRjp9kkG5he0t7RXNvPAJPCQSJqbGN4uCrFFeS3Kj3sLqY8NMYBEdA==", + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-2.1.5.tgz", + "integrity": "sha512-rd0QIgx74q4S1Rd56XIiL2cYEdyWn13cunYBIuqh9mpmQr7gGS0IxXoP8R6OaZtNQQLyXSWbd4rXKYUbhFpK5w==", "dev": true, "license": "MIT", "dependencies": { "cac": "^6.7.14", - "debug": "^4.3.6", + "debug": "^4.3.7", + "es-module-lexer": "^1.5.4", "pathe": "^1.1.2", "vite": "^5.0.0" }, @@ -6509,30 +6610,31 @@ } }, "node_modules/vitest": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-2.1.3.tgz", - "integrity": "sha512-Zrxbg/WiIvUP2uEzelDNTXmEMJXuzJ1kCpbDvaKByFA9MNeO95V+7r/3ti0qzJzrxdyuUw5VduN7k+D3VmVOSA==", + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-2.1.5.tgz", + "integrity": "sha512-P4ljsdpuzRTPI/kbND2sDZ4VmieerR2c9szEZpjc+98Z9ebvnXmM5+0tHEKqYZumXqlvnmfWsjeFOjXVriDG7A==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/expect": "2.1.3", - "@vitest/mocker": "2.1.3", - "@vitest/pretty-format": "^2.1.3", - "@vitest/runner": "2.1.3", - "@vitest/snapshot": "2.1.3", - "@vitest/spy": "2.1.3", - "@vitest/utils": "2.1.3", - "chai": "^5.1.1", - "debug": "^4.3.6", - "magic-string": "^0.30.11", + "@vitest/expect": "2.1.5", + "@vitest/mocker": "2.1.5", + "@vitest/pretty-format": "^2.1.5", + "@vitest/runner": "2.1.5", + "@vitest/snapshot": "2.1.5", + "@vitest/spy": "2.1.5", + "@vitest/utils": "2.1.5", + "chai": "^5.1.2", + "debug": "^4.3.7", + "expect-type": "^1.1.0", + "magic-string": "^0.30.12", "pathe": "^1.1.2", - "std-env": "^3.7.0", + "std-env": "^3.8.0", "tinybench": "^2.9.0", - "tinyexec": "^0.3.0", - "tinypool": "^1.0.0", + "tinyexec": "^0.3.1", + "tinypool": "^1.0.1", "tinyrainbow": "^1.2.0", "vite": "^5.0.0", - "vite-node": "2.1.3", + "vite-node": "2.1.5", "why-is-node-running": "^2.3.0" }, "bin": { @@ -6547,8 +6649,8 @@ "peerDependencies": { "@edge-runtime/vm": "*", "@types/node": "^18.0.0 || >=20.0.0", - "@vitest/browser": "2.1.3", - "@vitest/ui": "2.1.3", + "@vitest/browser": "2.1.5", + "@vitest/ui": "2.1.5", "happy-dom": "*", "jsdom": "*" }, diff --git a/e2e/package.json b/e2e/package.json index 86488e8a70632..d500d63bf0dc5 100644 --- a/e2e/package.json +++ b/e2e/package.json @@ -1,6 +1,6 @@ { "name": "immich-e2e", - "version": "1.119.1", + "version": "1.123.0", "description": "", "main": "index.js", "type": "module", @@ -25,18 +25,18 @@ "@immich/sdk": "file:../open-api/typescript-sdk", "@playwright/test": "^1.44.1", "@types/luxon": "^3.4.2", - "@types/node": "^22.8.1", + "@types/node": "^22.10.2", "@types/oidc-provider": "^8.5.1", "@types/pg": "^8.11.0", "@types/pngjs": "^6.0.4", "@types/supertest": "^6.0.2", - "@typescript-eslint/eslint-plugin": "^8.0.0", - "@typescript-eslint/parser": "^8.0.0", + "@typescript-eslint/eslint-plugin": "^8.15.0", + "@typescript-eslint/parser": "^8.15.0", "@vitest/coverage-v8": "^2.0.5", - "eslint": "^9.0.0", + "eslint": "^9.14.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-prettier": "^5.1.3", - "eslint-plugin-unicorn": "^55.0.0", + "eslint-plugin-unicorn": "^56.0.1", "exiftool-vendored": "^28.3.1", "globals": "^15.9.0", "jose": "^5.6.3", @@ -53,6 +53,6 @@ "vitest": "^2.0.5" }, "volta": { - "node": "22.11.0" + "node": "22.12.0" } } diff --git a/e2e/src/api/specs/album.e2e-spec.ts b/e2e/src/api/specs/album.e2e-spec.ts index 9e925c40210c1..5c101a0793599 100644 --- a/e2e/src/api/specs/album.e2e-spec.ts +++ b/e2e/src/api/specs/album.e2e-spec.ts @@ -141,6 +141,7 @@ describe('/albums', () => { expect(body).toEqual({ ...user1Albums[0], assets: [expect.objectContaining({ isFavorite: false })], + lastModifiedAssetTimestamp: expect.any(String), }); }); @@ -297,6 +298,7 @@ describe('/albums', () => { expect(body).toEqual({ ...user1Albums[0], assets: [expect.objectContaining({ id: user1Albums[0].assets[0].id })], + lastModifiedAssetTimestamp: expect.any(String), }); }); @@ -327,6 +329,7 @@ describe('/albums', () => { expect(body).toEqual({ ...user1Albums[0], assets: [expect.objectContaining({ id: user1Albums[0].assets[0].id })], + lastModifiedAssetTimestamp: expect.any(String), }); }); @@ -340,6 +343,7 @@ describe('/albums', () => { ...user1Albums[0], assets: [], assetCount: 1, + lastModifiedAssetTimestamp: expect.any(String), }); }); }); diff --git a/e2e/src/api/specs/asset.e2e-spec.ts b/e2e/src/api/specs/asset.e2e-spec.ts index cc898e7468717..a0c429a82e224 100644 --- a/e2e/src/api/specs/asset.e2e-spec.ts +++ b/e2e/src/api/specs/asset.e2e-spec.ts @@ -1148,6 +1148,78 @@ describe('/asset', () => { }, }, }, + { + input: 'formats/raw/Canon/PowerShot_G12.CR2', + expected: { + type: AssetTypeEnum.Image, + originalFileName: 'PowerShot_G12.CR2', + fileCreatedAt: '2015-12-27T09:55:40.000Z', + exifInfo: { + make: 'Canon', + model: 'Canon PowerShot G12', + exifImageHeight: 2736, + exifImageWidth: 3648, + exposureTime: '1/1000', + fNumber: 4, + focalLength: 18.098, + iso: 80, + lensModel: null, + fileSizeInByte: 11_113_617, + dateTimeOriginal: '2015-12-27T09:55:40.000Z', + latitude: null, + longitude: null, + orientation: '1', + }, + }, + }, + { + input: 'formats/raw/Fujifilm/X100V_compressed.RAF', + expected: { + type: AssetTypeEnum.Image, + originalFileName: 'X100V_compressed.RAF', + fileCreatedAt: '2024-10-12T21:01:01.000Z', + exifInfo: { + make: 'FUJIFILM', + model: 'X100V', + exifImageHeight: 4160, + exifImageWidth: 6240, + exposureTime: '1/4000', + fNumber: 16, + focalLength: 23, + iso: 160, + lensModel: null, + fileSizeInByte: 13_551_312, + dateTimeOriginal: '2024-10-12T21:01:01.000Z', + latitude: null, + longitude: null, + orientation: '6', + }, + }, + }, + { + input: 'formats/raw/Ricoh/GR3/Ricoh_GR3-450.DNG', + expected: { + type: AssetTypeEnum.Image, + originalFileName: 'Ricoh_GR3-450.DNG', + fileCreatedAt: '2024-06-08T13:48:39.000Z', + exifInfo: { + dateTimeOriginal: '2024-06-08T13:48:39.000Z', + exifImageHeight: 4064, + exifImageWidth: 6112, + exposureTime: '1/400', + fNumber: 5, + fileSizeInByte: 31_175_472, + focalLength: 18.3, + iso: 100, + latitude: 36.613_24, + lensModel: 'GR LENS 18.3mm F2.8', + longitude: -121.897_85, + make: 'RICOH IMAGING COMPANY, LTD.', + model: 'RICOH GR III', + orientation: '1', + }, + }, + }, ]; it(`should upload and generate a thumbnail for different file types`, async () => { diff --git a/e2e/src/api/specs/library.e2e-spec.ts b/e2e/src/api/specs/library.e2e-spec.ts index bf0bd4a9c65d7..23cdf092cfe7b 100644 --- a/e2e/src/api/specs/library.e2e-spec.ts +++ b/e2e/src/api/specs/library.e2e-spec.ts @@ -1,5 +1,5 @@ import { LibraryResponseDto, LoginResponseDto, getAllLibraries, scanLibrary } from '@immich/sdk'; -import { cpSync, existsSync } from 'node:fs'; +import { cpSync, existsSync, rmSync, unlinkSync } from 'node:fs'; import { Socket } from 'socket.io-client'; import { userDto, uuidDto } from 'src/fixtures'; import { errorDto } from 'src/responses'; @@ -299,7 +299,7 @@ describe('/libraries', () => { await utils.waitForQueueFinish(admin.accessToken, 'library'); - const { assets } = await utils.metadataSearch(admin.accessToken, { + const { assets } = await utils.searchAssets(admin.accessToken, { originalPath: `${testAssetDirInternal}/temp/directoryA/assetA.png`, }); expect(assets.count).toBe(1); @@ -320,7 +320,7 @@ describe('/libraries', () => { await utils.waitForQueueFinish(admin.accessToken, 'library'); - const { assets } = await utils.metadataSearch(admin.accessToken, { libraryId: library.id }); + const { assets } = await utils.searchAssets(admin.accessToken, { libraryId: library.id }); expect(assets.count).toBe(1); expect(assets.items[0].originalPath.includes('directoryB')); @@ -340,7 +340,7 @@ describe('/libraries', () => { await utils.waitForQueueFinish(admin.accessToken, 'library'); - const { assets } = await utils.metadataSearch(admin.accessToken, { libraryId: library.id }); + const { assets } = await utils.searchAssets(admin.accessToken, { libraryId: library.id }); expect(assets.count).toBe(2); expect(assets.items.find((asset) => asset.originalPath.includes('directoryA'))).toBeDefined(); @@ -365,7 +365,7 @@ describe('/libraries', () => { await utils.waitForQueueFinish(admin.accessToken, 'library'); - const { assets } = await utils.metadataSearch(admin.accessToken, { libraryId: library.id }); + const { assets } = await utils.searchAssets(admin.accessToken, { libraryId: library.id }); expect(assets.count).toBe(2); expect(assets.items.find((asset) => asset.originalPath.includes('folder, a'))).toBeDefined(); @@ -393,7 +393,7 @@ describe('/libraries', () => { await utils.waitForQueueFinish(admin.accessToken, 'library'); - const { assets } = await utils.metadataSearch(admin.accessToken, { libraryId: library.id }); + const { assets } = await utils.searchAssets(admin.accessToken, { libraryId: library.id }); expect(assets.count).toBe(2); expect(assets.items.find((asset) => asset.originalPath.includes('folder{ a'))).toBeDefined(); @@ -403,68 +403,157 @@ describe('/libraries', () => { utils.removeImageFile(`${testAssetDir}/temp/folder} b/assetB.png`); }); + const annoyingChars = [ + "'", + '"', + '`', + '*', + '{', + '}', + ',', + '(', + ')', + '[', + ']', + '?', + '!', + '@', + '#', + '$', + '%', + '^', + '&', + '=', + '+', + '~', + '|', + '<', + '>', + ';', + ':', + '/', // We never got backslashes to work + ]; + + it.each(annoyingChars)('should scan multiple import paths with %s', async (char) => { + const library = await utils.createLibrary(admin.accessToken, { + ownerId: admin.userId, + importPaths: [`${testAssetDirInternal}/temp/folder${char}1`, `${testAssetDirInternal}/temp/folder${char}2`], + }); + + utils.createImageFile(`${testAssetDir}/temp/folder${char}1/asset1.png`); + utils.createImageFile(`${testAssetDir}/temp/folder${char}2/asset2.png`); + + const { status } = await request(app) + .post(`/libraries/${library.id}/scan`) + .set('Authorization', `Bearer ${admin.accessToken}`) + .send(); + expect(status).toBe(204); + + await utils.waitForQueueFinish(admin.accessToken, 'library'); + + const { assets } = await utils.searchAssets(admin.accessToken, { libraryId: library.id }); + + expect(assets.items).toEqual( + expect.arrayContaining([ + expect.objectContaining({ originalPath: expect.stringContaining(`folder${char}1/asset1.png`) }), + expect.objectContaining({ originalPath: expect.stringContaining(`folder${char}2/asset2.png`) }), + ]), + ); + + utils.removeImageFile(`${testAssetDir}/temp/folder${char}1/asset1.png`); + utils.removeImageFile(`${testAssetDir}/temp/folder${char}2/asset2.png`); + }); + it('should reimport a modified file', async () => { const library = await utils.createLibrary(admin.accessToken, { ownerId: admin.userId, - importPaths: [`${testAssetDirInternal}/temp`], + importPaths: [`${testAssetDirInternal}/temp/reimport`], }); - utils.createImageFile(`${testAssetDir}/temp/directoryA/assetB.jpg`); - await utimes(`${testAssetDir}/temp/directoryA/assetB.jpg`, 447_775_200_000); + utils.createImageFile(`${testAssetDir}/temp/reimport/asset.jpg`); + await utimes(`${testAssetDir}/temp/reimport/asset.jpg`, 447_775_200_000); await scan(admin.accessToken, library.id); await utils.waitForQueueFinish(admin.accessToken, 'library'); + await utils.waitForQueueFinish(admin.accessToken, 'sidecar'); + await utils.waitForQueueFinish(admin.accessToken, 'metadataExtraction'); - cpSync(`${testAssetDir}/albums/nature/tanners_ridge.jpg`, `${testAssetDir}/temp/directoryA/assetB.jpg`); - await utimes(`${testAssetDir}/temp/directoryA/assetB.jpg`, 447_775_200_001); + cpSync(`${testAssetDir}/albums/nature/tanners_ridge.jpg`, `${testAssetDir}/temp/reimport/asset.jpg`); + await utimes(`${testAssetDir}/temp/reimport/asset.jpg`, 447_775_200_001); const { status } = await request(app) .post(`/libraries/${library.id}/scan`) .set('Authorization', `Bearer ${admin.accessToken}`) - .send({ refreshModifiedFiles: true }); + .send(); expect(status).toBe(204); await utils.waitForQueueFinish(admin.accessToken, 'library'); + await utils.waitForQueueFinish(admin.accessToken, 'sidecar'); await utils.waitForQueueFinish(admin.accessToken, 'metadataExtraction'); - utils.removeImageFile(`${testAssetDir}/temp/directoryA/assetB.jpg`); - const { assets } = await utils.metadataSearch(admin.accessToken, { + const { assets } = await utils.searchAssets(admin.accessToken, { libraryId: library.id, - model: 'NIKON D750', }); - expect(assets.count).toBe(1); + + expect(assets.count).toEqual(1); + + const asset = await utils.getAssetInfo(admin.accessToken, assets.items[0].id); + + expect(asset).toEqual( + expect.objectContaining({ + originalFileName: 'asset.jpg', + exifInfo: expect.objectContaining({ + model: 'NIKON D750', + }), + }), + ); + + utils.removeImageFile(`${testAssetDir}/temp/reimport/asset.jpg`); }); it('should not reimport unmodified files', async () => { const library = await utils.createLibrary(admin.accessToken, { ownerId: admin.userId, - importPaths: [`${testAssetDirInternal}/temp`], + importPaths: [`${testAssetDirInternal}/temp/reimport`], }); - utils.createImageFile(`${testAssetDir}/temp/directoryA/assetB.jpg`); - await utimes(`${testAssetDir}/temp/directoryA/assetB.jpg`, 447_775_200_000); + utils.createImageFile(`${testAssetDir}/temp/reimport/asset.jpg`); + await utimes(`${testAssetDir}/temp/reimport/asset.jpg`, 447_775_200_000); await scan(admin.accessToken, library.id); await utils.waitForQueueFinish(admin.accessToken, 'library'); - cpSync(`${testAssetDir}/albums/nature/tanners_ridge.jpg`, `${testAssetDir}/temp/directoryA/assetB.jpg`); - await utimes(`${testAssetDir}/temp/directoryA/assetB.jpg`, 447_775_200_000); + cpSync(`${testAssetDir}/albums/nature/tanners_ridge.jpg`, `${testAssetDir}/temp/reimport/asset.jpg`); + await utimes(`${testAssetDir}/temp/reimport/asset.jpg`, 447_775_200_000); const { status } = await request(app) .post(`/libraries/${library.id}/scan`) .set('Authorization', `Bearer ${admin.accessToken}`) - .send({ refreshModifiedFiles: true }); + .send(); expect(status).toBe(204); await utils.waitForQueueFinish(admin.accessToken, 'library'); + await utils.waitForQueueFinish(admin.accessToken, 'sidecar'); await utils.waitForQueueFinish(admin.accessToken, 'metadataExtraction'); - utils.removeImageFile(`${testAssetDir}/temp/directoryA/assetB.jpg`); - const { assets } = await utils.metadataSearch(admin.accessToken, { + const { assets } = await utils.searchAssets(admin.accessToken, { libraryId: library.id, - model: 'NIKON D750', }); - expect(assets.count).toBe(0); + + expect(assets.count).toEqual(1); + + const asset = await utils.getAssetInfo(admin.accessToken, assets.items[0].id); + + expect(asset).toEqual( + expect.objectContaining({ + originalFileName: 'asset.jpg', + exifInfo: expect.not.objectContaining({ + model: 'NIKON D750', + }), + }), + ); + + utils.removeImageFile(`${testAssetDir}/temp/reimport/asset.jpg`); }); it('should set an asset offline if its file is missing', async () => { @@ -478,7 +567,7 @@ describe('/libraries', () => { await scan(admin.accessToken, library.id); await utils.waitForQueueFinish(admin.accessToken, 'library'); - const { assets } = await utils.metadataSearch(admin.accessToken, { libraryId: library.id }); + const { assets } = await utils.searchAssets(admin.accessToken, { libraryId: library.id }); expect(assets.count).toBe(1); utils.removeImageFile(`${testAssetDir}/temp/offline/offline.png`); @@ -495,7 +584,7 @@ describe('/libraries', () => { expect(trashedAsset.originalPath).toBe(`${testAssetDirInternal}/temp/offline/offline.png`); expect(trashedAsset.isOffline).toEqual(true); - const { assets: newAssets } = await utils.metadataSearch(admin.accessToken, { libraryId: library.id }); + const { assets: newAssets } = await utils.searchAssets(admin.accessToken, { libraryId: library.id }); expect(newAssets.items).toEqual([]); }); @@ -510,7 +599,7 @@ describe('/libraries', () => { await scan(admin.accessToken, library.id); await utils.waitForQueueFinish(admin.accessToken, 'library'); - const { assets } = await utils.metadataSearch(admin.accessToken, { libraryId: library.id }); + const { assets } = await utils.searchAssets(admin.accessToken, { libraryId: library.id }); expect(assets.count).toBe(1); utils.createDirectory(`${testAssetDir}/temp/another-path/`); @@ -532,7 +621,7 @@ describe('/libraries', () => { expect(trashedAsset.originalPath).toBe(`${testAssetDirInternal}/temp/offline/offline.png`); expect(trashedAsset.isOffline).toBe(true); - const { assets: newAssets } = await utils.metadataSearch(admin.accessToken, { libraryId: library.id }); + const { assets: newAssets } = await utils.searchAssets(admin.accessToken, { libraryId: library.id }); expect(newAssets.items).toEqual([]); @@ -549,7 +638,7 @@ describe('/libraries', () => { await scan(admin.accessToken, library.id); await utils.waitForQueueFinish(admin.accessToken, 'library'); - const { assets } = await utils.metadataSearch(admin.accessToken, { + const { assets } = await utils.searchAssets(admin.accessToken, { libraryId: library.id, originalFileName: 'assetB.png', }); @@ -568,7 +657,7 @@ describe('/libraries', () => { expect(trashedAsset.originalPath).toBe(`${testAssetDirInternal}/temp/directoryB/assetB.png`); expect(trashedAsset.isOffline).toBe(true); - const { assets: newAssets } = await utils.metadataSearch(admin.accessToken, { libraryId: library.id }); + const { assets: newAssets } = await utils.searchAssets(admin.accessToken, { libraryId: library.id }); expect(newAssets.items).toEqual([ expect.objectContaining({ @@ -586,7 +675,7 @@ describe('/libraries', () => { await scan(admin.accessToken, library.id); await utils.waitForQueueFinish(admin.accessToken, 'library'); - const { assets: assetsBefore } = await utils.metadataSearch(admin.accessToken, { libraryId: library.id }); + const { assets: assetsBefore } = await utils.searchAssets(admin.accessToken, { libraryId: library.id }); expect(assetsBefore.count).toBeGreaterThan(1); const { status } = await request(app) @@ -597,10 +686,302 @@ describe('/libraries', () => { await utils.waitForQueueFinish(admin.accessToken, 'library'); - const { assets } = await utils.metadataSearch(admin.accessToken, { libraryId: library.id }); + const { assets } = await utils.searchAssets(admin.accessToken, { libraryId: library.id }); expect(assets).toEqual(assetsBefore); }); + + describe('xmp metadata', async () => { + it('should import metadata from file.xmp', async () => { + const library = await utils.createLibrary(admin.accessToken, { + ownerId: admin.userId, + importPaths: [`${testAssetDirInternal}/temp/xmp`], + }); + + cpSync(`${testAssetDir}/metadata/xmp/dates/2000.xmp`, `${testAssetDir}/temp/xmp/glarus.xmp`); + cpSync(`${testAssetDir}/formats/raw/Nikon/D80/glarus.nef`, `${testAssetDir}/temp/xmp/glarus.nef`); + + await scan(admin.accessToken, library.id); + + await utils.waitForQueueFinish(admin.accessToken, 'library'); + await utils.waitForQueueFinish(admin.accessToken, 'sidecar'); + await utils.waitForQueueFinish(admin.accessToken, 'metadataExtraction'); + + const { assets: newAssets } = await utils.searchAssets(admin.accessToken, { libraryId: library.id }); + + expect(newAssets.items).toEqual([ + expect.objectContaining({ + originalFileName: 'glarus.nef', + fileCreatedAt: '2000-09-27T12:35:33.000Z', + }), + ]); + + rmSync(`${testAssetDir}/temp/xmp`, { recursive: true, force: true }); + }); + + it('should import metadata from file.ext.xmp', async () => { + const library = await utils.createLibrary(admin.accessToken, { + ownerId: admin.userId, + importPaths: [`${testAssetDirInternal}/temp/xmp`], + }); + + cpSync(`${testAssetDir}/metadata/xmp/dates/2000.xmp`, `${testAssetDir}/temp/xmp/glarus.nef.xmp`); + cpSync(`${testAssetDir}/formats/raw/Nikon/D80/glarus.nef`, `${testAssetDir}/temp/xmp/glarus.nef`); + + await scan(admin.accessToken, library.id); + await utils.waitForQueueFinish(admin.accessToken, 'library'); + await utils.waitForQueueFinish(admin.accessToken, 'sidecar'); + await utils.waitForQueueFinish(admin.accessToken, 'metadataExtraction'); + + const { assets: newAssets } = await utils.searchAssets(admin.accessToken, { libraryId: library.id }); + + expect(newAssets.items).toEqual([ + expect.objectContaining({ + originalFileName: 'glarus.nef', + fileCreatedAt: '2000-09-27T12:35:33.000Z', + }), + ]); + + rmSync(`${testAssetDir}/temp/xmp`, { recursive: true, force: true }); + }); + + it('should import metadata in file.ext.xmp before file.xmp if both exist', async () => { + const library = await utils.createLibrary(admin.accessToken, { + ownerId: admin.userId, + importPaths: [`${testAssetDirInternal}/temp/xmp`], + }); + + cpSync(`${testAssetDir}/metadata/xmp/dates/2000.xmp`, `${testAssetDir}/temp/xmp/glarus.nef.xmp`); + cpSync(`${testAssetDir}/metadata/xmp/dates/2010.xmp`, `${testAssetDir}/temp/xmp/glarus.xmp`); + cpSync(`${testAssetDir}/formats/raw/Nikon/D80/glarus.nef`, `${testAssetDir}/temp/xmp/glarus.nef`); + + await scan(admin.accessToken, library.id); + await utils.waitForQueueFinish(admin.accessToken, 'library'); + await utils.waitForQueueFinish(admin.accessToken, 'sidecar'); + await utils.waitForQueueFinish(admin.accessToken, 'metadataExtraction'); + + const { assets: newAssets } = await utils.searchAssets(admin.accessToken, { libraryId: library.id }); + + expect(newAssets.items).toEqual([ + expect.objectContaining({ + originalFileName: 'glarus.nef', + fileCreatedAt: '2000-09-27T12:35:33.000Z', + }), + ]); + + rmSync(`${testAssetDir}/temp/xmp`, { recursive: true, force: true }); + }); + + it('should switch from using file.xmp to file.ext.xmp when asset refreshes', async () => { + const library = await utils.createLibrary(admin.accessToken, { + ownerId: admin.userId, + importPaths: [`${testAssetDirInternal}/temp/xmp`], + }); + + cpSync(`${testAssetDir}/metadata/xmp/dates/2000.xmp`, `${testAssetDir}/temp/xmp/glarus.xmp`); + cpSync(`${testAssetDir}/formats/raw/Nikon/D80/glarus.nef`, `${testAssetDir}/temp/xmp/glarus.nef`); + await utimes(`${testAssetDir}/temp/xmp/glarus.nef`, 447_775_200_000); + + await scan(admin.accessToken, library.id); + await utils.waitForQueueFinish(admin.accessToken, 'library'); + await utils.waitForQueueFinish(admin.accessToken, 'sidecar'); + await utils.waitForQueueFinish(admin.accessToken, 'metadataExtraction'); + + cpSync(`${testAssetDir}/metadata/xmp/dates/2010.xmp`, `${testAssetDir}/temp/xmp/glarus.nef.xmp`); + unlinkSync(`${testAssetDir}/temp/xmp/glarus.xmp`); + await utimes(`${testAssetDir}/temp/xmp/glarus.nef`, 447_775_200_001); + + await scan(admin.accessToken, library.id); + await utils.waitForQueueFinish(admin.accessToken, 'library'); + await utils.waitForQueueFinish(admin.accessToken, 'sidecar'); + await utils.waitForQueueFinish(admin.accessToken, 'metadataExtraction'); + + const { assets: newAssets } = await utils.searchAssets(admin.accessToken, { libraryId: library.id }); + + expect(newAssets.items).toEqual([ + expect.objectContaining({ + originalFileName: 'glarus.nef', + fileCreatedAt: '2010-09-27T12:35:33.000Z', + }), + ]); + + rmSync(`${testAssetDir}/temp/xmp`, { recursive: true, force: true }); + }); + + it('should switch from using file metadata to file.xmp metadata when asset refreshes', async () => { + const library = await utils.createLibrary(admin.accessToken, { + ownerId: admin.userId, + importPaths: [`${testAssetDirInternal}/temp/xmp`], + }); + + cpSync(`${testAssetDir}/formats/raw/Nikon/D80/glarus.nef`, `${testAssetDir}/temp/xmp/glarus.nef`); + await utimes(`${testAssetDir}/temp/xmp/glarus.nef`, 447_775_200_000); + + await scan(admin.accessToken, library.id); + await utils.waitForQueueFinish(admin.accessToken, 'library'); + await utils.waitForQueueFinish(admin.accessToken, 'sidecar'); + await utils.waitForQueueFinish(admin.accessToken, 'metadataExtraction'); + + cpSync(`${testAssetDir}/metadata/xmp/dates/2000.xmp`, `${testAssetDir}/temp/xmp/glarus.xmp`); + await utimes(`${testAssetDir}/temp/xmp/glarus.nef`, 447_775_200_001); + + await scan(admin.accessToken, library.id); + await utils.waitForQueueFinish(admin.accessToken, 'library'); + await utils.waitForQueueFinish(admin.accessToken, 'sidecar'); + await utils.waitForQueueFinish(admin.accessToken, 'metadataExtraction'); + + const { assets: newAssets } = await utils.searchAssets(admin.accessToken, { libraryId: library.id }); + + expect(newAssets.items).toEqual([ + expect.objectContaining({ + originalFileName: 'glarus.nef', + fileCreatedAt: '2000-09-27T12:35:33.000Z', + }), + ]); + + rmSync(`${testAssetDir}/temp/xmp`, { recursive: true, force: true }); + }); + + it('should switch from using file metadata to file.xmp metadata when asset refreshes', async () => { + const library = await utils.createLibrary(admin.accessToken, { + ownerId: admin.userId, + importPaths: [`${testAssetDirInternal}/temp/xmp`], + }); + + cpSync(`${testAssetDir}/formats/raw/Nikon/D80/glarus.nef`, `${testAssetDir}/temp/xmp/glarus.nef`); + await utimes(`${testAssetDir}/temp/xmp/glarus.nef`, 447_775_200_000); + + await scan(admin.accessToken, library.id); + await utils.waitForQueueFinish(admin.accessToken, 'library'); + await utils.waitForQueueFinish(admin.accessToken, 'sidecar'); + await utils.waitForQueueFinish(admin.accessToken, 'metadataExtraction'); + + cpSync(`${testAssetDir}/metadata/xmp/dates/2000.xmp`, `${testAssetDir}/temp/xmp/glarus.nef.xmp`); + await utimes(`${testAssetDir}/temp/xmp/glarus.nef`, 447_775_200_001); + + await scan(admin.accessToken, library.id); + await utils.waitForQueueFinish(admin.accessToken, 'library'); + await utils.waitForQueueFinish(admin.accessToken, 'sidecar'); + await utils.waitForQueueFinish(admin.accessToken, 'metadataExtraction'); + + const { assets: newAssets } = await utils.searchAssets(admin.accessToken, { libraryId: library.id }); + + expect(newAssets.items).toEqual([ + expect.objectContaining({ + originalFileName: 'glarus.nef', + fileCreatedAt: '2000-09-27T12:35:33.000Z', + }), + ]); + + rmSync(`${testAssetDir}/temp/xmp`, { recursive: true, force: true }); + }); + + it('should switch from using file.ext.xmp to file.xmp when asset refreshes', async () => { + const library = await utils.createLibrary(admin.accessToken, { + ownerId: admin.userId, + importPaths: [`${testAssetDirInternal}/temp/xmp`], + }); + + cpSync(`${testAssetDir}/metadata/xmp/dates/2000.xmp`, `${testAssetDir}/temp/xmp/glarus.nef.xmp`); + cpSync(`${testAssetDir}/formats/raw/Nikon/D80/glarus.nef`, `${testAssetDir}/temp/xmp/glarus.nef`); + await utimes(`${testAssetDir}/temp/xmp/glarus.nef`, 447_775_200_000); + + await scan(admin.accessToken, library.id); + await utils.waitForQueueFinish(admin.accessToken, 'library'); + await utils.waitForQueueFinish(admin.accessToken, 'sidecar'); + await utils.waitForQueueFinish(admin.accessToken, 'metadataExtraction'); + + cpSync(`${testAssetDir}/metadata/xmp/dates/2010.xmp`, `${testAssetDir}/temp/xmp/glarus.xmp`); + unlinkSync(`${testAssetDir}/temp/xmp/glarus.nef.xmp`); + await utimes(`${testAssetDir}/temp/xmp/glarus.nef`, 447_775_200_001); + + await scan(admin.accessToken, library.id); + await utils.waitForQueueFinish(admin.accessToken, 'library'); + await utils.waitForQueueFinish(admin.accessToken, 'sidecar'); + await utils.waitForQueueFinish(admin.accessToken, 'metadataExtraction'); + + const { assets: newAssets } = await utils.searchAssets(admin.accessToken, { libraryId: library.id }); + + expect(newAssets.items).toEqual([ + expect.objectContaining({ + originalFileName: 'glarus.nef', + fileCreatedAt: '2010-09-27T12:35:33.000Z', + }), + ]); + + rmSync(`${testAssetDir}/temp/xmp`, { recursive: true, force: true }); + }); + + it('should switch from using file.ext.xmp to file metadata', async () => { + const library = await utils.createLibrary(admin.accessToken, { + ownerId: admin.userId, + importPaths: [`${testAssetDirInternal}/temp/xmp`], + }); + + cpSync(`${testAssetDir}/metadata/xmp/dates/2000.xmp`, `${testAssetDir}/temp/xmp/glarus.nef.xmp`); + cpSync(`${testAssetDir}/formats/raw/Nikon/D80/glarus.nef`, `${testAssetDir}/temp/xmp/glarus.nef`); + await utimes(`${testAssetDir}/temp/xmp/glarus.nef`, 447_775_200_000); + + await scan(admin.accessToken, library.id); + await utils.waitForQueueFinish(admin.accessToken, 'library'); + await utils.waitForQueueFinish(admin.accessToken, 'sidecar'); + await utils.waitForQueueFinish(admin.accessToken, 'metadataExtraction'); + + unlinkSync(`${testAssetDir}/temp/xmp/glarus.nef.xmp`); + await utimes(`${testAssetDir}/temp/xmp/glarus.nef`, 447_775_200_001); + + await scan(admin.accessToken, library.id); + await utils.waitForQueueFinish(admin.accessToken, 'library'); + await utils.waitForQueueFinish(admin.accessToken, 'sidecar'); + await utils.waitForQueueFinish(admin.accessToken, 'metadataExtraction'); + + const { assets: newAssets } = await utils.searchAssets(admin.accessToken, { libraryId: library.id }); + + expect(newAssets.items).toEqual([ + expect.objectContaining({ + originalFileName: 'glarus.nef', + fileCreatedAt: '2010-07-20T17:27:12.000Z', + }), + ]); + + rmSync(`${testAssetDir}/temp/xmp`, { recursive: true, force: true }); + }); + + it('should switch from using file.xmp to file metadata', async () => { + const library = await utils.createLibrary(admin.accessToken, { + ownerId: admin.userId, + importPaths: [`${testAssetDirInternal}/temp/xmp`], + }); + + cpSync(`${testAssetDir}/metadata/xmp/dates/2000.xmp`, `${testAssetDir}/temp/xmp/glarus.xmp`); + cpSync(`${testAssetDir}/formats/raw/Nikon/D80/glarus.nef`, `${testAssetDir}/temp/xmp/glarus.nef`); + await utimes(`${testAssetDir}/temp/xmp/glarus.nef`, 447_775_200_000); + + await scan(admin.accessToken, library.id); + await utils.waitForQueueFinish(admin.accessToken, 'library'); + await utils.waitForQueueFinish(admin.accessToken, 'sidecar'); + await utils.waitForQueueFinish(admin.accessToken, 'metadataExtraction'); + + unlinkSync(`${testAssetDir}/temp/xmp/glarus.xmp`); + await utimes(`${testAssetDir}/temp/xmp/glarus.nef`, 447_775_200_001); + + await scan(admin.accessToken, library.id); + await utils.waitForQueueFinish(admin.accessToken, 'library'); + await utils.waitForQueueFinish(admin.accessToken, 'sidecar'); + await utils.waitForQueueFinish(admin.accessToken, 'metadataExtraction'); + + const { assets: newAssets } = await utils.searchAssets(admin.accessToken, { libraryId: library.id }); + + expect(newAssets.items).toEqual([ + expect.objectContaining({ + originalFileName: 'glarus.nef', + fileCreatedAt: '2010-07-20T17:27:12.000Z', + }), + ]); + + rmSync(`${testAssetDir}/temp/xmp`, { recursive: true, force: true }); + }); + }); }); describe('POST /libraries/:id/validate', () => { diff --git a/e2e/src/api/specs/search.e2e-spec.ts b/e2e/src/api/specs/search.e2e-spec.ts index 0e5d882f80e50..11bb37be1853b 100644 --- a/e2e/src/api/specs/search.e2e-spec.ts +++ b/e2e/src/api/specs/search.e2e-spec.ts @@ -98,6 +98,7 @@ describe('/search', () => { { latitude: 31.634_16, longitude: -7.999_94 }, // marrakesh { latitude: 38.523_735_4, longitude: -78.488_619_4 }, // tanners ridge { latitude: 59.938_63, longitude: 30.314_13 }, // st. petersburg + { latitude: 0, longitude: 0 }, // null island ]; const updates = coordinates.map((dto, i) => @@ -473,10 +474,7 @@ describe('/search', () => { .get('/search/explore') .set('Authorization', `Bearer ${admin.accessToken}`); expect(status).toBe(200); - expect(body).toEqual([ - { fieldName: 'exifInfo.city', items: [] }, - { fieldName: 'smartInfo.tags', items: [] }, - ]); + expect(body).toEqual([{ fieldName: 'exifInfo.city', items: [] }]); }); }); @@ -535,7 +533,7 @@ describe('/search', () => { expect(body).toEqual(errorDto.unauthorized); }); - it('should get suggestions for country', async () => { + it('should get suggestions for country (including null)', async () => { const { status, body } = await request(app) .get('/search/suggestions?type=country&includeNull=true') .set('Authorization', `Bearer ${admin.accessToken}`); @@ -558,7 +556,29 @@ describe('/search', () => { expect(status).toBe(200); }); - it('should get suggestions for state', async () => { + it('should get suggestions for country', async () => { + const { status, body } = await request(app) + .get('/search/suggestions?type=country') + .set('Authorization', `Bearer ${admin.accessToken}`); + expect(body).toEqual([ + 'Cuba', + 'France', + 'Georgia', + 'Germany', + 'Ghana', + 'Japan', + 'Morocco', + "People's Republic of China", + 'Russian Federation', + 'Singapore', + 'Spain', + 'Switzerland', + 'United States of America', + ]); + expect(status).toBe(200); + }); + + it('should get suggestions for state (including null)', async () => { const { status, body } = await request(app) .get('/search/suggestions?type=state&includeNull=true') .set('Authorization', `Bearer ${admin.accessToken}`); @@ -582,7 +602,30 @@ describe('/search', () => { expect(status).toBe(200); }); - it('should get suggestions for city', async () => { + it('should get suggestions for state', async () => { + const { status, body } = await request(app) + .get('/search/suggestions?type=state') + .set('Authorization', `Bearer ${admin.accessToken}`); + expect(body).toEqual([ + 'Andalusia', + 'Berlin', + 'Glarus', + 'Greater Accra', + 'Havana', + 'Île-de-France', + 'Marrakesh-Safi', + 'Mississippi', + 'New York', + 'Shanghai', + 'St.-Petersburg', + 'Tbilisi', + 'Tokyo', + 'Virginia', + ]); + expect(status).toBe(200); + }); + + it('should get suggestions for city (including null)', async () => { const { status, body } = await request(app) .get('/search/suggestions?type=city&includeNull=true') .set('Authorization', `Bearer ${admin.accessToken}`); @@ -607,7 +650,31 @@ describe('/search', () => { expect(status).toBe(200); }); - it('should get suggestions for camera make', async () => { + it('should get suggestions for city', async () => { + const { status, body } = await request(app) + .get('/search/suggestions?type=city') + .set('Authorization', `Bearer ${admin.accessToken}`); + expect(body).toEqual([ + 'Accra', + 'Berlin', + 'Glarus', + 'Havana', + 'Marrakesh', + 'Montalbán de Córdoba', + 'New York City', + 'Novena', + 'Paris', + 'Philadelphia', + 'Saint Petersburg', + 'Shanghai', + 'Stanley', + 'Tbilisi', + 'Tokyo', + ]); + expect(status).toBe(200); + }); + + it('should get suggestions for camera make (including null)', async () => { const { status, body } = await request(app) .get('/search/suggestions?type=camera-make&includeNull=true') .set('Authorization', `Bearer ${admin.accessToken}`); @@ -624,7 +691,23 @@ describe('/search', () => { expect(status).toBe(200); }); - it('should get suggestions for camera model', async () => { + it('should get suggestions for camera make', async () => { + const { status, body } = await request(app) + .get('/search/suggestions?type=camera-make') + .set('Authorization', `Bearer ${admin.accessToken}`); + expect(body).toEqual([ + 'Apple', + 'Canon', + 'FUJIFILM', + 'NIKON CORPORATION', + 'PENTAX Corporation', + 'samsung', + 'SONY', + ]); + expect(status).toBe(200); + }); + + it('should get suggestions for camera model (including null)', async () => { const { status, body } = await request(app) .get('/search/suggestions?type=camera-model&includeNull=true') .set('Authorization', `Bearer ${admin.accessToken}`); @@ -645,5 +728,26 @@ describe('/search', () => { ]); expect(status).toBe(200); }); + + it('should get suggestions for camera model', async () => { + const { status, body } = await request(app) + .get('/search/suggestions?type=camera-model') + .set('Authorization', `Bearer ${admin.accessToken}`); + expect(body).toEqual([ + 'Canon EOS 7D', + 'Canon EOS R5', + 'DSLR-A550', + 'FinePix S3Pro', + 'iPhone 7', + 'NIKON D700', + 'NIKON D750', + 'NIKON D80', + 'PENTAX K10D', + 'SM-F711N', + 'SM-S906U', + 'SM-T970', + ]); + expect(status).toBe(200); + }); }); }); diff --git a/e2e/src/api/specs/server.e2e-spec.ts b/e2e/src/api/specs/server.e2e-spec.ts index 3133460adaf2a..c89280f5796af 100644 --- a/e2e/src/api/specs/server.e2e-spec.ts +++ b/e2e/src/api/specs/server.e2e-spec.ts @@ -133,6 +133,7 @@ describe('/server', () => { userDeleteDelay: 7, isInitialized: true, externalDomain: '', + publicUsers: true, isOnboarded: false, mapDarkStyleUrl: 'https://tiles.immich.cloud/v1/style/dark.json', mapLightStyleUrl: 'https://tiles.immich.cloud/v1/style/light.json', @@ -163,11 +164,15 @@ describe('/server', () => { expect(body).toEqual({ photos: 0, usage: 0, + usagePhotos: 0, + usageVideos: 0, usageByUser: [ { quotaSizeInBytes: null, photos: 0, usage: 0, + usagePhotos: 0, + usageVideos: 0, userName: 'Immich Admin', userId: admin.userId, videos: 0, @@ -176,6 +181,8 @@ describe('/server', () => { quotaSizeInBytes: null, photos: 0, usage: 0, + usagePhotos: 0, + usageVideos: 0, userName: 'User 1', userId: nonAdmin.userId, videos: 0, diff --git a/e2e/src/api/specs/trash.e2e-spec.ts b/e2e/src/api/specs/trash.e2e-spec.ts index 0bfc0ec19be21..f86f38ab61d2f 100644 --- a/e2e/src/api/specs/trash.e2e-spec.ts +++ b/e2e/src/api/specs/trash.e2e-spec.ts @@ -84,7 +84,7 @@ describe('/trash', () => { await scan(admin.accessToken, library.id); await utils.waitForQueueFinish(admin.accessToken, 'library'); - const { assets } = await utils.metadataSearch(admin.accessToken, { libraryId: library.id }); + const { assets } = await utils.searchAssets(admin.accessToken, { libraryId: library.id }); expect(assets.items.length).toBe(1); const asset = assets.items[0]; @@ -148,7 +148,7 @@ describe('/trash', () => { await scan(admin.accessToken, library.id); await utils.waitForQueueFinish(admin.accessToken, 'library'); - const { assets } = await utils.metadataSearch(admin.accessToken, { libraryId: library.id }); + const { assets } = await utils.searchAssets(admin.accessToken, { libraryId: library.id }); expect(assets.count).toBe(1); const assetId = assets.items[0].id; @@ -206,7 +206,7 @@ describe('/trash', () => { await scan(admin.accessToken, library.id); await utils.waitForQueueFinish(admin.accessToken, 'library'); - const { assets } = await utils.metadataSearch(admin.accessToken, { libraryId: library.id }); + const { assets } = await utils.searchAssets(admin.accessToken, { libraryId: library.id }); expect(assets.count).toBe(1); const assetId = assets.items[0].id; diff --git a/e2e/src/cli/specs/upload.e2e-spec.ts b/e2e/src/cli/specs/upload.e2e-spec.ts index d700aa73b2091..301c6d3bf0621 100644 --- a/e2e/src/cli/specs/upload.e2e-spec.ts +++ b/e2e/src/cli/specs/upload.e2e-spec.ts @@ -103,7 +103,7 @@ describe(`immich upload`, () => { describe(`immich upload /path/to/file.jpg`, () => { it('should upload a single file', async () => { const { stderr, stdout, exitCode } = await immichCli(['upload', `${testAssetDir}/albums/nature/silver_fir.jpg`]); - expect(stderr).toBe(''); + expect(stderr).toContain('{message}'); expect(stdout.split('\n')).toEqual( expect.arrayContaining([expect.stringContaining('Successfully uploaded 1 new asset')]), ); @@ -126,7 +126,7 @@ describe(`immich upload`, () => { const expectedCount = Object.entries(files).filter((entry) => entry[1]).length; const { stderr, stdout, exitCode } = await immichCli(['upload', ...commandLine]); - expect(stderr).toBe(''); + expect(stderr).toContain('{message}'); expect(stdout.split('\n')).toEqual( expect.arrayContaining([expect.stringContaining(`Successfully uploaded ${expectedCount} new asset`)]), ); @@ -154,7 +154,7 @@ describe(`immich upload`, () => { cpSync(`${testAssetDir}/albums/nature/silver_fir.jpg`, testPaths[1]); const { stderr, stdout, exitCode } = await immichCli(['upload', ...testPaths]); - expect(stderr).toBe(''); + expect(stderr).toContain('{message}'); expect(stdout.split('\n')).toEqual( expect.arrayContaining([expect.stringContaining('Successfully uploaded 2 new assets')]), ); @@ -169,7 +169,7 @@ describe(`immich upload`, () => { it('should skip a duplicate file', async () => { const first = await immichCli(['upload', `${testAssetDir}/albums/nature/silver_fir.jpg`]); - expect(first.stderr).toBe(''); + expect(first.stderr).toContain('{message}'); expect(first.stdout.split('\n')).toEqual( expect.arrayContaining([expect.stringContaining('Successfully uploaded 1 new asset')]), ); @@ -179,7 +179,7 @@ describe(`immich upload`, () => { expect(assets.total).toBe(1); const second = await immichCli(['upload', `${testAssetDir}/albums/nature/silver_fir.jpg`]); - expect(second.stderr).toBe(''); + expect(second.stderr).toContain('{message}'); expect(second.stdout.split('\n')).toEqual( expect.arrayContaining([ expect.stringContaining('Found 0 new files and 1 duplicate'), @@ -205,7 +205,7 @@ describe(`immich upload`, () => { `${testAssetDir}/albums/nature/silver_fir.jpg`, '--dry-run', ]); - expect(stderr).toBe(''); + expect(stderr).toContain('{message}'); expect(stdout.split('\n')).toEqual( expect.arrayContaining([expect.stringContaining('Would have uploaded 1 asset')]), ); @@ -217,7 +217,7 @@ describe(`immich upload`, () => { it('dry run should handle duplicates', async () => { const first = await immichCli(['upload', `${testAssetDir}/albums/nature/silver_fir.jpg`]); - expect(first.stderr).toBe(''); + expect(first.stderr).toContain('{message}'); expect(first.stdout.split('\n')).toEqual( expect.arrayContaining([expect.stringContaining('Successfully uploaded 1 new asset')]), ); @@ -227,7 +227,7 @@ describe(`immich upload`, () => { expect(assets.total).toBe(1); const second = await immichCli(['upload', `${testAssetDir}/albums/nature/`, '--dry-run']); - expect(second.stderr).toBe(''); + expect(second.stderr).toContain('{message}'); expect(second.stdout.split('\n')).toEqual( expect.arrayContaining([ expect.stringContaining('Found 8 new files and 1 duplicate'), @@ -241,7 +241,7 @@ describe(`immich upload`, () => { describe('immich upload --recursive', () => { it('should upload a folder recursively', async () => { const { stderr, stdout, exitCode } = await immichCli(['upload', `${testAssetDir}/albums/nature/`, '--recursive']); - expect(stderr).toBe(''); + expect(stderr).toContain('{message}'); expect(stdout.split('\n')).toEqual( expect.arrayContaining([expect.stringContaining('Successfully uploaded 9 new assets')]), ); @@ -267,7 +267,7 @@ describe(`immich upload`, () => { expect.stringContaining('Successfully updated 9 assets'), ]), ); - expect(stderr).toBe(''); + expect(stderr).toContain('{message}'); expect(exitCode).toBe(0); const assets = await getAssetStatistics({}, { headers: asKeyAuth(key) }); @@ -283,7 +283,7 @@ describe(`immich upload`, () => { expect(response1.stdout.split('\n')).toEqual( expect.arrayContaining([expect.stringContaining('Successfully uploaded 9 new assets')]), ); - expect(response1.stderr).toBe(''); + expect(response1.stderr).toContain('{message}'); expect(response1.exitCode).toBe(0); const assets1 = await getAssetStatistics({}, { headers: asKeyAuth(key) }); @@ -299,7 +299,7 @@ describe(`immich upload`, () => { expect.stringContaining('Successfully updated 9 assets'), ]), ); - expect(response2.stderr).toBe(''); + expect(response2.stderr).toContain('{message}'); expect(response2.exitCode).toBe(0); const assets2 = await getAssetStatistics({}, { headers: asKeyAuth(key) }); @@ -325,7 +325,7 @@ describe(`immich upload`, () => { expect.stringContaining('Would have updated albums of 9 assets'), ]), ); - expect(stderr).toBe(''); + expect(stderr).toContain('{message}'); expect(exitCode).toBe(0); const assets = await getAssetStatistics({}, { headers: asKeyAuth(key) }); @@ -351,7 +351,7 @@ describe(`immich upload`, () => { expect.stringContaining('Successfully updated 9 assets'), ]), ); - expect(stderr).toBe(''); + expect(stderr).toContain('{message}'); expect(exitCode).toBe(0); const assets = await getAssetStatistics({}, { headers: asKeyAuth(key) }); @@ -377,7 +377,7 @@ describe(`immich upload`, () => { expect.stringContaining('Would have updated albums of 9 assets'), ]), ); - expect(stderr).toBe(''); + expect(stderr).toContain('{message}'); expect(exitCode).toBe(0); const assets = await getAssetStatistics({}, { headers: asKeyAuth(key) }); @@ -408,7 +408,7 @@ describe(`immich upload`, () => { expect.stringContaining('Deleting assets that have been uploaded'), ]), ); - expect(stderr).toBe(''); + expect(stderr).toContain('{message}'); expect(exitCode).toBe(0); const assets = await getAssetStatistics({}, { headers: asKeyAuth(key) }); @@ -434,7 +434,7 @@ describe(`immich upload`, () => { expect.stringContaining('Would have deleted 9 local assets'), ]), ); - expect(stderr).toBe(''); + expect(stderr).toContain('{message}'); expect(exitCode).toBe(0); const assets = await getAssetStatistics({}, { headers: asKeyAuth(key) }); @@ -493,7 +493,7 @@ describe(`immich upload`, () => { '2', ]); - expect(stderr).toBe(''); + expect(stderr).toContain('{message}'); expect(stdout.split('\n')).toEqual( expect.arrayContaining([ 'Found 9 new files and 0 duplicates', @@ -534,7 +534,7 @@ describe(`immich upload`, () => { 'silver_fir.jpg', ]); - expect(stderr).toBe(''); + expect(stderr).toContain('{message}'); expect(stdout.split('\n')).toEqual( expect.arrayContaining([ 'Found 8 new files and 0 duplicates', @@ -555,7 +555,7 @@ describe(`immich upload`, () => { '!(*_*_*).jpg', ]); - expect(stderr).toBe(''); + expect(stderr).toContain('{message}'); expect(stdout.split('\n')).toEqual( expect.arrayContaining([ 'Found 1 new files and 0 duplicates', @@ -577,7 +577,7 @@ describe(`immich upload`, () => { '--dry-run', ]); - expect(stderr).toBe(''); + expect(stderr).toContain('{message}'); expect(stdout.split('\n')).toEqual( expect.arrayContaining([ 'Found 8 new files and 0 duplicates', diff --git a/e2e/src/immich-admin/specs/immich-admin.e2e-spec.ts b/e2e/src/immich-admin/specs/immich-admin.e2e-spec.ts index d025b7a338185..cf0558883a0d9 100644 --- a/e2e/src/immich-admin/specs/immich-admin.e2e-spec.ts +++ b/e2e/src/immich-admin/specs/immich-admin.e2e-spec.ts @@ -9,9 +9,11 @@ describe(`immich-admin`, () => { describe('list-users', () => { it('should list the admin user', async () => { - const { stdout, stderr, exitCode } = await immichAdmin(['list-users']).promise; + const { stdout, exitCode } = await immichAdmin(['list-users']).promise; expect(exitCode).toBe(0); - expect(stderr).toBe(''); + + // TODO: Vitest needs upgrade to Node 22.x to fix the failed check + // expect(stderr).toBe(''); expect(stdout).toContain("email: 'admin@immich.cloud'"); expect(stdout).toContain("name: 'Immich Admin'"); }); @@ -29,9 +31,10 @@ describe(`immich-admin`, () => { } }); - const { stderr, stdout, exitCode } = await promise; + const { stdout, exitCode } = await promise; expect(exitCode).toBe(0); - expect(stderr).toBe(''); + // TODO: Vitest needs upgrade to Node 22.x to fix the failed check + // expect(stderr).toBe(''); expect(stdout).toContain('The admin password has been updated to:'); }); }); diff --git a/e2e/src/utils.ts b/e2e/src/utils.ts index 3af44b50b8330..14225ff063038 100644 --- a/e2e/src/utils.ts +++ b/e2e/src/utils.ts @@ -11,6 +11,7 @@ import { PersonCreateDto, SharedLinkCreateDto, UserAdminCreateDto, + UserPreferencesUpdateDto, ValidateLibraryDto, checkExistingAssets, createAlbum, @@ -19,19 +20,23 @@ import { createPartner, createPerson, createSharedLink, + createStack, createUserAdmin, deleteAssets, getAllJobsStatus, getAssetInfo, getConfigDefaults, login, - searchMetadata, + searchAssets, setBaseUrl, signUpAdmin, + tagAssets, updateAdminOnboarding, updateAlbumUser, updateAssets, updateConfig, + updateMyPreferences, + upsertTags, validate, } from '@immich/sdk'; import { BrowserContext } from '@playwright/test'; @@ -400,8 +405,8 @@ export const utils = { checkExistingAssets: (accessToken: string, checkExistingAssetsDto: CheckExistingAssetsDto) => checkExistingAssets({ checkExistingAssetsDto }, { headers: asBearerAuth(accessToken) }), - metadataSearch: async (accessToken: string, dto: MetadataSearchDto) => { - return searchMetadata({ metadataSearchDto: dto }, { headers: asBearerAuth(accessToken) }); + searchAssets: async (accessToken: string, dto: MetadataSearchDto) => { + return searchAssets({ metadataSearchDto: dto }, { headers: asBearerAuth(accessToken) }); }, archiveAssets: (accessToken: string, ids: string[]) => @@ -444,6 +449,18 @@ export const utils = { createPartner: (accessToken: string, id: string) => createPartner({ id }, { headers: asBearerAuth(accessToken) }), + updateMyPreferences: (accessToken: string, userPreferencesUpdateDto: UserPreferencesUpdateDto) => + updateMyPreferences({ userPreferencesUpdateDto }, { headers: asBearerAuth(accessToken) }), + + createStack: (accessToken: string, assetIds: string[]) => + createStack({ stackCreateDto: { assetIds } }, { headers: asBearerAuth(accessToken) }), + + upsertTags: (accessToken: string, tags: string[]) => + upsertTags({ tagUpsertDto: { tags } }, { headers: asBearerAuth(accessToken) }), + + tagAssets: (accessToken: string, tagId: string, assetIds: string[]) => + tagAssets({ id: tagId, bulkIdsDto: { ids: assetIds } }, { headers: asBearerAuth(accessToken) }), + setAuthCookies: async (context: BrowserContext, accessToken: string, domain = '127.0.0.1') => await context.addCookies([ { diff --git a/e2e/src/web/specs/asset-viewer/stack.e2e-spec.ts b/e2e/src/web/specs/asset-viewer/stack.e2e-spec.ts new file mode 100644 index 0000000000000..cb40f82c0a813 --- /dev/null +++ b/e2e/src/web/specs/asset-viewer/stack.e2e-spec.ts @@ -0,0 +1,66 @@ +import { AssetMediaResponseDto, LoginResponseDto } from '@immich/sdk'; +import { expect, Page, test } from '@playwright/test'; +import { utils } from 'src/utils'; + +async function ensureDetailPanelVisible(page: Page) { + await page.waitForSelector('#immich-asset-viewer'); + + const isVisible = await page.locator('#detail-panel').isVisible(); + if (!isVisible) { + await page.keyboard.press('i'); + await page.waitForSelector('#detail-panel'); + } +} + +test.describe('Asset Viewer stack', () => { + let admin: LoginResponseDto; + let assetOne: AssetMediaResponseDto; + let assetTwo: AssetMediaResponseDto; + + test.beforeAll(async () => { + utils.initSdk(); + await utils.resetDatabase(); + admin = await utils.adminSetup(); + await utils.updateMyPreferences(admin.accessToken, { tags: { enabled: true } }); + + assetOne = await utils.createAsset(admin.accessToken); + assetTwo = await utils.createAsset(admin.accessToken); + await utils.createStack(admin.accessToken, [assetOne.id, assetTwo.id]); + + const tags = await utils.upsertTags(admin.accessToken, ['test/1', 'test/2']); + const tagOne = tags.find((tag) => tag.value === 'test/1')!; + const tagTwo = tags.find((tag) => tag.value === 'test/2')!; + await utils.tagAssets(admin.accessToken, tagOne.id, [assetOne.id]); + await utils.tagAssets(admin.accessToken, tagTwo.id, [assetTwo.id]); + }); + + test('stack slideshow is visible', async ({ page, context }) => { + await utils.setAuthCookies(context, admin.accessToken); + await page.goto(`/photos/${assetOne.id}`); + + const stackAssets = page.locator('#stack-slideshow [data-asset]'); + await expect(stackAssets.first()).toBeVisible(); + await expect(stackAssets.nth(1)).toBeVisible(); + }); + + test('tags of primary asset are visible', async ({ page, context }) => { + await utils.setAuthCookies(context, admin.accessToken); + await page.goto(`/photos/${assetOne.id}`); + await ensureDetailPanelVisible(page); + + const tags = page.getByTestId('detail-panel-tags').getByRole('link'); + await expect(tags.first()).toHaveText('test/1'); + }); + + test('tags of second asset are visible', async ({ page, context }) => { + await utils.setAuthCookies(context, admin.accessToken); + await page.goto(`/photos/${assetOne.id}`); + await ensureDetailPanelVisible(page); + + const stackAssets = page.locator('#stack-slideshow [data-asset]'); + await stackAssets.nth(1).click(); + + const tags = page.getByTestId('detail-panel-tags').getByRole('link'); + await expect(tags.first()).toHaveText('test/2'); + }); +}); diff --git a/e2e/test-assets b/e2e/test-assets index 3e057d2f58750..9e3b964b080dc 160000 --- a/e2e/test-assets +++ b/e2e/test-assets @@ -1 +1 @@ -Subproject commit 3e057d2f58750acdf7ff281a3938e34a86cfef4d +Subproject commit 9e3b964b080dca6f035b29b86e66454ae8aeda78 diff --git a/i18n/af.json b/i18n/af.json index 0967ef424bce6..ede1a745eb321 100644 --- a/i18n/af.json +++ b/i18n/af.json @@ -1 +1,57 @@ -{} +{ + "about": "Verfris", + "account": "Rekening", + "account_settings": "Rekeninginstellings", + "acknowledge": "Erken", + "action": "Aksie", + "actions": "Aksies", + "active": "Aktief", + "activity": "Aktiwiteite", + "activity_changed": "Aktiwiteit is {enabled, select, true {aangeskakel} other {afgeskakel}}", + "add": "Voegby", + "add_a_description": "Voeg 'n beskrywing by", + "add_a_location": "Voeg 'n ligging by", + "add_a_name": "Voeg 'n naam by", + "add_a_title": "Voeg 'n titel by", + "add_exclusion_pattern": "Voeg uitsgluitingspatrone by", + "add_import_path": "Voeg invoerpad by", + "add_location": "Voeg ligging by", + "add_more_users": "Voeg meer gebruikers by", + "add_partner": "Voeg vennoot by", + "add_path": "Voeg pad by", + "add_photos": "Voeg foto's by", + "add_to": "Voeg na...", + "add_to_album": "Voeg na album", + "add_to_shared_album": "Voeg na gedeelde album", + "added_to_archive": "By argief gevoeg", + "added_to_favorites": "By gunstelinge gevoeg", + "added_to_favorites_count": "Het {count, number} by gunstelinge gevoeg", + "admin": { + "add_exclusion_pattern_description": "Voeg uitsluitingspatrone by. Globbing met *, ** en ? word ondersteun. Om alle lêers in enige lêergids genaamd \"Raw\" te ignoreer, gebruik \"**/Raw/**\". Om alle lêers wat op \".tif\" eindig, te ignoreer, gebruik \"**/*.tif\". Om 'n absolute pad te ignoreer, gebruik \"/path/to/ignore/**\".", + "asset_offline_description": "Hierdie eksterne biblioteekbate word nie meer op skyf gevind nie en is na die asblik geskuif. As die lêer binne die biblioteek geskuif is, gaan jou tydlyn na vir die nuwe ooreenstemmende bate. Om hierdie bate te herstel, maak asseblief seker dat die lêerpad hieronder deur Immich verkry kan word en skandeer die biblioteek.", + "authentication_settings": "Verifikasie instellings", + "authentication_settings_description": "Bestuur wagwoord, OAuth en ander verifikasie instellings", + "authentication_settings_disable_all": "Is jy seker jy wil alle aanmeldmetodes deaktiveer? Aanmelding sal heeltemal gedeaktiveer word.", + "authentication_settings_reenable": "Om te heraktiveer, gebruik 'n Server Command.", + "background_task_job": "Agtergrondtake", + "backup_database": "Rugsteun databasis", + "backup_database_enable_description": "Aktiveer databasisrugsteun", + "backup_keep_last_amount": "Aantal vorige rugsteune om te hou", + "backup_settings": "Rugsteun instellings", + "backup_settings_description": "Bestuur databasis rugsteun instellings", + "check_all": "Kies Alles", + "cleared_jobs": "Poste gevee vir: {job}", + "config_set_by_file": "Config word tans deur 'n konfigurasielêer gestel", + "confirm_delete_library": "Is jy seker jy wil {library}-biblioteek uitvee?", + "confirm_delete_library_assets": "Is jy seker jy wil hierdie biblioteek uitvee? Dit sal {count, plural, one {# bevatte base} other {# bevatte bates}} uit Immich uitvee en kan nie ongedaan gemaak word nie. Lêers sal op skyf bly.", + "confirm_email_below": "Om te bevestig, tik \"{email}\" hieronder", + "confirm_reprocess_all_faces": "Is jy seker jy wil alle gesigte herverwerk? Dit sal ook genoemde mense skoonmaak.", + "confirm_user_password_reset": "Is jy seker jy wil {user} se wagwoord terugstel?", + "create_job": "Skep werk", + "cron_expression": "Cron uitdrukking", + "cron_expression_description": "Stel die skanderingsinterval in met die cron-formaat. Vir meer inligting verwys asseblief na bv. Crontab Guru", + "cron_expression_presets": "Cron uitdrukking voorafinstellings", + "disable_login": "Deaktiveer aanmelding", + "duplicate_detection_job_description": "Begin masjienleer op bates om soortgelyke beelde op te spoor. Maak staat op Smart Search" + } +} diff --git a/i18n/ar.json b/i18n/ar.json index 7529ef82ca13a..7e1805ca34795 100644 --- a/i18n/ar.json +++ b/i18n/ar.json @@ -1,5 +1,5 @@ { - "about": "حول", + "about": "تحديث", "account": "الحساب", "account_settings": "إعدادات الحساب", "acknowledge": "أُدرك ذلك", @@ -34,6 +34,11 @@ "authentication_settings_disable_all": "هل أنت متأكد أنك تريد تعطيل جميع وسائل تسجيل الدخول؟ سيتم تعطيل تسجيل الدخول بالكامل.", "authentication_settings_reenable": "لإعادة التفعيل، استخدم أمر الخادم.", "background_task_job": "المهام الخلفية", + "backup_database": "قاعدة البيانات الاحتياطية", + "backup_database_enable_description": "تمكين النسخ الاحتياطي لقاعدة البيانات", + "backup_keep_last_amount": "مقدار النسخ الاحتياطية السابقة للاحتفاظ بها", + "backup_settings": "إعدادات النسخ الاحتياطي", + "backup_settings_description": "إدارة إعدادات النسخ الاحتياطي لقاعدة البيانات", "check_all": "اختر الكل", "cleared_jobs": "تم إخلاء مهام: {job}", "config_set_by_file": "الإعدادات حاليًا معينة عن طريق ملف الاعدادات", @@ -43,9 +48,10 @@ "confirm_reprocess_all_faces": "هل أنت متأكد أنك تريد إعادة معالجة جميع الوجوه؟ سيخلي هذا كل الأشخاص الذين سَميتَهم.", "confirm_user_password_reset": "هل أنت متأكد أنك تريد إعادة تعيين كلمة مرور {user}؟", "create_job": "إنشاء وظيفة", - "crontab_guru": "", + "cron_expression": "تعبير Cron", + "cron_expression_description": "اضبط الفاصل الزمني للفحص باستخدام تنسيق cron. لمزيد من المعلومات يُرجى الرجوع إلى Crontab Guru على سبيل المثال", + "cron_expression_presets": "الإعدادات المسبقة لتعبير Cron", "disable_login": "تعطيل تسجيل الدخول", - "disabled": "", "duplicate_detection_job_description": "بدء التعلم الآلي على المحتوى للعثور على الصور المتشابهة. يعتمد على البحث الذكي", "exclusion_pattern_description": "تتيح لك أنماط الاستبعاد تجاهل الملفات والمجلدات عند فحص مكتبتك. يعد هذا مفيدًا إذا كان لديك مجلدات تحتوي على ملفات لا تريد استيرادها، مثل ملفات RAW.", "external_library_created_at": "مكتبة خارجية (أُنشئت في {date})", @@ -63,22 +69,15 @@ "image_prefer_wide_gamut": "تفضيل نطاق الألوان الواسع", "image_prefer_wide_gamut_setting_description": "استخدم Display P3 للصور المصغرة. يحافظ هذا على حيوية الصور ذات مساحات الألوان الواسعة بشكل أفضل، ولكن قد تظهر الصور بشكل مختلف على الأجهزة القديمة ذات إصدار متصفح قديم. يتم الاحتفاظ بصور sRGB بتنسيق sRGB لتجنب تغيرات اللون.", "image_preview_description": "صورة متوسطة الحجم مع بيانات وصفية مجردة، تُستخدم عند عرض أصل واحد وللتعلم الآلي", - "image_preview_format": "تنسيق المعاينة", "image_preview_quality_description": "جودة المعاينة من 1 إلى 100. كلما كانت القيمة أعلى كان ذلك أفضل، ولكنها تنتج ملفات أكبر وقد تقلل من استجابة التطبيق. قد يؤثر ضبط قيمة منخفضة على جودة التعلم الآلي.", - "image_preview_resolution": "معاينة الدقّة", - "image_preview_resolution_description": "يُستخدم عند عرض صورة واحدة وللتعلم الآلي. ستحافظ الدقاتُ العالية على المزيد من التفاصيل ولكنها ستستغرق وقتًا أطول للترميز، ولها أحجام ملفات أكبر، ويمكن أن تقلل من استجابة التطبيق.", "image_preview_title": "إعدادات المعاينة", "image_quality": "الجودة", - "image_quality_description": "جودة الصورة من 1-100. الأعلى هو الأفضل من حيث الجودة ولكنه ينتج ملفات أكبر، ويؤثر هذا الخيار على صور المعاينة والصور المصغرة.", "image_resolution": "الدقة", "image_resolution_description": "يمكن للدقة العالية الحفاظ على مزيد من التفاصيل ولكنها تستغرق وقتًا أطول للترميز، وتحتوي على أحجام ملفات أكبر ويمكن أن تقلل من استجابة التطبيق.", "image_settings": "إعدادات الصور", "image_settings_description": "إدارة جودة ودقة الصور التي تم إنشاؤها", "image_thumbnail_description": "صورة مصغرة صغيرة مع بيانات وصفية مجردة، تُستخدم عند عرض مجموعات من الصور مثل الجدول الزمني الرئيسي", - "image_thumbnail_format": "تنسيق الصور المصغّرة", "image_thumbnail_quality_description": "تتراوح جودة الصورة المصغرة من 1 إلى 100. كلما كانت الجودة أعلى كان ذلك أفضل، ولكنها تنتج ملفات أكبر وقد تقلل من استجابة التطبيق.", - "image_thumbnail_resolution": "دقة الصور المصغّرة", - "image_thumbnail_resolution_description": "يُستخدم عند عرض مجموعات من الصور (المخطط الزمني الرئيسي، عرض الألبوم، وما إلى ذلك). ستحافظ الدقاتُ العالية على المزيد من التفاصيل ولكنها ستستغرق وقتًا أطول للترميز، ولها أحجام ملفات أكبر، ويمكن أن تقلل من استجابة التطبيق.", "image_thumbnail_title": "إعدادات الصورة المصغرة", "job_concurrency": "تزامن {job}", "job_created": "تم إنشاء الوظيفة", @@ -89,9 +88,6 @@ "jobs_delayed": "{jobCount, plural, other {# مؤجلة}}", "jobs_failed": "{jobCount, plural, other {# فشلت}}", "library_created": "تم إنشاء المكتبة: {library}", - "library_cron_expression": "تعبير Cron", - "library_cron_expression_description": "\"اضبط فواصلَ زمنِ الفحص باستخدام صيغة cron. للمزيد من المعلومات، يرجى الرجوع إلى Crontab Guru\"", - "library_cron_expression_presets": "إعدادات مسبقة لتعبير Cron", "library_deleted": "تم حذف المكتبة", "library_import_path_description": "حدد مجلدًا للاستيراد. سيتم فحص هذا المجلد، بما في ذلك المجلدات الفرعية، بحثًا عن الصور ومقاطع الفيديو.", "library_scanning": "الفحص الدوري", @@ -215,7 +211,6 @@ "refreshing_all_libraries": "تحديث كافة المكتبات", "registration": "تسجيل المدير", "registration_description": "بما أنك أول مستخدم في النظام، سيتم تعيينك كمسؤول وستكون مسؤولًا عن المهام الإدارية، وسيتم إنشاء مستخدمين إضافيين بواسطتك.", - "removing_deleted_files": "إزالة الملفات غير المتصلة", "repair_all": "إصلاح الكل", "repair_matched_items": "تمت مطابقة {count, plural, one {# عنصر} other {# عناصر}}", "repaired_items": "تم إصلاح {count, plural, one {# عنصر} other {# عناصر}}", @@ -223,12 +218,12 @@ "reset_settings_to_default": "إعادة ضبط الإعدادات إلى الوضع الافتراضي", "reset_settings_to_recent_saved": "إعادة ضبط الإعدادات إلى الإعدادات المحفوظة مؤخرًا", "scanning_library": "مسح المكتبة", - "scanning_library_for_changed_files": "فحص المكتبة لاكتشاف الملفات التي تم تغييرها", - "scanning_library_for_new_files": "فحص المكتبة للبحث عن ملفات جديدة", "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": "الرسالة الترحيبية", @@ -261,7 +256,6 @@ "these_files_matched_by_checksum": "تتم مطابقة هذه الملفات من خلال المجاميع الاختبارية الخاصة بهم", "thumbnail_generation_job": "إنشاء الصور المصغرة", "thumbnail_generation_job_description": "إنشاء صور مصغرة كبيرة وصغيرة وغير واضحة لكل أصل، بالإضافة إلى صور مصغرة لكل شخص", - "transcode_policy_description": "", "transcoding_acceleration_api": "واجهة برمجة التطبيقات للتسريع", "transcoding_acceleration_api_description": "الواجهة البرمجية التي ستتفاعل مع جهازك لتسريع التحويل. هذا الإعداد هو \"أفضل محاولة\": سيعود إلى التحويل البرمجي في حالة الفشل. قد لا يعمل VP9 اعتمادًا على عتادك.", "transcoding_acceleration_nvenc": "NVENC (يتطلب GPU من NVIDIA)", @@ -313,8 +307,6 @@ "transcoding_threads_description": "تؤدي القيم الأعلى إلى تشفير أسرع، ولكنها تترك مساحة أقل للخادم لمعالجة المهام الأخرى أثناء النشاط. يجب ألا تزيد هذه القيمة عن عدد مراكز وحدة المعالجة المركزية. يزيد من الإستغلال إذا تم ضبطه على 0.", "transcoding_tone_mapping": "رسم الخرائط النغمية", "transcoding_tone_mapping_description": "تحاول الحفاظ على مظهر مقاطع الفيديو HDR عند تحويلها إلى SDR. يقدم كل خوارزمية تنازلات مختلفة بين اللون والتفاصيل والسطوع. Hable تحافظ على التفاصيل، Mobius تحافظ على الألوان، و Reinhard تحافظ على السطوع.", - "transcoding_tone_mapping_npl": "تحويل الصور من نطاق الإضاءة العالية", - "transcoding_tone_mapping_npl_description": "سيتم ضبط الألوان لتبدو طبيعية على شاشة بهذه السطوع. على عكس المتوقع، تزيد القيم الأقل من سطوع الفيديو والعكس بسبب تعويضها لسطوع الشاشة. قيمة 0 تضبط هذه القيمة تلقائيًا.", "transcoding_transcode_policy": "سياسة الترميز", "transcoding_transcode_policy_description": "سياسة تحديد متى يجب ترميز الفيديو. سيتم دائمًا ترميز مقاطع الفيديو HDR (ما لم يتم تعطيل الترميز).", "transcoding_two_pass_encoding": "الترميز بمرورين", @@ -395,7 +387,6 @@ "archive_or_unarchive_photo": "أرشفة الصورة أو إلغاء أرشفتها", "archive_size": "حجم الأرشيف", "archive_size_description": "تكوين حجم الأرشيف للتنزيلات (بالجيجابايت)", - "archived": "", "archived_count": "{count, plural, other {الأرشيف #}}", "are_these_the_same_person": "هل هؤلاء هم نفس الشخص؟", "are_you_sure_to_do_this": "هل انت متأكد من أنك تريد أن تفعل هذا؟", @@ -445,10 +436,6 @@ "cannot_merge_people": "لا يمكن دمج الأشخاص", "cannot_undo_this_action": "لا يمكنك التراجع عن هذا الإجراء!", "cannot_update_the_description": "لا يمكن تحديث الوصف", - "cant_apply_changes": "", - "cant_get_faces": "", - "cant_search_people": "", - "cant_search_places": "", "change_date": "غيّر التاريخ", "change_expiration_time": "تغيير وقت انتهاء الصلاحية", "change_location": "غيّر الموقع", @@ -480,6 +467,7 @@ "confirm": "تأكيد", "confirm_admin_password": "تأكيد كلمة مرور المسؤول", "confirm_delete_shared_link": "هل أنت متأكد أنك تريد حذف هذا الرابط المشترك؟", + "confirm_keep_this_delete_others": "سيتم حذف جميع الأصول الأخرى في المجموعة باستثناء هذا الأصل. هل أنت متأكد من أنك تريد المتابعة؟", "confirm_password": "تأكيد كلمة المرور", "contain": "محتواة", "context": "السياق", @@ -529,6 +517,7 @@ "delete_key": "حذف المفتاح", "delete_library": "حذف المكتبة", "delete_link": "حذف الرابط", + "delete_others": "حذف الأخرى", "delete_shared_link": "حذف الرابط المشترك", "delete_tag": "حذف العلامة", "delete_tag_confirmation_prompt": "هل أنت متأكد أنك تريد حذف العلامة {tagName}؟", @@ -562,13 +551,6 @@ "duplicates": "التكرارات", "duplicates_description": "قم بحل كل مجموعة من خلال الإشارة إلى التكرارات، إن وجدت", "duration": "المدة", - "durations": { - "days": "", - "hours": "", - "minutes": "", - "months": "", - "years": "" - }, "edit": "تعديل", "edit_album": "تعديل الألبوم", "edit_avatar": "تعديل الصورة الشخصية", @@ -593,8 +575,6 @@ "editor_crop_tool_h2_aspect_ratios": "نسب العرض إلى الارتفاع", "editor_crop_tool_h2_rotation": "التدوير", "email": "البريد الإلكتروني", - "empty": "", - "empty_album": "", "empty_trash": "أفرغ سلة المهملات", "empty_trash_confirmation": "هل أنت متأكد أنك تريد إفراغ سلة المهملات؟ سيؤدي هذا إلى إزالة جميع المحتويات الموجودة في سلة المهملات بشكل نهائي من Immich.\nلا يمكنك التراجع عن هذا الإجراء!", "enable": "تفعيل", @@ -628,6 +608,7 @@ "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_people": "فشل تحميل الأشخاص", @@ -655,8 +636,6 @@ "unable_to_change_location": "غير قادر على تغيير الموقع", "unable_to_change_password": "غير قادر على تغيير كلمة المرور", "unable_to_change_visibility": "غير قادر على تغيير الظهور لـ {count, plural, one {# شخص} other {# أشخاص}}", - "unable_to_check_item": "", - "unable_to_check_items": "", "unable_to_complete_oauth_login": "غير قادر على إكمال تسجيل الدخول عبر OAuth", "unable_to_connect": "غير قادر على الإتصال", "unable_to_connect_to_server": "غير قادر على الإتصال بالسيرفر", @@ -697,12 +676,10 @@ "unable_to_remove_album_users": "تعذر إزالة المستخدمين من الألبوم", "unable_to_remove_api_key": "تعذر إزالة مفتاح API", "unable_to_remove_assets_from_shared_link": "غير قادر على إزالة المحتويات من الرابط المشترك", - "unable_to_remove_comment": "", "unable_to_remove_deleted_assets": "غير قادر على إزالة الملفات غير المتصلة", "unable_to_remove_library": "غير قادر على إزالة المكتبة", "unable_to_remove_partner": "غير قادر على إزالة الشريك", "unable_to_remove_reaction": "غير قادر على إزالة رد الفعل", - "unable_to_remove_user": "", "unable_to_repair_items": "غير قادر على إصلاح العناصر", "unable_to_reset_password": "غير قادر على إعادة تعيين كلمة المرور", "unable_to_resolve_duplicate": "غير قادر على حل التكرارات", @@ -732,10 +709,6 @@ "unable_to_update_user": "غير قادر على تحديث المستخدم", "unable_to_upload_file": "تعذر رفع الملف" }, - "every_day_at_onepm": "", - "every_night_at_midnight": "", - "every_night_at_twoam": "", - "every_six_hours": "", "exif": "Exif (صيغة ملف صوري قابل للتبادل)", "exit_slideshow": "خروج من العرض التقديمي", "expand_all": "توسيع الكل", @@ -750,33 +723,27 @@ "external": "خارجي", "external_libraries": "المكتبات الخارجية", "face_unassigned": "غير معين", - "failed_to_get_people": "", "favorite": "مفضل", "favorite_or_unfavorite_photo": "تفضيل أو إلغاء تفضيل الصورة", "favorites": "المفضلة", - "feature": "", "feature_photo_updated": "تم تحديث الصورة المميزة", - "featurecollection": "", "features": "الميزات", "features_setting_description": "إدارة ميزات التطبيق", "file_name": "إسم الملف", "file_name_or_extension": "اسم الملف أو امتداده", "filename": "اسم الملف", - "files": "", "filetype": "نوع الملف", "filter_people": "تصفية الاشخاص", "find_them_fast": "يمكنك العثور عليها بسرعة بالاسم من خلال البحث", "fix_incorrect_match": "إصلاح المطابقة غير الصحيحة", "folders": "المجلدات", "folders_feature_description": "تصفح عرض المجلد للصور ومقاطع الفيديو الموجودة على نظام الملفات", - "force_re-scan_library_files": "فرض إعادة فحص جميع ملفات المكتبة", "forward": "إلى الأمام", "general": "عام", "get_help": "الحصول على المساعدة", "getting_started": "البدء", "go_back": "الرجوع للخلف", "go_to_search": "اذهب إلى البحث", - "go_to_share_page": "انتقل إلى صفحة المشاركة", "group_albums_by": "تجميع الألبومات حسب...", "group_no": "بدون تجميع", "group_owner": "تجميع حسب المالك", @@ -802,10 +769,6 @@ "image_alt_text_date_place_2_people": "{isVideo, select, true {Video} other {Image}} تم التقاطها في {city}، {country} مع {person1} و{person2} في {date}", "image_alt_text_date_place_3_people": "{isVideo, select, true {Video} other {Image}} تم التقاطها في {city}، {country} مع {person1}، {person2}، و{person3} في {date}", "image_alt_text_date_place_4_or_more_people": "{isVideo, select, true {Video} other {Image}} تم التقاطها في {city}, {country} with {person1}, {person2}, مع {additionalCount, number} آخرين في {date}", - "image_alt_text_people": "{count, plural, =1 {مع {person1}} =2 {مع {person1} و {person2}} =3 {مع {person1} و {person2} و {person3}} other {مع {person1} و {person2} و {others, number} آخرين}}", - "image_alt_text_place": "في {city}, {country}", - "image_taken": "{isVideo, select, true {تم التقاط الفيديو} other {تم التقاط الصورة}}", - "img": "", "immich_logo": "شعار immich", "immich_web_interface": "واجهة ويب immich", "import_from_json": "استيراد من JSON", @@ -826,10 +789,11 @@ "invite_people": "دعوة الأشخاص", "invite_to_album": "دعوة إلى الألبوم", "items_count": "{count, plural, one {# عنصر} other {# عناصر}}", - "job_settings_description": "", "jobs": "الوظائف", "keep": "احتفظ", "keep_all": "احتفظ بالكل", + "keep_this_delete_others": "احتفظ بهذا، واحذف الآخرين", + "kept_this_deleted_others": "تم الاحتفاظ بهذا الأصل وحذف {count, plural, one {# asset} other {# assets}}", "keyboard_shortcuts": "اختصارات لوحة المفاتيح", "language": "اللغة", "language_setting_description": "اختر لغتك المفضلة", @@ -841,31 +805,6 @@ "level": "المستوى", "library": "مكتبة", "library_options": "خيارات المكتبة", - "license_account_info": "حسابك مرخص", - "license_activated_subtitle": "شكرا بدعمك لـ Immich وبرمجيات المصدر المفتوح", - "license_activated_title": "رخصتك نُشطت بنجاح", - "license_button_activate": "تنشيط", - "license_button_buy": "شراء", - "license_button_buy_license": "اشتر رخصة", - "license_button_select": "إختر", - "license_failed_activation": "فشل في تفعيل الترخيص. يرجى التحقق من بريدك الإلكتروني للحصول على مفتاح الترخيص الصحيح!", - "license_individual_description_1": "رخصة واحدة لكل مستخدم على أي خادم", - "license_individual_title": "رخصة فردية", - "license_info_licensed": "مُرَخص", - "license_info_unlicensed": "غير مُرَخص", - "license_input_suggestion": "لديك رخصة؟ أدخِل الرمز بالأسفل", - "license_license_subtitle": "اشتر رخصةً لدعم Immich", - "license_license_title": "الرخصة", - "license_lifetime_description": "رخصة مدى الحياة", - "license_per_server": "لكل خادم", - "license_per_user": "لكل مستحدم", - "license_server_description_1": "رخصة واحدة لكل خادم", - "license_server_description_2": "رخصة لكل المستخدمين على الخادم", - "license_server_title": "رخصة خادم", - "license_trial_info_1": "أنت تستخدم نسخةً غير مرخصة ل Immich", - "license_trial_info_2": "لقد استخدمتَ Immich تقريبا لمدة", - "license_trial_info_3": "{accountAge, plural, one {# يوم} other {# أيام}}", - "license_trial_info_4": "يُرجى التفكير في شراء رخصة لدعم التطوير المستمر للخدمة", "light": "المضيئ", "like_deleted": "تم حذف الإعجاب", "link_motion_video": "رابط فيديو الحركة", @@ -887,6 +826,7 @@ "look": "الشكل", "loop_videos": "تكرار مقاطع الفيديو", "loop_videos_description": "فَعْل لتكرار مقطع فيديو تلقائيًا في عارض التفاصيل.", + "main_branch_warning": "أنت تستخدم إصداراً تطويرياً؛ ونحن نوصي بشدة باستخدام إصدار النشر!", "make": "صنع", "manage_shared_links": "إدارة الروابط المشتركة", "manage_sharing_with_partners": "إدارة المشاركة مع الشركاء", @@ -969,7 +909,6 @@ "onboarding_welcome_user": "مرحبا، {user}", "online": "متصل", "only_favorites": "المفضلة فقط", - "only_refreshes_modified_files": "تحديث الملفات المعدلة فقط", "open_in_map_view": "فتح في عرض الخريطة", "open_in_openstreetmap": "فتح في OpenStreetMap", "open_the_search_filters": "افتح مرشحات البحث", @@ -1007,7 +946,6 @@ "people_edits_count": "تم تعديل {count, plural, one {# شخص } other {# أشخاص }}", "people_feature_description": "تصفح الصور ومقاطع الفيديو المجمعة حسب الأشخاص", "people_sidebar_description": "عرض رابط للأشخاص في الشريط الجانبي", - "perform_library_tasks": "", "permanent_deletion_warning": "تحذير الحذف الدائم", "permanent_deletion_warning_setting_description": "إظهار تحذير عند حذف المحتويات نهائيًا", "permanently_delete": "حذف بشكل دائم", @@ -1029,7 +967,6 @@ "play_memories": "تشغيل الذكريات", "play_motion_photo": "تشغيل الصور المتحركة", "play_or_pause_video": "تشغيل الفيديو أو إيقافه مؤقتًا", - "point": "", "port": "المنفذ", "preset": "الإعداد المسبق", "preview": "معاينة", @@ -1074,12 +1011,10 @@ "purchase_server_description_2": "حالة الداعم", "purchase_server_title": "الخادم", "purchase_settings_server_activated": "يتم إدارة مفتاح منتج الخادم من قبل مدير النظام", - "range": "", "rating": "تقييم نجمي", "rating_clear": "مسح التقييم", "rating_count": "{count, plural, one {# نجمة} other {# نجوم}}", "rating_description": "‫‌اعرض تقييم EXIF في لوحة المعلومات", - "raw": "", "reaction_options": "خيارات رد الفعل", "read_changelog": "قراءة سجل التغيير", "reassign": "إعادة التعيين", @@ -1124,7 +1059,6 @@ "reset": "إعادة ضبط", "reset_password": "إعادة تعيين كلمة المرور", "reset_people_visibility": "إعادة ضبط ظهور الأشخاص", - "reset_settings_to_default": "", "reset_to_default": "إعادة التعيين إلى الافتراضي", "resolve_duplicates": "معالجة النسخ المكررة", "resolved_all_duplicates": "تم حل جميع التكرارات", @@ -1144,9 +1078,7 @@ "saved_settings": "تم حفظ الإعدادات", "say_something": "قل شيئًا", "scan_all_libraries": "فحص كل المكتبات", - "scan_all_library_files": "إعادة فحص كافة ملفات المكتبة", "scan_library": "مسح", - "scan_new_library_files": "فحص ملفات المكتبة الجديدة", "scan_settings": "إعدادات الفحص", "scanning_for_album": "جارٍ الفحص عن ألبوم...", "search": "بحث", @@ -1189,7 +1121,6 @@ "selected_count": "{count, plural, other {# محددة }}", "send_message": "أرسل رسالة", "send_welcome_email": "أرسل بريدًا إلكترونيًا ترحيبيًا", - "server": "الخادم", "server_offline": "الخادم غير متصل", "server_online": "الخادم متصل", "server_stats": "إحصائيات الخادم", @@ -1294,6 +1225,7 @@ "they_will_be_merged_together": "سيتم دمجهم معًا", "third_party_resources": "موارد الطرف الثالث", "time_based_memories": "ذكريات استنادًا للوقت", + "timeline": "الخط الزمني", "timezone": "المنطقة الزمنية", "to_archive": "أرشفة", "to_change_password": "تغيير كلمة المرور", @@ -1303,7 +1235,7 @@ "to_trash": "حذف", "toggle_settings": "الإعدادات", "toggle_theme": "تبديل المظهر الداكن", - "toggle_visibility": "تبديل الرؤية", + "total": "الإجمالي", "total_usage": "الاستخدام الإجمالي", "trash": "المهملات", "trash_all": "نقل الكل إلى سلة المهملات", @@ -1313,12 +1245,10 @@ "trashed_items_will_be_permanently_deleted_after": "سيتم حذفُ العناصر المحذوفة نِهائيًا بعد {days, plural, one {# يوم} other {# أيام }}.", "type": "النوع", "unarchive": "أخرج من الأرشيف", - "unarchived": "", "unarchived_count": "{count, plural, other {غير مؤرشفة #}}", "unfavorite": "أزل التفضيل", "unhide_person": "أظهر الشخص", "unknown": "غير معروف", - "unknown_album": "", "unknown_year": "سنة غير معروفة", "unlimited": "غير محدود", "unlink_motion_video": "إلغاء ربط فيديو الحركة", @@ -1350,13 +1280,13 @@ "use_custom_date_range": "استخدم النطاق الزمني المخصص بدلاً من ذلك", "user": "مستخدم", "user_id": "معرف المستخدم", - "user_license_settings": "رخصة", - "user_license_settings_description": "ادر رخصتك", "user_liked": "قام {user} بالإعجاب {type, select, photo {بهذه الصورة} video {بهذا الفيديو} asset {بهذا المحتوى} other {بها}}", "user_purchase_settings": "الشراء", "user_purchase_settings_description": "إدارة عملية الشراء الخاصة بك", "user_role_set": "قم بتعيين {user} كـ {role}", "user_usage_detail": "تفاصيل استخدام المستخدم", + "user_usage_stats": "إحصائيات استخدام الحساب", + "user_usage_stats_description": "عرض إحصائيات استخدام الحساب", "username": "اسم المستخدم", "users": "المستخدمين", "utilities": "أدوات", @@ -1364,7 +1294,7 @@ "variables": "المتغيرات", "version": "الإصدار", "version_announcement_closing": "صديقك، أليكس", - "version_announcement_message": "مرحباً يا صديقي، هنالك نسخة جديدة من التطبيق. خذ وقتك لزيارة ملاحظات الإصدار والتأكد من أن ملف docker-compose.yml وإعداد .env مُحدّثين لتجنب أي إعدادات خاطئة، خاصةً إذا كنت تستخدم WatchTower أو أي آلية تقوم بتحديث التطبيق تلقائياً.", + "version_announcement_message": "مرحبًا! يتوفر إصدار جديد من Immich. يُرجى تخصيص بعض الوقت لقراءة ملاحظات الإصدار للتأكد من تحديث إعداداتك لمنع أي أخطاء في التكوين، خاصة إذا كنت تستخدم WatchTower أو أي آلية تتولى تحديث مثيل Immich الخاص بك تلقائيًا.", "version_history": "تاريخ الإصدار", "version_history_item": "تم تثبيت {version} في {date}", "video": "فيديو", @@ -1378,10 +1308,10 @@ "view_all_users": "عرض كافة المستخدمين", "view_in_timeline": "عرض في الجدول الزمني", "view_links": "عرض الروابط", + "view_name": "عرض", "view_next_asset": "عرض المحتوى التالي", "view_previous_asset": "عرض المحتوى السابق", "view_stack": "عرض التكديس", - "viewer": "", "visibility_changed": "الرؤية تغيرت لـ {count, plural, one {شخص واحد} other {# عدة أشخاص}}", "waiting": "في الانتظار", "warning": "تحذير", diff --git a/i18n/az.json b/i18n/az.json index 39ce318fa80ff..7848462414273 100644 --- a/i18n/az.json +++ b/i18n/az.json @@ -1,8 +1,10 @@ { - "about": "Haqqında", + "about": "Yenilə", "account": "Hesab", "account_settings": "Hesab parametrləri", "acknowledge": "Təsdiq et", + "action": "Əməliyyat", + "actions": "Əməliyyatlar", "active": "Aktiv", "activity": "Fəaliyyət", "add": "Əlavə et", @@ -10,9 +12,12 @@ "add_a_location": "Məkan əlavə et", "add_a_name": "Ad əlavə et", "add_a_title": "Başlıq əlavə et", + "add_exclusion_pattern": "İstisna nümunəsi əlavə et", + "add_import_path": "Import yolunu əlavə et", "add_location": "Məkanı əlavə et", "add_more_users": "Daha çox istifadəçi əlavə et", "add_partner": "Partnyor əlavə et", + "add_path": "Yol əlavə et", "add_photos": "Şəkilləri əlavə et", "add_to": "... əlavə et", "add_to_album": "Albom əlavə et", @@ -26,7 +31,11 @@ "authentication_settings_disable_all": "Bütün giriş etmə metodlarını söndürmək istədiyinizdən əminsinizmi? Giriş etmə funksiyası tamamilə söndürüləcəkdir.", "authentication_settings_reenable": "Yenidən aktiv etmək üçün Server Əmri -ni istifadə edin.", "background_task_job": "Arxa plan tapşırıqları", + "backup_database_enable_description": "Verilənlər bazasının ehtiyat nüsxələrini aktiv et", + "backup_settings": "Ehtiyat Nüsxə Parametrləri", + "backup_settings_description": "Verilənlər bazasının ehtiyat nüsxə parametrlərini idarə et", "check_all": "Hamısını yoxla", + "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", "confirm_user_password_reset": "{user} adlı istifadəçinin şifrəsini sıfırlamaq istədiyinizdən əminmisiniz?", @@ -54,9 +63,6 @@ "jobs_delayed": "{jobCount, plural, other {# gecikməli}}", "jobs_failed": "{jobCount, plural, other {# uğursuz}}", "library_created": "{library} kitabxanası yaradıldı", - "library_cron_expression": "Kron zamanlaması", - "library_cron_expression_description": "Kron zamanlama formatından istifadə edərək skan intervalının təyin edin. Daha çox məlumat üçün Crontab Guru", - "library_cron_expression_presets": "Kron zamanlamasının ilkin parametrləri", "library_deleted": "Kitabxana silindi", "library_import_path_description": "İdxal olunacaq qovluöu seçin. Bu qovluq, alt qovluqlar daxil olmaqla şəkil və videolar üçün skan ediləcəkdir.", "library_scanning": "Periodik skan", diff --git a/i18n/be.json b/i18n/be.json index 0967ef424bce6..8377ec538381c 100644 --- a/i18n/be.json +++ b/i18n/be.json @@ -1 +1,115 @@ -{} +{ + "about": "Аб", + "account": "Уліковы запіс", + "account_settings": "Налады ўліковага запісу", + "acknowledge": "Пацвердзіць", + "action": "Дзеянне", + "actions": "Дзеянні", + "active": "Актыўны", + "activity": "Актыўнасць", + "activity_changed": "Актыўнасць {enabled, select, true {уключана} other {адключана}}", + "add": "Дадаць", + "add_a_description": "Дадаць апісанне", + "add_a_location": "Дадаць месца", + "add_a_name": "Дадаць імя", + "add_a_title": "Дадаць загаловак", + "add_exclusion_pattern": "Дадаць шаблон выключэння", + "add_import_path": "Дадаць шлях імпарту", + "add_location": "Дадайце месца", + "add_more_users": "Дадаць больш карыстальнікаў", + "add_partner": "Дадаць партнёра", + "add_path": "Дадаць шлях", + "add_photos": "Дадаць фота", + "add_to": "Дадаць у...", + "add_to_album": "Дадаць у альбом", + "add_to_shared_album": "Дадаць у агульны альбом", + "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/**\".", + "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_settings": "Налады рэзервовага капіявання", + "backup_settings_description": "Кіраванне наладкамі рэзервовага капіявання базы даных", + "check_all": "Праверыць усе", + "cleared_jobs": "Ачышчаны заданні для: {job}", + "config_set_by_file": "Канфігурацыя ў зараз усталявана праз файл канфігурацыі", + "confirm_delete_library": "Вы ўпэўнены што жадаеце выдаліць {library} бібліятэку?", + "confirm_delete_library_assets": "Вы ўпэўнены, што хочаце выдаліць гэтую бібліятэку? Гэта прывядзе да выдалення {count, plural, one {# актыву} other {усіх # актываў}}, якія змяшчаюцца ў Immich, і гэта дзеянне немагчыма будзе адмяніць. Файлы застануцца на дыску.", + "confirm_email_below": "Каб пацвердзіць, увядзіце \"{email}\" ніжэй", + "confirm_reprocess_all_faces": "Вы ўпэўнены, што хочаце пераапрацаваць усе твары? Гэта таксама прывядзе да выдалення імя людзей.", + "confirm_user_password_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", + "exclusion_pattern_description": "Шаблоны выключэння дазваляюць ігнараваць файлы і папкі пры сканаванні вашай бібліятэкі. Гэта карысна, калі ў вас ёсць папкі, якія змяшчаюць файлы, якія вы не хочаце імпартаваць, напрыклад, файлы RAW.", + "external_library_created_at": "Знешняя бібліятэка (створана {date})", + "external_library_management": "Кіраванне знешняй бібліятэкай", + "face_detection": "Выяўленне твараў", + "force_delete_user_warning": "ПАПЯРЭДЖАННЕ: Гэта дзеянне неадкладна выдаліць карыстальніка і ўсе аб'екты. Гэта дзеянне не можа быць адроблена і файлы немагчыма будзе аднавіць.", + "image_format": "Фармат", + "image_preview_title": "Налады папярэдняга прагляду", + "image_quality": "Якасць", + "image_resolution": "Раздзяляльнасць", + "image_settings": "Налады відарыса", + "image_settings_description": "Кіруйце якасцю і раздзяляльнасцю сгенерыраваных відарысаў" + }, + "timeline": "Хроніка", + "total": "Усяго", + "user": "Карыстальнік", + "user_id": "ID карыстальніка", + "user_purchase_settings": "Купля", + "user_purchase_settings_description": "Кіруйце пакупкамі", + "user_role_set": "Прызначыць {user} як {role}", + "user_usage_detail": "Падрабязнасці выкарыстання карыстальнікам", + "user_usage_stats": "Статыстыка карыстання ўліковага запісу", + "user_usage_stats_description": "Прагледзець статыстыку карыстання ўліковага запісу", + "username": "Імя карыстальніка", + "users": "Карыстальнікі", + "utilities": "Утыліты", + "validate": "Праверыць", + "variables": "Пераменныя", + "version": "Версія", + "version_announcement_closing": "Твой сябар, Алекс", + "version_announcement_message": "Вітаем! Даступная новая версія Immich. Калі ласка, знайдзіце час, каб прачытаць нататкі да выпуску, каб пераканацца, што ваша налада актуальная і пазбегнуць магчымых памылак канфігурацыі, асабліва калі вы карыстаецеся WatchTower або іншымі механізмамі, якія аўтаматычна абнаўляюць вашу інстанцыю Immich.", + "version_history": "Гісторыя версій", + "version_history_item": "Усталявана версія {version} на {date}", + "video": "Відэа", + "video_hover_setting": "Прайграванне мініяцюры відэа пры навядзенні курсора", + "video_hover_setting_description": "Прайграванне мініяцюры відэа пры навядзенні курсора на элемент. Нават калі функцыя адключана, прайграванне можна пачаць, навёўшы курсор на значок прайгравання.", + "videos": "Відэа", + "videos_count": "{count, plural, one {# відэа} астатнія {# відэа}}", + "view": "Прагляд", + "view_album": "Праглядзець альбом", + "view_all": "Праглядзець усё", + "view_all_users": "Праглядзець усех карыстальнікаў", + "view_in_timeline": "Паглядзець хроніку", + "view_links": "Праглядзець спасылкі", + "view_name": "Прагледзець", + "view_next_asset": "Паказаць наступны аб'ект", + "view_previous_asset": "Праглядзець папярэдні аб'ект", + "view_stack": "Прагляд стэка", + "visibility_changed": "Відзімасць змянілася для {count, plural, one {# чалавек(-аў)} астатніх {# чалавек}}", + "waiting": "Чакаюць", + "warning": "Папярэджанне", + "week": "Тыдзень", + "welcome": "Вітаем", + "welcome_to_immich": "Вітаем у Immich", + "year": "Год", + "years_ago": "{years, plural, one {# год} other {# гадоў}} таму", + "yes": "Так", + "you_dont_have_any_shared_links": "У вас няма абагуленых спасылак", + "zoom_image": "Павялічыць відарыс" +} diff --git a/i18n/bg.json b/i18n/bg.json index fde9434e304a1..b0ab195289f0d 100644 --- a/i18n/bg.json +++ b/i18n/bg.json @@ -23,17 +23,23 @@ "add_to": "Добави към...", "add_to_album": "Добави към албум", "add_to_shared_album": "Добави към споделен албум", + "add_url": "Добави URL", "added_to_archive": "Добавено към архива", "added_to_favorites": "Добавени към любимите ви", "added_to_favorites_count": "Добавени {count, number} към любими", "admin": { "add_exclusion_pattern_description": "Добави модели за изключване. Поддържа се \"globbing\" с помощта на *, ** и ?. За да игнорирате всички файлове в директория с име \"Raw\", използвайте \"**/Raw/**\". За да игнорирате всички файлове, завършващи на \".tif\", използвайте \"**/*.tif\". За да игнорирате абсолютен път, използвайте \"/path/to/ignore/**\".", - "asset_offline_description": "Този външен библиотечен елемент не може да бъде открит на диска и е преместен в кошчето за боклук. Ако файлът е преместен в библиотеката, проверете вашата история за нов съответстващ елемент. За да възстановите елемента, моля проверете дали файловият път отдолу може да бъде достъпен от Immich и сканирайте библиотеката.", + "asset_offline_description": "Този външен библиотечен елемент не може да бъде открит на диска и е преместен в кошчето за боклук. Ако файлът е преместен в библиотеката, проверете вашата история за нов съответстващ елемент. За да възстановите елемента, моля проверете дали файловият път отдолу може да бъде достъпен от Immich и сканирайте библиотеката.", "authentication_settings": "Настройки за удостоверяване", "authentication_settings_description": "Управление на парола, OAuth и други настройки за удостоверяване", "authentication_settings_disable_all": "Сигурни ли сте, че искате да деактивирате всички методи за вписване? Вписването ще бъде напълно деактивирано.", "authentication_settings_reenable": "За да реактивирате, изполвайте Server Command.", "background_task_job": "Процеси на заден фон", + "backup_database": "Резервна База данни", + "backup_database_enable_description": "Разрешаване на резервни копия на базата данни", + "backup_keep_last_amount": "Брой резервни копия за запазване", + "backup_settings": "Настройка на резервни копия", + "backup_settings_description": "Управление на настройките за резервно копие на базата данни", "check_all": "Провери всичко", "cleared_jobs": "Изчистени задачи от тип: {job}", "config_set_by_file": "Конфигурацията е зададена от файл", @@ -43,6 +49,9 @@ "confirm_reprocess_all_faces": "Сигурни ли сте, че искате да се обработят лицата отново? Това ще изчисти всички именувани хора.", "confirm_user_password_reset": "Сигурни ли сте, че искате да нулирате паролата на {user}?", "create_job": "Създайте задача", + "cron_expression": "Cron израз", + "cron_expression_description": "Настрой интервала на сканиране използвайки cron формата. За повече информация Crontab Guru", + "cron_expression_presets": "Примерни Cron изрази", "disable_login": "Изключете вписването", "duplicate_detection_job_description": "Стартиране машинно обучение на ресурси, за откриване на подобни изображения. Разчита на Интелигентно Търсене", "exclusion_pattern_description": "Модели за изключване позволяват да игнорирате файлове и папки, когато сканирате вашата библиотека. Това е потребно, ако имате папки, които съдържат файлове, които не искате да импортирате. Примерно - RAW файлове.", @@ -54,21 +63,23 @@ "failed_job_command": "Командата {command} е неуспешна за задача: {job}", "force_delete_user_warning": "ВНИМАНИЕ: Това веднага ще изтрие потребителя и всичките му ресурси. Действието е необратимо и файловете не могат да бъдат възстановени.", "forcing_refresh_library_files": "Принуждаване обновяване на всички файлове в библиотеката", + "image_format": "Формат", "image_format_description": "WebP създава по-малки файлове от JPEG, но ги кодира по-бавно.", "image_prefer_embedded_preview": "Предпочитане на вградените прегледи", "image_prefer_embedded_preview_setting_description": "Използване на вградените прегледи в RAW снимките като вход за обработка на изображенията, когато има такива. Това може да доведе до по-точни цветове за някои изображения, но качеството на прегледите зависи от камерата и изображението може да има повече компресионни артефакти.", "image_prefer_wide_gamut": "Предпочитане на широка гама", "image_prefer_wide_gamut_setting_description": "Използване на Display P3 за миниатюри. Това запазва по-добре жизнеността на изображенията с широки цветови пространства, но изображенията може да изглеждат по различен начин на стари устройства със стара версия на браузъра. sRGB изображенията се запазват като sRGB, за да се избегнат цветови промени.", - "image_preview_format": "Формат на прегледите", - "image_preview_resolution": "Резолюция на прегледите", - "image_preview_resolution_description": "Използва се при разглеждане на единична снимка и за машинно обучение. По-високите резолюции могат да запазят повече детайли, но отнемат повече време за кодиране, имат по-големи размери на файловете и могат да намалят отзивчивостта на приложението.", + "image_preview_description": "Среден размер на изображението с премахнати метаданни, използвано при преглед на един актив и за машинно обучение", + "image_preview_quality_description": "Качество на предварителния преглед от 1 до 100. По-високата стойност е по-добра, но води до по-големи файлове и може да намали бързодействието на приложението. Задаването на ниска стойност може да повлияе на качеството на машинното обучение.", + "image_preview_title": "Настойки на прегледа", "image_quality": "Качество", - "image_quality_description": "Качество на изображението от 1-100. По-голяма стойност води до по-добро качество, но създава по-големи файлове. Тази настройка засяга изображенията от тип преглед и миниатюра.", + "image_resolution": "Резолюция", + "image_resolution_description": "По-високите резолюции могат да запазят повече детайли, но изискват повече време за кодиране, имат по-големи размери на файловете и могат да намалят бързодействието на приложението.", "image_settings": "Настройки за изображенията", "image_settings_description": "Управляване качеството и резолюцията на създадените изображения", - "image_thumbnail_format": "Формат на миниатюрните изображения", - "image_thumbnail_resolution": "Резолюция на миниатюрните изображения", - "image_thumbnail_resolution_description": "Използва се при разглеждане на групи от снимки (основна времева линия, изглед на албум и др.). По-високите резолюции могат да запазят повече детайли, но отнемат повече време за кодиране, имат по-големи размери на файловете и могат да намалят отзивчивостта на приложението.", + "image_thumbnail_description": "Малка миниатюра с премахнати метаданни, използвана при преглед на групи снимки, като основния екран", + "image_thumbnail_quality_description": "Качество на миниатюрата от 1 до 100. По-високата стойност е по-добра, но води до по-големи файлове и може да намали бързодействието на приложението.", + "image_thumbnail_title": "Настройки на миниатюрите", "job_concurrency": "Паралелност на {job}", "job_created": "Задачата е създадена", "job_not_concurrency_safe": "Тази задача не е безопасна за паралелно изпълнение.", @@ -78,9 +89,6 @@ "jobs_delayed": "{jobCount, plural, other {# delayed}}", "jobs_failed": "{jobCount, plural, other {# failed}}", "library_created": "Създадена библиотека: {library}", - "library_cron_expression": "Cron израз", - "library_cron_expression_description": "Задайте интервала за сканиране чрез cron интервал. За повече информация, вижте например Crontab Guru", - "library_cron_expression_presets": "Предварителни настройки на Cron израза", "library_deleted": "Библиотека е изтрита", "library_import_path_description": "Посочете папка за импортиране. Тази папка, включително подпапките, ще бъдат сканирани за изображения и видеоклипове.", "library_scanning": "Периодично сканиране", @@ -123,7 +131,7 @@ "machine_learning_smart_search_description": "Семантично търсене на изображения с помощта на CLIP вграждания", "machine_learning_smart_search_enabled": "Включване на Интелигентно Търсене", "machine_learning_smart_search_enabled_description": "Ако е деактивирано, изображенията няма да бъдат кодирани за Интелигентно Търсене.", - "machine_learning_url_description": "URL адрес на сървъра за машинно обучение", + "machine_learning_url_description": "URL на сървъра за машинно обучение. Ако са предоставени повече от един URL, всеки сървър ще бъде опитан един по един, докато един не отговори успешно, в реда от първия до последния", "manage_concurrency": "Управление на паралелност", "manage_log_settings": "Управление на настройките на записване", "map_dark_style": "Тъмен стил", @@ -199,11 +207,11 @@ "password_settings": "Вписване с парола", "password_settings_description": "Управление на настройките за влизане с парола", "paths_validated_successfully": "Всички пътища са валидирани успешно", + "person_cleanup_job": "Почистване на лица", "quota_size_gib": "Размер на квотата (GiB)", "refreshing_all_libraries": "Опресняване на всички библиотеки", "registration": "Администраторска регистрация", "registration_description": "Тъй като сте първият потребител в системата, ще бъдете назначен като администратор и ще отговаряте за административните задачи, а допълнителните потребители ще бъдат създадени от вас.", - "removing_deleted_files": "Премахване на офлайн файлове", "repair_all": "Поправяне на всичко", "repair_matched_items": "{count, plural, one {Съвпадащ елемент (#)} other {Съвпадащи елементи (#)}}", "repaired_items": "{count, plural, one {Поправен елемент (#)} other {Поправени елементи (#)}}", @@ -211,12 +219,12 @@ "reset_settings_to_default": "Възстановяване на настройките по подразбиране", "reset_settings_to_recent_saved": "Възстановяване на настройките до последните запазени настройки", "scanning_library": "Сканиране на библиотеката", - "scanning_library_for_changed_files": "Сканиране на библиотеката за променени файлове", - "scanning_library_for_new_files": "Сканиране на библиотеката за нови файлове", "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": "Поздравително съобщение", @@ -241,6 +249,17 @@ "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_settings_description": "Управление на шаблони за имейл известия", + "template_email_update_album": "Шаблон за актуализация на албум", + "template_email_welcome": "Шаблон за приветстващ имейл", + "template_settings": "Шаблони за известия", + "template_settings_description": "Управление на шаблони за известия.", "theme_custom_css_settings": "Персонализиран CSS", "theme_custom_css_settings_description": "Каскадните стилови таблици позволяват персонализиране на дизайна на Immich.", "theme_settings": "Настройки на темата", @@ -297,10 +316,8 @@ "transcoding_temporal_aq_description": "Само за NVENC. Повишава качеството на сцени с висока детайлност и ниско ниво на движение. Може да не е съвместимо с по-стари устройства.", "transcoding_threads": "Нишки", "transcoding_threads_description": "По-високите стойности водят до по-бързо разкодиране, но оставят по-малко място за сървъра да обработва други задачи, докато е активен. Тази стойност не трябва да надвишава броя на процесорните ядра. Увеличава максимално използването, ако е зададено на 0.", - "transcoding_tone_mapping": "", + "transcoding_tone_mapping": "Tone-mapping", "transcoding_tone_mapping_description": "Опитва се да запази външния вид на HDR видеоклипове, когато се преобразува в SDR. Всеки алгоритъм прави различни компромиси за цвят, детайлност и яркост. Hable запазва детайлите, Mobius запазва цвета, а Reinhard запазва яркостта.", - "transcoding_tone_mapping_npl": "", - "transcoding_tone_mapping_npl_description": "Цветовете ще бъдат коригирани, за да изглеждат нормално за дисплей с тази яркост. Противоинтуитивно, по-ниските стойности увеличават яркостта на видеото и обратно, тъй като компенсират яркостта на дисплея. 0 задава тази стойност автоматично.", "transcoding_transcode_policy": "Правила за транскодиране", "transcoding_transcode_policy_description": "Правила за това кога видеоклипът трябва да бъде транскодиран. HDR видеоклиповете винаги ще бъдат транскодирани (освен ако транскодирането е деактивирано).", "transcoding_two_pass_encoding": "Кодиране с двойно минаване", @@ -314,6 +331,7 @@ "trash_settings_description": "Управление на настройките на кошчето", "untracked_files": "Непроследени файлове", "untracked_files_description": "Тези файлове не се проследяват от приложението. Те могат да бъдат резултат от неуспешни премествания, прекъснати качвания или оставени поради грешка", + "user_cleanup_job": "Почистване на потребители", "user_delete_delay": "{user} aкаунтът и файловете на потребителя ще бъдат планирани за постоянно изтриване след {delay, plural, one {# ден} other {# дни}}.", "user_delete_delay_settings": "Забавяне на изтриване", "user_delete_delay_settings_description": "Брой дни след окончателно изтриване акаунта на потребителя. Задачата за изтриване на потребител се изпълнява в полунощ, за да се провери за потребители, които са готови за изтриване. Промените на тази настройка ще влязат в сила при следващото изпълнение.", @@ -338,6 +356,9 @@ "admin_password": "Администраторска парола", "administration": "Администрация", "advanced": "Разширено", + "age_months": "Възраст {months, plural, one {# month} other {# months}}", + "age_year_months": "Възраст 1 година, {months, plural, one {# month} other {# months}}", + "age_years": "{years, plural, other {Age #}}", "album_added": "Албумът е добавен", "album_added_notification_setting_description": "Получавайте известие по имейл, когато бъдете добавени към споделен албум", "album_cover_updated": "Обложката на албума е актуализирана", @@ -357,7 +378,7 @@ "album_user_removed": "Премахнат {user}", "album_with_link_access": "Нека всеки с линк вижда снимки и хора в този албум.", "albums": "Албуми", - "albums_count": "", + "albums_count": "{count, plural, one {{count, number} Album} other {{count, number} Albums}}", "all": "Всички", "all_albums": "Всички албуми", "all_people": "Всички хора", @@ -366,24 +387,44 @@ "allow_edits": "Позволяване на редакции", "allow_public_user_to_download": "Позволете на публичен потребител да може да изтегля", "allow_public_user_to_upload": "Позволете на публичния потребител да може да качва", + "anti_clockwise": "Обратно на часовниковата стрелка", "api_key": "API ключ", "api_key_description": "Тази стойност ще бъде показана само веднъж. Моля, не забравяйте да го копирате, преди да затворите прозореца.", "api_key_empty": "Името на вашия API ключ не трябва да е празно", "api_keys": "API ключове", "app_settings": "Настройки ма приложението", - "appears_in": "", + "appears_in": "Излиза в", "archive": "Архив", "archive_or_unarchive_photo": "Архивиране или деархивиране на снимка", "archive_size": "Размер на архива", "archive_size_description": "Конфигурирайте размера на архива за изтегляния (в GiB)", - "archived": "", + "archived_count": "{count, plural, other {Archived #}}", "are_these_the_same_person": "Това едно и също лице ли е?", + "are_you_sure_to_do_this": "Сигурни ли сте, че искате да направите това?", + "asset_added_to_album": "Добавено в албум", + "asset_adding_to_album": "Добавяне в албум...", + "asset_description_updated": "Описание на актива е обновено", + "asset_filename_is_offline": "Активът {filename} е офлайн", + "asset_has_unassigned_faces": "Активът има неразпределени лица", + "asset_hashing": "Хеширане...", "asset_offline": "Ресурсът е офлайн", + "asset_offline_description": "Този външен актив вече не се намира на диска. Моля, свържете се с администратора на Immich за помощ.", "asset_skipped": "Пропуснато", + "asset_skipped_in_trash": "В кошчето", "asset_uploaded": "Качено", "asset_uploading": "Качване...", "assets": "Ресурси", - "assets_moved_to_trash": "", + "assets_added_count": "Добавено {count, plural, one {# asset} other {# assets}}", + "assets_added_to_album_count": "Добавен(и) са {count, plural, one {# актив} other {# актива}} в албума", + "assets_added_to_name_count": "Добавен(и) са {count, plural, one {# актив} other {# актива}} към {hasName, select, true {{name}} other {нов албум}}", + "assets_count": "{count, plural, one {# актив} other {# актива}}", + "assets_moved_to_trash_count": "Преместен(и) са {count, plural, one {# актив} other {# актива}} в кошчето", + "assets_permanently_deleted_count": "Постоянно изтрит(и) са {count, plural, one {# актив} other {# актива}}", + "assets_removed_count": "Премахнат(и) са {count, plural, one {# актив} other {# актива}}", + "assets_restore_confirmation": "Сигурни ли сте, че искате да възстановите всички активи в кошчето? Не можете да отмените това действие! Имайте предвид, че активи, които са офлайн, не могат да бъдат възстановени по този начин.", + "assets_restored_count": "Възстановен(и) са {count, plural, one {# актив} other {# актива}}", + "assets_trashed_count": "Възстановен(и) са {count, plural, one {# файл} other {# файла}}", + "assets_were_part_of_album_count": "{count, plural, one {Файлът е} other {Файловете са}} вече част от албума", "authorized_devices": "Удостоверени устройства", "back": "Назад", "back_close_deselect": "Назад, затваряне или премахване на избора", @@ -391,9 +432,12 @@ "birthdate_saved": "Датата на раждане е запазена успешно", "birthdate_set_description": "Датата на раждане се използва за изчисляване на възрастта на този човек към момента на снимката.", "blurred_background": "Замъглен заден фон", - "bulk_delete_duplicates_confirmation": "", - "bulk_keep_duplicates_confirmation": "", - "bulk_trash_duplicates_confirmation": "", + "bugs_and_feature_requests": "Бъгове и заявки за функции", + "build": "Build", + "build_image": "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", "camera": "Камера", "camera_brand": "Марка на камерата", @@ -403,10 +447,6 @@ "cannot_merge_people": "Не може да обединява хора", "cannot_undo_this_action": "Не можете да отмените това действие!", "cannot_update_the_description": "Описанието не може да бъде актуализирано", - "cant_apply_changes": "", - "cant_get_faces": "", - "cant_search_people": "", - "cant_search_places": "", "change_date": "Промени датата", "change_expiration_time": "Променете времето на изтичане", "change_location": "Промени локацията", @@ -425,9 +465,11 @@ "clear_all_recent_searches": "Изчистете всички скорошни търсения", "clear_message": "Изчисти съобщението", "clear_value": "Изчисти стойността", + "clockwise": "По часовниковата стрелка", "close": "Затвори", "collapse": "Свиване", "collapse_all": "Свиване на всичко", + "color": "Цвят", "color_theme": "Цветова тема", "comment_deleted": "Коментарът е изтрит", "comment_options": "Опции за коментар", @@ -436,8 +478,9 @@ "confirm": "Потвърди", "confirm_admin_password": "Потвърждаване на паролата на администратора", "confirm_delete_shared_link": "Сигурни ли сте, че искате да изтриете тази споделена връзка?", + "confirm_keep_this_delete_others": "Всички останали файлове в стека ще бъдат изтрити, с изключение на този файл. Сигурни ли сте, че искате да продължите?", "confirm_password": "Потвърдете паролата", - "contain": "", + "contain": "В рамките на", "context": "Контекст", "continue": "Продължи", "copied_image_to_clipboard": "Изображението е копирано в клипборда.", @@ -450,7 +493,7 @@ "copy_password": "Копиране на парола", "copy_to_clipboard": "Копиране в клипборда", "country": "Държава", - "cover": "", + "cover": "Cover", "covers": "Обложка", "create": "Създай", "create_album": "Създай албум", @@ -459,7 +502,10 @@ "create_link_to_share": "Създаване на линк за споделяне", "create_link_to_share_description": "Позволете на всеки, който има линк, да види избраната(ите) снимка(и)", "create_new_person": "Създаване на ново лице", + "create_new_person_hint": "Присвойте избраните файлове на нов човек", "create_new_user": "Създаване на нов потребител", + "create_tag": "Създай таг", + "create_tag_description": "Създайте нов таг. За вложени тагове, моля, въведете пълния път на тага, включително наклонените черти.", "create_user": "Създай потребител", "created": "Създадено", "current_device": "Текущо устройство", @@ -473,7 +519,7 @@ "date_range": "Период от време", "day": "Ден", "deduplicate_all": "Дедупликиране на всички", - "default_locale": "", + "default_locale": "Локализация по подразбиране", "default_locale_description": "Форматиране на дати и числа в зависимост от местоположението на браузъра", "delete": "Изтрий", "delete_album": "Изтрий албум", @@ -482,14 +528,19 @@ "delete_key": "Изтрий ключ", "delete_library": "Изтрий библиотека", "delete_link": "Изтрий линк", + "delete_others": "Изтрий останалите", "delete_shared_link": "Изтриване на споделен линк", + "delete_tag": "Изтрий таг", + "delete_tag_confirmation_prompt": "Сигурни ли сте, че искате да изтриете таг {tagName}?", "delete_user": "Изтрий потребител", "deleted_shared_link": "Изтрит споделен линк", + "deletes_missing_assets": "Изтрива файлове, които липсват на диска", "description": "Описание", "details": "Детайли", "direction": "Посока", "disabled": "Изключено", "disallow_edits": "Забраняване на редакциите", + "discord": "Discord", "discover": "Открий", "dismiss_all_errors": "Отхвърляне на всички грешки", "dismiss_error": "Отхвърляне на грешка", @@ -498,15 +549,18 @@ "display_original_photos": "Показване на оригинални снимки", "display_original_photos_setting_description": "Показване на оригиналната снимка вместо миниатюри, когато оригиналният актив е съвместим с мрежата. Това може да доведе до по-бавни скорости на показване на снимки.", "do_not_show_again": "Не показвайте това съобщение отново", + "documentation": "Документация", "done": "Готово", "download": "Изтегли", + "download_include_embedded_motion_videos": "Вградени видеа", + "download_include_embedded_motion_videos_description": "Включете видеата, вградени в динамични снимки, като отделен файл", "download_settings": "Изтегли", "download_settings_description": "Управление на настройките, свързани с изтеглянето на файлове", "downloading": "Изтегляне", "downloading_asset_filename": "Изтегляне на файл {filename}", "drop_files_to_upload": "Пуснете файловете, за да ги качите", "duplicates": "Дубликати", - "duplicates_description": "", + "duplicates_description": "Изберете всяка група, като посочите кои, ако има такива, са дубликати", "duration": "Продължителност", "edit": "Редактиране", "edit_album": "Редактиране на албум", @@ -522,10 +576,15 @@ "edit_location": "Редактиране на местоположението", "edit_name": "Редактиране на име", "edit_people": "Редактиране на хора", + "edit_tag": "Редактирай таг", "edit_title": "Редактиране на заглавието", "edit_user": "Редактиране на потребител", "edited": "Редактирано", - "editor": "", + "editor": "Редактор", + "editor_close_without_save_prompt": "Промените няма да бъдат запазени", + "editor_close_without_save_title": "Затваряне на редактора?", + "editor_crop_tool_h2_aspect_ratios": "Съотношения на страните", + "editor_crop_tool_h2_rotation": "Завъртане", "email": "Имейл", "empty_trash": "Изпразване на кош", "empty_trash_confirmation": "Сигурни ли сте, че искате да изпразните кошчето? Това ще премахне всичко в кошчето за постоянно от Immich.\nНе можете да отмените това действие!", @@ -539,7 +598,9 @@ "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": "Не може да търси хора", @@ -558,19 +619,28 @@ "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": "Неуспешно зареждане на файлове", - "import_path_already_exists": "", + "failed_to_load_people": "Неуспешно зареждане на хора", + "failed_to_remove_product_key": "Неуспешно премахване на продуктовия ключ", + "failed_to_stack_assets": "Неуспешно подреждане на обекти", + "failed_to_unstack_assets": "Неуспешно премахване на подредбата на обекти", + "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": "Зададена е квота, по-голяма от размера на диска", - "repair_unable_to_check_items": "", - "unable_to_add_album_users": "", - "unable_to_add_comment": "", - "unable_to_add_exclusion_pattern": "", - "unable_to_add_import_path": "", - "unable_to_add_partners": "", + "repair_unable_to_check_items": "Неуспешно проверяване на {count, select, one {обект} other {обекти}}", + "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_favorite": "Не може да промени фаворит за актив", @@ -601,11 +671,12 @@ "unable_to_get_comments_number": "Не може да получи брой коментари", "unable_to_get_shared_link": "Неуспешно създаване на споделена връзка", "unable_to_hide_person": "Не може да скрие човек", - "unable_to_link_oauth_account": "", - "unable_to_load_album": "", - "unable_to_load_asset_activity": "", - "unable_to_load_items": "", - "unable_to_load_liked_status": "", + "unable_to_link_motion_video": "Неуспешно свързване на видео с движение", + "unable_to_link_oauth_account": "Неуспешно свързване на OAuth акаунт", + "unable_to_load_album": "Неуспешно зареждане на албум", + "unable_to_load_asset_activity": "Неуспешно зареждане на активност на обект", + "unable_to_load_items": "Неуспешно зареждане на обекти", + "unable_to_load_liked_status": "Неуспешно зареждане на статус на харесване", "unable_to_play_video": "", "unable_to_refresh_user": "", "unable_to_remove_album_users": "", @@ -650,7 +721,6 @@ "external": "Външно", "external_libraries": "Външни библиотеки", "face_unassigned": "Незададено", - "failed_to_get_people": "", "favorite": "Любим", "favorite_or_unfavorite_photo": "", "favorites": "Любими", @@ -662,14 +732,12 @@ "filter_people": "Филтриране на хора", "find_them_fast": "Намерете ги бързо по име с търсене", "fix_incorrect_match": "Поправяне на неправилно съвпадение", - "force_re-scan_library_files": "Принудително повторно сканиране на всички библиотечни файлове", "forward": "Напред", "general": "Общи", "get_help": "Помощ", "getting_started": "", "go_back": "Връщане назад", "go_to_search": "Преминаване към търсене", - "go_to_share_page": "", "group_albums_by": "Групирай албум по...", "group_owner": "Групиране по собственик", "group_year": "Групиране по година", @@ -685,7 +753,6 @@ "hour": "Час", "image": "Изображение", "image_alt_text_date": "на {date}", - "image_alt_text_place": "в {city}, {country}", "immich_logo": "Immich лого", "immich_web_interface": "", "import_from_json": "Импортиране от JSON", @@ -718,29 +785,6 @@ "level": "Ниво", "library": "Библиотека", "library_options": "Опции на библиотеката", - "license_account_info": "Вашият акаунт е лицензиран", - "license_activated_title": "Вашият лиценз е активиран успешно", - "license_button_activate": "Активирай", - "license_button_buy": "Купи", - "license_button_buy_license": "Купи лиценз", - "license_button_select": "Избери", - "license_failed_activation": "Неуспешно активиране на лиценз. Моля, проверете имейла си за правилния лицензен ключ!", - "license_individual_description_1": "1 лиценз за потребител на всеки сървър", - "license_individual_title": "Индивидуален лиценз", - "license_info_licensed": "Лицензиран", - "license_info_unlicensed": "Не лицензиран", - "license_input_suggestion": "Имате лиценз? Въведете ключа по-долу", - "license_license_subtitle": "Купете лиценз, за да подкрепите Immich", - "license_license_title": "ЛИЦЕНЗ", - "license_lifetime_description": "Доживотен лиценз", - "license_per_server": "За сървър", - "license_per_user": "За потребител", - "license_server_description_1": "1 лиценз за сървър", - "license_server_description_2": "Лиценз за всички потребители на сървъра", - "license_server_title": "Лиценз за сървър", - "license_trial_info_1": "Работите с нелицензирана версия на Immich", - "license_trial_info_2": "Използвали сте Immich за приблизително", - "license_trial_info_4": "Моля, помислете за закупуване на лиценз, за да подкрепите по-нататъшното развитие на услугата", "light": "Светло", "link_options": "Опции на линк за споделяне", "link_to_oauth": "", @@ -832,7 +876,6 @@ "onboarding_welcome_user": "Добре дошъл, {user}", "online": "Онлайн", "only_favorites": "Само любими", - "only_refreshes_modified_files": "Опреснява само модифицирани файлове", "open_the_search_filters": "Отваряне на филтрите за търсене", "options": "Настройки", "or": "или", @@ -870,7 +913,6 @@ "permanent_deletion_warning_setting_description": "Показване на предупреждение при трайно изтриване на активи", "permanently_delete": "Трайно изтриване", "permanently_deleted_asset": "", - "permanently_deleted_assets": "", "person": "Човек", "photos": "Снимки", "photos_count": "", @@ -931,8 +973,6 @@ "saved_settings": "", "say_something": "", "scan_all_libraries": "", - "scan_all_library_files": "", - "scan_new_library_files": "", "scan_settings": "", "scanning_for_album": "", "search": "Търсене", @@ -967,7 +1007,6 @@ "selected": "Избрано", "send_message": "Изпратете съобщение", "send_welcome_email": "Изпратете имейл за добре дошли", - "server": "Сървър", "server_offline": "Сървър офлайн", "server_online": "Сървър онлайн", "server_stats": "Статус на сървъра", @@ -1070,7 +1109,6 @@ "to_trash": "Кошче", "toggle_settings": "Превключване на настройките", "toggle_theme": "Превключване на тема", - "toggle_visibility": "", "total_usage": "Общо използвано", "trash": "кошче", "trash_all": "Изхвърли всички", @@ -1079,7 +1117,6 @@ "trashed_items_will_be_permanently_deleted_after": "Изхвърлените в кошчето елементи ще бъдат изтрити за постоянно след {days, plural, one {# day} other {# days}}.", "type": "Тип", "unarchive": "Разархивирай", - "unarchived": "", "unfavorite": "Премахване от любимите", "unhide_person": "", "unknown": "Неизвестно", @@ -1113,6 +1150,8 @@ "user_purchase_settings_description": "Управлявай покупката си", "user_role_set": "Задай {user} като {role}", "user_usage_detail": "Подробности за използването на потребителя", + "user_usage_stats": "Статистика за използването на акаунта", + "user_usage_stats_description": "Преглед на статистиката за използването на акаунта", "username": "Потребителско име", "users": "Потребители", "utilities": "Инструменти", @@ -1135,13 +1174,12 @@ "view_next_asset": "Преглед на следващия файл", "view_previous_asset": "Преглед на предишния файл", "view_stack": "Покажи в стек", - "viewer": "", "visibility_changed": "Видимостта е променена за {count, plural, one {# person} other {# people}}", "waiting": "в изчакване", "warning": "Внимание", "week": "Седмица", "welcome": "Добре дошли", - "welcome_to_immich": "Добре дошли в immich", + "welcome_to_immich": "Добре дошли в Immich", "year": "Година", "yes": "Да", "you_dont_have_any_shared_links": "Нямате споделени връзки", diff --git a/i18n/bi.json b/i18n/bi.json index aa5e3401c0ab2..dfcc614beab2c 100644 --- a/i18n/bi.json +++ b/i18n/bi.json @@ -33,7 +33,6 @@ "confirm_email_below": "", "confirm_reprocess_all_faces": "", "confirm_user_password_reset": "", - "crontab_guru": "", "disable_login": "", "duplicate_detection_job_description": "", "exclusion_pattern_description": "", @@ -49,16 +48,9 @@ "image_prefer_embedded_preview_setting_description": "", "image_prefer_wide_gamut": "", "image_prefer_wide_gamut_setting_description": "", - "image_preview_format": "", - "image_preview_resolution": "", - "image_preview_resolution_description": "", "image_quality": "", - "image_quality_description": "", "image_settings": "", "image_settings_description": "", - "image_thumbnail_format": "", - "image_thumbnail_resolution": "", - "image_thumbnail_resolution_description": "", "job_concurrency": "", "job_not_concurrency_safe": "", "job_settings": "", @@ -67,8 +59,6 @@ "jobs_delayed": "", "jobs_failed": "", "library_created": "", - "library_cron_expression": "", - "library_cron_expression_presets": "", "library_deleted": "", "library_import_path_description": "", "library_scanning": "", @@ -172,15 +162,12 @@ "paths_validated_successfully": "", "quota_size_gib": "", "refreshing_all_libraries": "", - "removing_deleted_files": "", "repair_all": "", "repair_matched_items": "", "repaired_items": "", "require_password_change_on_login": "", "reset_settings_to_default": "", "reset_settings_to_recent_saved": "", - "scanning_library_for_changed_files": "", - "scanning_library_for_new_files": "", "send_welcome_email": "", "server_external_domain_settings": "", "server_external_domain_settings_description": "", @@ -255,8 +242,6 @@ "transcoding_threads_description": "", "transcoding_tone_mapping": "", "transcoding_tone_mapping_description": "", - "transcoding_tone_mapping_npl": "", - "transcoding_tone_mapping_npl_description": "", "transcoding_transcode_policy": "", "transcoding_transcode_policy_description": "", "transcoding_two_pass_encoding": "", @@ -308,7 +293,6 @@ "appears_in": "", "archive": "", "archive_or_unarchive_photo": "", - "archived": "", "asset_offline": "", "assets": "", "authorized_devices": "", @@ -322,10 +306,6 @@ "cancel_search": "", "cannot_merge_people": "", "cannot_update_the_description": "", - "cant_apply_changes": "", - "cant_get_faces": "", - "cant_search_people": "", - "cant_search_places": "", "change_date": "", "change_expiration_time": "", "change_location": "", @@ -411,13 +391,6 @@ "download": "", "downloading": "", "duration": "", - "durations": { - "days": "", - "hours": "", - "minutes": "", - "months": "", - "years": "" - }, "edit_album": "", "edit_avatar": "", "edit_date": "", @@ -436,7 +409,6 @@ "edited": "", "editor": "", "email": "", - "empty_album": "", "empty_trash": "", "enable": "", "enabled": "", @@ -522,7 +494,6 @@ "extension": "", "external": "", "external_libraries": "", - "failed_to_get_people": "", "favorite": "", "favorite_or_unfavorite_photo": "", "favorites": "", @@ -534,14 +505,12 @@ "filter_people": "", "find_them_fast": "", "fix_incorrect_match": "", - "force_re-scan_library_files": "", "forward": "", "general": "", "get_help": "", "getting_started": "", "go_back": "", "go_to_search": "", - "go_to_share_page": "", "group_albums_by": "", "has_quota": "", "hide_gallery": "", @@ -656,7 +625,6 @@ "oldest_first": "", "online": "", "only_favorites": "", - "only_refreshes_modified_files": "", "open_the_search_filters": "", "options": "", "organize_your_library": "", @@ -745,8 +713,6 @@ "saved_settings": "", "say_something": "", "scan_all_libraries": "", - "scan_all_library_files": "", - "scan_new_library_files": "", "scan_settings": "", "search": "", "search_albums": "", @@ -777,7 +743,6 @@ "selected": "", "send_message": "", "send_welcome_email": "", - "server": "", "server_stats": "", "set": "", "set_as_album_cover": "", @@ -847,7 +812,6 @@ "to_favorite": "", "toggle_settings": "", "toggle_theme": "", - "toggle_visibility": "", "total_usage": "", "trash": "", "trash_all": "", @@ -855,11 +819,9 @@ "trashed_items_will_be_permanently_deleted_after": "", "type": "", "unarchive": "", - "unarchived": "", "unfavorite": "", "unhide_person": "", "unknown": "", - "unknown_album": "", "unknown_year": "", "unlimited": "", "unlink_oauth": "", @@ -893,7 +855,6 @@ "view_links": "", "view_next_asset": "", "view_previous_asset": "", - "viewer": "", "waiting": "", "week": "", "welcome_to_immich": "", diff --git a/i18n/bn.json b/i18n/bn.json new file mode 100644 index 0000000000000..0967ef424bce6 --- /dev/null +++ b/i18n/bn.json @@ -0,0 +1 @@ +{} diff --git a/i18n/ca.json b/i18n/ca.json index 86d85becf774c..a38e9e4743bba 100644 --- a/i18n/ca.json +++ b/i18n/ca.json @@ -1,8 +1,8 @@ { - "about": "Quant a", + "about": "Sobre", "account": "Compte", "account_settings": "Configuració del compte", - "acknowledge": "Reconeix", + "acknowledge": "Confirmar", "action": "Acció", "actions": "Accions", "active": "Actiu", @@ -14,26 +14,32 @@ "add_a_name": "Afegir un nom", "add_a_title": "Afegir un títol", "add_exclusion_pattern": "Afegir un patró d'exclusió", - "add_import_path": "Afegir un camí d'importació", + "add_import_path": "Afegir una ruta d'importació", "add_location": "Afegir la ubicació", "add_more_users": "Afegir més usuaris", "add_partner": "Afegir company/a", - "add_path": "Afegir un camí", + "add_path": "Afegir una ruta", "add_photos": "Afegir fotografies", "add_to": "Afegir a...", "add_to_album": "Afegir a un l'àlbum", "add_to_shared_album": "Afegir a un àlbum compartit", + "add_url": "Afegir URL", "added_to_archive": "Afegit als arxivats", "added_to_favorites": "Afegit als preferits", "added_to_favorites_count": "{count, number} afegits als preferits", "admin": { - "add_exclusion_pattern_description": "Afegeix patrons d'eclusió. És permès de l'ús de *, **, i ? (globbing). Per a ignorar els fitxers de qualsevol directori anomenat \"Raw\" introduïu \"**/Raw/**\". Per a ignorar els fitxers acabats en \".tif\" introduïu \"**/*.tif\". Per a ignorar un camí absolut, utilitzeu \"/camí/a/ignorar/**\".", + "add_exclusion_pattern_description": "Afegeix patrons d'exclusió. Es permet englobar fent ús de *, **, i ?. Per a ignorar els fitxers de qualsevol directori anomenat \"Raw\" introduïu \"**/Raw/**\". Per a ignorar els fitxers acabats en \".tif\" introduïu \"**/*.tif\". Per a ignorar una ruta absoluta, utilitzeu \"/ruta/a/ignorar/**\".", "asset_offline_description": "Aquest recurs de la biblioteca externa ja no es troba al disc i s'ha mogut a la paperera. Si el fitxer s'ha mogut dins de la biblioteca, comproveu la vostra línia de temps per trobar el nou recurs corresponent. Per restaurar aquest recurs, assegureu-vos que Immich pugui accedir a la ruta del fitxer següent i escanegeu la biblioteca.", "authentication_settings": "Configuració de l'autenticació", "authentication_settings_description": "Gestiona la contrasenya, OAuth i altres configuracions de l'autenticació", "authentication_settings_disable_all": "Estàs segur que vols desactivar tots els mètodes d'inici de sessió? L'inici de sessió quedarà completament desactivat.", "authentication_settings_reenable": "Per a tornar a habilitar, empra una Comanda de Servidor.", "background_task_job": "Tasques en segon pla", + "backup_database": "Còpia de la base de dades", + "backup_database_enable_description": "Habilitar còpies de la base de dades", + "backup_keep_last_amount": "Quantitat de còpies de seguretat anteriors per conservar", + "backup_settings": "Ajustes de les còpies de seguretat", + "backup_settings_description": "Gestionar la configuració de la còpia de seguretat de la base de dades", "check_all": "Marca-ho tot", "cleared_jobs": "Tasques esborrades per a: {job}", "config_set_by_file": "La configuració està definida per un fitxer de configuració", @@ -43,9 +49,10 @@ "confirm_reprocess_all_faces": "Esteu segur que voleu reprocessar totes les cares? Això també esborrarà la gent que heu anomenat.", "confirm_user_password_reset": "Esteu segur que voleu reinicialitzar la contrasenya de l'usuari {user}?", "create_job": "Crear tasca", - "crontab_guru": "Crontab Guru", + "cron_expression": "Expressió Cron", + "cron_expression_description": "Estableix l'interval d'escaneig amb el format cron. Per obtenir més informació, consulteu, p.e Crontab Guru", + "cron_expression_presets": "Ajustos predefinits d'expressions Cron", "disable_login": "Deshabiliteu l'inici de sessió", - "disabled": "Deshabilitat", "duplicate_detection_job_description": "Executa l'aprenentatge automàtic en els elements per a detectar imatges semblants. Fa servir l'Smart Search", "exclusion_pattern_description": "Els patrons d'exclusió permeten ignorar fitxers i carpetes quan escanegeu una llibreria. Això és útil si teniu carpetes que contenen fitxer que no voleu importar, com els fitxers RAW.", "external_library_created_at": "Llibreria externa (creada el {date})", @@ -63,22 +70,15 @@ "image_prefer_wide_gamut": "Prefereix àmplia gamma", "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_format": "Format de previsualització", "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.", - "image_preview_resolution": "Resolució de previsualització", - "image_preview_resolution_description": "S'empra al visualitzar una única fotografia i per a l'Aprenentatge Automàtic. L'alta resolució por preservar més detalls però es triga més a codificar, té fitxers més pesats i pot reduir la resposta de l'aplicació.", "image_preview_title": "Paràmetres de previsualització", "image_quality": "Qualitat", - "image_quality_description": "Qualitat d'imatge de 1 a 100. Un valor més alt millora la qualitat però genera fitxers més pesats.", "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_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_format": "Format de la miniatura", "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_resolution": "Resolució de la miniatura", - "image_thumbnail_resolution_description": "S'empra per a veure grups de fotos (cronologia, vista d'àlbum, etc.). L'alta resolució pot preservar més detalls però triguen més en codificar-se, tenen fitxers més pesats i poden reduir la reactivitat de l'aplicació.", "image_thumbnail_title": "Configuració de miniatures", "job_concurrency": "{job} concurrència", "job_created": "Tasca creada", @@ -89,9 +89,6 @@ "jobs_delayed": "{jobCount, plural, other {# posposades}}", "jobs_failed": "{jobCount, plural, other {# fallides}}", "library_created": "Bilbioteca creada: {library}", - "library_cron_expression": "Expressió cron", - "library_cron_expression_description": "Estableix l'interval d'escaneig utilitzant el format cron. Per a més informació, consulta per exemple, Crontab Guru", - "library_cron_expression_presets": "Expressions cron predeterminades", "library_deleted": "Bilbioteca eliminada", "library_import_path_description": "Especifiqueu una carpeta a importar. Aquesta carpeta, incloses les seves subcarpetes, serà escanejada per cercar-hi imatges i vídeos.", "library_scanning": "Escaneig periòdic", @@ -158,7 +155,7 @@ "metadata_settings_description": "Administrar la configuració de les metadades", "migration_job": "Migració", "migration_job_description": "Migra les miniatures d'elements i cares cap a la nova estructura de carpetes", - "no_paths_added": "Cap camí afegit", + "no_paths_added": "No s'ha afegit cap ruta", "no_pattern_added": "Cap patró aplicat", "note_apply_storage_label_previous_assets": "Nota: Per aplicar l'etiquetatge d'emmagatzematge a elements pujats prèviament, executeu la", "note_cannot_be_changed_later": "NOTA: Això és irreversible!", @@ -209,13 +206,12 @@ "password_enable_description": "Inicia sessió amb correu electrònic i contrasenya", "password_settings": "Inici de sessió amb contrasenya", "password_settings_description": "Gestiona la configuració de l'inici de sessió amb contrasenya", - "paths_validated_successfully": "Tots els camins han estat validats amb èxit", + "paths_validated_successfully": "Totes les rutes han estat validades amb èxit", "person_cleanup_job": "Neteja de persona", "quota_size_gib": "Tamany de la quota (GiB)", "refreshing_all_libraries": "Actualitzant totes les biblioteques", "registration": "Registre d'administrador", "registration_description": "Com que ets el primer usuari del sistema, seràs designat com a administrador i seràs responsable de les tasques administratives. També seràs l'encarregat de crear usuaris addicionals.", - "removing_deleted_files": "Eliminant fitxers fora de línia", "repair_all": "Reparar tot", "repair_matched_items": "Coincidència {count, plural, one {# element} other {# elements}}", "repaired_items": "Corregit {count, plural, one {# element} other {# elements}}", @@ -223,8 +219,6 @@ "reset_settings_to_default": "Restablir configuracions per defecte", "reset_settings_to_recent_saved": "Restablir la configuració guardada més recent", "scanning_library": "Escanejant biblioteca", - "scanning_library_for_changed_files": "Escanejant llibreria per trobar fitxers modificats", - "scanning_library_for_new_files": "Escanejant llibreria per trobar fitxers nous", "search_jobs": "Tasques de cerca...", "send_welcome_email": "Enviar correu electrònic de benvinguda", "server_external_domain_settings": "Domini extern", @@ -261,7 +255,6 @@ "these_files_matched_by_checksum": "Aquests fitxers coincideixen amb els seus checksums", "thumbnail_generation_job": "Generar miniatures", "thumbnail_generation_job_description": "Genera miniatures grans, petites i borroses per a cada element, així com miniatures per a cada persona", - "transcode_policy_description": "", "transcoding_acceleration_api": "API d'acceleració", "transcoding_acceleration_api_description": "L'API que interactuarà amb el vostre dispositiu per accelerar la transcodificació. Aquesta configuració és \"millor esforç\": tornarà a la transcodificació del programari en cas d'error. VP9 pot funcionar o no depenent del vostre maquinari.", "transcoding_acceleration_nvenc": "NVENC (requereix GPU d'NVIDIA)", @@ -313,8 +306,6 @@ "transcoding_threads_description": "Els valors més alts condueixen a una codificació més ràpida, però deixen menys espai perquè el servidor processi altres tasques mentre està actiu. Aquest valor no hauria de ser superior al nombre de nuclis de CPU. Maximitza la utilització si s'estableix a 0.", "transcoding_tone_mapping": "Mapeig de to", "transcoding_tone_mapping_description": "Intenta preservar l'aspecte dels vídeos HDR quan es converteixen a SDR. Cada algorisme fa diferents compensacions pel color, el detall i la brillantor. Hable conserva els detalls, Mobius conserva el color i Reinhard conserva la brillantor.", - "transcoding_tone_mapping_npl": "NPL de mapatge de to", - "transcoding_tone_mapping_npl_description": "Els colors s'ajustaran perquè semblin normals per a exposicions amb aquesta brillantor. Contra intuïtivament, els valors més baixos augmenten la brillantor del vídeo i viceversa, ja que compensa la brillantor de la pantalla. 0 estableix aquest valor automàticament.", "transcoding_transcode_policy": "Política de transcodificació", "transcoding_transcode_policy_description": "Política sobre quan s'ha de transcodificar un vídeo. Els vídeos HDR sempre es transcodificaran (excepte si la transcodificació està desactivada).", "transcoding_two_pass_encoding": "Codificació de dues passades", @@ -395,7 +386,6 @@ "archive_or_unarchive_photo": "Arxivar o desarxivar fotografia", "archive_size": "Mida de l'arxiu", "archive_size_description": "Configureu la mida de l'arxiu de les descàrregues (en GiB)", - "archived": "Arxivat", "archived_count": "{count, plural, one {Arxivat #} other {Arxivats #}}", "are_these_the_same_person": "Són la mateixa persona?", "are_you_sure_to_do_this": "Esteu segurs que voleu fer-ho?", @@ -445,10 +435,6 @@ "cannot_merge_people": "No es pot fusionar gent", "cannot_undo_this_action": "Aquesta acció no es pot desfer!", "cannot_update_the_description": "No es pot actualitzar la descripció", - "cant_apply_changes": "No es poden aplicar els canvis", - "cant_get_faces": "No es poden obtenir les cares", - "cant_search_people": "No es pot buscar gent", - "cant_search_places": "No es poden cercar llocs", "change_date": "Canvia la data", "change_expiration_time": "Canvia la data d'expiració", "change_location": "Canvia la ubicació", @@ -480,6 +466,7 @@ "confirm": "Confirmar", "confirm_admin_password": "Confirmeu la contrasenya d'administrador", "confirm_delete_shared_link": "Esteu segurs que voleu eliminar aquest enllaç compartit?", + "confirm_keep_this_delete_others": "Excepte aquest element, tots els altres de la pila se suprimiran. Esteu segur que voleu continuar?", "confirm_password": "Confirmació de contrasenya", "contain": "Contingut", "context": "Context", @@ -529,6 +516,7 @@ "delete_key": "Suprimeix la clau", "delete_library": "Suprimeix la Llibreria", "delete_link": "Esborra l'enllaç", + "delete_others": "Suprimeix altres", "delete_shared_link": "Odstranit sdílený odkaz", "delete_tag": "Eliminar etiqueta", "delete_tag_confirmation_prompt": "Estàs segur que vols eliminar l'etiqueta {tagName}?", @@ -562,13 +550,6 @@ "duplicates": "Duplicats", "duplicates_description": "Resol cada grup indicant quins, si n'hi ha, són duplicats", "duration": "Duració", - "durations": { - "days": "", - "hours": "", - "minutes": "", - "months": "", - "years": "" - }, "edit": "Editar", "edit_album": "Edita l'àlbum", "edit_avatar": "Edita l'avatar", @@ -576,8 +557,8 @@ "edit_date_and_time": "Edita data i hora", "edit_exclusion_pattern": "Edita patró d'exclusió", "edit_faces": "Edita les cares", - "edit_import_path": "Edita el camí d'importació", - "edit_import_paths": "Edita camins d'importació", + "edit_import_path": "Edita la ruta d'importació", + "edit_import_paths": "Edita les rutes d'importació", "edit_key": "Edita clau", "edit_link": "Edita enllaç", "edit_location": "Edita ubicació", @@ -593,8 +574,6 @@ "editor_crop_tool_h2_aspect_ratios": "Relació d'aspecte", "editor_crop_tool_h2_rotation": "Rotació", "email": "Correu electrònic", - "empty": "", - "empty_album": "", "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", @@ -628,13 +607,14 @@ "failed_to_create_shared_link": "No s'ha pogut crear l'enllaç compartit", "failed_to_edit_shared_link": "No s'ha pogut editar l'enllaç compartit", "failed_to_get_people": "No s'han pogut aconseguir persones", + "failed_to_keep_this_delete_others": "No s'ha pogut conservar aquest element i suprimir els altres", "failed_to_load_asset": "No s'ha pogut carregar l'element", "failed_to_load_assets": "No s'han pogut carregar els elements", "failed_to_load_people": "No s'han pogut carregar les persones", "failed_to_remove_product_key": "No s'ha pogut eliminar la clau del producte", "failed_to_stack_assets": "No s'han pogut apilar els elements", "failed_to_unstack_assets": "No s'han pogut desapilar els elements", - "import_path_already_exists": "Aquest camí d'importació ja existeix.", + "import_path_already_exists": "Aquesta ruta d'importació ja existeix.", "incorrect_email_or_password": "Correu electrònic o contrasenya incorrectes", "paths_validation_failed": "{paths, plural, one {# ruta} other {# rutes}} no ha pogut validar", "profile_picture_transparent_pixels": "Les fotos de perfil no poden tenir píxels transparents. Per favor, feu zoom in, mogueu la imatge o ambdues.", @@ -644,7 +624,7 @@ "unable_to_add_assets_to_shared_link": "No s'han pogut afegir els elements a l'enllaç compartit", "unable_to_add_comment": "No es pot afegir el comentari", "unable_to_add_exclusion_pattern": "No s'ha pogut afegir el patró d’exclusió", - "unable_to_add_import_path": "No s'ha pogut afegir el camí d'importació", + "unable_to_add_import_path": "No s'ha pogut afegir la ruta d'importació", "unable_to_add_partners": "No es poden afegir companys", "unable_to_add_remove_archive": "No s'ha pogut {archived, select, true {eliminar l'element de} other {afegir l'element a}} l'arxiu", "unable_to_add_remove_favorites": "No s'ha pogut {favorite, select, true {afegir l'element als} other {eliminar l'element dels}} preferits", @@ -655,8 +635,6 @@ "unable_to_change_location": "No es pot canviar la ubicació", "unable_to_change_password": "No es pot canviar la contrasenya", "unable_to_change_visibility": "No es pot canviar la visibilitat de {count, plural, one {# persona} other {# persones}}", - "unable_to_check_item": "", - "unable_to_check_items": "", "unable_to_complete_oauth_login": "No es pot completar l'inici de sessió OAuth", "unable_to_connect": "No pot connectar", "unable_to_connect_to_server": "No es pot connectar al servidor", @@ -697,12 +675,10 @@ "unable_to_remove_album_users": "No es poden eliminar usuaris de l'àlbum", "unable_to_remove_api_key": "No es pot eliminar la clau de l'API", "unable_to_remove_assets_from_shared_link": "No es poden eliminar recursos de l'enllaç compartit", - "unable_to_remove_comment": "", "unable_to_remove_deleted_assets": "No es poden eliminar els fitxers fora de línia", "unable_to_remove_library": "No es pot eliminar la biblioteca", "unable_to_remove_partner": "No es pot eliminar company/a", "unable_to_remove_reaction": "No es pot eliminar la reacció", - "unable_to_remove_user": "", "unable_to_repair_items": "No es poden reparar els elements", "unable_to_reset_password": "No es pot restablir la contrasenya", "unable_to_resolve_duplicate": "No es pot resoldre el duplicat", @@ -732,10 +708,6 @@ "unable_to_update_user": "No es pot actualitzar l'usuari", "unable_to_upload_file": "No es pot carregar el fitxer" }, - "every_day_at_onepm": "", - "every_night_at_midnight": "", - "every_night_at_twoam": "", - "every_six_hours": "", "exif": "Exif", "exit_slideshow": "Surt de la presentació de diapositives", "expand_all": "Ampliar-ho tot", @@ -750,33 +722,27 @@ "external": "Extern", "external_libraries": "Llibreries externes", "face_unassigned": "Sense assignar", - "failed_to_get_people": "", "favorite": "Preferit", "favorite_or_unfavorite_photo": "Foto preferida o no preferida", "favorites": "Preferits", - "feature": "", "feature_photo_updated": "Foto destacada actualitzada", - "featurecollection": "", "features": "Característiques", "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ó", "filename": "Nom del fitxer", - "files": "", "filetype": "Tipus d'arxiu", "filter_people": "Filtra persones", "find_them_fast": "Trobeu-los ràpidament pel nom amb la cerca", "fix_incorrect_match": "Corregiu la coincidència incorrecta", "folders": "Carpetes", "folders_feature_description": "Explorar la vista de carpetes per les fotos i vídeos del sistema d'arxius", - "force_re-scan_library_files": "Força a tornar a escanejar tots els fitxers de la biblioteca", "forward": "Endavant", "general": "General", "get_help": "Aconseguir ajuda", "getting_started": "Començant", "go_back": "Torna", "go_to_search": "Vés a cercar", - "go_to_share_page": "Vés a la pàgina de compartir", "group_albums_by": "Agrupa àlbums per...", "group_no": "Cap agrupació", "group_owner": "Agrupar per propietari", @@ -802,7 +768,6 @@ "image_alt_text_date_place_2_people": "{isVideo, select, true {Video} other {Image}} pres/a a {city}, {country} amb {person1} i {person2} el {date}", "image_alt_text_date_place_3_people": "{isVideo, select, true {Video} other {Image}} pres/a a {city}, {country} amb {person1}, {person2}, i {person3} el {date}", "image_alt_text_date_place_4_or_more_people": "{isVideo, select, true {Video} other {Image}} pres/a a {city}, {country} amb {person1}, {person2}, i {additionalCount, number} altres el {date}", - "img": "", "immich_logo": "Logotip d'Immich", "immich_web_interface": "Interfície web Immich", "import_from_json": "Importar des de JSON", @@ -823,10 +788,11 @@ "invite_people": "Convida gent", "invite_to_album": "Convida a l'àlbum", "items_count": "{count, plural, one {# element} other {# elements}}", - "job_settings_description": "", "jobs": "Tasques", "keep": "Mantenir", "keep_all": "Mantenir-ho tot", + "keep_this_delete_others": "Conserveu-ho, suprimiu-ne els altres", + "kept_this_deleted_others": "S'ha conservat aquest element i s'han suprimit {count, plural, one {# asset} other {# assets}}", "keyboard_shortcuts": "Dreceres de teclat", "language": "Idioma", "language_setting_description": "Seleccioneu el vostre idioma", @@ -838,19 +804,6 @@ "level": "Nivell", "library": "Bibilioteca", "library_options": "Opcions de biblioteca", - "license_activated_title": "La vostra llicència ha estat activada amb èxit", - "license_button_activate": "Activar", - "license_button_buy": "Comprar", - "license_button_select": "Seleccionar", - "license_individual_title": "Llicència individual", - "license_info_unlicensed": "Sense llicència", - "license_license_title": "LLICÈNCIA", - "license_per_server": "Per servidor", - "license_per_user": "Per usuari", - "license_server_description_1": "1 llicència per servidor", - "license_server_title": "Llicència de servidor", - "license_trial_info_2": "Heu utilitzat l'Immich durant uns", - "license_trial_info_3": "{accountAge, plural, one {# dia} other {# dies}}", "light": "Llum", "like_deleted": "M'agrada suprimit", "link_motion_video": "Enllaçar vídeo en moviment", @@ -955,7 +908,6 @@ "onboarding_welcome_user": "Benvingut, {user}", "online": "En línia", "only_favorites": "Només preferits", - "only_refreshes_modified_files": "Només actualitza els fitxers modificats", "open_in_map_view": "Obrir a la vista del mapa", "open_in_openstreetmap": "Obre a OpenStreetMap", "open_the_search_filters": "Obriu els filtres de cerca", @@ -993,7 +945,6 @@ "people_edits_count": "{count, plural, one {# persona editada} other {# persones editades}}", "people_feature_description": "Explorar fotos i vídeos agrupades per persona", "people_sidebar_description": "Mostrar un enllaç a Persones a la barra lateral", - "perform_library_tasks": "", "permanent_deletion_warning": "Avís d'eliminació permanent", "permanent_deletion_warning_setting_description": "Mostrar un avís quan s'eliminin els elements permanentment", "permanently_delete": "Eliminar permanentment", @@ -1015,7 +966,6 @@ "play_memories": "Reproduir records", "play_motion_photo": "Reproduir Fotos en Moviment", "play_or_pause_video": "Reproduir o posar en pausa el vídeo", - "point": "", "port": "Port", "preset": "Preestablert", "preview": "Previsualització", @@ -1060,12 +1010,10 @@ "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", - "range": "", "rating": "Valoració", "rating_clear": "Esborrar valoració", "rating_count": "{count, plural, one {# estrella} other {# estrelles}}", "rating_description": "Mostrar la valoració EXIF al panell d'informació", - "raw": "", "reaction_options": "Opcions de reacció", "read_changelog": "Llegeix el registre de canvis", "reassign": "Reassignar", @@ -1110,7 +1058,6 @@ "reset": "Restablir", "reset_password": "Restablir contrasenya", "reset_people_visibility": "Restablir la visibilitat de les persones", - "reset_settings_to_default": "", "reset_to_default": "Restableix els valors predeterminats", "resolve_duplicates": "Resoldre duplicats", "resolved_all_duplicates": "Tots els duplicats resolts", @@ -1130,9 +1077,7 @@ "saved_settings": "Configuració guardada", "say_something": "Digues quelcom", "scan_all_libraries": "Escanejar totes les llibreries", - "scan_all_library_files": "Re-escanejar tots els fitxers de la llibreria", "scan_library": "Escaneja", - "scan_new_library_files": "Escanejar nous fitxers de la llibreria", "scan_settings": "Configuració d'escaneig", "scanning_for_album": "S'està buscant l'àlbum...", "search": "Cerca", @@ -1175,7 +1120,6 @@ "selected_count": "{count, plural, one {# seleccionat} other {# seleccionats}}", "send_message": "Envia missatge", "send_welcome_email": "Envia correu de benvinguda", - "server": "Servidor", "server_offline": "Servidor fora de línia", "server_online": "Servidor en línia", "server_stats": "Estadístiques del servidor", @@ -1289,7 +1233,6 @@ "to_trash": "Paperera", "toggle_settings": "Canvia configuració", "toggle_theme": "Alternar tema", - "toggle_visibility": "Canvia visibilitat", "total_usage": "Ús total", "trash": "Paperera", "trash_all": "Envia-ho tot a la paperera", @@ -1299,12 +1242,10 @@ "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}}.", "type": "Tipus", "unarchive": "Desarxivar", - "unarchived": "Desarxivat", "unarchived_count": "{count, plural, other {# elements desarxivats}}", "unfavorite": "Reverteix preferit", "unhide_person": "Mostra persona", "unknown": "Desconegut", - "unknown_album": "Àlbum desconegut", "unknown_year": "Any desconegut", "unlimited": "Il·limitat", "unlink_motion_video": "Desvincular vídeo en moviment", @@ -1336,12 +1277,13 @@ "use_custom_date_range": "Fes servir un rang de dates personalitzat", "user": "Usuari", "user_id": "ID d'usuari", - "user_license_settings": "Llicència", "user_liked": "A {user} li ha agradat {type, select, photo {aquesta foto} video {aquest vídeo} asset {aquest recurs} other {}}", "user_purchase_settings": "Compra", "user_purchase_settings_description": "Gestiona la teva compra", "user_role_set": "Establir {user} com a {role}", "user_usage_detail": "Detall d'ús d'usuari", + "user_usage_stats": "Estadístiques d'ús de del compte", + "user_usage_stats_description": "Veure les estadístiques d'ús del compte", "username": "Nom d'usuari", "users": "Usuaris", "utilities": "Utilitats", @@ -1349,7 +1291,7 @@ "variables": "Variables", "version": "Versió", "version_announcement_closing": "El teu amic Alex", - "version_announcement_message": "Hola amic, hi ha una nova versió de l'aplicació, si us plau, preneu-vos el temps per visitar les release notes i assegureu-vos que el vostre docker-compose.yml i .env estàn actualitzats per evitar qualsevol configuració incorrecta, especialment si utilitzeu WatchTower o qualsevol mecanisme que gestioni l'actualització automàtica de la vostra aplicació.", + "version_announcement_message": "Hola! Hi ha una nova versió d'Immich, si us plau, preneu-vos una estona per llegir les notes de llançament per assegurar que la teva configuració estigui actualitzada per evitar qualsevol error de configuració, especialment si utilitzeu WatchTower o qualsevol mecanisme que gestioni l'actualització automàtica de la vostra instància Immich.", "version_history": "Historial de versions", "version_history_item": "Instal·lat {version} el {date}", "video": "Vídeo", @@ -1366,7 +1308,6 @@ "view_next_asset": "Mostra el següent element", "view_previous_asset": "Mostra l'element anterior", "view_stack": "Veure la pila", - "viewer": "Visualitzador", "visibility_changed": "La visibilitat ha canviat per {count, plural, one {# persona} other {# persones}}", "waiting": "Esperant", "warning": "Avís", diff --git a/i18n/cs.json b/i18n/cs.json index 12ba83b8e799b..a762f26b9a6b7 100644 --- a/i18n/cs.json +++ b/i18n/cs.json @@ -23,6 +23,7 @@ "add_to": "Přidat do...", "add_to_album": "Přidat do alba", "add_to_shared_album": "Přidat do sdíleného alba", + "add_url": "Přidat URL", "added_to_archive": "Přidáno do archivu", "added_to_favorites": "Přidáno do oblíbených", "added_to_favorites_count": "Přidáno {count, number} do oblíbených", @@ -34,6 +35,11 @@ "authentication_settings_disable_all": "Opravdu chcete zakázat všechny metody přihlášení? Přihlašování bude úplně zakázáno.", "authentication_settings_reenable": "Pro opětovné povolení použijte příkaz Příkaz serveru.", "background_task_job": "Úkoly na pozadí", + "backup_database": "Zálohování databáze", + "backup_database_enable_description": "Povolit zálohování databáze", + "backup_keep_last_amount": "Počet předchozích záloh k uchování", + "backup_settings": "Nastavení zálohování", + "backup_settings_description": "Správa nastavení zálohování databáze", "check_all": "Vše zkontrolovat", "cleared_jobs": "Hotové úlohy pro: {job}", "config_set_by_file": "Konfigurace je aktuálně prováděna konfiguračním souborem", @@ -43,9 +49,10 @@ "confirm_reprocess_all_faces": "Opravdu chcete znovu zpracovat všechny obličeje? Tím se vymažou i pojmenované osoby.", "confirm_user_password_reset": "Opravdu chcete obnovit heslo uživatele {user}?", "create_job": "Vytvořit úlohu", - "crontab_guru": "Crontab Guru", + "cron_expression": "Výraz cron", + "cron_expression_description": "Nastavte interval prohledávání pomocí cron formátu. Další informace naleznete např. v Crontab Guru", + "cron_expression_presets": "Předvolby výrazů cron", "disable_login": "Zakázat přihlášení", - "disabled": "Zakázáno", "duplicate_detection_job_description": "Spuštění strojového učení na položkách za účelem detekce podobných obrázků. Spoléhá na Chytré vyhledávání", "exclusion_pattern_description": "Vzory vyloučení umožňují při prohledávání knihovny ignorovat soubory a složky. To je užitečné, pokud máte složky obsahující soubory, které nechcete importovat, například RAW soubory.", "external_library_created_at": "Externí knihovna (vytvořena {date})", @@ -63,22 +70,15 @@ "image_prefer_wide_gamut": "Preferovat široký gamut", "image_prefer_wide_gamut_setting_description": "Použít Display P3 pro miniatury. To lépe zachovává živost obrázků s širokým barevným prostorem, ale obrázky se mohou na starých zařízeních se starou verzí prohlížeče zobrazovat jinak. sRGB obrázky jsou ponechány jako sRGB, aby se zabránilo posunům barev.", "image_preview_description": "Středně velký obrázek se zbavenými metadaty, který se používá při prohlížení jedné položky a pro strojové učení", - "image_preview_format": "Formát náhledů", "image_preview_quality_description": "Kvalita náhledu od 1 do 100. Vyšší je lepší, ale vytváří větší soubory a může snížit responzivitu aplikace. Nastavení nízké hodnoty může ovlivnit kvalitu strojového učení.", - "image_preview_resolution": "Rozlišení náhledů", - "image_preview_resolution_description": "Používá se při prohlížení jedné fotografie a pro strojové učení. Vyšší rozlišení mohou zachovat více detailů, ale jejich kódování trvá déle, mají větší velikost souboru a mohou snížit odezvu aplikace.", "image_preview_title": "Náhledy", "image_quality": "Kvalita", - "image_quality_description": "Kvalita obrazu od 1 do 100. Vyšší kvalita je lepší, ale vytváří větší soubory, tato volba ovlivňuje náhled a miniatury obrázků.", "image_resolution": "Rozlišení", "image_resolution_description": "Vyšší rozlišení mohou zachovat více detailů, ale jejich kódování trvá déle, mají větší velikost souboru a mohou snížit odezvu aplikace.", "image_settings": "Obrázky", "image_settings_description": "Správa kvality a rozlišení generovaných obrázků", "image_thumbnail_description": "Malá miniatura s odstraněnými metadaty, který se používá při prohlížení skupin fotografií, jako je hlavní časová osa", - "image_thumbnail_format": "Formát miniatur", "image_thumbnail_quality_description": "Kvalita miniatur od 1 do 100. Vyšší je lepší, ale vytváří větší soubory a může snížit odezvu aplikace.", - "image_thumbnail_resolution": "Rozlišení miniatur", - "image_thumbnail_resolution_description": "Používá se při prohlížení skupin fotografií (hlavní časová osa, zobrazení alba atd.). Vyšší rozlišení může zachovat více detailů, ale trvá déle, než se zakóduje, má větší velikost souboru a může snížit odezvu aplikace.", "image_thumbnail_title": "Miniatury", "job_concurrency": "Souběžnost úlohy {job}", "job_created": "Úloha vytvořena", @@ -89,9 +89,6 @@ "jobs_delayed": "{jobCount, plural, one {# zpožděný} few {# zpožděné} other {# zpožděných}}", "jobs_failed": "{jobCount, plural, one {# neúspěšný} few {# neúspěšné} other {# neúspěšných}}", "library_created": "Vytvořena knihovna: {library}", - "library_cron_expression": "Výraz pro Cron", - "library_cron_expression_description": "Nastavte interval prohledávání pomocí formátu cron. Další informace naleznete např. v Crontab Guru", - "library_cron_expression_presets": "Předvolby výrazu pro Cron", "library_deleted": "Knihovna smazána", "library_import_path_description": "Zadejte složku, kterou chcete importovat. Tato složka bude prohledána včetně podsložek a budou v ní hledány obrázky a videa.", "library_scanning": "Pravidelné prohledávání", @@ -134,7 +131,7 @@ "machine_learning_smart_search_description": "Sémantické vyhledávání obrázků pomocí CLIP embeddings", "machine_learning_smart_search_enabled": "Povolit chytré vyhledávání", "machine_learning_smart_search_enabled_description": "Pokud je vypnuto, obrázky nebudou kódovány pro inteligentní vyhledávání.", - "machine_learning_url_description": "URL serveru pro strojové učení", + "machine_learning_url_description": "URL serveru strojového učení. Pokud je zadáno více URL adres, budou jednotlivé servery zkoušeny postupně, dokud jeden z nich neodpoví úspěšně, a to v pořadí od prvního k poslednímu.", "manage_concurrency": "Správa souběžnosti", "manage_log_settings": "Správa nastavení protokolu", "map_dark_style": "Tmavý motiv", @@ -160,11 +157,11 @@ "migration_job_description": "Migrace miniatur snímků a obličejů do nejnovější struktury složek", "no_paths_added": "Nebyly přidány žádné cesty", "no_pattern_added": "Nebyl přidán žádný vzor", - "note_apply_storage_label_previous_assets": "Upozornění: Pro uplatnění Štítku úložiště na dříve nahrané položky, spusťte", + "note_apply_storage_label_previous_assets": "Upozornění: Pro uplatnění Štítku úložiště na dříve nahrané položky spusťte", "note_cannot_be_changed_later": "UPOZORNĚNÍ: Toto nelze později změnit!", "note_unlimited_quota": "Upozornění: Pro neomezenou kvótu zadejte 0", "notification_email_from_address": "Adresa Od", - "notification_email_from_address_description": "E-mailová adresa odesílatele, např.: \"Immich Photo Server \"", + "notification_email_from_address_description": "E-mailová adresa odesílatele, např.: „Immich Photo Server “", "notification_email_host_description": "Adresa e-mailového serveru (např. smtp.immich.app)", "notification_email_ignore_certificate_errors": "Ignorovat chyby certifikátů", "notification_email_ignore_certificate_errors_description": "Ignorovat chyby ověření certifikátu TLS (nedoporučuje se)", @@ -215,7 +212,6 @@ "refreshing_all_libraries": "Obnovení všech knihoven", "registration": "Registrace správce", "registration_description": "Vzhledem k tomu, že jste prvním uživatelem v systému, budete přiřazen jako správce a budete zodpovědný za úkoly správy a další uživatelé budou vytvořeni vámi.", - "removing_deleted_files": "Odstranění offline souborů", "repair_all": "Opravit vše", "repair_matched_items": "Shoda {count, plural, one {# položky} other {# položek}}", "repaired_items": "{count, plural, one {Opravena # položka} few {Opraveny # položky} other {Opraveno # položek}}", @@ -223,12 +219,12 @@ "reset_settings_to_default": "Obnovení výchozího nastavení", "reset_settings_to_recent_saved": "Obnovit poslední uložené nastavení", "scanning_library": "Prohledat knihovnu", - "scanning_library_for_changed_files": "Hledání změněných souborů v knihovně", - "scanning_library_for_new_files": "Hledání nových souborů v knihovně", "search_jobs": "Hledat úlohy...", "send_welcome_email": "Odeslat uvítací e-mail", "server_external_domain_settings": "Externí doména", "server_external_domain_settings_description": "Doména pro veřejně sdílené odkazy, včetně http(s)://", + "server_public_users": "Veřejní uživatelé", + "server_public_users_description": "Všichni uživatelé (jméno a e-mail) jsou uvedeni při přidávání uživatele do sdílených alb. Pokud je tato funkce vypnuta, bude seznam uživatelů dostupný pouze uživatelům z řad správců.", "server_settings": "Server", "server_settings_description": "Správa nastavení serveru", "server_welcome_message": "Uvítací zpráva", @@ -254,6 +250,16 @@ "storage_template_user_label": "{label} je štítek úložiště uživatele", "system_settings": "Systémová nastavení", "tag_cleanup_job": "Promazání značek", + "template_email_available_tags": "V šabloně můžete použít následující proměnné: {tags}", + "template_email_if_empty": "Pokud je šablona prázdná, použije se výchozí e-mail.", + "template_email_invite_album": "Šablona pozvánky do alba", + "template_email_preview": "Náhled", + "template_email_settings": "Šablony e-mailů", + "template_email_settings_description": "Správa vlastních šablon e-mailových oznámení", + "template_email_update_album": "Šablona aktualizace alba", + "template_email_welcome": "Šablona uvítacího e-mailu", + "template_settings": "Šablony oznámení", + "template_settings_description": "Správa vlastních šablon oznámení.", "theme_custom_css_settings": "Vlastní CSS", "theme_custom_css_settings_description": "Kaskádové styly umožňují přizpůsobit design aplikace Immich.", "theme_settings": "Motivy", @@ -261,7 +267,6 @@ "these_files_matched_by_checksum": "Tyto soubory jsou porovnávány podle jejich kontrolních součtů", "thumbnail_generation_job": "Generování miniatur", "thumbnail_generation_job_description": "Generování velkých, malých a rozmazaných miniatur pro každý obrázek a miniatur pro každou osobu", - "transcode_policy_description": "Zásady, kdy má být video překódováno. Videa HDR budou překódována vždy (kromě případů, kdy je překódování zakázáno).", "transcoding_acceleration_api": "API pro akceleraci", "transcoding_acceleration_api_description": "Rozhraní, které bude komunikovat se zařízením a urychlovat překódování. Toto nastavení je 'best effort': při selhání se vrátí k softwarovému překódování. VP9 může, ale nemusí fungovat v závislosti na vašem hardwaru.", "transcoding_acceleration_nvenc": "NVENC (vyžaduje NVIDIA GPU)", @@ -313,8 +318,6 @@ "transcoding_threads_description": "Vyšší hodnoty vedou k rychlejšímu kódování, ale ponechávají serveru méně prostoru pro zpracování jiných úloh. Tato hodnota by neměla být vyšší než počet jader procesoru. Maximalizuje využití, pokud je nastavena na 0.", "transcoding_tone_mapping": "Tone-mapping", "transcoding_tone_mapping_description": "Snaží se zachovat vzhled videí HDR při převodu na SDR. Každý algoritmus dělá různé kompromisy v oblasti barev, detailů a jasu. Hable zachovává detaily, Mobius zachovává barvy a Reinhard zachovává jas.", - "transcoding_tone_mapping_npl": "Tone-mapping NPL", - "transcoding_tone_mapping_npl_description": "Barvy budou upraveny tak, aby vypadaly normálně pro displej s tímto jasem. Nižší hodnoty naopak zvyšují jas videa a naopak, protože kompenzují jas displeje. Hodnota 0 nastavuje tuto hodnotu automaticky.", "transcoding_transcode_policy": "Zásady překódování", "transcoding_transcode_policy_description": "Zásady, kdy má být video překódováno. Videa HDR budou překódována vždy (kromě případů, kdy je překódování zakázáno).", "transcoding_two_pass_encoding": "Dvouprůchodové kódování", @@ -395,7 +398,6 @@ "archive_or_unarchive_photo": "Archivovat nebo odarchivovat fotku", "archive_size": "Velikost archivu", "archive_size_description": "Nastavte velikost archivu pro stahování (v GiB)", - "archived": "Archivováno", "archived_count": "{count, plural, other {Archivováno #}}", "are_these_the_same_person": "Jedná se o stejnou osobu?", "are_you_sure_to_do_this": "Opravdu to chcete udělat?", @@ -416,7 +418,6 @@ "assets_added_to_album_count": "Do alba {count, plural, one {byla přidána # položka} few {byly přidány # položky} other {bylo přidáno # položek}}", "assets_added_to_name_count": "{count, plural, one {Přidána # položka} few {Přidány # položky} other {Přidáno # položek}} do {hasName, select, true {alba {name}} other {nového alba}}", "assets_count": "{count, plural, one {# položka} few {# položky} other {# položek}}", - "assets_moved_to_trash": "{count, plural, one {# položka přesunuta} few {# položky přesunuty} other {# položek přesunuto}} do koše", "assets_moved_to_trash_count": "Do koše {count, plural, one {přesunuta # položka} few {přesunuty # položky} other {přesunuto # položek}}", "assets_permanently_deleted_count": "Trvale {count, plural, one {smazána # položka} few {smazány # položky} other {smazáno # položek}}", "assets_removed_count": "{count, plural, one {Odstraněna # položka} few {Odstraněny # položky} other {Odstraněno # položek}}", @@ -446,10 +447,6 @@ "cannot_merge_people": "Nelze sloučit osoby", "cannot_undo_this_action": "Tuto akci nelze vrátit zpět!", "cannot_update_the_description": "Nelze aktualizovat popis", - "cant_apply_changes": "Nelze uplatnit změny", - "cant_get_faces": "Nelze získat obličeje", - "cant_search_people": "Nelze vyhledávat lidi", - "cant_search_places": "Nelze vyhledávat místa", "change_date": "Změnit datum", "change_expiration_time": "Změna konce platnosti", "change_location": "Změna polohy", @@ -481,6 +478,7 @@ "confirm": "Potvrdit", "confirm_admin_password": "Potvrzení hesla správce", "confirm_delete_shared_link": "Opravdu chcete odstranit tento sdílený odkaz?", + "confirm_keep_this_delete_others": "Všechny ostatní položky v tomto uskupení mimo této budou odstraněny. Opravdu chcete pokračovat?", "confirm_password": "Potvrzení hesla", "contain": "Obsah", "context": "Kontext", @@ -530,6 +528,7 @@ "delete_key": "Smazat klíč", "delete_library": "Smazat knihovnu", "delete_link": "Smazat odkaz", + "delete_others": "Odstranit ostatní", "delete_shared_link": "Smazat sdílený odkaz", "delete_tag": "Smazat značku", "delete_tag_confirmation_prompt": "Opravdu chcete odstranit značku {tagName}?", @@ -563,13 +562,6 @@ "duplicates": "Duplicity", "duplicates_description": "Vyřešte každou skupinu tak, že uvedete, které skupiny jsou duplicitní", "duration": "Doba trvání", - "durations": { - "days": "{days, plural, one {den} few {{days, number} dny} other {{days, number} dní}}", - "hours": "{hours, plural, one {hodina} few {{hours, number} hodiny} other {{hours, number} hodin}}", - "minutes": "{minutes, plural, one {minuta} few {{minutes, number} minuty} other {{minutes, number} minut}}", - "months": "{months, plural, one {měsíc} few {{months, number} měsíce} other {{months, number} měsíců}}", - "years": "{years, plural, one {rok} few {{years, number} roky} other {{years, number} let}}" - }, "edit": "Upravit", "edit_album": "Upravit album", "edit_avatar": "Upravit avatar", @@ -594,8 +586,6 @@ "editor_crop_tool_h2_aspect_ratios": "Poměr stran", "editor_crop_tool_h2_rotation": "Otočení", "email": "E-mail", - "empty": "Prázdné", - "empty_album": "Prázdné album", "empty_trash": "Vyprázdnit koš", "empty_trash_confirmation": "Opravdu chcete vysypat koš? Tím se z Immiche trvale odstraní všechny položky v koši.\nTuto akci nelze vrátit zpět!", "enable": "Povolit", @@ -629,6 +619,7 @@ "failed_to_create_shared_link": "Nepodařilo se vytvořit sdílený odkaz", "failed_to_edit_shared_link": "Nepodařilo se upravit sdílený odkaz", "failed_to_get_people": "Nepodařilo se načíst lidi", + "failed_to_keep_this_delete_others": "Nepodařilo se zachovat tuto položku a odstranit ostatní položky", "failed_to_load_asset": "Nepodařilo se načíst položku", "failed_to_load_assets": "Nepodařilo se načíst položky", "failed_to_load_people": "Chyba načítání osob", @@ -656,8 +647,6 @@ "unable_to_change_location": "Nelze změnit polohu", "unable_to_change_password": "Nelze změnit heslo", "unable_to_change_visibility": "Nelze změnit viditelnost u {count, plural, one {# osoby} few {# osob} other {# lidí}}", - "unable_to_check_item": "Nelze zkontrolovat položku", - "unable_to_check_items": "Nelze zkontrolovat položky", "unable_to_complete_oauth_login": "Nelze dokončit OAuth přihlášení", "unable_to_connect": "Nelze se připojit", "unable_to_connect_to_server": "Nepodařilo se připojit k serveru", @@ -698,12 +687,10 @@ "unable_to_remove_album_users": "Nelze odebrat uživatele z alba", "unable_to_remove_api_key": "Nelze odstranit API klíč", "unable_to_remove_assets_from_shared_link": "Nelze odstranit položky ze sdíleného odkazu", - "unable_to_remove_comment": "Nelze odstranit komentář", "unable_to_remove_deleted_assets": "Nelze odstranit offline soubory", "unable_to_remove_library": "Nelze odstranit knihovnu", "unable_to_remove_partner": "Nelze odebrat partnera", "unable_to_remove_reaction": "Nelze odstranit reakci", - "unable_to_remove_user": "Nelze odebrat uživatele", "unable_to_repair_items": "Nelze opravit položky", "unable_to_reset_password": "Nelze obnovit heslo", "unable_to_resolve_duplicate": "Nelze vyřešit duplicitu", @@ -733,10 +720,6 @@ "unable_to_update_user": "Nelze aktualizovat uživatele", "unable_to_upload_file": "Nepodařilo se nahrát soubor" }, - "every_day_at_onepm": "Každý den ve 13:00", - "every_night_at_midnight": "Každý den o půlnoci", - "every_night_at_twoam": "Každou noc ve 2:00", - "every_six_hours": "Každých 6 hodin", "exif": "Exif", "exit_slideshow": "Ukončit prezentaci", "expand_all": "Rozbalit vše", @@ -751,33 +734,28 @@ "external": "Externí", "external_libraries": "Externí knihovny", "face_unassigned": "Nepřiřazena", - "failed_to_get_people": "Nepodařilo se načíst lidi", + "failed_to_load_assets": "Nepodařilo se načíst položky", "favorite": "Oblíbit", "favorite_or_unfavorite_photo": "Oblíbit nebo zrušit oblíbení fotky", "favorites": "Oblíbené", - "feature": "Funkce", "feature_photo_updated": "Hlavní fotka aktualizována", - "featurecollection": "Kolekce Funkcí", "features": "Funkce", "features_setting_description": "Správa funkcí aplikace", "file_name": "Název souboru", "file_name_or_extension": "Název nebo přípona souboru", "filename": "Filename", - "files": "", "filetype": "Filetype", "filter_people": "Filtrovat lidi", "find_them_fast": "Najděte je rychle vyhledáním jejich jména", "fix_incorrect_match": "Opravit nesprávnou shodu", "folders": "Složky", "folders_feature_description": "Procházení zobrazení složek s fotografiemi a videi v souborovém systému", - "force_re-scan_library_files": "Vynucené prohledání všech souborů knihovny", "forward": "Dopředu", "general": "Obecné", "get_help": "Získat pomoc", "getting_started": "Začínáme", "go_back": "Přejít zpět", "go_to_search": "Přejít na vyhledávání", - "go_to_share_page": "Přejít na stránku sdílení", "group_albums_by": "Seskupit alba podle...", "group_no": "Neseskupovat", "group_owner": "Seskupit podle uživatele", @@ -803,10 +781,6 @@ "image_alt_text_date_place_2_people": "{isVideo, select, true {Video pořízeno} other {Obrázek požízen}} {date} v místě {city}, {country} uživateli {person1} a {person2}", "image_alt_text_date_place_3_people": "{isVideo, select, true {Video pořízeno} other {Obrázek požízen}} {date} v místě {city}, {country} uživateli {person1}, {person2} a {person3}", "image_alt_text_date_place_4_or_more_people": "{isVideo, select, true {Video pořízeno} other {Obrázek požízen}} {date} v místě {city}, {country} uživateli {person1}, {person2} a {additionalCount, plural, one {dalším # uživatelem} other {dalšími # uživateli}}", - "image_alt_text_people": "{count, plural, =1 {a {person1}} =2 {s {person1} a {person2}} =3 {s {person1}, {person2}, a {person3}} other {s {person1}, {person2}, a {others, number} dalšími}}", - "image_alt_text_place": "v {city}, {country}", - "image_taken": "{isVideo, select, true {Video pořízeno} other {Obrázek požízen}}", - "img": "Img", "immich_logo": "Immich Logo", "immich_web_interface": "Webové rozhraní Immich", "import_from_json": "Import z JSONu", @@ -827,10 +801,11 @@ "invite_people": "Pozvat lidi", "invite_to_album": "Pozvat do alba", "items_count": "{count, plural, one {# položka} few {# položky} other {# položek}}", - "job_settings_description": "Správa souběhu úloh", "jobs": "Úlohy", "keep": "Ponechat", "keep_all": "Ponechat vše", + "keep_this_delete_others": "Ponechat tuto, odstranit ostatní", + "kept_this_deleted_others": "Ponechána tato položka a {count, plural, one {odstraněna # položka} few {odstraněny # položky} other {odstraněno # položek}}", "keyboard_shortcuts": "Klávesové zkratky", "language": "Jazyk", "language_setting_description": "Vyberte upřednostňovaný jazyk", @@ -842,31 +817,6 @@ "level": "Úroveň", "library": "Knihovna", "library_options": "Možnosti knihovny", - "license_account_info": "Váš účet je licencován", - "license_activated_subtitle": "Děkujeme vám za podporu aplikace Immich a open-source softwaru", - "license_activated_title": "Vaše licence byla úspěšně aktivována", - "license_button_activate": "Aktivovat", - "license_button_buy": "Koupit", - "license_button_buy_license": "Koupit licenci", - "license_button_select": "Vybrat", - "license_failed_activation": "Nepodařilo se aktivovat licenci. Zkontrolujte prosím svůj e-mail pro správný licenční klíč!", - "license_individual_description_1": "1 licence za uživatele na libovolném serveru", - "license_individual_title": "Individuální licence", - "license_info_licensed": "Licencováno", - "license_info_unlicensed": "Nelicencováno", - "license_input_suggestion": "Máte licenci? Zadejte klíč níže", - "license_license_subtitle": "Koupí licence podpoříte Immich", - "license_license_title": "LICENCE", - "license_lifetime_description": "Doživotní licence", - "license_per_server": "Za server", - "license_per_user": "Za uživatele", - "license_server_description_1": "1 licence za každý server", - "license_server_description_2": "Licence za všechny uživatele na serveru", - "license_server_title": "Serverová licence", - "license_trial_info_1": "Používáte nelicencovanou verzi aplikace Immich", - "license_trial_info_2": "Immich používáte přibližně", - "license_trial_info_3": "{accountAge, plural, one {# den} few {# dny} other {# dní}}", - "license_trial_info_4": "Zvažte prosím zakoupení licence na podporu dalšího rozvoje služby", "light": "Světlý", "like_deleted": "Lajk smazán", "link_motion_video": "Připojit pohyblivé video", @@ -966,13 +916,11 @@ "oldest_first": "Nejstarší první", "onboarding": "Zahájení", "onboarding_privacy_description": "Následující (volitelné) funkce jsou závislé na externích službách a lze je kdykoli zakázat v nastavení správy.", - "onboarding_storage_template_description": "Pokud je tato funkce povolena, automaticky uspořádá soubory na základě uživatelem definované šablony. Vzhledem k problémům se stabilitou byla tato funkce ve výchozím nastavení vypnuta. Další informace naleznete v [dokumentaci].", "onboarding_theme_description": "Zvolte si barevné téma pro svou instanci. Můžete to později změnit v nastavení.", "onboarding_welcome_description": "Nastavíme vaši instanci pomocí několika běžných nastavení.", "onboarding_welcome_user": "Vítej, {user}", "online": "Online", "only_favorites": "Pouze oblíbené", - "only_refreshes_modified_files": "Obnovuje pouze změněné soubory", "open_in_map_view": "Otevřít v zobrazení mapy", "open_in_openstreetmap": "Otevřít v OpenStreetMap", "open_the_search_filters": "Otevřít vyhledávací filtry", @@ -989,7 +937,7 @@ "partner_can_access": "{partner} má přístup", "partner_can_access_assets": "Všechny vaše fotky a videa kromě těch, které jsou v sekcích Archivováno a Smazáno", "partner_can_access_location": "Místo, kde byly vaše fotografie pořízeny", - "partner_sharing": "Sdílení partnerů", + "partner_sharing": "Sdílení mezi partnery", "partners": "Partneři", "password": "Heslo", "password_does_not_match": "Heslo se neshoduje", @@ -1010,14 +958,12 @@ "people_edits_count": "Upraveno {count, plural, one {# osoba} few {# osoby} other {# lidí}}", "people_feature_description": "Procházení fotografií a videí seskupených podle osob", "people_sidebar_description": "Zobrazit sekci Lidé v postranním panelu", - "perform_library_tasks": "", "permanent_deletion_warning": "Upozornění na trvalé smazání", "permanent_deletion_warning_setting_description": "Zobrazit varování při trvalém odstranění položek", "permanently_delete": "Trvale odstranit", - "permanently_delete_assets_count": "Trvale vymazat {count, plural, one {položku} other {položky}}", + "permanently_delete_assets_count": "Trvale smazat {count, plural, one {položku} other {položky}}", "permanently_delete_assets_prompt": "Opravdu chcete trvale smazat {count, plural, one {tuto položku} few {tyto # položky} other {těchto # položek}}? Tím {count, plural, one {ji také odstraníte z jejích} other {je také odstraníte z jejich}} alb.", "permanently_deleted_asset": "Položka trvale odstraněna", - "permanently_deleted_assets": "Trvale {count, plural, one {odstraněna # položka} few {odstraněny # položky} other {odstraněno # položek}}", "permanently_deleted_assets_count": "{count, plural, one {Položka trvale vymazána} other {Položky trvale vymazány}}", "person": "Osoba", "person_hidden": "{name}{hidden, select, true { (skryto)} other {}}", @@ -1033,7 +979,6 @@ "play_memories": "Přehrát vzpomníky", "play_motion_photo": "Přehrát pohybovou fotografii", "play_or_pause_video": "Přehrát nebo pozastavit video", - "point": "Bod", "port": "Port", "preset": "Přednastavení", "preview": "Náhled", @@ -1057,19 +1002,19 @@ "purchase_button_reminder": "Připomenout za 30 dní", "purchase_button_remove_key": "Odstranit klíč", "purchase_button_select": "Vybrat", - "purchase_failed_activation": "Aktivace se nezdařila! Zkontrolujte prosím svůj e-mail pro správný produktový klíč!", + "purchase_failed_activation": "Aktivace se nezdařila! Zkontrolujte prosím svůj e-mail zda je zadaný produktový klíč bez chyb!", "purchase_individual_description_1": "Pro jednotlivce", "purchase_individual_description_2": "Stav podporovatele", "purchase_individual_title": "Individuální", - "purchase_input_suggestion": "Máte produktový klíč? Zadejte klíč níže", - "purchase_license_subtitle": "Koupit Immich na podporu dalšího rozvoje služby", + "purchase_input_suggestion": "Máte produktový klíč? Zadejte ho níže", + "purchase_license_subtitle": "Koupit Immich a podpořit další rozvoj služby", "purchase_lifetime_description": "Doživotní platnost", - "purchase_option_title": "MOŽNOSTI NÁKUPU", + "purchase_option_title": "MOŽNOSTI ZAKOUPENÍ", "purchase_panel_info_1": "Tvorba aplikace Immich vyžaduje spoustu času a úsilí, a proto na ní pracují vývojáři na plný úvazek, aby byla co nejlepší. Naším cílem je, aby se software s otevřeným zdrojovým kódem a etické obchodní postupy staly udržitelným zdrojem příjmů pro vývojáře a aby vznikl ekosystém respektující soukromí se skutečnými alternativami k ziskuchtivým službám.", "purchase_panel_info_2": "Protože jsme se zavázali, že nebudeme zavádět paywally, nezískáte tímto nákupem žádné další funkce v aplikaci Immich. Spoléháme na uživatele, jako jste vy, že podpoří neustálý vývoj aplikace.", - "purchase_panel_title": "Podpora projektu", - "purchase_per_server": "Na server", - "purchase_per_user": "Na uživatele", + "purchase_panel_title": "Podpořit projekt", + "purchase_per_server": "Za server", + "purchase_per_user": "Za uživatele", "purchase_remove_product_key": "Odstranění produktového klíče", "purchase_remove_product_key_prompt": "Opravdu chcete odebrat produktový klíč?", "purchase_remove_server_product_key": "Odstranění serverového produktového klíče", @@ -1078,12 +1023,10 @@ "purchase_server_description_2": "Stav podporovatele", "purchase_server_title": "Server", "purchase_settings_server_activated": "Produktový klíč serveru spravuje správce", - "range": "Rozsah", "rating": "Hodnocení hvězdičkami", "rating_clear": "Vyčistit hodnocení", "rating_count": "{count, plural, one {# hvězdička} few {# hvězdičky} other {# hvězdček}}", "rating_description": "Zobrazit EXIF hodnocení v informačním panelu", - "raw": "Raw", "reaction_options": "Možnosti reakce", "read_changelog": "Přečtěte si seznam změn", "reassign": "Přeřadit", @@ -1091,6 +1034,7 @@ "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", "reassing_hint": "Přiřazení vybraných položek existující osobě", "recent": "Nedávné", + "recent-albums": "Nedávná alba", "recent_searches": "Nedávná vyhledávání", "refresh": "Obnovit", "refresh_encoded_videos": "Obnovit kódovaná videa", @@ -1112,6 +1056,7 @@ "remove_from_album": "Odstranit z alba", "remove_from_favorites": "Odstranit z oblíbených", "remove_from_shared_link": "Odstranit ze sdíleného odkazu", + "remove_url": "Odstranit URL", "remove_user": "Odebrat uživatele", "removed_api_key": "Odstraněn API klíč: {name}", "removed_from_archive": "Odstraněno z archivu", @@ -1128,7 +1073,6 @@ "reset": "Výchozí", "reset_password": "Obnovit heslo", "reset_people_visibility": "Obnovit viditelnost lidí", - "reset_settings_to_default": "Obnovit výchozí nastavení", "reset_to_default": "Obnovit výchozí nastavení", "resolve_duplicates": "Vyřešit duplicity", "resolved_all_duplicates": "Vyřešeny všechny duplicity", @@ -1148,9 +1092,7 @@ "saved_settings": "Nastavení uloženo", "say_something": "Řekněte něco", "scan_all_libraries": "Prohledat všechny knihovny", - "scan_all_library_files": "Prohledání všech souborů knihovny", "scan_library": "Prohledat", - "scan_new_library_files": "Hledat nové soubory v knihovně", "scan_settings": "Nastavení prohledávání", "scanning_for_album": "Prohledávání alba...", "search": "Hledat", @@ -1193,7 +1135,6 @@ "selected_count": "{count, plural, one {# vybraný} few {# vybrané} other {# vybraných}}", "send_message": "Odeslat zprávu", "send_welcome_email": "Poslat uvítací e-mail", - "server": "Server", "server_offline": "Server offline", "server_online": "Server online", "server_stats": "Statistiky serveru", @@ -1298,17 +1239,17 @@ "they_will_be_merged_together": "Budou sloučeny dohromady", "third_party_resources": "Zdroje třetích stran", "time_based_memories": "Časové vzpomínky", + "timeline": "Časová osa", "timezone": "Časové pásmo", "to_archive": "Archivovat", "to_change_password": "Změnit heslo", "to_favorite": "Oblíbit", "to_login": "Přihlásit", "to_parent": "Přejít k rodiči", - "to_root": "Přejít ke kořenu", "to_trash": "Vyhodit", "toggle_settings": "Přepnout nastavení", "toggle_theme": "Přepnout tmavý motiv", - "toggle_visibility": "Přepnout viditelnost", + "total": "Celkem", "total_usage": "Celkové využití", "trash": "Koš", "trash_all": "Vyhodit vše", @@ -1318,12 +1259,10 @@ "trashed_items_will_be_permanently_deleted_after": "Smazané položky budou trvale odstraněny po {days, plural, one {# dni} other {# dnech}}.", "type": "Typ", "unarchive": "Odarchivovat", - "unarchived": "Odarchivováno", "unarchived_count": "{count, plural, one {Odarchivována #} few {Odarchivovány #} other {Odarchivováno #}}", "unfavorite": "Zrušit oblíbení", "unhide_person": "Zrušit skrytí osoby", "unknown": "Neznámý", - "unknown_album": "Neznámé album", "unknown_year": "Neznámý rok", "unlimited": "Neomezeně", "unlink_motion_video": "Odpojit pohyblivé video", @@ -1331,7 +1270,7 @@ "unlinked_oauth_account": "OAuth účet odpojen", "unnamed_album": "Nepojmenované album", "unnamed_album_delete_confirmation": "Opravdu chcete toto album smazat?", - "unnamed_share": "Nejmenované sdílení", + "unnamed_share": "Nepojmenované sdílení", "unsaved_change": "Neuložená změna", "unselect_all": "Zrušit výběr všech", "unselect_all_duplicates": "Zrušit výběr všech duplicit", @@ -1355,13 +1294,13 @@ "use_custom_date_range": "Použít vlastní rozsah dat", "user": "Uživatel", "user_id": "ID uživatele", - "user_license_settings": "Licence", - "user_license_settings_description": "Správa licence", "user_liked": "Uživateli {user} se {type, select, photo {líbila tato fotka} video {líbilo toto video} asset {líbila tato položka} other {to líbilo}}", "user_purchase_settings": "Nákup", "user_purchase_settings_description": "Správa vašeho nákupu", "user_role_set": "Uživatel {user} nastaven jako {role}", "user_usage_detail": "Podrobnosti využití uživatelů", + "user_usage_stats": "Statistiky používání účtu", + "user_usage_stats_description": "Zobrazit statistiky používání účtu", "username": "Uživateleské jméno", "users": "Uživatelé", "utilities": "Nástroje", @@ -1369,7 +1308,7 @@ "variables": "Proměnné", "version": "Verze", "version_announcement_closing": "Váš přítel Alex", - "version_announcement_message": "Ahoj příteli, je tu nová verze aplikace, věnuj prosím čas přečtení poznámek k vydání a zajisti si, aby docker-compose.yml a nastavení .env bylo aktuální, a aby nedošlo k chybné konfiguraci, zejména pokud používáš WatchTower nebo jiný mechanismus, který se stará o automatickou aktualizaci aplikace.", + "version_announcement_message": "Ahoj! K dispozici je nová verze aplikace Immich. Věnujte prosím chvíli přečtení poznámek k vydání a ujistěte se, že je vaše nastavení aktuální, abyste předešli případným chybným konfiguracím, zejména pokud používáte WatchTower nebo jiný mechanismus, který se stará o automatickou aktualizaci instance aplikace Immich.", "version_history": "Historie verzí", "version_history_item": "Nainstalováno {version} dne {date}", "video": "Video", @@ -1383,10 +1322,10 @@ "view_all_users": "Zobrazit všechny uživatele", "view_in_timeline": "Zobrazit na časové ose", "view_links": "Zobrazit odkazy", + "view_name": "Zobrazit", "view_next_asset": "Zobrazit další položku", "view_previous_asset": "Zobrazit předchozí položku", "view_stack": "Zobrazit seskupení", - "viewer": "Prohlížeč", "visibility_changed": "Viditelnost změněna u {count, plural, one {# osoby} few {# osob} other {# lidí}}", "waiting": "Čekající", "warning": "Upozornění", diff --git a/i18n/cv.json b/i18n/cv.json index 8f0581053e2ca..61dcb12b8d54c 100644 --- a/i18n/cv.json +++ b/i18n/cv.json @@ -23,6 +23,7 @@ "add_to": "Мӗн те пулин хуш...", "add_to_album": "Альбома хуш", "add_to_shared_album": "Пӗрлехи альбома хуш", + "add_url": "URL хушӑр", "added_to_archive": "Архива хушнӑ", "added_to_favorites": "Суйласа илнине хушнӑ", "added_to_favorites_count": "Суйласа илнине {count, number} хушнӑ", @@ -45,5 +46,7 @@ "image_preview_title": "Малтанлӑха пӑхмалли ӗнерлевсем", "image_quality": "Пахалӑх", "image_resolution": "Виҫе" - } + }, + "user_usage_stats": "Шута ҫырни усӑ курмалли статистика", + "user_usage_stats_description": "Шута ҫырни усӑ курмалли статистикӑна пӑхасси" } diff --git a/i18n/da.json b/i18n/da.json index 9a4101b02350b..e455c4d567ca7 100644 --- a/i18n/da.json +++ b/i18n/da.json @@ -2,12 +2,12 @@ "about": "Om", "account": "Konto", "account_settings": "Kontoindstillinger", - "acknowledge": "Anerkend", + "acknowledge": "Godkend", "action": "Handling", "actions": "Handlinger", "active": "Aktive", "activity": "Aktivitet", - "activity_changed": "Aktivitet er {enabled, select, true {aktiveret} other {deaktiveret}}", + "activity_changed": "Aktivitet er {aktiveret, valg, sand {aktiveret} andet {deaktiveret}}", "add": "Tilføj", "add_a_description": "Tilføj en beskrivelse", "add_a_location": "Tilføj en placering", @@ -23,16 +23,23 @@ "add_to": "Tilføj til...", "add_to_album": "Tilføj til album", "add_to_shared_album": "Tilføj til delt album", + "add_url": "Tilføj URL", "added_to_archive": "Tilføjet til arkiv", "added_to_favorites": "Tilføjet til favoritter", "added_to_favorites_count": "Tilføjet {count, number} til favoritter", "admin": { "add_exclusion_pattern_description": "Tilføj udelukkelsesmønstre. Globbing ved hjælp af *, ** og ? understøttes. For at ignorere alle filer i enhver mappe med navnet \"Raw\", brug \"**/Raw/**\". For at ignorere alle filer, der slutter på \".tif\", brug \"**/*.tif\". For at ignorere en absolut sti, brug \"/sti/til/ignoreret/**\".", + "asset_offline_description": "Denne eksterne biblioteksressource findes ikke længere på disken og er blevet flyttet til papirkurven. Hvis filen blev flyttet inde i biblioteket, skal du tjekke din tidslinje for den nye tilsvarende ressource. For at gendanne denne ressource skal du sikre, at filstien nedenfor kan tilgås af Immich og scanne biblioteket.", "authentication_settings": "Godkendelsesindstillinger", "authentication_settings_description": "Administrer adgangskode, OAuth og andre godkendelsesindstillinger", "authentication_settings_disable_all": "Er du sikker på at du vil deaktivere alle loginmuligheder? Login vil blive helt deaktiveret.", "authentication_settings_reenable": "Brug en server-kommando for at genaktivere.", "background_task_job": "Baggrundsopgaver", + "backup_database": "Backup Database", + "backup_database_enable_description": "Slå database-backup til", + "backup_keep_last_amount": "Mængde af tidligere backups, der skal gemmes", + "backup_settings": "Backup-indstillinger", + "backup_settings_description": "Administrer backupindstillinger for database", "check_all": "Tjek Alle", "cleared_jobs": "Ryddet jobs til: {job}", "config_set_by_file": "konfigurationen er i øjeblikket indstillet af en konfigurations fil", @@ -41,9 +48,10 @@ "confirm_email_below": "For at bekræfte, skriv \"{email}\" herunder", "confirm_reprocess_all_faces": "Er du sikker på, at du vil genbehandle alle ansigter? Dette vil også rydde navngivne personer.", "confirm_user_password_reset": "Er du sikker på, at du vil nulstille {user}s adgangskode?", - "crontab_guru": "Crontab Guru", + "create_job": "Opret job", + "cron_expression": "Cron formel", + "cron_expression_description": "Indstil skannings intervallet i cron format. For mere information se: Crontab Guru", "disable_login": "Deaktiver login", - "disabled": "", "duplicate_detection_job_description": "Kør maskinlæring på mediefiler for at opdage lignende billeder. Er afhængig af Smart Søgning", "exclusion_pattern_description": "Ekskluderingsmønstre lader dig ignorere filer og mapper, når du scanner dit bibliotek. Dette er nyttigt, hvis du har mapper, der indeholder filer, du ikke vil importere, såsom RAW-filer.", "external_library_created_at": "Eksternt bibliotek (oprettet {date})", @@ -54,21 +62,20 @@ "failed_job_command": "Kommando {command} mislykkedes for job: {job}", "force_delete_user_warning": "ADVARSEL: Dette vil øjeblikkeligt fjerne brugeren og alle Billeder/Videoer. Dette kan ikke fortrydes, og filerne kan ikke gendannes.", "forcing_refresh_library_files": "Tvinger genopfriskning af alle biblioteksfiler", + "image_format": "Format", "image_format_description": "WebP producerer mindre filer end JPEG, men er langsommere at komprimere.", "image_prefer_embedded_preview": "Foretræk indlejret forhåndsvisning", "image_prefer_embedded_preview_setting_description": "Brug indlejrede forhåndsvisninger i RAW fotos som input til billedbehandling, når det er tilgængeligt. Dette kan give mere nøjagtige farver for nogle billeder, men kvaliteten af forhåndsvisningen er kameraafhængig, og billedet kan have flere komprimeringsartefakter.", "image_prefer_wide_gamut": "Foretrækker bred farveskala", "image_prefer_wide_gamut_setting_description": "Brug Display P3 til miniaturebilleder. Dette bevarer billeder med brede farveskalaers dynamik bedre, men billeder kan komme til at se anderledes ud på gamle enheder med en gammel browserversion. sRGB-billeder bliver beholdt som sRGB for at undgå farveskift.", - "image_preview_format": "Forhåndsvisningsformat", - "image_preview_resolution": "Forhåndsvisnings opløsning", - "image_preview_resolution_description": "Bliver brugt når et enkelt billede betragtes og ved maskinlæring. Højere opløsninger kan bevare flere detaljer, men tager længere tid at indkode, har større filstørrelser, og kan gøre appoplevelsen sløvere.", + "image_preview_description": "Mellemstørrelse billede med fjernet metadata, der bruges, når du ser en enkelt mediefil og til machine learning", + "image_preview_quality_description": "Kvalitet af forhåndsvisning fra 1-100. Højere er bedre, men producerer større filer og kan reducere apprespons. Valg af en lav værdi kan påvirke kvaliteten af machine learning.", + "image_preview_title": "Indstillinger for forhåndsvisning", "image_quality": "Kvalitet", - "image_quality_description": "Billedkvalitet fra 1-100. Højere er bedre for kvaliteten, men producerer større filer. Denne indstilling påvirker forhåndsvisningen og miniaturebillederne.", + "image_resolution": "Opløsning", "image_settings": "Billedindstillinger", "image_settings_description": "Administrer kvaliteten og opløsningen af genererede billeder", - "image_thumbnail_format": "Miniatureformat", - "image_thumbnail_resolution": "Miniature opløsning", - "image_thumbnail_resolution_description": "Bruges ved visning af grupper af billeder (hovedtidslinje, albumvisning osv.). Højere opløsninger kan bevare flere detaljer, men det tager længere tid at kode, har større filstørrelser og kan reducere appens reaktionsevne.", + "image_thumbnail_title": "Thumbnail-indstillinger", "job_concurrency": "{job} samtidighed", "job_not_concurrency_safe": "Denne opgave er ikke sikker at køre samtidigt med andre.", "job_settings": "Jobindstillinger", @@ -77,9 +84,6 @@ "jobs_delayed": "{jobCount, plural, one {# forsinket} other {# forsinkede}}", "jobs_failed": "{jobCount, plural, one {# fejlet} other {# fejlede}}", "library_created": "Skabte bibliotek: {library}", - "library_cron_expression": "Cron-udtryk", - "library_cron_expression_description": "Sæt skannings interval ved at bruge cron formatet. For mere information se dokumentation her Crontab Guru", - "library_cron_expression_presets": "Cron-udtryksforudindstillinger", "library_deleted": "Bibliotek slettet", "library_import_path_description": "Angiv en mappe, der skal importeres. Denne mappe, inklusive undermapper, vil blive scannet for billeder og videoer.", "library_scanning": "Periodisk scanning", @@ -198,19 +202,18 @@ "password_settings": "Adgangskodelogin", "password_settings_description": "Administrer indstillinger for adgangskodelogin", "paths_validated_successfully": "Alle stier valideret med succes", + "person_cleanup_job": "Person-oprydning", "quota_size_gib": "Kvotestørrelse (GiB)", "refreshing_all_libraries": "Opdaterer alle biblioteker", "registration": "Administratorregistrering", "registration_description": "Da du er den første bruger i systemet, får du tildelt rollen som administrator og ansvar for administration og oprettelsen af nye brugere.", - "removing_deleted_files": "Fjerner offline-filer", "repair_all": "Reparér alle", "repair_matched_items": "Har parret {count, plural, one {# element} other {# elementer}}", "repaired_items": "Reparerede {count, plural, one {# element} other {# elementer}}", "require_password_change_on_login": "Kræv at brugeren skifter adgangskode ved første login", "reset_settings_to_default": "Nulstil indstillingerne til standard", "reset_settings_to_recent_saved": "Nulstil indstillinger til de senest gemte indstillinger", - "scanning_library_for_changed_files": "Skanner bibliotek efter ændrede filer", - "scanning_library_for_new_files": "Skanner bibliotek efter nye filer", + "scanning_library": "Scanner bibliotek", "send_welcome_email": "Send velkomst-email", "server_external_domain_settings": "Eksternt domæne", "server_external_domain_settings_description": "Domæne til offentligt delte links, inklusiv http(s)://", @@ -245,7 +248,6 @@ "these_files_matched_by_checksum": "Disse filer er blevet matchet med deres checksummer", "thumbnail_generation_job": "Generér miniaturebilleder", "thumbnail_generation_job_description": "Generér store, små og slørede miniaturebilleder for hver mediefil, såvel som miniaturebilleder for hver person", - "transcode_policy_description": "", "transcoding_acceleration_api": "Accelerations-API", "transcoding_acceleration_api_description": "API'en som interagerer med din enhed for at accelerere transkodning. Denne er indstilling er \"i bedste fald\": Den vil falde tilbage til software-transkodning ved svigt. VP9 virker måske, måske ikke, afhængigt af dit hardware.", "transcoding_acceleration_nvenc": "NVENC (kræver NVIDIA GPU)", @@ -297,8 +299,6 @@ "transcoding_threads_description": "Højere værdier medfører hurtigere indkodning, men efterlader mindre plads til at serveren kan foretage andre opgaver når aktiv. Denne værdi bør ikke være større end antallet af CPU-kerner. Maksimerer udnyttelse hvis sat til 0.", "transcoding_tone_mapping": "Tone-kortlægning", "transcoding_tone_mapping_description": "Forsøger at bevare HDR-videoers udseende når konverteret til SDR. Hver algoritme har forskellige afvejninger af farve, detalje og lysstyrke. Hable bevarer farve og Reinhard bevarer lysstyrke.", - "transcoding_tone_mapping_npl": "Tone-kortlægning NPL", - "transcoding_tone_mapping_npl_description": "Farver vil blive justeret til at se normale ud for en skærm med denne lysstyrke. Ulogisk nok øger lavere værdier videoens lysstyrke og omvendt, siden det kompenserer for skærmens lysstyrke. 0 sætter debbe værdi automatisk.", "transcoding_transcode_policy": "Transkodningspolitik", "transcoding_transcode_policy_description": "Politik for hvornår en video skal transkodes. HDR videoer vil altid blive transkodet (bortset fra, hvis transkodning er slået fra).", "transcoding_two_pass_encoding": "To-omgangsindkodning", @@ -312,6 +312,7 @@ "trash_settings_description": "Administrér skraldeindstillinger", "untracked_files": "Utrackede filer", "untracked_files_description": "Applikationen holder ikke styr på disse filer. De kan være resultatet af mislykkede flytninger, afbrudte uploads eller være efterladt på grund af en fejl", + "user_cleanup_job": "Bruger-oprydning", "user_delete_delay": "{user}'s konto og mediefiler vil blive planlagt til permanent sletning om {delay, plural, one {# dag} other {# dage}}.", "user_delete_delay_settings": "Slet forsinkelse", "user_delete_delay_settings_description": "Antal dage efter fjernelse for permanent at slette en brugers konto og mediefiler. Opgaven for sletning af brugere kører ved midnat for at tjekke efter brugere, der er klar til sletning. Ændringer i denne indstilling vil blive evalueret ved næste udførelse.", @@ -356,6 +357,7 @@ "album_updated_setting_description": "Modtag en emailnotifikation når et delt album får nye mediefiler", "album_user_left": "Forlod {album}", "album_user_removed": "Fjernede {user}", + "album_with_link_access": "Lad alle med linket se billeder og personer i dette album.", "albums": "Albummer", "albums_count": "{count, plural, one {{count, number} Album} other {{count, number} Albummer}}", "all": "Alt", @@ -377,8 +379,17 @@ "archive_or_unarchive_photo": "Arkivér eller dearkivér billede", "archive_size": "Arkiv størelse", "archive_size_description": "Konfigurer arkivstørrelsen for downloads (i GiB)", - "archived": "Arkiveret", + "are_these_the_same_person": "Er disse den samme person?", + "are_you_sure_to_do_this": "Er du sikker på, at du vil gøre det her?", + "asset_added_to_album": "Tilføjet til album", + "asset_adding_to_album": "Tilføjer til album...", + "asset_description_updated": "Mediefilsbeskrivelse er blevet opdateret", + "asset_filename_is_offline": "Mediefil {filename} er offline", "asset_offline": "Mediefil offline", + "asset_offline_description": "Denne eksterne mediefil kan ikke længere findes på drevet. Kontakt venligst din Immich-administrator for hjælp.", + "asset_skipped": "Sprunget over", + "asset_uploaded": "Uploaded", + "asset_uploading": "Uploader...", "assets": "elementer", "authorized_devices": "Tilladte enheder", "back": "Tilbage", @@ -389,6 +400,7 @@ "build_image": "Byggefil", "bulk_delete_duplicates_confirmation": "Er du sikker på, at du vil slette alle {count, plural, one {# duplicate asset} other {# duplicate assets}}? Dette vil beholde den største fil i hver gruppe og slette alle dubletter. Denne handling kan ikke fortrydes!", "bulk_keep_duplicates_confirmation": "Er du sikker på, at du vil beholde {count, plural, one {# duplicate asset} other {# duplicate assets}}? Dette vil løse alle dubletgrupper uden at slette noget.", + "buy": "Køb Immich", "camera": "Kamera", "camera_brand": "Kameramærke", "camera_model": "Kameramodel", @@ -397,10 +409,6 @@ "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", - "cant_apply_changes": "Kan ikke anvende ændringer", - "cant_get_faces": "Kan ikke hente ansigter", - "cant_search_people": "Kan ikke søge i personer", - "cant_search_places": "Kan ikke søge i steder", "change_date": "Ændr dato", "change_expiration_time": "Ændr udløbstidspunkt", "change_location": "Ændr sted", @@ -425,7 +433,9 @@ "collapse_all": "Klap alle sammen", "color": "Farve", "color_theme": "Farvetema", + "comment_deleted": "Kommentar slettet", "comment_options": "Kommentarindstillinger", + "comments_and_likes": "Kommentarer og likes", "comments_are_disabled": "Kommentarer er slået fra", "confirm": "Bekræft", "confirm_admin_password": "Bekræft administratoradgangskode", @@ -481,6 +491,7 @@ "direction": "Retning", "disabled": "Deaktiveret", "disallow_edits": "Deaktivér redigeringer", + "discord": "Discord", "discover": "Opdag", "dismiss_all_errors": "Afvis alle fejl", "dismiss_error": "Afvis fejl", @@ -488,6 +499,7 @@ "display_order": "Display-rækkefølge", "display_original_photos": "Vis originale billeder", "display_original_photos_setting_description": "Foretræk at vise det originale billede frem for miniaturebilleder når den originale fil er web-kompatibelt. Dette kan gøre billedvisning langsommere.", + "do_not_show_again": "Vis ikke denne besked igen", "done": "Færdig", "download": "Hent", "download_settings": "Download", @@ -495,13 +507,7 @@ "downloading": "Downloader", "duplicates": "Duplikater", "duration": "Varighed", - "durations": { - "days": "{days, plural, one {dag} other {{days, number} dage}}", - "hours": "{hours, plural, one {time} other {{hours, number} timer}}", - "minutes": "{minutes, plural, one {minut} other {{minutes, number} minutter}}", - "months": "{months, plural, one {måned} other {{months, number} måneder}}", - "years": "{years, plural, one {år} other {{years, number} år}}" - }, + "edit": "Rediger", "edit_album": "Redigér album", "edit_avatar": "Redigér avatar", "edit_date": "Redigér dato", @@ -519,21 +525,40 @@ "edit_user": "Redigér bruger", "edited": "Redigeret", "editor": "Redaktør", + "editor_close_without_save_prompt": "Ændringerne vil ikke blive gemt", + "editor_close_without_save_title": "Luk editor?", + "editor_crop_tool_h2_rotation": "Rotation", "email": "E-mail", - "empty": "", - "empty_album": "Tomt album", "empty_trash": "Tøm papirkurv", "enable": "Aktivér", "enabled": "Aktiveret", "end_date": "Slutdato", "error": "Fejl", "error_loading_image": "Fejl ved indlæsning af billede", + "error_title": "Fejl - Noget gik galt", "errors": { + "cannot_navigate_next_asset": "Kan ikke navigere til næste mediefil", + "cannot_navigate_previous_asset": "Kan ikke navigere til forrige mediefil", "cleared_jobs": "Ryddede opgaver for: {job}", + "error_adding_assets_to_album": "Fejl i tilføjelse af mediefiler til album", + "error_adding_users_to_album": "Fejl i tilføjelse af brugere til album", + "error_deleting_shared_user": "Fejl i sletning af delt bruger", + "error_downloading": "Fejl i download af {filename}", + "error_hiding_buy_button": "Fejl i skjulning af køb-knap", + "error_removing_assets_from_album": "Fejl i fjernelse af mediefiler fra album. Tjek konsol for flere detaljer", "exclusion_pattern_already_exists": "Denne udelukkelsesmønster findes allerede.", "failed_job_command": "Kommando {command} slog fejl for opgave: {job}", + "failed_to_create_album": "Oprettelse af album mislykkedes", + "failed_to_create_shared_link": "Oprettelse af delt link mislykkedes", + "failed_to_edit_shared_link": "Redigering af delt link mislykkedes", + "failed_to_load_asset": "Indlæsning af mediefil mislykkedes", + "failed_to_load_assets": "Indlæsning af mediefiler mislykkedes", + "failed_to_load_people": "Indlæsning af personer mislykkedes", + "failed_to_remove_product_key": "Fjernelse af produktnøgle mislykkedes", "import_path_already_exists": "Denne importsti findes allerede.", + "incorrect_email_or_password": "Forkert email eller kodeord", "paths_validation_failed": "{paths, plural, one {# sti} other {# stier}} slog fejl ved validering", + "profile_picture_transparent_pixels": "Profilbilleder kan ikke have gennemsigtige pixels. Zoom venligst ind og/eller flyt billedet.", "quota_higher_than_disk_size": "Du har sat en kvote der er større end disken", "repair_unable_to_check_items": "Kunne ikke tjekke {count, select, one {element} other {elementer}}", "unable_to_add_album_users": "Ikke i stand til at tilføje brugere til album", @@ -545,8 +570,6 @@ "unable_to_change_date": "Ikke i stand til at ændre dato", "unable_to_change_location": "Ikke i stand til at ændre sted", "unable_to_change_password": "Kunne ikke ændre adgangskode", - "unable_to_check_item": "", - "unable_to_check_items": "", "unable_to_copy_to_clipboard": "Kan ikke kopiere til udklipsholder, sørg for at du tilgår siden gennem https", "unable_to_create_admin_account": "", "unable_to_create_api_key": "Kunne ikke oprette ny API-nøgle", @@ -554,6 +577,7 @@ "unable_to_create_user": "Ikke i stand til at oprette bruger", "unable_to_delete_album": "Ikke i stand til at slette album", "unable_to_delete_asset": "Kan ikke slette mediefil", + "unable_to_delete_assets": "Fejl i sletning af mediefiler", "unable_to_delete_exclusion_pattern": "Kunne ikke slette udelukkelsesmønster", "unable_to_delete_import_path": "Kunne ikke slette importsti", "unable_to_delete_shared_link": "Kunne ikke slette delt link", @@ -573,12 +597,10 @@ "unable_to_refresh_user": "Ikke i stand til at genopfriske bruger", "unable_to_remove_album_users": "Ikke i stand til at fjerne brugere fra album", "unable_to_remove_api_key": "Kunne ikke fjerne API-nøgle", - "unable_to_remove_comment": "", "unable_to_remove_deleted_assets": "Kunne ikke fjerne offlinefiler", "unable_to_remove_library": "Ikke i stand til at fjerne bibliotek", "unable_to_remove_partner": "Ikke i stand til at fjerne partner", "unable_to_remove_reaction": "Ikke i stand til at reaktion", - "unable_to_remove_user": "", "unable_to_repair_items": "Ikke i stand til at reparere ting", "unable_to_reset_password": "Ikke i stand til at nulstille adgangskode", "unable_to_resolve_duplicate": "Kunne ikke opklare duplikat", @@ -602,52 +624,51 @@ "unable_to_update_timeline_display_status": "Kunne ikke opdate status for tidslinjevisning", "unable_to_update_user": "Ikke i stand til at opdatere bruger" }, - "every_day_at_onepm": "", - "every_night_at_midnight": "", - "every_night_at_twoam": "", - "every_six_hours": "", + "exif": "Exif", "exit_slideshow": "Forlad slideshow", "expand_all": "Udvid alle", "expire_after": "Udløb efter", "expired": "Udløbet", + "expires_date": "Udløber {date}", "explore": "Udforsk", "export": "Eksportér", "export_as_json": "Eksportér som JSON", "extension": "Udvidelse", "external": "Ekstern", "external_libraries": "Eksterne biblioteker", - "failed_to_get_people": "At hente personer slog fejl", "favorite": "Favorit", "favorite_or_unfavorite_photo": "Tilføj eller fjern fra yndlingsbilleder", "favorites": "Favoritter", - "feature": "", "feature_photo_updated": "Forsidebillede uploadet", - "featurecollection": "", + "features": "Funktioner", + "features_setting_description": "Administrer app-funktioner", "file_name": "Filnavn", "file_name_or_extension": "Filnavn eller filtype", "filename": "Filnavn", - "files": "", "filetype": "Filtype", "filter_people": "Filtrér personer", "find_them_fast": "Find dem hurtigt med søgning via navn", "fix_incorrect_match": "Fix forkert match", - "force_re-scan_library_files": "Tving genskanning af alle biblioteksfiler", + "folders": "Mapper", "forward": "Fremad", "general": "Generel", "get_help": "Få hjælp", "getting_started": "Kom godt i gang", "go_back": "Gå tilbage", "go_to_search": "Gå til søgning", - "go_to_share_page": "Gå til delingsside", "group_albums_by": "Gruppér albummer efter...", + "group_no": "Ingen gruppering", "has_quota": "Har kvote", + "hi_user": "Hej {name} ({email})", + "hide_all_people": "Skjul alle personer", "hide_gallery": "Gem galleri", + "hide_named_person": "Skjul person {name}", "hide_password": "Gem adgangskode", "hide_person": "Gem person", + "hide_unnamed_people": "Skjul unavngivne personer", "host": "Host", "hour": "Time", "image": "Billede", - "img": "", "immich_logo": "Immich logo", "immich_web_interface": "Immich webinterface", "import_from_json": "Importér fra JSON", @@ -666,13 +687,14 @@ }, "invite_people": "Inviter personer", "invite_to_album": "Inviter til album", - "job_settings_description": "", "jobs": "Opgaver", "keep": "Behold", + "keep_all": "Behold alle", "keyboard_shortcuts": "Tastaturgenveje", "language": "Sprog", "language_setting_description": "Vælg dit foretrukne sprog", "last_seen": "Sidst set", + "latest_version": "Seneste version", "leave": "Forlad", "let_others_respond": "Lad andre svare", "level": "Niveau", @@ -687,7 +709,12 @@ "loading_search_results_failed": "At loade søgeresultater slog fejl", "log_out": "Log ud", "log_out_all_devices": "Log ud af alle enheder", + "logged_out_all_devices": "Logget ud af alle enheder", + "logged_out_device": "Logget ud af enhed", + "login": "Log ind", "login_has_been_disabled": "Login er blevet deaktiveret.", + "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?", "look": "Kig", "loop_videos": "Gentag videoer", "loop_videos_description": "Aktivér for at genafspille videoer automatisk i detaljeret visning.", @@ -721,15 +748,19 @@ "name": "Navn", "name_or_nickname": "Navn eller kælenavn", "never": "aldrig", + "new_album": "Nyt album", "new_api_key": "Ny API-nøgle", "new_password": "Ny adgangskode", "new_person": "Ny person", "new_user_created": "Ny bruger oprettet", + "new_version_available": "NY VERSION TILGÆNGELIG", "newest_first": "Nyeste først", "next": "Næste", "next_memory": "Næste minde", "no": "Nej", "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 fotos for at gemme dem væk fra dit Billed-view", "no_assets_message": "KLIK FOR AT UPLOADE DIT FØRSTE BILLEDE", "no_duplicates_found": "Ingen duplikater fundet.", @@ -740,6 +771,7 @@ "no_name": "Intet navn", "no_places": "Ingen steder", "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", "not_in_any_album": "Ikke i noget album", "note_apply_storage_label_to_previously_uploaded assets": "Bemærk: For at anvende Lagringsmærkat på tidligere uploadede medier, kør", @@ -749,17 +781,23 @@ "notifications": "Notifikationer", "notifications_setting_description": "Administrér notifikationer", "oauth": "OAuth", + "official_immich_resources": "Officielle Immich-ressourcer", "offline": "Offline", "offline_paths": "Offline-stier", "offline_paths_description": "Disse resultater kan være på grund af manuel sletning af filer, som ikke er en del af et eksternt bibliotek.", "ok": "Ok", "oldest_first": "Ældste først", + "onboarding_privacy_description": "Følgende (valgfrie) funktioner er afhængige af eksterne tjenester, og kan til enhver tid deaktiveres i administrationsindstillingerne.", + "onboarding_welcome_user": "Velkommen, {user}", "online": "Online", "only_favorites": "Kun favoritter", - "only_refreshes_modified_files": "Kun genopfrisk ændrede filer", + "open_in_map_view": "Åben i kortvisning", + "open_in_openstreetmap": "Åben i OpenStreetMap", "open_the_search_filters": "Åbn søgefiltre", "options": "Handlinger", + "or": "eller", "organize_your_library": "Organisér dit bibliotek", + "original": "original", "other": "Andet", "other_devices": "Andre enheder", "other_variables": "Andre variable", @@ -787,11 +825,11 @@ "pending": "Afventer", "people": "Personer", "people_sidebar_description": "Vis et link til Personer i sidepanelet", - "perform_library_tasks": "", "permanent_deletion_warning": "Advarsel om permanent sletning", "permanent_deletion_warning_setting_description": "Vis en advarsel, når medier slettes permanent", "permanently_delete": "Slet permanent", "permanently_deleted_asset": "Permanent slettet medie", + "person": "Person", "photos": "Billeder", "photos_count": "{count, plural, one {{count, number} Billede} other {{count, number} Billeder}}", "photos_from_previous_years": "Billeder fra tidligere år", @@ -802,7 +840,6 @@ "play_memories": "Afspil minder", "play_motion_photo": "Afspil bevægelsesbillede", "play_or_pause_video": "Afspil eller paus video", - "point": "", "port": "Port", "preset": "Forudindstilling", "preview": "Forhåndsvisning", @@ -812,8 +849,6 @@ "primary": "Primære", "profile_picture_set": "Profilbillede sat.", "public_share": "Offentlig deling", - "range": "", - "raw": "", "reaction_options": "Reaktionsindstillinger", "read_changelog": "Læs ændringslog", "recent": "For nylig", @@ -836,7 +871,6 @@ "reset": "Nulstil", "reset_password": "Nulstil adgangskode", "reset_people_visibility": "Nulstil personsynlighed", - "reset_settings_to_default": "", "restore": "Gendan", "restore_all": "Gendan alle", "restore_user": "Gendan bruger", @@ -850,8 +884,6 @@ "saved_settings": "Gemte indstillinger", "say_something": "Skriv noget", "scan_all_libraries": "Skan gennem alle biblioteker", - "scan_all_library_files": "Genskan alle biblioteksfiler", - "scan_new_library_files": "Skan nye biblioteksfiler", "scan_settings": "Skanningsindstillinger", "search": "Søg", "search_albums": "Søg i albummer", @@ -882,7 +914,6 @@ "selected": "Valgt", "send_message": "Send besked", "send_welcome_email": "Send velkomstemail", - "server": "Server", "server_stats": "Serverstatus", "set": "Sæt", "set_as_album_cover": "Sæt som albumcover", @@ -953,7 +984,6 @@ "to_favorite": "Gør til favorit", "toggle_settings": "Slå indstillinger til eller fra", "toggle_theme": "Slå mørkt tema til eller fra", - "toggle_visibility": "Slå synlighed til eller fra", "total_usage": "Samlet forbrug", "trash": "Papirkurv", "trash_all": "Smid alle ud", @@ -961,11 +991,9 @@ "trashed_items_will_be_permanently_deleted_after": "Mediefiler i skraldespanden vil blive slettet permanent efter {days, plural, one {# dag} other {# dage}}.", "type": "Type", "unarchive": "Afakivér", - "unarchived": "Uarkiveret", "unfavorite": "Fjern favorit", "unhide_person": "Hold op med at gemme person væk", "unknown": "Ukendt", - "unknown_album": "Ukendt album", "unknown_year": "Ukendt år", "unlimited": "Ubegrænset", "unlink_oauth": "Frakobl OAuth", @@ -983,6 +1011,8 @@ "user": "Bruger", "user_id": "Bruger-ID", "user_usage_detail": "Detaljer om brugers forbrug", + "user_usage_stats": "Konto anvendelsesstatistik", + "user_usage_stats_description": "Vis konto anvendelsesstatistik", "username": "Brugernavn", "users": "Brugere", "utilities": "Værktøjer", @@ -999,7 +1029,6 @@ "view_links": "Vis links", "view_next_asset": "Se næste medie", "view_previous_asset": "Se forrige medie", - "viewer": "Viewer", "waiting": "Venter", "week": "Uge", "welcome": "Velkommen", diff --git a/i18n/de.json b/i18n/de.json index 5bff3eb817a9f..7d6bffba91749 100644 --- a/i18n/de.json +++ b/i18n/de.json @@ -11,7 +11,7 @@ "add": "Hinzufügen", "add_a_description": "Beschreibung hinzufügen", "add_a_location": "Standort hinzufügen", - "add_a_name": "Namen hinzufügen", + "add_a_name": "Name hinzufügen", "add_a_title": "Titel hinzufügen", "add_exclusion_pattern": "Ausschlussmuster hinzufügen", "add_import_path": "Importpfad hinzufügen", @@ -23,6 +23,7 @@ "add_to": "Hinzufügen zu ...", "add_to_album": "Zu Album hinzufügen", "add_to_shared_album": "Zu geteiltem Album hinzufügen", + "add_url": "URL hinzufügen", "added_to_archive": "Zum Archiv hinzugefügt", "added_to_favorites": "Zu Favoriten hinzugefügt", "added_to_favorites_count": "{count, number} zu Favoriten hinzugefügt", @@ -34,6 +35,11 @@ "authentication_settings_disable_all": "Bist du sicher, dass du alle Anmeldemethoden deaktivieren willst? Die Anmeldung wird vollständig deaktiviert.", "authentication_settings_reenable": "Nutze einen Server-Befehl zur Reaktivierung.", "background_task_job": "Hintergrund-Aufgaben", + "backup_database": "Datenbank sichern", + "backup_database_enable_description": "Sicherung der Datenbank aktivieren", + "backup_keep_last_amount": "Anzahl der aufzubewahrenden früheren Sicherungen", + "backup_settings": "Datensicherungs-Einstellungen", + "backup_settings_description": "Datensicherungs-Einstellungen verwalten", "check_all": "Alle überprüfen", "cleared_jobs": "Folgende Aufgaben zurückgesetzt: {job}", "config_set_by_file": "Ist derzeit in einer Konfigurationsdatei festgelegt", @@ -43,9 +49,10 @@ "confirm_reprocess_all_faces": "Bist du sicher, dass du alle Gesichter erneut verarbeiten möchtest? Dies löscht auch alle bereits benannten Personen.", "confirm_user_password_reset": "Bist du sicher, dass du das Passwort für {user} zurücksetzen möchtest?", "create_job": "Aufgabe erstellen", - "crontab_guru": "Crontab Guru", + "cron_expression": "Cron-Ausdruck", + "cron_expression_description": "Stellen Sie das Scanintervall im Cron-Format ein. Weitere Informationen finden Sie beispielsweise unter Crontab Guru", + "cron_expression_presets": "Cron-Ausdruck-Vorlagen", "disable_login": "Login deaktvieren", - "disabled": "Deaktiviert", "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.", "external_library_created_at": "Externe Bibliothek (erstellt am {date})", @@ -63,22 +70,15 @@ "image_prefer_wide_gamut": "Breites Spektrum bevorzugen", "image_prefer_wide_gamut_setting_description": "Verwendung von Display P3 (DCI-P3) für Miniaturansichten. Dadurch bleibt die Lebendigkeit von Bildern mit breiten Farbräumen besser erhalten, aber die Bilder können auf älteren Geräten mit einer älteren Browserversion etwas anders aussehen. sRGB-Bilder werden im sRGB-Format belassen, um Farbverschiebungen zu vermeiden.", "image_preview_description": "Mittelgroßes Bild mit entfernten Metadaten, das bei der Betrachtung einer einzelnen Datei und für maschinelles Lernen verwendet wird", - "image_preview_format": "Vorschauformat", "image_preview_quality_description": "Vorschauqualität von 1-100. Ein höherer Wert ist besser, erzeugt dadurch aber größere Dateien und kann die Reaktionsfähigkeit der App beeinträchtigen. Die Einstellung eines niedrigen Wertes kann dafür aber die Qualität des maschinellen Lernens beeinträchtigen.", - "image_preview_resolution": "Vorschau-Auflösung", - "image_preview_resolution_description": "Dies wird beim Anzeigen eines einzelnen Fotos und für das maschinelle Lernen verwendet. Höhere Auflösungen können mehr Details beibehalten, benötigen aber mehr Zeit für die Kodierung, haben größere Dateigrößen und können die Reaktionsfähigkeit der App beeinträchtigen.", "image_preview_title": "Vorschaueinstellungen", "image_quality": "Qualität", - "image_quality_description": "Bildqualität von 1-100. Höher bedeutet bessere Qualität, erzeugt aber größere Dateien. Diese Option betrifft die Vorschaubilder und Miniaturansichten.", "image_resolution": "Auflösung", "image_resolution_description": "Höhere Auflösungen können mehr Details erhalten, benötigen aber mehr Zeit für die Kodierung, haben größere Dateigrößen und können die Reaktionsfähigkeit von Anwendungen beeinträchtigen.", "image_settings": "Bildeinstellungen", "image_settings_description": "Qualität und Auflösung von generierten Bildern verwalten", "image_thumbnail_description": "Kleine Miniaturansicht mit entfernten Metadaten, die bei der Anzeige von Sammlungen von Fotos wie der Zeitleiste verwendet wird", - "image_thumbnail_format": "Miniaturansichts-Format", "image_thumbnail_quality_description": "Qualität der Miniaturansicht von 1-100. Höher ist besser, erzeugt aber größere Dateien und kann die Reaktionsfähigkeit der App beeinträchtigen.", - "image_thumbnail_resolution": "Miniaturansichts-Auflösung", - "image_thumbnail_resolution_description": "Dies wird bei der Anzeige von Bildergruppen („Zeitleiste“, „Albumansicht“ usw.) verwendet. Höhere Auflösungen können mehr Details beibehalten, benötigen aber mehr Zeit für die Kodierung, haben größere Dateigrößen und können die Reaktionsfähigkeit der App beeinträchtigen.", "image_thumbnail_title": "Miniaturansicht-Einstellungen", "job_concurrency": "{job} (Anzahl gleichzeitiger Prozesse)", "job_created": "Aufgabe erstellt", @@ -89,9 +89,6 @@ "jobs_delayed": "{jobCount, plural, other {# verzögert}}", "jobs_failed": "{jobCount, plural, other {# fehlgeschlagen}}", "library_created": "Bibliothek erstellt: {library}", - "library_cron_expression": "Cron-Ausdruck", - "library_cron_expression_description": "Lege das Überprüfungsintervall mit Hilfe des cron-Formats fest. Für weitere Informationen siehe z.B. Crontab Guru", - "library_cron_expression_presets": "Cron-Expression Voreinstellungen", "library_deleted": "Bibliothek gelöscht", "library_import_path_description": "Gib einen Ordner für den Import an. Dieser Ordner, einschließlich der Unterordner, wird nach Bildern und Videos durchsucht.", "library_scanning": "Periodisches Scannen", @@ -134,7 +131,7 @@ "machine_learning_smart_search_description": "Semantische Bildsuche mittels CLIP-Einbettungen", "machine_learning_smart_search_enabled": "Intelligente Suche aktivieren", "machine_learning_smart_search_enabled_description": "Ist diese Option deaktiviert, werden die Bilder nicht für die intelligente Suche verwendet.", - "machine_learning_url_description": "Server-URL für maschinelles Lernen", + "machine_learning_url_description": "Die URL des Servers für maschinelles Lernen. Wenn mehr als eine URL angegeben wird, wird jeder Server einzeln ausprobiert, bis einer erfolgreich antwortet, und zwar in der Reihenfolge vom ersten bis zum letzten.", "manage_concurrency": "Gleichzeitige Ausführungen verwalten", "manage_log_settings": "Log-Einstellungen verwalten", "map_dark_style": "Dunkler Stil", @@ -215,7 +212,6 @@ "refreshing_all_libraries": "Alle Bibliotheken aktualisieren", "registration": "Admin-Registrierung", "registration_description": "Da du der erste Benutzer im System bist, wirst du als Admin zugewiesen und bist für administrative Aufgaben zuständig. Weitere Benutzer werden von dir erstellt.", - "removing_deleted_files": "Offline-Dateien entfernen", "repair_all": "Alle reparieren", "repair_matched_items": "{count, plural, one {# Eintrag} other {# Einträge}} gefunden", "repaired_items": "{count, plural, one {# Eintrag} other {# Einträge}} repariert", @@ -223,12 +219,12 @@ "reset_settings_to_default": "Einstellungen auf Standard zurücksetzen", "reset_settings_to_recent_saved": "Einstellungen auf die zuletzt gespeicherten Einstellungen zurücksetzen", "scanning_library": "Bibliothek scannen", - "scanning_library_for_changed_files": "Untersuche Bibliothek auf geänderte Dateien", - "scanning_library_for_new_files": "Untersuche Bibliothek auf neue Dateien", "search_jobs": "Aufgaben suchen...", "send_welcome_email": "Begrüssungsmail senden", "server_external_domain_settings": "Externe Domain", "server_external_domain_settings_description": "Domäne für öffentlich freigegebene Links, einschließlich http(s)://", + "server_public_users": "Öffentliche Benutzer", + "server_public_users_description": "Beim Hinzufügen eines Benutzers zu freigegebenen Alben werden alle Benutzer (Name und E-Mail) aufgelistet. Wenn diese Option deaktiviert ist, steht die Benutzerliste nur Administratoren zur Verfügung.", "server_settings": "Servereinstellungen", "server_settings_description": "Servereinstellungen verwalten", "server_welcome_message": "Willkommensnachricht", @@ -254,6 +250,16 @@ "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_preview": "Vorschau", + "template_email_settings": "E-Mail Vorlagen", + "template_email_settings_description": "Benutzerdefinierte E-Mail Benachrichtigungsvorlagen verwalten", + "template_email_update_album": "Album Vorlage aktualisieren", + "template_email_welcome": "Willkommen bei den E-Mail Vorlagen", + "template_settings": "Benachrichtigungsvorlagen", + "template_settings_description": "Benutzerdefinierte Vorlagen für Benachrichtigungen verwalten", "theme_custom_css_settings": "Benutzerdefiniertes CSS", "theme_custom_css_settings_description": "Mit Cascading Style Sheets (CSS) kann das Design von Immich angepasst werden.", "theme_settings": "Theme-Einstellungen", @@ -261,7 +267,6 @@ "these_files_matched_by_checksum": "Diese Dateien wurden anhand ihrer Prüfsummen abgeglichen", "thumbnail_generation_job": "Miniaturansichten generieren", "thumbnail_generation_job_description": "Diese Aufgabe erzeugt große, kleine und unscharfe Miniaturansichten für jede einzelne Datei, sowie Miniaturansichten für jede Person", - "transcode_policy_description": "Richtlinien, wann ein Video transkodiert werden soll. HDR-Videos werden immer transkodiert (außer wenn die Transkodierung deaktiviert ist).", "transcoding_acceleration_api": "Beschleunigungs-API", "transcoding_acceleration_api_description": "Die Schnittstelle welche mit dem Gerät interagiert, um die Transkodierung zu beschleunigen. Bei dieser Einstellung handelt es sich um die \"bestmögliche Lösung\": Bei einem Fehler wird auf die Software-Transkodierung zurückgegriffen. Abhängig von der verwendeten Hardware kann VP9 funktionieren oder auch nicht.", "transcoding_acceleration_nvenc": "NVENC (NVIDIA-GPU erforderlich)", @@ -313,8 +318,6 @@ "transcoding_threads_description": "Höhere Werte führen zu einer schnelleren Codierung, lassen dem Server aber weniger Spielraum für die Verarbeitung anderer Aufgaben, solange dies aktiv ist. Dieser Wert sollte nicht höher sein als die Anzahl der CPU-Kerne. Nutzt die maximale Auslastung, wenn der Wert auf 0 gesetzt ist.", "transcoding_tone_mapping": "Farbton-Mapping", "transcoding_tone_mapping_description": "Versucht, das Aussehen von HDR-Videos bei der Konvertierung in SDR beizubehalten. Jeder Algorithmus geht unterschiedliche Kompromisse bei Farbe, Details und Helligkeit ein. Hable bewahrt Details, Mobius bewahrt die Farbe und Reinhard bewahrt die Helligkeit.", - "transcoding_tone_mapping_npl": "Farbton-Mapping NPL", - "transcoding_tone_mapping_npl_description": "Die Farben werden so angepasst, dass sie für einen Bildschirm mit entsprechender Helligkeit normal aussehen. Entgegen der Annahme, dass niedrigere Werte die Helligkeit des Videos erhöhen und umgekehrt, wird die Helligkeit des Bildschirms ausgeglichen. Mit 0 wird dieser Wert automatisch eingestellt.", "transcoding_transcode_policy": "Transcodierungsrichtlinie", "transcoding_transcode_policy_description": "Richtlinie, wann ein Video transkodiert werden soll. HDR-Videos werden immer transkodiert (außer wenn die Transkodierung deaktiviert ist).", "transcoding_two_pass_encoding": "Two-Pass Codierung", @@ -395,7 +398,6 @@ "archive_or_unarchive_photo": "Foto archivieren bzw. Archivierung aufheben", "archive_size": "Archivgröße", "archive_size_description": "Archivgröße für Downloads konfigurieren (in GiB)", - "archived": "Archiviert", "archived_count": "{count, plural, other {# archiviert}}", "are_these_the_same_person": "Ist das dieselbe Person?", "are_you_sure_to_do_this": "Bist du sicher, dass du das tun willst?", @@ -416,9 +418,8 @@ "assets_added_to_album_count": "{count, plural, one {# Datei} other {# Dateien}} zum Album hinzugefügt", "assets_added_to_name_count": "{count, plural, one {# Element} other {# Elemente}} zu {hasName, select, true {{name}} other {neuem Album}} hinzugefügt", "assets_count": "{count, plural, one {# Datei} other {# Dateien}}", - "assets_moved_to_trash": "{count, plural, one {# Datei} other {# Dateien}} in den Papierkorb verschoben", "assets_moved_to_trash_count": "{count, plural, one {# Datei} other {# Dateien}} in den Papierkorb verschoben", - "assets_permanently_deleted_count": "{count, plural, one {# Datei} other {# Dateien}} dauerhaft gelöscht", + "assets_permanently_deleted_count": "{count, plural, one {# Datei} other {# Dateien}} endgültig gelöscht", "assets_removed_count": "{count, plural, one {# Datei} other {# Dateien}} entfernt", "assets_restore_confirmation": "Bist du sicher, dass du alle Dateien aus dem Papierkorb wiederherstellen willst? Diese Aktion kann nicht rückgängig gemacht werden! Beachte, dass Offline-Dateien auf diese Weise nicht wiederhergestellt werden können.", "assets_restored_count": "{count, plural, one {# Datei} other {# Dateien}} wiederhergestellt", @@ -434,7 +435,7 @@ "bugs_and_feature_requests": "Fehler & Verbesserungsvorschläge", "build": "Build", "build_image": "Build Abbild", - "bulk_delete_duplicates_confirmation": "Bist du sicher, dass du {count, plural, one {# duplizierte Datei} other {# duplizierte Dateien gemeinsam}} löschen möchtest? Dabei wird die größte Datei jeder Gruppe behalten und alle anderen Duplikate dauerhaft gelöscht. Diese Aktion kann nicht rückgängig gemacht werden!", + "bulk_delete_duplicates_confirmation": "Bist du sicher, dass du {count, plural, one {# duplizierte Datei} other {# duplizierte Dateien gemeinsam}} löschen möchtest? Dabei wird die größte Datei jeder Gruppe behalten und alle anderen Duplikate endgültig gelöscht. Diese Aktion kann nicht rückgängig gemacht werden!", "bulk_keep_duplicates_confirmation": "Bist du sicher, dass du {count, plural, one {# duplizierte Datei} other {# duplizierte Dateien}} behalten möchtest? Dies wird alle Duplikat-Gruppen auflösen ohne etwas zu löschen.", "bulk_trash_duplicates_confirmation": "Bist du sicher, dass du {count, plural, one {# duplizierte Datei} other {# duplizierte Dateien gemeinsam}} in den Papierkorb verschieben möchtest? Dies wird die größte Datei jeder Gruppe behalten und alle anderen Duplikate in den Papierkorb verschieben.", "buy": "Immich erwerben", @@ -446,10 +447,6 @@ "cannot_merge_people": "Personen können nicht zusammengeführt werden", "cannot_undo_this_action": "Diese Aktion kann nicht rückgängig gemacht werden!", "cannot_update_the_description": "Beschreibung kann nicht aktualisiert werden", - "cant_apply_changes": "Änderungen können nicht übernommen werden", - "cant_get_faces": "Es konnten keine Gesichter festgestellt werden", - "cant_search_people": "Es konnte nicht nach Personen gesucht werden", - "cant_search_places": "Es konnte nicht nach Orten gesucht werden", "change_date": "Datum ändern", "change_expiration_time": "Verfallszeitpunkt ändern", "change_location": "Ort ändern", @@ -481,6 +478,7 @@ "confirm": "Bestätigen", "confirm_admin_password": "Administrator Passwort bestätigen", "confirm_delete_shared_link": "Bist du sicher, dass du diesen geteilten Link löschen willst?", + "confirm_keep_this_delete_others": "Alle anderen Dateien im Stapel bis auf diese werden gelöscht. Bist du sicher, dass du fortfahren möchten?", "confirm_password": "Passwort bestätigen", "contain": "Vollständig", "context": "Kontext", @@ -526,10 +524,11 @@ "delete": "Löschen", "delete_album": "Album löschen", "delete_api_key_prompt": "Bist du sicher, dass du diesen API-Schlüssel löschen willst?", - "delete_duplicates_confirmation": "Bist du sicher, dass du diese Duplikate dauerhaft löschen willst?", + "delete_duplicates_confirmation": "Bist du sicher, dass du diese Duplikate endgültig löschen willst?", "delete_key": "Schlüssel löschen", "delete_library": "Bibliothek löschen", "delete_link": "Link löschen", + "delete_others": "Andere löschen", "delete_shared_link": "geteilten Link löschen", "delete_tag": "Tag löschen", "delete_tag_confirmation_prompt": "Bist du sicher, dass der Tag {tagName} gelöscht werden soll?", @@ -563,13 +562,6 @@ "duplicates": "Duplikate", "duplicates_description": "Löse jede Gruppe auf, indem du angibst, welche, wenn überhaupt, Duplikate sind", "duration": "Dauer", - "durations": { - "days": "{days, plural, one {Tag} other {{days, number} Tage}}", - "hours": "{hours, plural, one {eine Stunde} other {{hours, number} Stunden}}", - "minutes": "{minutes, plural, one {eine minute} other {{minutes, number} minuten}}", - "months": "{months, plural, one {ein Monat} other {{months, number} Monate}}", - "years": "{years, plural, one {ein Jahr} other {{years, number} Jahre}}" - }, "edit": "Bearbeiten", "edit_album": "Album bearbeiten", "edit_avatar": "Avatar bearbeiten", @@ -594,10 +586,8 @@ "editor_crop_tool_h2_aspect_ratios": "Seitenverhältnisse", "editor_crop_tool_h2_rotation": "Drehung", "email": "E-Mail", - "empty": "Leer", - "empty_album": "Leeres Album", "empty_trash": "Papierkorb leeren", - "empty_trash_confirmation": "Bist du sicher, dass du den Papierkorb leeren willst?\nDies entfernt alle Dateien im Papierkorb permanent aus Immich und kann nicht rückgängig gemacht werden!", + "empty_trash_confirmation": "Bist du sicher, dass du den Papierkorb leeren willst?\nDies entfernt alle Dateien im Papierkorb endgültig aus Immich und kann nicht rückgängig gemacht werden!", "enable": "Aktivieren", "enabled": "Aktiviert", "end_date": "Enddatum", @@ -629,6 +619,7 @@ "failed_to_create_shared_link": "Geteilter Link konnte nicht erstellt werden", "failed_to_edit_shared_link": "Geteilter Link konnte nicht bearbeitet werden", "failed_to_get_people": "Personen konnten nicht abgerufen werden", + "failed_to_keep_this_delete_others": "Fehler beim Löschen der anderen Dateien", "failed_to_load_asset": "Fehler beim Laden der Datei", "failed_to_load_assets": "Fehler beim Laden der Dateien", "failed_to_load_people": "Fehler beim Laden von Personen", @@ -656,8 +647,6 @@ "unable_to_change_location": "Ort kann nicht verändert werden", "unable_to_change_password": "Passwort konnte nicht geändert werden", "unable_to_change_visibility": "Sichtbarkeit von {count, plural, one {einer Person} other {# Personen}} konnte nicht geändert werden", - "unable_to_check_item": "Objekt kann nicht überprüft werden", - "unable_to_check_items": "Objekte konnten nicht überprüft werden", "unable_to_complete_oauth_login": "OAuth-Anmeldung konnte nicht abgeschlossen werden", "unable_to_connect": "Verbindung konnte nicht hergestellt werden", "unable_to_connect_to_server": "Verbindung zum Server konnte nicht hergestellt werden", @@ -698,12 +687,10 @@ "unable_to_remove_album_users": "Mitglieder der Alben können nicht entfernt werden", "unable_to_remove_api_key": "API-Schlüssel konnte nicht entfernt werden", "unable_to_remove_assets_from_shared_link": "Dateien konnten nicht von geteiltem Link entfernt werden", - "unable_to_remove_comment": "Kommentar kann nicht entfernt werden", "unable_to_remove_deleted_assets": "Offline-Dateien konnten nicht entfernt werden", "unable_to_remove_library": "Bibliothek kann nicht entfernt werden", "unable_to_remove_partner": "Partner kann nicht entfernt werden", "unable_to_remove_reaction": "Reaktion kann nicht entfernt werden", - "unable_to_remove_user": "Benutzer kann nicht entfernt werden", "unable_to_repair_items": "Objekte können nicht repariert werden", "unable_to_reset_password": "Passwort kann nicht zurückgesetzt werden", "unable_to_resolve_duplicate": "Duplikate können nicht aufgelöst werden", @@ -733,16 +720,12 @@ "unable_to_update_user": "Der Nutzer konnte nicht aktualisiert werden", "unable_to_upload_file": "Datei konnte nicht hochgeladen werden" }, - "every_day_at_onepm": "Täglich 13.00 Uhr", - "every_night_at_midnight": "Täglich um Mitternacht", - "every_night_at_twoam": "Jede Nacht um 2.00 Uhr", - "every_six_hours": "Alle 6 Stunden", "exif": "EXIF", "exit_slideshow": "Diashow beenden", "expand_all": "Alle aufklappen", "expire_after": "Verfällt nach", "expired": "Verfallen", - "expires_date": "Läuft am {date} ab", + "expires_date": "Läuft {date} ab", "explore": "Erkunden", "explorer": "Datei-Explorer", "export": "Exportieren", @@ -751,33 +734,28 @@ "external": "Extern", "external_libraries": "Externe Bibliotheken", "face_unassigned": "Nicht zugewiesen", - "failed_to_get_people": "Personen konnten nicht ermittelt werden", + "failed_to_load_assets": "Laden der Assets fehlgeschlagen", "favorite": "Favorit", "favorite_or_unfavorite_photo": "Favorisiertes oder nicht favorisiertes Foto", "favorites": "Favoriten", - "feature": "Funktion", "feature_photo_updated": "Profilbild aktualisiert", - "featurecollection": "Funktionssammlung", "features": "Funktionen", "features_setting_description": "Funktionen der App verwalten", "file_name": "Dateiname", "file_name_or_extension": "Dateiname oder -erweiterung", "filename": "Dateiname", - "files": "", "filetype": "Dateityp", "filter_people": "Personen filtern", "find_them_fast": "Finde sie schneller mit der Suche nach Namen", "fix_incorrect_match": "Fehlerhafte Übereinstimmung beheben", "folders": "Ordner", "folders_feature_description": "Durchsuchen der Ordneransicht für Fotos und Videos im Dateisystem", - "force_re-scan_library_files": "Erzwingen des erneuten Scannens aller Bibliotheksdateien", "forward": "Vorwärts", "general": "Allgemein", "get_help": "Hilfe erhalten", "getting_started": "Erste Schritte", "go_back": "Zurück", "go_to_search": "Zur Suche gehen", - "go_to_share_page": "Zur Freigabeseite gehen", "group_albums_by": "Alben gruppieren nach...", "group_no": "Keine Gruppierung", "group_owner": "Gruppierung nach Besitzer", @@ -803,10 +781,6 @@ "image_alt_text_date_place_2_people": "{isVideo, select, true {Video} other {Bild}} aufgenommen in {city}, {country} mit {person1} und {person2} am {date}", "image_alt_text_date_place_3_people": "{isVideo, select, true {Video} other {Bild}} aufgenommen in {city}, {country} mit {person1}, {person2}, und {person3} am {date}", "image_alt_text_date_place_4_or_more_people": "{isVideo, select, true {Video} other {Bild}} aufgenommen in {city}, {country} mit {person1}, {person2}, und {additionalCount, number} anderen am {date}", - "image_alt_text_people": "{count, plural, =1 {mit {person1}} =2 {mit {person1} und {person2}} =3 {mit {person1}, {person2} und {person3}} other {mit {person1}, {person2} und {others, number} anderen}}", - "image_alt_text_place": "in {city}, {country}", - "image_taken": "{isVideo, select, true {Video aufgenommen} other {Bild aufgenommen}}", - "img": "Img", "immich_logo": "Immich-Logo", "immich_web_interface": "Immich-Web-Oberfläche", "import_from_json": "Aus JSON importieren", @@ -827,10 +801,11 @@ "invite_people": "Personen einladen", "invite_to_album": "Zum Album einladen", "items_count": "{count, plural, one {# Eintrag} other {# Einträge}}", - "job_settings_description": "Parallelität von Jobs verwalten", "jobs": "Aufgaben", "keep": "Behalten", "keep_all": "Alle behalten", + "keep_this_delete_others": "Dieses behalten, andere löschen", + "kept_this_deleted_others": "Diese Datei behalten und {count, plural, one {# Datei} other {# Dateien}} gelöscht", "keyboard_shortcuts": "Tastenkürzel", "language": "Sprache", "language_setting_description": "Wähle deine bevorzugte Sprache", @@ -842,31 +817,6 @@ "level": "Level", "library": "Bibliothek", "library_options": "Bibliotheksoptionen", - "license_account_info": "Dein Account ist lizensiert", - "license_activated_subtitle": "Wir danken dir für die Unterstützung von Immich und Open-Source-Software", - "license_activated_title": "Deine Lizenz wurde erfolgreich aktiviert", - "license_button_activate": "Aktivieren", - "license_button_buy": "Kaufen", - "license_button_buy_license": "Lizenz erwerben", - "license_button_select": "Auswählen", - "license_failed_activation": "Die Aktivierung der Lizenz ist fehlgeschlagen. Bitte überprüfe deine E-Mail, um den korrekten Lizenzschlüssel zu finden!", - "license_individual_description_1": "1 Lizenz pro Benutzer auf einem beliebigen Server", - "license_individual_title": "Individuelle Lizenz", - "license_info_licensed": "Lizensiert", - "license_info_unlicensed": "Unlizensiert", - "license_input_suggestion": "Hast du bereits eine Lizenz? Gib den Key unten ein", - "license_license_subtitle": "Erwerbe eine Lizenz zur Unterstützung von Immich", - "license_license_title": "LIZENZ", - "license_lifetime_description": "Lebenslange Lizenz", - "license_per_server": "Pro Server", - "license_per_user": "Pro Nutzer", - "license_server_description_1": "1 Lizenz pro Server", - "license_server_description_2": "Lizenz für alle Nutzer des Servers", - "license_server_title": "Serverlizenz", - "license_trial_info_1": "Du verwendest eine unlizenzierte Version von Immich", - "license_trial_info_2": "Du benutzt Immich seit ungefähr", - "license_trial_info_3": "{accountAge, plural, one {# Tag} other {# Tage}}", - "license_trial_info_4": "Bitte erwäge den Kauf einer Lizenz, um die kontinuierliche Weiterentwicklung des Dienstes zu unterstützen", "light": "Hell", "like_deleted": "Like gelöscht", "link_motion_video": "Bewegungsvideo verknüpfen", @@ -971,7 +921,6 @@ "onboarding_welcome_user": "Willkommen, {user}", "online": "Online", "only_favorites": "Nur Favoriten", - "only_refreshes_modified_files": "Nur geänderte Dateien aktualisieren", "open_in_map_view": "In Kartenansicht öffnen", "open_in_openstreetmap": "In OpenStreetMap öffnen", "open_the_search_filters": "Die Suchfilter öffnen", @@ -1009,15 +958,13 @@ "people_edits_count": "{count, plural, one {# Person} other {# Personen}} bearbeitet", "people_feature_description": "Fotos und Videos nach Personen gruppiert durchsuchen", "people_sidebar_description": "Eine Verknüpfung zu Personen in der Seitenleiste anzeigen", - "perform_library_tasks": "", "permanent_deletion_warning": "Warnung vor endgültiger Löschung", - "permanent_deletion_warning_setting_description": "Anzeige einer Warnung beim permanenten Löschen von Objekten", - "permanently_delete": "Dauerhaft löschen", - "permanently_delete_assets_count": "{count, plural, one {Datei} other {Dateien}} dauerhaft gelöscht", - "permanently_delete_assets_prompt": "Bist du sicher, dass {count, plural, one {diese Datei} other {diese # Dateien}} dauerhaft gelöscht werden soll? Dadurch {count, plural, one {wird} other {werden}} diese auch aus deinen Alben entfernt.", - "permanently_deleted_asset": "Dauerhaft gelöschtes Objekt", - "permanently_deleted_assets": "{count, plural, one {# Objekt} other {# Objekte}} dauerhaft gelöscht", - "permanently_deleted_assets_count": "{count, plural, one {# Datei} other {# Dateien}} dauerhaft gelöscht", + "permanent_deletion_warning_setting_description": "Anzeige einer Warnung beim endgültigen Löschen von Objekten", + "permanently_delete": "Endgültig löschen", + "permanently_delete_assets_count": "{count, plural, one {Datei} other {Dateien}} endgültig löschen", + "permanently_delete_assets_prompt": "Bist du sicher, dass {count, plural, one {diese Datei} other {diese # Dateien}} endgültig gelöscht werden soll? Dadurch {count, plural, one {wird} other {werden}} diese auch aus deinen Alben entfernt.", + "permanently_deleted_asset": "Endgültig gelöschtes Objekt", + "permanently_deleted_assets_count": "{count, plural, one {# Datei} other {# Dateien}} endgültig gelöscht", "person": "Person", "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.", @@ -1032,7 +979,6 @@ "play_memories": "Erinnerungen abspielen", "play_motion_photo": "Bewegte Bilder abspielen", "play_or_pause_video": "Video abspielen oder pausieren", - "point": "Hinweis", "port": "Port", "preset": "Voreinstellung", "preview": "Vorschau", @@ -1077,12 +1023,10 @@ "purchase_server_description_2": "Unterstützerstatus", "purchase_server_title": "Server", "purchase_settings_server_activated": "Der Server-Produktschlüssel wird durch den Administrator verwaltet", - "range": "Reichweite", "rating": "Bewertung", "rating_clear": "Bewertung löschen", "rating_count": "{count, plural, one {# Stern} other {# Sterne}}", "rating_description": "Stellt die EXIF-Bewertung im Informationsbereich dar", - "raw": "RAW", "reaction_options": "Reaktionsmöglichkeiten", "read_changelog": "Changelog lesen", "reassign": "Neu zuweisen", @@ -1090,6 +1034,7 @@ "reassigned_assets_to_new_person": "{count, plural, one {# Datei wurde} other {# Dateien wurden}} einer neuen Person zugewiesen", "reassing_hint": "Markierte Dateien einer vorhandenen Person zuweisen", "recent": "Neuste", + "recent-albums": "Neuste Alben", "recent_searches": "Letzte Suchen", "refresh": "Aktualisieren", "refresh_encoded_videos": "Kodierte Videos aktualisieren", @@ -1111,6 +1056,7 @@ "remove_from_album": "Aus Album entfernen", "remove_from_favorites": "Aus Favoriten entfernen", "remove_from_shared_link": "Aus geteiltem Link entfernen", + "remove_url": "URL entfernen", "remove_user": "Nutzer entfernen", "removed_api_key": "API-Schlüssel {name} wurde entfernt", "removed_from_archive": "Aus dem Archiv entfernt", @@ -1127,7 +1073,6 @@ "reset": "Zurücksetzen", "reset_password": "Passwort zurücksetzen", "reset_people_visibility": "Sichtbarkeit von Personen zurücksetzen", - "reset_settings_to_default": "Einstellungen auf Standardwerte zurücksetzen", "reset_to_default": "Auf Standard zurücksetzen", "resolve_duplicates": "Duplikate entfernen", "resolved_all_duplicates": "Alle Duplikate aufgelöst", @@ -1147,9 +1092,7 @@ "saved_settings": "Einstellungen gespeichert", "say_something": "Etwas sagen", "scan_all_libraries": "Alle Bibliotheken scannen", - "scan_all_library_files": "Alle Bibliotheksdateien erneut scannen", "scan_library": "Scannen", - "scan_new_library_files": "Neue Bibliotheksdateien scannen", "scan_settings": "Scan-Einstellungen", "scanning_for_album": "Nach Alben scannen...", "search": "Suche", @@ -1192,7 +1135,6 @@ "selected_count": "{count, plural, other {# ausgewählt}}", "send_message": "Nachricht senden", "send_welcome_email": "Begrüssungsmail senden", - "server": "Server", "server_offline": "Server offline", "server_online": "Server online", "server_stats": "Server-Statistiken", @@ -1297,17 +1239,17 @@ "they_will_be_merged_together": "Sie werden zusammengeführt", "third_party_resources": "Drittanbieter-Quellen", "time_based_memories": "Zeitbasierte Erinnerungen", + "timeline": "Zeitleiste", "timezone": "Zeitzone", "to_archive": "Archivieren", "to_change_password": "Passwort ändern", "to_favorite": "Zu Favoriten hinzufügen", "to_login": "Anmelden", "to_parent": "Gehe zum Übergeordneten", - "to_root": "Zur Wurzel", "to_trash": "In den Papierkorb verschieben", "toggle_settings": "Einstellungen umschalten", "toggle_theme": "Dunkles Theme umschalten", - "toggle_visibility": "Sichtbarkeit umschalten", + "total": "Gesamt", "total_usage": "Gesamtnutzung", "trash": "Papierkorb", "trash_all": "Alle löschen", @@ -1317,12 +1259,10 @@ "trashed_items_will_be_permanently_deleted_after": "Gelöschte Objekte werden nach {days, plural, one {# Tag} other {# Tagen}} endgültig gelöscht.", "type": "Typ", "unarchive": "Entarchivieren", - "unarchived": "Unarchiviert", "unarchived_count": "{count, plural, other {# entarchiviert}}", "unfavorite": "Entfavorisieren", "unhide_person": "Person einblenden", "unknown": "Unbekannt", - "unknown_album": "Unbekanntes Album", "unknown_year": "Unbekanntes Jahr", "unlimited": "Unlimitiert", "unlink_motion_video": "Verknüpfung zum Bewegungsvideo aufheben", @@ -1354,13 +1294,13 @@ "use_custom_date_range": "Stattdessen einen benutzerdefinierten Datumsbereich verwenden", "user": "Nutzer", "user_id": "Nutzer-ID", - "user_license_settings": "Lizenz", - "user_license_settings_description": "Verwalte deine Lizenz", "user_liked": "{type, select, photo {Dieses Foto} video {Dieses Video} asset {Diese Datei} other {Dies}} gefällt {user}", "user_purchase_settings": "Kauf", "user_purchase_settings_description": "Kauf verwalten", "user_role_set": "{user} als {role} festlegen", "user_usage_detail": "Nutzungsdetails der Nutzer", + "user_usage_stats": "Statistiken zur Kontonutzung", + "user_usage_stats_description": "Statistiken zur Kontonutzung anzeigen", "username": "Nutzername", "users": "Benutzer", "utilities": "Hilfsmittel", @@ -1368,7 +1308,7 @@ "variables": "Variablen", "version": "Version", "version_announcement_closing": "Dein Freund, Alex", - "version_announcement_message": "Hallo Freund, es gibt eine neue Version dieser Anwendung. Bitte nimm dir Zeit, die Versionshinweise zu lesen und stelle sicher, dass deine docker-compose.yml- und .env-Konfiguration auf dem neuesten Stand ist, um Fehlkonfigurationen zu vermeiden, insbesondere wenn du WatchTower oder ein anderes Verfahren verwendest, das deine Anwendung automatisch aktualisiert.", + "version_announcement_message": "Hi! Es gibt eine neue Version von Immich. Bitte nimm dir Zeit, die Versionshinweise zu lesen, um Fehlkonfigurationen zu vermeiden, insbesondere wenn du WatchTower oder ein anderes Verfahren verwendest, das Immich automatisch aktualisiert.", "version_history": "Versionshistorie", "version_history_item": "{version} am {date} installiert", "video": "Video", @@ -1382,10 +1322,10 @@ "view_all_users": "Alle Nutzer anzeigen", "view_in_timeline": "In Zeitleiste anzeigen", "view_links": "Links anzeigen", + "view_name": "Ansicht", "view_next_asset": "Nächste Datei anzeigen", "view_previous_asset": "Vorherige Datei anzeigen", "view_stack": "Stapel anzeigen", - "viewer": "Zuschauer", "visibility_changed": "Sichtbarkeit für {count, plural, one {# Person} other {# Personen}} geändert", "waiting": "Wartend", "warning": "Warnung", diff --git a/i18n/el.json b/i18n/el.json index b29e95b9c4cc8..daad424022b18 100644 --- a/i18n/el.json +++ b/i18n/el.json @@ -10,11 +10,11 @@ "activity_changed": "Η δραστηριότητα είναι {enabled, select, true {ενεργοποιημένη} other {απενεργοποιημένη}}", "add": "Προσθήκη", "add_a_description": "Προσθήκη περιγραφής", - "add_a_location": "Προσθήκη μιας τοποθεσίας", + "add_a_location": "Προσθήκη μίας τοποθεσίας", "add_a_name": "Προσθήκη ονόματος", "add_a_title": "Προσθήκη τίτλου", - "add_exclusion_pattern": "Προσθήκη προτύπου αποκλεισμού", - "add_import_path": "Προσθήκη διαδρομής εισαγωγής", + "add_exclusion_pattern": "Προσθήκη μοτίβου αποκλεισμού", + "add_import_path": "Προσθήκη μονοπατιού εισαγωγής", "add_location": "Προσθήκη τοποθεσίας", "add_more_users": "Προσθήκη επιπλέον χρηστών", "add_partner": "Προσθήκη συνεργάτη", @@ -23,101 +23,100 @@ "add_to": "Προσθήκη σε...", "add_to_album": "Προσθήκη σε άλμπουμ", "add_to_shared_album": "Προσθήκη σε κοινόχρηστο άλμπουμ", - "added_to_archive": "Αρχειοθέτηση", + "add_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/**\".", - "asset_offline_description": "Αυτό το στοιχείο εξωτερικής βιβλιοθήκης δε βρίσκεται πλέον στο δίσκο και έχει μεταφερθεί στα σκουπίδια. Εάν το αρχείο έχει μετακινηθεί εντός της βιβλιοθήκης, ελέγξτε το χρονοδιάγραμμα σας για το νέο αντίστοιχο στοιχείο. Για να επαναφέρετε αυτό το στοιχείο, βεβαιωθείτε ότι το παρακάτω μονοπάτι αρχείου είναι προσβάσιμο από το Immich και ότι μπορεί να σαρώσει τη βιβλιοθήκη.", - "authentication_settings": "Ρυθμίσεις ελέγχου ταυτότητας", - "authentication_settings_description": "Διαχείριση κωδικού πρόσβασης, OAuth και άλλες ρυθμίσεις ελέγχου ταυτότητας", + "add_exclusion_pattern_description": "Προσθέστε μοτίβα αποκλεισμού. Υποστηρίζεται η επιλογή πολλών με *, **, και ?. Για να αγνοηθούν όλα τα αρχεία σε έναν φάκελο με το όνομα \"Raw\", χρησιμοποιήστε \"**/Raw/**\". Για να αγνοηθούν όλα τα αρχεία με κατάληξη \".tif\", χρησιμοποιήστε \"**/*.tif\". Για να αγνοηθεί μία απόλυτη διαδρομή, χρησιμοποιήστε \"/path/to/ignore/**\".", + "asset_offline_description": "Αυτό το στοιχείο εξωτερικής βιβλιοθήκης δε βρίσκεται πλέον στο δίσκο και έχει μεταφερθεί στα απορρίμματα. Εάν το αρχείο έχει μετακινηθεί εντός της βιβλιοθήκης, ελέγξτε το χρονολόγιο φωτογραφιών σας για το νέο αντίστοιχο στοιχείο. Για να επαναφέρετε αυτό το στοιχείο, βεβαιωθείτε ότι το παρακάτω μονοπάτι αρχείου είναι προσβάσιμο από το Immich και σαρώστε τη βιβλιοθήκη.", + "authentication_settings": "Ρυθμίσεις Ελέγχου Ταυτότητας", + "authentication_settings_description": "Διαχείριση κωδικού πρόσβασης, OAuth και άλλων ρυθμίσεων ελέγχου ταυτότητας", "authentication_settings_disable_all": "Είστε βέβαιοι ότι θέλετε να απενεργοποιήσετε όλες τις μεθόδους σύνδεσης; Η σύνδεση θα απενεργοποιηθεί πλήρως.", - "authentication_settings_reenable": "Για να επαναενεργοποιηθεί, χρησιμοποιήστε μία Server Command.", + "authentication_settings_reenable": "Για επανενεργοποίηση, χρησιμοποιήστε μία Εντολή Διακομιστή.", "background_task_job": "Εργασίες Παρασκηνίου", + "backup_database": "Δημιουργία Αντιγράφου Ασφαλείας της Βάσης Δεδομένων", + "backup_database_enable_description": "Ενεργοποίηση αντιγράφων ασφαλείας της βάσης δεδομένων", + "backup_keep_last_amount": "Αριθμός προηγούμενων αντιγράφων ασφαλείας για διατήρηση", + "backup_settings": "Ρυθμίσεις Αντιγράφων Ασφαλείας", + "backup_settings_description": "Διαχείρηση ρυθμίσεων των αντιγράφων ασφαλείας της βάσης δεδομένων", "check_all": "Έλεγχος Όλων", - "cleared_jobs": "Εκκαθάριση εργασιών για: {job}", - "config_set_by_file": "Η διαμόρφωση γίνεται προς το παρόν από ένα αρχείο config", + "cleared_jobs": "Εκκαθαρίστηκαν οι εργασίες για: {job}", + "config_set_by_file": "Η παραμετροποίηση γίνεται, προς το παρόν, μέσω ενός αρχείου παραμέτρων", "confirm_delete_library": "Είστε βέβαιοι ότι θέλετε να διαγράψετε τη βιβλιοθήκη {library};", - "confirm_delete_library_assets": "Είστε σίγουροι ότι θέλετε να διαγράψετε αυτή τη βιβλιοθήκη; Αυτό θα διαγράψει τα {count, plural, one {# contained asset} other {all # contained assets}} από το Immich και δεν μπορεί να αναιρεθεί. Τα αρχεία θα παραμείνουν στον δίσκο.", + "confirm_delete_library_assets": "Είστε βέβαιοι ότι θέλετε να διαγράψετε αυτή τη βιβλιοθήκη; Αυτό θα διαγράψει τα {count, plural, one {# contained asset} other {all # contained assets}} από το Immich και δεν μπορεί να αναιρεθεί. Τα αρχεία θα παραμείνουν στον δίσκο.", "confirm_email_below": "Για επιβεβαίωση, πληκτρολογήστε \"{email}\" παρακάτω", - "confirm_reprocess_all_faces": "Είστε βέβαιοι ότι θέλετε να επεξεργαστείτε ξανά όλα τα πρόσωπα; Αυτό θα διαγράψει επίσης άτομα με όνομα.", + "confirm_reprocess_all_faces": "Είστε βέβαιοι ότι θέλετε να επεξεργαστείτε ξανά όλα τα πρόσωπα; Αυτό θα εκκαθαρίσει ακόμα και τα άτομα στα οποία έχετε ήδη ορίσει το όνομα.", "confirm_user_password_reset": "Είστε βέβαιοι ότι θέλετε να επαναφέρετε τον κωδικό πρόσβασης του χρήστη {user};", "create_job": "Δημιουργία εργασίας", - "disable_login": "Απενεργοποίηση σύνδεσης κατά την είσοδο", - "duplicate_detection_job_description": "Εκτελέστε τη εκμάθηση μηχανής σε στοιχεία για να εντοπίσετε παρόμοιες εικόνες. Βασίζεται στην Έξυπνη Αναζήτηση", - "exclusion_pattern_description": "Τα πρότυπα αποκλεισμού σας επιτρέπουν να αγνοείται αρχεία κκαι φακέλους όσο σαρώνεται η βιβλιοθήκη. Αυτό είναι χρήσιμο εάν εχετε φακέλους που περιέχουν αρχεία που δεν θέλετε να εισαγάγετε, όπως αρχεία RAW.", + "cron_expression": "Σύνταξη Cron", + "cron_expression_description": "Ορίστε το διάστημα σάρωσης χρησιμοποιώντας τη μορφή cron. Για περισσότερες πληροφορίες, ανατρέξτε π.χ. στο Crontab Guru", + "cron_expression_presets": "Προκαθορισμένες εκφράσεις cron", + "disable_login": "Απενεργοποίηση σύνδεσης", + "duplicate_detection_job_description": "Εκτελέστε μηχανική μάθηση σε στοιχεία για να εντοπίσετε παρόμοιες εικόνες. Βασίζεται στην Έξυπνη Αναζήτηση", + "exclusion_pattern_description": "Τα μοτίβα αποκλεισμού σας επιτρέπουν να αγνοείται αρχεία και φακέλους κατά τη σάρωση της βιβλιοθήκης σας. Αυτό είναι χρήσιμο εάν εχετε φακέλους που περιέχουν αρχεία που δεν θέλετε να εισάγετε, όπως αρχεία RAW.", "external_library_created_at": "Εξωτερική βιβλιοθήκη (δημιουργήθηκε {date})", "external_library_management": "Διαχείριση Εξωτερικών Βιβλιοθηκών", - "face_detection": "Αναγνώριση προσώπου", - "face_detection_description": "Εντοπίστε τα πρόσωπα σε στοιχεία χρησιμοποιώντας μηχανική εκμάθηση. Για βίντεο, λαμβάνεται υπόψη μόνο η μικρογραφία. Η επιλογή \"Ανανέωση\" επεξεργάζεται εκ νέου όλα τα στοιχεία και η επιλογή \"Επαναφορά\", επιπλέον επαναφέρει ολα τα δεδομένα προσώπου. Η επιλογή \"Όσα Λείπουν\" προσθέτει στην ουρά στοιχεία που δεν έχουν υποστεί ακόμη επεξεργασία. Τα πρόσωπα που έχουν εντοπιστεί θα μπουν στην ουρά για την Αναγνώριση Προσώπου μετά την ολοκλήρωση της Ανίχνευσης Προσώπου, ομαδοποιώντας τα σε υπάρχοντα ή νέα άτομα.", - "facial_recognition_job_description": "Ομαδοποιήστε εντοπισμένα πρόσωπα σε άτομα. Αυτό το βήμα εκτελείται αφού ολοκληρωθεί η Ανίχνευση προσώπου. Η επιλογή \"Επαναφορά\" ομαδοποιεί εκ νέου όλα τα πρόσωπα. Η επιλογή \"Όσα Λείπουν\" ομαδοποιεί πρόσωπα που δεν έχουν αντιστοιχηθεί σε κάποιο άτομο.", - "failed_job_command": "Η Εντολή {command} απέτυχε για την εργασία: {job}", - "force_delete_user_warning": "ΠΡΟΕΙΔΟΠΟΙΗΣΗ: Αυτό θα αφαιρέσει άμεσα το χρήστη και όλα τα στοιχεία. Αυτό δεν μπορεί να αναιρεθεί και τα αρχεία δεν μπορούν να ανακτηθούν.", - "forcing_refresh_library_files": "Επιβολή ανανέωσης όλων των αρχείων της βιβλιοθήκης", + "face_detection": "Ανίχνευση προσώπου", + "face_detection_description": "Ανιχνεύστε τα πρόσωπα σε στοιχεία χρησιμοποιώντας μηχανική μάθηση. Για βίντεο, λαμβάνεται υπόψη μόνο η μικρογραφία. Η επιλογή \"Ανανέωση\" επεξεργάζεται εκ νέου όλα τα στοιχεία. Η επιλογή \"Επαναφορά\", επιπλέον εκκαθαρίζει όλα τα δεδομένα προσώπου. Η επιλογή \"Ελλείποντα\" προσθέτει στην ουρά στοιχεία που δεν έχουν υποστεί ακόμη επεξεργασία. Τα πρόσωπα που έχουν εντοπιστεί θα μπουν στην ουρά για την Αναγνώριση Προσώπου μετά την ολοκλήρωση της Ανίχνευσης Προσώπου, ομαδοποιώντας τα σε υπάρχοντα ή νέα άτομα.", + "facial_recognition_job_description": "Ομαδοποιήστε ανιχνευμένα πρόσωπα σε άτομα. Αυτό το βήμα εκτελείται αφού ολοκληρωθεί η Ανίχνευση Προσώπου. Η επιλογή \"Επαναφορά\" ομαδοποιεί εκ νέου όλα τα πρόσωπα. Η επιλογή \"Ελλείποντα\" βάζει στην ουρά για ομαδοποίηση πρόσωπα που δεν έχουν αντιστοιχηθεί σε κάποιο άτομο.", + "failed_job_command": "Η εντολή {command} απέτυχε για την εργασία: {job}", + "force_delete_user_warning": "ΠΡΟΕΙΔΟΠΟΙΗΣΗ: Αυτό θα αφαιρέσει άμεσα τον χρήστη και όλα τα στοιχεία. Αυτό δεν μπορεί να αναιρεθεί και τα αρχεία δεν μπορούν να ανακτηθούν.", + "forcing_refresh_library_files": "Εξαναγκαστική ανανέωση όλων των αρχείων της βιβλιοθήκης", "image_format": "Μορφή", "image_format_description": "Η μορφή WebP παράγει μικρότερα αρχεία από τη μορφή JPEG, αλλά είναι πιο αργή στην κωδικοποίηση.", "image_prefer_embedded_preview": "Προτίμηση ενσωματωμένης προεπισκόπησης", - "image_prefer_embedded_preview_setting_description": "Χρησιμοποιήστε ενσωματωμένες προεπισκοπίσεις για εικόνες RAW ως εισαγωγή στην επεξεργασία εικόνας όταν είναι διαθέσιμο. Αυτό μπορεί να δημιουργήσει πιο ακριβή χρωματα για κάποιες εικόνες, αλλά η ποιότητα των προεπισκοπίσεων εξαρτάται από την κάμερα και ενδέχεται να υπάρχουν περισσότερα μπιμπίκια λόγω συμπίεσης.", - "image_prefer_wide_gamut": "Προτίμηση ευρείας γκάμας", - "image_prefer_wide_gamut_setting_description": "Χρησιμοποιήστε Display P3 για τις μικρογραφίες. Αυτό διατηρεί την ζωντάνια των χρωμάτων σε εικόνες μεγάλου χρωματικού εύρους, αλλά ενδέχεται να εμφανίζονται αλλιώς σε παλαιότερες συσκευές με παλαιότερες εκδόσεις περιηγητών. Οι εικόνες sRGB μένουν ως έχουν για να αποφευχθούν χρωματικές αλλαγές.", - "image_preview_description": "Μεσαίου μεγέθους εικόνες, χωρίς μεταδεδομένα, οι οποίες χρησιμοποιύνται όταν γίνεται θέαση ενός αντικειμένου και για μηχανική μάθηση", - "image_preview_format": "Μορφή προεπισκόπησης", - "image_preview_quality_description": "Ποιότητα προεπισκόπησης, απο 1-100. Μεγαλύτερες τιμές είναι καλύτερες, αλλά παράγουν μεγαλύτερα αρχεία που μπορεί να μειώσουν την ταχύτητα της εφαρμογής. Χαμηλές τιμές μπορεί να επηρεάσουν τη ποιότητα του machine learning.", - "image_preview_resolution": "Ανάλυση προεπισκόπησης", - "image_preview_resolution_description": "Χρησιμοποιείται κατά την προβολή μιας φωτογραφίας και για μηχανική εκμάθηση. Οι υψηλότερες αναλύσεις μπορούν να διατηρήσουν περισσότερες λεπτομέρειες, αλλά χρειάζονται περισσότερο χρόνο για την κωδικοποίηση, έχουν μεγαλύτερα μεγέθη αρχείων και μπορούν να μειώσουν την απόκριση της εφαρμογής.", - "image_preview_title": "Ρυθμίσεις προεπισκόπισης", + "image_prefer_embedded_preview_setting_description": "Χρήση ενσωματωμένων προεπισκοπίσεων σε RAW εικόνες ως είσοδο για την επεξεργασία εικόνας εφόσον είναι διαθέσιμες. Αυτό μπορεί να δημιουργήσει πιο ακριβή χρώματα για κάποιες εικόνες, αλλά η ποιότητα των προεπισκοπίσεων εξαρτάται από την κάμερα και ενδέχεται να υπάρχουν περισσότερες αλλοιώσεις στην εικόνα λόγω συμπίεσης.", + "image_prefer_wide_gamut": "Προτίμηση ευρέος φάσματος", + "image_prefer_wide_gamut_setting_description": "Χρήση Display P3 για τις μικρογραφίες. Αυτό διατηρεί καλύτερα την ζωντάνια των χρωμάτων σε εικόνες μεγάλου χρωματικού εύρους, αλλά ενδέχεται να εμφανίζονται αλλιώς σε παλαιότερες συσκευές με παλαιότερες εκδόσεις περιηγητών. Οι εικόνες sRGB μένουν ως έχουν για να αποφευχθούν χρωματικές αλλαγές.", + "image_preview_description": "Μεσαίου μεγέθους εικόνες, χωρίς μεταδεδομένα, οι οποίες χρησιμοποιούνται στην προβολή ενός αντικειμένου και για μηχανική μάθηση", + "image_preview_quality_description": "Ποιότητα προεπισκόπησης από 1 έως 100. Όσο μεγαλύτερη τιμή τόσο καλύτερη η ποιότητα, αλλά παράγονται μεγαλύτερα αρχεία που ενδέχεται να μειώσουν την ταχύτητα απόκρισης της εφαρμογής. Οι χαμηλές τιμές μπορεί να επηρεάσουν τη ποιότητα της μηχανικής μάθησης.", + "image_preview_title": "Ρυθμίσεις Προεπισκόπισης", "image_quality": "Ποιότητα", - "image_quality_description": "Ποιότητα εικόνας από 1-100. Μεγαλύτερη τιμή σημαίνει καλύτερη ποιότητα, αλλά παράγει μεγαλύτερα αρχεία. Αυτή η επιλογή επηρεάζει τις εικόνες προεπισκόπησης και μικρογραφιών.", "image_resolution": "Ανάλυση", - "image_resolution_description": "Υψηλότερες αναλύσεις μπορούν να διατηρήσουν περισσότερες λεπτομέρειες, αλλά χρειάζονται περισσότερο χρόνο για την κωδικοποίηση, έχουν μεγαλύτερα μεγέθη αρχείων και μπορούν να μειώσουν την απόκριση της εφαρμογής.", + "image_resolution_description": "Υψηλότερες αναλύσεις μπορούν να διατηρήσουν περισσότερες λεπτομέρειες, αλλά χρειάζονται περισσότερο χρόνο να κωδικοποιηθούν, έχουν μεγαλύτερα μεγέθη αρχείων και μπορούν να μειώσουν την απόκριση της εφαρμογής.", "image_settings": "Ρυθμίσεις Εικόνας", - "image_settings_description": "Διαχείριση της ποιότητας και της ανάλυσης των εικόνων που δημιουργούνται", - "image_thumbnail_description": "Μικρό εικονίδιο χωρίς μεταδεδομένα, χρησιμοποιείται όταν γίνεται θέαση ομάδας φωτογραφιών, όπως η κύρια χρονογραμμή", - "image_thumbnail_format": "Μορφή μικρογραφίας", - "image_thumbnail_quality_description": "Ποιότητα μικρογραφίας, απο 1-100. Μεγαλύτερες τιμές είναι καλύτερες, αλλά παράγουν μεγαλύτερα αρχεία που μπορεί να μειώσουν την ταχύτητα της εφαρμογής.", - "image_thumbnail_resolution": "Ανάλυση μικρογραφίας", - "image_thumbnail_resolution_description": "Χρησιμοποιείται κατά την προβολή ομάδων φωτογραφιών (κύριο χρονολόγιο, προβολή άλμπουμ κλπ.). Υψηλότερες αναλύσεις μπορούν να διατηρήσουν περισσότερες λεπτομέρειες, αλλά χρειάζονται περισσότερο χρόνο για την κωδικοποίηση, έχουν μεγαλύτερα μεγέθη αρχείων και μπορούν να μειώσουν την απόκριση της εφαρμογής.", - "image_thumbnail_title": "Ρυθμίσεις μικρογραφίας", - "job_concurrency": "{job} συγχρονισμός", + "image_settings_description": "Διαχείριση της ποιότητας και της ανάλυσης των παραγόμενων εικόνων", + "image_thumbnail_description": "Μικρογραφία εικόνας χωρίς μεταδεδομένα, που χρησιμοποιείται όταν προβάλλονται ομάδες φωτογραφιών όπως το κύριο χρονολόγιο", + "image_thumbnail_quality_description": "Ποιότητα μικρογραφίας από 1 έως 100. Υψηλότερες τιμές είναι καλύτερες, αλλά παράγουν μεγαλύτερα αρχεία που μπορεί να μειώσουν την ταχύτητα απόκρισης της εφαρμογής.", + "image_thumbnail_title": "Ρυθμίσεις Μικρογραφίας", + "job_concurrency": "Ταυτόχρονη εκτέλεση {job}", "job_created": "Εργασία δημιουργήθηκε", "job_not_concurrency_safe": "Αυτή η εργασία δεν είναι ασφαλής για ταυτόχρονη εκτέλεση.", - "job_settings": "Ρυθμίσεις Εργασιών", - "job_settings_description": "Διαχείριση ταυτόχρονων εργασιών", - "job_status": "Κατάσταση Εργασιών", + "job_settings": "Ρυθμίσεις Εργασίας", + "job_settings_description": "Διαχείριση ταυτόχρονης εκτέλεσης εργασίας", + "job_status": "Κατάσταση Εργασίας", "jobs_delayed": "{jobCount, plural, one {# καθυστέρησε} other {# καθυστέρησαν}}", "jobs_failed": "{jobCount, plural, one {# απέτυχε} other {# απέτυχαν}}", "library_created": "Δημιουργήθηκε η βιβλιοθήκη: {library}", - "library_cron_expression": "Εκφράσεις Cron", - "library_cron_expression_description": "Ορισμός των διαστημάτων μεταξύ των σαρώσεων με χρήση cron μορφής. Για περισσότερες πληροφορίες παρακαλώ επισκεφθείτε το π.χ. Crontab Guru", - "library_cron_expression_presets": "Προκαθορισμένες εκφράσεις Cron", "library_deleted": "Η βιβλιοθήκη διαγράφηκε", "library_import_path_description": "Καθορίστε έναν φάκελο για εισαγωγή. Αυτός ο φάκελος, συμπεριλαμβανομένων των υποφακέλων του, θα σαρωθεί για εικόνες και βίντεο.", "library_scanning": "Περιοδική Σάρωση", - "library_scanning_description": "Διαμόρφωση περιοδικής σάρωσης βιβλιοθήκης", + "library_scanning_description": "Ρύθμιση περιοδικής σάρωσης βιβλιοθήκης", "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": "Καταγραφή", + "logging_enable_description": "Ενεργοποίηση καταγραφής συμβάντων", + "logging_level_description": "Το επίπεδο καταγραφής συμβάντων που θα εφαρμοστεί, όταν αυτή είναι ενεργοποιημένη.", + "logging_settings": "Καταγραφή Συμβάντων", "machine_learning_clip_model": "Μοντέλο CLIP", - "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_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": "Use CLIP embeddings to find likely duplicates", - "machine_learning_enabled": "Ενεργοποίηση μηχανικής εκμάθησης", - "machine_learning_enabled_description": "Εάν απενεργοποιηθεί, όλες οι λειτουργίες μηχανικής εκμάθησης θα απενεργοποιηθούν, ανεξάρτητα από τις παρακάτω ρυθμίσεις.", - "machine_learning_facial_recognition": "Αναγνώριση προσώπου", - "machine_learning_facial_recognition_description": "Εντοπισμός, αναγνώριση και ομαδοποίηση προσώπων σε εικόνες", + "machine_learning_duplicate_detection_enabled_description": "Εάν απενεργοποιηθεί, απολύτως παρόμοια στοιχεία θα συνεχίσουν να εκκαθαρίζονται από διπλότυπα.", + "machine_learning_duplicate_detection_setting_description": "Χρησιμοποιήστε τις ενσωματώσεις CLIP για να βρείτε πιθανά διπλότυπα", + "machine_learning_enabled": "Ενεργοποίηση μηχανικής μάθησης", + "machine_learning_enabled_description": "Εάν απενεργοποιηθεί, όλες οι λειτουργίες μηχανικής μάθησης θα απενεργοποιηθούν, ανεξάρτητα από τις παρακάτω ρυθμίσεις.", + "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_facial_recognition_setting_description": "Αν απενεργοποιηθεί, οι εικόνες δεν θα κωδικοποιούνται για αναγνώριση προσώπου και δεν θα συμπληρώνουν την ενότητα Άτομα στη σελίδα Περιήγησης.", "machine_learning_max_detection_distance": "Μέγιστη απόσταση ανίχνευσης", "machine_learning_max_detection_distance_description": "Η μέγιστη απόσταση μεταξύ δύο εικόνων για να θεωρηθούν διπλότυπες, που κυμαίνεται από 0,001-0,1. Οι υψηλότερες τιμές θα εντοπίσουν περισσότερες διπλότυπες, αλλά μπορεί να οδηγήσουν σε ψευδώς θετικά αποτελέσματα.", "machine_learning_max_recognition_distance": "Μέγιστη απόσταση αναγνώρισης", @@ -132,7 +131,7 @@ "machine_learning_smart_search_description": "Αναζητήστε εικόνες σημασιολογικά χρησιμοποιώντας ενσωματώσεις CLIP", "machine_learning_smart_search_enabled": "Ενεργοποίηση έξυπνης αναζήτησης", "machine_learning_smart_search_enabled_description": "Αν απενεργοποιηθεί, οι εικόνες δεν θα κωδικοποιούνται για έξυπνη αναζήτηση.", - "machine_learning_url_description": "URL του διακομιστή μηχανικής εκμάθησης", + "machine_learning_url_description": "Η διεύθυνση URL του διακομιστή μηχανικής εκμάθησης. Αν παρέχονται περισσότερες από μία διευθύνσεις URL, τότε, κάθε διακομιστής θα προσπαθήσει να συνδεθεί διαδοχικά, από την πρώτη μέχρι την τελευταία, έως ότου απαντήσει επιτυχώς.", "manage_concurrency": "Διαχείριση ταυτόχρονη εκτέλεσης", "manage_log_settings": "Διαχείριση ρυθμίσεων αρχείου καταγραφής", "map_dark_style": "Σκούρο Θέμα", @@ -183,34 +182,383 @@ "oauth_auto_register_description": "Αυτόματη καταχώρηση νέου χρήστη αφού συνδεθεί με OAuth", "oauth_button_text": "Κείμενο κουμπιού", "oauth_client_id": "Ταυτότητα πελάτη (Client)", - "oauth_client_secret": "Client Secret", + "oauth_client_secret": "Μυστικός κωδικός πελάτη", "oauth_enable_description": "Σύνδεση με OAuth", - "oauth_issuer_url": "Issuer URL", - "oauth_mobile_redirect_uri": "Mobile redirect URI", - "oauth_mobile_redirect_uri_override": "Mobile redirect URI override", - "oauth_mobile_redirect_uri_override_description": "Enable when OAuth provider does not allow a mobile URI, like '{callback}'", + "oauth_issuer_url": "Διεύθυνση URL εκδότη", + "oauth_mobile_redirect_uri": "URI Ανακατεύθυνσης για κινητά τηλέφωνα", + "oauth_mobile_redirect_uri_override": "Προσπέλαση URI ανακατεύθυνσης για κινητά τηλέφωνα", + "oauth_mobile_redirect_uri_override_description": "Ενεργοποιήστε το όταν ο πάροχος OAuth δεν επιτρέπει μια URI για κινητά, όπως το '{callback}'", "oauth_profile_signing_algorithm": "Αλγόριθμος σύνδεσης προφίλ", "oauth_profile_signing_algorithm_description": "Αλγόριθμος που χρησιμοποιείται για την σύνδεση των χρηστών.", - "oauth_scope": "Scope", - "oauth_settings": "OAuth" + "oauth_scope": "Εύρος", + "oauth_settings": "OAuth", + "oauth_settings_description": "Διαχείριση ρυθμίσεων σύνδεσης OAuth", + "oauth_settings_more_details": "Για περισσότερες λεπτομέρειες σχετικά με αυτήν τη δυνατότητα, ανατρέξτε στην τεκμηρίωση.", + "oauth_signing_algorithm": "Αλγόριθμος υπογραφής", + "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 που θα χρησιμοποιηθεί όταν δεν ορίζεται από τη δηλωμένη τιμή (Εισάγετε 0 για απεριόριστο ποσοστό).", + "offline_paths": "Διαδρομές αρχείων εκτός σύνδεσης", + "offline_paths_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": "Δεδομένου ότι είστε ο πρώτος χρήστης στο σύστημα, θα ανατεθείτε ως Διαχειριστής και θα είστε υπεύθυνος για τις διαχειριστικές εργασίες, ενώ οι επιπλέον χρήστες θα δημιουργούνται από εσάς.", + "repair_all": "Επιδιόρθωση όλων των στοιχείων", + "repair_matched_items": "Αντιστοιχίστηκαν {count, plural, one {# αντικείμενο} other {# αντικείμενα}}", + "repaired_items": "Επιδιορθώθηκαν {count, plural, one {# αντικείμενο} other {# αντικείμενα}}", + "require_password_change_on_login": "Απαιτείται από τον χρήστη να αλλάξει τον κωδικό πρόσβασης κατά την πρώτη σύνδεση", + "reset_settings_to_default": "Επαναφορά προεπιλεγμένων ρυθμίσεων", + "reset_settings_to_recent_saved": "Επαναφορά ρυθμίσεων στις πρόσφατα αποθηκευμένες ρυθμίσεις", + "scanning_library": "Σάρωση βιβλιοθήκης", + "search_jobs": "Αναζήτηση εργασιών...", + "send_welcome_email": "Αποστολή email καλωσορίσματος", + "server_external_domain_settings": "Εξωτερική διεύθυνση τομέα", + "server_external_domain_settings_description": "Διεύθυνση τομέα για δημόσιους κοινούς συνδέσμους, περιλαμβανομένου του http(s)://", + "server_public_users": "Δημόσιοι Χρήστες", + "server_public_users_description": "Όλοι οι χρήστες (όνομα και email) εμφανίζονται κατά την προσθήκη ενός χρήστη σε κοινόχρηστα άλμπουμ. Όταν αυτή η επιλογή είναι απενεργοποιημένη, η λίστα χρηστών θα είναι διαθέσιμη μόνο στους διαχειριστές.", + "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": "Ενεργοποιημένη επαλήθευση hash", + "storage_template_hash_verification_enabled_description": "Ενεργοποιεί την επαλήθευση hash. Μην το απενεργοποιήσεις εκτός αν είσαι βέβαιος/α για τις συνέπειες", + "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": "Όταν ενεργοποιηθεί, αυτή η δυνατότητα θα οργανώνει αυτόματα τα αρχεία με βάση ένα πρότυπο που καθορίζεται από τον χρήστη. Λόγω θεμάτων σταθερότητας, η δυνατότητα είναι απενεργοποιημένη από προεπιλογή. Για περισσότερες πληροφορίες, παρακαλώ δείτε την τεκμηρίωση.", + "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": "Αν το πρότυπο είναι κενό, θα χρησιμοποιηθεί το προεπιλεγμένο email.", + "template_email_invite_album": "Πρότυπο άλμπουμ πρόσκλησης", + "template_email_preview": "Προεπισκόπηση", + "template_email_settings": "Πρότυπα Email", + "template_email_settings_description": "Διαχείριση προσαρμοσμένων προτύπων ειδοποιήσεων email", + "template_email_update_album": "Ενημέρωση πρότυπου Άλμπουμ", + "template_email_welcome": "Πρότυπο email καλωσορίσματος", + "template_settings": "Πρότυπα ειδοποιήσεων", + "template_settings_description": "Διαχείριση προσαρμοσμένων προτύπων για ειδοποιήσεις.", + "theme_custom_css_settings": "Προσαρμοσμένο CSS", + "theme_custom_css_settings_description": "Τα Cascading Style Sheets(CSS) επιτρέπει την προσαρμογή του σχεδιασμού του Immich.", + "theme_settings": "Ρυθμίσεις Θέματος", + "theme_settings_description": "Διαχείριση της προσαρμογής του ιστότοπου του Immich", + "these_files_matched_by_checksum": "Αυτά τα αρχεία αντιστοιχίζονται με βάση τα checksums(μοναδικές αλγοριθμικές τιμές των περιεχομένων ενός αρχείου) τους", + "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": "Quick Sync (απαιτεί επεξεργαστή Intel 7ης γενιάς ή νεότερο)", + "transcoding_acceleration_rkmpp": "RKMPP (μόνο σε Rockchip SOCs)", + "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": "Για να μάθετε περισσότερα για την ορολογία που χρησιμοποιείται εδώ, ανατρέξτε στην τεκμηρίωση του FFmpeg για τους κωδικοποιητές H.264, HEVC και VP9.", + "transcoding_constant_quality_mode": "Λειτουργία σταθερής ποιότητας", + "transcoding_constant_quality_mode_description": "Το ICQ είναι καλύτερο από το CQP, αλλά ορισμένες συσκευές επιτάχυνσης υλικού δεν υποστηρίζουν αυτήν τη λειτουργία. Η ρύθμιση αυτής της επιλογής θα προτιμήσει την καθορισμένη λειτουργία κατά τη χρήση κωδικοποίησης βάσει ποιότητας. Αγνοείται από το NVENC, καθώς δεν υποστηρίζει το ICQ.", + "transcoding_constant_rate_factor": "Σταθερός παράγοντας ρυθμού (-crf)", + "transcoding_constant_rate_factor_description": "Επίπεδο ποιότητας βίντεο. Οι τυπικές τιμές είναι οι, 23 για το H.264, 28 για το HEVC, 31 για το VP9 και 35 για το AV1. Χαμηλότερες τιμές σημαίνουν καλύτερη ποιότητα, αλλά παράγουν μεγαλύτερα αρχεία.", + "transcoding_disabled_description": "Να μην μετατραπεί κανένα βίντεο γιατί δύναται να προκαλέσει πρόβλημα αναπαραγωγής σε ορισμένες συσκευές/εφαρμογές", + "transcoding_hardware_acceleration": "Επιτάχυνση υλικού", + "transcoding_hardware_acceleration_description": "Πειραματικό· πολύ πιο γρήγορο, αλλά θα έχει χαμηλότερη ποιότητα με τον ίδιο ρυθμό μετάδοσης (bitrate)", + "transcoding_hardware_decoding": "Αποκωδικοποίηση μέσω υλικού", + "transcoding_hardware_decoding_setting_description": "Ενεργοποιεί την επιτάχυνση από άκρη σε άκρη αντί για μόνο επιτάχυνση της κωδικοποίησης. Μπορεί να μην λειτουργεί σε όλα τα βίντεο.", + "transcoding_hevc_codec": "Κωδικοποιητής HEVC", + "transcoding_max_b_frames": "Μέγιστος αριθμός B-frames(Bidirectional Predictive Frames)", + "transcoding_max_b_frames_description": "Οι υψηλότερες τιμές βελτιώνουν την αποδοτικότητα της συμπίεσης, αλλά επιβραδύνουν την κωδικοποίηση. Ενδέχεται να μην είναι συμβατές με την επιτάχυνση υλικού σε παλαιότερες συσκευές. Η τιμή 0 απενεργοποιεί τα B-frames, ενώ η -1, τη ρυθμίζει αυτόματα.", + "transcoding_max_bitrate": "Μέγιστος ρυθμός μετάδοσης (bitrate)", + "transcoding_max_bitrate_description": "Η ρύθμιση ενός μέγιστου ρυθμού μετάδοσης(bitrate) μπορεί να κάνει το μέγεθος των αρχείων πιο προβλέψιμο, αλλά με ένα μικρό κόστος στην ποιότητα. Στην ανάλυση των 720p, οι τυπικές τιμές είναι 2600k για VP9 ή HEVC, ή 4500k για H.264. Απενεργοποιείται εάν οριστεί σε 0.", + "transcoding_max_keyframe_interval": "Μέγιστο χρονικό διάστημα μεταξύ των καρέ αναφοράς (keyframe)", + "transcoding_max_keyframe_interval_description": "Ορίζει το μέγιστο διάστημα μεταξύ των καρέ αναφοράς. Χαμηλότερες τιμές μειώνουν την αποδοτικότητα συμπίεσης, αλλά βελτιώνουν τον χρόνο αναζήτησης και μπορεί να βελτιώσουν την ποιότητα σε σκηνές με γρήγορη κίνηση. Η τιμή 0 ρυθμίζει αυτό το διάστημα αυτόματα.", + "transcoding_optimal_description": "Βίντεο με ανώτερη ανάλυση από την επιθυμητή ή σε μη αποδεκτή μορφή", + "transcoding_preferred_hardware_device": "Προτιμώμενη συσκευή", + "transcoding_preferred_hardware_device_description": "Ισχύει μόνο για VAAPI και QSV. Ορίζει τον κόμβο DRI που χρησιμοποιείται για την επιτάχυνση υλικού κατά την κωδικοποίηση.", + "transcoding_preset_preset": "Προκαθορισμένη ρύθμιση (-preset)", + "transcoding_preset_preset_description": "Ταχύτητα συμπίεσης. Οι πιο αργές προκαθορισμένες ρυθμίσεις παράγουν μικρότερα αρχεία και βελτιώνουν την ποιότητα όταν στοχεύουν σε έναν συγκεκριμένο ρυθμό μετάδοσης (bitrate). Ο VP9 αγνοεί τις ταχύτητες πάνω από την 'πιο γρήγορη' (faster).", + "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(Adaptive Quantization)", + "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": "Διαχείριση ρυθίσεων κάδου απορριμμάτων", + "untracked_files": "Αρχεία εκτός παρακολούθησης", + "untracked_files_description": "Αυτά τα αρχεία δεν παρακολουθούνται από την εφαρμογή. Μπορεί να είναι αποτέλεσμα αποτυχημένων μετακινήσεων, διακοπών κατά τη μεταφόρτωση ή να έχουν παραμείνει λόγω κάποιου εσωτερικού σφάλματος", + "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_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": "Email Διαχειριστή", + "admin_password": "Κωδικός πρόσβασης Διαχειριστή", + "administration": "Διαχείριση", + "advanced": "Για προχωρημένους", + "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": "Λάβετε ειδοποίηση μέσω email όταν προστεθείτε σε ένα κοινόχρηστο άλμπουμ", + "album_cover_updated": "Το εξώφυλλο του άλμπουμ, ενημερώθηκε", + "album_delete_confirmation": "Είστε σίγουροι ότι θέλετε να διαγράψετε το άλμπουμ {album};", + "album_delete_confirmation_description": "Εάν αυτό το άλμπουμ είναι κοινόχρηστο, οι άλλοι χρήστες δεν θα μπορούν να έχουν πρόσβαση.", + "album_info_updated": "Οι πληροφορίες του άλμπουμ, ενημερώθηκαν", + "album_leave": "Θέλετε να αποχωρήσετε από το άλμπουμ;", + "album_leave_confirmation": "Είστε σίγουροι ότι θέλετε να αποχωρήσετε από το {album};", + "album_name": "Ονομασία άλμπουμ", + "album_options": "Επιλογές άλμπουμ", + "album_remove_user": "Διαγραφή χρήστη;", + "album_remove_user_confirmation": "Είστε σίγουροι ότι θέλετε να αφαιρέσετε τον/την {user};", + "album_share_no_users": "Φαίνεται ότι έχετε κοινοποιήσει αυτό το άλμπουμ σε όλους τους χρήστες ή δεν έχετε χρήστες για να το κοινοποιήσετε.", + "album_updated": "Το άλμπουμ, ενημερώθηκε", + "album_updated_setting_description": "Λάβετε ειδοποίηση μέσω email όταν ένα κοινόχρηστο άλμπουμ έχει νέα αρχεία", + "album_user_left": "Αποχωρήσατε από το {album}", + "album_user_removed": "Αφαιρέθηκε ο/η {user}", + "album_with_link_access": "Επιτρέψτε σε οποιονδήποτε έχει τον σύνδεσμο, να δει τις φωτογραφίες και τα άτομα σε αυτό το άλμπουμ.", + "albums": "Άλμπουμ", + "albums_count": "{count, plural, one {{count, number} Άλμπουμ} other {{count, number} Άλμπουμ}}", + "all": "Όλα", + "all_albums": "Όλα τα άλμπουμ", + "all_people": "Όλοι οι άνθρωποι", + "all_videos": "Όλα τα βίντεο", + "allow_dark_mode": "Επιτρέψτε τη σκοτεινή λειτουργία", + "allow_edits": "Επιτρέψτε τις τροποποιήσεις", + "allow_public_user_to_download": "Επιτρέψτε σε δημόσιο χρήστη να κατεβάσει", + "allow_public_user_to_upload": "Επιτρέψτε στον δημόσιο χρήστη να ανεβάσει", + "anti_clockwise": "Αντίθετα με τη φορά του ρολογιού", + "api_key": "Κλειδί API", + "api_key_description": "Αυτή η τιμή θα εμφανιστεί μόνο μία φορά. Παρακαλώ βεβαιωθείτε ότι την έχετε αντιγράψει πριν κλείσετε το παράθυρο.", + "api_key_empty": "Το όνομα του κλειδιού API, δεν πρέπει να είναι κενό", + "api_keys": "Κλειδιά API", + "app_settings": "Ρυθμίσεις εφαρμογής", + "appears_in": "Εμφανίζεται σε", + "archive": "Αρχείο", + "archive_or_unarchive_photo": "Αρχειοθέτηση ή αποαρχειοθέτηση φωτογραφίας", + "archive_size": "Μέγεθος Αρχείου", + "archive_size_description": "Ρυθμίστε το μέγεθος του αρχείου για λήψεις (σε GiB)", + "archived_count": "{count, plural, other {Αρχειοθετήθηκαν #}}", + "are_these_the_same_person": "Είναι το ίδιο άτομο;", + "are_you_sure_to_do_this": "Είστε σίγουροι ότι θέλετε να το κάνετε αυτό;", + "asset_added_to_album": "Προστέθηκε στο άλμπουμ", + "asset_adding_to_album": "Προστίθεται στο άλμπουμ...", + "asset_description_updated": "Η περιγραφή του αντικειμένου έχει ενημερωθεί", + "asset_filename_is_offline": "Το αντικείμενο {filename} είναι εκτός σύνδεσης", + "asset_has_unassigned_faces": "Το αντικείμενο έχει μη ανατεθειμένα πρόσωπα", + "asset_hashing": "Δημιουργία κατακερματισμού...", + "asset_offline": "Αντικείμενο εκτός σύνδεσης", + "asset_offline_description": "Αυτό το εξωτερικό αντικείμενο δεν βρέθηκε πλέον στον δίσκο. Παρακαλώ επικοινωνήστε με τον διαχειριστή του Immich για βοήθεια.", + "asset_skipped": "Παραλείφθηκε", + "asset_skipped_in_trash": "Στον κάδο απορριμμάτων", + "asset_uploaded": "Ανεβάστηκε", + "asset_uploading": "Ανεβάζεται...", + "assets": "Αντικείμενα", + "assets_added_count": "Προστέθηκε {count, plural, one {# αρχείο} other {# αρχεία}}", + "assets_added_to_album_count": "Προστέθηκε {count, plural, one {# αρχείο} other {# αρχεία}} στο άλμπουμ", + "assets_added_to_name_count": "Προστέθηκε {count, plural, one {# αρχείο} other {# αρχεία}} στο {hasName, select, true {{name}} other {νέο άλμπουμ}}", + "assets_count": "{count, plural, one {# αρχείο} other {# αρχεία}}", + "assets_moved_to_trash_count": "Μετακινήθηκε/καν {count, plural, one {# αρχείο} other {# αρχεία}} στον κάδο απορριμμάτων", + "assets_permanently_deleted_count": "Διαγράφηκε/καν μόνιμα {count, plural, one {# αρχείο} other {# αρχεία}}", + "assets_removed_count": "Αφαιρέθηκαν {count, plural, one {# αρχείο} other {# αρχεία}}", "assets_restore_confirmation": "Είστε βέβαιοι ότι θέλετε να επαναφέρετε όλα τα στοιχεία που βρίσκονται στον κάδο απορριμμάτων; Αυτή η ενέργεια δεν μπορεί να αναιρεθεί! Λάβετε υπόψη ότι δεν θα είναι δυνατή η επαναφορά στοιχείων εκτός σύνδεσης.", "assets_restored_count": "Έγινε επαναφορά {count, plural, one {# στοιχείου} other {# στοιχείων}}", "assets_trashed_count": "Μετακιν. στον κάδο απορριμάτων {count, plural, one {# στοιχείο} other {# στοιχεία}}", "assets_were_part_of_album_count": "{count, plural, one {Το στοιχείο ανήκει} other {Τα στοιχεία ανήκουν}} ήδη στο άλμπουμ", "authorized_devices": "Εξουσιοδοτημένες Συσκευές", "back": "Πίσω", + "back_close_deselect": "Πίσω, κλείσιμο ή αποεπιλογή", "backward": "Προς τα πίσω", "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", + "camera": "Κάμερα", + "camera_brand": "Μάρκα κάμερας", + "camera_model": "Μοντέλο κάμερας", + "cancel": "Ακύρωση", + "cancel_search": "Ακύρωση αναζήτησης", + "cannot_merge_people": "Αδύνατη η συγχώνευση προσώπων", + "cannot_undo_this_action": "Δεν μπορείτε να αναιρέσετε αυτήν την ενέργεια!", + "cannot_update_the_description": "Αδύνατη η ενημέρωση της περιγραφής", + "change_date": "Αλλαγή ημερομηνίας", + "change_expiration_time": "Αλλαγή χρόνου λήξης", + "change_location": "Αλλαγή τοποθεσίας", + "change_name": "Αλλαγή ονομασίας", + "change_name_successfully": "Επιτυχής αλλαγή ονομασίας", + "change_password": "Αλλαγή Κωδικού", + "change_password_description": "Αυτή είναι ή η πρώτη φορά που συνδέεστε στο σύστημα ή έχει γίνει αίτημα για αλλαγή του κωδικού σας. Παρακαλώ εισάγετε τον νέο κωδικό, παρακάτω.", + "change_your_password": "Αλλάξτε τον κωδικό σας", + "changed_visibility_successfully": "Η προβολή, άλλαξε με επιτυχία", + "check_all": "Επιλογή Όλων", + "check_logs": "Ελέγξτε τα αρχεία καταγραφής", + "choose_matching_people_to_merge": "Επιλέξτε τα αντίστοιχα άτομα για συγχώνευση", + "city": "Πόλη", + "clear": "Εκκαθάριση", + "clear_all": "Εκκαθάριση όλων", + "clear_all_recent_searches": "Εκκαθάριση όλων των πρόσφατων αναζητήσεων", + "clear_message": "Εκκαθάριση μηνύματος", + "clear_value": "Εκκαθάριση τιμής", + "clockwise": "Δεξιόστροφα", + "close": "Κλείσιμο", + "collapse": "Σύμπτυξη", + "collapse_all": "Σύμπτυξη όλων", + "color": "Χρώμα", + "color_theme": "Χρώμα θέματος", + "comment_deleted": "Το σχόλιο διαγράφηκε", + "comment_options": "Επιλογές σχολίου", + "comments_and_likes": "Σχόλια & αντιδράσεις (likes)", + "comments_are_disabled": "Τα σχόλια είναι απενεργοποιημένα", + "confirm": "Επιβεβαίωση", + "confirm_admin_password": "Επιβεβαίωση κωδικού Διαχειριστή", + "confirm_delete_shared_link": "Είστε σίγουροι ότι θέλετε να διαγράψετε αυτόν τον κοινόχρηστο σύνδεσμο;", + "confirm_keep_this_delete_others": "Όλα τα άλλα στοιχεία της στοίβας θα διαγραφούν, εκτός από αυτό το στοιχείο. Είστε σίγουροι ότι θέλετε να συνεχίσετε;", + "confirm_password": "Επιβεβαίωση κωδικού", + "contain": "Περιέχει", + "context": "Συμφραζόμενα", + "continue": "Συνέχεια", + "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_library": "Δημιουργία Βιβλιοθήκης", + "create_link": "Δημιουργία συνδέσμου", + "create_link_to_share": "Δημιουργία συνδέσμου για διαμοιρασμό", + "create_link_to_share_description": "Επιτρέψτε σε οποιονδήποτε έχει τον σύνδεσμο να δει τη/τις επιλεγμένη/ες φωτογραφία/ες", + "create_new_person": "Δημιουργία νέου προσώπου", + "create_new_person_hint": "Αντιστοίχιση των επιλεγμένων αρχείων σε ένα νέο πρόσωπο", + "create_new_user": "Δημιουργία νέου χρήστη", + "create_tag": "Δημιουργία ετικέτας", + "create_tag_description": "Δημιουργία νέας ετικέτας. Για τις ένθετες ετικέτες, παρακαλώ εισάγετε τη πλήρη διαδρομή της, συμπεριλαμβανομένων των κάθετων διαχωριστικών.", + "create_user": "Δημιουργία χρήστη", + "created": "Δημιουργήθηκε", + "current_device": "Τρέχουσα συσκευή", + "custom_locale": "Προσαρμοσμένη Τοπική Ρύθμιση", + "custom_locale_description": "Μορφοποιήστε τις ημερομηνίες και τους αριθμούς, σύμφωνα με τη γλώσσα και την περιοχή", + "dark": "Σκούρο", + "date_after": "Ημερομηνία μετά", + "date_and_time": "Ημερομηνία και ώρα", + "date_before": "Ημερομηνία πριν", + "date_of_birth_saved": "Η ημερομηνία γέννησης αποθηκεύτηκε επιτυχώς", + "date_range": "Εύρος ημερομηνιών", + "day": "Ημέρα", + "deduplicate_all": "Αφαίρεση όλων των διπλότυπων", + "default_locale": "Προεπιλεγμένη Τοπική Ρύθμιση", + "default_locale_description": "Μορφοποιήστε τις ημερομηνίες και τους αριθμούς με βάση την τοπική ρύθμιση του προγράμματος περιήγησής σας", + "delete": "Διαγραφή", + "delete_album": "Διαγραφή άλμπουμ", + "delete_api_key_prompt": "Είστε σίγουροι ότι θέλετε να διαγράψετε αυτό κλειδί API;", + "delete_duplicates_confirmation": "Είστε σίγουροι ότι επιθυμείτε τη μόνιμη διαγραφή αυτών των διπλότυπων;", + "delete_key": "Διαγραφή κλειδιού", + "delete_library": "Διαγραφή Βιβλιοθήκης", + "delete_link": "Διαγραφή συνδέσμου", + "delete_others": "Διαγραφή υπολοίπων", + "delete_shared_link": "Διαγραφή κοινόχρηστου συνδέσμου", + "delete_tag": "Διαγραφή ετικέτας", + "delete_tag_confirmation_prompt": "Είστε σίγουροι ότι θέλετε να διαγράψετε την ετικέτα {tagName};", + "delete_user": "Διαγραφή χρήστη", + "deleted_shared_link": "Ο κοινόχρηστος σύνδεσμος, διαγράφηκε", + "deletes_missing_assets": "Διαγράφει στοιχεία που λείπουν από το δίσκο", + "description": "Περιγραφή", + "details": "Λεπτομέρειες", + "direction": "Κατεύθυνση", + "disabled": "Απενεργοποιημένο", + "disallow_edits": "Απαγόρευση επεξεργασιών", + "discord": "Discord", + "discover": "Ανίχνευση", + "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_include_embedded_motion_videos": "Ενσωματωμένα βίντεο", + "download_include_embedded_motion_videos_description": "Συμπεριλάβετε τα βίντεο που είναι ενσωματωμένα σε κινούμενες φωτογραφίες ως ξεχωριστό αρχείο", "download_settings": "Λήψη", + "download_settings_description": "Διαχείριση ρυθμίσεων που σχετίζονται με τη λήψη στοιχείων", + "downloading": "Γίνεται λήψη", + "downloading_asset_filename": "Λήψη στοιχείου {filename}", + "drop_files_to_upload": "Σύρετε αρχεία εδώ για να τα ανεβάσετε", "duplicates": "Διπλότυπα", "duplicates_description": "Επιλύστε κάθε ομάδα υποδεικνύοντας ποιες είναι διπλότυπες, εάν υπάρχουν", "duration": "Διάρκεια", @@ -219,39 +567,262 @@ "edit_avatar": "Επεξεργασία άβαταρ", "edit_date": "Επεξεργασία ημερομηνίας", "edit_date_and_time": "Επεξεργασία ημερομηνίας και ώρας", + "edit_exclusion_pattern": "Επεξεργασία μοτίβου αποκλεισμού", "edit_faces": "Επεξεργασία προσώπων", "edit_import_path": "Επεξεργασία διαδρομής εισαγωγής", "edit_import_paths": "Επεξεργασία Διαδρομών Εισαγωγής", + "edit_key": "Επεξεργασία κλειδιού", "edit_link": "Επεξεργασία συνδέσμου", "edit_location": "Επεξεργασία τοποθεσίας", "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", "empty_trash": "Άδειασμα κάδου απορριμμάτων", + "empty_trash_confirmation": "Είστε σίγουροι οτι θέλετε να αδειάσετε τον κάδο απορριμμάτων; Αυτό θα αφαιρέσει μόνιμα όλα τα στοιχεία του κάδου απορριμμάτων του Immich. \nΑυτή η ενέργεια δεν μπορεί να αναιρεθεί!", "enable": "Ενεργοποίηση", "enabled": "Ενεργοποιημένο", + "end_date": "Τελική ημερομηνία", "error": "Σφάλμα", "error_loading_image": "Σφάλμα κατά τη φόρτωση της εικόνας", "error_title": "Σφάλμα - Κάτι πήγε στραβά", "errors": { "cannot_navigate_next_asset": "Δεν είναι δυνατή η πλοήγηση στο επόμενο στοιχείο", "cannot_navigate_previous_asset": "Δεν είναι δυνατή η πλοήγηση στο προηγούμενο στοιχείο", - "cant_apply_changes": "Δεν είναι δυνατή η εφαρμογή αλλαγών" + "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": "Δεν μπορείτε να αναζητήσετε τοποθεσίες", + "cleared_jobs": "Εκκαθαρισμένες εργασίες για: {job}", + "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_job_command": "Η εντολή {command} απέτυχε για την εργασία: {job}", + "failed_to_create_album": "Αποτυχία δημιουργίας άλμπουμ", + "failed_to_create_shared_link": "Αποτυχία δημιουργίας κοινόχρηστου συνδέσμου", + "failed_to_edit_shared_link": "Αποτυχία επεξεργασίας κοινόχρηστου συνδέσμου", + "failed_to_get_people": "Αποτυχία ανάκτησης ατόμων", + "failed_to_keep_this_delete_others": "Αποτυχία διατήρησης αυτού του στοιχείου και διαγραφής των υπόλοιπων στοιχείων", + "failed_to_load_asset": "Αποτυχία φόρτωσης στοιχείου", + "failed_to_load_assets": "Αποτυχία φόρτωσης στοιχείων", + "failed_to_load_people": "Αποτυχία φόρτωσης ατόμων", + "failed_to_remove_product_key": "Αποτυχία αφαίρεσης κλειδιού προϊόντος", + "failed_to_stack_assets": "Αποτυχία στην συμπίεση των στοιχείων", + "failed_to_unstack_assets": "Αποτυχία στην αποσυμπίεση των στοιχείων", + "import_path_already_exists": "Αυτή η διαδρομή εισαγωγής υπάρχει ήδη.", + "incorrect_email_or_password": "Λανθασμένο email ή κωδικός πρόσβασης", + "paths_validation_failed": "{paths, plural, one {# διαδρομή} other {# διαδρομές}} απέτυχαν κατά την επικύρωση", + "profile_picture_transparent_pixels": "Οι εικόνες προφίλ δεν μπορούν να έχουν διαφανή εικονοστοιχεία. Παρακαλώ μεγεθύνετε ή/και μετακινήστε την εικόνα.", + "quota_higher_than_disk_size": "Έχετε ορίσει ένα όριο, μεγαλύτερο από το μέγεθος του δίσκου", + "repair_unable_to_check_items": "Αδυναμία ελέγχου {count, select, one {στοιχείου} other {στοιχείων}}", + "unable_to_add_album_users": "Αδυναμία προσθήκης χρήστη στο άλμπουμ", + "unable_to_add_assets_to_shared_link": "Αδυναμία προσθήκης στοιχείου στον κοινόχρηστο σύνδεσμο", + "unable_to_add_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_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_connect_to_server": "Αδυναμία σύνδεσης με το διακομιστή", + "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_load_album": "Αδυναμία φόρτωσης άλμπουμ", + "unable_to_load_asset_activity": "Αδυναμία φόρτωσης της δραστηριότητας του στοιχείου", + "unable_to_load_items": "Αδυναμία φόρτωσης αντικειμένων", + "unable_to_load_liked_status": "Αδυναμία φόρτωσης της κατάστασης \"μου αρέσει\"", + "unable_to_log_out_all_devices": "Αδυναμία αποσύνδεσης όλων των συσκευών", + "unable_to_log_out_device": "Αδυναμία αποσύνδεσης της συσκευής", + "unable_to_login_with_oauth": "Αδυναμία εισόδου μέσω OAuth", + "unable_to_play_video": "Αδυναμία αναπαραγωγής βίντεο", + "unable_to_reassign_assets_existing_person": "Αδυναμία επανακατηγοριοποίησης των στοιχείων στον/στην {name, select, null {υπάρχον άτομο} other {{name}}}", + "unable_to_reassign_assets_new_person": "Αδυναμία επανακατηγοριοποίησης των στοιχείων σε ένα νέο άτομο", + "unable_to_refresh_user": "Αδυναμία ανανέωσης χρήστη", + "unable_to_remove_album_users": "Αδυναμία διαγραφής χρηστών από το άλμπουμ", + "unable_to_remove_api_key": "Αδυναμία διαγραφής του κλειδιού API", + "unable_to_remove_assets_from_shared_link": "Αδυναμία διαγραφής στοιχείων από τον κοινόχρηστο σύνδεσμο", + "unable_to_remove_deleted_assets": "Αδυναμία αφαίρεσης αρχείων εκτός σύνδεσης", + "unable_to_remove_library": "Αδυναμία αφαίρεσης βιβλιοθήκης", + "unable_to_remove_partner": "Αδυναμία αφαίρεσης συνεργάτη", + "unable_to_remove_reaction": "Αδυναμία αφαίρεσης της αντίδρασης", + "unable_to_repair_items": "Αδυναμία επισκευής αντικειμένων", + "unable_to_reset_password": "Αδυναμία επαναφοράς κωδικού πρόσβασης", + "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", + "exit_slideshow": "Έξοδος από την παρουσίαση", + "expand_all": "Ανάπτυξη όλων", + "expire_after": "Λήγει μετά από", + "expired": "Έληξε", + "expires_date": "Λήγει {date}", + "explore": "Περιήγηση", + "explorer": "Περιηγητής", + "export": "Εξαγωγή", + "export_as_json": "Εξαγωγή ως JSON", + "extension": "Επέκταση", + "external": "Εξωτερικός", + "external_libraries": "Εξωτερικές βιβλιοθήκες", + "face_unassigned": "Μη ανατεθειμένο", + "failed_to_load_assets": "Αποτυχία φόρτωσης στοιχείων", + "favorite": "Αγαπημένο", + "favorite_or_unfavorite_photo": "Ορίστε μία φωτογραφία ως αγαπημένη ή αφαιρέστε την από τα αγαπημένα", + "favorites": "Αγαπημένα", + "feature_photo_updated": "Η φωτογραφία προβολής ενημερώθηκε", + "features": "Χαρακτηριστικά", + "features_setting_description": "Διαχειριστείτε τα χαρακτηριστικά της εφαρμογής", + "file_name": "Όνομα αρχείου", + "file_name_or_extension": "Όνομα αρχείου ή επέκταση", + "filename": "Ονομασία αρχείου", + "filetype": "Τύπος αρχείου", + "filter_people": "Φιλτράρισμα ατόμων", + "find_them_fast": "Βρείτε τους γρήγορα με αναζήτηση κατά όνομα", + "fix_incorrect_match": "Διόρθωση λανθασμένης αντιστοίχισης", + "folders": "Φάκελοι", + "folders_feature_description": "Περιήγηση στην προβολή φακέλου για τις φωτογραφίες και τα βίντεο στο σύστημα αρχείων", + "forward": "Προς τα εμπρός", + "general": "Γενικά", + "get_help": "Ζητήστε βοήθεια", + "getting_started": "Ξεκινώντας", + "go_back": "Πηγαίνετε πίσω", + "go_to_search": "Πηγαίνετε στην αναζήτηση", + "group_albums_by": "Ομαδοποίηση άλμπουμ κατά...", + "group_no": "Καμία ομοδοποίηση", + "group_owner": "Ομαδοποίηση κατά ιδιοκτήτη", + "group_year": "Ομαδοποίηση κατά έτος", + "has_quota": "Έχει ποσόστωση", + "hi_user": "Γειά σου {name} {email}", + "hide_all_people": "Απόκρυψη όλων των ατόμων", + "hide_gallery": "Απόκρυψη γκαλερί", + "hide_named_person": "Απόκρυψη του ατόμου {name}", + "hide_password": "Απόκρυψη κωδικού πρόσβασης", + "hide_person": "Απόκρυψη ατόμου", + "hide_unnamed_people": "Απόκρυψη ατόμων χωρίς όνομα", + "host": "Φιλοξενία", + "hour": "Ώρα", + "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}", + "image_alt_text_date_place_2_people": "{isVideo, select, true {Βίντεο} other {Εικόνα}} τραβηγμένο στην/στον {city}, {country} με τον/την {person1} και τον/την {person2} στις {date}", + "image_alt_text_date_place_3_people": "{isVideo, select, true {Βίντεο} other {Εικόνα}} τραβηγμένο στην/στον {city}, {country} με τον/την {person1}, τον/την {person2} και τον/την {person3} στις {date}", + "image_alt_text_date_place_4_or_more_people": "{isVideo, select, true {Βίντεο} other {Εικόνα}} τραβηγμένο στον/στην {city}, {country} με τον/την {person1}, {person2}, και {additionalCount, number} άλλους στις {date}", + "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": "Μεμονωμένος διαμοιρασμός", + "info": "Πληροφορίες", + "interval": { + "day_at_onepm": "Κάθε μέρα στη 1μμ", + "hours": "Κάθε {hours, plural, one {ώρα} other {{hours, number} ώρες}}", + "night_at_midnight": "Κάθε βράδυ τα μεσάνυχτα", + "night_at_twoam": "Κάθε βράδυ στις 2πμ" + }, + "invite_people": "Πρόσκληση Ατόμων", + "invite_to_album": "Πρόσκληση σε άλμπουμ", + "items_count": "{count, plural, one {# αντικείμενο} other {# αντικείμενα}}", "jobs": "Εργασίες", "keep": "Διατήρηση", "keep_all": "Διατήρηση Όλων", + "keep_this_delete_others": "Διατήρηση αυτού, διαγραφή υπολοίπων", + "kept_this_deleted_others": "Διατηρήθηκε αυτό το στοιχείο και διαγράφηκε/καν {count, plural, one {# στοιχείο} other {# στοιχεία}}", "keyboard_shortcuts": "Συντομεύσεις πληκτρολογίου", "language": "Γλώσσα", "language_setting_description": "Επιλέξτε τη γλώσσα που προτιμάτε", + "last_seen": "Τελευταία προβολή", "latest_version": "Τελευταία Έκδοση", "latitude": "Γεωγραφικό πλάτος", + "leave": "Εγκατάλειψη", + "let_others_respond": "Επέτρεψε σε άλλους να απαντήσουν", "level": "Επίπεδο", "library": "Βιβλιοθήκη", "library_options": "Επιλογές βιβλιοθήκης", + "light": "Φωτεινό", + "like_deleted": "Το \"μου αρέσει\" διαγράφηκε", + "link_motion_video": "Σύνδεσε βίντεο κίνησης", "link_options": "Επιλογές συνδέσμου", + "link_to_oauth": "Σύνδεση στον OAuth", + "linked_oauth_account": "Ο OAuth λογαριασμός συνδέθηκε", "list": "Λίστα", "loading": "Φόρτωση", "loading_search_results_failed": "Η φόρτωση αποτελεσμάτων αναζήτησης απέτυχε", @@ -267,6 +838,7 @@ "look": "Εμφάνιση", "loop_videos": "Επανάληψη βίντεο", "loop_videos_description": "Ενεργοποιήστε την αυτόματη επανάληψη ενός βίντεο στο πρόγραμμα προβολής λεπτομερειών.", + "main_branch_warning": "Χρησιμοποιείτε μια έκδοση σε ανάπτυξη· συνιστούμε ανεπιφύλακτα τη χρήση μιας επίσημης έκδοσης!", "make": "Κατασκευαστής", "manage_shared_links": "Διαχείριση κοινόχρηστων συνδέσμων", "manage_sharing_with_partners": "Διαχειριστείτε την κοινή χρήση με συνεργάτες", @@ -284,6 +856,7 @@ "memories": "Αναμνήσεις", "memories_setting_description": "Διαχειριστείτε τι θα εμφανίζεται στις αναμνήσεις σας", "memory": "Ανάμνηση", + "memory_lane_title": "Διαδρομή Αναμνήσεων {title}", "menu": "Μενού", "merge": "Συγχώνευση", "merge_people": "Συγχώνευση ατόμων", @@ -319,10 +892,11 @@ "no_assets_message": "ΚΑΝΤΕ ΚΛΙΚ ΓΙΑ ΝΑ ΑΝΕΒΑΣΕΤΕ ΤΗΝ ΠΡΩΤΗ ΣΑΣ ΦΩΤΟΓΡΑΦΙΑ", "no_duplicates_found": "Δεν βρέθηκαν διπλότυπα.", "no_exif_info_available": "Καμία πληροφορία exif διαθέσιμη", - "no_explore_results_message": "Ανεβάστε περισσότερες φωτογραφίες για να εξερευνήσετε τη συλλογή σας.", + "no_explore_results_message": "Ανεβάστε περισσότερες φωτογραφίες για να περιηγηθείτε στη συλλογή σας.", "no_favorites_message": "Προσθέστε αγαπημένα για να βρείτε γρήγορα τις καλύτερες φωτογραφίες και τα βίντεό σας", "no_libraries_message": "Δημιουργήστε μια εξωτερική βιβλιοθήκη για να προβάλετε τις φωτογραφίες και τα βίντεό σας", "no_name": "Χωρίς Όνομα", + "no_places": "Καμία τοποθεσία", "no_results": "Κανένα αποτέλεσμα", "no_results_description": "Δοκιμάστε ένα συνώνυμο ή πιο γενική λέξη-κλειδί", "no_shared_albums_message": "Δημιουργήστε ένα άλμπουμ για να μοιράζεστε φωτογραφίες και βίντεο με άτομα στο δίκτυό σας", @@ -334,17 +908,19 @@ "notifications": "Ειδοποιήσεις", "notifications_setting_description": "Διαχείριση ειδοποιήσεων", "oauth": "OAuth", + "official_immich_resources": "Επίσημοι Πόροι του Immich", "offline": "Εκτός σύνδεσης", "offline_paths": "Διαδρομές εκτός σύνδεσης", "offline_paths_description": "Αυτά τα αποτελέσματα μπορεί να οφείλονται στη μη αυτόματη διαγραφή αρχείων που δεν αποτελούν μέρος μιας εξωτερικής βιβλιοθήκης.", "ok": "Έγινε", "oldest_first": "Τα παλαιότερα πρώτα", + "onboarding": "Οδηγός εκκίνησης", + "onboarding_privacy_description": "Οι παρακάτω (προαιρετικές) λειτουργίες βασίζονται σε εξωτερικές υπηρεσίες και μπορούν να απενεργοποιηθούν ανά πάσα στιγμή από τις ρυθμίσεις διαχείρισης.", "onboarding_theme_description": "Επιλέξτε ένα θέμα χρώματος για το προφίλ σας. Μπορείτε να το αλλάξετε αργότερα στις ρυθμίσεις σας.", "onboarding_welcome_description": "Ας ρυθμίσουμε το προφίλ σας με ορισμένες κοινές ρυθμίσεις.", "onboarding_welcome_user": "Καλωσόρισες, {user}", "online": "Σε σύνδεση", "only_favorites": "Μόνο αγαπημένα", - "only_refreshes_modified_files": "Ανανεώνει μόνο τροποποιημένα αρχεία", "open_in_map_view": "Άνοιγμα σε προβολή χάρτη", "open_in_openstreetmap": "Άνοιγμα στο OpenStreetMap", "open_the_search_filters": "Ανοίξτε τα φίλτρα αναζήτησης", @@ -359,7 +935,7 @@ "owner": "Κάτοχος", "partner": "Συνεργάτης", "partner_can_access": "Ο χρήστης {partner} έχει πρόσβαση", - "partner_can_access_assets": "Όλες οι φωτογραφίες και τα βίντεό σας εκτός από αυτά που βρίσκονται στο Αρχείο και τα Διαγραμμένα", + "partner_can_access_assets": "Όλες οι φωτογραφίες και τα βίντεό σας εκτός από αυτά που βρίσκονται στο Αρχείο και τα Διεγραμμένα", "partner_can_access_location": "Η τοποθεσία όπου τραβήχτηκαν οι φωτογραφίες σας", "partner_sharing": "Κοινή Χρήση Συνεργατών", "partners": "Συνεργάτες", @@ -367,6 +943,11 @@ "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": "Πάυση", @@ -375,6 +956,7 @@ "pending": "Εκκρεμεί", "people": "Άτομα", "people_edits_count": "Έγινε επεξεργασία {count, plural, one {# ατόμου} other {# ατόμων}}", + "people_feature_description": "Περιήγηση σε φωτογραφίες και βίντεο ομαδοποιημένα ανά άτομο", "people_sidebar_description": "Εμφάνιση Ατόμων στην πλαϊνή γραμμή", "permanent_deletion_warning": "Προειδοποίηση οριστικής διαγραφής", "permanent_deletion_warning_setting_description": "Εμφάνιση προειδοποίησης κατά την οριστική διαγραφή στοιχείων", @@ -384,6 +966,7 @@ "permanently_deleted_asset": "Οριστικά διαγραμμένο στοιχείο", "permanently_deleted_assets_count": "Οριστική διαγραφή {count, plural, one {# στοιχείου} other {# στοιχείων}}", "person": "Άτομο", + "person_hidden": "{name}{hidden, select, true { (κρυφό)} other {}}", "photo_shared_all_users": "Φαίνεται ότι μοιραστήκατε τις φωτογραφίες σας με όλους τους χρήστες ή δεν έχετε κανέναν χρήστη για κοινή χρήση.", "photos": "Φωτογραφίες", "photos_and_videos": "Φωτογραφίες & Βίντεο", @@ -396,10 +979,14 @@ "play_memories": "Αναπαραγωγή αναμνήσεων", "play_motion_photo": "Αναπαραγωγή Κινούμενης Φωτογραφίας", "play_or_pause_video": "Αναπαραγωγή ή παύση βίντεο", + "port": "Θύρα", + "preset": "Προκαθορισμένη ρύθμιση", "preview": "Προεπισκόπηση", "previous": "Προηγούμενο", "previous_memory": "Προηγούμενη ανάμνηση", "previous_or_next_photo": "Προηγούμενη ή επόμενη φωτογραφία", + "primary": "Πρωτεύων", + "privacy": "Ιδιωτικότητα", "profile_image_of_user": "Εικόνα προφίλ του χρήστη {user}", "profile_picture_set": "Ορισμός εικόνας προφίλ.", "public_album": "Δημόσιο άλμπουμ", @@ -436,23 +1023,81 @@ "purchase_server_description_2": "Κατάσταση υποστηρικτή", "purchase_server_title": "Διακομιστής", "purchase_settings_server_activated": "Η διαχείριση του κλειδιού προϊόντος του διακομιστή γίνεται από τον διαχειριστή", + "rating": "Αξιολόγηση με αστέρια", + "rating_clear": "Εκκαθάριση αξιολόγησης", + "rating_count": "{count, plural, one {# αστέρι} other {# αστέρια}}", + "rating_description": "Εμφάνιση της αξιολόγησης EXIF στον πίνακα πληροφοριών", "reaction_options": "Επιλογές αντίδρασης", "read_changelog": "Διαβάστε το Αρχείο Καταγραφής Αλλαγών", + "reassign": "Ανάθεση", + "reassigned_assets_to_existing_person": "Η ανάθεση {count, plural, one {# αρχείου} other {# αρχείων}} στον/στην {name, select, null {έναν/μία υπάρχοντα/ουσα χρήστη} other {{name}}}", + "reassigned_assets_to_new_person": "Η ανάθεση {count, plural, one {# αρχείου} other {# αρχείων}} σε νέο άτομο", + "reassing_hint": "Ανάθεση των επιλεγμένων στοιχείων σε υπάρχον άτομο", + "recent": "Πρόσφατα", + "recent-albums": "Πρόσφατα άλμπουμ", + "recent_searches": "Πρόσφατες αναζητήσεις", + "refresh": "Ανανέωση", + "refresh_encoded_videos": "Ανανέωση κωδικοποιημένων βίντεο", "refresh_faces": "Ανανέωση προσώπων", + "refresh_metadata": "Ανανέωση μεταδεδομένων", + "refresh_thumbnails": "Ανανέωση μικρογραφιών", + "refreshed": "Ανανεωμένα", + "refreshes_every_file": "Επαναδιαβάζει όλα τα υπάρχοντα και νέα αρχεία", + "refreshing_encoded_video": "Ανανέωση κωδικοποιημένου βίντεο", "refreshing_faces": "Ανανεώνονται πρόσωπα", + "refreshing_metadata": "Τα μεταδεδομένα ανανεώνονται", + "regenerating_thumbnails": "Οι μικρογραφίες αναγεννώνται", + "remove": "Αφαίρεση", + "remove_assets_album_confirmation": "Είστε σίγουροι ότι θέλετε να αφαιρέσετε {count, plural, one {# στοιχείο} other {# στοιχεία}} από το άλμπουμ;", + "remove_assets_shared_link_confirmation": "Είστε σίγουροι ότι θέλετε να αφαιρέσετε {count, plural, one {# στοιχείο} other {# στοιχεία}} από αυτόν τον κοινόχρηστο σύνδεσμο;", + "remove_assets_title": "Αφαίρεση στοιχείων;", + "remove_custom_date_range": "Αφαίρεση προσαρμοσμένης χρονικής περιόδου", + "remove_deleted_assets": "Αφαίρεση Διεγραμμένων Στοιχείων", + "remove_from_album": "Αφαίρεση από το άλμπουμ", + "remove_from_favorites": "Αφαίρεση από τα αγαπημένα", + "remove_from_shared_link": "Αφαίρεση από τον κοινόχρηστο σύνδεσμο", + "remove_url": "Αφαίρεση Συνδέσμου", + "remove_user": "Αφαίρεση χρήστη", + "removed_api_key": "Αφαιρέθηκε το API Key: {name}", + "removed_from_archive": "Αφαιρέθηκε/καν από το Αρχείο", + "removed_from_favorites": "Αφαιρέθηκε από τα αγαπημένα", + "removed_from_favorites_count": "Αφαιρέθηκαν {count, plural, other {#}} από τα αγαπημένα", + "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": "Ο χρήστης απαιτείται να αλλάξει τον κωδικό πρόσβασής του κατά την πρώτη σύνδεση", + "reset": "Επαναφορά", + "reset_password": "Επαναφορά κωδικού πρόσβασης", + "reset_people_visibility": "Επαναφορά προβολής ατόμων", + "reset_to_default": "Επαναφορά στις προεπιλογές", + "resolve_duplicates": "Επίλυση διπλοτύπων", + "resolved_all_duplicates": "Επιλύθηκαν όλα τα διπλότυπα", + "restore": "Ανάκτηση", + "restore_all": "Ανάκτηση όλων", "restore_user": "Επαναφορά χρήστη", + "restored_asset": "Ανακτήθηκε το αρχείο", + "resume": "Συνέχιση", "retry_upload": "Επανάληψη ανεβάσματος", "review_duplicates": "Προβολή διπλότυπων", + "role": "Ρόλος", + "role_editor": "Επεξεργαστής", + "role_viewer": "Θεατής", "save": "Αποθήκευση", + "saved_api_key": "Αποθηκευμένο API key", "saved_profile": "Αποθηκευμένο προφίλ", "saved_settings": "Αποθηκευμένες ρυθμίσεις", "say_something": "Πείτε κάτι", "scan_all_libraries": "Σάρωση Όλων των Βιβλιοθηκών", - "scan_new_library_files": "Σάρωση Νέων Αρχείων Βιβλιοθήκης", + "scan_library": "Σάρωση", "scan_settings": "Ρυθμίσεις Σάρωσης", "scanning_for_album": "Σάρωση για άλμπουμ...", "search": "Αναζήτηση", "search_albums": "Αναζήτηση άλμπουμ", + "search_by_context": "Αναζήτηση με βάση το πλαίσιο", "search_by_filename": "Αναζήτηση βάσει ονόματος αρχείου ή επέκτασης αρχείου", "search_by_filename_example": "π.χ. IMG_1234.JPG ή PNG", "search_camera_make": "Αναζήτηση κατασκευαστή κάμερας...", @@ -462,12 +1107,16 @@ "search_for_existing_person": "Αναζήτηση υπάρχοντος ατόμου", "search_no_people": "Κανένα άτομο", "search_no_people_named": "Κανένα άτομο με όνομα \"{name}\"", + "search_options": "Επιλογές αναζήτησης", "search_people": "Αναζήτηση ατόμων", "search_places": "Αναζήτηση τοποθεσιών", + "search_settings": "Ρυθμίσεις αναζήτησης", "search_state": "Αναζήτηση νομού...", + "search_tags": "Αναζήτηση ετικετών...", "search_timezone": "Αναζήτηση ζώνης ώρας...", "search_type": "Τύπος αναζήτησης", "search_your_photos": "Αναζήτηση φωτογραφιών", + "searching_locales": "Αναζήτηση τοποθεσιών...", "second": "Δευτερόλεπτο", "see_all_people": "Προβολή όλων των ατόμων", "select_album_cover": "Επιλέξτε εξώφυλλο άλμπουμ", @@ -475,6 +1124,7 @@ "select_all_duplicates": "Επιλογή όλων των διπλότυπων", "select_avatar_color": "Επιλέξτε χρώμα avatar", "select_face": "Επιλογή προσώπου", + "select_featured_photo": "Επιλέξτε φωτογραφία για προβολή", "select_from_computer": "Επιλέξτε από υπολογιστή", "select_keep_all": "Επιλέξτε διατήρηση όλων", "select_library_owner": "Επιλέξτε κάτοχο βιβλιοθήκης", @@ -494,6 +1144,7 @@ "set_as_profile_picture": "Ορισμός ως εικόνα προφίλ", "set_date_of_birth": "Ορισμός ημερομηνίας γέννησης", "set_profile_picture": "Ορισμός εικόνας προφίλ", + "set_slideshow_to_fullscreen": "Ορίστε την παρουσίαση σε πλήρη οθόνη", "settings": "Ρυθμίσεις", "settings_saved": "Οι ρυθμίσεις αποθηκεύτηκαν", "share": "Κοινοποίηση", @@ -502,6 +1153,7 @@ "shared_by_user": "Σε κοινή χρήση από {user}", "shared_by_you": "Σε κοινή χρήση από εσάς", "shared_from_partner": "Φωτογραφίες από {partner}", + "shared_link_options": "Επιλογές κοινόχρηστου συνδέσμου", "shared_links": "Κοινόχρηστοι σύνδεσμοι", "shared_photos_and_videos_count": "{assetCount, plural, other {# κοινόχρηστες φωτογραφίες & βίντεο.}}", "shared_with_partner": "Σε κοινή χρήση με {partner}", @@ -510,6 +1162,7 @@ "sharing_sidebar_description": "Εμφανίστε έναν σύνδεσμο για Κοινή χρήση στην πλαϊνή γραμμή", "shift_to_permanent_delete": "πατήστε ⇧ για οριστική διαγραφή στοιχείου", "show_album_options": "Εμφάνιση επιλογών άλμπουμ", + "show_albums": "Προβολή των άλμπουμ", "show_all_people": "Προβολή όλων των ατόμων", "show_and_hide_people": "Εμφάνιση & απόκρυψη ατόμων", "show_file_location": "Εμφάνιση θέσης αρχείου", @@ -524,13 +1177,18 @@ "show_person_options": "Εμφάνιση επιλογών ατόμου", "show_progress_bar": "Εμφάνιση γραμμής προόδου", "show_search_options": "Εμφάνιση επιλογών αναζήτησης", + "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": "Ταξινόμηση άλμπουμ κατά...", @@ -541,6 +1199,12 @@ "sort_recent": "Η πιο πρόσφατη φωτογραφία", "sort_title": "Τίτλος", "source": "Πηγή", + "stack": "Στοίβα", + "stack_duplicates": "Στοίβαξη διπλότυπων", + "stack_select_one_photo": "Επιλέξτε μια κύρια φωτογραφία για τη στοίβαξη", + "stack_selected_photos": "Στοίβαγμα επιλεγμένων φωτογραφιών", + "stacked_assets_count": "Στοιβάχτηκαν {count, plural, one {# στοιχείο} other {# στοιχεία}}", + "stacktrace": "Καταγραφή στοίβας", "start": "Έναρξη", "start_date": "Από", "state": "Νομός", @@ -557,25 +1221,35 @@ "sunrise_on_the_beach": "Ηλιοβασίλεμα στην παραλία", "support": "Υποστήριξη", "support_and_feedback": "Υποστήριξη & Σχόλια", + "support_third_party_description": "Η εγκατάσταση του Immich που χρησιμοποιείτε, έχει πακεταριστεί από τρίτους. Τα προβλήματα που αντιμετωπίζετε μπορεί να οφείλονται σε αυτό το πακέτο, οπότε παρακαλούμε να αναφέρετε τα προβλήματα πρώτα σε εκείνους, χρησιμοποιώντας τους παρακάτω συνδέσμους.", "swap_merge_direction": "Εναλλαγή κατεύθυνσης συγχώνευσης", "sync": "Συγχρονισμός", "tag": "Ετικέτα", + "tag_assets": "Ετικετοποίηση στοιχείων", "tag_created": "Δημιουργήθηκε ετικέτα: {tag}", + "tag_feature_description": "Περιήγηση σε φωτογραφίες και βίντεο που είναι οργανωμένα σύμφωνα με λογικά θέματα ετικετών", + "tag_not_found_question": "Δεν μπορείτε να βρείτε μια ετικέτα; Δημιουργήστε μια νέα ετικέτα.", "tag_updated": "Ενημερώθηκε η ετικέτα: {tag}", + "tagged_assets": "Ετικετοποιημένο/α {count, plural, one {# στοιχείο} other {# στοιχεία}}", + "tags": "Ετικέτες", "template": "Πρότυπο", "theme": "Θέμα", "theme_selection": "Επιλογή θέματος", "theme_selection_description": "Ρυθμίστε αυτόματα το θέμα σε ανοιχτό ή σκούρο με βάση τις προτιμήσεις συστήματος του προγράμματος περιήγησής σας", "they_will_be_merged_together": "Θα συγχωνευθούν μαζί", + "third_party_resources": "Πόροι τρίτων", "time_based_memories": "Μνήμες βασισμένες στο χρόνο", + "timeline": "Χρονολόγιο", "timezone": "Ζώνη ώρας", "to_archive": "Αρχειοθέτηση", "to_change_password": "Αλλαγή κωδικού πρόσβασης", "to_favorite": "Αγαπημένο", "to_login": "Είσοδος", + "to_parent": "Μεταβείτε στο γονικό φάκελο", "to_trash": "Κάδος απορριμμάτων", "toggle_settings": "Εναλλαγή ρυθμίσεων", "toggle_theme": "Εναλλαγή θέματος", + "total": "Σύνολο", "total_usage": "Συνολική χρήση", "trash": "Κάδος απορριμμάτων", "trash_all": "Διαγραφή Όλων", @@ -583,24 +1257,31 @@ "trash_delete_asset": "Διαγραφή/Οριστ. Διαγραφή Αντικειμένου", "trash_no_results_message": "Οι φωτογραφίες και τα βίντεο που βρίσκονται στον κάδο απορριμμάτων θα εμφανίζονται εδώ.", "trashed_items_will_be_permanently_deleted_after": "Τα στοιχεία που βρίσκονται στον κάδο απορριμμάτων θα διαγραφούν οριστικά μετά από {days, plural, one {# ημέρα} other {# ημέρες}}.", + "type": "Τύπος", "unarchive": "Αναίρεση αρχειοθέτησης", "unarchived_count": "{count, plural, other {Αρχειοθετήσεις αναιρέθηκαν #}}", - "unfavorite": "Αφαίρεση από τα αγαπημένα", + "unfavorite": "Αποεπιλογή από τα αγαπημένα", "unhide_person": "Αναίρεση απόκρυψης ατόμου", "unknown": "Άγνωστο", "unknown_year": "Άγνωστο Έτος", "unlimited": "Απεριόριστο", + "unlink_motion_video": "Αποσυνδέστε το βίντεο κίνησης", "unlink_oauth": "Αποσύνδεση OAuth", "unlinked_oauth_account": "Ο λογαριασμός OAuth αποσυνδέθηκε", "unnamed_album": "Ανώνυμο Άλμπουμ", + "unnamed_album_delete_confirmation": "Είστε σίγουροι ότι θέλετε να διαγράψετε αυτό το άλμπουμ;", "unnamed_share": "Ανώνυμη Κοινή Χρήση", "unsaved_change": "Μη αποθηκευμένη αλλαγή", "unselect_all": "Αποεπιλογή όλων", "unselect_all_duplicates": "Αποεπιλογή όλων των διπλότυπων", + "unstack": "Αποστοίβαξη", + "unstacked_assets_count": "Αποστοιβάξατε {count, plural, one {# στοιχείο} other {# στοιχεία}}", "untracked_files": "Μη παρακολουθούμενα αρχεία", "untracked_files_decription": "Αυτά τα αρχεία δεν παρακολουθούνται από την εφαρμογή. Μπορεί να είναι αποτελέσματα αποτυχημένων μετακινήσεων, αποτυχημένες μεταφορτώσεις ή εναπομείναντα λόγω σφάλματος", + "up_next": "Ακολουθεί", "updated_password": "Ο κωδικός πρόσβασης ενημερώθηκε", "upload": "Μεταφόρτωση", + "upload_concurrency": "Συγχρονισμός μεταφόρτωσης", "upload_errors": "Η μεταφόρτωση ολοκληρώθηκε με {count, plural, one {# σφάλμα} other {# σφάλματα}}, ανανεώστε τη σελίδα για να δείτε νέα στοιχεία μεταφόρτωσης.", "upload_progress": "Απομένουν {remaining, number} - Ολοκληρώθηκαν {processed, number}/{total, number}", "upload_skipped_duplicates": "Παραλείφθηκαν {count, plural, one {# διπλότυπο στοιχείο} other {# διπλότυπα στοιχεία}}", @@ -617,6 +1298,9 @@ "user_purchase_settings": "Αγορά", "user_purchase_settings_description": "Διαχείριση Αγοράς", "user_role_set": "Ορισμός {user} ως {role}", + "user_usage_detail": "Λεπτομέρειες χρήσης του χρήστη", + "user_usage_stats": "Στατιστικά χρήσης λογαριασμού", + "user_usage_stats_description": "Προβολή στατιστικών χρήσης λογαριασμού", "username": "Όνομα Χρήστη", "users": "Χρήστες", "utilities": "Βοηθητικά προγράμματα", @@ -624,7 +1308,8 @@ "variables": "Μεταβλητές", "version": "Έκδοση", "version_announcement_closing": "Ο φίλος σου, Alex", - "version_announcement_message": "Γεια σου φίλε, υπάρχει μια νέα έκδοση της εφαρμογής, αφιέρωσε λίγο χρόνο για να επισκεφθείς την τοποθεσία release notes και να βεβαιωθείς ότι τα docker-compose.yml, και .env είναι ενημερωμένα για την αποτροπή τυχόν εσφαλμένων διαμορφώσεων, ειδικά εάν χρησιμοποιείτε το WatchTower ή οποιονδήποτε μηχανισμό που χειρίζεται την αυτόματη ενημέρωση της εφαρμογής σας.", + "version_announcement_message": "Γειά σας! Μια νέα έκδοση του Immich είναι διαθέσιμη. Παρακαλούμε αφιερώστε λίγο χρόνο για να διαβάσετε τις σημειώσεις έκδοσης ώστε να βεβαιωθείτε ότι η ρύθμιση σας είναι ενημερωμένη και να αποφύγετε τυχόν σφάλματα, ειδικά αν χρησιμοποιείτε το WatchTower ή οποιοδήποτε μηχανισμό που διαχειρίζεται αυτόματα την ενημέρωση της εγκατάστασης του Immich σας.", + "version_history": "Ιστορικό Εκδόσεων", "version_history_item": "Εγκαταστάθηκε {version} στις {date}", "video": "Βίντεο", "video_hover_setting": "Προεπισκόπηση βίντεο με το δείκτη του ποντικιού", @@ -637,14 +1322,16 @@ "view_all_users": "Προβολή όλων των χρηστών", "view_in_timeline": "Προβολή στο χρονοδιάγραμμα", "view_links": "Προβολή συνδέσμων", + "view_name": "Προβολή", "view_next_asset": "Προβολή επόμενου στοιχείου", "view_previous_asset": "Προβολή προηγούμενου στοιχείου", + "view_stack": "Προβολή της στοίβας", "visibility_changed": "Η ορατότητα άλλαξε για {count, plural, one {# άτομο} other {# άτομα}}", - "waiting": "Σε αναμονή", + "waiting": "Στοιχεία σε αναμονή", "warning": "Προειδοποίηση", "week": "Εβδομάδα", "welcome": "Καλωσορίσατε", - "welcome_to_immich": "Καλωσορίσατε στο immich", + "welcome_to_immich": "Καλωσορίσατε στο Ιmmich", "year": "Έτος", "years_ago": "πριν από {years, plural, one {# χρόνο} other {# χρόνια}}", "yes": "Ναι", diff --git a/i18n/en.json b/i18n/en.json index d607e088b399e..b5f8f3ca9a4d5 100644 --- a/i18n/en.json +++ b/i18n/en.json @@ -23,6 +23,7 @@ "add_to": "Add to...", "add_to_album": "Add to album", "add_to_shared_album": "Add to shared album", + "add_url": "Add URL", "added_to_archive": "Added to archive", "added_to_favorites": "Added to favorites", "added_to_favorites_count": "Added {count, number} to favorites", @@ -130,7 +131,7 @@ "machine_learning_smart_search_description": "Search for images semantically using CLIP embeddings", "machine_learning_smart_search_enabled": "Enable smart search", "machine_learning_smart_search_enabled_description": "If disabled, images will not be encoded for smart search.", - "machine_learning_url_description": "URL of the machine learning server", + "machine_learning_url_description": "The URL of the machine learning server. If more than one URL is provided, each server will be attempted one-at-a-time until one responds successfully, in order from first to last.", "manage_concurrency": "Manage Concurrency", "manage_log_settings": "Manage log settings", "map_dark_style": "Dark style", @@ -222,6 +223,8 @@ "send_welcome_email": "Send welcome email", "server_external_domain_settings": "External domain", "server_external_domain_settings_description": "Domain for public shared links, including http(s)://", + "server_public_users": "Public Users", + "server_public_users_description": "All users (name and email) are listed when adding a user to shared albums. When disabled, the user list will only be available to admin users.", "server_settings": "Server Settings", "server_settings_description": "Manage server settings", "server_welcome_message": "Welcome message", @@ -247,6 +250,16 @@ "storage_template_user_label": "{label} is the user's Storage Label", "system_settings": "System Settings", "tag_cleanup_job": "Tag cleanup", + "template_email_available_tags": "You can use the following variables in your template: {tags}", + "template_email_if_empty": "If the template is empty, the default email will be used.", + "template_email_invite_album": "Invite Album Template", + "template_email_preview": "Preview", + "template_email_settings": "Email Templates", + "template_email_settings_description": "Manage custom email notification templates", + "template_email_update_album": "Update Album Template", + "template_email_welcome": "Welcome email template", + "template_settings": "Notification Templates", + "template_settings_description": "Manage custom templates for notifications.", "theme_custom_css_settings": "Custom CSS", "theme_custom_css_settings_description": "Cascading Style Sheets allow the design of Immich to be customized.", "theme_settings": "Theme Settings", @@ -305,8 +318,6 @@ "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", "transcoding_tone_mapping_description": "Attempts to preserve the appearance of HDR videos when converted to SDR. Each algorithm makes different tradeoffs for color, detail and brightness. Hable preserves detail, Mobius preserves color, and Reinhard preserves brightness.", - "transcoding_tone_mapping_npl": "Tone-mapping NPL", - "transcoding_tone_mapping_npl_description": "Colors will be adjusted to look normal for a display of this brightness. Counter-intuitively, lower values increase the brightness of the video and vice versa since it compensates for the brightness of the display. 0 sets this value automatically.", "transcoding_transcode_policy": "Transcode policy", "transcoding_transcode_policy_description": "Policy for when a video should be transcoded. HDR videos will always be transcoded (except if transcoding is disabled).", "transcoding_two_pass_encoding": "Two-pass encoding", @@ -467,6 +478,7 @@ "confirm": "Confirm", "confirm_admin_password": "Confirm Admin Password", "confirm_delete_shared_link": "Are you sure you want to delete this shared link?", + "confirm_keep_this_delete_others": "All other assets in the stack will be deleted except for this asset. Are you sure you want to continue?", "confirm_password": "Confirm password", "contain": "Contain", "context": "Context", @@ -516,6 +528,7 @@ "delete_key": "Delete key", "delete_library": "Delete Library", "delete_link": "Delete link", + "delete_others": "Delete others", "delete_shared_link": "Delete shared link", "delete_tag": "Delete tag", "delete_tag_confirmation_prompt": "Are you sure you want to delete {tagName} tag?", @@ -606,6 +619,7 @@ "failed_to_create_shared_link": "Failed to create shared link", "failed_to_edit_shared_link": "Failed to edit shared link", "failed_to_get_people": "Failed to get people", + "failed_to_keep_this_delete_others": "Failed to keep this asset and delete the other assets", "failed_to_load_asset": "Failed to load asset", "failed_to_load_assets": "Failed to load assets", "failed_to_load_people": "Failed to load people", @@ -720,6 +734,7 @@ "external": "External", "external_libraries": "External Libraries", "face_unassigned": "Unassigned", + "failed_to_load_assets": "Failed to load assets", "favorite": "Favorite", "favorite_or_unfavorite_photo": "Favorite or unfavorite photo", "favorites": "Favorites", @@ -789,6 +804,8 @@ "jobs": "Jobs", "keep": "Keep", "keep_all": "Keep All", + "keep_this_delete_others": "Keep this, delete others", + "kept_this_deleted_others": "Kept this asset and deleted {count, plural, one {# asset} other {# assets}}", "keyboard_shortcuts": "Keyboard shortcuts", "language": "Language", "language_setting_description": "Select your preferred language", @@ -1017,6 +1034,7 @@ "reassigned_assets_to_new_person": "Re-assigned {count, plural, one {# asset} other {# assets}} to a new person", "reassing_hint": "Assign selected assets to an existing person", "recent": "Recent", + "recent-albums": "Recent albums", "recent_searches": "Recent searches", "refresh": "Refresh", "refresh_encoded_videos": "Refresh encoded videos", @@ -1038,6 +1056,7 @@ "remove_from_album": "Remove from album", "remove_from_favorites": "Remove from favorites", "remove_from_shared_link": "Remove from shared link", + "remove_url": "Remove URL", "remove_user": "Remove user", "removed_api_key": "Removed API Key: {name}", "removed_from_archive": "Removed from archive", @@ -1123,6 +1142,7 @@ "set": "Set", "set_as_album_cover": "Set as album cover", "set_as_profile_picture": "Set as profile picture", + "set_as_featured_photo": "Set as featured photo", "set_date_of_birth": "Set date of birth", "set_profile_picture": "Set profile picture", "set_slideshow_to_fullscreen": "Set Slideshow to fullscreen", @@ -1177,6 +1197,7 @@ "sort_items": "Number of items", "sort_modified": "Date modified", "sort_oldest": "Oldest photo", + "sort_people_by_similarity": "Sort people by similarity", "sort_recent": "Most recent photo", "sort_title": "Title", "source": "Source", @@ -1220,6 +1241,7 @@ "they_will_be_merged_together": "They will be merged together", "third_party_resources": "Third-Party Resources", "time_based_memories": "Time-based memories", + "timeline": "Timeline", "timezone": "Timezone", "to_archive": "Archive", "to_change_password": "Change password", @@ -1229,6 +1251,7 @@ "to_trash": "Trash", "toggle_settings": "Toggle settings", "toggle_theme": "Toggle dark theme", + "total": "Total", "total_usage": "Total usage", "trash": "Trash", "trash_all": "Trash All", @@ -1278,6 +1301,8 @@ "user_purchase_settings_description": "Manage your purchase", "user_role_set": "Set {user} as {role}", "user_usage_detail": "User usage detail", + "user_usage_stats": "Account usage statistics", + "user_usage_stats_description": "View account usage statistics", "username": "Username", "users": "Users", "utilities": "Utilities", @@ -1285,7 +1310,7 @@ "variables": "Variables", "version": "Version", "version_announcement_closing": "Your friend, Alex", - "version_announcement_message": "Hi friend, there is a new version of the application please take your time to visit the release notes and ensure your docker-compose.yml, and .env setup is up-to-date to prevent any misconfigurations, especially if you use WatchTower or any mechanism that handles updating your application automatically.", + "version_announcement_message": "Hi there! A new version of Immich is available. Please take some time to read the release notes to ensure your setup is up-to-date to prevent any misconfigurations, especially if you use WatchTower or any mechanism that handles updating your Immich instance automatically.", "version_history": "Version History", "version_history_item": "Installed {version} on {date}", "video": "Video", @@ -1299,6 +1324,7 @@ "view_all_users": "View all users", "view_in_timeline": "View in timeline", "view_links": "View links", + "view_name": "View", "view_next_asset": "View next asset", "view_previous_asset": "View previous asset", "view_stack": "View Stack", diff --git a/i18n/es.json b/i18n/es.json index c58888a57073e..10a0085f25926 100644 --- a/i18n/es.json +++ b/i18n/es.json @@ -1,5 +1,5 @@ { - "about": "Acerca de", + "about": "Acercade", "account": "Cuenta", "account_settings": "Ajustes de la cuenta", "acknowledge": "De acuerdo", @@ -17,68 +17,68 @@ "add_import_path": "Agregar ruta de importación", "add_location": "Agregar ubicación", "add_more_users": "Agregar más usuarios", - "add_partner": "Agregar invitado", - "add_path": "Agregar ruta", + "add_partner": "Agregar compañero", + "add_path": "Agregar carpeta", "add_photos": "Agregar fotos", "add_to": "Agregar a...", - "add_to_album": "Agregar a un álbum", - "add_to_shared_album": "Agregar a un álbum compartido", + "add_to_album": "Incluir en álbum", + "add_to_shared_album": "Incluir en álbum compartido", + "add_url": "Añadir URL", "added_to_archive": "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). 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/**\".", - "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 de tiempo 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.", + "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/**\".", + "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", - "authentication_settings_disable_all": "¿Está seguro de que deseas desactivar todos los métodos de inicio de sesión? El inicio de sesión se desactivará por completo.", - "authentication_settings_reenable": "Para volver a activarlo, utiliza un Comando del servidor .", + "authentication_settings_disable_all": "¿Estás seguro de que deseas desactivar todos los métodos de inicio de sesión? Esto desactivará por completo el inicio de sesión.", + "authentication_settings_reenable": "Para reactivarlo, utiliza un Comando del servidor.", "background_task_job": "Tareas en segundo plano", + "backup_database": "Respaldar base de datos", + "backup_database_enable_description": "Activar respaldo de base de datos", + "backup_keep_last_amount": "Cantidad de respaldos previos a mantener", + "backup_settings": "Ajustes de respaldo", + "backup_settings_description": "Administrar configuración de respaldo de base de datos", "check_all": "Verificar todo", "cleared_jobs": "Trabajos borrados para: {job}", "config_set_by_file": "La configuración está definida por un archivo de configuración", "confirm_delete_library": "¿Estás seguro de que quieres eliminar la biblioteca {library}?", - "confirm_delete_library_assets": "¿Estás seguro de que quieras eliminar esta biblioteca? Esto eliminará los {count, plural, one {# contained asset} other {all # contained assets}} elementos en Immich y no puede deshacerse. Los archivos permanecerán en tu almacenamiento.", + "confirm_delete_library_assets": "¿Estás seguro de que quieras eliminar esta biblioteca? Esto eliminará los {count, plural, one {# contained asset} other {all # contained assets}} elementos en Immich y no puede deshacerse. Los archivos permanecerán en disco.", "confirm_email_below": "Para confirmar, escribe \"{email}\" a continuación", "confirm_reprocess_all_faces": "¿Estás seguro de que deseas reprocesar todas las caras? Esto borrará a todas las personas que nombraste.", "confirm_user_password_reset": "¿Estás seguro de que quieres restablecer la contraseña de {user}?", "create_job": "Crear trabajo", - "crontab_guru": "Crontab Guru", + "cron_expression": "Expresión CRON", + "cron_expression_description": "Establece el intervalo de escaneo utilizando el formato CRON. Para más información puedes consultar, por ejemplo, Crontab Guru", + "cron_expression_presets": "Valores predefinidos de expresión CRON", "disable_login": "Deshabilitar inicio de sesión", - "disabled": "Deshabilitado", - "duplicate_detection_job_description": "Ejecuta aprendizaje automático sobre los activos para detectar imágenes similares. Se basa en la búsqueda inteligente", - "exclusion_pattern_description": "Los patrones de exclusión te permiten ignorar archivos y carpetas al escanear tu biblioteca. Esto es útil si tienes carpetas que contienen archivos que no deseas importar, como archivos RAW.", + "duplicate_detection_job_description": "Lanza el aprendizaje automático para detectar imágenes similares. Necesita tener activado \"Búsqueda Inteligente\"", + "exclusion_pattern_description": "Los patrones de exclusión te permiten ignorar archivos y carpetas al escanear tu biblioteca. Es útil si tienes carpetas que contienen archivos que no deseas importar, por ejemplo archivos RAW.", "external_library_created_at": "Biblioteca externa (creada el {date})", "external_library_management": "Gestión de bibliotecas externas", - "face_detection": "Detección de rostros", - "face_detection_description": "Detectar las caras en los activos mediante aprendizaje automático. En el caso de los vídeos, solo se tiene en cuenta la miniatura. \"Actualizar\" (re)procesar todos los activos. \"Restablecer\" borra además todos los datos de caras actuales. \"Falta\" pone en cola los activos que aún no se han procesado. Los rostros detectados se pondrán en cola para el reconocimiento facial una vez finalizada la detección facial, agrupándolos en personas existentes o nuevas.", - "facial_recognition_job_description": "Agrupa los rostros detectados en personas. Este paso se ejecuta una vez finalizada la detección de caras. \"Restablecer\" (re)agrupa todas las caras. \"Falta\" pone en cola los rostros que no tienen asignada una persona.", + "face_detection": "Detección de caras", + "face_detection_description": "Detecta las caras en los activos mediante aprendizaje automático. En el caso de los vídeos, solo se tiene en cuenta la miniatura. \"Actualizar\" (re)procesará todos los elementos. \"Restablecer\" borra además todos los datos de caras actuales. \"Falta\" pone en cola los elementos que aún no se han procesado. Las caras detectadas se pondrán en cola para el reconocimiento facial una vez finalizada la detección, agrupándolos en personas existentes o nuevas.", + "facial_recognition_job_description": "Agrupa las caras detectadas en personas. Este paso se ejecuta una vez finalizada la detección de caras. \"Restablecer\" (re)agrupa todas las caras. \"Falta\" pone en cola las caras que no tienen asignada una persona.", "failed_job_command": "El comando {command} ha fallado para la tarea: {job}", - "force_delete_user_warning": "CUIDADO: Esta acción eliminará inmediatamente el usuario y los elementos. Esta accion no se puede deshacer y los archivos no pueden ser recuperados.", - "forcing_refresh_library_files": "Forzar la recarga de todos los archivos de la biblioteca", + "force_delete_user_warning": "CUIDADO: Esta acción eliminará inmediatamente el usuario y todos los elementos. Esta accion no se puede deshacer y los archivos no pueden ser recuperados.", + "forcing_refresh_library_files": "Forzando la recarga de todos los elementos en la biblioteca", "image_format": "Formato", - "image_format_description": "WebP genera archivos más pequeños que JPEG, pero es más lento al codificar.", - "image_prefer_embedded_preview": "Preferir vista previa incrustada", - "image_prefer_embedded_preview_setting_description": "Usar vistas previas incrustadas en fotos RAW como entrada para el procesamiento de imágenes cuando estén disponibles. Esto puede producir colores más precisos en algunas imágenes, pero la calidad de la vista previa depende de la cámara y la imagen puede tener más artefactos de compresión.", - "image_prefer_wide_gamut": "Preferir gama amplia", - "image_prefer_wide_gamut_setting_description": "Usar \"Display P3\" para las miniaturas. Esto preserva mejor la vivacidad de las imágenes con espacios de color amplios, pero las imágenes pueden aparecer de manera diferente en dispositivos antiguos con una versión antigua del navegador. Las imágenes sRGB se mantienen como sRGB para evitar cambios de color.", - "image_preview_description": "Imagen de tamaño mediano con metadatos eliminados, utilizada al visualizar un solo activo y para aprendizaje automático", - "image_preview_format": "Formato de previsualización", - "image_preview_quality_description": "Calidad de vista previa de 1 a 100. Cuanto más alta sea la calidad, mejor, pero genera archivos más grandes y puede reducir la capacidad de respuesta de la aplicación. Establecer un valor bajo puede afectar la calidad del aprendizaje automático.", - "image_preview_resolution": "Resolución de previsualización", - "image_preview_resolution_description": "Se utiliza al ver una sola foto y para el aprendizaje automático. Las resoluciones más altas pueden preservar más detalles, pero tardan más en codificarse, tienen tamaños de archivo más grandes y pueden reducir la capacidad de respuesta de la aplicación.", + "image_format_description": "WebP genera archivos más pequeños que JPEG, pero es más lento al codificarlos.", + "image_prefer_embedded_preview": "Preferir vista previa embebida", + "image_prefer_embedded_preview_setting_description": "Usar vistas previas embebidas en fotos RAW como entrada para el procesamiento de imágenes cuando estén disponibles. Esto puede producir colores más precisos en algunas imágenes, pero la calidad de la vista previa depende de la cámara y la imagen puede tener más artefactos de compresión.", + "image_prefer_wide_gamut": "Preferir 'gamut' amplio", + "image_prefer_wide_gamut_setting_description": "Usar \"Display P3\" para las miniaturas. Preserva mejor la vivacidad de las imágenes con espacios de color amplios pero las imágenes pueden aparecer de manera diferente en dispositivos antiguos con una versión antigua del navegador. Las imágenes sRGB se mantienen como sRGB para evitar cambios de color.", + "image_preview_description": "Imagen de tamaño mediano con metadatos eliminados. Es utilizado al visualizar un solo activo y para el aprendizaje automático", + "image_preview_quality_description": "Calidad de vista previa de 1 a 100. Es mejor cuanto más alta sea la calidad pero genera archivos más grandes y puede reducir la capacidad de respuesta de la aplicación. Establecer un valor bajo puede afectar la calidad del aprendizaje automático.", "image_preview_title": "Ajustes de la vista previa", "image_quality": "Calidad", - "image_quality_description": "Calidad de imagen de 1 a 100. Un valor más alto mejora la calidad pero genera archivos más grandes.", "image_resolution": "Resolución", - "image_resolution_description": "Las resoluciones más altas pueden conservar más detalles, pero requieren más tiempo para codificar, tienen tamaños de archivo más grandes y pueden afectar la capacidad de respuesta de la aplicación.", + "image_resolution_description": "Las resoluciones más altas pueden conservar más detalles pero requieren más tiempo para codificar, tienen tamaños de archivo más grandes y pueden afectar la capacidad de respuesta de la aplicación.", "image_settings": "Ajustes de imagen", "image_settings_description": "Administrar la calidad y resolución de las imágenes generadas", - "image_thumbnail_description": "Miniatura pequeña con metadatos eliminados, que se utiliza al visualizar grupos de fotos como la línea de tiempo principal", - "image_thumbnail_format": "Formato de las miniaturas", - "image_thumbnail_quality_description": "Calidad de miniatura de 1 a 100. Cuanto más alta, mejor, pero genera archivos más grandes y puede reducir la capacidad de respuesta de la aplicación.", - "image_thumbnail_resolution": "Resolución de las miniaturas", - "image_thumbnail_resolution_description": "Se utiliza para ver grupos de fotos (cronología, vista de álbum, etc.). Las resoluciones más altas pueden conservar más detalles, pero tardan más en codificarse, tienen archivos de mayor tamaño y pueden reducir la reactividad de la aplicación.", + "image_thumbnail_description": "Miniatura pequeña con metadatos eliminados. Se utiliza al visualizar grupos de fotos como la línea temporal principal", + "image_thumbnail_quality_description": "Calidad de miniatura de 1 a 100. Es mejor cuanto más alto es el valor pero genera archivos más grandes y puede reducir la capacidad de respuesta de la aplicación.", "image_thumbnail_title": "Ajustes de las miniaturas", "job_concurrency": "{job}: Procesos simultáneos", "job_created": "Trabajo creado", @@ -89,52 +89,49 @@ "jobs_delayed": "{jobCount, plural, one {# retrasado} other {# retrasados}}", "jobs_failed": "{jobCount, plural, one {# fallido} other {# fallidos}}", "library_created": "La biblioteca ha sido creada: {library}", - "library_cron_expression": "Expresión cron", - "library_cron_expression_description": "Establece el intervalo de escaneo utilizando el formato cron. Para más información puede consultar, por ejemplo, Crontab Guru", - "library_cron_expression_presets": "Valores predefinidos de expresión cron", "library_deleted": "Biblioteca eliminada", - "library_import_path_description": "Indica una carpeta para importar. Esta carpeta, incluidas las subcarpetas, serán escaneadas en busca de multimedia.", - "library_scanning": "Escaneado periódico", - "library_scanning_description": "Configura el escaneo periódico de la biblioteca", + "library_import_path_description": "Indica una carpeta para importar. Esta carpeta y sus subcarpetas serán escaneadas en busca de elementos multimedia.", + "library_scanning": "Escaneo periódico", + "library_scanning_description": "Configurar el escaneo periódico de la biblioteca", "library_scanning_enable_description": "Activar el escaneo periódico de la biblioteca", "library_settings": "Biblioteca externa", "library_settings_description": "Administrar configuración biblioteca externa", "library_tasks_description": "Realizar tareas de biblioteca", - "library_watching_enable_description": "Ver las bibliotecas externas para detectar cambios en los archivos", + "library_watching_enable_description": "Vigilar las bibliotecas externas para detectar cambios en los archivos", "library_watching_settings": "Vigilancia de la biblioteca (EXPERIMENTAL)", "library_watching_settings_description": "Vigilar automaticamente en busca de archivos modificados", "logging_enable_description": "Habilitar registro", - "logging_level_description": "Cuando está habilitado, qué nivel de registro utilizar.", + "logging_level_description": "Indica el nivel de registro a utilizar cuando está habilitado.", "logging_settings": "Registro", - "machine_learning_clip_model": "Modelo de CLIP", - "machine_learning_clip_model_description": "El nombre de un modelo CLIP listado aquí. Tenga en cuenta que debe volver a ejecutar el trabajo 'Smart Search' para todas las imágenes al cambiar un modelo.", - "machine_learning_duplicate_detection": "Detección duplicados", + "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", "machine_learning_duplicate_detection_enabled": "Habilitar detección de duplicados", "machine_learning_duplicate_detection_enabled_description": "Si está deshabilitado, los activos exactamente idénticos seguirán siendo eliminados.", - "machine_learning_duplicate_detection_setting_description": "Utilice incrustaciones de CLIP para encontrar posibles duplicados", + "machine_learning_duplicate_detection_setting_description": "Usa incrustaciones de CLIP (Contrastive Language-Image Pre-Training) para encontrar posibles duplicados", "machine_learning_enabled": "Habilitar aprendizaje automático", - "machine_learning_enabled_description": "Si está deshabilitada, todas las funciones de ML se deshabilitarán independientemente de la configuración a continuación.", + "machine_learning_enabled_description": "Al desactivarla todas las funciones de ML se deshabilitarán independientemente de la configuración a continuación.", "machine_learning_facial_recognition": "Reconocimiento facial", - "machine_learning_facial_recognition_description": "Detecta, reconoce y agrupa las caras en imágenes", + "machine_learning_facial_recognition_description": "Detecta, reconoce y agrupa las caras en las imágenes", "machine_learning_facial_recognition_model": "Modelo de reconocimiento facial", - "machine_learning_facial_recognition_model_description": "Los modelos se enumeran en orden descendente de tamaño. Los modelos más grandes son más lentos y utilizan más memoria, pero producen mejores resultados. Tenga en cuenta que debe volver a ejecutar la tarea de reconocimiento facial para todas las imágenes al cambiar un modelo.", - "machine_learning_facial_recognition_setting": "Habilitar reconocimiento de caras", - "machine_learning_facial_recognition_setting_description": "Si está deshabilitada, las imágenes no se procesarán para el reconocimiento facial y no se incluirán en la sección Personas en la página Explorar.", - "machine_learning_max_detection_distance": "Distancia máxima de detección", - "machine_learning_max_detection_distance_description": "Distancia máxima entre dos imágenes para considerarlas duplicadas, oscilando entre 0,001-0,1. Los valores más altos detectarán más duplicados, pero pueden generar falsos positivos.", - "machine_learning_max_recognition_distance": "Distancia máxima de reconocimiento", - "machine_learning_max_recognition_distance_description": "Distancia máxima entre dos rostros para que se consideren una misma persona, oscilando entre 0-2. Reducirlo puede evitar etiquetar a dos personas como la misma persona, mientras que aumentarlo puede evitar etiquetar a la misma persona como dos personas diferentes. Tenga en cuenta que es más fácil fusionar a dos personas que dividir a una en dos, así que opte por un umbral más bajo cuando sea posible.", + "machine_learning_facial_recognition_model_description": "Los modelos se muestran en orden descendente de tamaño. Los modelos más grandes son más lentos y utilizan más memoria pero producen mejores resultados. Ten en cuenta que debes volver a ejecutar la tarea de reconocimiento facial para todas las imágenes al cambiar de modelo.", + "machine_learning_facial_recognition_setting": "Habilitar reconocimiento facial", + "machine_learning_facial_recognition_setting_description": "Cuando está desactivado no se utlizará reconocimiento facial y no aparecerán nuevas caras en la sección Personas en la página Explorar.", + "machine_learning_max_detection_distance": "Máxima distancia de detección", + "machine_learning_max_detection_distance_description": "Distancia máxima entre dos imágenes para considerarlas duplicadas, oscilando entre 0,001-0,1. Los valores más altos detectarán más duplicados pero pueden generar falsos positivos.", + "machine_learning_max_recognition_distance": "Máxima distancia de reconocimiento", + "machine_learning_max_recognition_distance_description": "Distancia máxima entre dos caras para que se consideren una misma persona, oscilando entre 0-2. Reducirlo puede evitar etiquetar a dos personas como la misma persona, mientras que aumentarlo puede evitar etiquetar a la misma persona como dos personas diferentes. Ten en cuenta que es más fácil fusionar a dos personas que dividir a una en dos, así que opta por un umbral más bajo cuando sea posible.", "machine_learning_min_detection_score": "Puntuación mínima de detección", - "machine_learning_min_detection_score_description": "Puntuación de confianza mínima para que se detecte una cara de 0 a 1. Los valores más bajos detectarán más rostros, pero pueden generar falsos positivos.", + "machine_learning_min_detection_score_description": "Puntuación de confianza mínima para que se detecte una cara de 0 a 1. Los valores más bajos detectarán más rostros pero pueden generar falsos positivos.", "machine_learning_min_recognized_faces": "Rostros mínimos reconocidos", - "machine_learning_min_recognized_faces_description": "El número mínimo de rostros reconocidos para que se cree una persona. Aumentar esto hace que el reconocimiento facial sea más preciso a costa de aumentar la posibilidad de que no se asigne una cara a una persona.", + "machine_learning_min_recognized_faces_description": "El número mínimo de rostros reconocidos para que se cree una persona. Aumentar esto permite que el reconocimiento facial sea más preciso a costa de aumentar la posibilidad de que no se asigne una cara a una persona.", "machine_learning_settings": "Configuración de aprendizaje automático", "machine_learning_settings_description": "Administrar funciones y configuraciones de aprendizaje automático", "machine_learning_smart_search": "Busqueda inteligente", - "machine_learning_smart_search_description": "Busque imágenes semánticamente utilizando incrustaciones CLIP", + "machine_learning_smart_search_description": "Busque imágenes semánticamente utilizando incrustaciones CLIP (Contrastive Language-Image Pre-Training)", "machine_learning_smart_search_enabled": "Habilitar búsqueda inteligente", - "machine_learning_smart_search_enabled_description": "Si está deshabilitado, las imágenes no se codificarán para la búsqueda inteligente.", - "machine_learning_url_description": "URL del servidor de aprendizaje automático", + "machine_learning_smart_search_enabled_description": "Al desactivarlo las imágenes no se procesarán para usar la búsqueda inteligente.", + "machine_learning_url_description": "La URL del servidor de aprendizaje automático. Si se proporciona más de una URL se intentará acceder a cada servidor sucesivamente hasta que uno responda correctamente en el orden especificado.", "manage_concurrency": "Ajustes de concurrencia", "manage_log_settings": "Administrar la configuración de los registros", "map_dark_style": "Estilo oscuro", @@ -215,7 +212,6 @@ "refreshing_all_libraries": "Actualizar todas las bibliotecas", "registration": "Registrar administrador", "registration_description": "Dado que eres el primer usuario del sistema, se te asignará como Admin y serás responsable de las tareas administrativas, y de crear a los usuarios adicionales.", - "removing_deleted_files": "Eliminando archivos sin conexión", "repair_all": "Reparar todo", "repair_matched_items": "Coincidencia {count, plural, one {# elemento} other {# elementos}}", "repaired_items": "Reparado {count, plural, one {# elemento} other {# elementos}}", @@ -223,12 +219,12 @@ "reset_settings_to_default": "Restablecer la configuración predeterminada", "reset_settings_to_recent_saved": "Restablecer la configuración a la configuración guardada recientemente", "scanning_library": "Escaneando la biblioteca", - "scanning_library_for_changed_files": "Escanear archivos modificados en biblioteca", - "scanning_library_for_new_files": "Escanear nuevos archivos en biblioteca", "search_jobs": "Buscar trabajo...", "send_welcome_email": "Enviar correo de bienvenida", "server_external_domain_settings": "Dominio externo", "server_external_domain_settings_description": "Dominio para enlaces públicos compartidos, incluidos http(s)://", + "server_public_users": "Usuarios públicos", + "server_public_users_description": "Todos los usuarios (nombre y correo electrónico) aparecen en la lista cuando se añade un usuario a los álbumes compartidos. Si se desactiva, la lista de usuarios sólo estará disponible para los usuarios administradores.", "server_settings": "Configuración del servidor", "server_settings_description": "Administrar la configuración del servidor", "server_welcome_message": "Mensaje de bienvenida", @@ -254,6 +250,16 @@ "storage_template_user_label": "{label} es la etiqueta de almacenamiento del usuario", "system_settings": "Ajustes del Sistema", "tag_cleanup_job": "Limpieza de etiquetas", + "template_email_available_tags": "Puede utilizar las siguientes variables en su plantilla: {tags}", + "template_email_if_empty": "Si la plantilla está vacía, se utilizará el correo electrónico predeterminado.", + "template_email_invite_album": "Plantilla de álbum de invitaciones", + "template_email_preview": "Vista previa", + "template_email_settings": "Modelos de correo electrónico", + "template_email_settings_description": "Gestionar plantillas de notificación por correo electrónico personalizadas", + "template_email_update_album": "Actualizar plantilla del álbum", + "template_email_welcome": "Plantilla de correo electrónico de bienvenida", + "template_settings": "Plantillas de notificación", + "template_settings_description": "Gestione plantillas personalizadas para las notificaciones.", "theme_custom_css_settings": "CSS Personalizado", "theme_custom_css_settings_description": "Las Hojas de Estilo (CSS) permiten personalizar el diseño de Immich.", "theme_settings": "Ajustes Tema", @@ -261,7 +267,6 @@ "these_files_matched_by_checksum": "Estos archivos coinciden con sus checksums", "thumbnail_generation_job": "Generar Miniaturas", "thumbnail_generation_job_description": "Genere miniaturas grandes, pequeñas y borrosas para cada archivo, así como miniaturas para cada persona", - "transcode_policy_description": "Política sobre cuándo se debe transcodificar un vídeo. Los vídeos HDR siempre se transcodificarán (excepto si la transcodificación está desactivada).", "transcoding_acceleration_api": "API Aceleración", "transcoding_acceleration_api_description": "La API que interactuará con su dispositivo para acelerar la transcodificación. Esta configuración es el \"mejor esfuerzo\": recurrirá a la transcodificación del software en caso de error. VP9 puede funcionar o no dependiendo de su hardware.", "transcoding_acceleration_nvenc": "NVENC (requiere GPU NVIDIA)", @@ -313,8 +318,6 @@ "transcoding_threads_description": "Los valores más altos conducen a una codificación más rápida, pero dejan menos espacio para que el servidor procese otras tareas mientras está activo. Este valor no debe ser mayor que la cantidad de núcleos de CPU. Maximiza la utilización si se establece en 0.", "transcoding_tone_mapping": "Mapeo de tonos", "transcoding_tone_mapping_description": "Intenta preservar la apariencia de los videos HDR cuando se convierten a SDR. Cada algoritmo realiza diferentes compensaciones en cuanto a color, detalle y brillo. Hable conserva los detalles, Mobius conserva el color y Reinhard conserva el brillo.", - "transcoding_tone_mapping_npl": "Mapeo de tonos NPL", - "transcoding_tone_mapping_npl_description": "Los colores se ajustarán para que parezcan normales en una pantalla con este brillo. Contrariamente a la intuición, los valores más bajos aumentan el brillo del vídeo y viceversa, ya que compensan el brillo de la pantalla. 0 establece este valor automáticamente.", "transcoding_transcode_policy": "Políticas de transcodificación", "transcoding_transcode_policy_description": "Política sobre cuándo se debe transcodificar un vídeo. Los vídeos HDR siempre se transcodificarán (excepto si la transcodificación está desactivada).", "transcoding_two_pass_encoding": "Codificación en dos pasadas", @@ -395,7 +398,6 @@ "archive_or_unarchive_photo": "Archivar o restaurar foto", "archive_size": "Tamaño del archivo", "archive_size_description": "Configure el tamaño del archivo para descargas (en GB)", - "archived": "Archivado", "archived_count": "{count, plural, one {# archivado} other {# archivados}}", "are_these_the_same_person": "¿Son la misma persona?", "are_you_sure_to_do_this": "¿Estas seguro de que quieres hacer esto?", @@ -416,7 +418,6 @@ "assets_added_to_album_count": "Añadido {count, plural, one {# asset} other {# assets}} al álbum", "assets_added_to_name_count": "Añadido {count, plural, one {# asset} other {# assets}} a {hasName, select, true {{name}} other {new album}}", "assets_count": "{count, plural, one {# activo} other {# activos}}", - "assets_moved_to_trash": "Se movió {count, plural, one {# activo} other {# activos}} a la papelera", "assets_moved_to_trash_count": "{count, plural, one {# elemento movido} other {# elementos movidos}} a la papelera", "assets_permanently_deleted_count": "Eliminado permanentemente {count, plural, one {# elemento} other {# elementos}}", "assets_removed_count": "Eliminado {count, plural, one {# elemento} other {# elementos}}", @@ -446,10 +447,6 @@ "cannot_merge_people": "No se pueden fusionar personas", "cannot_undo_this_action": "¡No puedes deshacer esta acción!", "cannot_update_the_description": "No se puede actualizar la descripción", - "cant_apply_changes": "No se pueden aplicar los cambios", - "cant_get_faces": "No se encuentran rostros", - "cant_search_people": "No se pueden buscar personas", - "cant_search_places": "No se pueden buscar lugares", "change_date": "Cambiar fecha", "change_expiration_time": "Cambiar fecha de caducidad", "change_location": "Cambiar ubicación", @@ -481,6 +478,7 @@ "confirm": "Confirmar", "confirm_admin_password": "Confirmar Contraseña de Administrador", "confirm_delete_shared_link": "¿Estás seguro de que deseas eliminar este enlace compartido?", + "confirm_keep_this_delete_others": "Todos los demás activos de la pila se eliminarán excepto este activo. ¿Está seguro de que quiere continuar?", "confirm_password": "Confirmar contraseña", "contain": "Incluido", "context": "Contexto", @@ -530,6 +528,7 @@ "delete_key": "Eliminar clave", "delete_library": "Eliminar biblioteca", "delete_link": "Eliminar enlace", + "delete_others": "Eliminar otros", "delete_shared_link": "Eliminar enlace compartido", "delete_tag": "Eliminar etiqueta", "delete_tag_confirmation_prompt": "¿Estás seguro de que deseas eliminar la etiqueta {tagName} ?", @@ -563,13 +562,6 @@ "duplicates": "Duplicados", "duplicates_description": "Resuelva cada grupo indicando, en cada caso, cuales están duplicados", "duration": "Duración", - "durations": { - "days": "{days, plural, one {día} other {{days, number} días}}", - "hours": "{hours, plural, one {hora} other {{hours, number} horas}}", - "minutes": "{minutes, plural, one {minuto} other {{minutes, number} minutos}}", - "months": "{months, plural, one {mes} other {{months, number} meses}}", - "years": "{years, plural, one {año} other {{years, number} años}}" - }, "edit": "Editar", "edit_album": "Editar album", "edit_avatar": "Editar avatar", @@ -594,8 +586,6 @@ "editor_crop_tool_h2_aspect_ratios": "Proporciones del aspecto", "editor_crop_tool_h2_rotation": "Rotación", "email": "Correo", - "empty": "", - "empty_album": "Álbum vacío", "empty_trash": "Vaciar papelera", "empty_trash_confirmation": "¿Estás seguro de que quieres vaciar la papelera? Esto eliminará permanentemente todos los archivos de la basura de Immich.\n¡No puedes deshacer esta acción!", "enable": "Habilitar", @@ -629,6 +619,7 @@ "failed_to_create_shared_link": "Error al crear el enlace compartido", "failed_to_edit_shared_link": "Error al editar el enlace compartido", "failed_to_get_people": "Error al obtener personas", + "failed_to_keep_this_delete_others": "No se pudo conservar este activo y eliminar los demás", "failed_to_load_asset": "Error al cargar el elemento", "failed_to_load_assets": "Error al cargar los elementos", "failed_to_load_people": "Error al cargar a los usuarios", @@ -656,8 +647,6 @@ "unable_to_change_location": "No se puede cambiar de ubicación", "unable_to_change_password": "No se puede cambiar la contraseña", "unable_to_change_visibility": "No se puede cambiar la visibilidad de {count, plural, one {# persona} other {# personas}}", - "unable_to_check_item": "", - "unable_to_check_items": "", "unable_to_complete_oauth_login": "No se puede completar el inicio de sesión de OAuth", "unable_to_connect": "No puede conectarse", "unable_to_connect_to_server": "Error al conectar al servidor", @@ -698,12 +687,10 @@ "unable_to_remove_album_users": "No se pueden eliminar usuarios del álbum", "unable_to_remove_api_key": "No se puede eliminar la clave API", "unable_to_remove_assets_from_shared_link": "No se pueden eliminar archivos desde el enlace compartido", - "unable_to_remove_comment": "", "unable_to_remove_deleted_assets": "No se pueden eliminar archivos sin conexión", "unable_to_remove_library": "No se puede eliminar la biblioteca", "unable_to_remove_partner": "No se puede eliminar el invitado", "unable_to_remove_reaction": "No se puede eliminar la reacción", - "unable_to_remove_user": "", "unable_to_repair_items": "No se pueden reparar los items", "unable_to_reset_password": "No se puede restablecer la contraseña", "unable_to_resolve_duplicate": "No se resolver duplicado", @@ -733,10 +720,6 @@ "unable_to_update_user": "No se puede actualizar el usuario", "unable_to_upload_file": "Error al subir el archivo" }, - "every_day_at_onepm": "", - "every_night_at_midnight": "", - "every_night_at_twoam": "", - "every_six_hours": "", "exif": "EXIF", "exit_slideshow": "Salir de la presentación", "expand_all": "Expandir todo", @@ -751,33 +734,28 @@ "external": "Externo", "external_libraries": "Bibliotecas Externas", "face_unassigned": "Sin asignar", - "failed_to_get_people": "No se pudo encontrar a personas", + "failed_to_load_assets": "Error al cargar los activos", "favorite": "Favorito", "favorite_or_unfavorite_photo": "Foto favorita o no favorita", "favorites": "Favoritos", - "feature": "", "feature_photo_updated": "Foto destacada actualizada", - "featurecollection": "", "features": "Características", "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", "filename": "Nombre del archivo", - "files": "", "filetype": "Tipo de archivo", "filter_people": "Filtrar personas", "find_them_fast": "Encuéntrelos rápidamente por nombre con la búsqueda", "fix_incorrect_match": "Corregir coincidencia incorrecta", "folders": "Carpetas", "folders_feature_description": "Explorar la vista de carpetas para las fotos y los videos en el sistema de archivos", - "force_re-scan_library_files": "Forzar reescaneo de todos los archivos de la biblioteca", "forward": "Reenviar", "general": "General", "get_help": "Solicitar ayuda", "getting_started": "Comenzamos", "go_back": "Volver atrás", "go_to_search": "Ir a búsqueda", - "go_to_share_page": "Ir a compartir página", "group_albums_by": "Agrupar albums por...", "group_no": "Sin agrupación", "group_owner": "Agrupar por propietario", @@ -803,10 +781,6 @@ "image_alt_text_date_place_2_people": "{isVideo, select, true {Video} other {Image}} tomada en {city}, {country} con {person1} y {person2} el {date}", "image_alt_text_date_place_3_people": "{isVideo, select, true {Video} other {Image}} tomada en {city}, {country} con {person1}, {person2}, y {person3} el {date}", "image_alt_text_date_place_4_or_more_people": "{isVideo, select, true {Video} other {Image}} tomada en {city}, {country} con {person1}, {person2}, y {additionalCount, number} más el {date}", - "image_alt_text_people": "{count, plural, =1 {with {person1}} =2 {with {person1} and {person2}} =3 {with {person1}, {person2}, and {person3}} other {with {person1}, {person2}, y {others, number} others}}", - "image_alt_text_place": "En {city}, {country}", - "image_taken": "{isVideo, select, true {Video taken} other {Image taken}}", - "img": "", "immich_logo": "Logo de Immich", "immich_web_interface": "Interfaz Web de Immich", "import_from_json": "Importar desde JSON", @@ -827,10 +801,11 @@ "invite_people": "Invitar a Personas", "invite_to_album": "Invitar al álbum", "items_count": "{count, plural, one {# elemento} other {# elementos}}", - "job_settings_description": "", "jobs": "Tareas", "keep": "Conservar", "keep_all": "Conservar Todo", + "keep_this_delete_others": "Mantener este, eliminar los otros", + "kept_this_deleted_others": "Mantuvo este activo y eliminó {count, plural, one {# activo} other {# activos}}", "keyboard_shortcuts": "Atajos de teclado", "language": "Idioma", "language_setting_description": "Selecciona tu idioma preferido", @@ -842,31 +817,6 @@ "level": "Nivel", "library": "Biblioteca", "library_options": "Opciones de biblioteca", - "license_account_info": "Tu cuenta tiene licencia", - "license_activated_subtitle": "Gracias por apoyar a Immich y al software de código abierto", - "license_activated_title": "Tu licencia ha sido activada exitosamente", - "license_button_activate": "Activar", - "license_button_buy": "Comprar", - "license_button_buy_license": "Comprar una licencia", - "license_button_select": "Seleccionar", - "license_failed_activation": "No se pudo activar la licencia. ¡Por favor, revisa tu correo electrónico para obtener la clave de licencia correcta!", - "license_individual_description_1": "1 licencia por usuario en cualquier servidor", - "license_individual_title": "Licencia individual", - "license_info_licensed": "Con licencia", - "license_info_unlicensed": "Sin licencia", - "license_input_suggestion": "¿Tienes una licencia? Introduzca la clave a continuación", - "license_license_subtitle": "Comprar una licencia para apoyar a Immich", - "license_license_title": "LICENCIA", - "license_lifetime_description": "Licencia de por vida", - "license_per_server": "Por servidor", - "license_per_user": "Por usuario", - "license_server_description_1": "1 licencia por servidor", - "license_server_description_2": "Licencia para todos los usuarios del servidor", - "license_server_title": "Licencia del servidor", - "license_trial_info_1": "Está ejecutando una versión sin licencia de Immich", - "license_trial_info_2": "Llevas utilizando Immich aproximadamente", - "license_trial_info_3": "{accountAge, plural, one {# día} other {# días}}", - "license_trial_info_4": "Por favor, considera la compra de una licencia para apoyar el desarrollo continuo del servicio", "light": "Claro", "like_deleted": "Me gusta eliminado", "link_motion_video": "Enlazar vídeo en movimiento", @@ -971,7 +921,6 @@ "onboarding_welcome_user": "Bienvenido, {user}", "online": "En línea", "only_favorites": "Solo favoritos", - "only_refreshes_modified_files": "Solo actualiza los archivos modificados", "open_in_map_view": "Abrir en la vista del mapa", "open_in_openstreetmap": "Abrir en OpenStreetMap", "open_the_search_filters": "Abre los filtros de búsqueda", @@ -1009,14 +958,12 @@ "people_edits_count": "Editada {count, plural, one {# persona} other {# personas}}", "people_feature_description": "Explorar fotos y vídeos agrupados por personas", "people_sidebar_description": "Mostrar un enlace a Personas en la barra lateral", - "perform_library_tasks": "", "permanent_deletion_warning": "Advertencia de eliminación permanente", "permanent_deletion_warning_setting_description": "Mostrar una advertencia al eliminar archivos permanentemente", "permanently_delete": "Borrar permanentemente", "permanently_delete_assets_count": "Eliminar permanentemente {count, plural, one {elemento} other {elementos}}", "permanently_delete_assets_prompt": "¿Está seguro de que desea eliminar permanentemente {count, plural, one {este activo?} other {estos # activos?}} Esto también eliminará {count, plural, one {de tu} other {de tus}} álbum(es).", "permanently_deleted_asset": "Archivo eliminado permanentemente", - "permanently_deleted_assets": "Eliminado permanentemente {count, plural, one {# activo} other {# activos}}", "permanently_deleted_assets_count": "Eliminado permanentemente {count, plural, one {# elemento} other {# elementos}}", "person": "Persona", "person_hidden": "{name}{hidden, select, true { (oculto)} other {}}", @@ -1032,7 +979,6 @@ "play_memories": "Reproducir recuerdos", "play_motion_photo": "Reproducir foto en movimiento", "play_or_pause_video": "Reproducir o pausar vídeo", - "point": "", "port": "Puerto", "preset": "Preestablecido", "preview": "Posterior", @@ -1077,12 +1023,10 @@ "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", - "range": "", "rating": "Valoración", "rating_clear": "Borrar calificación", "rating_count": "{count, plural, one {# estrella} other {# estrellas}}", "rating_description": "Mostrar la clasificación exif en el panel de información", - "raw": "", "reaction_options": "Opciones de reacción", "read_changelog": "Leer registro de cambios", "reassign": "Reasignar", @@ -1090,6 +1034,7 @@ "reassigned_assets_to_new_person": "Reasignado {count, plural, one {# elemento} other {# elementos}} a un nuevo usuario", "reassing_hint": "Asignar archivos seleccionados a una persona existente", "recent": "Reciente", + "recent-albums": "Últimos álbumes", "recent_searches": "Búsquedas recientes", "refresh": "Actualizar", "refresh_encoded_videos": "Recargar los vídeos codificados", @@ -1111,6 +1056,7 @@ "remove_from_album": "Eliminar del álbum", "remove_from_favorites": "Quitar de favoritos", "remove_from_shared_link": "Eliminar desde enlace compartido", + "remove_url": "Eliminar URL", "remove_user": "Eliminar usuario", "removed_api_key": "Clave API eliminada: {name}", "removed_from_archive": "Eliminado del archivo", @@ -1127,7 +1073,6 @@ "reset": "Reiniciar", "reset_password": "Restablecer la contraseña", "reset_people_visibility": "Restablecer la visibilidad de las personas", - "reset_settings_to_default": "", "reset_to_default": "Restablecer los valores predeterminados", "resolve_duplicates": "Resolver duplicados", "resolved_all_duplicates": "Todos los duplicados resueltos", @@ -1147,9 +1092,7 @@ "saved_settings": "Configuraciones guardadas", "say_something": "Comenta algo", "scan_all_libraries": "Escanear todas las bibliotecas", - "scan_all_library_files": "Vuelva a escanear todos los archivos de la biblioteca", "scan_library": "Escanear", - "scan_new_library_files": "Escanear nuevos archivos de biblioteca", "scan_settings": "Configuración de escaneo", "scanning_for_album": "Buscando álbum...", "search": "Buscar", @@ -1192,7 +1135,6 @@ "selected_count": "{count, plural, one {# seleccionado} other {# seleccionados}}", "send_message": "Enviar mensaje", "send_welcome_email": "Enviar correo de bienvenida", - "server": "Servidor", "server_offline": "Servidor desconectado", "server_online": "Servidor en línea", "server_stats": "Estadísticas del servidor", @@ -1297,17 +1239,17 @@ "they_will_be_merged_together": "Se fusionarán entre sí", "third_party_resources": "Recursos de terceros", "time_based_memories": "Recuerdos basados en tiempo", + "timeline": "Cronología", "timezone": "Zona horaria", "to_archive": "Archivar", "to_change_password": "Cambiar contraseña", "to_favorite": "A los favoritos", "to_login": "Iniciar Sesión", "to_parent": "Ir a los padres", - "to_root": "Para root", "to_trash": "Descartar", "toggle_settings": "Alternar ajustes", "toggle_theme": "Alternar tema oscuro", - "toggle_visibility": "Alternar visibilidad", + "total": "Total", "total_usage": "Uso total", "trash": "Papelera", "trash_all": "Descartar todo", @@ -1317,12 +1259,10 @@ "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}}.", "type": "Tipo", "unarchive": "Desarchivar", - "unarchived": "Restaurado", "unarchived_count": "{count, plural, one {# No archivado} other {# No archivados}}", "unfavorite": "Retirar favorito", "unhide_person": "Mostrar persona", "unknown": "Desconocido", - "unknown_album": "Álbum desconocido", "unknown_year": "Año desconocido", "unlimited": "Ilimitado", "unlink_motion_video": "Desvincular vídeo en movimiento", @@ -1354,13 +1294,13 @@ "use_custom_date_range": "Usa un intervalo de fechas personalizado", "user": "Usuario", "user_id": "ID de usuario", - "user_license_settings": "Licencia", - "user_license_settings_description": "Gestionar tu licencia", "user_liked": "{user} le gustó {type, select, photo {this photo} video {this video} asset {this asset} other {it}}", "user_purchase_settings": "Compra", "user_purchase_settings_description": "Gestiona tu compra", "user_role_set": "Carbiar {user} a {role}", "user_usage_detail": "Detalle del uso del usuario", + "user_usage_stats": "Estadísticas de uso de la cuenta", + "user_usage_stats_description": "Ver estadísticas de uso de la cuenta", "username": "Nombre de usuario", "users": "Usuarios", "utilities": "Utilidades", @@ -1368,7 +1308,7 @@ "variables": "Variables", "version": "Versión", "version_announcement_closing": "Tu amigo, Alex", - "version_announcement_message": "Hola Amigo: Hay una nueva versión de la aplicación, por favor, tómate tu tiempo para visitar las notas de la versión y asegúrate de que tu docker-compose.yml y la configuración .env estén actualizadas para evitar cualquier configuración incorrecta, especialmente si usas WatchTower o cualquier mecanismo que maneje la actualización automática de tu aplicación.", + "version_announcement_message": "¡Hola! Hay una nueva versión de Immich disponible. Tómese un tiempo para leer las notas de la versión para asegurarse de que su configuración esté actualizada y evitar errores de configuración, especialmente si utiliza WatchTower o cualquier mecanismo que se encargue de actualizar su instancia de Immich automáticamente.", "version_history": "Historial de versiones", "version_history_item": "Instalada la {version} el {date}", "video": "Vídeo", @@ -1382,10 +1322,10 @@ "view_all_users": "Mostrar todos los usuarios", "view_in_timeline": "Mostrar en la línea de tiempo", "view_links": "Mostrar enlaces", + "view_name": "Ver", "view_next_asset": "Mostrar siguiente elemento", "view_previous_asset": "Mostrar elemento anterior", "view_stack": "Ver Pila", - "viewer": "Visualizador", "visibility_changed": "Visibilidad cambiada para {count, plural, one {# persona} other {# personas}}", "waiting": "Esperando", "warning": "Advertencia", diff --git a/i18n/et.json b/i18n/et.json index d46714abe94f2..fc2cc3de9353f 100644 --- a/i18n/et.json +++ b/i18n/et.json @@ -1,5 +1,5 @@ { - "about": "Teave", + "about": "Värskenda", "account": "Konto", "account_settings": "Konto seaded", "acknowledge": "Sain aru", @@ -23,6 +23,7 @@ "add_to": "Lisa kohta...", "add_to_album": "Lisa albumisse", "add_to_shared_album": "Lisa jagatud albumisse", + "add_url": "Lisa URL", "added_to_archive": "Lisatud arhiivi", "added_to_favorites": "Lisatud lemmikutesse", "added_to_favorites_count": "{count, number} pilti lisatud lemmikutesse", @@ -34,6 +35,11 @@ "authentication_settings_disable_all": "Kas oled kindel, et soovid kõik sisselogimismeetodid välja lülitada? Sisselogimine lülitatakse täielikult välja.", "authentication_settings_reenable": "Et taas lubada, kasuta serveri käsku.", "background_task_job": "Tausttegumid", + "backup_database": "Varunda andmebaas", + "backup_database_enable_description": "Luba andmebaasi varundamine", + "backup_keep_last_amount": "Varukoopiate arv, mida alles hoida", + "backup_settings": "Varundamise seaded", + "backup_settings_description": "Halda andmebaasi varundamise seadeid", "check_all": "Märgi kõik", "cleared_jobs": "Tööted eemaldatud: {job}", "config_set_by_file": "Konfiguratsioon on määratud konfifaili abil", @@ -43,6 +49,9 @@ "confirm_reprocess_all_faces": "Kas oled kindel, et soovid kõik näod uuesti töödelda? See eemaldab kõik nimega isikud.", "confirm_user_password_reset": "Kas oled kindel, et soovid kasutaja {user} parooli lähtestada?", "create_job": "Lisa tööde", + "cron_expression": "Cron avaldis", + "cron_expression_description": "Sea skaneerimise intervall cron formaadis. Rohkema info jaoks vaata nt. Crontab Guru", + "cron_expression_presets": "Eelseadistatud cron avaldised", "disable_login": "Keela sisselogimine", "duplicate_detection_job_description": "Rakenda üksustele masinõpet, et leida sarnaseid pilte. Kasutab nutiotsingut", "exclusion_pattern_description": "Välistamismustrid võimaldavad ignoreerida faile ja kaustu kogu skaneerimisel. See on kasulik, kui sul on kaustu, mis sisaldavad faile, mida sa ei soovi importida, nagu RAW failid.", @@ -61,22 +70,15 @@ "image_prefer_wide_gamut": "Eelista laia värvigammat", "image_prefer_wide_gamut_setting_description": "Kasuta pisipiltide jaoks Display P3. See säilitab paremini laia värviruumiga piltide erksuse, aga vanematel seadmetel ja vanemate brauseritega võivad pildid teistsugused välja näha. sRGB pildid säilitatakse värvinihete vältimiseks.", "image_preview_description": "Keskmise suurusega pilt ilma metaandmeteta, kasutusel üksiku üksuse vaatamise ja masinõppe jaoks", - "image_preview_format": "Eelvaate formaat", "image_preview_quality_description": "Eelvaate kvaliteet vahemikus 1-100. Kõrgem väärtus on parem, aga tekitab suuremaid faile ning võib mõjutada rakenduse töökiirust. Madala väärtuse seadmine võib mõjutada masinõppe kvaliteeti.", - "image_preview_resolution": "Eelvaate resolutsioon", - "image_preview_resolution_description": "Kasutusel üksiku foto vaatamisel ja masinõppe jaoks. Kõrgem resolutsioon säilitab rohkem detaile, aga kodeerimine võtab rohkem aega, tekitab suurema faili ning võib mõjutada rakenduse töökiirust.", "image_preview_title": "Eelvaate seaded", "image_quality": "Kvaliteet", - "image_quality_description": "Pildikvaliteet vahemikus 1-100. Kõrgem väärtus tähendab paremat kvaliteeti ja suuremaid faile. See valik mõjutab eelvaateid ja pisipilte.", "image_resolution": "Resolutsioon", "image_resolution_description": "Kõrgemad resolutsioonid säilitavad rohkem detaile, aga kodeerimine võtab kauem aega, tekitab suuremaid faile ning võib mõjutada rakenduse töökiirust.", "image_settings": "Pildi seaded", "image_settings_description": "Halda genereeritud piltide kvaliteeti ja resolutsiooni", "image_thumbnail_description": "Väike pisipilt ilma metaandmeteta, kasutusel fotode grupikaupa vaatamisel, näiteks ajajoonel", - "image_thumbnail_format": "Pisipildi formaat", "image_thumbnail_quality_description": "Pisipildi kvaliteet vahemikus 1-100. Kõrgem väärtus on parem, aga tekitab suuremaid faile ning võib mõjutada rakenduse töökiirust.", - "image_thumbnail_resolution": "Pisipildi resolutsioon", - "image_thumbnail_resolution_description": "Kasutusel fotode mitmekaupa vaatamisel (ajajoon, albumi vaade, jne). Kõrgem resolutsioon säilitab rohkem detaile, aga kodeerimine võtab rohkem aega, tekitab suurema faili ning võib mõjutada rakenduse töökiirust.", "image_thumbnail_title": "Pisipildi seaded", "job_concurrency": "{job} samaaegsus", "job_created": "Tööde lisatud", @@ -87,9 +89,6 @@ "jobs_delayed": "{jobCount, plural, other {# edasi lükatud}}", "jobs_failed": "{jobCount, plural, other {# ebaõnnestus}}", "library_created": "Lisatud kogu: {library}", - "library_cron_expression": "Cron avaldis", - "library_cron_expression_description": "Sea skaneerimise intervall cron formaadis. Rohkema info jaoks vaata nt. Crontab Guru", - "library_cron_expression_presets": "Eelseadistatud cron avaldised", "library_deleted": "Kogu kustutatud", "library_import_path_description": "Määra kaust, mida importida. Sellest kaustast ning alamkaustadest otsitakse pilte ja videosid.", "library_scanning": "Perioodiline skaneerimine", @@ -132,7 +131,7 @@ "machine_learning_smart_search_description": "Otsi pilte semantiliselt CLIP-manuste abil", "machine_learning_smart_search_enabled": "Luba nutiotsing", "machine_learning_smart_search_enabled_description": "Kui keelatud, siis ei kodeerita pilte nutiotsingu jaoks.", - "machine_learning_url_description": "Masinõppe serveri URL", + "machine_learning_url_description": "Masinõppe serveri URL. Kui ette on antud rohkem kui üks URL, proovitakse neid järjest ükshaaval, kuni üks edukalt vastab.", "manage_concurrency": "Halda samaaegsust", "manage_log_settings": "Halda logi seadeid", "map_dark_style": "Tume stiil", @@ -220,12 +219,12 @@ "reset_settings_to_default": "Lähtesta seaded", "reset_settings_to_recent_saved": "Taasta hiljuti salvestatud seaded", "scanning_library": "Kogu skaneerimine", - "scanning_library_for_changed_files": "Kogu muutunud failide skaneerimine", - "scanning_library_for_new_files": "Kogu uute failide skaneerimine", "search_jobs": "Otsi töödet...", "send_welcome_email": "Saada tervituskiri", "server_external_domain_settings": "Väline domeen", "server_external_domain_settings_description": "Domeen avalikult jagatud linkide jaoks, k.a. http(s)://", + "server_public_users": "Avalikud kasutajad", + "server_public_users_description": "Kasutaja jagatud albumisse lisamisel kuvatakse kõiki kasutajaid (nime ja e-posti aadressiga). Kui keelatud, kuvatakse kasutajate nimekirja ainult administraatoritele.", "server_settings": "Serveri seaded", "server_settings_description": "Halda serveri seadeid", "server_welcome_message": "Tervitusteade", @@ -251,6 +250,16 @@ "storage_template_user_label": "{label} on kasutaja talletussilt", "system_settings": "Süsteemi seaded", "tag_cleanup_job": "Siltide korrastamine", + "template_email_available_tags": "Saad mallis kasutada järgmisi muutujaid: {tags}", + "template_email_if_empty": "Kui mall on tühi, kasutatakse vaikimisi e-kirja.", + "template_email_invite_album": "Albumisse kutse mall", + "template_email_preview": "Eelvaade", + "template_email_settings": "E-posti mallid", + "template_email_settings_description": "Halda e-posti teavitusmalle", + "template_email_update_album": "Albumi muutmise mall", + "template_email_welcome": "Tervituskirja mall", + "template_settings": "Teavituse mallid", + "template_settings_description": "Teavituste mallide haldamine.", "theme_custom_css_settings": "Kohandatud CSS", "theme_custom_css_settings_description": "Cascading Style Sheets lubab Immich'i kujunduse kohandamist.", "theme_settings": "Teema seaded", @@ -309,8 +318,6 @@ "transcoding_threads_description": "Kõrgem väärtus tähendab kiiremat kodeerimist, aga jätab serverile muude tegevuste jaoks vähem ressursse. See väärtus ei tohiks olla suurem kui protsessori tuumade arv. Väärtus 0 tähendab maksimaalset kasutust.", "transcoding_tone_mapping": "Toonivastendus", "transcoding_tone_mapping_description": "Üritab säilitada HDR videote kvaliteeti SDR-iks teisendamisel. Iga algoritm teeb värvi, detailide ja ereduse osas erinevaid kompromisse. Hable säilitab detaile, Mobius säilitab värve ning Reinhard säilitab eredust.", - "transcoding_tone_mapping_npl": "Toonivastendus NPL", - "transcoding_tone_mapping_npl_description": "Muudab värve, et need paistaksid sellise eredusega ekraanil normaalsed. Madalamad väärtused suurendavad video eredust ja vastupidi, kuna see kompenseerib ekraani eredust. 0 määrab väärtuse automaatselt.", "transcoding_transcode_policy": "Transkodeerimise reegel", "transcoding_transcode_policy_description": "Reegel, millal tuleks videot transkodeerida. HDR-videosid transkodeeritakse alati (v.a. kui transkodeerimine on keelatud).", "transcoding_two_pass_encoding": "Kahekäiguline kodeerimine", @@ -386,7 +393,7 @@ "api_key_empty": "Su API võtme nimi ei tohiks olla tühi", "api_keys": "API võtmed", "app_settings": "Rakenduse seaded", - "appears_in": "Kuvatud", + "appears_in": "Albumid", "archive": "Arhiiv", "archive_or_unarchive_photo": "Arhiveeri või taasta foto", "archive_size": "Arhiivi suurus", @@ -471,6 +478,7 @@ "confirm": "Kinnita", "confirm_admin_password": "Kinnita administraatori parool", "confirm_delete_shared_link": "Kas oled kindel, et soovid selle jagatud lingi kustutada?", + "confirm_keep_this_delete_others": "Kõik muud üksused selles virnas kustutatakse. Kas oled kindel, et soovid jätkata?", "confirm_password": "Kinnita parool", "contain": "Mahuta ära", "context": "Kontekst", @@ -520,6 +528,7 @@ "delete_key": "Kustuta võti", "delete_library": "Kustuta kogu", "delete_link": "Kustuta link", + "delete_others": "Kustuta teised", "delete_shared_link": "Kustuta jagatud link", "delete_tag": "Kustuta silt", "delete_tag_confirmation_prompt": "Kas oled kindel, et soovid sildi {tagName} kustutada?", @@ -610,6 +619,7 @@ "failed_to_create_shared_link": "Jagatud lingi lisamine ebaõnnestus", "failed_to_edit_shared_link": "Jagatud lingi muutmine ebaõnnestus", "failed_to_get_people": "Isikute pärimine ebaõnnestus", + "failed_to_keep_this_delete_others": "Selle üksuse säilitamine ja ülejäänute kustutamine ebaõnnestus", "failed_to_load_asset": "Üksuse laadimine ebaõnnestus", "failed_to_load_assets": "Üksuste laadimine ebaõnnestus", "failed_to_load_people": "Isikute laadimine ebaõnnestus", @@ -722,6 +732,7 @@ "external": "Väline", "external_libraries": "Välised kogud", "face_unassigned": "Seostamata", + "failed_to_load_assets": "Üksuste laadimine ebaõnnestus", "favorite": "Lemmik", "favorites": "Lemmikud", "feature_photo_updated": "Esiletõstetud foto muudetud", @@ -735,7 +746,6 @@ "find_them_fast": "Leia teda kiiresti nime järgi otsides", "folders": "Kaustad", "folders_feature_description": "Kaustavaate abil failisüsteemis olevate fotode ja videote sirvimine", - "force_re-scan_library_files": "Sundskaneeri kogu kõik failid uuesti", "forward": "Edasi", "general": "Üldine", "get_help": "Küsi abi", @@ -790,6 +800,8 @@ "jobs": "Tööted", "keep": "Jäta alles", "keep_all": "Jäta kõik alles", + "keep_this_delete_others": "Säilita see, kustuta ülejäänud", + "kept_this_deleted_others": "See üksus säilitatud ning {count, plural, one {# üksus} other {# üksust}} kustutatud", "keyboard_shortcuts": "Kiirklahvid", "language": "Keel", "language_setting_description": "Vali oma eelistatud keel", @@ -903,7 +915,6 @@ "onboarding_welcome_user": "Tere tulemast, {user}", "online": "Ühendatud", "only_favorites": "Ainult lemmikud", - "only_refreshes_modified_files": "Värskendab ainult muudetud failid", "open_in_map_view": "Ava kaardi vaates", "open_in_openstreetmap": "Ava OpenStreetMap", "open_the_search_filters": "Ava otsingufiltrid", @@ -1014,6 +1025,7 @@ "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", "reassing_hint": "Seosta valitud üksused olemasoleva isikuga", + "recent-albums": "Hiljutised albumid", "recent_searches": "Hiljutised otsingud", "refresh": "Värskenda", "refresh_encoded_videos": "Värskenda kodeeritud videod", @@ -1035,6 +1047,7 @@ "remove_from_album": "Eemalda albumist", "remove_from_favorites": "Eemalda lemmikutest", "remove_from_shared_link": "Eemalda jagatud lingist", + "remove_url": "Eemalda URL", "remove_user": "Eemalda kasutaja", "removed_api_key": "API võti eemaldatud: {name}", "removed_from_archive": "Arhiivist eemaldatud", @@ -1069,9 +1082,7 @@ "saved_settings": "Seaded salvestatud", "say_something": "Ütle midagi", "scan_all_libraries": "Skaneeri kõik kogud", - "scan_all_library_files": "Skaneeri kogu kõik failid uuesti", "scan_library": "Skaneeri", - "scan_new_library_files": "Skaneeri kogu uued failid", "scan_settings": "Skaneerimise seaded", "scanning_for_album": "Albumi skaneerimine...", "search": "Otsi", @@ -1116,6 +1127,7 @@ "server_online": "Server ühendatud", "server_stats": "Serveri statistika", "server_version": "Serveri versioon", + "set": "Määra", "set_as_album_cover": "Sea albumi kaanepildiks", "set_as_profile_picture": "Sea profiilipildiks", "set_date_of_birth": "Määra sünnikuupäev", @@ -1214,13 +1226,16 @@ "they_will_be_merged_together": "Nad ühendatakse kokku", "third_party_resources": "Kolmanda osapoole ressursid", "time_based_memories": "Ajapõhised mälestused", + "timeline": "Ajajoon", "timezone": "Ajavöönd", "to_archive": "Arhiivi", "to_change_password": "Muuda parool", "to_favorite": "Lemmik", + "to_login": "Logi sisse", "to_trash": "Prügikasti", "toggle_settings": "Kuva/peida seaded", "toggle_theme": "Lülita tume teema", + "total": "Kokku", "total_usage": "Kogukasutus", "trash": "Prügikast", "trash_all": "Kõik prügikasti", @@ -1266,6 +1281,8 @@ "user_purchase_settings_description": "Halda oma ostu", "user_role_set": "Määra kasutajale {user} roll {role}", "user_usage_detail": "Kasutajate kasutusandmed", + "user_usage_stats": "Konto kasutuse statistika", + "user_usage_stats_description": "Vaata konto kasutuse statistikat", "username": "Kasutajanimi", "users": "Kasutajad", "utilities": "Tööriistad", @@ -1273,7 +1290,7 @@ "variables": "Muutujad", "version": "Versioon", "version_announcement_closing": "Sinu sõber, Alex", - "version_announcement_message": "Hei sõber, saadaval on rakenduse uus versioon. Palun võta aega, et lugeda väljalasketeadet ning veendu, et su docker-compose.yml ja .env failid on ajakohased, et vältida konfiguratsiooniprobleeme, eriti kui kasutad WatchTower'it või muud mehhanismi, mis rakendust automaatselt uuendab.", + "version_announcement_message": "Hei! Saadaval on uus Immich'i versioon. Palun võta aega, et lugeda väljalasketeadet ning veendu, et su seadistus on ajakohane, et vältida konfiguratsiooniprobleeme, eriti kui kasutad WatchTower'it või muud mehhanismi, mis Immich'it automaatselt uuendab.", "version_history": "Versiooniajalugu", "version_history_item": "Versioon {version} paigaldatud {date}", "video": "Video", diff --git a/i18n/fa.json b/i18n/fa.json index 7c0fba9f3559b..1e40996f1591b 100644 --- a/i18n/fa.json +++ b/i18n/fa.json @@ -56,16 +56,9 @@ "image_prefer_embedded_preview_setting_description": "استفاده از پیش‌نمایش داخلی در عکس‌های RAW به عنوان ورودی پردازش تصویر هنگامی که در دسترس باشد. این می‌تواند رنگ‌های دقیق‌تری را برای برخی تصاویر تولید کند، اما کیفیت پیش‌نمایش به دوربین بستگی دارد و ممکن است تصویر آثار فشرده‌سازی بیشتری داشته باشد.", "image_prefer_wide_gamut": "ترجیحات گستره رنگی وسیع", "image_prefer_wide_gamut_setting_description": "برای تصاویر کوچک از فضای رنگی Display P3 استفاده کنید. این کار باعث حفظ زنده بودن رنگ‌ها در تصاویر با گستره رنگی وسیع می‌شود، اما ممکن است تصاویر در دستگاه‌های قدیمی با نسخه‌های قدیمی مرورگر به شکل متفاوتی نمایش داده شوند. تصاویر با فضای رنگی sRGB به همان حالت sRGB نگه داشته می‌شوند تا از تغییرات رنگی جلوگیری شود.", - "image_preview_format": "فرمت نمایش", - "image_preview_resolution": "وضوح پیش نمایش", - "image_preview_resolution_description": "از این فرمت برای مشاهده یک عکس و همچنین برای یادگیری ماشین استفاده می‌شود. وضوح بالاتر می‌تواند جزئیات بیشتری را حفظ کند، اما زمان بیشتری برای رمزگذاری نیاز دارد، حجم فایل‌ها را بزرگتر می‌کند و ممکن است باعث کاهش پاسخگویی برنامه شود.", "image_quality": "کیفیت", - "image_quality_description": "کیفیت تصویر از 1 تا 100. هرچه بالاتر باشد، کیفیت بهتر است اما فایل‌های بزرگ‌تری تولید می‌کند. این گزینه بر روی تصاویر پیش‌نمایش و بندانگشتی تأثیر می‌گذارد.", "image_settings": "تنظیمات عکس", "image_settings_description": "مدیریت کیفیت و وضوح تصاویر تولید شده", - "image_thumbnail_format": "قالب تصویر بندانگشتی", - "image_thumbnail_resolution": "وضوح تصویر بندانگشتی", - "image_thumbnail_resolution_description": "از این فرمت برای مشاهده گروهی عکس‌ها (مانند صفحه اصلی، نمایش آلبوم و غیره) استفاده می‌شود. وضوح بالاتر می‌تواند جزئیات بیشتری را حفظ کند، اما زمان بیشتری برای رمزگذاری نیاز دارد، حجم فایل‌ها را بزرگتر می‌کند و ممکن است باعث کاهش پاسخگویی برنامه شود.", "job_concurrency": "همزمانی {job}", "job_not_concurrency_safe": "این کار ایمنی همزمانی را تضمین نمی‌کند.", "job_settings": "تنظیمات کار", @@ -74,9 +67,6 @@ "jobs_delayed": "", "jobs_failed": "", "library_created": "کتابخانه ایجاد شده: {library}", - "library_cron_expression": "عبارت کرون", - "library_cron_expression_description": "تنظیم فاصله زمانی اسکن با استفاده از فرمت کرون. برای اطلاعات بیشتر لطفا به مثال‌های Crontab Guru مراجعه کنید", - "library_cron_expression_presets": "پیش‌تنظیمات عبارت Cron", "library_deleted": "کتابخانه حذف شد", "library_import_path_description": "یک پوشه برای وارد کردن مشخص کنید. این پوشه، به همراه زیرپوشه‌ها، برای یافتن تصاویر و ویدیوها اسکن خواهد شد.", "library_scanning": "اسکن دوره ای", @@ -194,15 +184,12 @@ "refreshing_all_libraries": "بروز رسانی همه کتابخانه ها", "registration": "ثبت نام مدیر", "registration_description": "از آنجایی که شما اولین کاربر در سیستم هستید، به عنوان مدیر تعیین شده‌اید و مسئولیت انجام وظایف مدیریتی بر عهده شما خواهد بود و کاربران اضافی توسط شما ایجاد خواهند شد.", - "removing_deleted_files": "حذف فایل‌های آفلاین", "repair_all": "بازسازی همه", "repair_matched_items": "", "repaired_items": "", "require_password_change_on_login": "الزام کاربر به تغییر گذرواژه در اولین ورود", "reset_settings_to_default": "بازنشانی تنظیمات به حالت پیش‌فرض", "reset_settings_to_recent_saved": "بازنشانی تنظیمات به آخرین تنظیمات ذخیره شده", - "scanning_library_for_changed_files": "اسکن کتابخانه برای فایل‌های تغییر یافته", - "scanning_library_for_new_files": "اسکن کتابخانه برای یافتن فایل های جدید", "send_welcome_email": "ارسال ایمیل خوش آمد گویی", "server_external_domain_settings": "دامنه خارجی", "server_external_domain_settings_description": "دامنه برای لینک های عمومی به اشتراک گذاشته شده، شامل //:(s)http", @@ -288,8 +275,6 @@ "transcoding_threads_description": "مقادیر بالاتر منجر به رمزگذاری سریع تر می شود، اما فضای کمتری برای پردازش سایر وظایف سرور در حین فعالیت باقی می گذارد. این مقدار نباید بیشتر از تعداد هسته های CPU باشد. اگر روی 0 تنظیم شود، بیشترین استفاده را خواهد داشت.", "transcoding_tone_mapping": "", "transcoding_tone_mapping_description": "تلاش برای حفظ ظاهر ویدیوهای HDR هنگام تبدیل به SDR. هر الگوریتم تعادل های متفاوتی را برای رنگ، جزئیات و روشنایی ایجاد می کند. Hable جزئیات را حفظ می کند، Mobius رنگ را حفظ می کند و Reinhard روشنایی را حفظ می کند.", - "transcoding_tone_mapping_npl": "", - "transcoding_tone_mapping_npl_description": "رنگ ها برای ظاهر طبیعی در یک نمایشگر با این روشنایی تنظیم خواهند شد. برخلاف انتظار، مقادیر پایین تر باعث افزایش روشنایی ویدیو و برعکس می شوند، زیرا آن را برای روشنایی نمایشگر جبران می کند. مقدار 0 این مقدار را به طور خودکار تنظیم می کند.", "transcoding_transcode_policy": "سیاست رمزگذاری", "transcoding_transcode_policy_description": "سیاست برای زمانی که ویدیویی باید مجددا تبدیل (رمزگذاری) شود. ویدیوهای HDR همیشه تبدیل (رمزگذاری) مجدد خواهند شد (مگر رمزگذاری مجدد غیرفعال باشد).", "transcoding_two_pass_encoding": "تبدیل (رمزگذاری) دو مرحله ای", @@ -349,10 +334,8 @@ "archive_or_unarchive_photo": "", "archive_size": "", "archive_size_description": "", - "archived": "", "asset_offline": "", "assets": "", - "assets_moved_to_trash": "", "authorized_devices": "", "back": "", "backward": "", @@ -367,10 +350,6 @@ "cancel_search": "", "cannot_merge_people": "", "cannot_update_the_description": "", - "cant_apply_changes": "", - "cant_get_faces": "", - "cant_search_people": "", - "cant_search_places": "", "change_date": "", "change_expiration_time": "", "change_location": "", @@ -561,7 +540,6 @@ "extension": "", "external": "", "external_libraries": "", - "failed_to_get_people": "", "favorite": "", "favorite_or_unfavorite_photo": "", "favorites": "", @@ -573,14 +551,12 @@ "filter_people": "", "find_them_fast": "", "fix_incorrect_match": "", - "force_re-scan_library_files": "", "forward": "", "general": "", "get_help": "", "getting_started": "", "go_back": "", "go_to_search": "", - "go_to_share_page": "", "group_albums_by": "", "has_quota": "", "hide_gallery": "", @@ -701,7 +677,6 @@ "oldest_first": "", "online": "", "only_favorites": "", - "only_refreshes_modified_files": "", "open_the_search_filters": "", "options": "", "organize_your_library": "", @@ -737,7 +712,6 @@ "permanent_deletion_warning_setting_description": "", "permanently_delete": "", "permanently_deleted_asset": "", - "permanently_deleted_assets": "", "person": "", "photos": "", "photos_count": "", @@ -794,8 +768,6 @@ "saved_settings": "", "say_something": "", "scan_all_libraries": "", - "scan_all_library_files": "", - "scan_new_library_files": "", "scan_settings": "", "scanning_for_album": "", "search": "", @@ -827,7 +799,6 @@ "selected": "", "send_message": "", "send_welcome_email": "", - "server": "", "server_stats": "", "set": "", "set_as_album_cover": "", @@ -899,7 +870,6 @@ "to_trash": "", "toggle_settings": "", "toggle_theme": "", - "toggle_visibility": "", "total_usage": "", "trash": "", "trash_all": "", @@ -908,7 +878,6 @@ "trashed_items_will_be_permanently_deleted_after": "", "type": "", "unarchive": "", - "unarchived": "", "unfavorite": "", "unhide_person": "", "unknown": "", @@ -949,7 +918,6 @@ "view_links": "", "view_next_asset": "", "view_previous_asset": "", - "viewer": "", "waiting": "", "week": "", "welcome": "", diff --git a/i18n/fi.json b/i18n/fi.json index d3783691bef1f..aa9f029cd8695 100644 --- a/i18n/fi.json +++ b/i18n/fi.json @@ -1,5 +1,5 @@ { - "about": "Tietoja", + "about": "Päivitä", "account": "Tili", "account_settings": "Tilin asetukset", "acknowledge": "Tiedostan", @@ -23,6 +23,7 @@ "add_to": "Lisää...", "add_to_album": "Lisää albumiin", "add_to_shared_album": "Lisää jaettuun albumiin", + "add_url": "Lisää URL", "added_to_archive": "Arkistoitu", "added_to_favorites": "Lisätty suosikkeihin", "added_to_favorites_count": "{count, number} lisätty suosikkeihin", @@ -34,6 +35,11 @@ "authentication_settings_disable_all": "Haluatko varmasti poistaa kaikki kirjautumistavat käytöstä? Kirjautuminen on tämän jälkeen mahdotonta.", "authentication_settings_reenable": "Ottaaksesi uudestaan käyttöön, käytä Palvelin Komentoa.", "background_task_job": "Taustatyöt", + "backup_database": "Varmuuskopioi Tietokanta", + "backup_database_enable_description": "Ota käyttöön tietokannan varmuuskopiointi", + "backup_keep_last_amount": "Varmuuskopioiden lukumäärä", + "backup_settings": "Varmuuskopioinnin asetukset", + "backup_settings_description": "Hallitse tietokannan varmuuskopioiden asetuksia", "check_all": "Tarkista kaikki", "cleared_jobs": "Työn {job} tehtävät tyhjennetty", "config_set_by_file": "Asetukset on tällä hetkellä määritelty tiedostosta", @@ -43,9 +49,10 @@ "confirm_reprocess_all_faces": "Haluatko varmasti käsitellä uudelleen kaikki kasvot? Tämä poistaa myös nimetyt henkilöt.", "confirm_user_password_reset": "Haluatko varmasti nollata käyttäjän {user} salasanan?", "create_job": "Luo tehtävä", - "crontab_guru": "Crontab Guru", + "cron_expression": "Cron-lauseke", + "cron_expression_description": "Aseta skannausväli käyttämällä cron-formaattia. Lisätietoja linkistä. Crontab Guru", + "cron_expression_presets": "Esiasetetut Cron-lausekkeet", "disable_login": "Poista kirjautuminen käytöstä", - "disabled": "Ei käytössä", "duplicate_detection_job_description": "Tunnista samankaltaiset kuvat käyttäen koneoppimista. Tukeutuu Smart Search:iin", "exclusion_pattern_description": "Poissulkemismallit mahdollistavat tiettyjen tiedostojen ja kansioiden jättämisen pois kirjastoasi skannatessa. Tästä on hyötyä jos kansiot sisältävät tiedostoja mitä et halua tuoda, kuten RAW-tiedostot.", "external_library_created_at": "Ulkoinen kirjasto (luotu {date})", @@ -63,22 +70,15 @@ "image_prefer_wide_gamut": "Suosi laajaa väriskaalaa", "image_prefer_wide_gamut_setting_description": "Käytä Display P3 -nimiavaruutta pikkukuville. Tämä säilöö värien vivahteet paremmin, mutta kuvat saattavat näyttää erilaisilta vanhemmissa laitteissa. sRGB-kuvat pidetään muuttumattomina, jottei värit muuttuisi.", "image_preview_description": "Keskikokoinen kuva, josta metatiedot on poistettu, käytetään yksittäisen resurssin katseluun ja koneoppimiseen", - "image_preview_format": "Esikatselun muoto", "image_preview_quality_description": "Esikatselulaatu 1-100. Korkeampi arvo on parempi, mutta tuottaa suurempia tiedostoja ja voi heikentää sovelluksen reagointikykyä. Matalan arvon asettaminen voi vaikuttaa koneoppimisen laatuun.", - "image_preview_resolution": "Esikatselun resoluutio", - "image_preview_resolution_description": "Käytetään kun katsellaan yksittäisiä kuvia, tai koneoppimiseen. Suurempi resoluutio voi säilyttää paremmin yksityiskohtia. Tosin koodaus kestää kauemmin, tiedostokoko kasvaa, ja se saattaa hidastaa sovelluksen responsiivisuutta.", "image_preview_title": "Esikatselun asetukset", "image_quality": "Laatu", - "image_quality_description": "Kuvan laatu välillä 1-100. Suurempi arvo on paremman laatuinen, mutta tuottaa kookkaampia tiedostoja. Tämä asetus vaikuttaa esikatselu- ja pikkukuviin.", "image_resolution": "Resoluutio", "image_resolution_description": "Korkeammat resoluutiot voivat säilyttää enemmän yksityiskohtia, mutta niiden koodaus kestää kauemmin, tiedostokoot ovat suurempia ja ne voivat heikentää sovelluksen reagointikykyä.", "image_settings": "Kuva-asetukset", "image_settings_description": "Hallitse luotujen kuvien laatua ja resoluutiota", "image_thumbnail_description": "Pieni pikkukuva, josta metatiedot on poistettu, käytetään valokuvaryhmien katseluun, kuten pääaikajanalla", - "image_thumbnail_format": "Pikkukuvien muoto", "image_thumbnail_quality_description": "Pikkukuvan laatu 1-100. Korkeampi arvo on parempi, mutta tuottaa suurempia tiedostoja ja voi heikentää sovelluksen reagointikykyä.", - "image_thumbnail_resolution": "Pikkukuvien resoluutio", - "image_thumbnail_resolution_description": "Käytetään katsottaessa useita kuvia kerralla (aikajana, albuminäkymä, jne.) Korkeampi resoluutio antaa enemmän yksityiskohtia, mutta niiden luonti kestää kauemmin, tiedostokoot ovat isompia ja voivat heikentää sovelluksen responsiivisuutta.", "image_thumbnail_title": "Pikkukuva-asetukset", "job_concurrency": "Tehtävän \"{job}\" samanaikaisuus", "job_created": "Tehtävä luotu", @@ -89,9 +89,6 @@ "jobs_delayed": "{jobCount, plural, other {# viivästynyttä}}", "jobs_failed": "{jobCount, plural, other {# epäonnistunutta}}", "library_created": "Kirjasto {library} luotu", - "library_cron_expression": "Cron-lauseke", - "library_cron_expression_description": "Anna skannaustiheys cron-formaatissa. Saadaksesi lisätietoja katso esimerkiksi Crontab Guru", - "library_cron_expression_presets": "Cron-lausekkeen esiasetukset", "library_deleted": "Kirjasto poistettu", "library_import_path_description": "Määritä kansio joka tuodaan. Kuvat ja videot skannataan tästä kansiosta, sekä alikansioista.", "library_scanning": "Ajoittainen skannaus", @@ -215,7 +212,6 @@ "refreshing_all_libraries": "Virkistetään kaikki kirjastot", "registration": "Pääkäyttäjän rekisteröinti", "registration_description": "Pääkäyttäjänä olet vastuussa järjestelmän hallinnallisista tehtävistä ja uusien käyttäjien luomisesta.", - "removing_deleted_files": "Poistetaan Offline-tiedostot", "repair_all": "Korjaa kaikki", "repair_matched_items": "Löytyi {count, plural, one {# osuma} other {# osumaa}}", "repaired_items": "Korjattiin {count, plural, one {# kohta} other {# kohtaa}}", @@ -223,12 +219,12 @@ "reset_settings_to_default": "Nollaa asetukset oletuksille", "reset_settings_to_recent_saved": "Palauta aiemmin tallennetut asetukset", "scanning_library": "Kirjastoa skannataan", - "scanning_library_for_changed_files": "Etsitään kirjaston muuttuneita tiedostoja", - "scanning_library_for_new_files": "Etsitään uusia tiedostoja", "search_jobs": "Etsi tehtäviä...", "send_welcome_email": "Lähetä tervetuloviesti", "server_external_domain_settings": "Ulkoinen osoite", "server_external_domain_settings_description": "Osoite julkisille linkeille, http(s):// mukaan lukien", + "server_public_users": "Julkiset käyttäjät", + "server_public_users_description": "Kaikki käyttäjät (nimi ja sähköpostiosoite) luetellaan, kun käyttäjä lisätään jaettuihin albumeihin. Kun toiminto on poistettu käytöstä, käyttäjäluettelo on vain pääkäyttäjien käytettävissä.", "server_settings": "Palvelimen asetukset", "server_settings_description": "Ylläpidä palvelimen asetuksia", "server_welcome_message": "Tervetuloviesti", @@ -254,6 +250,7 @@ "storage_template_user_label": "{label} on käyttäjän Tallennustilan Tunniste", "system_settings": "Järjestelmäasetukset", "tag_cleanup_job": "Merkintäpuhdistus", + "template_email_preview": "Esikatselu", "theme_custom_css_settings": "Mukautettu CSS", "theme_custom_css_settings_description": "Mukauta Immichin ulkoasua CSS:llä.", "theme_settings": "Teeman asetukset", @@ -261,7 +258,6 @@ "these_files_matched_by_checksum": "Näillä tiedostoilla on yhteinen tarkistussumma", "thumbnail_generation_job": "Generoi pikkukuvat", "thumbnail_generation_job_description": "Generoi isot, pienet sekä sumeat pikkukuvat jokaisesta aineistosta, kuten myös henkilöistä", - "transcode_policy_description": "", "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_nvenc": "NVENC (vaatii NVIDIA:n grafiikkasuorittimen)", @@ -313,8 +309,6 @@ "transcoding_threads_description": "Korkeampi arvo nopeuttaa enkoodausta, mutta vie tilaa palvelimen muilta tehtäviltä. Tämä arvo ei tulisi olla suurempi mitä suorittimen ytimien määrä. Suurin mahdollinen käyttö, mikäli arvo on 0.", "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_tone_mapping_npl": "Sävykartoitus (NPL)", - "transcoding_tone_mapping_npl_description": "Värejä säädetään niin, että ne näyttävät luonnollisilta tällä kirkkaudella. Päinvastoin kuin luulisi, alempi arvo nostaa kirkkautta ja päinvastoin, koska se kompensoi näytön kirkkautta. 0 määrittää tason automaattisesti.", "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_two_pass_encoding": "Two-pass enkoodaus", @@ -395,7 +389,6 @@ "archive_or_unarchive_photo": "Arkistoi kuva tai palauta arkistosta", "archive_size": "Arkiston koko", "archive_size_description": "Määritä arkiston koko latauksissa (Gt)", - "archived": "Arkistoitu", "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?", @@ -416,7 +409,6 @@ "assets_added_to_album_count": "Albumiin lisätty {count, plural, one {# kohde} other {# kohdetta}}", "assets_added_to_name_count": "Lisätty {count, plural, one {# kohde} other {# kohdetta}} {hasName, select, true {{name}} other {uuteen albumiin}}", "assets_count": "{count, plural, one {# media} other {# mediaa}}", - "assets_moved_to_trash": "Siirretty {count, plural, one {# aineisto} other {# aineistoa}} roskakoriin", "assets_moved_to_trash_count": "Siirretty {count, plural, one {# media} other {# mediaa}} roskakoriin", "assets_permanently_deleted_count": "{count, plural, one {# media} other {# mediaa}} poistettu pysyvästi", "assets_removed_count": "{count, plural, one {# media} other {# mediaa}} poistettu", @@ -446,10 +438,6 @@ "cannot_merge_people": "Ihmisiä ei voitu yhdistää", "cannot_undo_this_action": "Et voi perua tätä toimintoa!", "cannot_update_the_description": "Kuvausta ei voi päivittää", - "cant_apply_changes": "Asetuksia ei voitu määrittää", - "cant_get_faces": "Kasvoja ei voinut hakea", - "cant_search_people": "Ihmisiä ei voinut etsiä", - "cant_search_places": "Sijainteja ei voinut etsiä", "change_date": "Vaihda päiväys", "change_expiration_time": "Muuta erääntymisaikaa", "change_location": "Vaihda sijainti", @@ -481,6 +469,7 @@ "confirm": "Vahvista", "confirm_admin_password": "Vahvista ylläpitäjän salasana", "confirm_delete_shared_link": "Haluatko varmasti poistaa tämän jaetun linkin?", + "confirm_keep_this_delete_others": "Kuvapinon muut kuvat tätä lukuunottamatta poistetaan. Oletko varma, että haluat jatkaa?", "confirm_password": "Vahvista salasana", "contain": "Mahduta", "context": "Konteksti", @@ -530,6 +519,7 @@ "delete_key": "Poista avain", "delete_library": "Poista kirjasto", "delete_link": "Poista linkki", + "delete_others": "Poista muut", "delete_shared_link": "Poista jaettu linkki", "delete_tag": "Poista tunniste", "delete_tag_confirmation_prompt": "Haluatko varmasti poistaa tunnisteen {tagName}?", @@ -563,13 +553,6 @@ "duplicates": "Kaksoiskappaleet", "duplicates_description": "Selvitä jokaisen kohdalla mitkä (jos yksikään) ovat kaksoiskappaleita", "duration": "Kesto", - "durations": { - "days": "", - "hours": "", - "minutes": "", - "months": "", - "years": "" - }, "edit": "Muokkaa", "edit_album": "Muokkaa albumia", "edit_avatar": "Muokkaa avataria", @@ -594,8 +577,6 @@ "editor_crop_tool_h2_aspect_ratios": "Kuvasuhteet", "editor_crop_tool_h2_rotation": "Rotaatio", "email": "Sähköposti", - "empty": "", - "empty_album": "", "empty_trash": "Tyhjennä roskakori", "empty_trash_confirmation": "Haluatko varmasti tyhjentää roskakorin? Tämä poistaa pysyvästi kaikki tiedostot Immich:stä.\nToimintoa ei voi perua!", "enable": "Ota käyttöön", @@ -629,6 +610,7 @@ "failed_to_create_shared_link": "Jaetun linkin luonti epäonnistui", "failed_to_edit_shared_link": "Jaetun linkin muokkaus epäonnistui", "failed_to_get_people": "Henkilöiden haku epäonnistui", + "failed_to_keep_this_delete_others": "Muiden kohteiden poisto epäonnistui", "failed_to_load_asset": "Kohteen lataus epäonnistui", "failed_to_load_assets": "Kohteiden lataus epäonnistui", "failed_to_load_people": "Henkilöiden lataus epäonnistui", @@ -656,8 +638,6 @@ "unable_to_change_location": "Sijainnin muuttaminen epäonnistui", "unable_to_change_password": "Salasanan vaihto epäonnistui", "unable_to_change_visibility": "Ei voida muuttaa näkyvyyttä {count, plural, one {# henkilölle} other {# henkilölle}}", - "unable_to_check_item": "", - "unable_to_check_items": "", "unable_to_complete_oauth_login": "OAuth-kirjautumista ei voitu suorittaa loppuun", "unable_to_connect": "Yhteyttä ei voitu muodostaa", "unable_to_connect_to_server": "Palvelimeen ei saatu yhteyttä", @@ -698,13 +678,10 @@ "unable_to_remove_album_users": "Käyttäjien poistaminen albumista epäonnistui", "unable_to_remove_api_key": "API-avaimen poistaminen epäonnistui", "unable_to_remove_assets_from_shared_link": "kohteiden poistaminen jaetusta linkistä epäonnistui", - "unable_to_remove_comment": "", "unable_to_remove_deleted_assets": "Offline-tiedostoja ei voitu poistaa", "unable_to_remove_library": "Kirjaston poistaminen epäonnistui", - "unable_to_remove_offline_files": "Offline-tiedostojen poistaminen epäonnistui", "unable_to_remove_partner": "Kumppanin poistaminen epäonnistui", "unable_to_remove_reaction": "Reaktion poistaminen epäonnistui", - "unable_to_remove_user": "", "unable_to_repair_items": "Kohteiden korjaaminen epäonnistui", "unable_to_reset_password": "Salasanan nollaaminen epäonnistui", "unable_to_resolve_duplicate": "Virheilmoitus näkyy, kun palvelin palauttaa virheen painettaessa roskakorin tai säilytä-painiketta.", @@ -734,10 +711,6 @@ "unable_to_update_user": "Käyttäjän muokkaus epäonnistui", "unable_to_upload_file": "Tiedostoa ei voitu ladata" }, - "every_day_at_onepm": "", - "every_night_at_midnight": "", - "every_night_at_twoam": "", - "every_six_hours": "", "exif": "Exif", "exit_slideshow": "Poistu diaesityksestä", "expand_all": "Laajenna kaikki", @@ -752,33 +725,27 @@ "external": "Ulkoisesta", "external_libraries": "Ulkoiset kirjastot", "face_unassigned": "Ei määritelty", - "failed_to_get_people": "", "favorite": "Suosikki", "favorite_or_unfavorite_photo": "Suosikki- tai ei-suosikkikuva", "favorites": "Suosikit", - "feature": "", "feature_photo_updated": "Kansikuva ladattu", - "featurecollection": "", "features": "Ominaisuudet", "features_setting_description": "Hallitse sovelluksen ominaisuuksia", "file_name": "Tiedoston nimi", "file_name_or_extension": "Tiedostonimi tai tiedostopääte", "filename": "Tiedostonimi", - "files": "", "filetype": "Tiedostotyyppi", "filter_people": "Suodata henkilöt", "find_them_fast": "Löydä nopeasti hakemalla nimellä", "fix_incorrect_match": "Korjaa virheellinen osuma", "folders": "Kansiot", "folders_feature_description": "Käytetään kansionäkymää valokuvien ja videoiden selaamiseen järjestelmässä", - "force_re-scan_library_files": "Pakota kaikkien kirjastotiedostojen uudelleenskannaus", "forward": "Eteenpäin", "general": "Yleinen", "get_help": "Hae apua", "getting_started": "Aloittaminen", "go_back": "Palaa", "go_to_search": "Siirry hakuun", - "go_to_share_page": "", "group_albums_by": "Ryhmitä albumi...", "group_no": "Ei ryhmitystä", "group_owner": "Ryhmitä omistajan mukaan", @@ -804,7 +771,6 @@ "image_alt_text_date_place_2_people": "{isVideo, select, true {Video} other {Kuva}} otettu {city}ssä, {country}ssä {person1}n ja {person2}n kanssa {date}", "image_alt_text_date_place_3_people": "{isVideo, select, true {Video} other {Kuva}} otettu {city}ssä, {country}ssä {person1}n, {person2}n ja {person3}n kanssa {date}", "image_alt_text_date_place_4_or_more_people": "{isVideo, select, true {Video} other {Kuva}} otettu {city}ssä, {country}ssä {person1}n, {person2}n ja {additionalCount, number} muun kanssa {date}", - "img": "", "immich_logo": "Immich-logo", "immich_web_interface": "Immich-verkkokäyttöliittymä", "import_from_json": "Tuo JSON-tiedostosta", @@ -825,10 +791,11 @@ "invite_people": "Kutsu ihmisiä", "invite_to_album": "Kutsu albumiin", "items_count": "{count, plural, one {# kpl} other {# kpl}}", - "job_settings_description": "", "jobs": "Taustatehtävät", "keep": "Säilytä", "keep_all": "Säilytä kaikki", + "keep_this_delete_others": "Säilytä tämä, poista muut", + "kept_this_deleted_others": "Tämä kohde säilytettiin. {count, plural, one {# asset} other {# assets}} poistettiin", "keyboard_shortcuts": "Pikanäppäimet", "language": "Kieli", "language_setting_description": "Valitse suosimasi kieli", @@ -840,8 +807,6 @@ "level": "Taso", "library": "Kirjasto", "library_options": "Kirjastovaihtoehdot", - "license_button_buy": "Osta", - "license_button_select": "Valitse", "light": "Vaalea", "like_deleted": "Tykkäys poistettu", "link_motion_video": "Linkitä liikevideo", @@ -946,7 +911,6 @@ "onboarding_welcome_user": "Tervetuloa {user}", "online": "Online", "only_favorites": "Vain suosikit", - "only_refreshes_modified_files": "Päivittää vain muakatut tiedostot", "open_in_map_view": "Avaa karttanäkymässä", "open_in_openstreetmap": "Avaa OpenStreetMapissa", "open_the_search_filters": "Avaa hakusuodattimet", @@ -984,7 +948,6 @@ "people_edits_count": "Muokattu {count, plural, one {# henkilö} other {# henkilöä}}", "people_feature_description": "Selataan valokuvia ja videoita, jotka on ryhmitelty henkilöiden mukaan", "people_sidebar_description": "Näytä linkki Henkilöihin sivupalkissa", - "perform_library_tasks": "", "permanent_deletion_warning": "Pysyvän poiston varoitus", "permanent_deletion_warning_setting_description": "Näytä varoitus, kun poistat kohteita pysyvästi", "permanently_delete": "Poista pysyvästi", @@ -1006,7 +969,6 @@ "play_memories": "Toista muistot", "play_motion_photo": "Toista Liikekuva", "play_or_pause_video": "Toista tai keskeytä video", - "point": "", "port": "Portti", "preset": "Asetus", "preview": "Esikatselu", @@ -1051,12 +1013,10 @@ "purchase_server_description_2": "Tukijan tila", "purchase_server_title": "Palvelin", "purchase_settings_server_activated": "Palvelimen tuoteavainta hallinnoi ylläpitäjä", - "range": "", "rating": "Tähtiarvostelu", "rating_clear": "Tyhjennä arvostelu", "rating_count": "{count, plural, one {# tähti} other {# tähteä}}", "rating_description": "Näytä EXIF-arvosana lisätietopaneelissa", - "raw": "", "reaction_options": "Reaktioasetukset", "read_changelog": "Lue muutosloki", "reassign": "Määritä uudelleen", @@ -1101,7 +1061,6 @@ "reset": "Nollaa", "reset_password": "Nollaa salasana", "reset_people_visibility": "Nollaa henkilöiden näkyvyysasetukset", - "reset_settings_to_default": "", "reset_to_default": "Palauta oletusasetukset", "resolve_duplicates": "Ratkaise kaksoiskappaleet", "resolved_all_duplicates": "Kaikki kaksoiskappaleet selvitetty", @@ -1121,9 +1080,7 @@ "saved_settings": "Asetukset tallennettu", "say_something": "Sano jotain", "scan_all_libraries": "Skannaa kaikki kirjastot", - "scan_all_library_files": "Skannaa uudelleen kaikki kirjastotiedostot", "scan_library": "Skannaa", - "scan_new_library_files": "Skannaa uusia kirjastotiedostoja", "scan_settings": "Skannausasetukset", "scanning_for_album": "Etsitään albumia...", "search": "Haku", @@ -1166,7 +1123,6 @@ "selected_count": "{count, plural, other {# valittu}}", "send_message": "Lähetä viesti", "send_welcome_email": "Lähetä tervetuloviesti", - "server": "Palvelin", "server_offline": "Palvelin Offline-tilassa", "server_online": "Palvelin Online-tilassa", "server_stats": "Palvelimen tilastot", @@ -1271,6 +1227,7 @@ "they_will_be_merged_together": "Nämä tullaan yhdistämään", "third_party_resources": "Kolmannen osapuolen resurssit", "time_based_memories": "Aikaan perustuvat muistot", + "timeline": "Aikajana", "timezone": "Aikavyöhyke", "to_archive": "Arkistoi", "to_change_password": "Vaihda salasana", @@ -1280,7 +1237,7 @@ "to_trash": "Roskakoriin", "toggle_settings": "Määritä asetukset", "toggle_theme": "Aseta tumma teema", - "toggle_visibility": "Aseta näkyvyys", + "total": "Yhteensä", "total_usage": "Käyttö yhteensä", "trash": "Roskakori", "trash_all": "Vie kaikki roskakoriin", @@ -1290,12 +1247,10 @@ "trashed_items_will_be_permanently_deleted_after": "Roskakorin kohteet poistetaan pysyvästi {days, plural, one {# päivän} other {# päivän}} päästä.", "type": "Tyyppi", "unarchive": "Palauta arkistosta", - "unarchived": "", "unarchived_count": "{count, plural, other {# poistettu arkistosta}}", "unfavorite": "Poista suosikeista", "unhide_person": "Poista henkilö piilosta", "unknown": "Tuntematon", - "unknown_album": "", "unknown_year": "Tuntematon vuosi", "unlimited": "Rajoittamaton", "unlink_motion_video": "Poista liikevideon linkitys", @@ -1332,6 +1287,8 @@ "user_purchase_settings_description": "Hallitse ostostasi", "user_role_set": "Tee käyttäjästä {user} {role}", "user_usage_detail": "Käyttäjän käytön tiedot", + "user_usage_stats": "Tilin käyttötilastot", + "user_usage_stats_description": "Näytä tilin käyttötilastot", "username": "Käyttäjänimi", "users": "Käyttäjät", "utilities": "Apuohjelmat", @@ -1339,7 +1296,7 @@ "variables": "Muuttujat", "version": "Versio", "version_announcement_closing": "Ystäväsi Alex", - "version_announcement_message": "Hei! Sovelluksen uusi versio on saatavilla. Käythän vilkaisemassa julkaisun tiedot ja varmistathan, että docker-compose.yml ja .env määritykset ovat ajan tasalla. Näin varmistat järjestelmän toimivuuden, varsinkin jos käytät WatchToweria tai muuta automaattista päivitysjärjestelmää.", + "version_announcement_message": "Hei! Sovelluksen uusi versio on saatavilla. Käythän vilkaisemassa julkaisun tiedot ja varmistathan, että ohjelman määritykset ovat ajan tasalla. Erityisesti, jos käytössä on Watchtower tai jokin muu mekanismi Immich-sovelluksen automaattista päivitystä varten.", "version_history": "Versiohistoria", "version_history_item": "Asennettu {version} päivänä {date}", "video": "Video", @@ -1353,10 +1310,10 @@ "view_all_users": "Näytä kaikki käyttäjät", "view_in_timeline": "Näytä aikajanalla", "view_links": "Näytä linkit", + "view_name": "Näkymä", "view_next_asset": "Näytä seuraava", "view_previous_asset": "Näytä edellinen", "view_stack": "Näytä pinona", - "viewer": "", "visibility_changed": "{count, plural, one {# henkilön} other {# henkilöiden}} näkyvyys vaihdettu", "waiting": "Odottaa", "warning": "Varoitus", diff --git a/i18n/fil.json b/i18n/fil.json new file mode 100644 index 0000000000000..c296e59dd151b --- /dev/null +++ b/i18n/fil.json @@ -0,0 +1,25 @@ +{ + "about": "I-refresh", + "account": "Account", + "account_settings": "Mga Setting ng Account", + "acknowledge": "Tanggapin", + "action": "Aksyon", + "actions": "Mga Aksyon", + "active": "Tumatakbo", + "activity": "Mga Aktibidad", + "activity_changed": "Ang aktibidad ay {enabled, select, true {naka-enable} other {hindi naka-enable}}", + "add": "Mag dagdag", + "add_a_description": "Dagdagan ng deskripsyon", + "add_a_location": "Dagdagan ng lugar", + "add_a_name": "Dagdagan ng pangalan", + "add_a_title": "Dagdagan ng pamagat", + "add_location": "Magdagdag ng lugar", + "add_more_users": "Magdagdag ng mga user", + "add_photos": "Magdagdag ng litrato", + "add_to": "Idagdag sa...", + "add_to_album": "Idagdag sa album", + "add_to_shared_album": "Idagdag sa shared album", + "added_to_archive": "Idinagdag sa archive", + "added_to_favorites": "Idinagdag sa mga paborito", + "added_to_favorites_count": "Idinagdag ang {count, number} sa mga paborito" +} diff --git a/i18n/fr.json b/i18n/fr.json index 781f801bb9f36..ad141208c69e0 100644 --- a/i18n/fr.json +++ b/i18n/fr.json @@ -5,12 +5,12 @@ "acknowledge": "Compris", "action": "Action", "actions": "Actions", - "active": "En cours d'exécution", + "active": "En cours", "activity": "Activité", "activity_changed": "Activité {enabled, select, true {autorisée} other {interdite}}", "add": "Ajouter", "add_a_description": "Ajouter une description", - "add_a_location": "Ajouter un emplacement", + "add_a_location": "Ajouter une localisation", "add_a_name": "Ajouter un nom", "add_a_title": "Ajouter un titre", "add_exclusion_pattern": "Ajouter un schéma d'exclusion", @@ -23,6 +23,7 @@ "add_to": "Ajouter à…", "add_to_album": "Ajouter à l'album", "add_to_shared_album": "Ajouter à l'album partagé", + "add_url": "Ajouter l'URL", "added_to_archive": "Ajouté à l'archive", "added_to_favorites": "Ajouté aux favoris", "added_to_favorites_count": "{count, number} ajouté(s) aux favoris", @@ -30,12 +31,17 @@ "add_exclusion_pattern_description": "Ajouter des schémas d'exclusion. Les caractères génériques *, ** et ? sont pris en charge. Pour ignorer tous les fichiers dans un répertoire nommé « Raw », utilisez « **/Raw/** ». Pour ignorer tous les fichiers se terminant par « .tif », utilisez « **/*.tif ». Pour ignorer un chemin absolu, utilisez « /chemin/à/ignorer/** ».", "asset_offline_description": "Ce média de la bibliothèque externe n'est plus présent sur le disque et a été déplacé vers la corbeille. Si le fichier a été déplacé dans la bibliothèque, vérifiez votre chronologie pour le nouveau média correspondant. Pour restaurer ce média, veuillez vous assurer que le chemin du fichier ci-dessous peut être accédé par Immich et lancez l'analyse de la bibliothèque.", "authentication_settings": "Paramètres d'authentification", - "authentication_settings_description": "Gérer le mot de passe, la délégation d'authentification OAuth et d'autres paramètres d'authentification", + "authentication_settings_description": "Gérer le mot de passe, l'authentification OAuth et d'autres paramètres d'authentification", "authentication_settings_disable_all": "Êtes-vous sûr de vouloir désactiver toutes les méthodes de connexion ? La connexion sera complètement désactivée.", "authentication_settings_reenable": "Pour réactiver, utilisez une Commande Serveur.", "background_task_job": "Tâches de fond", - "check_all": "Vérifier tout", - "cleared_jobs": "Tâches supprimées pour : {job}", + "backup_database": "Sauvegarde de la base de données", + "backup_database_enable_description": "Activer la sauvegarde", + "backup_keep_last_amount": "Nombre de sauvegardes à conserver", + "backup_settings": "Paramètres de la sauvegarde", + "backup_settings_description": "Gérer les paramètres de la sauvegarde", + "check_all": "Tout cocher", + "cleared_jobs": "Tâches supprimées pour : {job}", "config_set_by_file": "La configuration est actuellement définie par un fichier de configuration", "confirm_delete_library": "Êtes-vous sûr de vouloir supprimer la bibliothèque {library} ?", "confirm_delete_library_assets": "Êtes-vous sûr de vouloir supprimer cette bibliothèque ? Cette opération supprimera d'Immich {count, plural, one {le média} other {les # médias}} qu'elle contient et ne pourra pas être annulée. Les fichiers resteront sur le disque.", @@ -43,15 +49,16 @@ "confirm_reprocess_all_faces": "Êtes-vous sûr de vouloir retraiter tous les visages ? Cela effacera également les personnes déjà identifiées.", "confirm_user_password_reset": "Êtes-vous sûr de vouloir réinitialiser le mot de passe de {user} ?", "create_job": "Créer une tâche", - "crontab_guru": "Générateur de règles Cron", + "cron_expression": "Expression cron", + "cron_expression_description": "Définir l'intervalle d'analyse à l'aide d'une expression cron. Pour plus d'informations, voir Crontab Guru", + "cron_expression_presets": "Préréglages d'expression cron", "disable_login": "Désactiver la connexion", - "disabled": "Désactivé", - "duplicate_detection_job_description": "Exécution de l'apprentissage automatique sur les médias pour détecter les images similaires. S'appuie sur la recherche intelligente", + "duplicate_detection_job_description": "Lancement de l'apprentissage automatique sur les médias pour détecter les images similaires. Se base sur la recherche intelligente", "exclusion_pattern_description": "Les schémas d'exclusion vous permettent d'ignorer des fichiers et des dossiers lors de l'analyse de votre bibliothèque. Cette fonction est utile si des dossiers contiennent des fichiers que vous ne souhaitez pas importer, tels que des fichiers RAW.", "external_library_created_at": "Bibliothèque externe (créée le {date})", "external_library_management": "Gestion de la bibliothèque externe", "face_detection": "Détection des visages", - "face_detection_description": "Détection des visages dans les médias à l'aide de l'apprentissage automatique. Pour les vidéos, seule la miniature est prise en compte. « Rafraichir» (re)traite tous les médias. « Réinitialise» met en file d'attente les médias qui n'ont pas encore été traités. Les visages détectés seront mis en file d'attente pour la reconnaissance faciale une fois la détection des visages terminée, les regroupant en personnes existantes ou nouvelles.", + "face_detection_description": "Détection des visages dans les médias à l'aide de l'apprentissage automatique. Pour les vidéos, seule la miniature est prise en compte. « Actualiser » (re)traite tous les médias. « Réinitialiser » efface en plus toutes les données actuelles de visages. « Manquants » Les visages détectés seront mis en file d'attente pour la reconnaissance faciale. Une fois la détection des visages terminée, les regroupant en personnes existantes ou nouvelles.", "facial_recognition_job_description": "Regrouper les visages détectés en personnes. Cette étape est exécutée une fois la détection des visages terminée. « Rafraichir» (re)regroupe tous les visages. « Manquant» met en file d'attente les visages auxquels aucune personne n'a été attribuée.", "failed_job_command": "La commande {command} a échoué pour la tâche : {job}", "force_delete_user_warning": "ATTENTION : Cette opération entraîne la suppression immédiate de l'utilisateur et de tous ses médias. Cette opération ne peut être annulée et les fichiers ne peuvent être récupérés.", @@ -63,22 +70,15 @@ "image_prefer_wide_gamut": "Préférer une gamme de couleurs étendue", "image_prefer_wide_gamut_setting_description": "Utiliser Display P3 pour les miniatures. Cela préserve mieux la vivacité des images avec des espaces colorimétriques étendus, mais les images peuvent apparaître différemment sur les anciens appareils avec une ancienne version du navigateur. Conserver les images sRGB en sRGB pour éviter les décalages de couleur.", "image_preview_description": "Image de taille moyenne avec métadonnées retirées, utilisée lors de la visualisation d'un seul média et pour l'apprentissage automatique", - "image_preview_format": "Format des aperçus", "image_preview_quality_description": "Qualité de l'aperçu : de 1 à 100. Une valeur plus élevée produit de meilleurs résultats, mais elle produit des fichiers plus volumineux et peut réduire la réactivité de l'application. Une valeur trop basse peut affecter la qualité de l'apprentissage automatique.", - "image_preview_resolution": "Résolution des aperçus", - "image_preview_resolution_description": "Utilisé lors de l'affichage d'une seule photo et pour l'apprentissage automatique. Des résolutions plus élevées peuvent préserver plus de détails mais prennent plus de temps à encoder, ont des tailles de fichiers plus importantes et peuvent réduire la réactivité de l'application.", "image_preview_title": "Paramètres de prévisualisation", "image_quality": "Qualité", - "image_quality_description": "Qualité d'image de 1 à 100. Une valeur plus élevée offre une meilleure qualité mais produit des fichiers plus volumineux. Cette option affecte les images d'aperçu et de miniature.", "image_resolution": "Résolution", "image_resolution_description": "Les résolutions plus élevées permettent de préserver davantage de détails, mais l'encodage est plus long, les fichiers sont plus volumineux et la réactivité de l'application peut s'en trouver réduite.", "image_settings": "Paramètres d'image", "image_settings_description": "Gestion de la qualité et résolution des images générées", "image_thumbnail_description": "Petite vignette avec métadonnées retirées, utilisée lors de la visualisation de groupes de photos comme sur la vue chronologique principale", - "image_thumbnail_format": "Format des miniatures", "image_thumbnail_quality_description": "Qualité des vignettes : de 1 à 100. Une valeur élevée produit de meilleurs résultats, mais elle produit des fichiers plus volumineux et peut réduire la réactivité de l'application.", - "image_thumbnail_resolution": "Résolution des miniatures", - "image_thumbnail_resolution_description": "Utilisée lors du visionnage de groupes de photos (vue chronologique principale, albums, etc.). Une résolution plus élevée préserve davantage de détails, mais est plus longue à encoder, produit des fichiers plus lourds, et peut réduire la réactivité de l'application.", "image_thumbnail_title": "Paramètres des vignettes", "job_concurrency": "{job} : nombre de tâches simultanées", "job_created": "Tâche créée", @@ -89,11 +89,8 @@ "jobs_delayed": "{jobCount, plural, other {# retardés}}", "jobs_failed": "{jobCount, plural, other {# en échec}}", "library_created": "Bibliothèque créée : {library}", - "library_cron_expression": "Expression Cron", - "library_cron_expression_description": "Réglez l'intervalle d'analyse en utilisant le format cron. Pour plus d'informations, veuillez consulter par exemple Crontab Guru", - "library_cron_expression_presets": "Préréglages d'expressions Cron", "library_deleted": "Bibliothèque supprimée", - "library_import_path_description": "Spécifier un dossier à importer. Ce dossier, y compris les sous-dossiers, sera analysé à la recherche d'images et de vidéos.", + "library_import_path_description": "Spécifier un dossier à importer. Ce dossier, y compris ses sous-dossiers, sera analysé à la recherche d'images et de vidéos.", "library_scanning": "Analyse périodique", "library_scanning_description": "Configurer l'analyse périodique de la bibliothèque", "library_scanning_enable_description": "Activer l'analyse périodique de la bibliothèque", @@ -134,7 +131,7 @@ "machine_learning_smart_search_description": "Rechercher des images de manière sémantique en utilisant les intégrations CLIP", "machine_learning_smart_search_enabled": "Activer la recherche intelligente", "machine_learning_smart_search_enabled_description": "Si cette option est désactivée, les images ne seront pas encodées pour la recherche intelligente.", - "machine_learning_url_description": "URL du serveur d'apprentissage automatique", + "machine_learning_url_description": "L’URL du serveur d'apprentissage automatique. Si plusieurs URL sont fournies, chaque serveur sera essayé un par un jusqu’à ce que l’un d’eux réponde avec succès, dans l’ordre de la première à la dernière.", "manage_concurrency": "Gérer du multitâche", "manage_log_settings": "Gérer les paramètres de journalisation", "map_dark_style": "Thème sombre", @@ -193,7 +190,7 @@ "oauth_mobile_redirect_uri_override_description": "Activer quand le fournisseur d'OAuth ne permet pas un URI mobile, comme '{callback} '", "oauth_profile_signing_algorithm": "Algorithme de signature de profil", "oauth_profile_signing_algorithm_description": "Algorithme utilisé pour signer le profil utilisateur.", - "oauth_scope": "Portée", + "oauth_scope": "Périmètre", "oauth_settings": "OAuth", "oauth_settings_description": "Gérer les paramètres de connexion OAuth", "oauth_settings_more_details": "Pour plus de détails sur cette fonctionnalité, consultez ce lien.", @@ -215,7 +212,6 @@ "refreshing_all_libraries": "Actualisation de toutes les bibliothèques", "registration": "Enregistrement de l'administrateur", "registration_description": "Puisque vous êtes le premier utilisateur sur le système, vous serez désigné en tant qu'administrateur et responsable des tâches administratives, et vous pourrez alors créer d'autres utilisateurs.", - "removing_deleted_files": "Suppression des fichiers hors ligne", "repair_all": "Réparer tout", "repair_matched_items": "{count, plural, one {# Élément correspondant} other {# Éléments correspondants}}", "repaired_items": "{count, plural, one {# Élément corrigé} other {# Éléments corrigés}}", @@ -223,12 +219,12 @@ "reset_settings_to_default": "Réinitialiser les paramètres par défaut", "reset_settings_to_recent_saved": "Paramètres réinitialisés avec les derniers paramètres enregistrés", "scanning_library": "Analyse de la bibliothèque", - "scanning_library_for_changed_files": "Recherche de fichiers modifiés dans la bibliothèque", - "scanning_library_for_new_files": "Recherche de nouveaux fichiers dans la bibliothèque", "search_jobs": "Recherche des tâches ...", "send_welcome_email": "Envoyer un courriel de bienvenue", "server_external_domain_settings": "Domaine externe", "server_external_domain_settings_description": "Nom de domaine pour les liens partagés publics, y compris http(s)://", + "server_public_users": "Utilisateurs publics", + "server_public_users_description": "Tous les utilisateurs (nom et courriel) sont listés lors de l'ajout d'un utilisateur à des albums partagés. Quand cela est désactivé, la liste des utilisateurs est uniquement disponible pour les comptes administrateurs.", "server_settings": "Paramètres du serveur", "server_settings_description": "Gérer les paramètres du serveur", "server_welcome_message": "Message de bienvenue", @@ -254,14 +250,23 @@ "storage_template_user_label": "{label} est l'étiquette de stockage de l'utilisateur", "system_settings": "Paramètres du système", "tag_cleanup_job": "Nettoyage des étiquettes", + "template_email_available_tags": "Vous pouvez utiliser les variables suivantes dans votre modèle : {tags}", + "template_email_if_empty": "Si le modèle est vide, l’e-mail par défaut sera utilisé.", + "template_email_invite_album": "Modèle d'invitation à un album", + "template_email_preview": "Prévisualiser", + "template_email_settings": "Modèles de courriel", + "template_email_settings_description": "Gérer les modèles de notifications par courriel personnalisés", + "template_email_update_album": "Mettre à jour le modèle d’album", + "template_email_welcome": "Modèle de courriel de bienvenue", + "template_settings": "Modèles de notifications", + "template_settings_description": "Gérer les modèles personnalisés pour les notifications.", "theme_custom_css_settings": "CSS personnalisé", "theme_custom_css_settings_description": "Les feuilles de style en cascade (CSS) permettent de personnaliser l'apparence d'Immich.", "theme_settings": "Paramètres du thème", "theme_settings_description": "Gérer la personnalisation de l'interface web d'Immich", - "these_files_matched_by_checksum": "Ces fichiers correspondent par leur somme de contrôle", + "these_files_matched_by_checksum": "Ces fichiers sont identiques d'après leur somme de contrôle", "thumbnail_generation_job": "Génération des miniatures", "thumbnail_generation_job_description": "Génération des miniatures pour chaque média ainsi que pour les visages détectés", - "transcode_policy_description": "", "transcoding_acceleration_api": "API d'accélération", "transcoding_acceleration_api_description": "Il s'agit de l'API qui interagira avec votre appareil pour accélérer le transcodage. Ce paramètre fait au mieux : il basculera vers le transcodage logiciel en cas d'échec. Le codec vidéo VP9 peut fonctionner ou non selon votre matériel.", "transcoding_acceleration_nvenc": "NVENC (nécessite un GPU NVIDIA)", @@ -270,7 +275,7 @@ "transcoding_acceleration_vaapi": "VAAPI", "transcoding_accepted_audio_codecs": "Codecs audio acceptés", "transcoding_accepted_audio_codecs_description": "Sélectionnez les codecs audio qui n'ont pas besoin d'être transcodés. Utilisé uniquement pour certaines politiques de transcodage.", - "transcoding_accepted_containers": "Containers acceptés", + "transcoding_accepted_containers": "Conteneurs acceptés", "transcoding_accepted_containers_description": "Sélectionnez les formats de conteneurs qui n'ont pas besoin d'être remuxés en MP4. Utilisé uniquement pour certaines politiques de transcodage.", "transcoding_accepted_video_codecs": "Codecs vidéo acceptés", "transcoding_accepted_video_codecs_description": "Sélectionnez les codecs vidéo qui n'ont pas besoin d'être transcodés. Utilisé uniquement pour certaines politiques de transcodage.", @@ -307,14 +312,12 @@ "transcoding_settings_description": "Gérer les informations de résolution et d'encodage des fichiers vidéo", "transcoding_target_resolution": "Résolution cible", "transcoding_target_resolution_description": "Des résolutions plus élevées peuvent préserver plus de détails, mais prennent plus de temps à encoder, ont de plus grandes tailles de fichiers, et peuvent réduire la réactivité de l'application.", - "transcoding_temporal_aq": "AQ temporelle", + "transcoding_temporal_aq": "Quantification adaptative temporelle (temporal AQ)", "transcoding_temporal_aq_description": "S'applique uniquement à NVENC. Améliore la qualité des scènes riches en détails et à faible mouvement. Peut ne pas être compatible avec les anciens appareils.", "transcoding_threads": "Processus", "transcoding_threads_description": "Une valeur plus élevée entraîne un encodage plus rapide, mais laisse moins de place au serveur pour traiter d'autres tâches pendant son activité. Cette valeur ne doit pas être supérieure au nombre de cœurs de CPU. Une valeur égale à 0 maximise l'utilisation.", "transcoding_tone_mapping": "Mappage tonal", "transcoding_tone_mapping_description": "Tente de préserver l'apparence des vidéos HDR lorsqu'elles sont converties en SDR. Chaque algorithme effectue différents compromis pour la couleur, les détails et la luminosité. Hable préserve les détails, Mobius préserve la couleur, et Reinhard préserve la luminosité.", - "transcoding_tone_mapping_npl": "Mappage tonal NPL", - "transcoding_tone_mapping_npl_description": "Les couleurs seront ajustées pour paraître normales sur un écran de cette luminosité. De manière contre-intuitive, des valeurs plus basses augmentent la luminosité de la vidéo et vice versa, car cela compense la luminosité de l'écran. 0 configure cette valeur automatiquement.", "transcoding_transcode_policy": "Politique de transcodage", "transcoding_transcode_policy_description": "Politique indiquant quand une vidéo doit être transcodée. Les vidéos HDR seront toujours transcodées (sauf si le transcodage est désactivé).", "transcoding_two_pass_encoding": "Encodage en deux passes", @@ -395,7 +398,6 @@ "archive_or_unarchive_photo": "Archiver ou désarchiver une photo", "archive_size": "Taille de l'archive", "archive_size_description": "Configurer la taille de l'archive maximale pour les téléchargements (en Go)", - "archived": "Archivé", "archived_count": "{count, plural, one {# archivé} other {# archivés}}", "are_these_the_same_person": "Est-ce la même personne ?", "are_you_sure_to_do_this": "Êtes-vous sûr de vouloir faire ceci ?", @@ -403,7 +405,7 @@ "asset_adding_to_album": "Ajout à l'album...", "asset_description_updated": "La description du média a été mise à jour", "asset_filename_is_offline": "Le média {filename} est hors ligne", - "asset_has_unassigned_faces": "Le média a des visages non assignés", + "asset_has_unassigned_faces": "Le média a des visages non attribués", "asset_hashing": "Hachage...", "asset_offline": "Média hors ligne", "asset_offline_description": "Ce média externe n'est plus accessible sur le disque. Veuillez contacter votre administrateur Immich pour obtenir de l'aide.", @@ -416,7 +418,6 @@ "assets_added_to_album_count": "{count, plural, one {# média ajouté} other {# médias ajoutés}} à l'album", "assets_added_to_name_count": "{count, plural, one {# média ajouté} other {# médias ajoutés}} à {hasName, select, true {{name}} other {new album}}", "assets_count": "{count, plural, one {# média} other {# médias}}", - "assets_moved_to_trash": "{count, plural, one {# média déplacé} other {# médias déplacés}} vers la corbeille", "assets_moved_to_trash_count": "{count, plural, one {# média déplacé} other {# médias déplacés}} dans la corbeille", "assets_permanently_deleted_count": "{count, plural, one {# média supprimé} other {# médias supprimés}} définitivement", "assets_removed_count": "{count, plural, one {# média supprimé} other {# médias supprimés}}", @@ -446,10 +447,6 @@ "cannot_merge_people": "Impossible de fusionner les personnes", "cannot_undo_this_action": "Vous ne pouvez pas annuler cette action !", "cannot_update_the_description": "Impossible de mettre à jour la description", - "cant_apply_changes": "Impossible d'enregistrer les changements", - "cant_get_faces": "Aucun visage détecté", - "cant_search_people": "Impossible de rechercher des personnes", - "cant_search_places": "Impossible de rechercher des lieux", "change_date": "Changer la date", "change_expiration_time": "Modifier le délai d'expiration", "change_location": "Changer la localisation", @@ -481,6 +478,7 @@ "confirm": "Confirmer", "confirm_admin_password": "Confirmer le mot de passe Admin", "confirm_delete_shared_link": "Voulez-vous vraiment supprimer ce lien partagé ?", + "confirm_keep_this_delete_others": "Tous les autres médias dans la pile seront supprimés sauf celui-ci. Êtes-vous sûr de vouloir continuer ?", "confirm_password": "Confirmer le mot de passe", "contain": "Contenu", "context": "Contexte", @@ -530,6 +528,7 @@ "delete_key": "Supprimer la clé", "delete_library": "Supprimer la bibliothèque", "delete_link": "Supprimer le lien", + "delete_others": "Supprimer les autres", "delete_shared_link": "Supprimer le lien partagé", "delete_tag": "Supprimer l'étiquette", "delete_tag_confirmation_prompt": "Êtes-vous sûr de vouloir supprimer l'étiquette {tagName} ?", @@ -548,12 +547,12 @@ "display_options": "Afficher les options", "display_order": "Ordre d'affichage", "display_original_photos": "Afficher les photos originales", - "display_original_photos_setting_description": "Préférer afficher la photo originale lors de la visualisation d'un média plutôt que sa miniature lorsque cela est possible. Cela peut entraîner des vitesses d'affichage plus lentes.", + "display_original_photos_setting_description": "Afficher de préférence la photo originale lors de la visualisation d'un média plutôt que sa miniature lorsque cela est possible. Cela peut entraîner des vitesses d'affichage plus lentes.", "do_not_show_again": "Ne plus afficher ce message", "documentation": "Documentation", "done": "Terminé", "download": "Télécharger", - "download_include_embedded_motion_videos": "Vidéos embarquées", + "download_include_embedded_motion_videos": "Vidéos intégrées", "download_include_embedded_motion_videos_description": "Inclure des vidéos intégrées dans les photos de mouvement comme un fichier séparé", "download_settings": "Télécharger", "download_settings_description": "Gérer les paramètres de téléchargement des médias", @@ -563,13 +562,6 @@ "duplicates": "Doublons", "duplicates_description": "Examiner chaque groupe et indiquer s'il y a des doublons", "duration": "Durée", - "durations": { - "days": "{days, plural, one {jour} other {{days, number} jours}}", - "hours": "{hours, plural, one{une heure} other {{hours, number} heures}}", - "minutes": "{minutes, plural, one {minute} other {{minutes, number} minutes}}", - "months": "{months, plural, one {mois} other {{months, number} mois}}", - "years": "{years, plural, one {an} other {{years, number} ans}}" - }, "edit": "Modifier", "edit_album": "Modifier l'album", "edit_avatar": "Modifier l'avatar", @@ -585,7 +577,7 @@ "edit_name": "Modifier le nom", "edit_people": "Modifier les personnes", "edit_tag": "Modifier l'étiquette", - "edit_title": "Modifier le title", + "edit_title": "Modifier le titre", "edit_user": "Modifier l'utilisateur", "edited": "Modifié", "editor": "Editeur", @@ -594,8 +586,6 @@ "editor_crop_tool_h2_aspect_ratios": "Rapports hauteur/largeur", "editor_crop_tool_h2_rotation": "Rotation", "email": "Courriel", - "empty": "", - "empty_album": "Album vide", "empty_trash": "Vider la corbeille", "empty_trash_confirmation": "Êtes-vous sûr de vouloir vider la corbeille ? Cela supprimera définitivement de Immich tous les médias qu'elle contient.\nVous ne pouvez pas annuler cette action !", "enable": "Active", @@ -610,15 +600,15 @@ "cant_apply_changes": "Impossible d'appliquer les changements", "cant_change_activity": "Impossible {enabled, select, true {d'interdire} other {d'autoriser}} l'activité", "cant_change_asset_favorite": "Impossible de changer le favori du média", - "cant_change_metadata_assets_count": "Impossible de modifier les métadonnées de {count, plural, one {# média} other {# médias}}", - "cant_get_faces": "Impossible d'obtenir de visages", + "cant_change_metadata_assets_count": "Impossible de modifier les métadonnées {count, plural, one {d'un média} other {de # médias}}", + "cant_get_faces": "Impossible d'obtenir des visages", "cant_get_number_of_comments": "Impossible d'obtenir le nombre de commentaires", "cant_search_people": "Impossible de rechercher des personnes", "cant_search_places": "Impossible de rechercher des lieux", "cleared_jobs": "Tâches supprimées pour : {job}", "error_adding_assets_to_album": "Erreur lors de l'ajout des médias à l'album", "error_adding_users_to_album": "Erreur lors de l'ajout d'utilisateurs à l'album", - "error_deleting_shared_user": "Erreur lors de la suppression l'utilisateur partagé", + "error_deleting_shared_user": "Erreur lors de la suppression de l'utilisateur partagé", "error_downloading": "Erreur lors du téléchargement de {filename}", "error_hiding_buy_button": "Impossible de masquer le bouton d'achat", "error_removing_assets_from_album": "Erreur lors de la suppression des médias de l'album, vérifier la console pour plus de détails", @@ -629,6 +619,7 @@ "failed_to_create_shared_link": "Impossible de créer le lien partagé", "failed_to_edit_shared_link": "Impossible de modifier le lien partagé", "failed_to_get_people": "Impossible d'obtenir les personnes", + "failed_to_keep_this_delete_others": "Impossible de conserver ce média et de supprimer les autres médias", "failed_to_load_asset": "Impossible de charger le média", "failed_to_load_assets": "Impossible de charger les médias", "failed_to_load_people": "Impossible de charger les personnes", @@ -656,29 +647,27 @@ "unable_to_change_location": "Impossible de changer la localisation", "unable_to_change_password": "Impossible de changer le mot de passe", "unable_to_change_visibility": "Impossible de changer la visibilité pour {count, plural, one {# personne} other {# personnes}}", - "unable_to_check_item": "", - "unable_to_check_items": "", "unable_to_complete_oauth_login": "Impossible de terminer la connexion OAuth", "unable_to_connect": "Impossible de se connecter", "unable_to_connect_to_server": "Impossible de se connecter au serveur", "unable_to_copy_to_clipboard": "Impossible de copier dans le presse-papiers, assurez-vous que vous accédez à la page via https", "unable_to_create_admin_account": "Impossible de créer le compte administrateur", "unable_to_create_api_key": "Impossible de créer une nouvelle clé API", - "unable_to_create_library": "Création de bibliothèque impossible", - "unable_to_create_user": "Création de l'utilisateur impossible", - "unable_to_delete_album": "Suppression de l'album impossible", - "unable_to_delete_asset": "Suppression du média impossible", + "unable_to_create_library": "Impossible de créer la bibliothèque", + "unable_to_create_user": "Impossible de créer l'utilisateur", + "unable_to_delete_album": "Impossible de supprimer l'album", + "unable_to_delete_asset": "Impossible de supprimer le média", "unable_to_delete_assets": "Erreur lors de la suppression des médias", - "unable_to_delete_exclusion_pattern": "Suppression du modèle d'exclusion impossible", - "unable_to_delete_import_path": "Suppression du chemin d'importation impossible", - "unable_to_delete_shared_link": "Suppression du lien de partage impossible", - "unable_to_delete_user": "Suppression de l'utilisateur impossible", + "unable_to_delete_exclusion_pattern": "Impossible de supprimer le modèle d'exclusion", + "unable_to_delete_import_path": "Impossible de supprimer le chemin d'importation", + "unable_to_delete_shared_link": "Impossible de supprimer le lien de partage", + "unable_to_delete_user": "Impossible de supprimer l'utilisateur", "unable_to_download_files": "Impossible de télécharger les fichiers", - "unable_to_edit_exclusion_pattern": "Modification du modèle d'exclusion impossible", - "unable_to_edit_import_path": "Modification du chemin d'importation impossible", + "unable_to_edit_exclusion_pattern": "Impossible de modifier le modèle d'exclusion", + "unable_to_edit_import_path": "Impossible de modifier le chemin d'importation", "unable_to_empty_trash": "Impossible de vider la corbeille", "unable_to_enter_fullscreen": "Mode plein écran indisponible", - "unable_to_exit_fullscreen": "Sortie du mode plein écran impossible", + "unable_to_exit_fullscreen": "Impossible de sortir du mode plein écran", "unable_to_get_comments_number": "Impossible d'obtenir le nombre de commentaires", "unable_to_get_shared_link": "Échec de la récupération du lien partagé", "unable_to_hide_person": "Impossible de cacher la personne", @@ -692,18 +681,16 @@ "unable_to_log_out_device": "Impossible de déconnecter l'appareil", "unable_to_login_with_oauth": "Impossible de se connecter avec OAuth", "unable_to_play_video": "Impossible de jouer la vidéo", - "unable_to_reassign_assets_existing_person": "Incapable de réaffecter des médias à {name, select, null {une personne existante} other {{name}}}", - "unable_to_reassign_assets_new_person": "Impossible de réaffecter les médias à une nouvelle personne", + "unable_to_reassign_assets_existing_person": "Impossible de réattribuer les médias à {name, select, null {une personne existante} other {{name}}}", + "unable_to_reassign_assets_new_person": "Impossible de réattribuer les médias à une nouvelle personne", "unable_to_refresh_user": "Impossible d'actualiser l'utilisateur", "unable_to_remove_album_users": "Impossible de supprimer les utilisateurs de l'album", "unable_to_remove_api_key": "Impossible de supprimer la clé API", "unable_to_remove_assets_from_shared_link": "Impossible de supprimer des médias du lien partagé", - "unable_to_remove_comment": "", "unable_to_remove_deleted_assets": "Impossible de supprimer les fichiers hors ligne", "unable_to_remove_library": "Impossible de supprimer la bibliothèque", "unable_to_remove_partner": "Impossible de supprimer le partenaire", "unable_to_remove_reaction": "Impossible de supprimer la réaction", - "unable_to_remove_user": "", "unable_to_repair_items": "Impossible de réparer les éléments", "unable_to_reset_password": "Impossible de réinitialiser le mot de passe", "unable_to_resolve_duplicate": "Impossible de résoudre le doublon", @@ -714,7 +701,7 @@ "unable_to_save_api_key": "Impossible de sauvegarder la clé API", "unable_to_save_date_of_birth": "Impossible de sauvegarder la date de naissance", "unable_to_save_name": "Impossible de sauvegarder le nom", - "unable_to_save_profile": "Impossible de sauvegarder le profile", + "unable_to_save_profile": "Impossible de sauvegarder le profil", "unable_to_save_settings": "Impossible d'enregistrer les préférences", "unable_to_scan_libraries": "Impossible de scanner les bibliothèques", "unable_to_scan_library": "Impossible de scanner la bibliothèque", @@ -733,10 +720,6 @@ "unable_to_update_user": "Impossible de mettre à jour l'utilisateur", "unable_to_upload_file": "Impossible d'envoyer le fichier" }, - "every_day_at_onepm": "", - "every_night_at_midnight": "", - "every_night_at_twoam": "", - "every_six_hours": "", "exif": "Exif", "exit_slideshow": "Quitter le diaporama", "expand_all": "Tout développer", @@ -749,35 +732,30 @@ "export_as_json": "Exporter en JSON", "extension": "Extension", "external": "Externe", - "external_libraries": "Bibliothèques ext.", + "external_libraries": "Bibliothèques externes", "face_unassigned": "Non attribué", - "failed_to_get_people": "Impossible d'obtenir les personnes", + "failed_to_load_assets": "Échec du chargement des ressources", "favorite": "Favori", "favorite_or_unfavorite_photo": "Ajouter ou supprimer des favoris", "favorites": "Favoris", - "feature": "", "feature_photo_updated": "Photo de la personne mise à jour", - "featurecollection": "", "features": "Fonctionnalités", "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", "filename": "Nom du fichier", - "files": "", "filetype": "Type de fichier", "filter_people": "Filtrer les personnes", "find_them_fast": "Pour les retrouver rapidement par leur nom", "fix_incorrect_match": "Corriger une association incorrecte", "folders": "Dossiers", "folders_feature_description": "Parcourir l'affichage par dossiers pour les photos et les vidéos sur le système de fichiers", - "force_re-scan_library_files": "Forcer la réactualisation de tous les fichiers de la bibliothèque", "forward": "Avant", "general": "Général", "get_help": "Obtenir de l'aide", "getting_started": "Commencer", "go_back": "Retour", "go_to_search": "Faire une recherche", - "go_to_share_page": "Aller sur la page des Partages", "group_albums_by": "Grouper les albums par...", "group_no": "Pas de groupe", "group_owner": "Groupe par propriétaire", @@ -803,10 +781,6 @@ "image_alt_text_date_place_2_people": "{isVideo, select, true {Video} other {Image}} prise à {city}, {country} avec {person1} et {person2} le {date}", "image_alt_text_date_place_3_people": "{isVideo, select, true {Video} other {Image}} prise à {city}, {country} avec {person1}, {person2}, et {person3} le {date}", "image_alt_text_date_place_4_or_more_people": "{isVideo, select, true {Video} other {Image}} prise à {city}, {country} avec {person1}, {person2} et {additionalCount, number} autres personnes le {date}", - "image_alt_text_people": "{count, plural, =1 {with {person1}} =2 {with {person1} and {person2}} =3 {with {person1}, {person2}, and {person3}} other {with {person1}, {person2}, and {others, number} others}}", - "image_alt_text_place": "à {city}, {country}", - "image_taken": "{isVideo, select, true {Video prise} other {Image prise}}", - "img": "", "immich_logo": "Logo Immich", "immich_web_interface": "Interface Web Immich", "import_from_json": "Importer depuis un fichier JSON", @@ -827,10 +801,11 @@ "invite_people": "Inviter une personne", "invite_to_album": "Inviter à l'album", "items_count": "{count, plural, one {# élément} other {# éléments}}", - "job_settings_description": "", "jobs": "Tâches", "keep": "Conserver", "keep_all": "Les conserver tous", + "keep_this_delete_others": "Conserver celui-ci, supprimer les autres", + "kept_this_deleted_others": "Ce média a été conservé, et {count, plural, one {un autre a été supprimé} other {# autres ont été supprimés}}", "keyboard_shortcuts": "Raccourcis clavier", "language": "Langue", "language_setting_description": "Sélectionnez votre langue préférée", @@ -842,31 +817,6 @@ "level": "Niveau", "library": "Bibliothèque", "library_options": "Options de bibliothèque", - "license_account_info": "Ton compte a une licence", - "license_activated_subtitle": "Merci de soutenir Immich ainsi que les logiciels open source", - "license_activated_title": "Votre licence a été activée avec succès", - "license_button_activate": "Activer", - "license_button_buy": "Acheter", - "license_button_buy_license": "Acheter une licence", - "license_button_select": "Sélectionner", - "license_failed_activation": "Echec lors de l'activation de la licence. Merci de vérifier la clef reçu par mail !", - "license_individual_description_1": "1 licence par utilisateur sur n'importe quel serveur", - "license_individual_title": "Licence individuelle", - "license_info_licensed": "Licence active", - "license_info_unlicensed": "Sans licence", - "license_input_suggestion": "Vous avez une licence ? Renseignez la clef ci-dessous", - "license_license_subtitle": "Acheter une licence pour soutenir Immich", - "license_license_title": "LICENCE", - "license_lifetime_description": "Licence à vie", - "license_per_server": "Par serveur", - "license_per_user": "Par utilisateur", - "license_server_description_1": "1 licence par serveur", - "license_server_description_2": "Licence pour tous les utilisateurs du serveur", - "license_server_title": "Licence serveur", - "license_trial_info_1": "Vous utilisez une version Sans Licence de Immich", - "license_trial_info_2": "Vous utilisez Immich depuis approximativement", - "license_trial_info_3": "{accountAge, plural, one {# jour} other {# jours}}", - "license_trial_info_4": "Pensez à acheter une licence pour soutenir le développement du service", "light": "Clair", "like_deleted": "Réaction « j'aime » supprimée", "link_motion_video": "Lier la photo animée", @@ -905,7 +855,7 @@ "media_type": "Type de média", "memories": "Souvenirs", "memories_setting_description": "Gérer ce que vous voyez dans vos souvenirs", - "memory": "Mémoire", + "memory": "Souvenir", "memory_lane_title": "Fil de souvenirs {title}", "menu": "Menu", "merge": "Fusionner", @@ -971,7 +921,6 @@ "onboarding_welcome_user": "Bienvenue {user}", "online": "En ligne", "only_favorites": "Uniquement les favoris", - "only_refreshes_modified_files": "Actualise les fichiers modifiés uniquement", "open_in_map_view": "Montrer sur la carte", "open_in_openstreetmap": "Ouvrir dans OpenStreetMap", "open_the_search_filters": "Ouvrir les filtres de recherche", @@ -1009,14 +958,12 @@ "people_edits_count": "{count, plural, one {# personne éditée} other {# personnes éditées}}", "people_feature_description": "Parcourir les photos et vidéos groupées par personnes", "people_sidebar_description": "Afficher le menu Personnes dans la barre latérale", - "perform_library_tasks": "", "permanent_deletion_warning": "Avertissement avant suppression définitive", "permanent_deletion_warning_setting_description": "Afficher un avertissement avant la suppression définitive d'un média", "permanently_delete": "Supprimer définitivement", - "permanently_delete_assets_count": "Suppression définitive de {count, plural, one {média} other {médias}}", + "permanently_delete_assets_count": "Suppression définitive {count, plural, one {du média} other {des médias}}", "permanently_delete_assets_prompt": "Êtes-vous sûr de vouloir supprimer définitivement {count, plural, one {ce média ?} other {ces # médias ?}} Cela {count, plural, one {le} other {les}} supprimera aussi de {count, plural, one {son (ses)} other {leur(s)}} album(s).", "permanently_deleted_asset": "Média supprimé définitivement", - "permanently_deleted_assets": "{count, plural, one {# média supprimé} other {# médias supprimés}} définitivement", "permanently_deleted_assets_count": "{count, plural, one {# média définitivement supprimé} other {# médias définitivement supprimés}}", "person": "Personne", "person_hidden": "{name}{hidden, select, true { (caché)} other {}}", @@ -1032,7 +979,6 @@ "play_memories": "Lancer les souvenirs", "play_motion_photo": "Jouer la photo animée", "play_or_pause_video": "Jouer ou mettre en pause la vidéo", - "point": "", "port": "Port", "preset": "Préréglage", "preview": "Aperçu", @@ -1046,7 +992,7 @@ "public_album": "Album public", "public_share": "Partage public", "purchase_account_info": "Contributeur", - "purchase_activated_subtitle": "Merci d'avoir apporté votre soutien à Immich et les logiciels open source", + "purchase_activated_subtitle": "Merci d'avoir apporté votre soutien à Immich et aux logiciels open source", "purchase_activated_time": "Activé le {date, date}", "purchase_activated_title": "Votre clé a été activée avec succès", "purchase_button_activate": "Activer", @@ -1056,7 +1002,7 @@ "purchase_button_reminder": "Me le rappeler dans 30 jours", "purchase_button_remove_key": "Supprimer la clé", "purchase_button_select": "Sélectionner", - "purchase_failed_activation": "Erreur à l'activation. Veuillez vérifier votre e-mail pour obtenir la clé du produit correcte !", + "purchase_failed_activation": "Erreur à l'activation. Veuillez vérifier votre courriel pour obtenir la clé du produit correcte !", "purchase_individual_description_1": "Pour un utilisateur", "purchase_individual_description_2": "Statut de contributeur", "purchase_individual_title": "Utilisateur", @@ -1065,43 +1011,42 @@ "purchase_lifetime_description": "Achat à vie", "purchase_option_title": "OPTIONS D'ACHAT", "purchase_panel_info_1": "Développer Immich nécessite du temps et de l'énergie, et nous avons des ingénieurs qui travaillent à plein temps pour en faire le meilleur produit possible. Notre mission est de générer, pour les logiciels open source et les pratiques de travail éthique, une source de revenus suffisante pour les développeurs et de créer un écosystème respectueux de la vie privée grâce a des alternatives crédibles aux services cloud peu scrupuleux.", - "purchase_panel_info_2": "Étant donné que nous nous engageons à ne pas ajouter de murs de paiement, cet achat ne vous donnera pas de fonctionnalités supplémentaires dans Immich. Nous comptons sur des utilisateurs comme vous pour soutenir le développement continu d'Immich.", + "purchase_panel_info_2": "Étant donné que nous nous engageons à ne pas ajouter de fonctionnalités payantes, cet achat ne vous donnera pas de fonctionnalités supplémentaires dans Immich. Nous comptons sur des utilisateurs comme vous pour soutenir le développement continu d'Immich.", "purchase_panel_title": "Soutenir le projet", "purchase_per_server": "Par serveur", "purchase_per_user": "Par utilisateur", "purchase_remove_product_key": "Supprimer la clé du produit", "purchase_remove_product_key_prompt": "Êtes-vous sûr de vouloir supprimer la clé du produit ?", "purchase_remove_server_product_key": "Supprimer la clé du produit pour le Serveur", - "purchase_remove_server_product_key_prompt": "Êtes-vous sûr de vouloir supprimer la clé du produit pour le serveur ?", + "purchase_remove_server_product_key_prompt": "Êtes-vous sûr de vouloir supprimer la clé du produit pour le Serveur ?", "purchase_server_description_1": "Pour l'ensemble du serveur", "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", - "range": "", "rating": "Étoile d'évaluation", "rating_clear": "Effacer l'évaluation", "rating_count": "{count, plural, one {# étoile} other {# étoiles}}", "rating_description": "Afficher l'évaluation EXIF dans le panneau d'information", - "raw": "", "reaction_options": "Options de réaction", "read_changelog": "Lire les changements", - "reassign": "Réaffecter", - "reassigned_assets_to_existing_person": "{count, plural, one {# média réaffecté} other {# médias réaffectés}} à {name, select, null {une personne existante} other {{name}}}", - "reassigned_assets_to_new_person": "{count, plural, one {# média réassigné} other {# médias réassignés}} à une nouvelle personne", + "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", "reassing_hint": "Attribuer ces médias à une personne existante", "recent": "Récent", + "recent-albums": "Albums récents", "recent_searches": "Recherches récentes", "refresh": "Actualiser", "refresh_encoded_videos": "Actualiser les vidéos encodées", - "refresh_faces": "Mettre à jour les visages", + "refresh_faces": "Actualiser les visages", "refresh_metadata": "Actualiser les métadonnées", "refresh_thumbnails": "Actualiser les vignettes", "refreshed": "Actualisé", "refreshes_every_file": "Actualise tous les fichiers (existants et nouveaux)", "refreshing_encoded_video": "Actualisation de la vidéo encodée", - "refreshing_faces": "Actualiser les visages", + "refreshing_faces": "Actualisation des visages", "refreshing_metadata": "Actualisation des métadonnées", - "regenerating_thumbnails": "Régénération des vignettes", + "regenerating_thumbnails": "Regénération des vignettes", "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é ?", @@ -1111,6 +1056,7 @@ "remove_from_album": "Supprimer de l'album", "remove_from_favorites": "Supprimer des favoris", "remove_from_shared_link": "Supprimer des liens partagés", + "remove_url": "Supprimer l'URL", "remove_user": "Supprimer l'utilisateur", "removed_api_key": "Clé API supprimée : {name}", "removed_from_archive": "Supprimé de l'archive", @@ -1127,7 +1073,6 @@ "reset": "Réinitialiser", "reset_password": "Réinitialiser le mot de passe", "reset_people_visibility": "Réinitialiser la visibilité des personnes", - "reset_settings_to_default": "", "reset_to_default": "Rétablir les valeurs par défaut", "resolve_duplicates": "Résoudre les doublons", "resolved_all_duplicates": "Résolution de tous les doublons", @@ -1147,9 +1092,7 @@ "saved_settings": "Paramètres enregistrés", "say_something": "Réagir", "scan_all_libraries": "Analyser toutes les bibliothèques", - "scan_all_library_files": "Analyser tous les fichiers", "scan_library": "Analyser", - "scan_new_library_files": "Analyser les nouveaux fichiers", "scan_settings": "Paramètres d'analyse", "scanning_for_album": "Recherche d'albums en cours...", "search": "Recherche", @@ -1192,10 +1135,9 @@ "selected_count": "{count, plural, one {# sélectionné} other {# sélectionnés}}", "send_message": "Envoyer un message", "send_welcome_email": "Envoyer un courriel de bienvenue", - "server": "Serveur", "server_offline": "Serveur hors ligne", "server_online": "Serveur en ligne", - "server_stats": "Statistiques Serveur", + "server_stats": "Statistiques du serveur", "server_version": "Version du serveur", "set": "Définir", "set_as_album_cover": "Définir comme couverture d'album", @@ -1217,14 +1159,14 @@ "shared_with_partner": "Partagé avec {partner}", "sharing": "Partage", "sharing_enter_password": "Veuillez saisir le mot de passe pour visualiser cette page.", - "sharing_sidebar_description": "Afficher un lien vers Partage dans la barre latérale", + "sharing_sidebar_description": "Afficher un lien vers Partager dans la barre latérale", "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_people": "Montrer toutes les personnes", "show_and_hide_people": "Afficher / Masquer les personnes", "show_file_location": "Afficher l'emplacement du fichier", - "show_gallery": "Afficher la gallerie", + "show_gallery": "Afficher la galerie", "show_hidden_people": "Afficher les personnes masquées", "show_in_timeline": "Afficher dans la vue chronologique", "show_in_timeline_setting_description": "Afficher les photos et vidéos de cet utilisateur dans votre vue chronologique", @@ -1276,19 +1218,19 @@ "storage_usage": "{used} sur {available} utilisé", "submit": "Soumettre", "suggestions": "Suggestions", - "sunrise_on_the_beach": "Aurore sur la plage", + "sunrise_on_the_beach": "Lever de soleil sur la plage", "support": "Support", "support_and_feedback": "Support & Retours", "support_third_party_description": "Votre installation d'Immich est packagée via une application tierce. Si vous rencontrez des anomalies, elles peuvent venir de ce packaging tiers, merci de créer les anomalies avec ces tiers en premier lieu en utilisant les liens ci-dessous.", "swap_merge_direction": "Inverser la direction de fusion", "sync": "Synchroniser", - "tag": "Tag", - "tag_assets": "Taguer les médias", + "tag": "Étiquette", + "tag_assets": "Étiqueter les médias", "tag_created": "Étiquette créée : {tag}", "tag_feature_description": "Parcourir les photos et vidéos groupées par thèmes logiques", "tag_not_found_question": "Vous ne trouvez pas une étiquette ? Créer une nouvelle étiquette.", "tag_updated": "Étiquette mise à jour : {tag}", - "tagged_assets": "Tag ajouté à {count, plural, one {# média} other {# médias}}", + "tagged_assets": "Étiquette ajoutée à {count, plural, one {# média} other {# médias}}", "tags": "Étiquettes", "template": "Modèle", "theme": "Thème", @@ -1297,32 +1239,30 @@ "they_will_be_merged_together": "Elles seront fusionnées ensemble", "third_party_resources": "Ressources tierces", "time_based_memories": "Souvenirs basés sur la date", + "timeline": "Vue chronologique", "timezone": "Fuseau horaire", "to_archive": "Archiver", "to_change_password": "Modifier le mot de passe", "to_favorite": "Ajouter aux favoris", "to_login": "Se connecter", "to_parent": "Aller au dossier parent", - "to_root": "Vers la racine", "to_trash": "Corbeille", "toggle_settings": "Inverser les paramètres", "toggle_theme": "Inverser le thème sombre", - "toggle_visibility": "Modifier la visibilité", + "total": "Total", "total_usage": "Utilisation globale", "trash": "Corbeille", "trash_all": "Tout supprimer", "trash_count": "Corbeille {count, number}", - "trash_delete_asset": "Corbeille/Suppression d'un média", + "trash_delete_asset": "Mettre à la corbeille/Supprimer un média", "trash_no_results_message": "Les photos et vidéos supprimées s'afficheront ici.", "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}}.", "type": "Type", "unarchive": "Désarchiver", - "unarchived": "Non archivé", "unarchived_count": "{count, plural, one {# supprimé} other {# supprimés}} de l'archive", "unfavorite": "Enlever des favoris", "unhide_person": "Afficher la personne", "unknown": "Inconnu", - "unknown_album": "", "unknown_year": "Année inconnue", "unlimited": "Illimité", "unlink_motion_video": "Détacher la photo animée", @@ -1354,13 +1294,13 @@ "use_custom_date_range": "Utilisez une plage de date personnalisée à la place", "user": "Utilisateur", "user_id": "ID Utilisateur", - "user_license_settings": "Licence", - "user_license_settings_description": "Gérer votre licence", "user_liked": "{user} a aimé {type, select, photo {cette photo} video {cette vidéo} asset {ce média} other {ceci}}", "user_purchase_settings": "Achat", "user_purchase_settings_description": "Gérer votre achat", "user_role_set": "Définir {user} comme {role}", "user_usage_detail": "Détail de l'utilisation des utilisateurs", + "user_usage_stats": "Statistiques d'utilisation du compte", + "user_usage_stats_description": "Voir les statistiques d'utilisation du compte", "username": "Nom d'utilisateur", "users": "Utilisateurs", "utilities": "Utilitaires", @@ -1368,7 +1308,7 @@ "variables": "Variables", "version": "Version", "version_announcement_closing": "Ton ami, Alex", - "version_announcement_message": "Bonjour, il y a une nouvelle version de l'application. Prenez le temps de consulter les notes de version et assurez-vous que vos fichiers docker-compose.yml et .env sont à jour pour éviter toute erreur de configuration, surtout si vous utilisez WatchTower ou tout autre mécanisme qui gère la mise à jour de votre application automatiquement.", + "version_announcement_message": "Bonjour, il y a une nouvelle version de l'application. Prenez le temps de consulter les notes de version et assurez vous que votre installation est à jour pour éviter toute erreur de configuration, surtout si vous utilisez WatchTower ou tout autre mécanisme qui gère automatiquement la mise à jour de votre application.", "version_history": "Historique de version", "version_history_item": "Version {version} installée le {date}", "video": "Vidéo", @@ -1382,16 +1322,16 @@ "view_all_users": "Voir tous les utilisateurs", "view_in_timeline": "Voir dans la vue chronologique", "view_links": "Voir les liens", + "view_name": "Vue", "view_next_asset": "Voir le média suivant", "view_previous_asset": "Voir le média précédent", "view_stack": "Afficher la pile", - "viewer": "Vue", "visibility_changed": "Visibilité changée pour {count, plural, one {# personne} other {# personnes}}", "waiting": "En attente", "warning": "Attention", "week": "Semaine", "welcome": "Bienvenue", - "welcome_to_immich": "Bienvenue sur immich", + "welcome_to_immich": "Bienvenue sur Immich", "year": "Année", "years_ago": "Il y a {years, plural, one {# an} other {# ans}}", "yes": "Oui", diff --git a/i18n/he.json b/i18n/he.json index 7cb896f1f0b3f..71b6ab3c917df 100644 --- a/i18n/he.json +++ b/i18n/he.json @@ -23,6 +23,7 @@ "add_to": "הוסף ל..", "add_to_album": "הוסף לאלבום", "add_to_shared_album": "הוסף לאלבום משותף", + "add_url": "הוספת קישור", "added_to_archive": "נוסף לארכיון", "added_to_favorites": "נוסף למועדפים", "added_to_favorites_count": "{count, number} נוספו למועדפים", @@ -34,6 +35,11 @@ "authentication_settings_disable_all": "האם ברצונך להשבית את כל שיטות ההתחברות? כניסה למערכת תהיה מושבתת לחלוטין.", "authentication_settings_reenable": "כדי לאפשר מחדש, השתמש בפקודת שרת.", "background_task_job": "משימות רקע", + "backup_database": "גיבוי מסד נתונים", + "backup_database_enable_description": "אפשר גיבויי מסד נתונים", + "backup_keep_last_amount": "כמות של גיבויים קודמים שיש לשמור", + "backup_settings": "הגדרות גיבוי", + "backup_settings_description": "נהל הגדרות גיבוי מסד נתונים", "check_all": "סמן הכל", "cleared_jobs": "נוקו משימות עבור: {job}", "config_set_by_file": "התצורה מוגדרת כעת על ידי קובץ תצורה", @@ -43,9 +49,10 @@ "confirm_reprocess_all_faces": "האם את/ה בטוח/ה שברצונך לעבד מחדש את כל הפנים? זה גם ינקה אנשים בעלי שם.", "confirm_user_password_reset": "האם את/ה בטוח/ה שברצונך לאפס את הסיסמה של המשתמש {user}?", "create_job": "צור עבודה", - "crontab_guru": "Crontab Guru", + "cron_expression": "ביטוי cron", + "cron_expression_description": "הגדר את מרווח הסריקה באמצעות תבנית ה- cron. למידע נוסף נא לפנות למשל אל Crontab Guru", + "cron_expression_presets": "הגדרות קבועות מראש של ביטוי cron", "disable_login": "השבת כניסה", - "disabled": "מושבת", "duplicate_detection_job_description": "הפעל למידת מכונה על נכסים כדי לזהות תמונות דומות. נשען על חיפוש חכם", "exclusion_pattern_description": "דפוסי החרגה מאפשרים לך להתעלם מקבצים ומתיקיות בעת סריקת הספרייה שלך. זה שימושי אם יש לך תיקיות המכילות קבצים שאינך רוצה לייבא, כגון קובצי RAW.", "external_library_created_at": "ספרייה חיצונית (נוצרה ב-{date})", @@ -63,22 +70,15 @@ "image_prefer_wide_gamut": "העדף סולם צבעים רחב", "image_prefer_wide_gamut_setting_description": "השתמש ב-Display P3 לתמונות ממוזערות. זה משמר טוב יותר את החיוניות של תמונות עם מרחבי צבע רחבים, אבל תמונות עשויות להופיע אחרת במכשירים ישנים עם גרסת דפדפן ישנה. תמונות sRGB נשמרות כ-sRGB כדי למנוע שינויי צבע.", "image_preview_description": "תמונה בגודל בינוני עם מטא-נתונים שהוסרו, משמשת בעת צפייה בנכס בודד ועבור למידת מכונה", - "image_preview_format": "פורמט תצוגה מקדימה", "image_preview_quality_description": "איכות תצוגה מקדימה בין 1-100. גבוה יותר הוא טוב יותר, אבל מייצר קבצים גדולים יותר ויכול להפחית את תגובתיות היישום. הגדרת ערך נמוך עשויה להשפיע על איכות תוצאות של למידת מכונה.", - "image_preview_resolution": "רזולוציית תצוגה מקדימה", - "image_preview_resolution_description": "משמש בעת צפייה בתמונה בודדת ועבור למידת מכונה. רזולוציות גבוהות יותר יכולות לשמר פירוט רב יותר אך לוקחות יותר זמן לקידוד, יש להן גדלי קבצים גדולים יותר, ויכולות להפחית את תגובתיות היישום.", "image_preview_title": "הגדרות תצוגה מקדימה", "image_quality": "איכות", - "image_quality_description": "איכות תמונה מ-1 עד 100. ערך גבוה יותר עדיף לאיכות אך מייצר קבצים גדולים יותר, אפשרות זו משפיעה על התצוגה המקדימה ותמונות ממוזערות.", "image_resolution": "רזולוציה", "image_resolution_description": "רזולוציות גבוהות יותר יכולות לשמר פרטים רבים יותר אך לוקחות זמן רב יותר לקידוד, יש להן גדלי קבצים גדולים יותר ויכולות להפחית את תגובתיות היישום.", "image_settings": "הגדרות תמונה", "image_settings_description": "נהל את האיכות והרזולוציה של תמונות שנוצרו", "image_thumbnail_description": "תמונה ממוזערת קטנה עם מטא-נתונים שהוסרו, משמשת בעת צפייה בקבוצות של תמונות כמו ציר הזמן הראשי", - "image_thumbnail_format": "פורמט תמונה ממוזערת", "image_thumbnail_quality_description": "איכות תמונה ממוזערת בין 1-100. גבוה יותר הוא טוב יותר, אבל מייצר קבצים גדולים יותר ויכול להפחית את תגובתיות היישום.", - "image_thumbnail_resolution": "רזולוציית תמונה ממוזערת", - "image_thumbnail_resolution_description": "משמש בעת צפייה בקבוצות של תמונות (ציר זמן ראשי, תצוגת אלבום וכו'). רזולוציות גבוהות יותר יכולות לשמר פירוט רב יותר אך לוקחות יותר זמן לקידוד, יש להן גדלי קבצים גדולים יותר, ויכולות להפחית את תגובתיות היישום.", "image_thumbnail_title": "הגדרות תמונה ממוזערת", "job_concurrency": "בו-זמניות של {job}", "job_created": "עבודה נוצרה", @@ -89,9 +89,6 @@ "jobs_delayed": "{jobCount, plural, other {# עוכבו}}", "jobs_failed": "{jobCount, plural, other {# נכשלו}}", "library_created": "נוצרה ספרייה: {library}", - "library_cron_expression": "ביטוי cron", - "library_cron_expression_description": "הגדר את מרווח הסריקה באמצעות פורמט ה-cron. למידע נוסף אנא פנה למשל אל Crontab Guru", - "library_cron_expression_presets": "הגדרות ביטוי cron קבועות מראש", "library_deleted": "ספרייה נמחקה", "library_import_path_description": "ציין תיקיה לייבוא. תיקייה זו, כולל תיקיות משנה, תיסרק עבור תמונות וסרטונים.", "library_scanning": "סריקה תקופתית", @@ -134,7 +131,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": "עיצוב כהה", @@ -215,7 +212,6 @@ "refreshing_all_libraries": "מרענן את כל הספריות", "registration": "רישום מנהל מערכת", "registration_description": "מכיוון שאתה המשתמש הראשון במערכת, אתה תוקצה כמנהל ואתה אחראי על משימות ניהול, ומשתמשים נוספים ייווצרו על ידך.", - "removing_deleted_files": "הסרת קבצים לא מקוונים", "repair_all": "תקן הכל", "repair_matched_items": "{count, plural, one {פריט # תואם} other {# פריטים תואמים}}", "repaired_items": "{count, plural, one {פריט # תוקן} other {# פריטים תוקנו}}", @@ -223,12 +219,12 @@ "reset_settings_to_default": "אפס הגדרות לברירת המחדל", "reset_settings_to_recent_saved": "אפס הגדרות להגדרות שנשמרו לאחרונה", "scanning_library": "סורק ספרייה", - "scanning_library_for_changed_files": "סורק ספרייה לאיתור קבצים שהשתנו", - "scanning_library_for_new_files": "סורק ספרייה לאיתור קבצים חדשים", "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": "הודעת פתיחה", @@ -254,6 +250,16 @@ "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_settings_description": "נהל תבניות התראת דוא\"ל מותאמות אישית", + "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": "הגדרות ערכת נושא", @@ -261,7 +267,6 @@ "these_files_matched_by_checksum": "קבצים אלה תואמים לפי סיכומי הביקורת שלהם", "thumbnail_generation_job": "צור תמונות ממוזערות", "thumbnail_generation_job_description": "יוצר תמונות ממוזערות גדולות, קטנות ומטושטשות עבור כל נכס, כמו גם תמונות ממוזערות עבור כל אדם", - "transcode_policy_description": "", "transcoding_acceleration_api": "API האצה", "transcoding_acceleration_api_description": "ה-API שייצור אינטראקציה עם המכשיר שלך כדי להאיץ את המרת הקידוד. הגדרה זו היא 'המאמץ הטוב ביותר': היא תחזור לקידוד תוכנה במקרה של כשל. VP9 עשוי לעבוד או לא, תלוי בחומרה שלך.", "transcoding_acceleration_nvenc": "NVENC (דורש כרטיס מסך של NVIDIA)", @@ -313,8 +318,6 @@ "transcoding_threads_description": "ערכים גבוהים יותר מובילים לקידוד מהיר יותר, אך משאירים פחות מקום לשרת לעבד משימות אחרות בעודו פעיל. ערך זה לא אמור להיות יותר ממספר ליבות המעבד. ממקסם את הניצול אם מוגדר ל-0.", "transcoding_tone_mapping": "מיפוי גוונים", "transcoding_tone_mapping_description": "מנסה לשמר את המראה של סרטוני HDR כשהם מומרים ל-SDR. כל אלגוריתם עושה פשרות שונות עבור צבע, פירוט ובהירות. Hable משמר פרטים, Mobius משמר צבע, ו-Reinhard משמר בהירות.", - "transcoding_tone_mapping_npl": "בהירות שיא נומינלית למיפוי גוונים", - "transcoding_tone_mapping_npl_description": "הצבעים יותאמו כך שיראו נורמליים לתצוגה של בהירות זו. באופן מנוגד לאינטואיציה, ערכים נמוכים מגבירים את בהירות הווידאו ולהפך מכיוון שזה מפצה על בהירות התצוגה. 0 מגדיר ערך זה באופן אוטומטי.", "transcoding_transcode_policy": "מדיניות המרת קידוד", "transcoding_transcode_policy_description": "מדיניות לגבי מתי יש להמיר קידוד של סרטון. תמיד יומר הקידוד של סרטוני HDR (למעט אם המרת קידוד מושבתת).", "transcoding_two_pass_encoding": "קידוד בשני מעברים", @@ -395,7 +398,6 @@ "archive_or_unarchive_photo": "העבר תמונה לארכיון או הוצא אותה משם", "archive_size": "גודל הארכיון", "archive_size_description": "הגדר את גודל הארכיון להורדות (ב-GiB)", - "archived": "בארכיון", "archived_count": "{count, plural, other {# הועברו לארכיון}}", "are_these_the_same_person": "האם אלה אותו האדם?", "are_you_sure_to_do_this": "האם את/ה בטוח/ה שברצונך לעשות את זה?", @@ -416,7 +418,6 @@ "assets_added_to_album_count": "{count, plural, one {נוסף נכס #} other {נוספו # נכסים}} לאלבום", "assets_added_to_name_count": "{count, plural, one {נכס # נוסף} other {# נכסים נוספו}} אל {hasName, select, true {{name}} other {אלבום חדש}}", "assets_count": "{count, plural, one {נכס #} other {# נכסים}}", - "assets_moved_to_trash": "Moved {count, plural, one {# asset} other {# assets}} to trash", "assets_moved_to_trash_count": "{count, plural, one {נכס # הועבר} other {# נכסים הועברו}} לאשפה", "assets_permanently_deleted_count": "{count, plural, one {נכס # נמחק} other {# נכסים נמחקו}} לצמיתות", "assets_removed_count": "{count, plural, one {נכס # הוסר} other {# נכסים הוסרו}}", @@ -446,10 +447,6 @@ "cannot_merge_people": "לא ניתן למזג אנשים", "cannot_undo_this_action": "את/ה לא יכול/ה לבטל את הפעולה הזו!", "cannot_update_the_description": "לא ניתן לעדכן את התיאור", - "cant_apply_changes": "לא ניתן להחיל שינויים", - "cant_get_faces": "לא ניתן לאחזר פרצופים", - "cant_search_people": "לא ניתן לחפש אנשים", - "cant_search_places": "לא ניתן לחפש מקומות", "change_date": "שנה תאריך", "change_expiration_time": "שנה את זמן התפוגה", "change_location": "שנה מיקום", @@ -481,6 +478,7 @@ "confirm": "אישור", "confirm_admin_password": "אשר סיסמת מנהל", "confirm_delete_shared_link": "האם את/ה בטוח/ה שברצונך למחוק את הקישור המשותף הזה?", + "confirm_keep_this_delete_others": "כל שאר הנכסים בערימה יימחקו למעט נכס זה. האם את/ה בטוח/ה שברצונך להמשיך?", "confirm_password": "אשר סיסמה", "contain": "מכיל", "context": "הקשר", @@ -530,6 +528,7 @@ "delete_key": "מחק מפתח", "delete_library": "מחק ספרייה", "delete_link": "מחק קישור", + "delete_others": "מחק אחרים", "delete_shared_link": "מחק קישור משותף", "delete_tag": "מחק תג", "delete_tag_confirmation_prompt": "האם את/ה בטוח/ה שברצונך למחוק תג {tagName}?", @@ -563,13 +562,6 @@ "duplicates": "כפילויות", "duplicates_description": "הפרד כל קבוצה על ידי ציון אילו, אם בכלל, הן כפילויות", "duration": "משך זמן", - "durations": { - "days": "{days, plural, one {day} other {{days, number} days}}", - "hours": "{hours, plural, one {hour} other {{hours, number} hours}}", - "minutes": "{minutes, plural, one {minute} other {{minutes, number} minutes}}", - "months": "{months, plural, one {month} other {{months, number} months}}", - "years": "{years, plural, one {year} other {{years, number} years}}" - }, "edit": "ערוך", "edit_album": "ערוך אלבום", "edit_avatar": "ערוך תמונת פרופיל", @@ -594,8 +586,6 @@ "editor_crop_tool_h2_aspect_ratios": "יחסי רוחב גובה", "editor_crop_tool_h2_rotation": "סיבוב", "email": "דוא\"ל", - "empty": "", - "empty_album": "אלבום ריק", "empty_trash": "רוקן אשפה", "empty_trash_confirmation": "האם את/ה בטוח/ה שברצונך לרוקן את האשפה? זה יסיר לצמיתות את כל הנכסים באשפה מImmich.\nאת/ה לא יכול/ה לבטל פעולה זו!", "enable": "אפשר", @@ -629,6 +619,7 @@ "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_people": "נכשל באחזור אנשים", @@ -656,8 +647,6 @@ "unable_to_change_location": "לא ניתן לשנות מיקום", "unable_to_change_password": "לא ניתן לשנות סיסמה", "unable_to_change_visibility": "לא ניתן לשנות את הנראות עבור {count, plural, one {אדם #} other {# אנשים}}", - "unable_to_check_item": "", - "unable_to_check_items": "", "unable_to_complete_oauth_login": "לא ניתן להשלים התחברות OAuth", "unable_to_connect": "לא ניתן להתחבר", "unable_to_connect_to_server": "לא ניתן להתחבר לשרת", @@ -698,12 +687,10 @@ "unable_to_remove_album_users": "לא ניתן להסיר משתמשים מהאלבום", "unable_to_remove_api_key": "לא ניתן להסיר מפתח API", "unable_to_remove_assets_from_shared_link": "לא ניתן להסיר נכסים מקישור משותף", - "unable_to_remove_comment": "", "unable_to_remove_deleted_assets": "לא ניתן להסיר קבצים לא מקוונים", "unable_to_remove_library": "לא ניתן להסיר ספרייה", "unable_to_remove_partner": "לא ניתן להסיר שותף", "unable_to_remove_reaction": "לא ניתן להסיר תגובה", - "unable_to_remove_user": "", "unable_to_repair_items": "לא ניתן לתקן פריטים", "unable_to_reset_password": "לא ניתן לאפס סיסמה", "unable_to_resolve_duplicate": "לא ניתן לפתור כפילות", @@ -733,10 +720,6 @@ "unable_to_update_user": "לא ניתן לעדכן משתמש", "unable_to_upload_file": "לא ניתן להעלות קובץ" }, - "every_day_at_onepm": "", - "every_night_at_midnight": "", - "every_night_at_twoam": "", - "every_six_hours": "", "exif": "Exif", "exit_slideshow": "צא ממצגת שקופיות", "expand_all": "הרחב הכל", @@ -751,33 +734,28 @@ "external": "חיצוני", "external_libraries": "ספריות חיצוניות", "face_unassigned": "לא מוקצה", - "failed_to_get_people": "נכשל באחזור אנשים", + "failed_to_load_assets": "טעינת נכסים נכשלה", "favorite": "מועדף", "favorite_or_unfavorite_photo": "הוסף או הסר תמונה מהמועדפים", "favorites": "מועדפים", - "feature": "", "feature_photo_updated": "תמונה מייצגת עודכנה", - "featurecollection": "", "features": "תכונות", "features_setting_description": "נהל את תכונות היישום", "file_name": "שם הקובץ", "file_name_or_extension": "שם קובץ או סיומת", "filename": "שם קובץ", - "files": "", "filetype": "סוג קובץ", "filter_people": "סנן אנשים", "find_them_fast": "מצא אותם מהר לפי שם עם חיפוש", "fix_incorrect_match": "תקן התאמה שגויה", "folders": "תיקיות", "folders_feature_description": "עיון בתצוגת התיקייה עבור התמונות והסרטונים שבמערכת הקבצים", - "force_re-scan_library_files": "כפה סריקה מחדש של כל קבצי הספרייה", "forward": "קדימה", "general": "כללי", "get_help": "קבל עזרה", "getting_started": "תחילת העבודה", "go_back": "חזור", "go_to_search": "עבור לחיפוש", - "go_to_share_page": "עבור לדף השיתוף", "group_albums_by": "קבץ אלבומים לפי..", "group_no": "אין קיבוץ", "group_owner": "קבץ לפי בעלים", @@ -803,10 +781,6 @@ "image_alt_text_date_place_2_people": "{isVideo, select, true {סרטון שצולם} other {תמונה שצולמה}} ב-{city}, {country} עם {person1} ו-{person2} ב-{date}", "image_alt_text_date_place_3_people": "{isVideo, select, true {סרטון שצולם} other {תמונה שצולמה}} ב-{city}, {country} עם {person1}, {person2}, ו-{person3} ב-{date}", "image_alt_text_date_place_4_or_more_people": "{isVideo, select, true {סרטון שצולם} other {תמונה שצולמה}} ב-{city}, {country} עם {person1}, {person2}, ו-{additionalCount, number} אחרים ב-{date}", - "image_alt_text_people": "{count, plural, =1 {עם {person1}} =2 {עם {person1} ו{person2}} =3 {עם {person1}, {person2}, ו{person3}} other {עם {person1}, {person2}, ו{others, number} אחרים}}", - "image_alt_text_place": "ב{city}, {country}", - "image_taken": "{isVideo, select, true {סרטון שצולם} other {תמונה שצולמה}}", - "img": "", "immich_logo": "הלוגו של Immich", "immich_web_interface": "ממשק האינטרנט של Immich", "import_from_json": "ייבוא מ-JSON", @@ -827,10 +801,11 @@ "invite_people": "הזמן אנשים", "invite_to_album": "הזמן לאלבום", "items_count": "{count, plural, one {פריט #} other {# פריטים}}", - "job_settings_description": "", "jobs": "משימות", "keep": "שמור", "keep_all": "שמור הכל", + "keep_this_delete_others": "שמור על זה, מחק אחרים", + "kept_this_deleted_others": "נכס זה נשמר ונמחקו {count, plural, one {נכס #} other {# נכסים}}", "keyboard_shortcuts": "קיצורי מקלדת", "language": "שפה", "language_setting_description": "בחר/י את השפה המועדפת עליך", @@ -842,31 +817,6 @@ "level": "רמה", "library": "ספרייה", "library_options": "אפשרויות ספרייה", - "license_account_info": "החשבון שלך מורשה", - "license_activated_subtitle": "תודה לך על התמיכה ב-Immich ובתוכנות קוד פתוח", - "license_activated_title": "הרישיון שלך הופעל בהצלחה", - "license_button_activate": "הפעל", - "license_button_buy": "קנה", - "license_button_buy_license": "קנה רישיון", - "license_button_select": "בחר", - "license_failed_activation": "הפעלת הרישיון נכשלה. נא לבדוק את הדוא\"ל שלך כדי למצוא את מפתח הרישיון הנכון!", - "license_individual_description_1": "רישיון 1 למשתמש בכל שרת", - "license_individual_title": "רישיון אישי", - "license_info_licensed": "מורשה", - "license_info_unlicensed": "ללא רשיון", - "license_input_suggestion": "יש לך רישיון? הזן את המפתח למטה", - "license_license_subtitle": "רכוש רישיון כדי לתמוך ב Immich", - "license_license_title": "רישיון", - "license_lifetime_description": "רישיון לכל החיים", - "license_per_server": "עבור שרת", - "license_per_user": "עבור משתמש", - "license_server_description_1": "רישיון 1 עבור שרת", - "license_server_description_2": "רישיון לכל המשתמשים בשרת", - "license_server_title": "רישיון שרת", - "license_trial_info_1": "אתה מפעיל גרסה ללא רישיון של Immich", - "license_trial_info_2": "אתה משתמש ב Immich קרוב ל", - "license_trial_info_3": "{accountAge, plural, one {יום #} other {# ימים}}", - "license_trial_info_4": "אנא שקול לרכוש רישיון כדי לתמוך בפיתוח המתמשך של השירות", "light": "בהיר", "like_deleted": "לייק נמחק", "link_motion_video": "קשר סרטון תנועה", @@ -971,7 +921,6 @@ "onboarding_welcome_user": "ברוכ/ה הבא/ה, {user}", "online": "מקוון", "only_favorites": "רק מועדפים", - "only_refreshes_modified_files": "מרענן רק קבצים שהשתנו", "open_in_map_view": "פתח בתצוגת מפה", "open_in_openstreetmap": "פתח ב-OpenStreetMap", "open_the_search_filters": "פתח את מסנני החיפוש", @@ -1009,14 +958,12 @@ "people_edits_count": "{count, plural, one {אדם # נערך} other {# אנשים נערכו}}", "people_feature_description": "עיון בתמונות וסרטונים שקובצו על ידי אנשים", "people_sidebar_description": "הצג קישור אל אנשים בסרגל הצד", - "perform_library_tasks": "", "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": "Permanently deleted {count, plural, one {# asset} other {# assets}}", "permanently_deleted_assets_count": "{count, plural, one {נכס # נמחק} other {# נכסים נמחקו}} לצמיתות", "person": "אדם", "person_hidden": "{name}{hidden, select, true { (מוסתר)} other {}}", @@ -1032,7 +979,6 @@ "play_memories": "נגן זכרונות", "play_motion_photo": "הפעל תמונה עם תנועה", "play_or_pause_video": "הפעל או השהה סרטון", - "point": "", "port": "יציאה", "preset": "הגדרות קבועות מראש", "preview": "תצוגה מקדימה", @@ -1077,12 +1023,10 @@ "purchase_server_description_2": "מעמד תומך", "purchase_server_title": "שרת", "purchase_settings_server_activated": "מפתח המוצר של השרת מנוהל על ידי מנהל המערכת", - "range": "", "rating": "דירוג כוכב", "rating_clear": "נקה דירוג", "rating_count": "{count, plural, one {כוכב #} other {# כוכבים}}", "rating_description": "הצג את דירוג ה-EXIF בלוח המידע", - "raw": "", "reaction_options": "אפשרויות הגבה", "read_changelog": "קרא את יומן השינויים", "reassign": "הקצה מחדש", @@ -1090,6 +1034,7 @@ "reassigned_assets_to_new_person": "{count, plural, one {נכס # הוקצה} other {# נכסים הוקצו}} מחדש לאדם חדש", "reassing_hint": "הקצה נכסים שנבחרו לאדם קיים", "recent": "חדש", + "recent-albums": "אלבומים אחרונים", "recent_searches": "חיפושים אחרונים", "refresh": "רענן", "refresh_encoded_videos": "רענן סרטונים מקודדים", @@ -1111,6 +1056,7 @@ "remove_from_album": "הסר מאלבום", "remove_from_favorites": "הסר מהמועדפים", "remove_from_shared_link": "הסר מקישור משותף", + "remove_url": "הסר URL", "remove_user": "הסר משתמש", "removed_api_key": "מפתח API הוסר: {name}", "removed_from_archive": "הוסר מארכיון", @@ -1127,7 +1073,6 @@ "reset": "איפוס", "reset_password": "איפוס סיסמה", "reset_people_visibility": "אפס את נראות האנשים", - "reset_settings_to_default": "", "reset_to_default": "אפס לברירת מחדל", "resolve_duplicates": "פתור כפילויות", "resolved_all_duplicates": "כל הכפילויות נפתרו", @@ -1147,9 +1092,7 @@ "saved_settings": "הגדרות שמורות", "say_something": "תגיד/י משהו", "scan_all_libraries": "סרוק את כל הספריות", - "scan_all_library_files": "סרוק מחדש את כל קבצי הספרייה", "scan_library": "סרוק", - "scan_new_library_files": "סרוק קבצי ספרייה חדשים", "scan_settings": "הגדרות סריקה", "scanning_for_album": "סורק אחר אלבום...", "search": "חפש", @@ -1192,7 +1135,6 @@ "selected_count": "{count, plural, other {# נבחרו}}", "send_message": "שלח הודעה", "send_welcome_email": "שלח דוא\"ל קבלת פנים", - "server": "שרת", "server_offline": "שרת לא מקוון", "server_online": "שרת מקוון", "server_stats": "סטטיסטיקות שרת", @@ -1297,17 +1239,17 @@ "they_will_be_merged_together": "הם יתמזגו יחד", "third_party_resources": "משאבי צד שלישי", "time_based_memories": "זכרונות מבוססי זמן", + "timeline": "ציר זמן", "timezone": "אזור זמן", "to_archive": "העבר לארכיון", "to_change_password": "שנה סיסמה", "to_favorite": "מועדף", "to_login": "כניסה", "to_parent": "לך להורה", - "to_root": "לשורש", "to_trash": "אשפה", "toggle_settings": "החלף מצב הגדרות", "toggle_theme": "החלף ערכת נושא כהה", - "toggle_visibility": "החלף נראות", + "total": "סה\"כ", "total_usage": "שימוש כולל", "trash": "אשפה", "trash_all": "העבר הכל לאשפה", @@ -1317,12 +1259,10 @@ "trashed_items_will_be_permanently_deleted_after": "פריטים באשפה ימחקו לצמיתות לאחר {days, plural, one {יום #} other {# ימים}}.", "type": "סוג", "unarchive": "הוצא מארכיון", - "unarchived": "הוצא מהארכיון", "unarchived_count": "{count, plural, other {# הוצאו מהארכיון}}", "unfavorite": "לא מועדף", "unhide_person": "בטל הסתרת אדם", "unknown": "לא ידוע", - "unknown_album": "אלבום לא ידוע", "unknown_year": "שנה לא ידועה", "unlimited": "בלתי מוגבל", "unlink_motion_video": "בטל קישור סרטון תנועה", @@ -1354,13 +1294,13 @@ "use_custom_date_range": "השתמש בטווח תאריכים מותאם במקום", "user": "משתמש", "user_id": "מזהה משתמש", - "user_license_settings": "רישיון", - "user_license_settings_description": "נהל את הרישיון שלך", "user_liked": "{user} אהב את {type, select, photo {התמונה הזאת} video {הסרטון הזה} asset {הנכס הזה} other {זה}}", "user_purchase_settings": "רכישה", "user_purchase_settings_description": "נהל את הרכישה שלך", "user_role_set": "הגדר את {user} בתור {role}", "user_usage_detail": "פרטי השימוש של המשתמש", + "user_usage_stats": "סטטיסטיקות שימוש בחשבון", + "user_usage_stats_description": "הצג סטטיסטיקות שימוש בחשבון", "username": "שם משתמש", "users": "משתמשים", "utilities": "כלים", @@ -1368,7 +1308,7 @@ "variables": "משתנים", "version": "גרסה", "version_announcement_closing": "החבר שלך, אלכס", - "version_announcement_message": "הי חבר/ה, יש מהדורה חדשה של היישום, אנא קח/י את הזמן שלך לבקר ב הערות פרסום ולוודא שמבנה ה-docker-compose.yml, וה-.env שלך עדכני כדי למנוע תצורות שגויות, במיוחד אם את/ה משתמש/ת ב-WatchTower או בכל מנגנון שמטפל בעדכון היישום שלך באופן אוטומטי.", + "version_announcement_message": "שלום לך! זמינה גרסה חדשה של Immich. אנא קח/י זמן מה לקרוא את הערות הפרסום כדי לוודא שההתקנה שלך עדכנית על מנת למנוע תצורות שגויות, במיוחד אם את/ה משתמש/ת ב-WatchTower או בכל מנגנון שמטפל בעדכון מופע ה-Immich שלך באופן אוטומטי.", "version_history": "היסטוריית גרסאות", "version_history_item": "{version} הותקנה ב-{date}", "video": "סרטון", @@ -1382,10 +1322,10 @@ "view_all_users": "הצג את כל המשתמשים", "view_in_timeline": "ראה בציר הזמן", "view_links": "הצג קישורים", + "view_name": "הצג", "view_next_asset": "הצג את הנכס הבא", "view_previous_asset": "הצג את הנכס הקודם", "view_stack": "הצג ערימה", - "viewer": "מציג", "visibility_changed": "הנראות השתנתה עבור {count, plural, one {אדם #} other {# אנשים}}", "waiting": "ממתין", "warning": "אזהרה", diff --git a/i18n/hi.json b/i18n/hi.json index 58b99dbc3cbfd..5df14e72968f3 100644 --- a/i18n/hi.json +++ b/i18n/hi.json @@ -23,6 +23,7 @@ "add_to": "इसमें जोड़ें..।", "add_to_album": "एल्बम में जोड़ें", "add_to_shared_album": "साझा एल्बम में जोड़ें", + "add_url": "URL जोड़ें", "added_to_archive": "संग्रहीत कर दिया गया है", "added_to_favorites": "पसंदीदा में जोड़ा गया", "added_to_favorites_count": "पसंदीदा में {count, number} जोड़ा गया", @@ -41,9 +42,7 @@ "confirm_email_below": "पुष्टि करने के लिए नीचे \"{email}\" टाइप करें", "confirm_reprocess_all_faces": "क्या आप वाकई सभी चेहरों को दोबारा संसाधित करना चाहते हैं? इससे नामित लोग भी साफ हो जायेंगे।", "confirm_user_password_reset": "क्या आप वाकई {user} का पासवर्ड रीसेट करना चाहते हैं?", - "crontab_guru": "", "disable_login": "लॉगिन अक्षम करें", - "disabled": "", "duplicate_detection_job_description": "समान छवियों का पता लगाने के लिए संपत्तियों पर मशीन लर्निंग चलाएं। यह कार्यक्षमता स्मार्ट खोज पर निर्भर करती है", "exclusion_pattern_description": "Exclusion पैटर्न आपको अपनी लाइब्रेरी को स्कैन करते समय फ़ाइलों और फ़ोल्डरों को अनदेखा करने देता है। यह उपयोगी है यदि आपके पास ऐसे फ़ोल्डर हैं जिनमें ऐसी फ़ाइलें हैं जिन्हें आप आयात नहीं करना चाहते हैं, जैसे RAW फ़ाइलें।", "external_library_created_at": "बाहरी लाइब्रेरी ({date} को बनाई गई)", @@ -59,16 +58,9 @@ "image_prefer_embedded_preview_setting_description": "जब उपलब्ध हो तो RAW फ़ोटो में एम्बेडेड पूर्वावलोकन का उपयोग इमेज प्रोसेसिंग के इनपुट के रूप में करें। यह कुछ छवियों के लिए अधिक सटीक रंग उत्पन्न कर सकता है, लेकिन पूर्वावलोकन की गुणवत्ता कैमरे पर निर्भर करती है और छवि में अधिक संपीड़न कलाकृतियाँ हो सकती हैं।", "image_prefer_wide_gamut": "विस्तृत सरगम को प्राथमिकता दें", "image_prefer_wide_gamut_setting_description": "थंबनेल के लिए डिस्प्ले P3 का उपयोग करें। यह विस्तृत कलरस्पेस वाली छवियों की जीवंतता को बेहतर ढंग से संरक्षित करता है, लेकिन पुराने ब्राउज़र संस्करण वाले पुराने डिवाइस पर छवियां अलग-अलग दिखाई दे सकती हैं। रंग परिवर्तन से बचने के लिए sRGB छवियों को sRGB के रूप में रखा जाता है।", - "image_preview_format": "पूर्वावलोकन प्रारूप", - "image_preview_resolution": "पूर्वावलोकन रिज़ॉल्यूशन", - "image_preview_resolution_description": "एकल फ़ोटो देखते समय और मशीन लर्निंग के लिए उपयोग किया जाता है। उच्च रिज़ॉल्यूशन अधिक विवरण को संरक्षित कर सकता है लेकिन एन्कोड करने में अधिक समय लेता है, फ़ाइल आकार बड़ा होता है, और ऐप की प्रतिक्रियाशीलता कम हो सकती है।", "image_quality": "गुणवत्ता", - "image_quality_description": "छवि गुणवत्ता 1-100 तक। उच्च गुणवत्ता बेहतर है लेकिन बड़ी फ़ाइलें बनाती है, यह विकल्प पूर्वावलोकन और थंबनेल छवियों को प्रभावित करता है।", "image_settings": "छवि सेटिंग्स", "image_settings_description": "उत्पन्न छवियों की गुणवत्ता और रिज़ॉल्यूशन प्रबंधित करें", - "image_thumbnail_format": "थंबनेल प्रारूप", - "image_thumbnail_resolution": "थंबनेल रिज़ॉल्यूशन", - "image_thumbnail_resolution_description": "फ़ोटो के समूह (मुख्य टाइमलाइन, एल्बम दृश्य, आदि) देखते समय उपयोग किया जाता है। उच्च रिज़ॉल्यूशन अधिक विवरण को संरक्षित कर सकता है लेकिन एन्कोड करने में अधिक समय लेता है, फ़ाइल आकार बड़ा होता है, और ऐप की प्रतिक्रियाशीलता कम हो सकती है।", "job_concurrency": "{job} समरूपता", "job_not_concurrency_safe": "यह कार्य (जॉब) समवर्ती-सुरक्षित नहीं है।", "job_settings": "कार्य (जॉब) सेटिंग्स", @@ -77,9 +69,6 @@ "jobs_delayed": "{jobCount, plural, other {# विलंबित}}", "jobs_failed": "{jobCount, plural, other {# असफल}}", "library_created": "निर्मित संग्रह: {library}", - "library_cron_expression": "क्रॉन व्यंजक", - "library_cron_expression_description": "क्रॉन प्रारूप का उपयोग करके स्कैनिंग अंतराल सेट करें। अधिक जानकारी के लिए कृपया उदाहरण के लिए Crontab Guru देखें", - "library_cron_expression_presets": "क्रॉन व्यंजक प्रीसेट", "library_deleted": "संग्रह हटा दिया गया", "library_import_path_description": "आयात करने के लिए एक फ़ोल्डर निर्दिष्ट करें। सबफ़ोल्डर्स सहित इस फ़ोल्डर को छवियों और वीडियो के लिए स्कैन किया जाएगा।", "library_scanning": "सामयिक स्कैनिंग", @@ -197,13 +186,10 @@ "refreshing_all_libraries": "सभी पुस्तकालयों को ताज़ा किया जा रहा है", "registration": "व्यवस्थापक पंजीकरण", "registration_description": "चूंकि आप सिस्टम पर पहले उपयोगकर्ता हैं, इसलिए आपको व्यवस्थापक के रूप में नियुक्त किया जाएगा और आप प्रशासनिक कार्यों के लिए जिम्मेदार होंगे, और अतिरिक्त उपयोगकर्ता आपके द्वारा बनाए जाएंगे।", - "removing_deleted_files": "ऑफ़लाइन फ़ाइलें हटाना", "repair_all": "सभी की मरम्मत", "require_password_change_on_login": "उपयोगकर्ता को पहले लॉगिन पर पासवर्ड बदलने की आवश्यकता है", "reset_settings_to_default": "सेटिंग्स को डिफ़ॉल्ट पर रीसेट करें", "reset_settings_to_recent_saved": "सेटिंग्स को हाल ही में सहेजी गई सेटिंग्स पर रीसेट करें", - "scanning_library_for_changed_files": "परिवर्तित फ़ाइलों के लिए लाइब्रेरी को स्कैन करना", - "scanning_library_for_new_files": "नई फ़ाइलों के लिए लाइब्रेरी को स्कैन करना", "send_welcome_email": "स्वागत ईमेल भेजें", "server_external_domain_settings": "बाहरी डोमेन", "server_external_domain_settings_description": "सार्वजनिक साझा लिंक के लिए डोमेन, जिसमें http(s):// शामिल है", @@ -233,7 +219,6 @@ "these_files_matched_by_checksum": "इन फ़ाइलों का मिलान उनके चेकसम से किया जाता है", "thumbnail_generation_job": "थंबनेल उत्पन्न करें", "thumbnail_generation_job_description": "प्रत्येक संपत्ति के लिए बड़े, छोटे और धुंधले थंबनेल, साथ ही प्रत्येक व्यक्ति के लिए थंबनेल बनाएं", - "transcode_policy_description": "", "transcoding_acceleration_api": "त्वरण एपीआई", "transcoding_acceleration_api_description": "एपीआई जो ट्रांसकोडिंग को तेज करने के लिए आपके डिवाइस के साथ इंटरैक्ट करेगा।", "transcoding_acceleration_nvenc": "NVENC (NVIDIA GPU की आवश्यकता है)", @@ -285,8 +270,6 @@ "transcoding_threads_description": "उच्च मान तेज़ एन्कोडिंग की ओर ले जाते हैं, लेकिन सक्रिय रहते हुए सर्वर के लिए अन्य कार्यों को संसाधित करने के लिए कम जगह छोड़ते हैं।", "transcoding_tone_mapping": "टोन-मैपिंग", "transcoding_tone_mapping_description": "एसडीआर में परिवर्तित होने पर एचडीआर वीडियो की उपस्थिति को संरक्षित करने का प्रयास।", - "transcoding_tone_mapping_npl": "टोन-मैपिंग एनपीएल", - "transcoding_tone_mapping_npl_description": "इस चमक के प्रदर्शन को सामान्य दिखाने के लिए रंगों को समायोजित किया जाएगा।", "transcoding_transcode_policy": "ट्रांसकोड नीति", "transcoding_transcode_policy_description": "किसी वीडियो को कब ट्रांसकोड किया जाना चाहिए, इसके लिए नीति।", "transcoding_two_pass_encoding": "दो-पास एन्कोडिंग", @@ -349,7 +332,6 @@ "archive_or_unarchive_photo": "फ़ोटो को संग्रहीत या असंग्रहीत करें", "archive_size": "पुरालेख आकार", "archive_size_description": "डाउनलोड के लिए संग्रह आकार कॉन्फ़िगर करें (GiB में)", - "archived": "", "are_these_the_same_person": "क्या ये वही व्यक्ति हैं?", "are_you_sure_to_do_this": "क्या आप वास्तव में इसे करना चाहते हैं?", "asset_added_to_album": "एल्बम में जोड़ा गया", @@ -382,10 +364,6 @@ "cannot_merge_people": "लोगों का विलय नहीं हो सकता", "cannot_undo_this_action": "आप इस क्रिया को पूर्ववत नहीं कर सकते!", "cannot_update_the_description": "विवरण अद्यतन नहीं किया जा सकता", - "cant_apply_changes": "", - "cant_get_faces": "", - "cant_search_people": "", - "cant_search_places": "", "change_date": "बदलाव दिनांक", "change_expiration_time": "समाप्ति समय बदलें", "change_location": "स्थान बदलें", @@ -487,13 +465,6 @@ "duplicates": "डुप्लिकेट", "duplicates_description": "प्रत्येक समूह को यह इंगित करके हल करें कि कौन सा, यदि कोई है, डुप्लिकेट है", "duration": "अवधि", - "durations": { - "days": "", - "hours": "", - "minutes": "", - "months": "", - "years": "" - }, "edit": "संपादन करना", "edit_album": "एल्बम संपादित करें", "edit_avatar": "अवतार को एडिट करें", @@ -513,8 +484,6 @@ "edited": "संपादित", "editor": "", "email": "ईमेल", - "empty": "", - "empty_album": "", "empty_trash": "कूड़ेदान खाली करें", "empty_trash_confirmation": "क्या आपको यकीन है कि आप कचरा खाली करना चाहते हैं? यह इमिच से स्थायी रूप से कचरा में सभी संपत्तियों को हटा देगा।\nआप इस कार्रवाई को नहीं रोक सकते!", "enable": "सक्षम", @@ -564,8 +533,6 @@ "unable_to_change_favorite": "संपत्ति के लिए पसंदीदा बदलने में असमर्थ", "unable_to_change_location": "स्थान बदलने में असमर्थ", "unable_to_change_password": "पासवर्ड बदलने में असमर्थ", - "unable_to_check_item": "", - "unable_to_check_items": "", "unable_to_complete_oauth_login": "OAuth लॉगिन पूर्ण करने में असमर्थ", "unable_to_connect": "कनेक्ट करने में असमर्थ", "unable_to_connect_to_server": "सर्वर से कनेक्ट करने में असमर्थ है", @@ -604,12 +571,10 @@ "unable_to_remove_album_users": "उपयोगकर्ताओं को एल्बम से निकालने में असमर्थ", "unable_to_remove_api_key": "API कुंजी निकालने में असमर्थ", "unable_to_remove_assets_from_shared_link": "साझा लिंक से संपत्तियों को निकालने में असमर्थ", - "unable_to_remove_comment": "", "unable_to_remove_deleted_assets": "ऑफ़लाइन फ़ाइलें निकालने में असमर्थ", "unable_to_remove_library": "लाइब्रेरी हटाने में असमर्थ", "unable_to_remove_partner": "पार्टनर को हटाने में असमर्थ", "unable_to_remove_reaction": "प्रतिक्रिया निकालने में असमर्थ", - "unable_to_remove_user": "", "unable_to_repair_items": "वस्तुओं की मरम्मत करने में असमर्थ", "unable_to_reset_password": "पासवर्ड रीसेट करने में असमर्थ", "unable_to_resolve_duplicate": "डुप्लिकेट का समाधान करने में असमर्थ", @@ -638,10 +603,6 @@ "unable_to_update_user": "उपयोगकर्ता को अद्यतन करने में असमर्थ", "unable_to_upload_file": "फाइल अपलोड करने में असमर्थ" }, - "every_day_at_onepm": "", - "every_night_at_midnight": "", - "every_night_at_twoam": "", - "every_six_hours": "", "exif": "एक्सिफ", "exit_slideshow": "स्लाइड शो से बाहर निकलें", "expand_all": "सभी का विस्तार", @@ -654,29 +615,23 @@ "external": "बाहरी", "external_libraries": "बाहरी पुस्तकालय", "face_unassigned": "सौंपे नहीं गए", - "failed_to_get_people": "", "favorite": "पसंदीदा", "favorite_or_unfavorite_photo": "पसंदीदा या नापसंद फोटो", "favorites": "पसंदीदा", - "feature": "", "feature_photo_updated": "फ़ीचर फ़ोटो अपडेट किया गया", - "featurecollection": "", "file_name": "फ़ाइल का नाम", "file_name_or_extension": "फ़ाइल का नाम या एक्सटेंशन", "filename": "फ़ाइल का नाम", - "files": "", "filetype": "फाइल का प्रकार", "filter_people": "लोगों को फ़िल्टर करें", "find_them_fast": "खोज के साथ नाम से उन्हें तेजी से ढूंढें", "fix_incorrect_match": "ग़लत मिलान ठीक करें", - "force_re-scan_library_files": "सभी लाइब्रेरी फ़ाइलों को बलपूर्वक पुनः स्कैन करें", "forward": "आगे", "general": "सामान्य", "get_help": "मदद लें", "getting_started": "शुरू करना", "go_back": "वापस जाओ", "go_to_search": "खोज पर जाएँ", - "go_to_share_page": "शेयर पेज पर जाएं", "group_albums_by": "इनके द्वारा समूह एल्बम..।", "group_no": "कोई समूहीकरण नहीं", "group_owner": "स्वामी द्वारा समूह", @@ -690,7 +645,6 @@ "host": "मेज़बान", "hour": "घंटा", "image": "छवि", - "img": "", "immich_logo": "Immich लोगो", "immich_web_interface": "इमिच वेब इंटरफ़ेस", "import_from_json": "JSON से आयात करें", @@ -709,7 +663,6 @@ }, "invite_people": "लोगो को निमंत्रण भेजो", "invite_to_album": "एल्बम के लिए आमंत्रित करें", - "job_settings_description": "", "jobs": "नौकरियां", "keep": "रखना", "keep_all": "सभी रखना", @@ -820,7 +773,6 @@ "onboarding_welcome_description": "आइए कुछ सामान्य सेटिंग्स के साथ अपना इंस्टेंस सेट अप करें।", "online": "ऑनलाइन", "only_favorites": "केवल पसंदीदा", - "only_refreshes_modified_files": "केवल संशोधित फ़ाइलों को ताज़ा करता है", "open_in_openstreetmap": "OpenStreetMap में खोलें", "open_the_search_filters": "खोज फ़िल्टर खोलें", "options": "विकल्प", @@ -854,7 +806,6 @@ "pending": "लंबित", "people": "लोग", "people_sidebar_description": "साइडबार में लोगों के लिए एक लिंक प्रदर्शित करें", - "perform_library_tasks": "", "permanent_deletion_warning": "स्थायी विलोपन चेतावनी", "permanent_deletion_warning_setting_description": "संपत्तियों को स्थायी रूप से हटाते समय एक चेतावनी दिखाएं", "permanently_delete": "स्थायी रूप से हटाना", @@ -871,7 +822,6 @@ "play_memories": "यादें खेलें", "play_motion_photo": "मोशन फ़ोटो चलाएं", "play_or_pause_video": "वीडियो चलाएं या रोकें", - "point": "", "port": "पत्तन", "preset": "प्रीसेट", "preview": "पूर्व दर्शन", @@ -913,8 +863,6 @@ "purchase_server_description_2": "समर्थक स्थिति", "purchase_server_title": "सर्वर", "purchase_settings_server_activated": "सर्वर उत्पाद कुंजी व्यवस्थापक द्वारा प्रबंधित की जाती है", - "range": "", - "raw": "", "reaction_options": "प्रतिक्रिया विकल्प", "read_changelog": "चेंजलॉग पढ़ें", "reassign": "पुनः असाइन", @@ -950,7 +898,6 @@ "reset": "रीसेट", "reset_password": "पासवर्ड रीसेट", "reset_people_visibility": "लोगों की दृश्यता रीसेट करें", - "reset_settings_to_default": "", "reset_to_default": "वितथ पर ले जाएं", "resolve_duplicates": "डुप्लिकेट का समाधान करें", "resolved_all_duplicates": "सभी डुप्लिकेट का समाधान किया गया", @@ -970,8 +917,6 @@ "saved_settings": "सहेजी गई सेटिंग्स", "say_something": "कुछ कहें", "scan_all_libraries": "सभी पुस्तकालयों को स्कैन करें", - "scan_all_library_files": "सभी लाइब्रेरी फ़ाइलों को पुनः स्कैन करें", - "scan_new_library_files": "नई लाइब्रेरी फ़ाइलें स्कैन करें", "scan_settings": "सेटिंग्स स्कैन करें", "scanning_for_album": "एल्बम के लिए स्कैन किया जा रहा है..।", "search": "खोज", @@ -1009,7 +954,6 @@ "selected": "चयनित", "send_message": "मेसेज भेजें", "send_welcome_email": "स्वागत ईमेल भेजें", - "server": "", "server_offline": "सर्वर ऑफ़लाइन", "server_online": "सर्वर ऑनलाइन", "server_stats": "सर्वर आँकड़े", @@ -1094,7 +1038,6 @@ "to_trash": "कचरा", "toggle_settings": "सेटिंग्स टॉगल करें", "toggle_theme": "थीम टॉगल करें", - "toggle_visibility": "", "total_usage": "कुल उपयोग", "trash": "कचरा", "trash_all": "सब कचरा", @@ -1102,11 +1045,9 @@ "trash_no_results_message": "ट्रैश की गई फ़ोटो और वीडियो यहां दिखाई देंगे।", "type": "प्रकार", "unarchive": "संग्रह से निकालें", - "unarchived": "", "unfavorite": "नापसंद करें", "unhide_person": "व्यक्ति को उजागर करें", "unknown": "अज्ञात", - "unknown_album": "", "unknown_year": "अज्ञात वर्ष", "unlimited": "असीमित", "unlink_oauth": "OAuth को अनलिंक करें", @@ -1155,7 +1096,6 @@ "view_next_asset": "अगली संपत्ति देखें", "view_previous_asset": "पिछली संपत्ति देखें", "view_stack": "ढेर देखें", - "viewer": "", "waiting": "इंतज़ार में", "warning": "चेतावनी", "week": "सप्ताह", diff --git a/i18n/hr.json b/i18n/hr.json index 0b1c6c64badba..d4273b8741665 100644 --- a/i18n/hr.json +++ b/i18n/hr.json @@ -34,6 +34,11 @@ "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.", "background_task_job": "Pozadinski zadaci", + "backup_database": "Sigurnosna kopija baze podataka", + "backup_database_enable_description": "Omogućite sigurnosne kopije baze podataka", + "backup_keep_last_amount": "Količina prethodnih sigurnosnih kopija za čuvanje", + "backup_settings": "Postavke sigurnosne kopije", + "backup_settings_description": "Upravljanje postavkama sigurnosne kopije baze podataka", "check_all": "Provjeri sve", "cleared_jobs": "Izbrisani poslovi za: {job}", "config_set_by_file": "Konfiguracija je trenutno postavljena konfiguracijskom datotekom", @@ -43,7 +48,9 @@ "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}?", "create_job": "Izradi zadatak", - "crontab_guru": "Crontab Guru", + "cron_expression": "Cron izraz (expression)", + "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", "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.", @@ -62,17 +69,16 @@ "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_format": "Format pregleda", "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_resolution": "Razlučivost pregleda", - "image_preview_resolution_description": "Koristi se pri gledanju jedne fotografije i za strojno učenje. Veće razlučivosti mogu sačuvati više detalja, ali trebaju dulje za kodiranje, imaju veće veličine datoteka i mogu smanjiti odaziv aplikacije.", + "image_preview_title": "Postavke pregleda", "image_quality": "Kvaliteta", - "image_quality_description": "Kvaliteta slike od 1-100. Više je bolji za kvalitetu, ali daje veće datoteke, ova opcija utječe na Pretpregled i sličice.", + "image_resolution": "Rezolucija", + "image_resolution_description": "Veće razlučivosti mogu sačuvati više detalja, ali trebaju dulje za kodiranje, imaju veće veličine datoteka i mogu smanjiti odziv aplikacije.", "image_settings": "Postavke slike", "image_settings_description": "Upravljajte kvalitetom i rezolucijom generiranih slika", - "image_thumbnail_format": "Format sličica", - "image_thumbnail_resolution": "Razlučivost sličica", - "image_thumbnail_resolution_description": "Koristi se prilikom pregledavanja grupa fotografija (glavna vremenska traka, prikaz albuma itd.). Veće razlučivosti mogu sačuvati više detalja, ali trebaju dulje za kodiranje, imaju veće veličine datoteka i mogu smanjiti odaziv aplikacije.", + "image_thumbnail_description": "Mala minijatura s ogoljenim metapodacima, koristi se pri gledanju grupa fotografija poput glavne vremenske trake", + "image_thumbnail_quality_description": "Kvaliteta sličica od 1-100. Više je bolje, ali proizvodi veće datoteke i može smanjiti odziv aplikacije.", + "image_thumbnail_title": "Postavke sličica", "job_concurrency": "{job} istovremenost", "job_created": "Zadatak je kreiran", "job_not_concurrency_safe": "Ovaj posao nije siguran za istovremenost.", @@ -82,9 +88,6 @@ "jobs_delayed": "{jobCount, plural, other {# delayed}}", "jobs_failed": "{jobCount, plural, other {# failed}}", "library_created": "Stvorena biblioteka: {library}", - "library_cron_expression": "Cron izraz", - "library_cron_expression_description": "Postavite interval skeniranja koristeći cron format. Za više informacija pogledajte npr. Crontab Guru", - "library_cron_expression_presets": "Unaprijed postavljene cron izraze", "library_deleted": "Biblioteka izbrisana", "library_import_path_description": "Navedite mapu za uvoz. Ova će se mapa, uključujući podmape, skenirati u potrazi za slikama i videozapisima.", "library_scanning": "Periodično Skeniranje", @@ -208,19 +211,19 @@ "refreshing_all_libraries": "Osvježavanje svih biblioteka", "registration": "Registracija administratora", "registration_description": "Budući da ste prvi korisnik na sustavu, bit ćete dodijeljeni administratorsku ulogu i odgovorni ste za administrativne poslove, a dodatne korisnike kreirat ćete sami.", - "removing_deleted_files": "Uklanjanje izvanmrežnih datoteka", "repair_all": "Popravi sve", "repair_matched_items": "Podudaranje {count, plural, one {# item} other {# items}}", "repaired_items": "Popravljeno {count, plural, one {# item} other {# items}}", "require_password_change_on_login": "Zahtijevajte od korisnika promjenu lozinke pri prvoj prijavi", "reset_settings_to_default": "Vrati postavke na zadane", "reset_settings_to_recent_saved": "Resetirajte postavke na nedavno spremljene postavke", - "scanning_library_for_changed_files": "Skeniranje biblioteke za promijenjene datoteke", - "scanning_library_for_new_files": "Skeniranje biblioteke za nove datoteke", + "scanning_library": "Skeniranje biblioteke", "search_jobs": "Traži zadatke…", "send_welcome_email": "Pošaljite email dobrodošlice", "server_external_domain_settings": "Vanjska domena", "server_external_domain_settings_description": "Domena za javno dijeljene linkove, uključujući http(s)://", + "server_public_users": "Javni korisnici", + "server_public_users_description": "Svi korisnici (ime i e-pošta) navedeni su prilikom dodavanja korisnika u dijeljene albume. Kada je onemogućeno, popis korisnika bit će dostupan samo korisnicima administratora.", "server_settings": "Postavke servera", "server_settings_description": "Upravljanje postavkama servera", "server_welcome_message": "Poruka dobrodošlice", @@ -304,8 +307,6 @@ "transcoding_threads_description": "Više vrijednosti dovode do bržeg kodiranja, ali ostavljaju manje prostora poslužitelju za obradu drugih zadataka dok je aktivan. Ova vrijednost ne smije biti veća od broja CPU jezgri. Maksimalno povećava iskorištenje ako je postavljeno na 0.", "transcoding_tone_mapping": "Tonsko preslikavanje", "transcoding_tone_mapping_description": "Pokušava sačuvati izgled HDR videozapisa kada se pretvori u SDR. Svaki algoritam čini različite kompromise za boju, detalje i svjetlinu. Hable čuva detalje, Mobius čuva boju, a Reinhard svjetlinu.", - "transcoding_tone_mapping_npl": "Tone-mapping NPL", - "transcoding_tone_mapping_npl_description": "Boje će se prilagoditi tako da izgledaju normalno za zaslon ove svjetline. Suprotno intuiciji, niže vrijednosti povećavaju svjetlinu videa i obrnuto budući da kompenziraju svjetlinu zaslona. 0 automatski postavlja ovu vrijednost.", "transcoding_transcode_policy": "Pravila transkodiranja", "transcoding_transcode_policy_description": "Pravila o tome kada se video treba transkodirati. HDR videozapisi uvijek će biti transkodirani (osim ako je transkodiranje onemogućeno).", "transcoding_two_pass_encoding": "Kodiranje u dva prolaza", @@ -386,7 +387,6 @@ "archive_or_unarchive_photo": "Arhivirajte ili dearhivirajte fotografiju", "archive_size": "Veličina arhive", "archive_size_description": "Konfigurirajte veličinu arhive za preuzimanja (u GiB)", - "archived": "", "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?", @@ -421,6 +421,7 @@ "birthdate_saved": "Datum rođenja uspješno spremljen", "birthdate_set_description": "Datum rođenja se koristi za izračunavanje godina ove osobe u trenutku fotografije.", "blurred_background": "Zamućena pozadina", + "bugs_and_feature_requests": "Bugovi i zahtjevi za značajke", "build": "Sagradi (Build)", "build_image": "Sagradi (Build) Image", "bulk_delete_duplicates_confirmation": "Jeste li sigurni da želite skupno izbrisati {count, plural, one {# duplicate asset} other {# duplicate asset}}? Ovo će zadržati najveće sredstvo svake grupe i trajno izbrisati sve druge duplikate. Ne možete poništiti ovu radnju!", @@ -435,10 +436,6 @@ "cannot_merge_people": "Nije moguće spojiti osobe", "cannot_undo_this_action": "Ne možete poništiti ovu radnju!", "cannot_update_the_description": "Nije moguće ažurirati opis", - "cant_apply_changes": "", - "cant_get_faces": "", - "cant_search_people": "", - "cant_search_places": "", "change_date": "Promjena datuma", "change_expiration_time": "Promjena vremena isteka", "change_location": "Promjena lokacije", @@ -470,6 +467,7 @@ "confirm": "Potvrdi", "confirm_admin_password": "Potvrdite lozinku administratora", "confirm_delete_shared_link": "Jeste li sigurni da želite izbrisati ovu zajedničku vezu?", + "confirm_keep_this_delete_others": "Sva druga sredstva u nizu bit će izbrisana osim ovog sredstva. Jeste li sigurni da želite nastaviti?", "confirm_password": "Potvrdite lozinku", "contain": "Sadrži", "context": "Kontekst", @@ -519,16 +517,19 @@ "delete_key": "Ključ za brisanje", "delete_library": "Izbriši knjižnicu", "delete_link": "Izbriši poveznicu", + "delete_others": "Izbriši druge", "delete_shared_link": "Izbriši dijeljenu poveznicu", "delete_tag": "Izbriši oznaku", "delete_tag_confirmation_prompt": "Jeste li sigurni da želite izbrisati oznaku {tagName}?", "delete_user": "Izbriši korisnika", "deleted_shared_link": "Izbrisana dijeljena poveznica", + "deletes_missing_assets": "Briše sredstva koja nedostaju s diska", "description": "Opis", "details": "Detalji", "direction": "Smjer", "disabled": "Onemogućeno", "disallow_edits": "Zabrani izmjene", + "discord": "Discord", "discover": "Otkrij", "dismiss_all_errors": "Odbaci sve pogreške", "dismiss_error": "Odbaci pogrešku", @@ -537,6 +538,7 @@ "display_original_photos": "Prikaz originalnih fotografija", "display_original_photos_setting_description": "Radije prikažite izvornu fotografiju kada gledate materijal umjesto sličica kada je izvorni materijal kompatibilan s webom. To može rezultirati sporijim brzinama prikaza fotografija.", "do_not_show_again": "Ne prikazuj više ovu poruku", + "documentation": "Dokumentacija", "done": "Gotovo", "download": "Preuzmi", "download_include_embedded_motion_videos": "Ugrađeni videozapisi", @@ -549,13 +551,6 @@ "duplicates": "Duplikati", "duplicates_description": "Razriješite svaku grupu tako da naznačite koji su duplikati, ako ih ima", "duration": "Trajanje", - "durations": { - "days": "", - "hours": "", - "minutes": "", - "months": "", - "years": "" - }, "edit": "Izmjena", "edit_album": "Uredi album", "edit_avatar": "Uredi avatar", @@ -580,7 +575,6 @@ "editor_crop_tool_h2_aspect_ratios": "Omjeri stranica", "editor_crop_tool_h2_rotation": "Rotacija", "email": "E-pošta", - "empty_album": "", "empty_trash": "Isprazni smeće", "empty_trash_confirmation": "Jeste li sigurni da želite isprazniti smeće? Time će se iz Immicha trajno ukloniti sva sredstva u otpadu.\nNe možete poništiti ovu radnju!", "enable": "Omogući", @@ -614,6 +608,7 @@ "failed_to_create_shared_link": "Stvaranje dijeljene veze nije uspjelo", "failed_to_edit_shared_link": "Nije uspjelo uređivanje dijeljene poveznice", "failed_to_get_people": "Dohvaćanje ljudi nije uspjelo", + "failed_to_keep_this_delete_others": "Zadržavanje ovog sredstva i brisanje ostalih sredstava nije uspjelo", "failed_to_load_asset": "Učitavanje sredstva nije uspjelo", "failed_to_load_assets": "Učitavanje sredstava nije uspjelo", "failed_to_load_people": "Učitavanje ljudi nije uspjelo", @@ -681,8 +676,8 @@ "unable_to_remove_album_users": "Nije moguće ukloniti korisnike iz albuma", "unable_to_remove_api_key": "Nije moguće ukloniti API ključ", "unable_to_remove_assets_from_shared_link": "Nije moguće ukloniti sredstva iz dijeljene poveznice", + "unable_to_remove_deleted_assets": "Nije moguće ukloniti izvanmrežne datoteke", "unable_to_remove_library": "Nije moguće ukloniti biblioteku", - "unable_to_remove_offline_files": "Nije moguće ukloniti izvanmrežne datoteke", "unable_to_remove_partner": "Nije moguće ukloniti partnera", "unable_to_remove_reaction": "Nije moguće ukloniti reakciju", "unable_to_repair_items": "Nije moguće popraviti stavke", @@ -728,7 +723,6 @@ "external": "Vanjski", "external_libraries": "Vanjske Biblioteke", "face_unassigned": "Nedodijeljeno", - "failed_to_get_people": "", "favorite": "Omiljeno", "favorite_or_unfavorite_photo": "Omiljena ili neomiljena fotografija", "favorites": "Omiljene", @@ -744,14 +738,12 @@ "fix_incorrect_match": "Ispravite netočno podudaranje", "folders": "Mape", "folders_feature_description": "Pregledavanje prikaza mape za fotografije i videozapise u sustavu datoteka", - "force_re-scan_library_files": "Prisilno ponovno skeniraj sve datoteke biblioteke", "forward": "Naprijed", "general": "Općenito", "get_help": "Potražite pomoć", "getting_started": "Početak Rada", "go_back": "Idi natrag", "go_to_search": "Idi na pretragu", - "go_to_share_page": "", "group_albums_by": "Grupiraj albume po...", "group_no": "Nema grupiranja", "group_owner": "Grupiraj po vlasniku", @@ -800,6 +792,8 @@ "jobs": "Poslovi", "keep": "Zadrži", "keep_all": "Zadrži Sve", + "keep_this_delete_others": "Zadrži ovo, izbriši ostale", + "kept_this_deleted_others": "Zadržana je ova datoteka i izbrisano {count, plural, one {# datoteka} other {# datoteka}}", "keyboard_shortcuts": "Prečaci tipkovnice", "language": "Jezik", "language_setting_description": "Odaberite željeni jezik", @@ -832,6 +826,7 @@ "look": "Izgled", "loop_videos": "Ponavljajte videozapise", "loop_videos_description": "Omogućite automatsko ponavljanje videozapisa u pregledniku detalja.", + "main_branch_warning": "Koristite razvojnu verziju; strogo preporučamo korištenje izdane verzije!", "make": "Proizvođač", "manage_shared_links": "Upravljanje dijeljenim vezama", "manage_sharing_with_partners": "Upravljajte dijeljenjem s partnerima", @@ -901,6 +896,7 @@ "notifications": "Obavijesti", "notifications_setting_description": "Upravljanje obavijestima", "oauth": "OAuth", + "official_immich_resources": "Službeni Immich resursi", "offline": "Izvan mreže", "offline_paths": "Izvanmrežne putanje", "offline_paths_description": "Ovi rezultati mogu biti posljedica ručnog brisanja datoteka koje nisu dio vanjske biblioteke.", @@ -913,7 +909,6 @@ "onboarding_welcome_user": "Dobro došli, {user}", "online": "Dostupan (Online)", "only_favorites": "Samo omiljeno", - "only_refreshes_modified_files": "Osvježava samo izmijenjene datoteke", "open_in_map_view": "Otvori u prikazu karte", "open_in_openstreetmap": "Otvori u OpenStreetMap", "open_the_search_filters": "Otvorite filtre pretraživanja", @@ -1030,11 +1025,13 @@ "recent_searches": "Nedavne pretrage", "refresh": "Osvježi", "refresh_encoded_videos": "Osvježite kodirane videozapise", + "refresh_faces": "Osvježite lica", "refresh_metadata": "Osvježi metapodatke", "refresh_thumbnails": "Osvježi sličice", "refreshed": "Osvježeno", "refreshes_every_file": "Osvježava svaku datoteku", "refreshing_encoded_video": "Osvježavanje kodiranog videa", + "refreshing_faces": "Osvježavanje lica", "refreshing_metadata": "Osvježavanje metapodataka", "regenerating_thumbnails": "Obnavljanje sličica", "remove": "Ukloni", @@ -1042,7 +1039,7 @@ "remove_assets_shared_link_confirmation": "Jeste li sigurni da želite ukloniti {count, plural, one {# datoteku} other {# datoteke}} iz ove dijeljene veze?", "remove_assets_title": "Ukloniti datoteke?", "remove_custom_date_range": "Ukloni prilagođeni datumski raspon", - "remove_deleted_assets": "", + "remove_deleted_assets": "Ukloni izbrisana sredstva", "remove_from_album": "Ukloni iz albuma", "remove_from_favorites": "Ukloni iz favorita", "remove_from_shared_link": "Ukloni iz dijeljene poveznice", @@ -1081,8 +1078,7 @@ "saved_settings": "Spremljene postavke", "say_something": "Reci nešto", "scan_all_libraries": "Skeniraj sve Knjižnice", - "scan_all_library_files": "Ponovno skenirajte sve datoteke Knjižnice", - "scan_new_library_files": "Skeniraj nove datoteke Knjižnice", + "scan_library": "Skeniraj", "scan_settings": "Postavke skeniranja", "scanning_for_album": "Skeniranje albuma...", "search": "Pretraživanje", @@ -1101,50 +1097,58 @@ "search_people": "Traži ljude", "search_places": "Traži mjesta", "search_settings": "Postavke pretraživanja", - "search_state": "", - "search_timezone": "", - "search_type": "", - "search_your_photos": "", - "searching_locales": "", - "second": "", - "select_album_cover": "", - "select_all": "", + "search_state": "Država pretraživanja...", + "search_tags": "Traži oznake...", + "search_timezone": "Pretraži vremenske zone", + "search_type": "Vrsta pretraživanja", + "search_your_photos": "Pretražite svoje fotografije", + "searching_locales": "Traženje lokaliteta...", + "second": "Drugi", + "see_all_people": "Vidi sve ljude", + "select_album_cover": "Odaberite omot albuma", + "select_all": "Odaberi sve", + "select_all_duplicates": "Odaberi sve duplikate", "select_avatar_color": "", - "select_face": "", + "select_face": "Odaberi lice", "select_featured_photo": "", "select_keep_all": "", "select_library_owner": "", "select_new_face": "", "select_photos": "", "select_trash_all": "", - "selected": "", + "selected": "Odabrano", "send_message": "", - "send_welcome_email": "", - "server": "", - "server_stats": "", - "set": "", + "send_welcome_email": "Pošalji email dobrodošlice", + "server_offline": "Server izvan mreže", + "server_online": "Server na mreži", + "server_stats": "Statistike servera", + "server_version": "Verzija servera", + "set": "Postavi", "set_as_album_cover": "", - "set_as_profile_picture": "", - "set_date_of_birth": "", - "set_profile_picture": "", + "set_as_profile_picture": "Postavi kao profilnu sliku", + "set_date_of_birth": "Postavi datum rođenja", + "set_profile_picture": "Postavi profilnu sliku", "set_slideshow_to_fullscreen": "", - "settings": "", - "settings_saved": "", - "share": "", - "shared": "", - "shared_by": "", - "shared_by_you": "", - "shared_from_partner": "", + "settings": "Postavke", + "settings_saved": "Postavke su spremljene", + "share": "Podijeli", + "shared": "Podijeljeno", + "shared_by": "Podijelio", + "shared_by_user": "Podijelio {user}", + "shared_by_you": "Podijelili vi", + "shared_from_partner": "Fotografije od {partner}", "shared_links": "", "shared_with_partner": "", "sharing": "", "sharing_sidebar_description": "", "show_album_options": "", - "show_and_hide_people": "", - "show_file_location": "", - "show_gallery": "", - "show_hidden_people": "", - "show_in_timeline": "", + "show_albums": "Prikaži albume", + "show_all_people": "Prikaži sve osobe", + "show_and_hide_people": "Prikaži i sakrij osobe", + "show_file_location": "Pokaži mjesto datoteke", + "show_gallery": "Prikaži galeriju", + "show_hidden_people": "Prikaži skrivene osobe", + "show_in_timeline": "Prikaži na vremenskoj crti", "show_in_timeline_setting_description": "", "show_keyboard_shortcuts": "", "show_metadata": "", @@ -1194,7 +1198,6 @@ "to_trash": "Smeće", "toggle_settings": "Uključi/isključi postavke", "toggle_theme": "Promjeni temu", - "toggle_visibility": "", "total_usage": "Ukupna upotreba", "trash": "Smeće", "trash_all": "Stavi sve u smeće", @@ -1202,11 +1205,9 @@ "trashed_items_will_be_permanently_deleted_after": "Stavke bačene u smeće trajno će se izbrisati nakon {days, plural, one {# day} other {# days}}.", "type": "Vrsta", "unarchive": "", - "unarchived": "", "unfavorite": "", "unhide_person": "", "unknown": "", - "unknown_album": "", "unknown_year": "", "unlimited": "", "unlink_oauth": "", @@ -1224,6 +1225,8 @@ "user": "", "user_id": "", "user_usage_detail": "", + "user_usage_stats": "Statistika korištenja računa", + "user_usage_stats_description": "Pregledajte statistiku korištenja računa", "username": "", "users": "", "utilities": "", @@ -1240,7 +1243,6 @@ "view_links": "", "view_next_asset": "", "view_previous_asset": "", - "viewer": "", "waiting": "", "week": "", "welcome_to_immich": "", diff --git a/i18n/hu.json b/i18n/hu.json index 4bde75b5ef7fa..b6e9617993ac0 100644 --- a/i18n/hu.json +++ b/i18n/hu.json @@ -1,5 +1,5 @@ { - "about": "Névjegy", + "about": "Frissítés", "account": "Fiók", "account_settings": "Fiók Beállítások", "acknowledge": "Megértettem", @@ -23,6 +23,7 @@ "add_to": "Hozzáadás ide...", "add_to_album": "Felvétel albumba", "add_to_shared_album": "Felvétel megosztott albumba", + "add_url": "URL hozzáadása", "added_to_archive": "Hozzáadva az archívumhoz", "added_to_favorites": "Hozzáadva a kedvencekhez", "added_to_favorites_count": "{count, number} hozzáadva a kedvencekhez", @@ -34,6 +35,11 @@ "authentication_settings_disable_all": "Biztosan letiltod az összes bejelentkezési módot? A bejelentkezés teljesen le lesz tiltva.", "authentication_settings_reenable": "Az újbóli engedélyezéshez használj egySzerver Parancsot.", "background_task_job": "Háttérfeladatok", + "backup_database": "Tartalék Adatbázis", + "backup_database_enable_description": "Adatbázis biztonsági mentések engedélyezése", + "backup_keep_last_amount": "Megőrizendő korábbi biztonsági mentések száma", + "backup_settings": "Biztonsági mentés beállításai", + "backup_settings_description": "Adatbázis mentési beállításainak kezelése", "check_all": "Összes Kipiálása", "cleared_jobs": "{job}: feladatai törölve", "config_set_by_file": "A konfigurációt jelenleg egy konfigurációs fájl állítja be", @@ -43,9 +49,10 @@ "confirm_reprocess_all_faces": "Biztos vagy benne, hogy újra fel szeretnéd dolgozni az összes arcot? Ez a már elnevezett személyeket is törli.", "confirm_user_password_reset": "Biztosan vissza szeretnéd állítani {user} jelszavát?", "create_job": "Feladat létrehozása", - "crontab_guru": "Crontab Guru", + "cron_expression": "Cron kifejezés", + "cron_expression_description": "A beolvasási időköz beállítása a cron formátummal. További információért lásd pl. Crontab Guru", + "cron_expression_presets": "Cron kifejezés előbeállítások", "disable_login": "Belépés letiltása", - "disabled": "Letiltva", "duplicate_detection_job_description": "Gépi tanulás futtatása a hasonló elemek megtalálása céljából. Ez az Okos Keresés funkciót használja", "exclusion_pattern_description": "A kihagyási minták (pattern) használatakor a mintának megfelelő fájlok vagy mappák át lesznek ugorva a képtár átfésülésekor. Akkor hasznos, ha a mappákban vannak olyan fájlok is, amelyeket nem szeretnél importálni, pl. nyers (RAW) fájlok.", "external_library_created_at": "Külső képtár (létrehozva: {date})", @@ -63,22 +70,15 @@ "image_prefer_wide_gamut": "Széles színtér preferálása", "image_prefer_wide_gamut_setting_description": "A bélyegképekhez DCI-P3 színtér használata. Ez a széles színteret használó képek esetén (pl: Adobe RGB, P3) jobban megőrzi az élénkebb színeket, de régebbi eszközökön vagy böngészőkben a kép színei másképpen jelenhetnek meg. Az sRGB képek a színeltolódások megelőzése érdekében nem változnak.", "image_preview_description": "Közepes méretű kép eltávolított metaadatokkal, egy képes nézethez és a gépi tanuláshoz", - "image_preview_format": "Előnézet formátuma", "image_preview_quality_description": "Előnézet minősége 1-100 között. A magasabb szám jobb minőséget, de nagyobb fájlokat eredményez és belassíthatja az alkalmazást. Túl alacsony érték befolyásolhatja a gépi tanulás pontosságát.", - "image_preview_resolution": "Előnézet felbontása", - "image_preview_resolution_description": "Fotó egyedüli nézetéhez használatos beállítás, valamint a gépi tanulás is ezt használja. Nagyobb felbontás több részletet megőriz, de tovább tart a folyamat, nagyobb fájl méretet eredményez, és befolyásolhatja az alkalmazás reakcióidejét.", "image_preview_title": "Előnézet Beállításai", "image_quality": "Minőség", - "image_quality_description": "Képminőség 1 és 100 között. A nagyobb érték jobb minőséget, de nagyobb fájlt eredményez. Ez a beállítás az Előnézeti képre és a Bélyegképre vonatkozik.", "image_resolution": "Felbontás", "image_resolution_description": "A nagyobb felbontás több részletet őriz meg, de lassabb létrehozni, nagyobb fájlt eredményez és belassíthatja az alkalmazást.", "image_settings": "Képbeállítások", "image_settings_description": "A létrehozott képek minőségi és felbontási beállításainak kezelése", "image_thumbnail_description": "Kicsi bélyegkép eltávolított metaadatokkal, sok kis kép (pl idővonal) megjelenítéséhez", - "image_thumbnail_format": "Bélyegkép formátum", "image_thumbnail_quality_description": "Bélyegkép minősége 1-100 között. A magasabb szám jobb minőséget, de nagyobb fájlméretet eredményez és belassíthatja az alkalmazást.", - "image_thumbnail_resolution": "Bélyegkép felbontás", - "image_thumbnail_resolution_description": "Képek csoportosított nézetekor használatos (idővonal, album nézet stb). Nagyobb felbontás esetén a kép részletgazdagabb marad, de tovább tart elkészíteni, nagyobb fájl méretet eredményes, és ronthatja az alkalmazás reagálását.", "image_thumbnail_title": "Bélyegkép Beállítások", "job_concurrency": "{job} párhuzamosság", "job_created": "Feladat létrehozva", @@ -89,9 +89,6 @@ "jobs_delayed": "{jobCount, plural, other {# késik}}", "jobs_failed": "{jobCount, plural, other {# sikertelen}}", "library_created": "Képtár létrehozva: {library}", - "library_cron_expression": "Cron kifejezés", - "library_cron_expression_description": "Átfésülések közötti intervallum beállítása cron formátumban. Több információt találhatsz például itt: Crontab Guru", - "library_cron_expression_presets": "Cron kifejezés sablonok", "library_deleted": "Képtár törölve", "library_import_path_description": "Add meg az importálandó mappát. A rendszer ebben a mappában és összes almappájában fog képeket és videókat keresni.", "library_scanning": "Időszakos Átfésülés", @@ -134,7 +131,7 @@ "machine_learning_smart_search_description": "Képek szemantikai keresése CLIP beágyazások segítségével", "machine_learning_smart_search_enabled": "Okos keresés engedélyezése", "machine_learning_smart_search_enabled_description": "Ha ki van kapcsolva, a képek nem lesznek átalakítva okos kereséshez.", - "machine_learning_url_description": "Gépi tanulás szerver URL címe", + "machine_learning_url_description": "Gépi tanulás szerver URL címe. Ha többi, mint egy URL van megadva, mindegyik szervert egyenként próbálja meg, amíg az egyik sikeresen nem válaszol, sorrendben az elsőtől az utólsóig.", "manage_concurrency": "Párhuzamos Feladatok Kezelése", "manage_log_settings": "Naplózási beállítások kezelése", "map_dark_style": "Sötét stílus", @@ -215,7 +212,6 @@ "refreshing_all_libraries": "Összes képtár frissítése", "registration": "Admin Regisztráció", "registration_description": "Mivel ez az első felhasználó a rendszerben, ezért te leszel az Admin, aki az adminisztratív teendőkért felelős és további felhasználókat tud létrehozni.", - "removing_deleted_files": "Offline Fájlok eltávolítása", "repair_all": "Összes Javítása", "repair_matched_items": "{count, plural, one {# egyezés} other {# egyezés}}", "repaired_items": "Javítva {count, plural, one {# fájl} other {# fájl}}", @@ -223,12 +219,12 @@ "reset_settings_to_default": "Beállítások visszaállítása az alapértelmezettre", "reset_settings_to_recent_saved": "Beállítások visszaállítása a legutóbb mentettre", "scanning_library": "Képtár átfésülése", - "scanning_library_for_changed_files": "Képtár átfésülése megváltozott fájlok után", - "scanning_library_for_new_files": "Képtár átfésülése új fájlok után", "search_jobs": "Feladatok keresése...", "send_welcome_email": "Üdvözlő email küldése", "server_external_domain_settings": "Külső domain", "server_external_domain_settings_description": "Nyilvánosan megosztott linkek domainje (http(s)://-sel)", + "server_public_users": "Nyilvános felhasználók", + "server_public_users_description": "Az összes felhasználó (név és email) ki van írva, amikor egy felhasználót adsz hozzá egy megosztott albumhoz. Amikor le van tiltva, a felhasználólista csak adminok számára lesz elérhető.", "server_settings": "Szerver Beállítások", "server_settings_description": "Szerver beállítások kezelése", "server_welcome_message": "Üdvözlő üzenet", @@ -254,6 +250,16 @@ "storage_template_user_label": "A felhasználó Tárhely Címkéje {label}", "system_settings": "Rendszerbeállítások", "tag_cleanup_job": "Címkék kipucolása", + "template_email_available_tags": "Használthatod a következő változókat a sablonodban: {tags}", + "template_email_if_empty": "Ha a sablon üres, akkor az alapértelmezett email lesz használva.", + "template_email_invite_album": "Album meghívás sablon", + "template_email_preview": "Előnézet", + "template_email_settings": "Email sablonok", + "template_email_settings_description": "Saját email értesítések kezelése", + "template_email_update_album": "Album frissítve sablon", + "template_email_welcome": "Üdvözlő email sablon", + "template_settings": "Értesítés sablon", + "template_settings_description": "Egyéni sablonok kezelése az értesítésekhez.", "theme_custom_css_settings": "Egyedi CSS", "theme_custom_css_settings_description": "CSS Stíluslapokkal az Immich stílusa megváltoztatható.", "theme_settings": "Téma Beállítások", @@ -261,7 +267,6 @@ "these_files_matched_by_checksum": "Ezek a fájlok egyeznek az ellenőrző összegük alapján", "thumbnail_generation_job": "Bélyegképek Generálása", "thumbnail_generation_job_description": "Nagy, kicsi és elmosódott bélyegképek létrehozása minden elemhez, valamint bélyegképek generálása minden személyhez", - "transcode_policy_description": "", "transcoding_acceleration_api": "Gyorsító API", "transcoding_acceleration_api_description": "Az átkódolás felgyorsításához használt eszközödhöz tartozó API. Ez a beállítás „legtöbb, amit megtehetünk” alapon működik: probléma esetén visszaáll szoftveres átkódolásra. A VP9 a hardvertől függően vagy működik, vagy nem.", "transcoding_acceleration_nvenc": "NVENC (NVIDIA GPU-t igényel)", @@ -312,9 +317,7 @@ "transcoding_threads": "Folyamatok száma", "transcoding_threads_description": "Magas értékek esetén gyorsabban kódol, viszont kevesebb erőforrást hagy a szerver többi folyamatának. Nem ajánlott a CPU magjainak számánál nagyobb érték beállítása. A 0 érték maximalizálja a processzor kihasználását.", "transcoding_tone_mapping": "Tónusleképezés (tone-mapping)", - "transcoding_tone_mapping_description": "Megpróbálja megőrizni a HDR videók kinézetét SDR-re való konvertálás során. Minden algoritmus különböző módon tesz kompromisszumot a színek, részletek, és a fényerő megőrzésében. A Hable inkább a részletek őrzi meg, a Mobius a színeket, a Reinhard pedig a fényerőt.", - "transcoding_tone_mapping_npl": "Tónusleképezés NPL", - "transcoding_tone_mapping_npl_description": "A színek úgy lesznek beállítva, hogy ezen a fényerőn lévő kijelzőn nézzenek ki jól. Alacsonyabb értékek esetén világosabb videót készít, és magasabb értékek esetén sötétebbet, mivel a kijelző fényerejéhez kompenzál. 0 esetén a szoftver magának állítja be az értéket.", + "transcoding_tone_mapping_description": "Megpróbálja megőrizni a HDR videók kinézetét SDR-re való konvertálás során. Minden algoritmus különböző módon tesz kompromisszumot a színek, részletek, és a fényerő megőrzésében. A Hable inkább a részleteket őrzi meg, a Mobius a színeket, a Reinhard pedig a fényerőt.", "transcoding_transcode_policy": "Átkódolási szabályzat", "transcoding_transcode_policy_description": "Videó átkódolási szabályzat . HDR videók mindig átkódolásra kerülnek (kivéve, ha az átkódolás ki van kapcsolva).", "transcoding_two_pass_encoding": "Átkódolás két menetben", @@ -395,7 +398,6 @@ "archive_or_unarchive_photo": "Fotó archiválása vagy archiválásának visszavonása", "archive_size": "Archívum mérete", "archive_size_description": "Beállítja letöltésnél az archívum méretét (GiB)", - "archived": "Archíválva", "archived_count": "{count, plural, other {Archiválva #}}", "are_these_the_same_person": "Ugyanaz a személy?", "are_you_sure_to_do_this": "Biztosan ezt szeretnéd csinálni?", @@ -416,7 +418,6 @@ "assets_added_to_album_count": "{count, plural, other {# elem}} hozzáadva az albumhoz", "assets_added_to_name_count": "{count, plural, other {# elem}} hozzáadva {hasName, select, true {a(z) {name}} other {az új}} albumhoz", "assets_count": "{count, plural, other {# elem}}", - "assets_moved_to_trash": "{count, plural, one {# fájl} other {# fájl}} a lomtárba mozgatva", "assets_moved_to_trash_count": "{count, plural, other {# elem}} áthelyezve a lomtárba", "assets_permanently_deleted_count": "{count, plural, other {# elem}} véglegesen törölve", "assets_removed_count": "{count, plural, other {# elem}} eltávolítva", @@ -446,10 +447,6 @@ "cannot_merge_people": "Személyek összevonása nem sikerült", "cannot_undo_this_action": "Ez a művelet nem visszavonható!", "cannot_update_the_description": "A leírás megváltoztatása nem sikerült", - "cant_apply_changes": "A változtatások nem alkalmazhatóak", - "cant_get_faces": "Az arcok nem elérhetőek", - "cant_search_people": "", - "cant_search_places": "A helyek nem kereshetőek", "change_date": "Dátum változtatása", "change_expiration_time": "Lejárati idő megváltoztatása", "change_location": "Helyszín változtatása", @@ -481,6 +478,7 @@ "confirm": "Jóváhagy", "confirm_admin_password": "Admin Jelszó Újból", "confirm_delete_shared_link": "Biztosan törölni szeretnéd ezt a megosztott linket?", + "confirm_keep_this_delete_others": "Minden más elem a készletben törlésre kerül, kivéve ezt az elemet. Biztosan folytatni szeretnéd?", "confirm_password": "Jelszó megerősítése", "contain": "Belül", "context": "Kontextus", @@ -530,6 +528,7 @@ "delete_key": "Kulcs törlése", "delete_library": "Képtár Törlése", "delete_link": "Link törlése", + "delete_others": "Többi törlése", "delete_shared_link": "Megosztott link törlése", "delete_tag": "Címke törlése", "delete_tag_confirmation_prompt": "Biztosan törölni szeretnéd a(z) {tagName} címkét?", @@ -563,13 +562,6 @@ "duplicates": "Duplikátumok", "duplicates_description": "Jelöld meg a duplikátumokat (ha léteznek) a csoportokban", "duration": "Időtartam", - "durations": { - "days": "{days, plural, one {nap} other {{days, number} nap}}", - "hours": "{hours, plural, one {óra} other {{hours, number} óra}}", - "minutes": "{minutes, plural, one {perc} other {{minutes, number} perc}}", - "months": "{months, plural, one {hónap} other {{months, number} hónap}}", - "years": "{years, plural, one {év} other {{years, number} év}}" - }, "edit": "Szerkesztés", "edit_album": "Album módosítása", "edit_avatar": "Profilkép módosítása", @@ -594,8 +586,6 @@ "editor_crop_tool_h2_aspect_ratios": "Oldalarányok", "editor_crop_tool_h2_rotation": "Forgatás", "email": "Email", - "empty": "", - "empty_album": "Üres Album", "empty_trash": "Lomtár ürítése", "empty_trash_confirmation": "Biztosan kiüríted a lomtárat? Ez az Immich lomtárában lévő összes elemet véglegesen törli.\nEz a művelet nem visszavonható!", "enable": "Engedélyezés", @@ -629,6 +619,7 @@ "failed_to_create_shared_link": "Megosztott link készítése sikertelen", "failed_to_edit_shared_link": "Megosztott link módosítása sikertelen", "failed_to_get_people": "Személyek lekérdezése sikertelen", + "failed_to_keep_this_delete_others": "Nem sikerült megtartani ezt az elemet, és a többi elemet törölni", "failed_to_load_asset": "Elem betöltése sikertelen", "failed_to_load_assets": "Elemek betöltése sikertelen", "failed_to_load_people": "Személyek betöltése sikertelen", @@ -656,8 +647,6 @@ "unable_to_change_location": "Hely megváltoztatása sikertelen", "unable_to_change_password": "Jelszó megváltoztatása sikertelen", "unable_to_change_visibility": "{count, plural, other {# személy}} láthatóságának megváltoztatása sikertelen", - "unable_to_check_item": "", - "unable_to_check_items": "", "unable_to_complete_oauth_login": "OAuth bejelentkezés befejezése sikertelen", "unable_to_connect": "Csatlakozás sikertelen", "unable_to_connect_to_server": "Szerverhez csatlakozás sikertelen", @@ -698,12 +687,10 @@ "unable_to_remove_album_users": "Felhasználó eltávolítása az albumból sikertelen", "unable_to_remove_api_key": "API kulcs eltávolítása sikertelen", "unable_to_remove_assets_from_shared_link": "Elemek eltávolítása a megosztott linkből sikertelen", - "unable_to_remove_comment": "", "unable_to_remove_deleted_assets": "Offline fájlok eltávolítása sikertelen", "unable_to_remove_library": "Képtár eltávolítása sikertelen", "unable_to_remove_partner": "Partner eltávolítása sikertelen", "unable_to_remove_reaction": "Reakció eltávolítása sikertelen", - "unable_to_remove_user": "", "unable_to_repair_items": "Elemek javítása sikertelen", "unable_to_reset_password": "Jelszó visszaállítása sikertelen", "unable_to_resolve_duplicate": "Duplikátum feloldása sikertelen", @@ -733,10 +720,6 @@ "unable_to_update_user": "Felhasználó módosítása sikertelen", "unable_to_upload_file": "Fájlfeltöltés sikertelen" }, - "every_day_at_onepm": "", - "every_night_at_midnight": "", - "every_night_at_twoam": "", - "every_six_hours": "", "exif": "Exif", "exit_slideshow": "Kilépés a Diavetítésből", "expand_all": "Összes kinyitása", @@ -751,38 +734,33 @@ "external": "Külső Képtár", "external_libraries": "Külső Képtárak", "face_unassigned": "Nincs hozzárendelve", - "failed_to_get_people": "Személyek lekérése sikertelen", + "failed_to_load_assets": "Nem sikerült betölteni az elemeket", "favorite": "Kedvenc", "favorite_or_unfavorite_photo": "Fotó kedvencnek jelölése vagy annak visszavonása", "favorites": "Kedvencek", - "feature": "", "feature_photo_updated": "Címlapkép frissítve", - "featurecollection": "", "features": "Jellemzők", "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", "filename": "Fájlnév", - "files": "", "filetype": "Fájltípus", "filter_people": "Személyek szűrése", "find_them_fast": "Név alapján kereséssel gyorsan megtalálhatóak", "fix_incorrect_match": "Hibás találat javítása", "folders": "Mappák", "folders_feature_description": "A fájlrendszerben lévő fényképek és videók mappanézetben való böngészése", - "force_re-scan_library_files": "Az összes Képtár fájl újbóli átfésülésének indítása", "forward": "Előre", "general": "Általános", "get_help": "Segítségkérés", "getting_started": "Kezdő Lépések", "go_back": "Visszalépés", "go_to_search": "Ugrás a kereséshez", - "go_to_share_page": "Ugrás a megosztás oldalhoz", "group_albums_by": "Albumok csoportosítása...", "group_no": "Nincs csoportosítás", "group_owner": "Csoportosítás tulajdonos szerint", "group_year": "Csoportosítás év szerint", - "has_quota": "Van kvótája", + "has_quota": "Kvóta", "hi_user": "Szia {name} ({email})", "hide_all_people": "Minden személy elrejtése", "hide_gallery": "Galéria elrejtése", @@ -803,7 +781,6 @@ "image_alt_text_date_place_2_people": "{isVideo, select, true {Videó} other {Kép}} itt: {country}, {city}, velük: {person1} és {person2} (készült: {date})", "image_alt_text_date_place_3_people": "{isVideo, select, true {Videó} other {Kép}} itt: {country}, {city}, velük: {person1}, {person2} és {person3} (készült: {date})", "image_alt_text_date_place_4_or_more_people": "{isVideo, select, true {Videó} other {Kép}} itt: {country}, {city}, velük: {person1}, {person2} és további {additionalCount, number} személy (készült: {date})", - "img": "", "immich_logo": "Immich Logó", "immich_web_interface": "Immich Webes Felület", "import_from_json": "Importálás JSON formátumból", @@ -824,10 +801,11 @@ "invite_people": "Személyek Meghívása", "invite_to_album": "Meghívás az albumba", "items_count": "{count, plural, other {# elem}}", - "job_settings_description": "", "jobs": "Feladatok", "keep": "Megtart", "keep_all": "Összeset Megtart", + "keep_this_delete_others": "Ennek a meghagyása, a többi törlése", + "kept_this_deleted_others": "Ez az elem és a töröltek meg lettek hagyva {count, plural, one {# asset} other {# assets}}", "keyboard_shortcuts": "Billentyűparancsok", "language": "Nyelv", "language_setting_description": "Válaszd ki preferált nyelvet", @@ -943,7 +921,6 @@ "onboarding_welcome_user": "Üdvözöllek {user}", "online": "Online", "only_favorites": "Csak kedvencek", - "only_refreshes_modified_files": "Csak a megváltoztatott fájlokat frissíti", "open_in_map_view": "Megnyitás térkép nézetben", "open_in_openstreetmap": "Megnyitás OpenStreetMap-ben", "open_the_search_filters": "Keresési szűrők megnyitása", @@ -981,7 +958,6 @@ "people_edits_count": "{count, plural, other {# személy}} módosítva", "people_feature_description": "Személyek szerint csoportosított fényképek és videók böngészése", "people_sidebar_description": "Személyek link megjelenítése az oldalsávban", - "perform_library_tasks": "", "permanent_deletion_warning": "Figyelmeztetés végleges törlésről", "permanent_deletion_warning_setting_description": "Figyelmeztessen elemek végleges törlése előtt", "permanently_delete": "Végleges törlés", @@ -1003,7 +979,6 @@ "play_memories": "Emlékek lejátszása", "play_motion_photo": "Mozgókép lejátszása", "play_or_pause_video": "Videó elindítása vagy megállítása", - "point": "", "port": "Port", "preset": "Sablon", "preview": "Előnézet", @@ -1048,12 +1023,10 @@ "purchase_server_description_2": "Támogató státusz", "purchase_server_title": "Szerver", "purchase_settings_server_activated": "A szerver termékkulcsot az admin kezeli", - "range": "", "rating": "Értékelés csillagokkal", "rating_clear": "Értékelés törlése", "rating_count": "{count, plural, one {# csillag} other {# csillag}}", "rating_description": "Exif értékelés megjelenítése az infópanelen", - "raw": "", "reaction_options": "Reakció lehetőségek", "read_changelog": "Változásnapló Elolvasása", "reassign": "Hozzárendel", @@ -1061,6 +1034,7 @@ "reassigned_assets_to_new_person": "{count, plural, other {# elem}} hozzárendelve egy új személyhez", "reassing_hint": "Kijelölt elemek létező személyhez rendelése", "recent": "Friss", + "recent-albums": "Legutóbbi albumok", "recent_searches": "Legutóbbi keresések", "refresh": "Frissítés", "refresh_encoded_videos": "Átkódolt videók frissítése", @@ -1082,6 +1056,7 @@ "remove_from_album": "Eltávolítás az albumból", "remove_from_favorites": "Eltávolítás a kedvencekből", "remove_from_shared_link": "Eltávolítás a megosztott linkből", + "remove_url": "URL eltávolítása", "remove_user": "Felhasználó eltávolítása", "removed_api_key": "API Kulcs eltávolítva: {name}", "removed_from_archive": "Archívumból eltávolítva", @@ -1098,7 +1073,6 @@ "reset": "Visszaállítás", "reset_password": "Jelszó visszaállítása", "reset_people_visibility": "Személyek láthatóságának visszaállítása", - "reset_settings_to_default": "", "reset_to_default": "Visszaállítás alapállapotba", "resolve_duplicates": "Duplikátumok feloldása", "resolved_all_duplicates": "Minden duplikátum feloldása", @@ -1118,9 +1092,7 @@ "saved_settings": "Elmentett beállítások", "say_something": "Szólj hozzá", "scan_all_libraries": "Minden Képtár Átfésülése", - "scan_all_library_files": "Minden könyvtárbeli elem újraellenőrzése", "scan_library": "Átfésülés", - "scan_new_library_files": "Ellenőrzés új könyvtárbeli elemekért", "scan_settings": "Átfésülési Beállítások", "scanning_for_album": "Albumok átfésülése...", "search": "Keresés", @@ -1163,7 +1135,6 @@ "selected_count": "{count, plural, other {# kiválasztva}}", "send_message": "Üzenet küldése", "send_welcome_email": "Üdvözlő email küldése", - "server": "Szerver", "server_offline": "Szerver Nem Elérhető", "server_online": "Szerver Elérhető", "server_stats": "Szerver Statisztikák", @@ -1213,7 +1184,7 @@ "sidebar": "Oldalsáv", "sidebar_display_description": "Nézet link megjelenítése az oldalsávban", "sign_out": "Kijelentkezés", - "sign_up": "Feliratkozás", + "sign_up": "Regisztráció", "size": "Méret", "skip_to_content": "Ugrás a tartalomhoz", "skip_to_folders": "Ugrás a mappákhoz", @@ -1268,6 +1239,7 @@ "they_will_be_merged_together": "Egyesítve lesznek", "third_party_resources": "Harmadik Féltől Származó Források", "time_based_memories": "Emlékek idő alapján", + "timeline": "Idővonal", "timezone": "Időzóna", "to_archive": "Archiválás", "to_change_password": "Jelszó megváltoztatása", @@ -1277,7 +1249,7 @@ "to_trash": "Lomtárba helyezés", "toggle_settings": "Beállítások átállítása", "toggle_theme": "Sötét téma átváltása", - "toggle_visibility": "Láthatóság változtatása", + "total": "Összesen", "total_usage": "Összesen használatban", "trash": "Lomtár", "trash_all": "Mindet lomtárba", @@ -1287,12 +1259,10 @@ "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.", "type": "Típus", "unarchive": "Archívumból kivesz", - "unarchived": "Archívumból kivett", "unarchived_count": "{count, plural, other {# elem kivéve az archívumból}}", "unfavorite": "Kedvenc közül kivesz", "unhide_person": "Nem rejtett személy", "unknown": "Ismeretlen", - "unknown_album": "Ismeretlen Album", "unknown_year": "Ismeretlen Év", "unlimited": "Korlátlan", "unlink_motion_video": "Mozgókép leválasztása", @@ -1329,6 +1299,8 @@ "user_purchase_settings_description": "Vásárlás kezelése", "user_role_set": "{user} felhasználónak {role} jogkör biztosítása", "user_usage_detail": "Felhasználó használati adatai", + "user_usage_stats": "Fiók használati statisztikái", + "user_usage_stats_description": "Fiók használati statisztikáinak megtekintése", "username": "Felhasználónév", "users": "Felhasználók", "utilities": "Segédeszközök", @@ -1336,7 +1308,7 @@ "variables": "Változók", "version": "Verzió", "version_announcement_closing": "Barátsággal, Alex", - "version_announcement_message": "Szia barátom, az alkalmazásnak van egy új verziója. Kérjük, szánj időt a kiadási megjegyzések áttekintésére, és győződj meg róla, hogy a docker-compose.yml és az .env beállításaid naprakészek, hogy elkerüld a hibás konfigurációkat, különösen, ha a WatchTower-t vagy bármilyen automatikus frissítési megoldást használsz.", + "version_announcement_message": "Szia! Az Immich-nek elérhető egy új verziója. Kérjük, szánj időt a verzióinformáció elolvasására, hogy meggyőződj róla, hogy a beállításaid naprakészek, így elkerülj egy esetleges félrekonfigurálást. Különösen, ha WatchTower-t vagy más automatikus frissítési megoldást használsz.", "version_history": "Verziótörténet", "version_history_item": "{version} telepítve: {date}", "video": "Videó", @@ -1350,10 +1322,10 @@ "view_all_users": "Minden Felhasználó Megtekintése", "view_in_timeline": "Megtekintés az idővonalon", "view_links": "Linkek megtekintése", + "view_name": "Megtekintés", "view_next_asset": "Következő elem megtekintése", "view_previous_asset": "Előző elem megtekintése", "view_stack": "Csoport Megtekintése", - "viewer": "", "visibility_changed": "{count, plural, other {# személy}} láthatósága megváltozott", "waiting": "Várakozás", "warning": "Figyelmeztetés", diff --git a/i18n/hy.json b/i18n/hy.json index 57651d0063518..a0ebff369c0ee 100644 --- a/i18n/hy.json +++ b/i18n/hy.json @@ -33,7 +33,6 @@ "confirm_email_below": "", "confirm_reprocess_all_faces": "", "confirm_user_password_reset": "", - "crontab_guru": "", "disable_login": "", "duplicate_detection_job_description": "", "exclusion_pattern_description": "", @@ -49,16 +48,9 @@ "image_prefer_embedded_preview_setting_description": "", "image_prefer_wide_gamut": "", "image_prefer_wide_gamut_setting_description": "", - "image_preview_format": "", - "image_preview_resolution": "", - "image_preview_resolution_description": "", "image_quality": "", - "image_quality_description": "", "image_settings": "", "image_settings_description": "", - "image_thumbnail_format": "", - "image_thumbnail_resolution": "", - "image_thumbnail_resolution_description": "", "job_concurrency": "", "job_not_concurrency_safe": "", "job_settings": "", @@ -67,8 +59,6 @@ "jobs_delayed": "", "jobs_failed": "", "library_created": "", - "library_cron_expression": "", - "library_cron_expression_presets": "", "library_deleted": "", "library_import_path_description": "", "library_scanning": "", @@ -172,15 +162,12 @@ "paths_validated_successfully": "", "quota_size_gib": "", "refreshing_all_libraries": "", - "removing_deleted_files": "", "repair_all": "", "repair_matched_items": "", "repaired_items": "", "require_password_change_on_login": "", "reset_settings_to_default": "", "reset_settings_to_recent_saved": "", - "scanning_library_for_changed_files": "", - "scanning_library_for_new_files": "", "send_welcome_email": "", "server_external_domain_settings": "", "server_external_domain_settings_description": "", @@ -255,8 +242,6 @@ "transcoding_threads_description": "", "transcoding_tone_mapping": "", "transcoding_tone_mapping_description": "", - "transcoding_tone_mapping_npl": "", - "transcoding_tone_mapping_npl_description": "", "transcoding_transcode_policy": "", "transcoding_transcode_policy_description": "", "transcoding_two_pass_encoding": "", @@ -308,7 +293,6 @@ "appears_in": "", "archive": "", "archive_or_unarchive_photo": "", - "archived": "", "asset_offline": "", "assets": "", "authorized_devices": "", @@ -322,10 +306,6 @@ "cancel_search": "", "cannot_merge_people": "", "cannot_update_the_description": "", - "cant_apply_changes": "", - "cant_get_faces": "", - "cant_search_people": "", - "cant_search_places": "", "change_date": "", "change_expiration_time": "", "change_location": "", @@ -412,13 +392,6 @@ "downloading": "", "duplicates": "", "duration": "", - "durations": { - "days": "", - "hours": "", - "minutes": "", - "months": "", - "years": "" - }, "edit_album": "", "edit_avatar": "", "edit_date": "", @@ -437,7 +410,6 @@ "edited": "", "editor": "", "email": "", - "empty_album": "", "empty_trash": "", "enable": "", "enabled": "", @@ -523,7 +495,6 @@ "extension": "", "external": "", "external_libraries": "", - "failed_to_get_people": "", "favorite": "", "favorite_or_unfavorite_photo": "", "favorites": "", @@ -535,14 +506,12 @@ "filter_people": "", "find_them_fast": "", "fix_incorrect_match": "", - "force_re-scan_library_files": "", "forward": "", "general": "", "get_help": "", "getting_started": "", "go_back": "", "go_to_search": "", - "go_to_share_page": "", "group_albums_by": "", "has_quota": "", "hide_gallery": "", @@ -658,7 +627,6 @@ "oldest_first": "", "online": "", "only_favorites": "", - "only_refreshes_modified_files": "", "open_the_search_filters": "", "options": "", "organize_your_library": "", @@ -747,8 +715,6 @@ "saved_settings": "", "say_something": "", "scan_all_libraries": "", - "scan_all_library_files": "", - "scan_new_library_files": "", "scan_settings": "", "search": "", "search_albums": "", @@ -779,7 +745,6 @@ "selected": "", "send_message": "", "send_welcome_email": "", - "server": "", "server_stats": "", "set": "", "set_as_album_cover": "", @@ -850,7 +815,6 @@ "to_favorite": "", "toggle_settings": "", "toggle_theme": "", - "toggle_visibility": "", "total_usage": "", "trash": "", "trash_all": "", @@ -858,11 +822,9 @@ "trashed_items_will_be_permanently_deleted_after": "", "type": "", "unarchive": "", - "unarchived": "", "unfavorite": "", "unhide_person": "", "unknown": "", - "unknown_album": "", "unknown_year": "", "unlimited": "", "unlink_oauth": "", @@ -896,7 +858,6 @@ "view_links": "", "view_next_asset": "", "view_previous_asset": "", - "viewer": "", "waiting": "", "week": "", "welcome": "", diff --git a/i18n/id.json b/i18n/id.json index 6b9a352dc8834..f44bcf8905b4b 100644 --- a/i18n/id.json +++ b/i18n/id.json @@ -23,6 +23,7 @@ "add_to": "Tambahkan ke...", "add_to_album": "Tambahkan ke album", "add_to_shared_album": "Tambahkan ke album terbagi", + "add_url": "Tambahkan URL", "added_to_archive": "Ditambahkan ke arsip", "added_to_favorites": "Ditambahkan ke favorit", "added_to_favorites_count": "Ditambahkan {count, number} ke favorit", @@ -34,6 +35,11 @@ "authentication_settings_disable_all": "Anda yakin untuk menonaktifkan semua cara login? Login akan dinonaktikan secara menyeluruh.", "authentication_settings_reenable": "Untuk mengaktifkan ulang, gunakan Perintah Server.", "background_task_job": "Tugas Latar Belakang", + "backup_database": "Basis Data Cadangan", + "backup_database_enable_description": "Aktifkan pencadangan basis data", + "backup_keep_last_amount": "Jumlah cadangan untuk disimpan", + "backup_settings": "Pengaturan Pencadangan", + "backup_settings_description": "Kelola pengaturan pencadangan basis data", "check_all": "Periksa Semua", "cleared_jobs": "Tugas terselesaikan untuk: {job}", "config_set_by_file": "Konfigurasi saat ini ditetapkan oleh berkas konfigurasi", @@ -43,6 +49,9 @@ "confirm_reprocess_all_faces": "Apakah Anda yakin ingin memproses semua wajah? Ini juga akan menghapus nama orang.", "confirm_user_password_reset": "Apakah Anda yakin ingin mengatur ulang kata sandi {user}?", "create_job": "Buat tugas", + "cron_expression": "Ekspresi cron", + "cron_expression_description": "Tetapkan interval pemindaian menggunakan format cron. Untuk informasi lebih lanjut, silakan merujuk misalnya ke Crontab Guru", + "cron_expression_presets": "Prasetel ekspresi cron", "disable_login": "Nonaktifkan log masuk", "duplicate_detection_job_description": "Jalankan pembelajaran mesin pada aset untuk mendeteksi gambar yang serupa. Bergantung pada Pencarian Pintar", "exclusion_pattern_description": "Pola pengecualian memungkinkan Anda mengabaikan berkas dan folder ketika memindai pustaka Anda. Ini berguna jika Anda memiliki folder yang berisi berkas yang tidak ingin diimpor, seperti berkas RAW.", @@ -61,22 +70,15 @@ "image_prefer_wide_gamut": "Utamakan gamut luas", "image_prefer_wide_gamut_setting_description": "Gunakan Display P3 untuk gambar kecil. Ini menjaga kecerahan gambar dengan ruang warna yang luas, tetapi gambar dapat terlihat beda pada perangkat lawas dengan versi peramban yang lawas. Gambar sRGB tetap dalam sRGB untuk menghindari perubahan warna.", "image_preview_description": "Gambar berukuran sedang tanpa metadata, digunakan ketika melihat aset satuan dan untuk pembelajaran mesin", - "image_preview_format": "Format pratinjau", "image_preview_quality_description": "Kualitas pratinjau dari 1-100. Lebih tinggi lebih baik, tetapi menghasilkan berkas lebih besar dan respons aplikasi. Menetapkan nilai rendah dapat memengaruhi kualitas pembelajaran mesin.", - "image_preview_resolution": "Resolusi pratinjau", - "image_preview_resolution_description": "Digunakan ketika menampilkan satu foto untuk pembelajaran mesin. Resolusi yang lebih tinggi dapat menjaga lebih banyak detail tetapi dapat membutuhkan waktu lama untuk mengode, memiliki ukuran berkas yang lebih besar, dan dapat mengurangi respons aplikasi.", "image_preview_title": "Pengaturan Pratinjau", "image_quality": "Kualitas", - "image_quality_description": "Kualitas gambar dari 1 sampai 100. Lebih tinggi baik untuk kualitas tetapi menghasilkan berkas lebih besar, opsi ini memengaruhi gambar Pratinjau dan Gambar Kecil.", "image_resolution": "Resolusi", "image_resolution_description": "Resolusi lebih tinggi dapat menjaga lebih banyak detail tetapi dapat memerlukan waktu lebih lama untuk dienkode, memiliki ukuran berkas yang lebih besar, dan dapat mengurangi respons aplikasi.", "image_settings": "Pengaturan Gambar", "image_settings_description": "Kelola kualitas dan resolusi gambar yang dibuat", "image_thumbnail_description": "Gambar kecil tanpa metadata, digunakan ketika melihat kelompok foto seperti lini masa utama", - "image_thumbnail_format": "Format gambar kecil", "image_thumbnail_quality_description": "Kualitas gambar kecil dari 1-100. Lebih tinggi lebih baik, tetapi menghasilkan berkas lebih besar dan dapat mengurangi respons aplikasi.", - "image_thumbnail_resolution": "Resolusi gambar kecil", - "image_thumbnail_resolution_description": "Digunakan ketika menampilkan kelompok foto (lini masa utama, tampilan album, dll.). Resolusi yang lebih tinggi dapat menjaga lebih banyak detail tetapi memerlukan waktu lama untuk mengode, memiliki ukuran berkas yang lebih besar, dan dapat mengurangi respons aplikasi.", "image_thumbnail_title": "Pengaturan Gambar Kecil", "job_concurrency": "Konkurensi {job}", "job_created": "Tugas telah dibuat", @@ -87,9 +89,6 @@ "jobs_delayed": "{jobCount, plural, other {# tertunda}}", "jobs_failed": "{jobCount, plural, other {# gagal}}", "library_created": "Pustaka dibuat: {library}", - "library_cron_expression": "Ekspresi cron", - "library_cron_expression_description": "Menetapkan interval pemindaian menggunakan format cron. Untuk informasi lanjut silakan merujuk ke mis. Crontab Guru", - "library_cron_expression_presets": "Prasetel ekspresi cron", "library_deleted": "Pustaka dihapus", "library_import_path_description": "Tentukan folder untuk diimpor. Folder ini, termasuk subfolder, akan dipindai gambar dan videonya.", "library_scanning": "Pemindaian Berkala", @@ -132,7 +131,7 @@ "machine_learning_smart_search_description": "Cari gambar secara semantik menggunakan penyematan CLIP", "machine_learning_smart_search_enabled": "Aktifkan pencarian pintar", "machine_learning_smart_search_enabled_description": "Jika dinonaktifkan, gambar tidak akan dienkode untuk pencarian pintar.", - "machine_learning_url_description": "URL server pembelajaran mesin", + "machine_learning_url_description": "URL server pembelajaran mesin. Jika lebih dari satu URL disediakan, setiap server akan dicoba satu per satu sampai salah satu berhasil merespons, dari urutan pertama sampai terakhir.", "manage_concurrency": "Kelola Konkurensi", "manage_log_settings": "Kelola pengaturan log", "map_dark_style": "Gaya gelap", @@ -213,7 +212,6 @@ "refreshing_all_libraries": "Menyegarkan semua pustaka", "registration": "Pendaftaran Admin", "registration_description": "Karena Anda merupakan pengguna pertama dalam sistem, Anda akan ditetapkan sebagai Admin dan bertanggung jawab atas tugas administratif dan pengguna tambahan akan dibuat oleh Anda.", - "removing_deleted_files": "Menghapus Berkas Luring", "repair_all": "Perbaiki Semua", "repair_matched_items": "{count, plural, one {# item} other {# item}} dicocokkan", "repaired_items": "{count, plural, one {# item} other {# item}} diperbaiki", @@ -221,12 +219,12 @@ "reset_settings_to_default": "Atur ulang pengaturan ke bawaan", "reset_settings_to_recent_saved": "Atur ulang pengaturan ke pengaturan tersimpan terkini", "scanning_library": "Memindai pustaka", - "scanning_library_for_changed_files": "Memindai pustaka untuk berkas yang telah diubah", - "scanning_library_for_new_files": "Memindai pustaka untuk berkas baru", "search_jobs": "Mencari tugas...", "send_welcome_email": "Kirim surel selamat datang", "server_external_domain_settings": "Domain eksternal", "server_external_domain_settings_description": "Domain untuk tautan terbagi publik, termasuk http(s)://", + "server_public_users": "Pengguna Publik", + "server_public_users_description": "Semua pengguna (nama dan email) didaftarkan ketika menambahkan pengguna ke album terbagi. Ketika dinonaktifkan, daftar pengguna hanya akan tersedia kepada pengguna admin.", "server_settings": "Pengaturan Server", "server_settings_description": "Kelola pengaturan server", "server_welcome_message": "Pesan selamat datang", @@ -252,6 +250,16 @@ "storage_template_user_label": "{label} adalah Label Penyimpanan pengguna", "system_settings": "Pengaturan Sistem", "tag_cleanup_job": "Pembersihan tag", + "template_email_available_tags": "Anda dapat menggunakan variabel berikut dalam templat Anda: {tags}", + "template_email_if_empty": "Jika templat kosong, surel bawaan akan digunakan.", + "template_email_invite_album": "Templat Undangan Album", + "template_email_preview": "Pratinjau", + "template_email_settings": "Templat Surel", + "template_email_settings_description": "Kelola templat notifikasi surel kustom", + "template_email_update_album": "Perbarui Templat Album", + "template_email_welcome": "Templat surel selamat datang", + "template_settings": "Templat Notifikasi", + "template_settings_description": "Kelola templat kustom untuk notifikasi.", "theme_custom_css_settings": "CSS Kustom", "theme_custom_css_settings_description": "CSS memungkinkan desain Immich untuk diubah.", "theme_settings": "Pengaturan Tema", @@ -310,8 +318,6 @@ "transcoding_threads_description": "Nilai yang lebih tinggi dapat mengode dengan cepat, tetapi mengurangi ruang bagi server untuk memproses tugas lain selagi aktif. Nilai ini seharusnya tidak lebih dari jumlah inti CPU. Memaksimalkan pemakaian jika ditetapkan ke 0.", "transcoding_tone_mapping": "Pemetaan nada", "transcoding_tone_mapping_description": "Mencoba menjaga tampilan video HDR ketika dikonversikan ke SDR. Setiap algoritma memiliki kekurangan pada warna, detail, dan kecerahan. Hable menjaga detail, Mobius menjaga warna, dan Reinhard menjada kecerahan.", - "transcoding_tone_mapping_npl": "NPL pemetaan nada", - "transcoding_tone_mapping_npl_description": "Warna akan disesuaikan agar terlihat normal untuk tampilan kecerahan ini. Nilai yang lebih rendah meningkatkan kecerahan video dan sebaliknya, karena nilai ini mengimbangi kecerahan tampilan. 0 menetapkan nilai ini secara otomatis.", "transcoding_transcode_policy": "Kebijakan transkode", "transcoding_transcode_policy_description": "Kebijakan untuk kapan sebuah video harus ditranskode. Video HDR akan selalu ditranskode (kecuali jika transkode dinonaktifkan).", "transcoding_two_pass_encoding": "Pengodean dua arah", @@ -392,7 +398,6 @@ "archive_or_unarchive_photo": "Arsipkan atau batalkan pengarsipan foto", "archive_size": "Ukuran arsip", "archive_size_description": "Atur ukuran arsip untuk unduhan (dalam GiB)", - "archived": "", "archived_count": "{count, plural, other {# terarsip}}", "are_these_the_same_person": "Apakah ini adalah orang yang sama?", "are_you_sure_to_do_this": "Apakah Anda yakin ingin melakukan ini?", @@ -413,7 +418,6 @@ "assets_added_to_album_count": "Ditambahkan {count, plural, one {# aset} other {# aset}} ke album", "assets_added_to_name_count": "Ditambahkan {count, plural, one {# aset} other {# aset}} ke {hasName, select, true {{name}} other {album baru}}", "assets_count": "{count, plural, one {# aset} other {# aset}}", - "assets_moved_to_trash": "", "assets_moved_to_trash_count": "Dipindahkan {count, plural, one {# aset} other {# aset}} ke sampah", "assets_permanently_deleted_count": "{count, plural, one {# aset} other {# aset}} dihapus secara permanen", "assets_removed_count": "{count, plural, one {# aset} other {# aset}} dihapus", @@ -443,10 +447,6 @@ "cannot_merge_people": "Tidak dapat menggabungkan orang", "cannot_undo_this_action": "Anda tidak dapat mengurungkan tindakan ini!", "cannot_update_the_description": "Tidak dapat memperbarui deskripsi", - "cant_apply_changes": "", - "cant_get_faces": "", - "cant_search_people": "", - "cant_search_places": "", "change_date": "Ubah tanggal", "change_expiration_time": "Ubah waktu kedaluwarsa", "change_location": "Ubah lokasi", @@ -478,6 +478,7 @@ "confirm": "Konfirmasi", "confirm_admin_password": "Konfirmasi Kata Sandi Admin", "confirm_delete_shared_link": "Apakah Anda yakin ingin menghapus tautan terbagi ini?", + "confirm_keep_this_delete_others": "Semua aset lain di dalam stack akan dihapus kecuali aset ini. Anda yakin untuk melanjutkan?", "confirm_password": "Konfirmasi kata sandi", "contain": "Berisi", "context": "Konteks", @@ -527,6 +528,7 @@ "delete_key": "Hapus kunci", "delete_library": "Hapus Pustaka", "delete_link": "Hapus tautan", + "delete_others": "Hapus lainnya", "delete_shared_link": "Hapus tautan terbagi", "delete_tag": "Hapus tag", "delete_tag_confirmation_prompt": "Apakah Anda yakin ingin menghapus label tag {tagName}?", @@ -617,6 +619,7 @@ "failed_to_create_shared_link": "Gagal membuat tautan terbagi", "failed_to_edit_shared_link": "Gagal menyunting tautan terbagi", "failed_to_get_people": "Gagal mendapatkan orang", + "failed_to_keep_this_delete_others": "Gagal mempertahankan aset ini dan hapus aset-aset lainnya", "failed_to_load_asset": "Gagal membuka aset", "failed_to_load_assets": "Gagal membuka aset-aset", "failed_to_load_people": "Gagal mengunggah orang", @@ -731,7 +734,7 @@ "external": "Eksternal", "external_libraries": "Pustaka Eksternal", "face_unassigned": "Tidak ada nama", - "failed_to_get_people": "", + "failed_to_load_assets": "Gagal memuat aset", "favorite": "Favorit", "favorite_or_unfavorite_photo": "Favorit atau batalkan pemfavoritan foto", "favorites": "Favorit", @@ -747,14 +750,12 @@ "fix_incorrect_match": "Perbaiki pencocokan salah", "folders": "Berkas", "folders_feature_description": "Menjelajahi tampilan folder untuk foto dan video pada sistem file", - "force_re-scan_library_files": "Paksa Pindai Ulang Semua Berkas Pustaka", "forward": "Maju", "general": "Umum", "get_help": "Dapatkan Bantuan", "getting_started": "Memulai", "go_back": "Kembali", "go_to_search": "Pergi ke pencarian", - "go_to_share_page": "Pergi ke laman pembagian", "group_albums_by": "Kelompokkan album berdasarkan...", "group_no": "Tidak ada pengelompokan", "group_owner": "Kelompokkan berdasarkan pemilik", @@ -780,9 +781,6 @@ "image_alt_text_date_place_2_people": "{isVideo, select, true {Video} other {Image}} diambil di {city}, {country} oleh {person1} dan {person2} pada {date}", "image_alt_text_date_place_3_people": "{isVideo, select, true {Video} other {Image}} diambil di {city}, {country} oleh {person1}, {person2}, dan {person3} pada {date}", "image_alt_text_date_place_4_or_more_people": "{isVideo, select, true {Video} other {Image}} diambil di {city}, {country} oleh {person1}, {person2}, dan {additionalCount, number} lainnya pada {date}", - "image_alt_text_people": "{count, plural, =1 {dengan {person1}} =2 {dengan {person1} dan {person2}} =3 {dengan {person1}, {person2}, dan {person3}} other {dengan {person1}, {person2}, dan {others, number} lainnya}}", - "image_alt_text_place": "di {city}, {country}", - "image_taken": "{isVideo, select, true {Video diambil} other {Gambar diambil}}", "immich_logo": "Logo Immich", "immich_web_interface": "Antarmuka Web Immich", "import_from_json": "Impor dari JSON", @@ -806,6 +804,8 @@ "jobs": "Tugas", "keep": "Simpan", "keep_all": "Simpan Semua", + "keep_this_delete_others": "Pertahankan ini, hapus lainnya", + "kept_this_deleted_others": "Aset ini dipertahankan dan {count, plural, one {# asset} other {# assets}} dihapus", "keyboard_shortcuts": "Pintasan papan ketik", "language": "Bahasa", "language_setting_description": "Pilih bahasa Anda yang disukai", @@ -817,31 +817,6 @@ "level": "Tingkat", "library": "Pustaka", "library_options": "Opsi pustaka", - "license_account_info": "Akun Anda sudah berlisensi", - "license_activated_subtitle": "Terima kasih atas dukungan Immich dan perangkat lunak bersumber terbuka", - "license_activated_title": "Lisensi Anda berhasil diaktifkan", - "license_button_activate": "Aktivasikan", - "license_button_buy": "Beli", - "license_button_buy_license": "Beli Lisensi", - "license_button_select": "Pilih", - "license_failed_activation": "Gagal mengaktivasi lisensi. Silakan periksa surel Anda untuk mendapatkan kunci yang benar!", - "license_individual_description_1": "1 lisensi per pengguna di server mana pun", - "license_individual_title": "Lisensi Individu", - "license_info_licensed": "Berlisensi", - "license_info_unlicensed": "Tidak Berlisensi", - "license_input_suggestion": "Ada lisensi? Masukan kuncinya di bawah", - "license_license_subtitle": "Beli lisensi untuk mendukung Immich", - "license_license_title": "LISENSI", - "license_lifetime_description": "Lisensi seumur hidup", - "license_per_server": "Per server", - "license_per_user": "Per pengguna", - "license_server_description_1": "1 lisensi per server", - "license_server_description_2": "Lisensi untuk semua pengguna di server", - "license_server_title": "Lisensi Server", - "license_trial_info_1": "Anda menjalankan versi Immich yang Tidak Berlisensi", - "license_trial_info_2": "Anda telah menggunakan Immich sekitar", - "license_trial_info_3": "{accountAge, plural, one {# hari} other {# hari}}", - "license_trial_info_4": "Pertimbangkan membeli lisensi untuk mendukung keberlanjutan pengembangan layanan", "light": "Terang", "like_deleted": "Suka dihapus", "link_motion_video": "Tautan video gerak", @@ -946,7 +921,6 @@ "onboarding_welcome_user": "Selamat datang, {user}", "online": "Daring", "only_favorites": "Hanya favorit", - "only_refreshes_modified_files": "Hanya menyegarkan berkas yang diubah", "open_in_map_view": "Buka dalam tampilan peta", "open_in_openstreetmap": "Buka di OpenStreetMap", "open_the_search_filters": "Buka saringan pencarian", @@ -990,7 +964,6 @@ "permanently_delete_assets_count": "Hapus {count, plural, one {aset} other {aset}} secara permanen", "permanently_delete_assets_prompt": "Apakah Anda yakin untuk menghapus {count, plural, one {aset ini secara permanen?} other {sebanyak # aset-aset berikut secara permanen?}} Ini juga akan menghapus {count, plural, one {ini dari} other {semua dari}} album-albumnya.", "permanently_deleted_asset": "Aset dihapus secara permanen", - "permanently_deleted_assets": "", "permanently_deleted_assets_count": "{count, plural, one {# aset} other {# aset}} dihapus secara permanen", "person": "Orang", "person_hidden": "{name}{hidden, select, true { (tersembunyi)} other {}}", @@ -1061,6 +1034,7 @@ "reassigned_assets_to_new_person": "Menetapkan ulang {count, plural, one {# aset} other {# aset}} kepada orang baru", "reassing_hint": "Tetapkan aset yang dipilih ke orang yang sudah ada", "recent": "Terkini", + "recent-albums": "Album terkini", "recent_searches": "Pencarian terkini", "refresh": "Segarkan", "refresh_encoded_videos": "Segarkan video terenkode", @@ -1082,6 +1056,7 @@ "remove_from_album": "Hapus dari album", "remove_from_favorites": "Hapus dari favorit", "remove_from_shared_link": "Hapus dari tautan terbagi", + "remove_url": "Hapus URL", "remove_user": "Keluarkan pengguna", "removed_api_key": "Kunci API Dihapus: {name}", "removed_from_archive": "Dihapus dari arsip", @@ -1117,9 +1092,7 @@ "saved_settings": "Pengaturan disimpan", "say_something": "Ucapkan sesuatu", "scan_all_libraries": "Pindai Semua Pustaka", - "scan_all_library_files": "Pindai Ulang Semua Berkas Pustaka", "scan_library": "Pindai", - "scan_new_library_files": "Pindai Berkas Pustaka Baru", "scan_settings": "Pengaturan Pemindaian", "scanning_for_album": "Memindai album...", "search": "Cari", @@ -1162,7 +1135,6 @@ "selected_count": "{count, plural, other {# dipilih}}", "send_message": "Kirim pesan", "send_welcome_email": "Kirim surel selamat datang", - "server": "Server", "server_offline": "Server Luring", "server_online": "Server Daring", "server_stats": "Statistik Server", @@ -1267,17 +1239,17 @@ "they_will_be_merged_together": "Mereka akan digabungkan bersama", "third_party_resources": "Sumber Daya Pihak Ketiga", "time_based_memories": "Kenangan berbasis waktu", + "timeline": "Lini masa", "timezone": "Zona waktu", "to_archive": "Arsipkan", "to_change_password": "Ubah kata sandi", "to_favorite": "Favorit", "to_login": "Log masuk", "to_parent": "Ke induk", - "to_root": "Untuk melakukan root", "to_trash": "Sampah", "toggle_settings": "Saklar pengaturan", "toggle_theme": "Beralih tema gelap", - "toggle_visibility": "Saklar keterlihatan", + "total": "Jumlah", "total_usage": "Jumlah penggunaan", "trash": "Sampah", "trash_all": "Buang Semua", @@ -1287,7 +1259,6 @@ "trashed_items_will_be_permanently_deleted_after": "Item yang dibuang akan dihapus secara permanen setelah {days, plural, one {# hari} other {# hari}}.", "type": "Jenis", "unarchive": "Keluarkan dari arsip", - "unarchived": "", "unarchived_count": "{count, plural, other {# dipindahkan dari arsip}}", "unfavorite": "Hapus favorit", "unhide_person": "Munculkan orang", @@ -1323,13 +1294,13 @@ "use_custom_date_range": "Gunakan jangka tanggal khusus saja", "user": "Pengguna", "user_id": "ID Pengguna", - "user_license_settings": "Lisensi", - "user_license_settings_description": "Kelola lisensi Anda", "user_liked": "{user} menyukai {type, select, photo {foto ini} video {tayangan ini} asset {aset ini} other {ini}}", "user_purchase_settings": "Pembelian", "user_purchase_settings_description": "Atur pembelian kamu", "user_role_set": "Tetapkan {user} sebagai {role}", "user_usage_detail": "Detail penggunaan pengguna", + "user_usage_stats": "Statistik penggunaan akun", + "user_usage_stats_description": "Tampilkan statistik penggunaan akun", "username": "Nama pengguna", "users": "Pengguna", "utilities": "Peralatan", @@ -1337,7 +1308,7 @@ "variables": "Variabel", "version": "Versi", "version_announcement_closing": "Temanmu, Alex", - "version_announcement_message": "Halo, ada versi aplikasi yang baru. Silakan luangkan waktu Anda untuk mengunjungi catatan rilis dan pastikan pengaturan docker-compose.yml dan .env Anda sudah terkini untuk menghindari kesalahan dalam pengaturan, terutama jika Anda menggunakan WatchTower atau mekanisme lain yang menangani pembaruan aplikasi Anda secara otomatis.", + "version_announcement_message": "Hai! Versi baru Immich telah tersedia. Harap luangkan waktu untuk membaca catatan rilis untuk memastikan pengaturan Anda terkini untuk mencegah kesalahan konfigurasi, terutama jika Anda menggunakan WatchTower atau mekanisme apa pun yang menangani pembaruan server Immich secara otomatis.", "version_history": "Riwayat Versi", "version_history_item": "Terpasang {version} pada {date}", "video": "Video", @@ -1351,10 +1322,10 @@ "view_all_users": "Tampilkan semua pengguna", "view_in_timeline": "Lihat di timeline", "view_links": "Tampilkan tautan", + "view_name": "Tampilkan", "view_next_asset": "Tampilkan aset berikutnya", "view_previous_asset": "Tampilkan aset sebelumnya", "view_stack": "Tampilkan Tumpukan", - "viewer": "", "visibility_changed": "Keterlihatan diubah untuk {count, plural, one {# orang} other {# orang}}", "waiting": "Menunggu", "warning": "Peringatan", diff --git a/i18n/it.json b/i18n/it.json index fc3e9d97fc505..57e6fc1ab7f43 100644 --- a/i18n/it.json +++ b/i18n/it.json @@ -1,5 +1,5 @@ { - "about": "Informazioni", + "about": "Informazioni su", "account": "Profilo", "account_settings": "Impostazioni Account", "acknowledge": "Acconsento", @@ -23,6 +23,7 @@ "add_to": "Aggiungi a...", "add_to_album": "Aggiungi all'album", "add_to_shared_album": "Aggiungi all'album condiviso", + "add_url": "Aggiungi URL", "added_to_archive": "Aggiunto all'archivio", "added_to_favorites": "Aggiunto ai preferiti", "added_to_favorites_count": "Aggiunti {count, number} ai preferiti", @@ -34,6 +35,11 @@ "authentication_settings_disable_all": "Sei sicuro di voler disabilitare tutte le modalità di accesso? Il login verrà disabilitato completamente.", "authentication_settings_reenable": "Per riabilitare, utilizza un Comando Server.", "background_task_job": "Attività in Background", + "backup_database": "Backup Database", + "backup_database_enable_description": "Abilita i backup del database", + "backup_keep_last_amount": "Quantità di backup precedenti da mantenere", + "backup_settings": "Impostazioni backup", + "backup_settings_description": "Gestisci le impostazioni dei backup", "check_all": "Controlla Tutto", "cleared_jobs": "Cancellati i processi per: {job}", "config_set_by_file": "La configurazione è attualmente impostata da un file di configurazione", @@ -43,9 +49,10 @@ "confirm_reprocess_all_faces": "Sei sicuro di voler riprocessare tutti i volti? Questo cancellerà tutte le persone nominate.", "confirm_user_password_reset": "Sei sicuro di voler resettare la password di {user}?", "create_job": "creare lavoro", - "crontab_guru": "Crontab Guru", + "cron_expression": "Espressione Cron", + "cron_expression_description": "Imposta il tempo di scansione utilizzando il formato Cron. Per ulteriori informazioni fare riferimento a Crontab Guru", + "cron_expression_presets": "Espressione Cron preimpostata", "disable_login": "Disabilita login", - "disabled": "Disattivato", "duplicate_detection_job_description": "Esegui il machine learning sugli assets per rilevare immagini simili. Basato su Ricerca Intelligente", "exclusion_pattern_description": "I modelli di esclusione ti permettono di ignorare file e cartelle durante la scansione della tua libreria. Questo è utile se hai cartelle che contengono file che non vuoi importare, come ad esempio, i file RAW.", "external_library_created_at": "Libreria esterna (creata il {date})", @@ -63,22 +70,15 @@ "image_prefer_wide_gamut": "Preferisci gamut più ampio", "image_prefer_wide_gamut_setting_description": "Usa lo spazio colore Display P3 per le anteprime. Questo aiuta a mantenere la vivacità delle immagini con spazi colore più ampi, tuttavia potrebbe non mostrare correttamente le immagini con dispositivi e browser obsoleti. Le immagini sRGB vengono preservate per evitare alterazioni del colore.", "image_preview_description": "Immagine di medie dimensioni con metadati eliminati, utilizzata durante la visualizzazione di una singola risorsa e per l'apprendimento automatico", - "image_preview_format": "Formato anteprima", "image_preview_quality_description": "Qualità dell'anteprima da 1 a 100. Elevata è migliore ma produce file più pesanti e può ridurre la reattività dell'app. Impostare un valore basso può influenzare negativamente la qualità del machine learning.", - "image_preview_resolution": "Risoluzione anteprima", - "image_preview_resolution_description": "Usata per visualizzazione individuale di foto e per machine learning. Risoluzioni più alte possono preservare più dettagli ma richiedono un encoding più lento, occupano più spazio, e possono ridurre la responsività della app.", "image_preview_title": "Impostazioni dell'anteprima", "image_quality": "Qualità", - "image_quality_description": "Qualità dell'immagine da 1 a 100. Un valore più alto risulta in una migliore qualità, ma produce file più grandi.", "image_resolution": "Risoluzione", "image_resolution_description": "Risoluzioni più elevate possono preservare più dettagli ma richiedere più tempo per la codifica, avere dimensioni di file più grandi e possono ridurre la reattività dell'app.", "image_settings": "Impostazioni delle immagini", "image_settings_description": "Gestisci qualità e risoluzione delle immagini generate", "image_thumbnail_description": "Miniatura piccola senza metadati, utilizzata durante la visualizzazione di gruppi di foto come la sequenza temporale principale", - "image_thumbnail_format": "Formato miniatura", "image_thumbnail_quality_description": "Qualità delle miniature da 1 a 100. Un valore più alto è migliore, ma produce file più grandi e può ridurre la reattività dell'app.", - "image_thumbnail_resolution": "Risoluzione miniatura", - "image_thumbnail_resolution_description": "Utilizzato per vedere gruppi di foto (linea temporale, vista album, etc.). Risoluzioni più alte possono mantenere più dettaglio però l'encoding sarà più lungo, i file avranno dimensioni maggiori e potrebbero causare una riduzione nella responsività dell'applicazione.", "image_thumbnail_title": "Impostazioni della copertina", "job_concurrency": "Concorrenza {job}", "job_created": "Lavoro creato", @@ -89,9 +89,6 @@ "jobs_delayed": "{jobCount, plural, one {# posticipato} other {# posticipati}}", "jobs_failed": "{jobCount, plural, one {# fallito} other {# falliti}}", "library_created": "Creata libreria: {library}", - "library_cron_expression": "Espressione cron", - "library_cron_expression_description": "Imposta l'intervallo di rilevazione utilizzando il formato cron. Per più informazioni consulta es. Crontab Guru", - "library_cron_expression_presets": "Espressioni cron preimpostate", "library_deleted": "Libreria eliminata", "library_import_path_description": "Specifica una cartella da importare. Questa cartella e le sue sottocartelle, verranno analizzate per cercare immagini e video.", "library_scanning": "Scansione periodica", @@ -134,7 +131,7 @@ "machine_learning_smart_search_description": "Cerca immagini semanticamente utilizzato gli embedding CLIP", "machine_learning_smart_search_enabled": "Attiva ricerca intelligente", "machine_learning_smart_search_enabled_description": "Se disabilitato le immagini non saranno codificate per la ricerca intelligente.", - "machine_learning_url_description": "URL del server machine learning", + "machine_learning_url_description": "URL del server machine learning. Se sono stati forniti più di un URL, verrà testato un server alla volta finché uno non risponderà, in ordine dal primo all'ultimo.", "manage_concurrency": "Gestisci Concorrenza", "manage_log_settings": "Gestisci le impostazioni dei log", "map_dark_style": "Tema scuro", @@ -215,7 +212,6 @@ "refreshing_all_libraries": "Aggiorna tutte le librerie", "registration": "Registrazione amministratore", "registration_description": "Poiché sei il primo utente del sistema, sarai assegnato come Amministratore e sarai responsabile dei task amministrativi, e utenti aggiuntivi saranno creati da te.", - "removing_deleted_files": "Cancella File Offline", "repair_all": "Ripara Tutto", "repair_matched_items": "{count, plural, one {Rilevato # elemento} other {Rilevati # elementi}}", "repaired_items": "{count, plural, one {Riparato # elemento} other {Riparati # elementi}}", @@ -223,12 +219,12 @@ "reset_settings_to_default": "Ripristina impostazioni predefinite", "reset_settings_to_recent_saved": "Ripristina impostazioni alle impostazioni salvate di recente", "scanning_library": "Scansione della libreria", - "scanning_library_for_changed_files": "Scansiona la libreria per file modificati", - "scanning_library_for_new_files": "Scansiona la libreria per nuovi file", "search_jobs": "Cerca Jobs...", "send_welcome_email": "Invia email di benvenuto", "server_external_domain_settings": "Dominio esterno", "server_external_domain_settings_description": "Dominio per link condivisi pubblicamente, incluso http(s)://", + "server_public_users": "Utenti Pubblici", + "server_public_users_description": "Tutti gli utenti (nome ed e-mail) sono elencati quando si aggiunge un utente agli album condivisi. Quando disabilitato, l'elenco degli utenti sarà disponibile solo per gli utenti amministratori.", "server_settings": "Impostazioni Server", "server_settings_description": "Gestisci le impostazioni del server", "server_welcome_message": "Messaggio di benvenuto", @@ -246,7 +242,7 @@ "storage_template_migration_description": "Applica il {template} attuale agli asset caricati in precedenza", "storage_template_migration_info": "Le modifiche al modello di archiviazione verranno applicate solo agli asset nuovi. Per applicare le modifiche retroattivamente esegui {job}.", "storage_template_migration_job": "Processo Migrazione Modello di Archiviazione", - "storage_template_more_details": "Per più informazioni riguardo a questa funzionalità, consulta il Modello Archiviazione e le sue conseguenze", + "storage_template_more_details": "Per maggiori informazioni riguardo a questa funzionalità, consulta il Modello Archiviazione e le sue conseguenze", "storage_template_onboarding_description": "Quando attivata, questa funzionalità organizzerà automaticamente i file utilizzando il modello di archiviazione definito dall'utente. Per ragioni di stabilità, questa funzionalità è disabilitata per impostazione predefinita. Per più informazioni, consulta la documentazione.", "storage_template_path_length": "Limite approssimativo lunghezza percorso: {length, number}/{limit, number}", "storage_template_settings": "Modello Archiviazione", @@ -254,6 +250,16 @@ "storage_template_user_label": "{label} è l'etichetta di archiviazione dell'utente", "system_settings": "Impostazioni di sistema", "tag_cleanup_job": "Pulisci Tag", + "template_email_available_tags": "Puoi usare le seguenti variabili nel tuo modello: {tags}", + "template_email_if_empty": "Se il modello è vuoto, verrà usata l'email di default.", + "template_email_invite_album": "Modello di invito all'album", + "template_email_preview": "Anteprima", + "template_email_settings": "Template Email", + "template_email_settings_description": "Gestisci i modelli personalizzati di notifiche email", + "template_email_update_album": "Modello di aggiornamento dell'album", + "template_email_welcome": "Modello di email di benvenuto", + "template_settings": "Templates Notifiche", + "template_settings_description": "Gestisci i modelli personalizzati per le notifiche.", "theme_custom_css_settings": "CSS Personalizzato", "theme_custom_css_settings_description": "I Cascading Style Sheets (CSS) permettono di personalizzare l'interfaccia di Immich.", "theme_settings": "Impostazioni Tema", @@ -261,7 +267,6 @@ "these_files_matched_by_checksum": "File abbinati per checksum", "thumbnail_generation_job": "Generazione Miniature", "thumbnail_generation_job_description": "Genera miniature grandi, piccole e sfocate per ogni asset, oltre a miniature per ogni persona", - "transcode_policy_description": "", "transcoding_acceleration_api": "API di accelerazione", "transcoding_acceleration_api_description": "L'API che interagirà con il tuo dispositivo per accelerare la transcodifica. Questa impostazione è \"best effort\": ripiegherà sulla transcodifica software in caso di fallimento. VP9 potrebbe funzionare o meno a seconda del tuo hardware.", "transcoding_acceleration_nvenc": "NVENC (richiede GPU NVIDIA)", @@ -313,8 +318,6 @@ "transcoding_threads_description": "Valori più alti portano a una codifica più veloce, ma lasciano meno spazio al server per elaborare altre attività durante l'attività. Questo valore non dovrebbe essere superiore al numero di core CPU. Massimizza l'utilizzo se impostato su 0.", "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_tone_mapping_npl": "Mappatura della tonalità NPL", - "transcoding_tone_mapping_npl_description": "I colori verranno regolati per apparire normali su uno schermo di questa luminosità. Contrariamente all'intuito, valori più bassi aumentano la luminosità del video e viceversa poiché compensano la luminosità dello schermo. 0 imposta questo valore automaticamente.", "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_two_pass_encoding": "Codifica a due passaggi", @@ -395,7 +398,6 @@ "archive_or_unarchive_photo": "Archivia o ripristina foto", "archive_size": "Dimensioni Archivio", "archive_size_description": "Imposta le dimensioni dell'archivio per i download (in GiB)", - "archived": "Archiviato", "archived_count": "{count, plural, other {Archiviati #}}", "are_these_the_same_person": "Sono la stessa persona?", "are_you_sure_to_do_this": "Sei sicuro di voler procedere?", @@ -416,7 +418,6 @@ "assets_added_to_album_count": "{count, plural, one {# asset aggiunto} other {# asset aggiunti}} all'album", "assets_added_to_name_count": "Aggiunti {count, plural, one {# asset} other {# assets}} a {hasName, select, true {{name}} other {new album}}", "assets_count": "{count, plural, other {# asset}}", - "assets_moved_to_trash": "{count, plural, one {Spostato # asset} other {Spostati # asset}} nel cestino", "assets_moved_to_trash_count": "{count, plural, one {# asset spostato} other {# asset spostati}} nel cestino", "assets_permanently_deleted_count": "{count, plural, one {# asset cancellato} other {# asset cancellati}} definitivamente", "assets_removed_count": "{count, plural, one {# asset rimosso} other {# asset rimossi}}", @@ -446,10 +447,6 @@ "cannot_merge_people": "Impossibile unire le persone", "cannot_undo_this_action": "Non puoi annullare questa azione!", "cannot_update_the_description": "Impossibile aggiornare la descrizione", - "cant_apply_changes": "Impossibile applicare le modifiche", - "cant_get_faces": "Impossibile caricare i volti", - "cant_search_people": "Impossibile cercare le persone", - "cant_search_places": "Impossibile cercare i luoghi", "change_date": "Modifica data", "change_expiration_time": "Modifica tempo di scadenza", "change_location": "Modifica posizione", @@ -481,6 +478,7 @@ "confirm": "Conferma", "confirm_admin_password": "Conferma password amministratore", "confirm_delete_shared_link": "Sei sicuro di voler eliminare questo link condiviso?", + "confirm_keep_this_delete_others": "Tutti gli altri asset nello stack saranno eliminati, eccetto questo asset. Vuoi continuare?", "confirm_password": "Conferma password", "contain": "Adatta", "context": "Contesto", @@ -530,6 +528,7 @@ "delete_key": "Elimina chiave", "delete_library": "Elimina Libreria", "delete_link": "Elimina link", + "delete_others": "Elimina gli altri", "delete_shared_link": "Elimina link condiviso", "delete_tag": "Elimina tag", "delete_tag_confirmation_prompt": "Sei sicuro di voler cancellare il tag {tagName}?", @@ -563,13 +562,6 @@ "duplicates": "Duplicati", "duplicates_description": "Risolvi ciascun gruppo indicando quali sono, se esistono, i duplicati", "duration": "Durata", - "durations": { - "days": "{days, plural, one {giorno} other {{days, number} giorni}}", - "hours": "{hours, plural, one {ora} other {{hours, number} ore}}", - "minutes": "{minutes, plural, one {minuto} other {{minutes, number} minuti}}", - "months": "{months, plural, one {mese} other {{months, number} mesi}}", - "years": "{years, plural, one {anno} other {{years, number} anni}}" - }, "edit": "Modifica", "edit_album": "Modifica album", "edit_avatar": "Modifica avatar", @@ -594,8 +586,6 @@ "editor_crop_tool_h2_aspect_ratios": "Proporzioni", "editor_crop_tool_h2_rotation": "Rotazione", "email": "Email", - "empty": "", - "empty_album": "Album Vuoto", "empty_trash": "Svuota cestino", "empty_trash_confirmation": "Sei sicuro di volere svuotare il cestino? Questo rimuoverà tutte le risorse nel cestino in modo permanente da Immich.\nNon puoi annullare questa azione!", "enable": "Abilita", @@ -629,6 +619,7 @@ "failed_to_create_shared_link": "Creazione del link condivisibile non riuscita", "failed_to_edit_shared_link": "Errore durante la modifica del link condivisibile", "failed_to_get_people": "Impossibile ottenere le persone", + "failed_to_keep_this_delete_others": "Impossibile conservare questa risorsa ed eliminare le altre risorse", "failed_to_load_asset": "Errore durante il caricamento della risorsa", "failed_to_load_assets": "Errore durante il caricamento delle risorse", "failed_to_load_people": "Caricamento delle persone non riuscito", @@ -656,8 +647,6 @@ "unable_to_change_location": "Impossibile modificare posizione", "unable_to_change_password": "Impossibile modificare password", "unable_to_change_visibility": "Errore durante la modifica della visibilità per {count, plural, one {# persona} other {# persone}}", - "unable_to_check_item": "", - "unable_to_check_items": "", "unable_to_complete_oauth_login": "Errore durante l'accesso tramite OAuth", "unable_to_connect": "Impossibile connettersi", "unable_to_connect_to_server": "Impossibile connettersi al server", @@ -698,12 +687,10 @@ "unable_to_remove_album_users": "Impossibile rimuovere gli utenti dall'album", "unable_to_remove_api_key": "Impossibile rimuovere la chiave API", "unable_to_remove_assets_from_shared_link": "Errore durante la rimozione degli assets da un link condiviso", - "unable_to_remove_comment": "", "unable_to_remove_deleted_assets": "Impossibile rimuovere i file offline", "unable_to_remove_library": "Impossibile rimuovere libreria", "unable_to_remove_partner": "Impossibile rimuovere compagno", "unable_to_remove_reaction": "Impossibile rimuovere reazione", - "unable_to_remove_user": "", "unable_to_repair_items": "Impossibile riparare elementi", "unable_to_reset_password": "Impossibile reimpostare la password", "unable_to_resolve_duplicate": "Impossibile risolvere duplicato", @@ -733,10 +720,6 @@ "unable_to_update_user": "Impossibile aggiornare l'utente", "unable_to_upload_file": "Impossibile caricare il file" }, - "every_day_at_onepm": "", - "every_night_at_midnight": "", - "every_night_at_twoam": "", - "every_six_hours": "", "exif": "Exif", "exit_slideshow": "Esci dalla presentazione", "expand_all": "Espandi tutto", @@ -751,33 +734,28 @@ "external": "Esterno", "external_libraries": "Librerie esterne", "face_unassigned": "Non assegnata", - "failed_to_get_people": "Impossibile recuperare persone", + "failed_to_load_assets": "Impossibile caricare gli asset", "favorite": "Preferito", "favorite_or_unfavorite_photo": "Aggiungi o rimuovi foto da preferiti", "favorites": "Preferiti", - "feature": "", "feature_photo_updated": "Foto in evidenza aggiornata", - "featurecollection": "", "features": "Funzionalità", "features_setting_description": "Gestisci le funzionalità dell'app", "file_name": "Nome file", "file_name_or_extension": "Nome file o estensione", "filename": "Nome file", - "files": "", "filetype": "Tipo file", "filter_people": "Filtra persone", "find_them_fast": "Trovale velocemente con la ricerca", "fix_incorrect_match": "Correggi corrispondenza errata", "folders": "Cartelle", "folders_feature_description": "Navigare la visualizzazione a cartelle per le foto e i video sul file system", - "force_re-scan_library_files": "Forza nuova scansione di tutti i file della libreria", "forward": "Avanti", "general": "Generale", "get_help": "Chiedi Aiuto", "getting_started": "Iniziamo", "go_back": "Torna indietro", "go_to_search": "Vai alla ricerca", - "go_to_share_page": "Vai alla pagina condivisione", "group_albums_by": "Raggruppa album in base a...", "group_no": "Nessun raggruppamento", "group_owner": "Raggruppa in base al proprietario", @@ -803,10 +781,6 @@ "image_alt_text_date_place_2_people": "{isVideo, select, true {Video girato} other {Foto scattata}} a {city}, {country} con {person1} e {person2} il giorno {date}", "image_alt_text_date_place_3_people": "{isVideo, select, true {Video girato} other {Foto scattata}} a {city}, {country} con {person1}, {person2}, e {person3} il giorno {date}", "image_alt_text_date_place_4_or_more_people": "{isVideo, select, true {Video girato} other {Foto scattata}} a {city}, {country} con {person1}, {person2} e {additionalCount, number} altre persone il {date}", - "image_alt_text_people": "{count, plural, =1 {con {person1}} =2 {con {person1} e {person2}} =3 {con {person1}, {person2} e {person3}} other {con {person1}, {person2} e {others, number} altri}}", - "image_alt_text_place": "a {city}, {country}", - "image_taken": "{isVideo, select, true {Video registrato} other {Immagine scattata}}", - "img": "", "immich_logo": "Logo Immich", "immich_web_interface": "Interfaccia Web Immich", "import_from_json": "Importa da JSON", @@ -827,10 +801,11 @@ "invite_people": "Invita Persone", "invite_to_album": "Invita nell'album", "items_count": "{count, plural, one {# elemento} other {# elementi}}", - "job_settings_description": "", "jobs": "Processi", "keep": "Mantieni", "keep_all": "Tieni tutto", + "keep_this_delete_others": "Tieni questo, elimina gli altri", + "kept_this_deleted_others": "Mantenuto questo asset ed eliminati {count, plural, one {# asset} other {# assets}}", "keyboard_shortcuts": "Scorciatoie da tastiera", "language": "Lingua", "language_setting_description": "Seleziona la tua lingua predefinita", @@ -842,31 +817,6 @@ "level": "Livello", "library": "Libreria", "library_options": "Impostazioni Libreria", - "license_account_info": "Il tuo account è attivo", - "license_activated_subtitle": "Grazie per supportare Immich e il software open-source", - "license_activated_title": "La tua licenza è stata attivata con successo", - "license_button_activate": "Attiva", - "license_button_buy": "Sborsa", - "license_button_buy_license": "Sborsa per la Licenza", - "license_button_select": "Seleziona", - "license_failed_activation": "Attivazione licenza fallita. Per favore controlla la tua email per la chiave di licenza corretta!", - "license_individual_description_1": "1 licenza per utente su qualsiasi server", - "license_individual_title": "Licenza Individuale", - "license_info_licensed": "Con Licenza", - "license_info_unlicensed": "Senza Licenza", - "license_input_suggestion": "Hai una licenza? Inserisci la chiave qua sotto", - "license_license_subtitle": "Sborsa per una licenza per sopportare Immich", - "license_license_title": "LICENZA", - "license_lifetime_description": "Licenza Lifetime", - "license_per_server": "Per server", - "license_per_user": "Per utente", - "license_server_description_1": "1 licenza per server", - "license_server_description_2": "Licenza per tutti gli utenti sul server", - "license_server_title": "Licenza Server", - "license_trial_info_1": "Stai eseguendo una versione di Immich senza licenza", - "license_trial_info_2": "Stai usando Immich basatamente da circa", - "license_trial_info_3": "{accountAge, plural, one {# day} other {# days}}", - "license_trial_info_4": "Per favore considera sborsare soldi per una licenza e per sopportare il continuo sviluppo del servizio", "light": "Chiaro", "like_deleted": "Mi piace rimosso", "link_motion_video": "Collega video in movimento", @@ -971,7 +921,6 @@ "onboarding_welcome_user": "Benvenuto, {user}", "online": "Online", "only_favorites": "Solo preferiti", - "only_refreshes_modified_files": "Aggiorna solo i file modificati", "open_in_map_view": "Apri nella visualizzazione mappa", "open_in_openstreetmap": "Apri su OpenStreetMap", "open_the_search_filters": "Apri filtri di ricerca", @@ -1009,29 +958,27 @@ "people_edits_count": "{count, plural, one {Modificata # persona} other {Modificate # persone}}", "people_feature_description": "Navigare foto e video raggruppati da persone", "people_sidebar_description": "Mostra un link alle persone nella barra laterale", - "perform_library_tasks": "", "permanent_deletion_warning": "Avviso eliminazione permanente", "permanent_deletion_warning_setting_description": "Mostra un avviso all'eliminazione definitiva di un asset", "permanently_delete": "Elimina definitivamente", "permanently_delete_assets_count": "Cancella definitivamente {count, plural, one {l'asset} other {gli assets}}", "permanently_delete_assets_prompt": "Sei sicuro di voler cancellare definitivamente {count, plural, one {questo asset?} other {# assets?}} Questa operazione {count, plural, one {lo cancellerà dal suo} other {li cancellerà dai loro}} album.", - "permanently_deleted_asset": "Elimina asset definitivamente", + "permanently_deleted_asset": "Asset eliminato definitivamente", "permanently_deleted_assets_count": "Cancellati {count, plural, one {# asset} other {# assets}} definitivamente", "person": "Persona", "person_hidden": "{name}{hidden, select, true { (nascosto)} other {}}", - "photo_shared_all_users": "Sembra che tu abbia condiviso le foto con tutti gli utenti (oppure non hai utenti con cui condividerle).", + "photo_shared_all_users": "Sembra che tu abbia condiviso le foto con tutti gli utenti, oppure che non ci siano utenti con i quali condividerle.", "photos": "Foto", "photos_and_videos": "Foto & Video", "photos_count": "{count, plural, one {{count, number} Foto} other {{count, number} Foto}}", "photos_from_previous_years": "Foto degli anni scorsi", "pick_a_location": "Scegli una posizione", "place": "Posizione", - "places": "Location", + "places": "Luoghi", "play": "Avvia", "play_memories": "Avvia ricordi", "play_motion_photo": "Avvia Foto in movimento", "play_or_pause_video": "Avvia o metti in pausa il video", - "point": "", "port": "Porta", "preset": "Preimpostazione", "preview": "Anteprima", @@ -1076,12 +1023,10 @@ "purchase_server_description_2": "Stato di Contributore", "purchase_server_title": "Server", "purchase_settings_server_activated": "La chiave del prodotto del server è gestita dall'amministratore", - "range": "", "rating": "Valutazione a stelle", "rating_clear": "Crea valutazione", "rating_count": "{count, plural, one {# stella} other {# stelle}}", "rating_description": "Visualizza la valutazione EXIF nel pannello informazioni", - "raw": "", "reaction_options": "Impostazioni Reazioni", "read_changelog": "Leggi Riepilogo Modifiche", "reassign": "Riassegna", @@ -1089,6 +1034,7 @@ "reassigned_assets_to_new_person": "{count, plural, one {Riassegnato # asset} other {Riassegnati # assets}} ad una nuova persona", "reassing_hint": "Assegna gli assets selezionati ad una persona esistente", "recent": "Recenti", + "recent-albums": "Album recenti", "recent_searches": "Ricerche recenti", "refresh": "Aggiorna", "refresh_encoded_videos": "Ricarica video codificati", @@ -1110,6 +1056,7 @@ "remove_from_album": "Rimuovere dall'album", "remove_from_favorites": "Rimuovi dai preferiti", "remove_from_shared_link": "Rimuovi dal link condiviso", + "remove_url": "Rimuovi URL", "remove_user": "Rimuovi utente", "removed_api_key": "Rimossa chiave API: {name}", "removed_from_archive": "Rimosso dall'archivio", @@ -1126,7 +1073,6 @@ "reset": "Ripristina", "reset_password": "Ripristina password", "reset_people_visibility": "Ripristina visibilità persone", - "reset_settings_to_default": "", "reset_to_default": "Ripristina i valori predefiniti", "resolve_duplicates": "Risolvi duplicati", "resolved_all_duplicates": "Tutti i duplicati sono stati risolti", @@ -1146,9 +1092,7 @@ "saved_settings": "Impostazioni salvate", "say_something": "Dici qualcosa", "scan_all_libraries": "Analizza tutte le librerie", - "scan_all_library_files": "Scansiona nuovamente tutti i file della libreria", - "scan_library": "Scan", - "scan_new_library_files": "Analizza i File Nuovi della Libreria", + "scan_library": "Scansione", "scan_settings": "Impostazioni Analisi", "scanning_for_album": "Sto cercando l'album...", "search": "Cerca", @@ -1191,7 +1135,6 @@ "selected_count": "{count, plural, one {# selezionato} other {# selezionati}}", "send_message": "Manda messaggio", "send_welcome_email": "Invia email di benvenuto", - "server": "Server", "server_offline": "Server Offline", "server_online": "Server Online", "server_stats": "Statistiche Server", @@ -1296,17 +1239,17 @@ "they_will_be_merged_together": "Verranno uniti insieme", "third_party_resources": "Risorse di Terze Parti", "time_based_memories": "Ricordi basati sul tempo", + "timeline": "Linea temporale", "timezone": "Fuso orario", "to_archive": "Archivio", "to_change_password": "Modifica password", "to_favorite": "Preferito", "to_login": "Login", "to_parent": "Sali di un livello", - "to_root": "Alla radice", "to_trash": "Cancella", "toggle_settings": "Attiva/disattiva impostazioni", "toggle_theme": "Abilita tema scuro", - "toggle_visibility": "Cambia visibilità", + "total": "Totale", "total_usage": "Utilizzo totale", "trash": "Cestino", "trash_all": "Cestina Tutto", @@ -1316,12 +1259,10 @@ "trashed_items_will_be_permanently_deleted_after": "Gli elementi cestinati saranno eliminati definitivamente dopo {days, plural, one {# giorno} other {# giorni}}.", "type": "Tipo", "unarchive": "Annulla l'archiviazione", - "unarchived": "Rimosso dall'archivio", "unarchived_count": "{count, plural, other {Non archiviati #}}", "unfavorite": "Rimuovi preferito", "unhide_person": "Mostra persona", "unknown": "Sconosciuto", - "unknown_album": "Album sconosciuto", "unknown_year": "Anno sconosciuto", "unlimited": "Illimitato", "unlink_motion_video": "Scollega video in movimento", @@ -1353,13 +1294,13 @@ "use_custom_date_range": "Altrimenti utilizza un intervallo date personalizzato", "user": "Utente", "user_id": "ID utente", - "user_license_settings": "Licenza", - "user_license_settings_description": "Gestisci la tua licenza", "user_liked": "A {user} piace {type, select, photo {questa foto} video {questo video} asset {questo asset} other {questo elemento}}", "user_purchase_settings": "Acquisto", "user_purchase_settings_description": "Gestisci il tuo acquisto", "user_role_set": "Imposta {user} come {role}", "user_usage_detail": "Dettagli utilizzo utente", + "user_usage_stats": "Statistiche d'uso", + "user_usage_stats_description": "Consulta le statistiche d'uso dell'account", "username": "Nome utente", "users": "Utenti", "utilities": "Utilità", @@ -1367,7 +1308,7 @@ "variables": "Variabili", "version": "Versione", "version_announcement_closing": "Il tuo amico, Alex", - "version_announcement_message": "Ehilà! È stata rilasciata una nuova versione dell'applicazione. Leggi le note di rilascio e assicurati che i tuoi file docker-compose.yml/.env siano aggiornati per evitare problemi e incongruenze, soprattutto se utilizzi WatchTower o altri strumenti per aggiornare l'applicazione in automatico.", + "version_announcement_message": "Ehilà! È stata rilasciata una nuova versione di Immich. Leggi le note di rilascio e assicurati che i tuoi file docker-compose.yml/.env siano aggiornati per evitare problemi e incongruenze, soprattutto se utilizzi WatchTower o altri strumenti per aggiornare Immich in automatico.", "version_history": "Storico delle Versioni", "version_history_item": "Versione installata {version} il {date}", "video": "Video", @@ -1381,10 +1322,10 @@ "view_all_users": "Visualizza tutti gli utenti", "view_in_timeline": "Visualizza in timeline", "view_links": "Visualizza i link", + "view_name": "Visualizza", "view_next_asset": "Visualizza risorsa successiva", "view_previous_asset": "Visualizza risorsa precedente", "view_stack": "Visualizza Raggruppamento", - "viewer": "Visualizzatore", "visibility_changed": "Visibilità modificata per {count, plural, one {# persona} other {# persone}}", "waiting": "In Attesa", "warning": "Attenzione", diff --git a/i18n/ja.json b/i18n/ja.json index c220828e54f80..0eb2c880f16fa 100644 --- a/i18n/ja.json +++ b/i18n/ja.json @@ -41,9 +41,7 @@ "confirm_email_below": "確認のため、以下に \"{email}\" と入力してください", "confirm_reprocess_all_faces": "本当にすべての顔を再処理しますか? これにより名前が付けられた人物も消去されます。", "confirm_user_password_reset": "本当に {user} のパスワードをリセットしますか?", - "crontab_guru": "Crontab Guru", "disable_login": "ログインを無効にする", - "disabled": "", "duplicate_detection_job_description": "機械学習を用いて類似画像の検出を行います。(スマートサーチに依存)", "exclusion_pattern_description": "除外パターンを使用すると、ライブラリをスキャンする際にファイルやフォルダを無視することができます。RAWファイルなど、インポートしたくないファイルを含むフォルダがある場合に便利です。", "external_library_created_at": "外部ライブラリ(作成日:{date})", @@ -59,16 +57,9 @@ "image_prefer_embedded_preview_setting_description": "RAW写真の埋め込みプレビューが利用可能な場合に画像処理の入力として使用します。これにより、いくつかの画像でより正確な色を得ることができますが、プレビューの品質はカメラによって異なり、画像により多くの圧縮アーティファクトが含まれる場合があります。", "image_prefer_wide_gamut": "広色域に対応させる", "image_prefer_wide_gamut_setting_description": "サムネイルにはDisplay P3を使用します。これにより、広色域の画像の鮮やかさをよりよく保つことができますが、古いデバイスや古いブラウザバージョンでは画像が異なって見える場合があります。sRGBの画像は、色の変化を避けるためにsRGBのままにします。", - "image_preview_format": "プレビューのファイル形式", - "image_preview_resolution": "プレビュー解像度", - "image_preview_resolution_description": "単一写真のプレビューや機械学習で使用する解像度を設定します。解像度を高くすると細かなディテールを保持できますが、エンコードに時間がかかり、ファイルサイズが大きくなり、アプリの応答性が低下する可能性があります。", "image_quality": "品質", - "image_quality_description": "画像の品質を1から100の範囲で設定します。数値が高いほど品質が良くなりますが、ファイルサイズも大きくなります。このオプションは、プレビュー画像とサムネイル画像に影響します。", "image_settings": "画像設定", "image_settings_description": "生成される画像の品質と解像度の設定", - "image_thumbnail_format": "サムネイルフォーマット", - "image_thumbnail_resolution": "サムネイル解像度", - "image_thumbnail_resolution_description": "複数の写真を閲覧する際(タイムライン、アルバムビューなど)に使用されます。解像度を高くすると細かなディテールを保持できますが、エンコードに時間がかかり、ファイルサイズが大きくなり、アプリの応答性が低下する可能性があります。", "job_concurrency": "{job} の同時実行数", "job_not_concurrency_safe": "このジョブは安全に同時実行できません。", "job_settings": "ジョブ設定", @@ -77,9 +68,6 @@ "jobs_delayed": "{jobCount, plural, other {#件}}の遅延", "jobs_failed": "{jobCount, plural, other {#件}}の失敗", "library_created": "作成されたライブラリ:{library}", - "library_cron_expression": "Cron表記", - "library_cron_expression_description": "cron形式を使用してスキャン間隔を設定します。 詳細については、Crontab Guru などを参照してください", - "library_cron_expression_presets": "Cron表記プリセット", "library_deleted": "ライブラリは削除されました", "library_import_path_description": "インポートするフォルダを指定します。このフォルダはサブフォルダを含めて、画像と動画のスキャンが行われます。", "library_scanning": "定期スキャン", @@ -198,15 +186,12 @@ "refreshing_all_libraries": "すべてのライブラリを更新", "registration": "管理者登録", "registration_description": "あなたはシステムの最初のユーザーであるため、管理者として割り当てられ、管理タスクを担当し、追加のユーザーはあなたによって作成されます。", - "removing_deleted_files": "オフライン ファイルを削除します", "repair_all": "すべてを修復", "repair_matched_items": "一致: {count, plural, one {#件} other {#件}}", "repaired_items": "修復済み: {count, plural, one {#件} other {#件}}", "require_password_change_on_login": "初回ログイン時にパスワード変更を要求する", "reset_settings_to_default": "設定をデフォルトにリセットします", "reset_settings_to_recent_saved": "前回の設定値に戻す", - "scanning_library_for_changed_files": "変更されたファイルを検出するためにライブラリをスキャン中", - "scanning_library_for_new_files": "新しいファイルを検出するためにライブラリをスキャン中", "send_welcome_email": "ウェルカム メール を送信します", "server_external_domain_settings": "外部ドメイン", "server_external_domain_settings_description": "公開共有リンク用のドメイン( http(s):// を含める)", @@ -241,7 +226,6 @@ "these_files_matched_by_checksum": "これらのファイルはチェックサムによって照合されます", "thumbnail_generation_job": "サムネイル生成", "thumbnail_generation_job_description": "各アセットのサムネイル(大、小、ぼかし)と、各人物のサムネイルを生成します", - "transcode_policy_description": "", "transcoding_acceleration_api": "アクセラレーション API", "transcoding_acceleration_api_description": "デバイスでハードウェアトランスコードを行うためのAPIです。この設定は『ベストエフォート』であり、失敗した場合はソフトウェアトランスコードになります。VP9はハードウェアによって機能する場合としない場合があります。", "transcoding_acceleration_nvenc": "NVEnc(NVIDIA GPUが必要)", @@ -293,8 +277,6 @@ "transcoding_threads_description": "値を高くするとエンコード速度が速くなりますが、アクティブな間はサーバーが他のタスクを処理する余裕が少なくなります。この値はCPUのコア数を超えないようにする必要があります。\"0\" に設定すると、最大限利用されます。", "transcoding_tone_mapping": "トーンマッピング", "transcoding_tone_mapping_description": "HDR動画をSDRに変換する際に見た目を維持しようと試みます。各アルゴリズムは、色、詳細、明るさに対して異なるトレードオフを行います。Hableは詳細を維持し、Mobiusは色を維持し、Reinhardは明るさを維持します。", - "transcoding_tone_mapping_npl": "トーンマッピング NPL", - "transcoding_tone_mapping_npl_description": "この明るさの表示で正常に見えるように色が調整されます。直観に反しますが、値を低くするとディスプレイの明るさが補正されてビデオの明るさが増加し、その逆も同様です。0にするとこの値は自動で設定されます。", "transcoding_transcode_policy": "トランスコードポリシー", "transcoding_transcode_policy_description": "動画がトランスコードされるべきかを決めるポリシー。HDR動画は常にトランスコードされます(トランスコードが無効化されている場合を除く)。", "transcoding_two_pass_encoding": "Two-passエンコード", @@ -374,7 +356,6 @@ "archive_or_unarchive_photo": "写真をアーカイブまたはアーカイブ解除", "archive_size": "アーカイブサイズ", "archive_size_description": "ダウンロードのアーカイブ サイズを設定(GiB 単位)", - "archived": "", "archived_count": "アーカイブされた{count, plural, other {#個の項目}}", "are_these_the_same_person": "これらは同じ人物ですか?", "are_you_sure_to_do_this": "本当にこれを行いますか?", @@ -422,10 +403,6 @@ "cannot_merge_people": "人物を統合できません", "cannot_undo_this_action": "この操作は元に戻せません!", "cannot_update_the_description": "説明を更新できません", - "cant_apply_changes": "", - "cant_get_faces": "", - "cant_search_people": "", - "cant_search_places": "", "change_date": "日時を変更", "change_expiration_time": "有効期限を変更", "change_location": "場所を変更", @@ -536,13 +513,6 @@ "duplicates": "重複", "duplicates_description": "もしあれば、重複しているグループを示すことで解決します", "duration": "間隔", - "durations": { - "days": "", - "hours": "", - "minutes": "", - "months": "", - "years": "" - }, "edit": "編集", "edit_album": "アルバムを編集", "edit_avatar": "アバターを編集", @@ -567,8 +537,6 @@ "editor_crop_tool_h2_aspect_ratios": "アスペクト比", "editor_crop_tool_h2_rotation": "回転", "email": "メールアドレス", - "empty": "", - "empty_album": "", "empty_trash": "コミ箱を空にする", "empty_trash_confirmation": "本当にゴミ箱を空にしますか? これにより、ゴミ箱内のすべてのアセットが Immich から永久に削除されます。\nこの操作を元に戻すことはできません!", "enable": "有効化", @@ -629,8 +597,6 @@ "unable_to_change_location": "場所を変更できません", "unable_to_change_password": "パスワードを変更できません", "unable_to_change_visibility": "{count, plural, one {#人} other {#人}}の人物の非表示設定を変更できません", - "unable_to_check_item": "", - "unable_to_check_items": "", "unable_to_complete_oauth_login": "OAuth ログインを完了できません", "unable_to_connect": "接続できません", "unable_to_connect_to_server": "サーバーに接続できません", @@ -670,12 +636,10 @@ "unable_to_remove_album_users": "アルバムからユーザーを削除できません", "unable_to_remove_api_key": "API キーを削除できません", "unable_to_remove_assets_from_shared_link": "共有リンクからアセットを削除できません", - "unable_to_remove_comment": "", "unable_to_remove_deleted_assets": "オフラインのファイルを削除できません", "unable_to_remove_library": "ライブラリを削除できません", "unable_to_remove_partner": "パートナーを削除できません", "unable_to_remove_reaction": "リアクションを削除できません", - "unable_to_remove_user": "", "unable_to_repair_items": "アイテムを修復できません", "unable_to_reset_password": "パスワードをリセットできません", "unable_to_resolve_duplicate": "重複を解決できません", @@ -704,10 +668,6 @@ "unable_to_update_user": "ユーザーを更新できません", "unable_to_upload_file": "ファイルをアップロードできません" }, - "every_day_at_onepm": "", - "every_night_at_midnight": "", - "every_night_at_twoam": "", - "every_six_hours": "", "exif": "Exif", "exit_slideshow": "スライドショーを終わる", "expand_all": "全て展開", @@ -722,33 +682,27 @@ "external": "外部", "external_libraries": "外部ライブラリ", "face_unassigned": "未割り当て", - "failed_to_get_people": "", "favorite": "お気に入り", "favorite_or_unfavorite_photo": "写真をお気に入りまたはお気に入り解除", "favorites": "お気に入り", - "feature": "", "feature_photo_updated": "人物画像が更新されました", - "featurecollection": "", "features": "機能", "features_setting_description": "アプリの機能を管理する", "file_name": "ファイル名", "file_name_or_extension": "ファイル名または拡張子", "filename": "ファイル名", - "files": "", "filetype": "ファイルタイプ", "filter_people": "人物を絞り込み", "find_them_fast": "名前で検索して素早く発見", "fix_incorrect_match": "間違った一致を修正", "folders": "フォルダ", "folders_feature_description": "ファイルシステム上の写真と動画のフォルダビューを閲覧する", - "force_re-scan_library_files": "強制的に全てのライブラリのファイルを再スキャン", "forward": "前へ", "general": "一般", "get_help": "助けを求める", "getting_started": "はじめる", "go_back": "戻る", "go_to_search": "検索へ", - "go_to_share_page": "共有ページへ", "group_albums_by": "これでアルバムをグループ化…", "group_no": "グループ化なし", "group_owner": "所有者でグループ化", @@ -774,9 +728,6 @@ "image_alt_text_date_place_2_people": "{date}の、{country}、{city}での{person1}と{person2}の{isVideo, select, true {動画} other {画像}}", "image_alt_text_date_place_3_people": "{date}の、{country}、{city}での{person1}と{person2}、そして{person3}の{isVideo, select, true {動画} other {画像}}", "image_alt_text_date_place_4_or_more_people": "{date}の、{country}、{city}での{person1}と{person2}、そしてその他{additionalCount, number}人の{isVideo, select, true {動画} other {画像}}", - "image_alt_text_place": "{country} {city}で撮影", - "image_taken": "{isVideo, select, true {動画は} other {写真は}}", - "img": "", "immich_logo": "Immich ロゴ", "immich_web_interface": "Immich Webインターフェース", "import_from_json": "JSONからインポート", @@ -797,7 +748,6 @@ "invite_people": "人々を招待", "invite_to_album": "アルバムに招待", "items_count": "{count, plural, one {#個} other {#個}}の項目", - "job_settings_description": "", "jobs": "ジョブ", "keep": "保持", "keep_all": "全て保持", @@ -913,7 +863,6 @@ "onboarding_welcome_user": "ようこそ、{user} さん", "online": "オンライン", "only_favorites": "お気に入りのみ", - "only_refreshes_modified_files": "変更されたファイルのみを更新します", "open_in_map_view": "地図表示で見る", "open_in_openstreetmap": "OpenStreetMapで開く", "open_the_search_filters": "検索フィルタを開く", @@ -951,7 +900,6 @@ "people_edits_count": "{count, plural, one {#人} other {#人}}が編集済", "people_feature_description": "人物でグループ化された写真と動画を閲覧する", "people_sidebar_description": "人物へのリンクをサイドバーに表示", - "perform_library_tasks": "", "permanent_deletion_warning": "永久削除の警告", "permanent_deletion_warning_setting_description": "アセットを完全に削除するときに警告を表示する", "permanently_delete": "完全に削除", @@ -973,7 +921,6 @@ "play_memories": "メモリーを再生", "play_motion_photo": "モーションビデオを再生", "play_or_pause_video": "動画を再生または一時停止", - "point": "", "port": "ポートレート", "preset": "プリセット", "preview": "プレビュー", @@ -1018,12 +965,10 @@ "purchase_server_description_2": "サポーターの状態", "purchase_server_title": "サーバー", "purchase_settings_server_activated": "サーバーのプロダクトキーは管理者に管理されています", - "range": "", "rating": "星での評価", "rating_clear": "評価を取り消す", "rating_count": "星{count, plural, one {#つ} other {#つ}}", "rating_description": "情報欄にEXIFの評価を表示", - "raw": "", "reaction_options": "リアクションの選択", "read_changelog": "変更履歴を読む", "reassign": "再割り当て", @@ -1066,7 +1011,6 @@ "reset": "リセット", "reset_password": "パスワードをリセット", "reset_people_visibility": "人物の非表示設定をリセット", - "reset_settings_to_default": "", "reset_to_default": "デフォルトにリセット", "resolve_duplicates": "重複を解決する", "resolved_all_duplicates": "全ての重複を解決しました", @@ -1086,8 +1030,6 @@ "saved_settings": "設定を保存しました", "say_something": "何か書き込みましょう", "scan_all_libraries": "全てのライブラリをスキャン", - "scan_all_library_files": "全てのライブラリのファイルを再スキャン", - "scan_new_library_files": "新しいライブラリのファイルをスキャン", "scan_settings": "スキャン設定", "scanning_for_album": "アルバムをスキャン中…", "search": "検索", @@ -1128,7 +1070,6 @@ "selected_count": "{count, plural, other {#個選択済み}}", "send_message": "メッセージを送信", "send_welcome_email": "ウェルカムメールを送信", - "server": "サーバー", "server_offline": "サーバーがオフラインです", "server_online": "サーバーがオンラインです", "server_stats": "サーバー統計", @@ -1230,11 +1171,9 @@ "to_change_password": "パスワードを変更", "to_favorite": "お気に入り", "to_login": "ログイン", - "to_root": "最上層のフォルダへ", "to_trash": "ゴミ箱", "toggle_settings": "設定をトグル", "toggle_theme": "ダークテーマを切り替え", - "toggle_visibility": "", "total_usage": "総使用量", "trash": "ゴミ箱", "trash_all": "全て削除", @@ -1244,12 +1183,10 @@ "trashed_items_will_be_permanently_deleted_after": "ゴミ箱に入れられたアイテムは{days, plural, one {#日} other {#日}}後に完全に削除されます。", "type": "タイプ", "unarchive": "アーカイブを解除", - "unarchived": "", "unarchived_count": "{count, plural, other {#枚アーカイブしました}}", "unfavorite": "お気に入りから外す", "unhide_person": "人物の非表示を解除", "unknown": "不明", - "unknown_album": "", "unknown_year": "不明な年", "unlimited": "無制限", "unlink_oauth": "OAuthのリンクを解除", @@ -1307,7 +1244,6 @@ "view_next_asset": "次のアセットを見る", "view_previous_asset": "前のアセットを見る", "view_stack": "ビュースタック", - "viewer": "", "visibility_changed": "{count, plural, one {#人} other {#人}}の人物の非表示設定が変更されました", "waiting": "待機中", "warning": "警告", diff --git a/i18n/kmr.json b/i18n/kmr.json index 9d8bd29808e88..a764851442462 100644 --- a/i18n/kmr.json +++ b/i18n/kmr.json @@ -34,7 +34,6 @@ "confirm_email_below": "", "confirm_reprocess_all_faces": "", "confirm_user_password_reset": "", - "crontab_guru": "", "disable_login": "", "duplicate_detection_job_description": "", "exclusion_pattern_description": "", @@ -50,16 +49,9 @@ "image_prefer_embedded_preview_setting_description": "", "image_prefer_wide_gamut": "", "image_prefer_wide_gamut_setting_description": "", - "image_preview_format": "", - "image_preview_resolution": "", - "image_preview_resolution_description": "", "image_quality": "", - "image_quality_description": "", "image_settings": "", "image_settings_description": "", - "image_thumbnail_format": "", - "image_thumbnail_resolution": "", - "image_thumbnail_resolution_description": "", "job_concurrency": "", "job_not_concurrency_safe": "", "job_settings": "", @@ -68,8 +60,6 @@ "jobs_delayed": "", "jobs_failed": "", "library_created": "", - "library_cron_expression": "", - "library_cron_expression_presets": "", "library_deleted": "", "library_import_path_description": "", "library_scanning": "", @@ -177,15 +167,12 @@ "paths_validated_successfully": "", "quota_size_gib": "", "refreshing_all_libraries": "", - "removing_deleted_files": "", "repair_all": "", "repair_matched_items": "", "repaired_items": "", "require_password_change_on_login": "", "reset_settings_to_default": "", "reset_settings_to_recent_saved": "", - "scanning_library_for_changed_files": "", - "scanning_library_for_new_files": "", "send_welcome_email": "", "server_external_domain_settings": "", "server_external_domain_settings_description": "", @@ -260,8 +247,6 @@ "transcoding_threads_description": "", "transcoding_tone_mapping": "", "transcoding_tone_mapping_description": "", - "transcoding_tone_mapping_npl": "", - "transcoding_tone_mapping_npl_description": "", "transcoding_transcode_policy": "", "transcoding_transcode_policy_description": "", "transcoding_two_pass_encoding": "", @@ -315,7 +300,6 @@ "archive_or_unarchive_photo": "", "archive_size": "", "archive_size_description": "", - "archived": "", "asset_offline": "", "assets": "", "authorized_devices": "", @@ -329,10 +313,6 @@ "cancel_search": "", "cannot_merge_people": "", "cannot_update_the_description": "", - "cant_apply_changes": "", - "cant_get_faces": "", - "cant_search_people": "", - "cant_search_places": "", "change_date": "", "change_expiration_time": "", "change_location": "", @@ -421,13 +401,6 @@ "downloading": "", "duplicates": "", "duration": "", - "durations": { - "days": "", - "hours": "", - "minutes": "", - "months": "", - "years": "" - }, "edit_album": "", "edit_avatar": "", "edit_date": "", @@ -446,7 +419,6 @@ "edited": "", "editor": "", "email": "", - "empty_album": "", "empty_trash": "", "end_date": "", "error": "", @@ -530,7 +502,6 @@ "extension": "", "external": "", "external_libraries": "", - "failed_to_get_people": "", "favorite": "", "favorite_or_unfavorite_photo": "", "favorites": "", @@ -542,14 +513,12 @@ "filter_people": "", "find_them_fast": "", "fix_incorrect_match": "", - "force_re-scan_library_files": "", "forward": "", "general": "", "get_help": "", "getting_started": "", "go_back": "", "go_to_search": "", - "go_to_share_page": "", "group_albums_by": "", "has_quota": "", "hide_gallery": "", @@ -665,7 +634,6 @@ "oldest_first": "", "online": "", "only_favorites": "", - "only_refreshes_modified_files": "", "open_the_search_filters": "", "options": "", "organize_your_library": "", @@ -754,8 +722,6 @@ "saved_settings": "", "say_something": "", "scan_all_libraries": "", - "scan_all_library_files": "", - "scan_new_library_files": "", "scan_settings": "", "search": "", "search_albums": "", @@ -786,7 +752,6 @@ "selected": "", "send_message": "", "send_welcome_email": "", - "server": "", "server_stats": "", "set": "", "set_as_album_cover": "", @@ -857,7 +822,6 @@ "to_favorite": "", "toggle_settings": "", "toggle_theme": "", - "toggle_visibility": "", "total_usage": "", "trash": "", "trash_all": "", @@ -865,11 +829,9 @@ "trashed_items_will_be_permanently_deleted_after": "", "type": "", "unarchive": "", - "unarchived": "", "unfavorite": "", "unhide_person": "", "unknown": "", - "unknown_album": "", "unknown_year": "", "unlimited": "", "unlink_oauth": "", @@ -903,7 +865,6 @@ "view_links": "", "view_next_asset": "", "view_previous_asset": "", - "viewer": "", "waiting": "", "week": "", "welcome": "", diff --git a/i18n/ko.json b/i18n/ko.json index d3fd6c9022389..a58e20244ad45 100644 --- a/i18n/ko.json +++ b/i18n/ko.json @@ -27,13 +27,18 @@ "added_to_favorites": "즐겨찾기에 추가되었습니다.", "added_to_favorites_count": "즐겨찾기에 항목 {count, number}개 추가됨", "admin": { - "add_exclusion_pattern_description": "규칙에 *, ** 및 ? 를 사용할 수 있습니다. \"Raw\" 디렉터리의 모든 파일을 제외하려면 **/Raw/**를, \".tif\"로 끝나는 파일을 제외하려면 **/*.tif를 사용합니다. 절대 경로는 /path/to/ignore/** 와 같은 방식으로 사용하세요.", - "asset_offline_description": "이 외부 라이브러리 항목을 디스크에서 찾을 수 없어 휴지통으로 이동되었습니다. 라이브러리 내에서 파일이 이동된 경우 해당하는 새 항목을 타임라인에서 확인하세요. 이 항목을 복원하려면 파일 경로에 Immich가 접근할 수 있는지 확인한 후, 라이브러리 스캔을 진행하세요.", + "add_exclusion_pattern_description": "규칙에 *, ** 및 ? 를 사용할 수 있습니다. 이름이 \"Raw\"인 디렉터리의 모든 파일을 제외하려면 \"**/Raw/**\"를, \".tif\"로 끝나는 모든 파일을 제외하려면 \"**/*.tif\"를 사용하고, 절대 경로의 경우 \"/path/to/ignore/**\"와 같은 방식으로 사용합니다.", + "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_settings": "백업 설정", + "backup_settings_description": "데이터베이스 백업 설정 관리", "check_all": "모두 확인", "cleared_jobs": "작업 중단: {job}", "config_set_by_file": "현재 설정은 구성 파일에 의해 관리됩니다.", @@ -43,42 +48,36 @@ "confirm_reprocess_all_faces": "모든 얼굴을 다시 처리하시겠습니까? 이름이 지정된 인물을 포함한 모든 인물이 삭제됩니다.", "confirm_user_password_reset": "{user}님의 비밀번호를 재설정하시겠습니까?", "create_job": "작업 생성", - "crontab_guru": "Crontab Guru", + "cron_expression": "Cron 표현식", + "cron_expression_description": "Cron 형식을 사용하여 스캔 주기를 설정합니다. 자세한 내용과 예시는 Crontab Guru를 참조하세요.", + "cron_expression_presets": "Cron 표현식 사전 설정", "disable_login": "로그인 비활성화", - "disabled": "비활성화", "duplicate_detection_job_description": "기계 학습을 통해 유사한 이미지를 감지합니다. 스마트 검색이 활성화되어 있어야 합니다.", - "exclusion_pattern_description": "제외 규칙을 사용하면 스캔 중 특정 파일과 폴더를 제외할 수 있습니다. 가져오고 싶지 않은 파일(RAW 파일 등)이 존재하는 경우 유용합니다.", + "exclusion_pattern_description": "제외 규칙을 사용하여 라이브러리 스캔 시 특정 파일과 폴더를 제외할 수 있습니다. 폴더에 원하지 않는 파일(RAW 파일 등)이 존재하는 경우 유용합니다.", "external_library_created_at": "외부 라이브러리 ({date}에 생성됨)", "external_library_management": "외부 라이브러리 관리", "face_detection": "얼굴 감지", - "face_detection_description": "기계 학습을 통해 항목에 존재하는 얼굴을 감지합니다. 동영상의 경우 섬네일만 사용합니다. \"새로고침\"은 이미 처리된 항목을 포함한 모든 항목 다시 처리합니다. \"초기화\"는 모든 얼굴 데이터를 삭제합니다. \"누락\"은 처리되지 않은 항목을 대기열에 추가합니다. 얼굴 감지 작업이 완료된 후 얼굴 인식 작업을 진행하여 얼굴을 기존 인물이나 새 인물로 그룹화합니다.", - "facial_recognition_job_description": "감지된 얼굴을 인물로 그룹화합니다. 이 작업은 얼굴 감지 작업이 완료된 후 진행됩니다. \"초기화\"는 모든 얼굴의 그룹화를 다시 진행합니다. \"누락\"은 그룹화가 완료되지 않은 얼굴을 대기열에 추가합니다.", + "face_detection_description": "기계 학습을 통해 항목에 존재하는 얼굴을 감지합니다. 동영상의 경우 섬네일만 사용합니다. \"새로고침\"은 이미 처리된 항목을 포함한 모든 항목을 다시 처리합니다. \"초기화\"는 모든 얼굴 데이터를 삭제합니다. \"누락\"은 처리되지 않은 항목을 대기열에 추가합니다. 얼굴 감지 작업이 완료되면 얼굴 인식 작업이 진행되어 감지된 얼굴을 기존 인물이나 새 인물로 그룹화합니다.", + "facial_recognition_job_description": "감지된 얼굴을 인물로 그룹화합니다. 이 작업은 얼굴 감지 작업이 완료된 후 진행됩니다. \"초기화\"는 모든 얼굴의 그룹화를 다시 진행합니다. \"누락\"은 그룹화되지 않은 얼굴을 대기열에 추가합니다.", "failed_job_command": "{job} 작업에서 {command} 실패", "force_delete_user_warning": "경고: 사용자 및 사용자가 업로드한 모든 항목이 즉시 삭제됩니다. 이 작업은 되돌릴 수 없으며 파일을 복구할 수 없습니다.", - "forcing_refresh_library_files": "모든 파일을 다시 스캔하는 중...", + "forcing_refresh_library_files": "라이브러리의 모든 파일을 다시 스캔하는 중...", "image_format": "형식", "image_format_description": "WebP는 JPEG보다 파일 크기가 작지만 변환에 더 많은 시간이 소요됩니다.", "image_prefer_embedded_preview": "포함된 미리 보기 선호", "image_prefer_embedded_preview_setting_description": "가능한 경우 이미지 처리 시 RAW 사진에 포함된 미리 보기를 사용합니다. 포함된 미리 보기는 카메라에서 생성된 것으로 카메라마다 품질이 다릅니다. 일부 이미지의 경우 더 정확한 색상이 표현될 수 있지만 반대로 더 많은 아티팩트가 있을 수도 있습니다.", "image_prefer_wide_gamut": "넓은 색 영역 선호", "image_prefer_wide_gamut_setting_description": "섬네일 이미지에 Display P3을 사용합니다. 많은 색상을 표현할 수 있어 더 정확한 표현이 가능하지만, 오래된 브라우저를 사용하는 경우 이미지가 다르게 보일 수 있습니다. 색상 왜곡을 방지하기 위해 sRGB 이미지는 이 설정이 적용되지 않습니다.", - "image_preview_description": "메타데이터를 제거한 중간 크기 이미지, 한장씩 볼때나 기계학습에 사용됨", - "image_preview_format": "미리 보기 형식", - "image_preview_quality_description": "1부터 100 사이의 미리보기 품질. 값이 높을수록 좋지만 파일 크기가 커져 앱의 반응성이 떨어질 수 있습니다. 또한 값이 낮으면 기계 학습의 품질이 떨어질 수 있습니다.", - "image_preview_resolution": "미리 보기 해상도", - "image_preview_resolution_description": "사진을 보거나 기계 학습을 실행할 때 사용되는 사진의 해상도를 설정합니다. 높은 해상도를 선택하면 세부 묘사의 손실을 최소화할 수 있지만, 인코딩 시간과 파일 크기가 증가하여 앱의 반응 속도가 느려질 수 있습니다.", + "image_preview_description": "메타데이터를 제거한 중간 크기의 이미지, 단일 항목을 보는 경우 및 기계 학습에 사용됨", + "image_preview_quality_description": "1부터 100 사이의 미리보기 품질. 값이 높을수록 좋지만 파일 크기가 커져 앱의 반응성이 떨어질 수 있으며, 값이 낮으면 기계 학습의 품질이 떨어질 수 있습니다.", "image_preview_title": "미리보기 설정", "image_quality": "품질", - "image_quality_description": "이미지 품질을 1에서 100 사이로 설정합니다. 높은 품질을 선택하면 파일 크기가 증가하지만 생성된 이미지의 품질이 향상됩니다. 이 옵션은 미리 보기 및 섬네일 이미지에 영향을 미칩니다.", "image_resolution": "해상도", "image_resolution_description": "해상도가 높을 수록 디테일이 보존되지만 파일이 크고 인코딩이 오래 걸리며 앱 응답성이 떨어질 수 있습니다.", "image_settings": "이미지 설정", "image_settings_description": "생성된 이미지의 품질 및 해상도 관리", "image_thumbnail_description": "메타데이터가 제거된 작은 섬네일 이미지, 타임라인 등 사진을 그룹화하여 보는 경우에 사용됨", - "image_thumbnail_format": "섬네일 형식", "image_thumbnail_quality_description": "섬네일 품질(1~100). 높을수록 좋지만 파일크기가 커져 앱의 반응성이 떨어질 수 있습니다.", - "image_thumbnail_resolution": "섬네일 해상도", - "image_thumbnail_resolution_description": "여러 항목을 표시할 때 사용되는 사진의 해상도를 설정합니다. (메인 타임라인, 앨범 보기 등) 높은 해상도를 선택하면 세부 묘사의 손실을 최소화할 수 있지만, 인코딩 시간과 파일 크기가 증가하여 앱의 반응 속도가 느려질 수 있습니다.", "image_thumbnail_title": "섬네일 설정", "job_concurrency": "{job} 동시성", "job_created": "작업이 생성되었습니다.", @@ -89,9 +88,6 @@ "jobs_delayed": "{jobCount, plural, other {#개}} 지연", "jobs_failed": "{jobCount, plural, other {#개}} 실패", "library_created": "{library} 라이브러리를 생성했습니다.", - "library_cron_expression": "Cron 표현식", - "library_cron_expression_description": "cron 형식을 사용하여 스캔 주기를 설정합니다. 자세한 내용 및 예제는 Crontab Guru를 참조하세요.", - "library_cron_expression_presets": "Cron 표현식 사전 설정", "library_deleted": "라이브러리가 삭제되었습니다.", "library_import_path_description": "가져올 폴더를 선택하세요. 선택한 폴더 및 하위 폴더에서 사진과 동영상을 스캔합니다.", "library_scanning": "주기적 스캔", @@ -102,38 +98,38 @@ "library_tasks_description": "라이브러리 구성 및 확인 작업 수행", "library_watching_enable_description": "외부 라이브러리의 파일 변경 감시", "library_watching_settings": "라이브러리 감시 (실험 기능)", - "library_watching_settings_description": "변경된 파일을 자동으로 감지", - "logging_enable_description": "로깅 활성화", - "logging_level_description": "로깅이 활성화된 경우 사용할 로그 레벨을 선택합니다.", - "logging_settings": "로깅", + "library_watching_settings_description": "파일 변겅을 자동으로 감지", + "logging_enable_description": "로그 기록 활성화", + "logging_level_description": "활성화된 경우 사용할 로그 레벨을 선택합니다.", + "logging_settings": "로그 설정", "machine_learning_clip_model": "CLIP 모델", - "machine_learning_clip_model_description": "CLIP 모델의 종류는 이곳을 참조하세요. 한국어로 검색하려면 Multilingual CLIP 모델을 선택하세요. 변경 후 모든 항목에 대한 스마트 검색 작업을 다시 진행해야 합니다.", + "machine_learning_clip_model_description": "CLIP 모델의 종류는 이곳을 참조하세요. 한국어 등 다국어 검색을 사용하려면 Multilingual CLIP 모델을 선택하세요. 모델을 변경한 후 모든 항목에 대한 스마트 검색 작업을 다시 진행해야 합니다.", "machine_learning_duplicate_detection": "비슷한 항목 감지", "machine_learning_duplicate_detection_enabled": "비슷한 항목 감지 활성화", - "machine_learning_duplicate_detection_enabled_description": "비활성화된 경우에도 완전히 일치하는 항목은 여전히 감지됩니다.", + "machine_learning_duplicate_detection_enabled_description": "비활성화된 경우에도 완전히 동일한 항목은 중복 제거됩니다.", "machine_learning_duplicate_detection_setting_description": "CLIP 임베딩을 사용하여 비슷한 항목 찾기", "machine_learning_enabled": "기계 학습 활성화", - "machine_learning_enabled_description": "비활성화하는 경우 기계 학습 설정 여부와 관계없이 모든 기계 학습 기능이 비활성화됩니다.", + "machine_learning_enabled_description": "비활성화된 경우 아래 설정 여부와 관계없이 모든 기계 학습 기능이 비활성화됩니다.", "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_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_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_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_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_log_settings": "로그 설정 관리", @@ -141,7 +137,7 @@ "map_enable_description": "지도 기능 활성화", "map_gps_settings": "지도 및 GPS 설정", "map_gps_settings_description": "지도 및 GPS (역지오코딩) 설정 관리", - "map_implications": "지도 기능은 외부 타일 서비스(tiles.immich.clou를 사용합니다.", + "map_implications": "지도 기능은 외부 타일 서비스(tiles.immich.cloud)에 의존합니다.", "map_light_style": "라이트 스타일", "map_manage_reverse_geocoding_settings": "역지오코딩 설정 관리", "map_reverse_geocoding": "역지오코딩", @@ -162,7 +158,7 @@ "no_pattern_added": "추가된 규칙 없음", "note_apply_storage_label_previous_assets": "참고: 이전에 업로드한 항목에도 스토리지 레이블을 적용하려면 다음을 실행합니다,", "note_cannot_be_changed_later": "주의: 추후 변경할 수 없습니다!", - "note_unlimited_quota": "참고: 할당량을 설정하지 않으려면 0을 입력하세요.", + "note_unlimited_quota": "참고: 무제한 할당량의 경우 0을 입력하세요.", "notification_email_from_address": "보낸 사람 이메일", "notification_email_from_address_description": "보낸 사람의 이메일 주소, 예: \"Immich Photo Server \"", "notification_email_host_description": "이메일 서버의 호스트 (예: smtp.immich.app)", @@ -203,7 +199,7 @@ "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 단위의 기본 할당량 (무제한 할당량의 경우 0 입력)", "offline_paths": "누락된 파일", "offline_paths_description": "외부 라이브러리의 항목이 아닌 파일을 수동으로 삭제한 경우 발생할 수 있습니다.", "password_enable_description": "이메일과 비밀번호로 로그인", @@ -213,18 +209,15 @@ "person_cleanup_job": "인물 정리", "quota_size_gib": "할당량 (GiB)", "refreshing_all_libraries": "모든 라이브러리 다시 스캔 중...", - "registration": "관리자 가입", - "registration_description": "첫 번째 사용자이기 때문에 관리자로 지정되었습니다. 관리 작업 및 사용자 생성이 가능합니다.", - "removing_deleted_files": "누락된 파일을 제거하는 중...", + "registration": "관리자 계정 생성", + "registration_description": "첫 번째로 생성되는 사용자는 관리자 권한을 부여받으며, 관리 및 사용자 생성이 가능합니다.", "repair_all": "모두 수리", - "repair_matched_items": "동일한 항목 {count, plural, one {#개} other {#개}}를 확인했습니다.", + "repair_matched_items": "동일 항목 {count, plural, one {#개} other {#개}}를 확인했습니다.", "repaired_items": "항목 {count, plural, one {#개} other {#개}}를 수리했습니다.", "require_password_change_on_login": "첫 로그인 시 비밀번호 변경 요구", "reset_settings_to_default": "설정을 기본값으로 복원", "reset_settings_to_recent_saved": "마지막으로 저장된 설정으로 복원", "scanning_library": "라이브러리 스캔 중", - "scanning_library_for_changed_files": "라이브러리 변경 사항 확인 중...", - "scanning_library_for_new_files": "라이브러리에서 새 파일 스캔 중...", "search_jobs": "작업 검색...", "send_welcome_email": "환영 이메일 전송", "server_external_domain_settings": "외부 도메인", @@ -232,10 +225,10 @@ "server_settings": "서버 설정", "server_settings_description": "서버 설정 관리", "server_welcome_message": "환영 메시지", - "server_welcome_message_description": "로그인 페이지에 표시되는 메시지를 설정합니다.", + "server_welcome_message_description": "로그인 페이지에 표시되는 메시지입니다.", "sidecar_job": "사이드카 메타데이터", "sidecar_job_description": "파일 시스템에서 사이드카 메타데이터 파일 탐색 및 동기화", - "slideshow_duration_description": "각 사진을 표시할 초 단위의 시간", + "slideshow_duration_description": "개별 사진이 표시되는 초 단위의 시간", "smart_search_job_description": "기계 학습을 진행하여 스마트 검색 기능 지원", "storage_template_date_time_description": "항목이 생성된 날짜의 타임스탬프를 날짜 및 시간 정보로 사용합니다.", "storage_template_date_time_sample": "시간 형식 예: {date}", @@ -258,10 +251,9 @@ "theme_custom_css_settings_description": "Immich에 적용할 사용자 정의 CSS(Cascading Style Sheets) 설정", "theme_settings": "테마 설정", "theme_settings_description": "Immich 웹 인터페이스 사용자 정의", - "these_files_matched_by_checksum": "동일한 체크섬을 가진 파일 목록입니다.", + "these_files_matched_by_checksum": "체크섬이 동일한 파일 목록입니다.", "thumbnail_generation_job": "섬네일 생성", "thumbnail_generation_job_description": "각 항목에 대한 큰 섬네일, 작은 섬네일, 흐린 섬네일 및 인물 섬네일 생성", - "transcode_policy_description": "", "transcoding_acceleration_api": "가속 API", "transcoding_acceleration_api_description": "트랜스코딩 가속을 위해 기기와 상호 작용할 API입니다. 이 설정은 '최선의 노력'으로, 실패 시 소프트웨어 트랜스코딩을 사용합니다. VP9의 작동 여부는 하드웨어에 따라 달라질 수 있습니다.", "transcoding_acceleration_nvenc": "NVENC (NVIDIA GPU 필요)", @@ -278,7 +270,7 @@ "transcoding_audio_codec": "오디오 코덱", "transcoding_audio_codec_description": "Opus는 가장 좋은 품질의 옵션이지만 기기 및 소프트웨어가 오래된 경우 호환되지 않을 수 있습니다.", "transcoding_bitrate_description": "최대 비트레이트를 초과하는 동영상 또는 허용되지 않는 형식의 동영상", - "transcoding_codecs_learn_more": "이곳에서 사용되는 용어에 대한 자세한 내용은 FFmpeg 문서의 H.264 코덱, HEVC 코덱VP9 코덱을 참조하세요.", + "transcoding_codecs_learn_more": "여기에서 사용되는 용어에 대한 자세한 내용은 FFmpeg 문서의 H.264 코덱, HEVC 코덱VP9 코덱 항목을 참조하세요.", "transcoding_constant_quality_mode": "Constant quality mode", "transcoding_constant_quality_mode_description": "ICQ는 CQP보다 나은 성능을 보이나 일부 기기의 하드웨어 가속에서 지원되지 않을 수 있습니다. 이 옵션을 설정하면 품질 기반 인코딩 시 지정된 모드를 우선적으로 사용합니다. NVENC에서는 ICQ를 지원하지 않아 이 설정이 적용되지 않습니다.", "transcoding_constant_rate_factor": "Constant rate factor (-crf)", @@ -313,8 +305,6 @@ "transcoding_threads_description": "값이 높으면 인코딩 속도가 향상되지만 리소스 사용량이 증가합니다. 값은 CPU 코어 수보다 작아야 하며, 설정하지 않으려면 0을 입력합니다.", "transcoding_tone_mapping": "톤 매핑", "transcoding_tone_mapping_description": "HDR 동영상을 SDR로 변환할 때 사용할 톤 매핑 알고리즘을 설정합니다. 알고리즘마다 중점을 두는 부분에 차이가 있습니다. Hable 알고리즘은 세부 묘사를 보존하고, Mobius 알고리즘은 색상을 보존하며, Reinhard 알고리즘은 밝기를 보존합니다.", - "transcoding_tone_mapping_npl": "톤 매핑 NPL", - "transcoding_tone_mapping_npl_description": "현재 화면의 밝기에서 색상이 정상적으로 보이도록 조정합니다. 화면 밝기를 보정하기에 낮은 값과 높은 값 모두 동영상의 밝기를 높입니다. 0을 입력한 경우 자동으로 설정합니다.", "transcoding_transcode_policy": "트랜스코드 정책", "transcoding_transcode_policy_description": "트랜스코딩할 동영상을 설정합니다. HDR 영상은 항상 트랜스코딩을 진행합니다. (트랜스코딩이 비활성화된 경우 제외)", "transcoding_two_pass_encoding": "투 패스 인코딩", @@ -386,7 +376,7 @@ "allow_public_user_to_upload": "모든 사용자의 업로드 허용", "anti_clockwise": "반시계 방향", "api_key": "API 키", - "api_key_description": "이 값은 한 번만 표시됩니다. 창을 닫기 전 반드시 복사하세요.", + "api_key_description": "이 값은 한 번만 표시됩니다. 창을 닫기 전 반드시 복사해주세요.", "api_key_empty": "키 이름은 비어 있을 수 없습니다.", "api_keys": "API 키", "app_settings": "앱 설정", @@ -395,7 +385,6 @@ "archive_or_unarchive_photo": "보관함으로 이동 또는 제거", "archive_size": "압축 파일 크기", "archive_size_description": "다운로드할 압축 파일의 크기 구성 (GiB 단위)", - "archived": "보관됨", "archived_count": "보관함으로 항목 {count, plural, other {#개}} 이동됨", "are_these_the_same_person": "동일한 인물인가요?", "are_you_sure_to_do_this": "계속 진행하시겠습니까?", @@ -416,7 +405,6 @@ "assets_added_to_album_count": "앨범에 항목 {count, plural, one {#개} other {#개}} 추가됨", "assets_added_to_name_count": "{hasName, select, true {{name}} other {새 앨범}}에 항목 {count, plural, one {#개} other {#개}} 추가됨", "assets_count": "{count, plural, one {#개} other {#개}} 항목", - "assets_moved_to_trash": "항목 {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 {#개}}를 제거했습니다.", @@ -446,10 +434,6 @@ "cannot_merge_people": "인물을 병합할 수 없습니다.", "cannot_undo_this_action": "이 작업은 되돌릴 수 없습니다!", "cannot_update_the_description": "설명을 변경할 수 없습니다.", - "cant_apply_changes": "변경 사항을 적용할 수 없음", - "cant_get_faces": "얼굴을 가져올 수 없음", - "cant_search_people": "인물을 검색할 수 없음", - "cant_search_places": "장소를 검색할 수 없음", "change_date": "날짜 변경", "change_expiration_time": "만료일 변경", "change_location": "위치 변경", @@ -458,7 +442,7 @@ "change_password": "비밀번호 변경", "change_password_description": "첫 로그인이거나 비밀번호가 초기화되어 비밀번호를 설정해야 합니다. 아래에 새 비밀번호를 입력하세요.", "change_your_password": "비밀번호 변경", - "changed_visibility_successfully": "숨김 여부가 성공적으로 변경되었습니다.", + "changed_visibility_successfully": "표시 여부가 성공적으로 변경되었습니다.", "check_all": "모두 확인", "check_logs": "로그 확인", "choose_matching_people_to_merge": "병합할 인물 선택", @@ -549,7 +533,7 @@ "display_order": "표시 순서", "display_original_photos": "원본 이미지 표시", "display_original_photos_setting_description": "원본 사진이 웹과 호환되는 경우 섬네일 대신 원본을 표시합니다. 사진이 표시되는 속도가 느려질 수 있습니다.", - "do_not_show_again": "다시 표시하지 않음", + "do_not_show_again": "이 메시지를 다시 표시하지 않음", "documentation": "문서", "done": "완료", "download": "다운로드", @@ -563,41 +547,32 @@ "duplicates": "비슷한 항목", "duplicates_description": "비슷한 항목들을 확인하고, 유지하거나 삭제할 항목 선택", "duration": "기간", - "durations": { - "days": "", - "hours": "", - "minutes": "", - "months": "", - "years": "" - }, "edit": "편집", "edit_album": "앨범 수정", - "edit_avatar": "프로필 편집", + "edit_avatar": "프로필 수정", "edit_date": "날짜 변경", "edit_date_and_time": "날짜 및 시간 변경", - "edit_exclusion_pattern": "제외 규칙 편집", - "edit_faces": "인물 변경", - "edit_import_path": "가져올 경로 편집", - "edit_import_paths": "가져올 경로 편집", + "edit_exclusion_pattern": "제외 규칙 수정", + "edit_faces": "얼굴 수정", + "edit_import_path": "가져올 경로 수정", + "edit_import_paths": "가져올 경로 수정", "edit_key": "키 수정", - "edit_link": "링크 편집", + "edit_link": "링크 수정", "edit_location": "위치 변경", "edit_name": "이름 변경", - "edit_people": "인물 변경", - "edit_tag": "태그 편집", + "edit_people": "인물 수정", + "edit_tag": "태그 수정", "edit_title": "제목 변경", "edit_user": "사용자 수정", "edited": "공유 링크가 수정되었습니다.", "editor": "편집자", - "editor_close_without_save_prompt": "변경 사항이 반영되지 않습니다.", + "editor_close_without_save_prompt": "변경 사항이 저장되지 않습니다.", "editor_close_without_save_title": "편집을 종료하시겠습니까?", "editor_crop_tool_h2_aspect_ratios": "종횡비", "editor_crop_tool_h2_rotation": "회전", "email": "이메일", - "empty": "", - "empty_album": "", "empty_trash": "휴지통 비우기", - "empty_trash_confirmation": "휴지통을 비우시겠습니까? 휴지통에 있는 모든 항목이 Immich에서 영구적으로 제거됩니다. 이 작업은 되돌릴 수 없습니다!", + "empty_trash_confirmation": "휴지통을 비우시겠습니까? 휴지통에 있는 모든 항목이 Immich에서 영구적으로 삭제됩니다. 이 작업은 되돌릴 수 없습니다!", "enable": "활성화", "enabled": "활성화됨", "end_date": "종료일", @@ -609,29 +584,29 @@ "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": "장소를 검색할 수 없음", "cleared_jobs": "{job} 작업 중단됨", - "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_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_job_command": "{job} 작업 {command} 실패", "failed_to_create_album": "앨범을 생성하지 못했습니다.", "failed_to_create_shared_link": "공유 링크를 생성하지 못했습니다.", - "failed_to_edit_shared_link": "공유 링크를 편집하지 못했습니다.", - "failed_to_get_people": "인물을 불러오지 못했습니다.", - "failed_to_load_asset": "항목을 불러오지 못했습니다.", - "failed_to_load_assets": "항목을 불러오지 못했습니다.", - "failed_to_load_people": "인물을 불러오지 못했습니다.", + "failed_to_edit_shared_link": "공유 링크를 수정하지 못했습니다.", + "failed_to_get_people": "인물 로드 실패", + "failed_to_load_asset": "항목 로드 실패", + "failed_to_load_assets": "항목 로드 실패", + "failed_to_load_people": "인물 로드 실패", "failed_to_remove_product_key": "제품 키를 제거하지 못했습니다.", "failed_to_stack_assets": "스택을 만들지 못했습니다.", "failed_to_unstack_assets": "스택을 해제하지 못했습니다.", @@ -652,12 +627,10 @@ "unable_to_archive_unarchive": "{archived, select, true {보관함으로 항목을 이동할} other {보관함에서 항목을 제거할}} 수 없습니다.", "unable_to_change_album_user_role": "사용자의 역할을 변경할 수 없습니다.", "unable_to_change_date": "날짜를 변경할 수 없습니다.", - "unable_to_change_favorite": "즐겨찾기 상태를 변경할 수 없습니다.", + "unable_to_change_favorite": "즐겨찾기에 추가/제거할 수 없습니다.", "unable_to_change_location": "위치를 변경할 수 없습니다.", "unable_to_change_password": "비밀번호를 변경할 수 없습니다.", - "unable_to_change_visibility": "인물 {count, plural, one {#명} other {#명}}의 숨김 여부를 변경할 수 없습니다.", - "unable_to_check_item": "", - "unable_to_check_items": "", + "unable_to_change_visibility": "인물 {count, plural, one {#명} other {#명}}의 표시 여부를 변경할 수 없음", "unable_to_complete_oauth_login": "OAuth 로그인을 완료할 수 없습니다.", "unable_to_connect": "연결할 수 없음", "unable_to_connect_to_server": "서버에 연결할 수 없습니다.", @@ -668,18 +641,18 @@ "unable_to_create_user": "사용자를 생성할 수 없습니다.", "unable_to_delete_album": "앨범을 삭제할 수 없습니다.", "unable_to_delete_asset": "항목을 삭제할 수 없습니다.", - "unable_to_delete_assets": "항목을 삭제하는 중 문제가 발생했습니다.", + "unable_to_delete_assets": "항목 삭제 중 오류 발생", "unable_to_delete_exclusion_pattern": "제외 규칙을 삭제할 수 없습니다.", - "unable_to_delete_import_path": "가져올 경로를 삭제할 수 없습니다.", + "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_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_exit_fullscreen": "전체 화면에서 나갈 수 없습니다.", + "unable_to_get_comments_number": "댓글 수를 불러올 수 없습니다.", "unable_to_get_shared_link": "공유 링크를 불러오지 못했습니다.", "unable_to_hide_person": "인물을 숨길 수 없습니다.", "unable_to_link_motion_video": "모션 비디오를 연결할 수 없습니다", @@ -692,23 +665,21 @@ "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 {#에}} 할당할 수 없습니다.", + "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_comment": "", "unable_to_remove_deleted_assets": "누락된 파일을 제거할 수 없습니다.", "unable_to_remove_library": "라이브러리를 제거할 수 없습니다.", "unable_to_remove_partner": "파트너를 제거할 수 없습니다.", "unable_to_remove_reaction": "반응을 제거할 수 없습니다.", - "unable_to_remove_user": "", "unable_to_repair_items": "항목을 수리할 수 없습니다.", "unable_to_reset_password": "비밀번호를 초기화할 수 없습니다.", "unable_to_resolve_duplicate": "비슷한 항목을 처리할 수 없습니다.", "unable_to_restore_assets": "항목을 복원할 수 없습니다.", - "unable_to_restore_trash": "휴지통을 복원할 수 없습니다.", + "unable_to_restore_trash": "휴지통에서 항목을 복원할 수 없음", "unable_to_restore_user": "사용자 삭제를 취소할 수 없습니다.", "unable_to_save_album": "앨범을 저장할 수 없습니다.", "unable_to_save_api_key": "API 키를 수정할 수 없습니다.", @@ -721,7 +692,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": "앨범 커버를 변경할 수 없습니다.", @@ -729,14 +700,10 @@ "unable_to_update_library": "라이브러리를 업데이트할 수 없습니다.", "unable_to_update_location": "위치를 변경할 수 없습니다.", "unable_to_update_settings": "설정을 변경할 수 없습니다.", - "unable_to_update_timeline_display_status": "타임라인 표시 설정을 변경할 수 없습니다.", + "unable_to_update_timeline_display_status": "타임라인 표시 여부를 변경할 수 없습니다.", "unable_to_update_user": "사용자를 업데이트할 수 없습니다.", "unable_to_upload_file": "파일을 업로드할 수 없습니다." }, - "every_day_at_onepm": "", - "every_night_at_midnight": "", - "every_night_at_twoam": "", - "every_six_hours": "", "exif": "EXIF", "exit_slideshow": "슬라이드 쇼 종료", "expand_all": "모두 확장", @@ -751,33 +718,27 @@ "external": "외부", "external_libraries": "외부 라이브러리", "face_unassigned": "알 수 없음", - "failed_to_get_people": "인물 불러오기 실패", "favorite": "즐겨찾기", - "favorite_or_unfavorite_photo": "즐겨찾기 추가 및 제거", + "favorite_or_unfavorite_photo": "즐겨찾기 추가/제거", "favorites": "즐겨찾기", - "feature": "", "feature_photo_updated": "대표 사진 업데이트됨", - "featurecollection": "", "features": "기능", "features_setting_description": "앱 기능 관리", "file_name": "파일 이름", "file_name_or_extension": "파일명 또는 확장자", "filename": "파일명", - "files": "", "filetype": "파일 형식", "filter_people": "인물 필터", "find_them_fast": "이름으로 검색하여 빠르게 찾기", "fix_incorrect_match": "잘못된 분류 수정", "folders": "폴더", "folders_feature_description": "파일 시스템의 사진 및 동영상을 폴더 뷰로 탐색", - "force_re-scan_library_files": "모든 파일 강제 다시 스캔", "forward": "앞으로", "general": "일반", "get_help": "도움 요청", "getting_started": "시작하기", "go_back": "뒤로", "go_to_search": "검색으로 이동", - "go_to_share_page": "공유 페이지로 이동", "group_albums_by": "다음으로 앨범 그룹화...", "group_no": "그룹화 없음", "group_owner": "소유자로 그룹화", @@ -803,10 +764,6 @@ "image_alt_text_date_place_2_people": "{date} {country}, {city}에서 {person1}, {person2}님과 함께한 {isVideo, select, true {동영상} other {사진}}", "image_alt_text_date_place_3_people": "{date} {country}, {city}에서 {person1}, {person2}님 및 {person3}님과 함께한 {isVideo, select, true {동영상} other {사진}}", "image_alt_text_date_place_4_or_more_people": "{date} {country}, {city}에서 {person1}, {person2}님 및 {additionalCount, number}명과 함께한 {isVideo, select, true {동영상} other {사진}}", - "image_alt_text_people": "{count, plural, =1 {{person1}님과 함께,} =2 {{person1} 및 {person2}님과 함께,} =3 {{person1}, {person2} 및 {person3}님과 함께,} other {{person1}, {person2}, 및 {others, number}명과 함께,}}", - "image_alt_text_place": "{country}, {city}에서", - "image_taken": "{isVideo, select, true {동영상} other {사진}},", - "img": "", "immich_logo": "Immich 로고", "immich_web_interface": "Immich 웹 인터페이스", "import_from_json": "JSON에서 가져오기", @@ -827,7 +784,6 @@ "invite_people": "사용자 초대", "invite_to_album": "앨범으로 초대", "items_count": "{count, plural, one {#개} other {#개}} 항목", - "job_settings_description": "", "jobs": "작업", "keep": "유지", "keep_all": "모두 유지", @@ -842,14 +798,6 @@ "level": "레벨", "library": "라이브러리", "library_options": "라이브러리 옵션", - "license_account_info": "라이선스가 등록된 계정입니다.", - "license_activated_subtitle": "Immich와 오픈소스 소프트웨어를 지원해주셔서 감사합니다.", - "license_activated_title": "라이선스가 성공적으로 활성화되었습니다.", - "license_button_activate": "활성화", - "license_button_buy": "구입", - "license_button_buy_license": "라이선스 구입", - "license_button_select": "선택", - "license_failed_activation": "라이선스를 활성화하지 못했습니다. 이메일로 발송된 키를 정확히 입력했는지 확인하세요!", "light": "라이트", "like_deleted": "좋아요가 삭제되었습니다.", "link_motion_video": "모션 비디오 링크", @@ -870,7 +818,7 @@ "longitude": "경도", "look": "보기", "loop_videos": "동영상 반복", - "loop_videos_description": "상세 보기에서 동영상을 자동으로 반복 재생합니다.", + "loop_videos_description": "상세 보기에서 자동으로 동영상을 반복 재생합니다.", "main_branch_warning": "현재 개발 버전을 사용 중입니다. 정식 버전을 사용하는 것을 강력히 권장합니다!", "make": "제조사", "manage_shared_links": "공유 링크 관리", @@ -893,10 +841,10 @@ "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 {#명}}을 병합했습니다.", + "merge_people_successfully": "인물을 성공적으로 합쳤습니다.", + "merged_people_count": "인물 {count, plural, one {#명} other {#명}}을 합쳤습니다.", "minimize": "최소화", "minute": "분", "missing": "누락", @@ -922,12 +870,12 @@ "no_albums_with_name_yet": "아직 해당하는 이름의 앨범이 없는 것 같습니다.", "no_albums_yet": "아직 앨범이 없는 것 같습니다.", "no_archived_assets_message": "사진과 동영상을 보관함으로 이동하여 목록에서 숨기기", - "no_assets_message": "이곳을 클릭하여 첫 이미지를 업로드하세요", + "no_assets_message": "여기를 클릭하여 첫 사진을 업로드하세요.", "no_duplicates_found": "비슷한 항목을 찾을 수 없습니다.", "no_exif_info_available": "EXIF 정보 없음", "no_explore_results_message": "더 많은 사진을 업로드하여 탐색 기능을 사용하세요.", "no_favorites_message": "즐겨찾기에 좋아하는 사진과 동영상을 추가하기", - "no_libraries_message": "외부 라이브러리를 생성하여 사진과 동영상 가져오기", + "no_libraries_message": "외부 라이브러리를 생성하여 기존 사진과 동영상을 확인하세요.", "no_name": "이름 없음", "no_places": "장소 없음", "no_results": "결과가 없습니다.", @@ -949,14 +897,12 @@ "oldest_first": "오래된 순", "onboarding": "온보딩", "onboarding_privacy_description": "이 선택적 기능은 외부 서비스를 사용하며, 관리자 설정에서 언제든 비활성화할 수 있습니다.", - "onboarding_storage_template_description": "활성화한 경우, 사용자 정의 템플릿을 기반으로 파일을 자동 분류합니다. 안정성 문제로 인해 해당 기능은 기본적으로 비활성화 되어 있습니다. 자세한 내용은 [공식 문서]를 참조하세요.", "onboarding_theme_description": "색상 테마를 선택하세요. 나중에 설정에서 변경할 수 있습니다.", "onboarding_welcome_description": "몇 가지 일반적인 설정을 진행하겠습니다.", "onboarding_welcome_user": "{user}님, 환영합니다", "online": "온라인", - "only_favorites": "즐겨찾기만 표시", - "only_refreshes_modified_files": "변경된 파일만 다시 스캔", - "open_in_map_view": "지도 뷰에서 보기", + "only_favorites": "즐겨찾기만", + "open_in_map_view": "지도 보기에서 열기", "open_in_openstreetmap": "OpenStreetMap에서 열기", "open_the_search_filters": "검색 필터 열기", "options": "옵션", @@ -990,17 +936,15 @@ "paused": "일시 정지됨", "pending": "진행 중", "people": "인물", - "people_edits_count": "인물 {count, plural, one {#명} other {#명}}을 변경했습니다.", + "people_edits_count": "인물 {count, plural, one {#명} other {#명}}을 수정했습니다.", "people_feature_description": "사진 및 동영상을 인물 그룹별로 탐색", "people_sidebar_description": "사이드바에 인물 링크 표시", - "perform_library_tasks": "", "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, plural, one {#개} other {#개}}가 영구적으로 삭제됨", "permanently_deleted_assets_count": "항목 {count, plural, one {#개} other {#개}}가 영구적으로 삭제되었습니다.", "person": "인물", "person_hidden": "{name}{hidden, select, true { (숨김)} other {}}", @@ -1016,7 +960,6 @@ "play_memories": "추억 재생", "play_motion_photo": "모션 포토 재생", "play_or_pause_video": "동영상 재생, 일시 정지", - "point": "", "port": "포트", "preset": "사전 설정", "preview": "미리 보기", @@ -1024,7 +967,7 @@ "previous_memory": "이전 추억", "previous_or_next_photo": "이전 또는 다음 이미지로", "primary": "주요", - "privacy": "프라이버시", + "privacy": "개인 정보", "profile_image_of_user": "{user}님의 프로필 이미지", "profile_picture_set": "프로필 사진이 설정되었습니다.", "public_album": "공개 앨범", @@ -1042,7 +985,7 @@ "purchase_button_select": "선택", "purchase_failed_activation": "등록하지 못했습니다. 이메일로 전송된 키를 정확히 입력했는지 확인하세요!", "purchase_individual_description_1": "개인 사용자용", - "purchase_individual_description_2": "서포터 배지 및 표시", + "purchase_individual_description_2": "서포터 배지", "purchase_individual_title": "개인", "purchase_input_suggestion": "제품 키를 보유하고 있나요? 아래에 제품 키를 입력하세요.", "purchase_license_subtitle": "Immich를 구매하여 지속적인 개발에 도움을 주세요.", @@ -1058,21 +1001,19 @@ "purchase_remove_server_product_key": "서버 제품 키 제거", "purchase_remove_server_product_key_prompt": "서버 제품 키를 제거하시겠습니까?", "purchase_server_description_1": "서버 전체에 적용", - "purchase_server_description_2": "서포터 배지 및 표시", + "purchase_server_description_2": "서포터 배지", "purchase_server_title": "서버", "purchase_settings_server_activated": "서버 제품 키는 관리자가 관리합니다.", - "range": "", "rating": "등급", "rating_clear": "등급 초기화", "rating_count": "{count, plural, one {#점} other {#점}}", - "rating_description": "상세 정보에 EXIF의 등급 정보 표시", - "raw": "", + "rating_description": "상세 정보 패널에 EXIF 등급 태그 표시", "reaction_options": "반응 옵션", "read_changelog": "변경 사항 보기", "reassign": "다시 할당", "reassigned_assets_to_existing_person": "항목 {count, plural, one {#개} other {#개}}가 {name, select, null {다른 인물에} other {{name}에}} 할당되었습니다.", "reassigned_assets_to_new_person": "항목 {count, plural, one {#개} other {#개}}가 새 인물에 할당되었습니다.", - "reassing_hint": "선택한 항목의 인물 변경", + "reassing_hint": "기존 인물에 선택한 항목 할당", "recent": "최근", "recent_searches": "최근 검색", "refresh": "새로고침", @@ -1083,8 +1024,8 @@ "refreshed": "새로고침이 완료되었습니다.", "refreshes_every_file": "기존 파일 및 새 파일 스캔", "refreshing_encoded_video": "인코딩을 다시 진행하는 중...", - "refreshing_faces": "얼굴 새로고침 중", - "refreshing_metadata": "메타데이터를 갱신하는 중...", + "refreshing_faces": "얼굴 새로고침 중...", + "refreshing_metadata": "메타데이터를 새로 고치는 중...", "regenerating_thumbnails": "섬네일을 다시 생성하는 중...", "remove": "제거", "remove_assets_album_confirmation": "앨범에서 항목 {count, plural, one {#개} other {#개}}를 제거하시겠습니까?", @@ -1103,15 +1044,14 @@ "removed_tagged_assets": "항목 {count, plural, one {#개} other {#개}}에서 태그를 제거함", "rename": "이름 바꾸기", "repair": "수리", - "repair_no_results_message": "추적되지 않거나 누락된 파일이 이곳에 표시됩니다.", + "repair_no_results_message": "추적되지 않거나 누락된 파일이 여기에 표시됩니다.", "replace_with_upload": "파일 바꾸기", "repository": "리포지터리", "require_password": "비밀번호 필요", "require_user_to_change_password_on_first_login": "사용자가 처음 로그인할 때 비밀번호를 변경하도록 요구", "reset": "초기화", "reset_password": "비밀번호 재설정", - "reset_people_visibility": "인물 숨김 여부 초기화", - "reset_settings_to_default": "", + "reset_people_visibility": "인물 표시 여부 초기화", "reset_to_default": "기본값으로 복원", "resolve_duplicates": "비슷한 항목 확인", "resolved_all_duplicates": "비슷한 항목을 모두 확인했습니다.", @@ -1131,9 +1071,7 @@ "saved_settings": "설정이 저장되었습니다.", "say_something": "댓글을 입력하세요", "scan_all_libraries": "모든 라이브러리 스캔", - "scan_all_library_files": "모든 파일 다시 스캔", "scan_library": "스캔", - "scan_new_library_files": "새 라이브러리 파일 스캔", "scan_settings": "스캔 설정", "scanning_for_album": "앨범을 스캔하는 중...", "search": "검색", @@ -1176,7 +1114,6 @@ "selected_count": "{count, plural, other {#개}} 항목 선택됨", "send_message": "메시지 전송", "send_welcome_email": "환영 이메일 전송", - "server": "서버", "server_offline": "오프라인", "server_online": "온라인", "server_stats": "서버 통계", @@ -1209,12 +1146,12 @@ "show_and_hide_people": "인물 숨기기", "show_file_location": "파일 위치 표시", "show_gallery": "갤러리 표시", - "show_hidden_people": "숨긴 인물 표시", + "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_or_hide_info": "정보 표시/숨기기", "show_password": "비밀번호 표시", "show_person_options": "인물 옵션 표시", "show_progress_bar": "진행 표시줄 표시", @@ -1224,7 +1161,7 @@ "show_supporter_badge_description": "서포터 배지 표시", "shuffle": "셔플", "sidebar": "사이드바", - "sidebar_display_description": "뷰 링크를 사이드바에 표시", + "sidebar_display_description": "보기 링크를 사이드바에 표시", "sign_out": "로그아웃", "sign_up": "로그인", "size": "크기", @@ -1287,26 +1224,22 @@ "to_favorite": "즐겨찾기", "to_login": "로그인", "to_parent": "상위 항목으로", - "to_root": "루트", "to_trash": "삭제", "toggle_settings": "설정 변경", "toggle_theme": "다크 모드 사용", - "toggle_visibility": "숨김 여부 변경", "total_usage": "총 사용량", "trash": "휴지통", "trash_all": "모두 삭제", "trash_count": "{count, number}개 삭제", "trash_delete_asset": "휴지통 이동/삭제", - "trash_no_results_message": "휴지통으로 이동된 항목이 이곳에 표시됩니다.", + "trash_no_results_message": "삭제된 사진과 동영상이 여기에 표시됩니다.", "trashed_items_will_be_permanently_deleted_after": "휴지통으로 이동된 항목은 {days, plural, one {#일} other {#일}} 후 영구적으로 삭제됩니다.", "type": "형식", "unarchive": "보관함에서 제거", - "unarchived": "보관 해제됨", "unarchived_count": "보관함에서 항목 {count, plural, other {#개}} 제거됨", "unfavorite": "즐겨찾기 해제", "unhide_person": "인물 숨김 해제", "unknown": "알 수 없음", - "unknown_album": "", "unknown_year": "알 수 없는 연도", "unlimited": "무제한", "unlink_motion_video": "모션 비디오 링크 해제", @@ -1326,7 +1259,7 @@ "updated_password": "비밀번호가 변경되었습니다.", "upload": "업로드", "upload_concurrency": "업로드 동시성", - "upload_errors": "업로드가 완료되었습니다. 항목 {count, plural, one {#개} other {#개}}는 업로드하지 못했습니다. 업로드된 항목을 보려면 페이지를 새로고침하세요.", + "upload_errors": "업로드가 완료되었습니다. 항목 {count, plural, one {#개} other {#개}}를 업로드하지 못했습니다. 업로드된 항목을 보려면 페이지를 새로고침하세요.", "upload_progress": "전체 {total, number}개 중 {processed, number}개 완료, {remaining, number}개 대기 중", "upload_skipped_duplicates": "동일한 항목 {count, plural, one {#개} other {#개}}를 건너뛰었습니다.", "upload_status_duplicates": "중복", @@ -1351,8 +1284,8 @@ "version": "버전", "version_announcement_closing": "당신의 친구, Alex가", "version_announcement_message": "안녕하세요, 새 버전의 Immich를 사용할 수 있습니다. 자세한 내용은 릴리스 노트를 참조하세요. WatchTower 등의 자동 업데이트 기능을 사용하는 경우 의도하지 않은 동작을 방지하기 위해 docker-compose.yml.env 구성이 최신인지 확인하세요.", - "version_history": "버전 히스토리", - "version_history_item": "버전 {version}, {date} 설치됨", + "version_history": "버전 기록", + "version_history_item": "{date} 버전 {version} 설치", "video": "동영상", "video_hover_setting": "마우스 오버 재생", "video_hover_setting_description": "마우스를 동영상 위에 올리면 재생이 시작됩니다. 비활성화된 경우에도 재생 아이콘에 마우스를 올리면 재생이 시작됩니다.", @@ -1363,12 +1296,11 @@ "view_all": "모두 보기", "view_all_users": "모든 사용자 보기", "view_in_timeline": "타임라인에서 보기", - "view_links": "링크 보기", + "view_links": "링크 확인", "view_next_asset": "다음 항목 보기", "view_previous_asset": "이전 항목 보기", "view_stack": "스택 보기", - "viewer": "뷰어", - "visibility_changed": "인물 {count, plural, one {#명} other {#명}}의 숨김 여부가 변경되었습니다.", + "visibility_changed": "인물 {count, plural, one {#명} other {#명}}의 표시 여부가 변경됨", "waiting": "대기", "warning": "경고", "week": "주", @@ -1378,5 +1310,5 @@ "years_ago": "{years, plural, one {#년} other {#년}} 전", "yes": "네", "you_dont_have_any_shared_links": "생성한 공유 링크가 없습니다.", - "zoom_image": "확대" + "zoom_image": "이미지 확대" } diff --git a/i18n/lt.json b/i18n/lt.json index 399ef31c3e3fe..cfb9701c1612c 100644 --- a/i18n/lt.json +++ b/i18n/lt.json @@ -1,5 +1,5 @@ { - "about": "Apie", + "about": "Atnaujinti", "account": "Paskyra", "account_settings": "Paskyros nustatymai", "acknowledge": "Patvirtinti", @@ -23,6 +23,7 @@ "add_to": "Pridėti į ...", "add_to_album": "Pridėti į albumą", "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ų", @@ -30,16 +31,19 @@ "authentication_settings": "Autentifikavimo nustatymai", "authentication_settings_description": "Tvarkyti slaptažodžių, OAuth ir kitus autentifikavimo parametrus", "authentication_settings_disable_all": "Ar tikrai norite išjungti visus prisijungimo būdus? Prisijungimas bus visiškai išjungtas.", + "authentication_settings_reenable": "Norėdami vėl įjungti, naudokite Serverio komandą.", "background_task_job": "Foninės užduotys", + "backup_database": "Duomenų bazės atsarginė kopija", + "backup_database_enable_description": "Įgalinti duomenų bazės atsarginė kopijas", + "backup_keep_last_amount": "Išsaugomų ankstesnių atsarginių duomenų bazės kopijų skaičius", + "backup_settings": "Atsarginės kopijos nustatymai", "check_all": "Pažymėti viską", "config_set_by_file": "Konfigūracija dabar nustatyta konfigūracinio failo", "confirm_delete_library": "Ar tikrai norite ištrinti {library} biblioteką?", "confirm_email_below": "Patvirtinimui įveskite \"{email}\" žemiau", "confirm_reprocess_all_faces": "Ar tikrai norite iš naujo apdoroti visus veidus? Tai taip pat ištrins įvardytus asmenis.", "confirm_user_password_reset": "Ar tikrai norite iš naujo nustatyti {user} slaptažodį?", - "crontab_guru": "", "disable_login": "Išjungti prisijungimą", - "disabled": "", "duplicate_detection_job_description": "Vykdykite mašininį mokymąsi tam, kad aptiktumėte panašius vaizdus. Nuo šios funkcijos priklauso išmanioji paieška", "exclusion_pattern_description": "Išimčių šablonai leidžia nepaisyti failų ir aplankų skenuojant jūsų biblioteką. Tai yra naudinga, jei turite aplankų su failais, kurių nenorite importuoti, pavyzdžiui, RAW failai.", "external_library_created_at": "Išorinė biblioteka (sukurta {date})", @@ -50,30 +54,22 @@ "failed_job_command": "Darbo {job} komanda {command} nepavyko", "force_delete_user_warning": "ĮSPĖJIMAS: Šis veiksmas iš karto pašalins naudotoją ir visą jo informaciją. Šis žingsnis nesugrąžinamas ir failų nebus galima atkurti.", "forcing_refresh_library_files": "Priverstinai atnaujinami visi failai bilbiotekoje", + "image_format": "Formatas", "image_format_description": "WebP sukuria mažesnius failus nei JPEG, bet lėčiau juos apdoroja.", "image_prefer_embedded_preview": "Pageidautinai rodyti įterptą peržiūrą", "image_prefer_embedded_preview_setting_description": "", "image_prefer_wide_gamut": "Teikti pirmenybę plačiai gamai", "image_prefer_wide_gamut_setting_description": "", - "image_preview_format": "Peržiūros formatas", - "image_preview_resolution": "Peržiūros rezoliucija", - "image_preview_resolution_description": "Naudojama peržiūrint vieną nuotrauką ir mašininiam mokymui. Didesnė rezoliucija gali išsaugoti daugiau detalių, bet ilgiau užtrukti apdoroti ir sumažinti programos greitumą.", "image_quality": "Kokybė", - "image_quality_description": "Vaizdo kokybė nuo 1 iki 100. Aukštesnė kokybė yra geresnė, tačiau sukuriami didesni failai. Ši parinktis turi įtakos peržiūros ir miniatiūrų vaizdams.", + "image_resolution": "Rezoliucija", "image_settings": "Nuotraukos nustatymai", "image_settings_description": "Keisti sugeneruotų nuotraukų kokybę ir rezoliuciją", - "image_thumbnail_format": "Miniatūros formatas", - "image_thumbnail_resolution": "Miniatūros rezoliucija", - "image_thumbnail_resolution_description": "Naudojama žiūrint nuotraukų grupes (pagrindinis nuotraukų puslapis, albumų peržiūra ir t.t.). Aukštesnė rezoliucija gali išlaikyti daugiau detalių, bet užtrunka ilgiau apdoroti, gali turėti didesnius failų dydžius ir gali sumažinti programos greitumą.", "job_concurrency": "{job} lygiagretumas", "job_not_concurrency_safe": "Šis darbas nėra saugus apdoroti lygiagrečiai.", "job_settings": "Darbų nustatymai", "job_settings_description": "Keisti darbų lygiagretumą", "job_status": "Darbų būsenos", "library_created": "Sukurta biblioteka: {library}", - "library_cron_expression": "Cron išraiška", - "library_cron_expression_description": "Nustatykite nuskaitymo intervalą naudodami „cron“ formatą. Daugiau informacijos rasite pvz. Crontab Guru", - "library_cron_expression_presets": "", "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.", "library_scanning": "Periodinis skanavimas", @@ -119,7 +115,7 @@ "manage_concurrency": "Tvarkyti lygiagretumą", "manage_log_settings": "", "map_dark_style": "Tamsioji tema", - "map_enable_description": "", + "map_enable_description": "Įgalinti žemėlapio funkcijas", "map_gps_settings": "Žemėlapio ir GPS nustatymai", "map_gps_settings_description": "Tvarkyti žemėlapio ir GPS (atvirkštinio geokodavimo) nustatymus", "map_light_style": "Šviesioji tema", @@ -132,9 +128,13 @@ "map_style_description": "", "metadata_extraction_job": "Metaduomenų nuskaitymas", "metadata_extraction_job_description": "Kiekvieno bibliotekos elemento metaduomenų nuskaitymas, tokių kaip GPS koordinatės, veidai ar rezoliucija", + "metadata_settings": "Metaduomenų nustatymai", + "metadata_settings_description": "Tvarkyti metaduomenų nustatymus", + "migration_job": "Migracija", "migration_job_description": "", "no_paths_added": "Keliai nepridėti", "no_pattern_added": "Šablonas nepridėtas", + "note_cannot_be_changed_later": "PASTABA: Vėliau to pakeisti negalima!", "notification_email_from_address": "", "notification_email_from_address_description": "", "notification_email_host_description": "", @@ -148,7 +148,7 @@ "notification_email_test_email_failed": "Nepavyko išsiųsti bandomojo el. laiško, patikrinkite savo nustatymus", "notification_email_test_email_sent": "Bandomasis el. laiškas buvo išsiųstas į {email}. Patikrinkite savo pašto dėžutę.", "notification_email_username_description": "", - "notification_enable_email_notifications": "", + "notification_enable_email_notifications": "Įgalinti el. pašto pranešimus", "notification_settings": "Pranešimų nustatymai", "notification_settings_description": "Tvarkyti pranešimų nustatymus, įskaitant el. pašto", "oauth_auto_launch": "Paleisti automatiškai", @@ -179,15 +179,18 @@ "password_settings_description": "Tvarkyti prisijungimo slaptažodžiu nustatymus", "paths_validated_successfully": "Visi keliai patvirtinti sėkmingai", "refreshing_all_libraries": "Perkraunamos visos bibliotekos", + "registration": "Administratoriaus registracija", "registration_description": "Kadangi esate pirmasis šio sistemos naudotojas, jums bus priskirta administratoriaus rolė, ir būsite atsakingas už administracines užduotis ir papildomų naudotojų kūrimą.", "repair_all": "Pataisyti visus", "require_password_change_on_login": "Reikalauti, kad naudotojas pasikeistų slaptažodį po pirmojo prisijungimo", "reset_settings_to_default": "Atstatyti nustatymus į numatytuosius", + "reset_settings_to_recent_saved": "Nustatymų atstatymas į neseniai išsaugotus nustatymus", + "send_welcome_email": "Siųsti sveikinimo el. laišką", "server_external_domain_settings": "Išorinis domenas", "server_external_domain_settings_description": "", "server_settings": "Serverio nustatymai", "server_settings_description": "Tvarkyti serverio nustatymus", - "server_welcome_message": "", + "server_welcome_message": "Sveikinimo pranešimas", "server_welcome_message_description": "Žinutė, rodoma prisijungimo puslapyje.", "sidecar_job_description": "", "slideshow_duration_description": "", @@ -200,13 +203,12 @@ "storage_template_settings_description": "", "system_settings": "Sistemos nustatymai", "tag_cleanup_job": "Žymų išvalymas", - "theme_custom_css_settings": "", + "theme_custom_css_settings": "Individualizuotas CSS", "theme_custom_css_settings_description": "", "theme_settings": "Temos nustatymai", "theme_settings_description": "", "thumbnail_generation_job": "Generuoti miniatiūras", "thumbnail_generation_job_description": "Didelių, mažų ir neryškių miniatiūrų generavimas kiekvienam bibliotekos elementui, taip pat miniatiūrų generavimas kiekvienam asmeniui", - "transcode_policy_description": "", "transcoding_acceleration_api": "Spartinimo API", "transcoding_acceleration_api_description": "", "transcoding_acceleration_nvenc": "NVENC (reikalinga NVIDIA GPU)", @@ -227,9 +229,9 @@ "transcoding_constant_rate_factor": "", "transcoding_constant_rate_factor_description": "", "transcoding_disabled_description": "", - "transcoding_hardware_acceleration": "", + "transcoding_hardware_acceleration": "Techninės įrangos spartinimas", "transcoding_hardware_acceleration_description": "", - "transcoding_hardware_decoding": "", + "transcoding_hardware_decoding": "Aparatinis dekodavimas", "transcoding_hardware_decoding_setting_description": "", "transcoding_hevc_codec": "HEVC kodekas", "transcoding_max_b_frames": "", @@ -249,21 +251,19 @@ "transcoding_settings": "", "transcoding_settings_description": "", "transcoding_target_resolution": "", - "transcoding_target_resolution_description": "", + "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": "", "transcoding_temporal_aq_description": "", "transcoding_threads": "", "transcoding_threads_description": "", "transcoding_tone_mapping": "", "transcoding_tone_mapping_description": "", - "transcoding_tone_mapping_npl": "", - "transcoding_tone_mapping_npl_description": "", "transcoding_transcode_policy": "", "transcoding_two_pass_encoding": "", "transcoding_two_pass_encoding_setting_description": "", "transcoding_video_codec": "Video kodekas", "transcoding_video_codec_description": "", - "trash_enabled_description": "", + "trash_enabled_description": "Įgalinti šiukšliadėžės funkcijas", "trash_number_of_days": "Dienų skaičius", "trash_number_of_days_description": "", "trash_settings": "Šiukšliadėžės nustatymai", @@ -322,7 +322,6 @@ "archive_or_unarchive_photo": "Archyvuoti arba išarchyvuoti nuotrauką", "archive_size": "Archyvo dydis", "archive_size_description": "Konfigūruoti archyvo dydį atsisiuntimams (GiB)", - "archived": "", "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?", @@ -357,10 +356,6 @@ "cancel_search": "Atšaukti paiešką", "cannot_merge_people": "Negalima sujungti asmenų", "cannot_update_the_description": "Negalima atnaujinti aprašymo", - "cant_apply_changes": "", - "cant_get_faces": "", - "cant_search_people": "", - "cant_search_places": "", "change_date": "Pakeisti datą", "change_expiration_time": "Pakeisti galiojimo trukmę", "change_location": "Pakeisti vietovę", @@ -461,13 +456,6 @@ "downloading": "Siunčiama", "duplicates": "Dublikatai", "duration": "Trukmė", - "durations": { - "days": "", - "hours": "", - "minutes": "", - "months": "", - "years": "" - }, "edit": "Redaguoti", "edit_album": "Redaguoti albumą", "edit_avatar": "Redaguoti avatarą", @@ -488,8 +476,6 @@ "edited": "Redaguota", "editor": "", "email": "El. paštas", - "empty": "", - "empty_album": "", "empty_trash": "Ištuštinti šiukšliadėžę", "enable": "Įgalinti", "enabled": "Įgalintas", @@ -525,8 +511,6 @@ "unable_to_change_date": "Negalima pakeisti datos", "unable_to_change_location": "Negalima pakeisti vietos", "unable_to_change_password": "Negalima pakeisti slaptažodžio", - "unable_to_check_item": "", - "unable_to_check_items": "", "unable_to_connect": "Nepavyko prisijungti", "unable_to_connect_to_server": "Nepavyko prisijungti prie serverio", "unable_to_copy_to_clipboard": "Negalima kopijuoti į iškarpinę, įsitikinkite, kad prie puslapio prieinate per https", @@ -558,11 +542,9 @@ "unable_to_refresh_user": "Nepavyksta atnaujinti naudotojo", "unable_to_remove_album_users": "", "unable_to_remove_api_key": "Nepavyko pašalinti API rakto", - "unable_to_remove_comment": "", "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_remove_user": "", "unable_to_repair_items": "", "unable_to_reset_password": "", "unable_to_resolve_duplicate": "", @@ -586,10 +568,6 @@ "unable_to_update_user": "", "unable_to_upload_file": "Nepavyksta įkelti failo" }, - "every_day_at_onepm": "", - "every_night_at_midnight": "", - "every_night_at_twoam": "", - "every_six_hours": "", "exif": "Exif", "exit_slideshow": "", "expand_all": "Išskleisti viską", @@ -603,29 +581,23 @@ "external": "Išorinis", "external_libraries": "Išorinės bibliotekos", "face_unassigned": "Nepriskirta", - "failed_to_get_people": "", "favorite": "Mėgstamiausi", "favorite_or_unfavorite_photo": "Įtraukti prie arba pašalinti iš mėgstamiausių", "favorites": "Mėgstamiausi", - "feature": "", "feature_photo_updated": "", - "featurecollection": "", "file_name": "Failo pavadinimas", "file_name_or_extension": "Failo pavadinimas arba plėtinys", "filename": "", - "files": "", "filetype": "Failo tipas", "filter_people": "Filtruoti žmones", "fix_incorrect_match": "", "folders": "Aplankai", - "force_re-scan_library_files": "", "forward": "", "general": "", "get_help": "Gauti pagalbos", "getting_started": "", "go_back": "", "go_to_search": "", - "go_to_share_page": "", "group_albums_by": "Grupuoti albumus pagal...", "group_no": "Negrupuoti", "group_owner": "Grupuoti pagal savininką", @@ -641,7 +613,6 @@ "host": "", "hour": "Valanda", "image": "Nuotrauka", - "img": "", "immich_logo": "Immich logotipas", "import_from_json": "Importuoti iš JSON", "import_path": "Importavimo kelias", @@ -660,7 +631,6 @@ "invite_people": "Kviesti žmones", "invite_to_album": "Pakviesti į albumą", "items_count": "{count, plural, one {# elementas} few {# elementai} other {# elementų}}", - "job_settings_description": "", "jobs": "Darbai", "keep": "Palikti", "keep_all": "Palikti visus", @@ -766,7 +736,6 @@ "onboarding_welcome_user": "Sveiki atvykę, {user}", "online": "Prisijungęs", "only_favorites": "Tik mėgstamiausi", - "only_refreshes_modified_files": "Atnaujina tik modifikuotus failus", "open_the_search_filters": "Atidaryti paieškos filtrus", "options": "Pasirinktys", "or": "arba", @@ -801,7 +770,6 @@ "people": "Asmenys", "people_edits_count": "{count, plural, one {Redaguotas # asmuo} few {Redaguoti # asmenys} other {Redaguota # asmenų}}", "people_sidebar_description": "", - "perform_library_tasks": "", "permanent_deletion_warning": "", "permanent_deletion_warning_setting_description": "", "permanently_delete": "Ištrinti visam laikui", @@ -819,7 +787,6 @@ "play_memories": "", "play_motion_photo": "", "play_or_pause_video": "", - "point": "", "port": "", "preset": "", "preview": "", @@ -861,10 +828,8 @@ "purchase_server_description_2": "Rėmėjo statusas", "purchase_server_title": "Serveris", "purchase_settings_server_activated": "Serverio produkto raktas yra tvarkomas administratoriaus", - "range": "", "rating": "Įvertinimas žvaigždutėmis", "rating_count": "{count, plural, one {# įvertinimas} few {# įvertinimai} other {# įvertinimų}}", - "raw": "", "reaction_options": "", "read_changelog": "", "recent": "", @@ -891,7 +856,6 @@ "reset": "Atstatyti", "reset_password": "", "reset_people_visibility": "", - "reset_settings_to_default": "", "resolved_all_duplicates": "Išspręsti visi dublikatai", "restore": "Atkurti", "restore_all": "Atkurti visus", @@ -905,9 +869,7 @@ "saved_settings": "Išsaugoti nustatymai", "say_something": "Ką nors pasakykite", "scan_all_libraries": "Skenuoti visas bibliotekas", - "scan_all_library_files": "", "scan_library": "Skenuoti", - "scan_new_library_files": "", "scan_settings": "Skenavimo nustatymai", "search": "Ieškoti", "search_albums": "", @@ -943,7 +905,6 @@ "selected_count": "{count, plural, one {# pasirinktas} few {# pasirinkti} other {# pasirinktų}}", "send_message": "Siųsti žinutę", "send_welcome_email": "Siųsti sveikinimo el. laišką", - "server": "Serveris", "server_offline": "Serveris nepasiekiamas", "server_online": "Serveris pasiekiamas", "server_stats": "Serverio statistika", @@ -1032,7 +993,6 @@ "to_favorite": "Įtraukti prie mėgstamiausių", "toggle_settings": "", "toggle_theme": "", - "toggle_visibility": "", "total_usage": "", "trash": "Šiukšliadėžė", "trash_all": "Ištrinti visus", @@ -1041,17 +1001,17 @@ "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", - "unarchived": "", "unarchived_count": "{count, plural, other {# išarchyvuota}}", "unfavorite": "Pašalinti iš mėgstamiausių", "unhide_person": "", "unknown": "", - "unknown_album": "", "unknown_year": "Nežinomi metai", "unlink_oauth": "", "unlinked_oauth_account": "", + "unnamed_album_delete_confirmation": "Ar tikrai norite ištrinti šį albumą?", "unsaved_change": "Neišsaugoti pakeitimai", "unselect_all": "", + "unselect_all_duplicates": "Atžymėti visus dublikatus", "unstack": "Išgrupuoti", "unstacked_assets_count": "{count, plural, one {Išgrupuotas # elementas} few {Išgrupuoti # elementai} other {Išgrupuota # elementų}}", "up_next": "", @@ -1062,37 +1022,38 @@ "upload_status_duplicates": "Dublikatai", "upload_status_errors": "Klaidos", "upload_status_uploaded": "Įkelta", - "url": "", + "url": "URL", "usage": "", "user": "Naudotojas", "user_id": "Naudotojo ID", "user_usage_detail": "", + "user_usage_stats": "Paskyros naudojimo statistika", + "user_usage_stats_description": "Žiūrėti paskyros naudojimo statistiką", "username": "Naudotojo vardas", "users": "Naudotojai", "utilities": "Priemonės", - "validate": "", + "validate": "Validuoti", "variables": "Kintamieji", "version": "Versija", "version_announcement_closing": "Tavo draugas, Alex", "version_history": "Versijų istorija", "version_history_item": "Versija {version} įdiegta {date}", "video": "Vaizdo įrašas", - "video_hover_setting_description": "", + "video_hover_setting_description": "Atkurti vaizdo įrašo miniatiūrą, kai pelė užvedama ant elemento. Net ir išjungus, atkūrimą galima pradėti užvedus pelės žymeklį ant atkūrimo piktogramos.", "videos": "Video", "videos_count": "{count, plural, one {# vaizdo įrašas} few {# vaizdo įrašai} other {# vaizdo įrašų}}", "view": "Rodyti", "view_album": "Rodyti albumą", - "view_all": "", + "view_all": "Peržiūrėti viską", "view_all_users": "Peržiūrėti visus naudotojus", "view_links": "Rodyti nuorodas", "view_next_asset": "", "view_previous_asset": "", "view_stack": "Peržiūrėti grupę", - "viewer": "", "waiting": "Laukiama", "warning": "Įspėjimas", "week": "Savaitė", - "welcome_to_immich": "", + "welcome_to_immich": "Sveiki atvykę į Immich", "year": "Metai", "yes": "Taip", "zoom_image": "Priartinti vaizdą" diff --git a/i18n/lv.json b/i18n/lv.json index b2c57d7595815..c6cbc9c3b75a7 100644 --- a/i18n/lv.json +++ b/i18n/lv.json @@ -23,6 +23,7 @@ "add_to": "Pievienot ..", "add_to_album": "Pievienot albumam", "add_to_shared_album": "Pievienot koplietotam albumam", + "add_url": "Pievienot URL", "added_to_archive": "Pievienots arhīvam", "added_to_favorites": "Pievienots izlasei", "added_to_favorites_count": "Pievienots {count, number} izlasei", @@ -41,9 +42,8 @@ "confirm_reprocess_all_faces": "Vai tiešām vēlaties atkārtoti apstrādāt visas sejas? Tas arī atiestatīs cilvēkus ar vārdiem.", "confirm_user_password_reset": "Vai tiešām vēlaties atiestatīt lietotāja {user} paroli?", "create_job": "Izveidot darbu", - "crontab_guru": "", + "cron_expression": "Cron izteiksme", "disable_login": "Atspējot pieteikšanos", - "disabled": "", "duplicate_detection_job_description": "Palaidiet mašīnmācīšanos uz līdzekļiem, lai noteiktu līdzīgus attēlus. Paļaujas uz Viedo Meklēšanu", "external_library_created_at": "Ārēja bibliotēka (izveidota {date})", "external_library_management": "Ārējo bibliotēku pārvaldība", @@ -54,24 +54,15 @@ "image_prefer_embedded_preview_setting_description": "", "image_prefer_wide_gamut": "", "image_prefer_wide_gamut_setting_description": "", - "image_preview_format": "Priekšskatījuma formāts", - "image_preview_resolution": "Priekšskatījuma izšķirtspēja", - "image_preview_resolution_description": "", "image_quality": "Kvalitāte", - "image_quality_description": "Attēla kvalitāte no 1 līdz 100. Augstāka kvalitāte ir labāka, bet veido lielākus failus. Šī opcija ietekmē Priekšskatījums un Sīktēls attēlus.", "image_resolution": "Izšķirtspēja", "image_settings": "Attēla Iestatījumi", "image_settings_description": "Ģenerēto attēlu kvalitātes un izšķirtspējas pārvaldība", - "image_thumbnail_format": "Sīktēlu formāts", - "image_thumbnail_resolution": "Sīktēlu izšķirtspēja", - "image_thumbnail_resolution_description": "", "image_thumbnail_title": "Sīktēlu iestatījumi", "job_created": "Darbs izveidots", "job_settings": "", "job_settings_description": "", "job_status": "Darbu statuss", - "library_cron_expression": "Cron izteiksme", - "library_cron_expression_presets": "", "library_deleted": "Bibliotēka dzēsta", "library_scanning": "", "library_scanning_description": "", @@ -121,12 +112,14 @@ "map_settings": "Karte", "map_settings_description": "", "map_style_description": "", + "metadata_extraction_job": "Metadatu iegūšana", "metadata_extraction_job_description": "", "metadata_settings": "Metadatu iestatījumi", "migration_job": "Migrācija", "migration_job_description": "", + "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": "", + "notification_email_from_address_description": "Sūtītāja e-pasta adrese, piemēram: “Immich foto serveris ”", "notification_email_host_description": "", "notification_email_ignore_certificate_errors": "Ignorēt sertifikātu kļūdas", "notification_email_ignore_certificate_errors_description": "Ignorēt TLS sertifikāta apstiprināšanas kļūdas (nav ieteicams)", @@ -165,11 +158,13 @@ "oauth_storage_quota_claim_description": "", "oauth_storage_quota_default": "", "oauth_storage_quota_default_description": "", - "password_enable_description": "", - "password_settings": "", - "password_settings_description": "", + "password_enable_description": "Pieteikšanās ar e-pasta adresi un paroli", + "password_settings": "Pieteikšanās ar paroli", + "password_settings_description": "Pārvaldīt pieteikšanās ar paroli iestatījumus", + "person_cleanup_job": "Personu tīrīšana", "quota_size_gib": "Kvotas izmērs (GiB)", "registration": "Administratora reģistrācija", + "repair_all": "Salabot visu", "require_password_change_on_login": "Pieprasīt lietotājam mainīt paroli pēc pirmās pieteikšanās", "scanning_library": "Skenē bibliotēku", "server_external_domain_settings": "", @@ -193,7 +188,6 @@ "theme_settings": "", "theme_settings_description": "", "thumbnail_generation_job_description": "", - "transcode_policy_description": "", "transcoding_acceleration_api": "", "transcoding_acceleration_api_description": "", "transcoding_acceleration_nvenc": "NVENC (nepieciešams NVIDIA GPU)", @@ -242,8 +236,6 @@ "transcoding_threads_description": "", "transcoding_tone_mapping": "", "transcoding_tone_mapping_description": "", - "transcoding_tone_mapping_npl": "", - "transcoding_tone_mapping_npl_description": "", "transcoding_transcode_policy": "", "transcoding_two_pass_encoding": "", "transcoding_two_pass_encoding_setting_description": "", @@ -301,7 +293,6 @@ "archive": "Arhīvs", "archive_or_unarchive_photo": "", "archive_size": "Arhīva izmērs", - "archived": "", "are_these_the_same_person": "Vai šī ir tā pati persona?", "asset_adding_to_album": "Pievieno albumam...", "asset_offline": "", @@ -320,10 +311,6 @@ "cancel_search": "", "cannot_merge_people": "Nevar apvienot cilvēkus", "cannot_update_the_description": "", - "cant_apply_changes": "", - "cant_get_faces": "", - "cant_search_people": "", - "cant_search_places": "", "change_date": "Mainīt datumu", "change_expiration_time": "Izmainīt derīguma termiņu", "change_location": "Mainīt atrašanās vietu", @@ -395,7 +382,7 @@ "deleted_shared_link": "", "description": "Apraksts", "details": "INFORMĀCIJA", - "direction": "", + "direction": "Virziens", "disallow_edits": "", "discover": "", "dismiss_all_errors": "", @@ -407,16 +394,10 @@ "documentation": "Dokumentācija", "done": "Gatavs", "download": "Lejupielādēt", + "download_settings": "Lejupielāde", "downloading": "", "duplicates": "Dublikāti", "duration": "", - "durations": { - "days": "", - "hours": "", - "minutes": "", - "months": "", - "years": "" - }, "edit_album": "", "edit_avatar": "", "edit_date": "", @@ -437,8 +418,6 @@ "editor_close_without_save_prompt": "Izmaiņas netiks saglabātas", "editor_close_without_save_title": "Aizvērt redaktoru?", "email": "E-pasts", - "empty": "", - "empty_album": "", "empty_trash": "Iztukšot atkritni", "enable": "", "enabled": "", @@ -455,8 +434,6 @@ "unable_to_change_album_user_role": "", "unable_to_change_date": "", "unable_to_change_location": "", - "unable_to_check_item": "", - "unable_to_check_items": "", "unable_to_create_admin_account": "", "unable_to_create_library": "", "unable_to_create_user": "Neizdevās izveidot lietotāju", @@ -474,11 +451,9 @@ "unable_to_play_video": "", "unable_to_refresh_user": "", "unable_to_remove_album_users": "", - "unable_to_remove_comment": "", "unable_to_remove_library": "", "unable_to_remove_partner": "", "unable_to_remove_reaction": "", - "unable_to_remove_user": "", "unable_to_repair_items": "", "unable_to_reset_password": "", "unable_to_resolve_duplicate": "", @@ -501,10 +476,6 @@ "unable_to_update_settings": "", "unable_to_update_user": "" }, - "every_day_at_onepm": "", - "every_night_at_midnight": "", - "every_night_at_twoam": "", - "every_six_hours": "", "exit_slideshow": "Iziet no slīdrādes", "expand_all": "", "expire_after": "Derīguma termiņš beidzas pēc", @@ -512,29 +483,23 @@ "explore": "Izpētīt", "extension": "", "external_libraries": "", - "failed_to_get_people": "", "favorite": "Izlase", "favorite_or_unfavorite_photo": "", "favorites": "Izlase", - "feature": "", "feature_photo_updated": "", - "featurecollection": "", "file_name": "", "file_name_or_extension": "", "filename": "", - "files": "", "filetype": "", "filter_people": "", "fix_incorrect_match": "", "folders": "Mapes", - "force_re-scan_library_files": "", "forward": "", "general": "", "get_help": "", "getting_started": "", "go_back": "", "go_to_search": "", - "go_to_share_page": "", "group_albums_by": "", "has_quota": "Ir kvota", "hide_gallery": "", @@ -544,7 +509,6 @@ "host": "", "hour": "", "image": "Attēls", - "img": "", "immich_logo": "Immich logo", "import_from_json": "Importēt no JSON", "import_path": "Importa ceļš", @@ -563,7 +527,6 @@ }, "invite_people": "Ielūgt cilvēkus", "invite_to_album": "Uzaicināt albumā", - "job_settings_description": "", "jobs": "Darbi", "keep": "Paturēt", "keep_all": "Paturēt visus", @@ -661,7 +624,6 @@ "oldest_first": "", "online": "Tiešsaistē", "only_favorites": "Tikai izlase", - "only_refreshes_modified_files": "", "open_in_map_view": "Atvērt kartes skatā", "open_in_openstreetmap": "Atvērt OpenStreetMap", "open_the_search_filters": "Atvērt meklēšanas filtrus", @@ -692,7 +654,6 @@ "pending": "", "people": "Cilvēki", "people_sidebar_description": "", - "perform_library_tasks": "", "permanent_deletion_warning": "", "permanent_deletion_warning_setting_description": "", "permanently_delete": "", @@ -706,7 +667,6 @@ "play_memories": "", "play_motion_photo": "", "play_or_pause_video": "", - "point": "", "port": "", "preset": "", "preview": "", @@ -726,8 +686,6 @@ "purchase_server_description_1": "Visam serverim", "purchase_server_description_2": "Atbalstītāja statuss", "purchase_server_title": "Serveris", - "range": "", - "raw": "", "reaction_options": "", "read_changelog": "Lasīt izmaiņu sarakstu", "recent": "", @@ -753,7 +711,6 @@ "reset": "", "reset_password": "", "reset_people_visibility": "", - "reset_settings_to_default": "", "resolve_duplicates": "Atrisināt dublēšanās gadījumus", "resolved_all_duplicates": "Visi dublikāti ir atrisināti", "restore": "Atjaunot", @@ -771,8 +728,6 @@ "saved_settings": "Iestatījumi saglabāti", "say_something": "Teikt kaut ko", "scan_all_libraries": "", - "scan_all_library_files": "", - "scan_new_library_files": "", "scan_settings": "", "search": "Meklēt", "search_albums": "Meklēt albumus", @@ -804,7 +759,6 @@ "select_photos": "Fotoattēlu Izvēle", "selected": "", "send_message": "", - "server": "", "server_online": "Serveris tiešsaistē", "server_stats": "Servera statistika", "server_version": "Servera versija", @@ -855,7 +809,7 @@ "sort_recent": "Nesenākā fotogrāfija", "sort_title": "Nosaukums", "source": "Avots", - "stack": "Steks", + "stack": "Apvienot kaudzē", "stack_selected_photos": "", "stacktrace": "", "start_date": "", @@ -884,18 +838,15 @@ "to_change_password": "Mainīt paroli", "toggle_settings": "Pārslēgt iestatījumus", "toggle_theme": "", - "toggle_visibility": "", "total_usage": "Kopējais lietojums", "trash": "Atkritne", "trash_all": "", "trash_no_results_message": "", "type": "", "unarchive": "Atarhivēt", - "unarchived": "", "unfavorite": "Noņemt no izlases", "unhide_person": "Atcelt personas slēpšanu", "unknown": "", - "unknown_album": "", "unknown_year": "Nezināms gads", "unlimited": "Neierobežots", "unlink_oauth": "", @@ -930,7 +881,6 @@ "view_links": "", "view_next_asset": "", "view_previous_asset": "", - "viewer": "", "waiting": "Gaida", "week": "", "welcome_to_immich": "", diff --git a/i18n/mk.json b/i18n/mk.json index 0967ef424bce6..0bfbcfefe99f4 100644 --- a/i18n/mk.json +++ b/i18n/mk.json @@ -1 +1,28 @@ -{} +{ + "about": "Освежи", + "account": "Профил", + "account_settings": "Поставки за профилот", + "acknowledge": "Означи како прочитано", + "action": "Акција", + "actions": "Акции", + "active": "Активни", + "activity": "Активности", + "add": "Додај", + "add_a_description": "Додај опис", + "add_a_location": "Додај локација", + "add_a_name": "Додај име", + "add_a_title": "Додај наслов", + "add_exclusion_pattern": "Додај патерн за игнотирање", + "add_import_path": "Додај патека за импортирање", + "add_location": "Додај локација", + "add_more_users": "Додај уште корисници", + "add_partner": "Додај партнер", + "add_path": "Додај патека", + "add_photos": "Додај слики", + "add_to": "Додај во...", + "add_to_album": "Додај во албум", + "add_to_shared_album": "Додај во споделен албум", + "added_to_archive": "Додадено во архива", + "added_to_favorites": "Додадено во омилени", + "added_to_favorites_count": "Додадени {count, number} во омилени" +} diff --git a/i18n/mn.json b/i18n/mn.json index 231c84e4cf0f2..b1a8a7970e365 100644 --- a/i18n/mn.json +++ b/i18n/mn.json @@ -31,9 +31,7 @@ "authentication_settings_description": "Нууц үгийн удирдлага, OAuth болон бусад танин нэвтрэлтийн тохиргоо", "authentication_settings_disable_all": "Бүх нэвтрэх аргуудыг идэвхигүй болгохдоо итгэлтэй байна уу? Нэвтрэх үйлдэл бүрэн идэвхигүй болно.", "check_all": "Бүгдийг сонгох", - "crontab_guru": "", "disable_login": "", - "disabled": "", "duplicate_detection_job_description": "", "face_detection": "Нүүр илрүүлэх", "image_format_description": "", @@ -41,21 +39,12 @@ "image_prefer_embedded_preview_setting_description": "", "image_prefer_wide_gamut": "", "image_prefer_wide_gamut_setting_description": "", - "image_preview_format": "", - "image_preview_resolution": "", - "image_preview_resolution_description": "", "image_quality": "Чанар", - "image_quality_description": "", "image_settings": "", "image_settings_description": "", - "image_thumbnail_format": "", - "image_thumbnail_resolution": "", - "image_thumbnail_resolution_description": "", "job_settings": "Ажлын тохиргоо", "job_settings_description": "", "job_status": "Ажлын төлөв", - "library_cron_expression": "", - "library_cron_expression_presets": "", "library_scanning": "", "library_scanning_description": "", "library_scanning_enable_description": "", @@ -166,7 +155,6 @@ "theme_settings": "", "theme_settings_description": "", "thumbnail_generation_job_description": "", - "transcode_policy_description": "", "transcoding_acceleration_api": "", "transcoding_acceleration_api_description": "", "transcoding_acceleration_nvenc": "", @@ -215,8 +203,6 @@ "transcoding_threads_description": "", "transcoding_tone_mapping": "", "transcoding_tone_mapping_description": "", - "transcoding_tone_mapping_npl": "", - "transcoding_tone_mapping_npl_description": "", "transcoding_transcode_policy": "", "transcoding_two_pass_encoding": "", "transcoding_two_pass_encoding_setting_description": "", @@ -272,7 +258,6 @@ "archive_or_unarchive_photo": "Зургийг архивт хийх эсвэл гаргах", "archive_size": "Архивын хэмжээ", "archive_size_description": "Татах үеийн архивын хэмжээг тохируулах (GiB-р)", - "archived": "", "asset_added_to_album": "Цомогт нэмсэн", "asset_adding_to_album": "Цомогт нэмж байна...", "asset_offline": "", @@ -289,10 +274,6 @@ "cancel_search": "Хайлт цуцлах", "cannot_merge_people": "", "cannot_update_the_description": "", - "cant_apply_changes": "", - "cant_get_faces": "", - "cant_search_people": "", - "cant_search_places": "", "change_date": "Огноо өөрчлөх", "change_expiration_time": "", "change_location": "Байршил өөрчлөх", @@ -372,13 +353,6 @@ "download": "", "downloading": "", "duration": "", - "durations": { - "days": "", - "hours": "", - "minutes": "", - "months": "", - "years": "" - }, "edit_album": "", "edit_avatar": "", "edit_date": "", @@ -397,8 +371,6 @@ "edited": "", "editor": "", "email": "", - "empty": "", - "empty_album": "", "empty_trash": "Хогийн сав хоослох", "enable": "", "enabled": "", @@ -412,8 +384,6 @@ "unable_to_change_album_user_role": "", "unable_to_change_date": "", "unable_to_change_location": "", - "unable_to_check_item": "", - "unable_to_check_items": "", "unable_to_create_admin_account": "", "unable_to_create_library": "", "unable_to_create_user": "", @@ -431,11 +401,9 @@ "unable_to_play_video": "", "unable_to_refresh_user": "", "unable_to_remove_album_users": "", - "unable_to_remove_comment": "", "unable_to_remove_library": "", "unable_to_remove_partner": "", "unable_to_remove_reaction": "", - "unable_to_remove_user": "", "unable_to_repair_items": "", "unable_to_reset_password": "", "unable_to_resolve_duplicate": "", @@ -457,10 +425,6 @@ "unable_to_update_settings": "", "unable_to_update_user": "" }, - "every_day_at_onepm": "", - "every_night_at_midnight": "", - "every_night_at_twoam": "", - "every_six_hours": "", "exit_slideshow": "", "expand_all": "", "expire_after": "", @@ -468,28 +432,22 @@ "explore": "Эрж олох", "extension": "", "external_libraries": "", - "failed_to_get_people": "", "favorite": "", "favorite_or_unfavorite_photo": "", "favorites": "Дуртай", - "feature": "", "feature_photo_updated": "", - "featurecollection": "", "file_name": "", "file_name_or_extension": "", "filename": "", - "files": "", "filetype": "", "filter_people": "", "fix_incorrect_match": "", - "force_re-scan_library_files": "", "forward": "", "general": "", "get_help": "", "getting_started": "", "go_back": "", "go_to_search": "", - "go_to_share_page": "", "group_albums_by": "", "has_quota": "", "hide_gallery": "", @@ -498,7 +456,6 @@ "host": "", "hour": "", "image": "", - "img": "", "immich_logo": "", "import_path": "", "in_archive": "", @@ -515,7 +472,6 @@ }, "invite_people": "Хүмүүс урих", "invite_to_album": "", - "job_settings_description": "", "jobs": "", "keep": "", "keyboard_shortcuts": "", @@ -599,7 +555,6 @@ "oldest_first": "", "online": "", "only_favorites": "Зөвхөн дуртай зурагнууд", - "only_refreshes_modified_files": "", "open_the_search_filters": "", "options": "", "organize_your_library": "", @@ -627,7 +582,6 @@ "pending": "", "people": "Хүмүүс", "people_sidebar_description": "", - "perform_library_tasks": "", "permanent_deletion_warning": "", "permanent_deletion_warning_setting_description": "", "permanently_delete": "", @@ -641,7 +595,6 @@ "play_memories": "", "play_motion_photo": "", "play_or_pause_video": "", - "point": "", "port": "", "preset": "", "preview": "", @@ -651,8 +604,6 @@ "primary": "", "profile_picture_set": "", "public_share": "", - "range": "", - "raw": "", "reaction_options": "", "read_changelog": "", "recent": "", @@ -674,7 +625,6 @@ "reset": "", "reset_password": "", "reset_people_visibility": "", - "reset_settings_to_default": "", "restore": "", "restore_user": "", "retry_upload": "", @@ -685,8 +635,6 @@ "saved_settings": "", "say_something": "", "scan_all_libraries": "", - "scan_all_library_files": "", - "scan_new_library_files": "", "scan_settings": "", "search": "", "search_albums": "", @@ -714,7 +662,6 @@ "select_photos": "", "selected": "", "send_message": "", - "server": "", "server_online": "Сервер Онлайн", "server_stats": "", "set": "", @@ -776,18 +723,15 @@ "timezone": "", "toggle_settings": "", "toggle_theme": "", - "toggle_visibility": "", "total_usage": "", "trash": "Хогийн сав", "trash_all": "", "trash_no_results_message": "", "type": "", "unarchive": "", - "unarchived": "", "unfavorite": "", "unhide_person": "", "unknown": "", - "unknown_album": "", "unknown_year": "", "unlink_oauth": "", "unlinked_oauth_account": "", @@ -816,7 +760,6 @@ "view_links": "", "view_next_asset": "", "view_previous_asset": "", - "viewer": "", "waiting": "Хүлээж байна", "warning": "Анхааруулга", "week": "Долоо хоног", diff --git a/i18n/ms.json b/i18n/ms.json index cec6f00273728..f45f8e1c9f085 100644 --- a/i18n/ms.json +++ b/i18n/ms.json @@ -23,6 +23,7 @@ "add_to": "Tambah ke...", "add_to_album": "Tambah ke album", "add_to_shared_album": "Tambah ke album yang dikongsi", + "add_url": "Tambah URL", "added_to_archive": "Tambah ke arkib", "added_to_favorites": "Ditambah pada favorit", "added_to_favorites_count": "Menambahkan {count, number} ke favorit", @@ -34,6 +35,11 @@ "authentication_settings_disable_all": "Adakah anda pasti mahu melumpuhkan semua kaedah log masuk? Log masuk akan dilumpuhkan sepenuhnya.", "authentication_settings_reenable": "Untuk menghidupkan semula, guna Arahan Pelayan.", "background_task_job": "Tugas Latar Belakang", + "backup_database": "Sandar pangkalan data", + "backup_database_enable_description": "Aktifkan sandaran pangkalan data", + "backup_keep_last_amount": "Jumlah sandaran sebelumnya yang hendak disimpan", + "backup_settings": "Tetapan Sandaran", + "backup_settings_description": "Urus tetapan sandaran pangkalan data", "check_all": "Tanda Semua", "cleared_jobs": "Kerja telah dibersihkan untuk: {job}", "config_set_by_file": "Konfigurasi kini ditetapkan oleh fail konfigurasi", @@ -43,6 +49,9 @@ "confirm_reprocess_all_faces": "Adakah anda pasti mahu memproses semula semua wajah? Ini juga akan membersihkan orang bernama.", "confirm_user_password_reset": "Adakah anda pasti mahu menetapkan semula kata laluan {user}?", "create_job": "Cipta tugas", + "cron_expression": "Ungkapan cron", + "cron_expression_description": "Tetapkan selang imbasan menggunakan format cron. Untuk maklumat lanjut, sila rujuk ke sebagai contoh Crontab Guru", + "cron_expression_presets": "Pratetap-pratetap ungkapan Cron", "disable_login": "Lumpuhkan fungsi log masuk", "duplicate_detection_job_description": "Jalankan pembelajaran mesin pada aset untuk mengesan imej yang serupa. Bergantung pada Carian Pintar", "exclusion_pattern_description": "Corak pengecualian membolehkan anda mengabaikan fail dan folder semasa mengimbas pustaka anda. Ini berguna jika anda mempunyai folder yang mengandungi fail yang anda tidak mahu import, seperti fail RAW.", @@ -80,9 +89,6 @@ "jobs_delayed": "{jobCount, plural, other {# tertangguh}}", "jobs_failed": "{jobCount, plural, other {# gagal}}", "library_created": "Pustaka dicipta: {library}", - "library_cron_expression": "Ungkapan Cron", - "library_cron_expression_description": "Tetapkan selang pengimbasan menggunakan format cron. Untuk maklumat lanjut sila rujuk cth. Crontab Guru", - "library_cron_expression_presets": "Pratetap ungkapan Cron", "library_deleted": "Pustaka dipadamkan", "library_import_path_description": "Tentukan folder untuk diimport. Folder ini, termasuk subfolder, akan diimbas untuk imej dan video.", "library_scanning": "Pengimbasan Berkala", @@ -117,6 +123,76 @@ "machine_learning_max_recognition_distance_description": "Jarak maksimum antara dua muka untuk dianggap sebagai orang yang sama, antara 0-2. Menurunkan ini boleh menghalang pelabelan dua orang sebagai orang yang sama, manakala menaikkannya boleh menghalang pelabelan orang yang sama sebagai dua orang yang berbeza. Ambil perhatian bahawa adalah lebih mudah untuk menggabungkan dua orang daripada membelah satu orang kepada dua, jadi silap pada bahagian ambang yang lebih rendah apabila boleh.", "machine_learning_min_detection_score": "Skor pengesanan minimum", "machine_learning_min_detection_score_description": "Skor keyakinan minimum untuk wajah dikesan dari 0-1. Nilai yang lebih rendah akan mengesan lebih banyak muka tetapi mungkin menghasilkan positif palsu.", - "machine_learning_min_recognized_faces": "Minimum mengenali wajah" - } + "machine_learning_min_recognized_faces": "Minimum mengenali wajah", + "machine_learning_min_recognized_faces_description": "Bilangan minima wajah yang dikenali untuk seseorang dicipta. Peningkatan ini menjadikan Pengecaman Wajah lebih tepat atas kos meningkatkan peluang wajah tidak diberikan kepada seseorang.", + "machine_learning_settings": "Tetapan Pembelajaran Mesin", + "machine_learning_smart_search_enabled_description": "Jika ditutup, gambar-gambar tidak akan dikodkan untuk carian pintar.", + "map_dark_style": "Tema gelap", + "map_enable_description": "Aktifkan ciri peta", + "map_gps_settings": "Tetapan Peta & GPS", + "map_light_style": "Tema terang", + "map_reverse_geocoding_enable_description": "Dayakan pengekodan geo terbalik", + "map_reverse_geocoding_settings": "Tetapan Pengekodan Geo Terbalik", + "map_settings": "Peta", + "map_settings_description": "Urus tetapan peta", + "metadata_extraction_job": "Sari metadata", + "metadata_extraction_job_description": "Sari maklumat metadata dari setiap aset, seperti GPS, muka-muka, dan pelaraian", + "metadata_faces_import_setting": "Dayakan import muka", + "metadata_settings": "Tetapan Metadata", + "metadata_settings_description": "Urus tetapan metadata", + "migration_job": "Migrasi", + "migration_job_description": "Pindahkan imej kecil untuk aset-aset dan muka-muka kepada struktur folder terkini", + "no_paths_added": "Tiada laluan yang ditambah", + "no_pattern_added": "Tiada corak ditambah", + "note_cannot_be_changed_later": "NOTA: Ini tidak boleh diubah kemudian!", + "note_unlimited_quota": "Nota: Masukkan 0 untuk kuota tanpa had", + "notification_email_from_address": "Dari alamat", + "notification_email_from_address_description": "Alamat e-mel penghantar, sebagai contoh: \"Immich Photo Server \"", + "notification_email_host_description": "Hos e-mel pelayan (cth. smtp.immich.app)", + "notification_email_ignore_certificate_errors": "Abaikan ralat-ralat sijil", + "notification_email_password_description": "Kata laluan untuk digunakan semasa membuat pengesahan dengan pelayan e-mel", + "notification_email_port_description": "Port pelayan e-mel (cth 25, 465 atau 587)", + "notification_email_sent_test_email_button": "Hantar e-mel ujian dan simpan", + "notification_email_setting_description": "Tetapan-tetapan untuk menghantar notifikasi e-mel", + "notification_email_test_email": "Hantar e-mel ujian", + "notification_email_test_email_failed": "Gagal untuk menghantar e-mel ujian, sila semak nilai-nilai anda", + "notification_email_test_email_sent": "E-mel ujian telah dihantar ke {email}. Sila semak peti masuk anda.", + "notification_email_username_description": "Nama pengguna untuk digunakan semasa mengesahkan dengan pelayan e-mel", + "notification_enable_email_notifications": "Dayakan notifikasi-notifikasi e-mel", + "notification_settings": "Tetapan Pemberitahuan", + "notification_settings_description": "Urus tetapan-tetapan notifikasi, termasuk e-mel", + "oauth_auto_launch": "Pelancaran automatik", + "oauth_auto_register": "Daftar secara automatik", + "oauth_auto_register_description": "Daftar secara automatik pengguna-pengguna baharu selepas mendaftar masuk dengan OAuth", + "oauth_button_text": "Teks butang", + "oauth_client_id": "ID Pelanggan", + "oauth_client_secret": "Rahsia Pelanggan", + "oauth_enable_description": "Log masuk dengan OAuth", + "oauth_issuer_url": "URL Pengeluar", + "oauth_mobile_redirect_uri": "URI ubah hala mudah alih", + "oauth_scope": "Skop", + "oauth_settings": "OAuth", + "oauth_settings_description": "Urus tetapan-tetapan log masuk OAuth", + "oauth_settings_more_details": "Untuk maklumat lanjut tentang ciri ini, rujuk ke dokumen.", + "oauth_storage_quota_default": "Kuota storan lalai (GiB)", + "password_enable_description": "Log masuk dengan e-mel dan kata laluan", + "password_settings": "Kata Laluan Log Masuk", + "password_settings_description": "Urus tetapan-tetapan kata laluan log masuk", + "paths_validated_successfully": "Semua laluan berjaya disahkan", + "quota_size_gib": "Saiz Kuota (GiB)", + "registration": "Pendaftaran Admin", + "registration_description": "Memandangkan anda adalah pengguna pertama pada sistem, anda akan ditugaskan sebagai Admin dan bertanggungjawab untuk tugas pentadbiran, serta pengguna tambahan yang akan anda tambah.", + "repair_all": "Baiki Semua", + "require_password_change_on_login": "Perlukan pengguna menukar kata laluan ketika log masuk pertama", + "reset_settings_to_default": "Tetapkan semula tetapan kepada lalai", + "reset_settings_to_recent_saved": "Tetapkan semula tetapan kepada tetapan yang disimpan baru-baru ini" + }, + "timeline": "Garis masa", + "total": "Jumlah", + "user_usage_stats": "Statistik penggunaan akaun", + "user_usage_stats_description": "Papar statistik penggunaan akaun", + "year": "Tahun", + "yes": "Ya", + "you_dont_have_any_shared_links": "Anda tidak mempunyai apa-apa pautan yang dikongsi", + "zoom_image": "Zum Gambar" } diff --git a/i18n/nb_NO.json b/i18n/nb_NO.json index ea508d1b7ef2a..2d78ea414a15b 100644 --- a/i18n/nb_NO.json +++ b/i18n/nb_NO.json @@ -33,6 +33,11 @@ "authentication_settings_disable_all": "Er du sikker på at du ønsker å deaktivere alle innloggingsmetoder? Innlogging vil bli fullstendig deaktivert.", "authentication_settings_reenable": "For å aktivere på nytt, bruk en Server Command.", "background_task_job": "Bakgrunnsjobber", + "backup_database": "Backupdatabase", + "backup_database_enable_description": "Aktiver databasebackup", + "backup_keep_last_amount": "Antall backuper å beholde", + "backup_settings": "Backupinnstillinger", + "backup_settings_description": "Håndter innstillinger for databasebackup", "check_all": "Merk Alle", "cleared_jobs": "Ryddet opp jobber for: {job}", "config_set_by_file": "Konfigurasjonen er for øyeblikket satt av en konfigurasjonsfil", @@ -41,9 +46,8 @@ "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}?", - "crontab_guru": "Crontab Guru", + "create_job": "Lag jobb", "disable_login": "Deaktiver innlogging", - "disabled": "Deaktivert", "duplicate_detection_job_description": "Kjør maskinlæring på filer for å oppdage lignende bilder. Krever bruk av Smart Search", "exclusion_pattern_description": "Ekskluderingsmønstre lar deg ignorere filer og mapper når du skanner biblioteket ditt. Dette er nyttig hvis du har mapper som inneholder filer du ikke vil importere, for eksempel RAW-filer.", "external_library_created_at": "Ekstern bibliotek (opprettet {date})", @@ -54,21 +58,17 @@ "failed_job_command": "Kommandoen {command} feilet for jobben: {job}", "force_delete_user_warning": "ADVARSEL: Dette vil umiddelbart fjerne brukeren og alle eiendeler. Dette kan ikke angres, og filene kan ikke gjenopprettes.", "forcing_refresh_library_files": "Tvinger oppdatering av alle bibliotekfiler", + "image_format": "Format", "image_format_description": "WebP gir mindre filer enn JPEG, men er tregere å lage.", "image_prefer_embedded_preview": "Foretrekk innebygd forhåndsvisning", "image_prefer_embedded_preview_setting_description": "Bruk innebygd forhåndsvisning i RAW-bilder som inndata til bildebehandling når tilgjengelig. Dette kan gi mer nøyaktige farger for noen bilder, men kvaliteten er avhengig av kamera og bildet kan ha komprimeringsartefakter.", "image_prefer_wide_gamut": "Foretrekk bredt fargespekter", "image_prefer_wide_gamut_setting_description": "Bruk Display P3 for miniatyrbilder. Dette bevarer glød bedre i bilder med bredt fargerom, men det kan hende bilder ser annerledes ut på gamle enheter med en gammel nettleserversjon. sRBG bilder beholdes som sRGB for å unngå fargeforskyvninger.", - "image_preview_format": "Forhåndsvisningsformat", - "image_preview_resolution": "Oppløsning for forhåndsvisninger", - "image_preview_resolution_description": "Brukes ved visning av enkeltbilder og for maskinlæring. Høyere oppløsning kan bevare flere detaljer men tar lengre tid, gir større filer, og kan redusere appens responsivitet.", + "image_preview_title": "Forhåndsvisningsinnstillinger", "image_quality": "Kvalitet", - "image_quality_description": "Bildekvalitet fra 1-100. Høyere verdi gir bedre kvalitet men større filer. Dette valget påvirker forhåndsvisning og miniatyrbilder.", + "image_resolution": "Oppløsning", "image_settings": "Bildeinnstilliinger", "image_settings_description": "Administrer kvalitet og oppløsning på genererte bilder", - "image_thumbnail_format": "Miniatyrbildeformat", - "image_thumbnail_resolution": "Miniatyrbildeoppløsning", - "image_thumbnail_resolution_description": "Brukes ved visning av grupper av bilder (hovedtidslinje, albumvisning, osv.). Høyere oppløsning kan bevare flere detaljer men tar lengre tid å lage, gir større filer, og kan redusere appens responsivitet.", "job_concurrency": "{job} samtidighet", "job_not_concurrency_safe": "Denne jobben er ikke samtidlighet sikker.", "job_settings": "Jobbinnstillinger", @@ -77,9 +77,6 @@ "jobs_delayed": "{jobCount, plural, other {# forsinket}}", "jobs_failed": "{jobCount, plural, other {# mislyktes}}", "library_created": "Opprettet bibliotek: {library}", - "library_cron_expression": "Cron-uttrykk", - "library_cron_expression_description": "Sett skanneintervallet ved å bruke cron-formatering. For mer informasjon, vennligst se f.eks. Crontab Guru.", - "library_cron_expression_presets": "Forhåndsinnstilte Cron-uttrykk", "library_deleted": "Bibliotek slettet", "library_import_path_description": "Spesifiser en mappe for importering. Denne mappen, inkludert undermapper, vil bli skannet for bilder og videoer.", "library_scanning": "Periodisk skanning", @@ -122,7 +119,7 @@ "machine_learning_smart_search_description": "Søk etter bilder semantisk ved å bruke CLIP-embeddings", "machine_learning_smart_search_enabled": "Aktiver smart søk", "machine_learning_smart_search_enabled_description": "Hvis deaktivert, vil bilder ikke bli enkodet for smart søk.", - "machine_learning_url_description": "URL til maskinlærings-serveren", + "machine_learning_url_description": "URL til maskinlærings-serveren. Hvis mer enn en URL er lagt inn, hver server vill bli forsøkt en om gangen frem til en svarer suksessfullt, i rekkefølge fra først til sist.", "manage_concurrency": "Administrer samtidighet", "manage_log_settings": "Administrer logginnstillinger", "map_dark_style": "Mørk stil", @@ -198,15 +195,12 @@ "refreshing_all_libraries": "Oppdaterer alle biblioteker", "registration": "Administrator registrering", "registration_description": "Siden du er den første brukeren på systemet, vil du bli utnevnt til administrator og ha ansvar for administrative oppgaver. Du vil også opprette eventuelle nye brukere.", - "removing_deleted_files": "Fjerner frakoblede filer", "repair_all": "Reparer alle", "repair_matched_items": "Samsvarte med {count, plural, one {# element} other {# elementer}}", "repaired_items": "Reparerte {count, plural, one {# item} other {# items}}", "require_password_change_on_login": "Krev at brukeren endrer passord ved første pålogging", "reset_settings_to_default": "Tilbakestill innstillinger til standard", "reset_settings_to_recent_saved": "Tilbakestill innstillingene til de nylig lagrede innstillingene", - "scanning_library_for_changed_files": "Skanner biblioteket for endrede filer", - "scanning_library_for_new_files": "Skanner biblioteket for nye filer", "send_welcome_email": "Send velkomst-e-post", "server_external_domain_settings": "Eksternt domene", "server_external_domain_settings_description": "Domene for offentlige delingslenker, inkludert http(s)://", @@ -241,7 +235,6 @@ "these_files_matched_by_checksum": "Disse filene er matchet ved hjelp av deres checksum", "thumbnail_generation_job": "Generer miniatyrbilder", "thumbnail_generation_job_description": "Generer store, små og uskarpe miniatyrbilder for hver fil, samt miniatyrbilder for hver person", - "transcode_policy_description": "", "transcoding_acceleration_api": "Akselerasjons-API", "transcoding_acceleration_api_description": "API-et som vil samhandle med enheten din for å akselerere transcoding. Denne innstillingen er 'best effort': den vil falle tilbake til programvaretranscoding ved feil. VP9 kan eller kan ikke fungere avhengig av maskinvaren din.", "transcoding_acceleration_nvenc": "NVENC (krever NVIDIA GPU)", @@ -293,8 +286,6 @@ "transcoding_threads_description": "Høyere verdier fører til raskere koding, men gir mindre plass for serveren til å behandle andre oppgaver mens den er aktiv. Verdien bør ikke være mer enn antall CPU-kjerner. Maksimerer utnyttelsen hvis satt til 0.", "transcoding_tone_mapping": "Tone mapping", "transcoding_tone_mapping_description": "Forsøker å bevare utseendet til HDR-videoer når de konverteres til SDR. Hver algoritme gjør ulike avveininger mellom farge, detaljer og lysstyrke. Hable bevarer detaljer, Mobius bevarer farge, og Reinhard bevarer lysstyrke.", - "transcoding_tone_mapping_npl": "Tone mapping NPL", - "transcoding_tone_mapping_npl_description": "Fargene vil bli justert for å se normale ut på en skjerm med denne lysstyrken. Motintuitivt øker lavere verdier lysstyrken på videoen, og omvendt, siden det kompenserer for skjermens lysstyrke. 0 setter denne verdien automatisk.", "transcoding_transcode_policy": "Transkode retningslinjer", "transcoding_transcode_policy_description": "Retningslinjer for når en video skal transkodes. HDR-videoer vil alltid bli transkodet (unntatt hvis transkoding er deaktivert).", "transcoding_two_pass_encoding": "To-passert koding", @@ -373,7 +364,6 @@ "archive_or_unarchive_photo": "Arkiver eller ta ut av arkivet", "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?", @@ -391,7 +381,6 @@ "asset_uploading": "Laster opp...", "assets": "Filer", "assets_added_count": "Lagt til {count, plural, one {# element} other {# elementer}}", - "assets_moved_to_trash": "Flyttet {count, plural, one {# fil} other {# filer}} til papirkurv", "assets_restore_confirmation": "Er du sikker på at du vil gjenopprette alle slettede eiendeler? Denne handlingen kan ikke angres!", "authorized_devices": "Autoriserte enheter", "back": "Tilbake", @@ -410,10 +399,6 @@ "cannot_merge_people": "Kan ikke slå sammen personer", "cannot_undo_this_action": "Du kan ikke gjøre om denne handlingen!", "cannot_update_the_description": "Kan ikke oppdatere beskrivelsen", - "cant_apply_changes": "Kan ikke gjennomføre endringene", - "cant_get_faces": "Kan ikke hente ansikter", - "cant_search_people": "Kan ikke søke etter personer", - "cant_search_places": "Kan ikke søke etter steder", "change_date": "Endre dato", "change_expiration_time": "Endre utløpstid", "change_location": "Endre sted", @@ -513,13 +498,6 @@ "duplicates": "Duplikater", "duplicates_description": "Løs hver gruppe ved å angi hvilke, hvis noen, er duplikater", "duration": "Varighet", - "durations": { - "days": "{days, plural, one {dag} other {{days, number} dager}}", - "hours": "{hours, plural, one {time} other {{hours, number} timer}}", - "minutes": "{minutes, plural, one {minutt} other {{minutes, number} minutter}}", - "months": "{months, plural, one {måned} other {{months, number} måneder}}", - "years": "{years, plural, one {år} other {{years, number} år}}" - }, "edit_album": "Rediger album", "edit_avatar": "Rediger avatar", "edit_date": "Rediger dato", @@ -538,8 +516,6 @@ "edited": "Redigert", "editor": "Redaktør", "email": "E-postadresse", - "empty": "", - "empty_album": "Tomt Album", "empty_trash": "Tøm papirkurv", "enable": "", "enabled": "", @@ -563,8 +539,6 @@ "unable_to_change_date": "Kan ikke endre dato", "unable_to_change_location": "Kan ikke endre plassering", "unable_to_change_password": "Kan ikke endre passord", - "unable_to_check_item": "", - "unable_to_check_items": "", "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": "", "unable_to_create_api_key": "Kan ikke opprette en ny API-nøkkel", @@ -591,12 +565,10 @@ "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_remove_comment": "", "unable_to_remove_deleted_assets": "Kan ikke fjerne offlinefiler", "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_remove_user": "", "unable_to_repair_items": "Kan ikke reparere elementer", "unable_to_reset_password": "Kan ikke tilbakestille passord", "unable_to_resolve_duplicate": "Kan ikke løse duplikat", @@ -620,10 +592,6 @@ "unable_to_update_timeline_display_status": "Kan ikke oppdatere visningsstatus for tidslinje", "unable_to_update_user": "Kan ikke oppdatere bruker" }, - "every_day_at_onepm": "", - "every_night_at_midnight": "", - "every_night_at_twoam": "", - "every_six_hours": "", "exit_slideshow": "Avslutt lysbildefremvisning", "expand_all": "Utvid alle", "expire_after": "Utgå etter", @@ -634,29 +602,23 @@ "extension": "Utvidelse", "external": "Ekstern", "external_libraries": "Eksterne Bibliotek", - "failed_to_get_people": "Kunne ikke hente personer", "favorite": "Favoritt", "favorite_or_unfavorite_photo": "Merk som favoritt eller fjern som favoritt", "favorites": "Favoritter", - "feature": "", "feature_photo_updated": "Fremhevet bilde oppdatert", - "featurecollection": "", "file_name": "Filnavn", "file_name_or_extension": "Filnavn eller filtype", "filename": "Filnavn", - "files": "", "filetype": "Filtype", "filter_people": "Filtrer personer", "find_them_fast": "Finn dem raskt ved søking av navn", "fix_incorrect_match": "Fiks feilaktig match", - "force_re-scan_library_files": "Tving til å skanne alle bibliotekfiler på nytt", "forward": "Fremover", "general": "Generelt", "get_help": "Få Hjelp", "getting_started": "Kom i gang", "go_back": "Gå tilbake", "go_to_search": "Gå til søk", - "go_to_share_page": "Gå til delingssiden", "group_albums_by": "Grupper album etter...", "has_quota": "Har kvote", "hide_gallery": "Skjul galleri", @@ -665,7 +627,6 @@ "host": "Vert", "hour": "Time", "image": "Bilde", - "img": "", "immich_logo": "Immich Logo", "immich_web_interface": "Immich webgrensesnitt", "import_from_json": "Importer fra JSON", @@ -684,7 +645,6 @@ }, "invite_people": "Inviter Personer", "invite_to_album": "Inviter til album", - "job_settings_description": "", "jobs": "Oppgaver", "keep": "Behold", "keep_all": "Behold alle", @@ -777,7 +737,6 @@ "oldest_first": "Eldste først", "online": "Tilkoblet", "only_favorites": "Bare favoritter", - "only_refreshes_modified_files": "Oppdaterer bare endrede filer", "open_the_search_filters": "Åpne søkefiltrene", "options": "Valg", "organize_your_library": "Organiser biblioteket ditt", @@ -808,12 +767,10 @@ "pending": "Avventer", "people": "Folk", "people_sidebar_description": "Vis en lenke til Personer i sidepanelet", - "perform_library_tasks": "", "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_deleted_asset": "Filen har blitt permanent slettet", - "permanently_deleted_assets": "Permanent slettet {count, plural, one {# asset} other {# assets}}", "photos": "Bilder", "photos_count": "{count, plural, one {{count, number} Bilde} other {{count, number} Bilder}}", "photos_from_previous_years": "Bilder fra tidliger år", @@ -824,7 +781,6 @@ "play_memories": "Spill av minner", "play_motion_photo": "Spill av bevegelsesbilde", "play_or_pause_video": "Spill av eller pause video", - "point": "", "port": "Port", "preset": "Forhåndsinstilling", "preview": "Forhåndsvis", @@ -834,8 +790,6 @@ "primary": "Primær", "profile_picture_set": "Profilbildet er satt.", "public_share": "Offentlig deling", - "range": "", - "raw": "", "reaction_options": "Reaksjonsalternativer", "read_changelog": "Les endringslogg", "recent": "Nylig", @@ -858,7 +812,6 @@ "reset": "Tilbakestill", "reset_password": "Tilbakestill passord", "reset_people_visibility": "Tilbakestill personsynlighet", - "reset_settings_to_default": "", "resolved_all_duplicates": "Løste alle duplikater", "restore": "Gjenopprett", "restore_all": "Gjenopprett alle", @@ -873,8 +826,6 @@ "saved_settings": "Lagret instillinger", "say_something": "Si noe", "scan_all_libraries": "Skann alle biblioteker", - "scan_all_library_files": "Skann alle bibliotekfiler på nytt", - "scan_new_library_files": "Skann nye bibliotekfiler", "scan_settings": "Skanneinnstillinger", "search": "Søk", "search_albums": "Søk i album", @@ -905,7 +856,6 @@ "selected": "Valgt", "send_message": "Send melding", "send_welcome_email": "Send velkomstmelding", - "server": "Server", "server_stats": "Server Statistikk", "set": "Sett", "set_as_album_cover": "Sett som albumomslag", @@ -977,7 +927,6 @@ "to_trash": "Papirkurv", "toggle_settings": "Bytt innstillinger", "toggle_theme": "Bytt tema", - "toggle_visibility": "Bytt synlighet", "total_usage": "Totalt brukt", "trash": "Papirkurv", "trash_all": "Slett alt", @@ -985,11 +934,9 @@ "trashed_items_will_be_permanently_deleted_after": "Elementer i papirkurven vil bli permanent slettet etter {days, plural, one {# dag} other {# dager}}.", "type": "Type", "unarchive": "Fjern fra arkiv", - "unarchived": "Uarkivert", "unfavorite": "Fjern favoritt", "unhide_person": "Vis person", "unknown": "Ukjent", - "unknown_album": "Ukjent Album", "unknown_year": "Ukjent År", "unlimited": "Ubegrenset", "unlink_oauth": "Fjern kobling til OAuth", @@ -1024,11 +971,10 @@ "view_links": "Vis lenker", "view_next_asset": "Vis neste fil", "view_previous_asset": "Vis forrige fil", - "viewer": "Seer", "waiting": "Venter", "week": "Uke", "welcome": "Velkommen", - "welcome_to_immich": "Velkommen til immich", + "welcome_to_immich": "Velkommen til Immich", "year": "År", "yes": "Ja", "you_dont_have_any_shared_links": "Du har ingen delte lenker", diff --git a/i18n/nl.json b/i18n/nl.json index d437ae17f7361..de88cba9da813 100644 --- a/i18n/nl.json +++ b/i18n/nl.json @@ -23,6 +23,7 @@ "add_to": "Toevoegen aan...", "add_to_album": "Aan album toevoegen", "add_to_shared_album": "Aan gedeeld album toevoegen", + "add_url": "URL toevoegen", "added_to_archive": "Toegevoegd aan archief", "added_to_favorites": "Toegevoegd aan favorieten", "added_to_favorites_count": "{count, number} toegevoegd aan favorieten", @@ -34,6 +35,11 @@ "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", + "backup_database": "Backup Database", + "backup_database_enable_description": "Database back-ups activeren", + "backup_keep_last_amount": "Maximaal aantal back-ups om te bewaren", + "backup_settings": "Back-up instellingen", + "backup_settings_description": "Database back-up instellingen beheren", "check_all": "Controleer het logboek", "cleared_jobs": "Taken gewist voor: {job}", "config_set_by_file": "Instellingen worden momenteel beheerd door een configuratiebestand", @@ -43,9 +49,10 @@ "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 u zeker dat je het wachtwoord van {user} wilt resetten?", "create_job": "Taak maken", - "crontab_guru": "Crontab Guru", + "cron_expression": "Cron expressie", + "cron_expression_description": "Stel de scaninterval in met het cron-formaat. Voor meer informatie kun je kijken naar bijvoorbeeld Crontab Guru", + "cron_expression_presets": "Cron-expressie presets", "disable_login": "Inloggen uitschakelen", - "disabled": "Uitgeschakeld", "duplicate_detection_job_description": "Machine learning uitvoeren op assets om vergelijkbare assets te vinden. Dit is gebaseerd op Slim Zoeken", "exclusion_pattern_description": "Met uitsluitingspatronen kun je bestanden en mappen negeren bij het scannen van je bibliotheek. Dit is handig als je mappen hebt met bestanden die je niet wilt importeren, zoals RAW bestanden.", "external_library_created_at": "Externe bibliotheek (gemaakt op {date})", @@ -63,22 +70,15 @@ "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.", "image_preview_description": "Middelgrote afbeelding met verwijderde metadata, gebruikt bij het bekijken van een enkele asset en voor machine learning", - "image_preview_format": "Voorbeeldformaat", "image_preview_quality_description": "Voorbeeldafbeelding kwaliteit van 1-100. Hoger is beter, maar produceert grotere bestanden en kan de app vertragen. Een lage waarde kan de kwaliteit van machine learning beïnvloeden.", - "image_preview_resolution": "Voorbeeldresolutie", - "image_preview_resolution_description": "Gebruikt bij het tonen van een enkele foto en voor machine learning. Hogere resoluties kunnen meer detail behouden maar duren langer om te verwerken, hebben hogere bestandsgrootte, en kunnen de applicatie langzamer maken.", "image_preview_title": "Voorbeeldafbeelding instellingen", "image_quality": "Kwaliteit", - "image_quality_description": "Afbeeldingskwaliteit van 1-100. Een hoger getal zorgt voor een betere fotokwaliteit, maar produceert grotere bestanden. Dit heeft effect op voorbeeldfoto's en thumbnails.", "image_resolution": "Resolutie", "image_resolution_description": "Hogere resoluties behouden meer details, maar verhogen de coderingstijd, bestandsgrootte en kunnen de app vertragen.", "image_settings": "Afbeeldings instellingen", "image_settings_description": "Beheer de kwaliteit en resolutie van gegenereerde afbeeldingen", "image_thumbnail_description": "Kleine thumbnail zonder metadata, gebruikt voor het bekijken van groepen met foto's zoals de tijdlijn", - "image_thumbnail_format": "Thumbnail bestandsformaat", "image_thumbnail_quality_description": "Thumbnail kwaliteit van 1-100. Hoger is beter, maar produceert grotere bestanden en kan de app vertragen.", - "image_thumbnail_resolution": "Thumbnail resolutie", - "image_thumbnail_resolution_description": "Gebruikt wanneer groepen foto's bekeken worden (hoofdtijdslijn, album, enzo). Hogere resoluties kunnen meer detail behouden maar duren langer om te verwerken, hebben hogere bestandsgrootte, en kunnen de applicatie langzamer maken.", "image_thumbnail_title": "Thumbnail instellingen", "job_concurrency": "{job} gelijktijdigheid", "job_created": "Taak aangemaakt", @@ -89,9 +89,6 @@ "jobs_delayed": "{jobCount, plural, other {# vertraagd}}", "jobs_failed": "{jobCount, plural, other {# mislukt}}", "library_created": "Bibliotheek aangemaakt: {library}", - "library_cron_expression": "Cron expressie", - "library_cron_expression_description": "Stel het scaninterval in met het cron-formaat. Voor meer informatie kun je kijken naar bijvoorbeeld Crontab Guru", - "library_cron_expression_presets": "Standaard cron expressies", "library_deleted": "Bibliotheek verwijderd", "library_import_path_description": "Voer een map in om te importeren. Deze map, inclusief submappen, wordt gescand op afbeeldingen en video's.", "library_scanning": "Periodiek scannen", @@ -134,7 +131,7 @@ "machine_learning_smart_search_description": "Semantisch zoeken naar afbeeldingen met CLIP-embeddings", "machine_learning_smart_search_enabled": "Slim zoeken inschakelen", "machine_learning_smart_search_enabled_description": "Indien uitgeschakeld, worden afbeeldingen niet verwerkt voor slim zoeken.", - "machine_learning_url_description": "URL van de machine learning server", + "machine_learning_url_description": "De URL van de machine learning server. Als er meer dan één URL is opgegeven, wordt elke server geprobeerd totdat er een succesvol reageert, op volgorde van eerste tot laatste.", "manage_concurrency": "Beheer gelijktijdigheid", "manage_log_settings": "Beheer logboekinstellingen", "map_dark_style": "Donkere stijl", @@ -215,7 +212,6 @@ "refreshing_all_libraries": "Alle bibliotheken aan het vernieuwen", "registration": "Beheerder registratie", "registration_description": "Omdat je de eerste gebruiker in het systeem bent, word je toegewezen als beheerder en ben je verantwoordelijk voor administratieve taken. Extra gebruikers kunnen door jou worden aangemaakt.", - "removing_deleted_files": "Offline bestanden verwijderen", "repair_all": "Repareer alle", "repair_matched_items": "Overeenkomend {count, plural, one {# item} other {# items}}", "repaired_items": "Gerepareerd {count, plural, one {# item} other {# items}}", @@ -223,17 +219,17 @@ "reset_settings_to_default": "Instellingen teruggezet naar standaard", "reset_settings_to_recent_saved": "Instellingen zijn gereset naar de recent opgeslagen instellingen", "scanning_library": "Bibliotheek scannen", - "scanning_library_for_changed_files": "Bibliotheek scannen op gewijzigde bestanden", - "scanning_library_for_new_files": "Bibliotheek scannen op nieuwe bestanden", "search_jobs": "Taak zoeken...", "send_welcome_email": "Stuur een welkomstmail", "server_external_domain_settings": "Extern domein", "server_external_domain_settings_description": "Domein voor openbaar gedeelde links, inclusief http(s)://", + "server_public_users": "Openbare gebruikerslijst", + "server_public_users_description": "Alle gebruikers (met naam en e-mailadres) worden weergegeven wanneer een gebruiker wordt toegevoegd aan gedeelde albums. Wanneer uitgeschakeld, is de gebruikerslijst alleen beschikbaar voor beheerders.", "server_settings": "Serverinstellingen", "server_settings_description": "Beheer serverinstellingen", "server_welcome_message": "Welkomstbericht", "server_welcome_message_description": "Een bericht dat op de inlogpagina wordt weergegeven.", - "sidecar_job": "Sidecar metadata", + "sidecar_job": "Sidecar metagegevens", "sidecar_job_description": "Zoek of synchroniseer sidecar metadata van het bestandssysteem", "slideshow_duration_description": "Aantal seconden dat iedere afbeelding wordt getoond", "smart_search_job_description": "Voer machine learning uit op assets om te gebruiken voor slim zoeken", @@ -254,6 +250,16 @@ "storage_template_user_label": "{label} is het opslaglabel van de gebruiker", "system_settings": "Systeeminstellingen", "tag_cleanup_job": "Tag opschoning", + "template_email_available_tags": "Je kan de volgende tags gebruiken in een template: {tags}", + "template_email_if_empty": "Wanneer het sjabloon leeg is, wordt de standaard mail gebruikt.", + "template_email_invite_album": "Uitgenodigd in album sjabloon", + "template_email_preview": "Voorbeeld", + "template_email_settings": "Email", + "template_email_settings_description": "Beheer aangepaste email melding sjablonen", + "template_email_update_album": "Update in album sjabloon", + "template_email_welcome": "Welkom email sjabloon", + "template_settings": "Melding sjablonen", + "template_settings_description": "Beheer aangepast sjablonen voor meldingen.", "theme_custom_css_settings": "Aangepaste CSS", "theme_custom_css_settings_description": "Met Cascading Style Sheets kan het ontwerp van Immich worden aangepast.", "theme_settings": "Thema instellingen", @@ -261,7 +267,6 @@ "these_files_matched_by_checksum": "Deze bestanden worden gematcht op basis van hun checksums", "thumbnail_generation_job": "Thumbnail genereren", "thumbnail_generation_job_description": "Genereer grote, kleine en vervaagde thumbnails voor iedere asset, en genereer thumbnails voor iedere persoon", - "transcode_policy_description": "Beleid voor wanneer een video moet worden getranscodeerd. HDR-video's worden altijd getranscodeerd (behalve als transcodering is uitgeschakeld).", "transcoding_acceleration_api": "Acceleration 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)", @@ -300,7 +305,7 @@ "transcoding_preferred_hardware_device_description": "Geldt alleen voor VAAPI en QSV. Stelt de dri node in die wordt gebruikt voor hardwaretranscodering.", "transcoding_preset_preset": "Preset (-preset)", "transcoding_preset_preset_description": "Compressiesnelheid. Langzamere presets produceren kleinere bestanden en verhogen de kwaliteit bij het targeten van een bepaalde bitrate. VP9 negeert snelheden boven 'faster'.", - "transcoding_reference_frames": "Reference frames", + "transcoding_reference_frames": "Referentie frames", "transcoding_reference_frames_description": "Het aantal frames om naar te verwijzen bij het comprimeren van een bepaald frame. Hogere waarden verbeteren de compressie-efficiëntie, maar vertragen de codering. Bij 0 wordt deze waarde automatisch ingesteld.", "transcoding_required_description": "Alleen video's die geen geaccepteerd formaat hebben", "transcoding_settings": "Instellingen voor videotranscodering", @@ -313,11 +318,9 @@ "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_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_tone_mapping_npl": "Tone-mapping NPL", - "transcoding_tone_mapping_npl_description": "Kleuren zullen aangepast worden om normaal te lijken voor een display van deze helderheid. Contra-intuïtief, lagere waarden verhogen de helderheid van de video en vice versa sinds het compenseert voor de helderheid van de tentoonstelling. 0 zet deze waarde automatisch.", "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).", - "transcoding_two_pass_encoding": "Two-pass encoding", + "transcoding_two_pass_encoding": "Two-pass encodering", "transcoding_two_pass_encoding_setting_description": "Transcodeer in twee passes om beter gecodeerde video's te produceren. Wanneer de maximale bitrate is ingeschakeld (vereist om te werken met H.264 en HEVC), gebruikt deze modus een bitraterange op basis van de maximale bitrate en negeert CRF. Voor VP9 kan CRF worden gebruikt als de maximale bitrate is uitgeschakeld.", "transcoding_video_codec": "Video codec", "transcoding_video_codec_description": "VP9 heeft een hoge efficiëntie en webcompatibiliteit, maar duurt langer om te transcoderen. HEVC presteert vergelijkbaar, maar heeft een lagere webcompatibiliteit. H.264 is breed compatibel en snel om te transcoderen, maar produceert veel grotere bestanden. AV1 is de meest efficiënte codec, maar mist ondersteuning op oudere apparaten.", @@ -395,7 +398,6 @@ "archive_or_unarchive_photo": "Foto archiveren of uit het archief halen", "archive_size": "Archiefgrootte", "archive_size_description": "Configureer de archiefgrootte voor downloads (in GiB)", - "archived": "Gearchiveerd", "archived_count": "{count, plural, other {# gearchiveerd}}", "are_these_the_same_person": "Zijn dit dezelfde personen?", "are_you_sure_to_do_this": "Weet je zeker dat je dit wilt doen?", @@ -416,7 +418,6 @@ "assets_added_to_album_count": "{count, plural, one {# asset} other {# assets}} aan het album toegevoegd", "assets_added_to_name_count": "{count, plural, one {# asset} other {# assets}} toegevoegd aan {hasName, select, true {{name}} other {nieuw album}}", "assets_count": "{count, plural, one {# asset} other {# assets}}", - "assets_moved_to_trash": "{count, plural, one {# asset} other {# assets}} naar de prullenbak verplaatst", "assets_moved_to_trash_count": "{count, plural, one {# asset} other {# assets}} verplaatst naar prullenbak", "assets_permanently_deleted_count": "{count, plural, one {# asset} other {# assets}} permanent verwijderd", "assets_removed_count": "{count, plural, one {# asset} other {# assets}} verwijderd", @@ -446,10 +447,6 @@ "cannot_merge_people": "Kan mensen niet samenvoegen", "cannot_undo_this_action": "Je kunt deze actie niet ongedaan maken!", "cannot_update_the_description": "Kan de beschrijving niet bijwerken", - "cant_apply_changes": "Kan wijzigingen niet toepassen", - "cant_get_faces": "Kan gezichten niet ophalen", - "cant_search_people": "Kan mensen niet zoeken", - "cant_search_places": "Kan plaatsen niet zoeken", "change_date": "Wijzig datum", "change_expiration_time": "Wijzig verlooptijd", "change_location": "Wijzig locatie", @@ -481,6 +478,7 @@ "confirm": "Bevestigen", "confirm_admin_password": "Bevestig beheerder wachtwoord", "confirm_delete_shared_link": "Weet je zeker dat je deze gedeelde link wilt verwijderen?", + "confirm_keep_this_delete_others": "Alle andere assets in de stack worden verwijderd, behalve deze. Weet je zeker dat je wilt doorgaan?", "confirm_password": "Bevestig wachtwoord", "contain": "Bevat", "context": "Context", @@ -530,6 +528,7 @@ "delete_key": "Verwijder sleutel", "delete_library": "Verwijder bibliotheek", "delete_link": "Verwijder link", + "delete_others": "Andere verwijderen", "delete_shared_link": "Verwijder gedeelde link", "delete_tag": "Tag verwijderen", "delete_tag_confirmation_prompt": "Weet je zeker dat je de tag {tagName} wilt verwijderen?", @@ -563,13 +562,6 @@ "duplicates": "Duplicaten", "duplicates_description": "Kies voor iedere groep welke, indien aanwezig, duplicaten zijn", "duration": "Tijdsduur", - "durations": { - "days": "{days, plural, one {dag} other {{days, number} dagen}}", - "hours": "{hours, plural, one {uur} other {{hours, number} uren}}", - "minutes": "{minutes, plural, one {minuut} other {{minutes, number} minuten}}", - "months": "{months, plural, one {maand} other {{months, number} maanden}}", - "years": "{years, plural, one {jaar} other {{years, number} jaren}}" - }, "edit": "Bewerken", "edit_album": "Album bewerken", "edit_avatar": "Avatar bewerken", @@ -594,8 +586,6 @@ "editor_crop_tool_h2_aspect_ratios": "Beeldverhoudingen", "editor_crop_tool_h2_rotation": "Rotatie", "email": "E-mailadres", - "empty": "", - "empty_album": "Leeg album", "empty_trash": "Prullenbak leegmaken", "empty_trash_confirmation": "Weet je zeker dat je de prullenbak wilt legen? Hiermee worden alle assets in de prullenbak permanent uit Immich verwijderd.\nJe kunt deze actie niet ongedaan maken!", "enable": "Inschakelen", @@ -629,6 +619,7 @@ "failed_to_create_shared_link": "Fout bij maken van gedeelde link", "failed_to_edit_shared_link": "Fout bij bewerken van gedeelde link", "failed_to_get_people": "Fout bij ophalen van mensen", + "failed_to_keep_this_delete_others": "Het is niet gelukt om dit asset te behouden en de andere assets te verwijderen", "failed_to_load_asset": "Kan asset niet laden", "failed_to_load_assets": "Kan assets niet laden", "failed_to_load_people": "Kan mensen niet laden", @@ -656,8 +647,6 @@ "unable_to_change_location": "Kan locatie niet wijzigen", "unable_to_change_password": "Kan wachtwoord niet veranderen", "unable_to_change_visibility": "Kan de zichtbaarheid van {count, plural, one {# persoon} other {# mensen}} niet wijzigen", - "unable_to_check_item": "", - "unable_to_check_items": "", "unable_to_complete_oauth_login": "Kan inloggen met OAuth niet voltooie", "unable_to_connect": "Kan niet verbinden", "unable_to_connect_to_server": "Kan geen verbinding maken met server", @@ -679,7 +668,7 @@ "unable_to_empty_trash": "Kan prullenbak niet legen", "unable_to_enter_fullscreen": "Kan volledig scherm niet openen", "unable_to_exit_fullscreen": "Kan volledig scherm niet afsluiten", - "unable_to_get_comments_number": "Kan het aantal opmerkingen niet ophalen", + "unable_to_get_comments_number": "Niet mogelijk om het aantal opmerkingen op te halen", "unable_to_get_shared_link": "Kan gedeelde link niet ophalen", "unable_to_hide_person": "Kan persoon niet verbergen", "unable_to_link_motion_video": "Kan bewegende video niet verbinden", @@ -698,12 +687,10 @@ "unable_to_remove_album_users": "Kan gebruiker niet van album verwijderen", "unable_to_remove_api_key": "Kan API sleutel niet verwijderen", "unable_to_remove_assets_from_shared_link": "Kan assets niet verwijderen uit gedeelde link", - "unable_to_remove_comment": "", "unable_to_remove_deleted_assets": "Kan offline bestanden niet verwijderen", "unable_to_remove_library": "Kan bibliotheek niet verwijderen", "unable_to_remove_partner": "Kan partner niet verwijderen", "unable_to_remove_reaction": "Kan reactie niet verwijderen", - "unable_to_remove_user": "", "unable_to_repair_items": "Kan items niet repareren", "unable_to_reset_password": "Kan wachtwoord niet resetten", "unable_to_resolve_duplicate": "Kan duplicaat niet oplossen", @@ -733,10 +720,6 @@ "unable_to_update_user": "Kan gebruiker niet bijwerken", "unable_to_upload_file": "Kan bestand niet uploaden" }, - "every_day_at_onepm": "", - "every_night_at_midnight": "", - "every_night_at_twoam": "", - "every_six_hours": "", "exif": "Exif", "exit_slideshow": "Diavoorstelling sluiten", "expand_all": "Alles uitvouwen", @@ -751,33 +734,28 @@ "external": "Extern", "external_libraries": "Externe bibliotheken", "face_unassigned": "Niet toegewezen", - "failed_to_get_people": "Kan mensen niet ophalen", + "failed_to_load_assets": "Kan assets niet laden", "favorite": "Favoriet", "favorite_or_unfavorite_photo": "Foto markeren als of verwijderen uit favorieten", "favorites": "Favorieten", - "feature": "", "feature_photo_updated": "Uitgelichte afbeelding bijgewerkt", - "featurecollection": "", "features": "Functies", "features_setting_description": "Beheer de app functies", "file_name": "Bestandsnaam", "file_name_or_extension": "Bestandsnaam of extensie", "filename": "Bestandsnaam", - "files": "", "filetype": "Bestandstype", "filter_people": "Filter op mensen", "find_them_fast": "Vind ze snel op naam door te zoeken", "fix_incorrect_match": "Onjuiste overeenkomst corrigeren", "folders": "Mappen", "folders_feature_description": "Bladeren door de mapweergave van de foto's en video's op het bestandssysteem", - "force_re-scan_library_files": "Forceer herscan van alle bibliotheekbestanden", "forward": "Vooruit", "general": "Algemeen", "get_help": "Krijg hulp", "getting_started": "Aan de slag", "go_back": "Ga terug", "go_to_search": "Ga naar zoeken", - "go_to_share_page": "Ga naar de deelpagina", "group_albums_by": "Groepeer albums op...", "group_no": "Niet groeperen", "group_owner": "Groeperen op eigenaar", @@ -803,10 +781,6 @@ "image_alt_text_date_place_2_people": "{isVideo, select, true {Video} other {Image}} genomen in {city}, {country} met {person1} en {person2} op {date}", "image_alt_text_date_place_3_people": "{isVideo, select, true {Video} other {Image}} genomen in {city}, {country} met {person1}, {person2}, en {person3} op {date}", "image_alt_text_date_place_4_or_more_people": "{isVideo, select, true {Video} other {Image}} genomen in {city}, {country} met {person1}, {person2}, en {additionalCount, number} anderen op {date}", - "image_alt_text_people": "{count, plural, =1 {met {person1}} =2 {met {person1} en {person2}} =3 {met {person1}, {person2} en {person3}} other {met {person1}, {person2} en {others, number} anderen}}", - "image_alt_text_place": "in {city}, {country}", - "image_taken": "{isVideo, select, true {Video gemaakt} other {Afbeelding genomen}}", - "img": "", "immich_logo": "Immich logo", "immich_web_interface": "Immich Web Interface", "import_from_json": "Importeren vanuit JSON", @@ -827,10 +801,11 @@ "invite_people": "Mensen uitnodigen", "invite_to_album": "Uitnodigen voor album", "items_count": "{count, plural, one {# item} other {# items}}", - "job_settings_description": "", "jobs": "Taken", "keep": "Behouden", "keep_all": "Behoud alle", + "keep_this_delete_others": "Deze behouden, andere verwijderen", + "kept_this_deleted_others": "Deze asset behouden en {count, plural, one {# andere asset} other {# andere assets}} verwijderd", "keyboard_shortcuts": "Sneltoetsen", "language": "Taal", "language_setting_description": "Selecteer je voorkeurstaal", @@ -842,31 +817,6 @@ "level": "Niveau", "library": "Bibliotheek", "library_options": "Bibliotheek opties", - "license_account_info": "Je account heeft een licentie", - "license_activated_subtitle": "Bedankt voor het ondersteunen van Immich en open-source software", - "license_activated_title": "Je licentie is succesvol geactiveerd", - "license_button_activate": "Activeren", - "license_button_buy": "Kopen", - "license_button_buy_license": "Koop licentie", - "license_button_select": "Selecteren", - "license_failed_activation": "Activeren licentie mislukt. Controleer je e-mail voor de juiste licentiesleutel!", - "license_individual_description_1": "1 licentie per gebruiker op iedere server", - "license_individual_title": "Individuele licentie", - "license_info_licensed": "Gelicentieerd", - "license_info_unlicensed": "Ongelicentieerd", - "license_input_suggestion": "Heb je een licentie? Voer de sleutel hieronder in", - "license_license_subtitle": "Koop een licentie om Immich te ondersteunen", - "license_license_title": "LICENTIE", - "license_lifetime_description": "Levenslange licentie", - "license_per_server": "Per server", - "license_per_user": "Per gebruiker", - "license_server_description_1": "1 licentie per server", - "license_server_description_2": "Licentie voor alle gebruikers op de server", - "license_server_title": "Serverlicentie", - "license_trial_info_1": "Je gebruikt een niet-gelicentieerde versie van Immich", - "license_trial_info_2": "Je hebt Immich al gebruikt voor ongeveer", - "license_trial_info_3": "{accountAge, plural, one {# dag} other {# dagen}}", - "license_trial_info_4": "Overweeg een licentie te kopen om de verdere ontwikkeling van de service te ondersteunen", "light": "Licht", "like_deleted": "Like verwijderd", "link_motion_video": "verbind bewegende video", @@ -966,13 +916,11 @@ "oldest_first": "Oudste eerst", "onboarding": "Onboarding", "onboarding_privacy_description": "De volgende (optionele) functies zijn afhankelijk van externe services en kunnen op elk moment worden uitgeschakeld in de beheerdersinstellingen.", - "onboarding_storage_template_description": "Wanneer ingeschakeld, zal deze functie bestanden automatisch organiseren gebaseerd op een gebruiker-definieerd template. Gezien de stabiliteitsproblemen is de functie standaard uitgeschakeld. Voor meer informatie, bekijk de [documentatie].", "onboarding_theme_description": "Kies een kleurenthema voor de applicatie. Dit kun je later wijzigen in je instellingen.", "onboarding_welcome_description": "Laten we de applicatie instellen met enkele veelgebruikte instellingen.", "onboarding_welcome_user": "Welkom, {user}", "online": "Online", "only_favorites": "Alleen favorieten", - "only_refreshes_modified_files": "Vernieuwt alleen gewijzigde bestanden", "open_in_map_view": "Openen in kaartweergave", "open_in_openstreetmap": "Openen in OpenStreetMap", "open_the_search_filters": "Open de zoekfilters", @@ -1010,14 +958,12 @@ "people_edits_count": "{count, plural, one {# persoon} other {# mensen}} bijgewerkt", "people_feature_description": "Bladeren door foto's en video's gegroepeerd op personen", "people_sidebar_description": "Toon een link naar Mensen in de zijbalk", - "perform_library_tasks": "", "permanent_deletion_warning": "Waarschuwing voor permanent verwijderen", "permanent_deletion_warning_setting_description": "Toon een waarschuwing bij het permanent verwijderen van assets", "permanently_delete": "Permanent verwijderen", "permanently_delete_assets_count": "{count, plural, one {Asset} other {Assets}} permanent verwijderen", "permanently_delete_assets_prompt": "Weet je zeker dat je deze {count, plural, one {asset} other {# assets}} permanent wilt verwijderen? Hiermee {count, plural, one {wordt} other {worden}} deze ook uit de bijbehorende album(s) verwijderd.", "permanently_deleted_asset": "Asset permanent verwijderd", - "permanently_deleted_assets": "{count, plural, one {# asset} other {# assets}} permanent verwijderd", "permanently_deleted_assets_count": "{count, plural, one {# asset} other {# assets}} permanent verwijderd", "person": "Persoon", "person_hidden": "{name}{hidden, select, true { (verborgen)} other {}}", @@ -1033,7 +979,6 @@ "play_memories": "Herinneringen afspelen", "play_motion_photo": "Bewegingsfoto afspelen", "play_or_pause_video": "Video afspelen of pauzeren", - "point": "", "port": "Poort", "preset": "Voorinstelling", "preview": "Voorbeeld", @@ -1078,12 +1023,10 @@ "purchase_server_description_2": "Supporter badge", "purchase_server_title": "Server", "purchase_settings_server_activated": "De productcode van de server wordt beheerd door de beheerder", - "range": "", "rating": "Ster waardering", "rating_clear": "Waardering verwijderen", "rating_count": "{count, plural, one {# ster} other {# sterren}}", "rating_description": "De EXIF-waardering weergeven in het infopaneel", - "raw": "", "reaction_options": "Reactie opties", "read_changelog": "Lees wijzigingen", "reassign": "Opnieuw toewijzen", @@ -1091,6 +1034,7 @@ "reassigned_assets_to_new_person": "{count, plural, one {# asset} other {# assets}} opnieuw toegewezen aan een nieuw persoon", "reassing_hint": "Geselecteerde assets toewijzen aan een bestaand persoon", "recent": "Recent", + "recent-albums": "Recente albums", "recent_searches": "Recente zoekopdrachten", "refresh": "Vernieuwen", "refresh_encoded_videos": "Vernieuw gecodeerde video's", @@ -1112,6 +1056,7 @@ "remove_from_album": "Verwijder uit album", "remove_from_favorites": "Verwijderen uit favorieten", "remove_from_shared_link": "Verwijderen uit gedeelde link", + "remove_url": "Verwijder URL", "remove_user": "Gebruiker verwijderen", "removed_api_key": "API sleutel verwijderd: {name}", "removed_from_archive": "Verwijderd uit archief", @@ -1128,7 +1073,6 @@ "reset": "Resetten", "reset_password": "Wachtwoord resetten", "reset_people_visibility": "Zichtbaarheid mensen resetten", - "reset_settings_to_default": "", "reset_to_default": "Resetten naar standaard", "resolve_duplicates": "Duplicaten oplossen", "resolved_all_duplicates": "Alle duplicaten verwerkt", @@ -1148,9 +1092,7 @@ "saved_settings": "Instellingen opgeslagen", "say_something": "Zeg iets", "scan_all_libraries": "Scan alle bibliotheken", - "scan_all_library_files": "Herscan alle bibliotheekbestanden", "scan_library": "Scannen", - "scan_new_library_files": "Scan nieuwe bibliotheekbestanden", "scan_settings": "Scaninstellingen", "scanning_for_album": "Scannen voor album...", "search": "Zoeken", @@ -1193,7 +1135,6 @@ "selected_count": "{count, plural, other {# geselecteerd}}", "send_message": "Bericht versturen", "send_welcome_email": "Stuur welkomstmail", - "server": "Server", "server_offline": "Server offline", "server_online": "Server online", "server_stats": "Serverstatistieken", @@ -1298,17 +1239,17 @@ "they_will_be_merged_together": "Zij zullen worden samengevoegd", "third_party_resources": "Bronnen van derden", "time_based_memories": "Tijdgebaseerde herinneringen", + "timeline": "Tijdlijn", "timezone": "Tijdzone", "to_archive": "Archiveren", "to_change_password": "Wijzig wachtwoord", "to_favorite": "Toevoegen aan favorieten", "to_login": "Inloggen", "to_parent": "Ga naar hoofdmap", - "to_root": "Naar hoofdmap", "to_trash": "Prullenbak", "toggle_settings": "Zichtbaarheid instellingen wisselen", "toggle_theme": "Donker thema toepassen", - "toggle_visibility": "Zichtbaarheid wisselen", + "total": "Totaal", "total_usage": "Totaal gebruik", "trash": "Prullenbak", "trash_all": "Verplaats alle naar prullenbak", @@ -1318,12 +1259,10 @@ "trashed_items_will_be_permanently_deleted_after": "Items in de prullenbak worden na {days, plural, one {# dag} other {# dagen}} permanent verwijderd.", "type": "Type", "unarchive": "Herstellen uit archief", - "unarchived": "Hersteld uit archief", "unarchived_count": "{count, plural, other {# verwijderd uit archief}}", "unfavorite": "Verwijderen uit favorieten", "unhide_person": "Persoon zichtbaar maken", "unknown": "Onbekend", - "unknown_album": "Onbekend album", "unknown_year": "Onbekend jaar", "unlimited": "Onbeperkt", "unlink_motion_video": "Maak bewegende video los", @@ -1355,13 +1294,13 @@ "use_custom_date_range": "Gebruik in plaats daarvan een aangepast datumbereik", "user": "Gebruiker", "user_id": "Gebruikers ID", - "user_license_settings": "Licentie", - "user_license_settings_description": "Beheer je licentie", "user_liked": "{user} heeft {type, select, photo {deze foto} video {deze video} asset {deze asset} other {dit}} geliket", "user_purchase_settings": "Kopen", "user_purchase_settings_description": "Beheer je aankoop", "user_role_set": "{user} instellen als {role}", "user_usage_detail": "Gedetailleerd gebruik van gebruikers", + "user_usage_stats": "Statistieken van accountgebruik", + "user_usage_stats_description": "Bekijk statistieken van accountgebruik", "username": "Gebruikersnaam", "users": "Gebruikers", "utilities": "Gereedschap", @@ -1369,7 +1308,7 @@ "variables": "Variabelen", "version": "Versie", "version_announcement_closing": "Je vriend, Alex", - "version_announcement_message": "Hallo vriend, er is een nieuwe versie van de applicatie beschikbaar. Neem de tijd om de release notes te bekijken en zorg ervoor dat je docker-compose.yml en .env up-to-date zijn om misconfiguraties te voorkomen, vooral als je WatchTower of een andere automatische update-mechanisme gebruikt.", + "version_announcement_message": "Hallo! Er is een nieuwe versie van Immich beschikbaar. Neem even de tijd om de release notes te lezen en zorg ervoor dat je setup up-to-date is om misconfiguraties te voorkomen, vooral als je WatchTower of een andere update-mechanisme gebruikt.", "version_history": "Versiegeschiedenis", "version_history_item": "{version} geïnstalleerd op {date}", "video": "Video", @@ -1383,10 +1322,10 @@ "view_all_users": "Bekijk alle gebruikers", "view_in_timeline": "Bekijk in tijdlijn", "view_links": "Links bekijken", + "view_name": "Bekijken", "view_next_asset": "Bekijk volgende asset", "view_previous_asset": "Bekijk vorige asset", "view_stack": "Bekijk stapel", - "viewer": "Bekijker", "visibility_changed": "Zichtbaarheid gewijzigd voor {count, plural, one {# persoon} other {# mensen}}", "waiting": "Wachtend", "warning": "Waarschuwing", diff --git a/i18n/nn.json b/i18n/nn.json new file mode 100644 index 0000000000000..bfbb2dc2acc5c --- /dev/null +++ b/i18n/nn.json @@ -0,0 +1,33 @@ +{ + "about": "Om", + "account": "Konto", + "account_settings": "Kontoinnstillingar", + "acknowledge": "Godkjenn", + "action": "Handling", + "actions": "Handlingar", + "active": "Aktiv", + "activity": "Aktivitet", + "activity_changed": "Aktivitet er {enabled, select, true {aktivert} other {deaktivert}}", + "add": "Legg til", + "add_a_description": "Legg til ei skildring", + "add_a_location": "Legg til ein stad", + "add_a_name": "Legg til eit namn", + "add_a_title": "Legg til ein tittel", + "add_exclusion_pattern": "Legg til ekskluderingsmønster", + "add_import_path": "Legg til sti for importering", + "add_location": "Legg til stad", + "add_more_users": "Legg til fleire brukarar", + "add_partner": "Legg til partnar", + "add_path": "Legg til sti", + "add_photos": "Legg til bilete", + "add_to": "Legg til...", + "add_to_album": "Legg til album", + "add_to_shared_album": "Legg til delt album", + "add_url": "Legg til URL", + "added_to_archive": "Lagt til arkiv", + "added_to_favorites": "Lagt til favorittar", + "added_to_favorites_count": "Lagt {count, number} til favorittar", + "admin": { + "confirm_delete_library": "Er du sikker på at du vil slette biblioteket {library}?" + } +} diff --git a/i18n/pl.json b/i18n/pl.json index 26b89008a740b..5aa732327ea92 100644 --- a/i18n/pl.json +++ b/i18n/pl.json @@ -1,8 +1,8 @@ { - "about": "O aplikacji", + "about": "O", "account": "Konto", "account_settings": "Ustawienia konta", - "acknowledge": "Rozumiem", + "acknowledge": "Zrozumiałem/łam", "action": "Akcja", "actions": "Akcje/i", "active": "Aktywne", @@ -23,6 +23,7 @@ "add_to": "Dodaj do...", "add_to_album": "Dodaj do albumu", "add_to_shared_album": "Dodaj do udostępnionego albumu", + "add_url": "Dodaj URL", "added_to_archive": "Dodano do archiwum", "added_to_favorites": "Dodano do ulubionych", "added_to_favorites_count": "Dodano {count, number} do ulubionych", @@ -34,6 +35,11 @@ "authentication_settings_disable_all": "Czy jesteś pewny, że chcesz wyłączyć wszystkie metody logowania? Logowanie będzie całkowicie wyłączone.", "authentication_settings_reenable": "Aby ponownie włączyć, użyj Polecenia serwera.", "background_task_job": "Zadania w Tle", + "backup_database": "Kopia zapasowa bazy danych", + "backup_database_enable_description": "Włącz kopię zapasową bazy danych", + "backup_keep_last_amount": "Ile poprzednich kopii zapasowych przechowywać", + "backup_settings": "Ustawienia kopii zapasowej", + "backup_settings_description": "Zarządzaj ustawieniami kopii zapasowej bazy dnaych", "check_all": "Zaznacz Wszystko", "cleared_jobs": "Usunięto zadania dla: {job}", "config_set_by_file": "Konfiguracja pochodzi z pliku konfiguracyjnego", @@ -43,9 +49,10 @@ "confirm_reprocess_all_faces": "Czy na pewno chcesz ponownie przetworzyć wszystkie twarze? Spowoduje to utratę nazwanych osób.", "confirm_user_password_reset": "Czy na pewno chcesz zresetować hasło użytkownika {user}?", "create_job": "Utwórz zadanie", - "crontab_guru": "Crontab Guru", + "cron_expression": "Wyrażenie Cron", + "cron_expression_description": "Ustaw intwerwał skanowania przy pomocy formatu Cron'a. Po więcej informacji na temat formatu Cron zobacz . Crontab Guru", + "cron_expression_presets": "Predefiniowane wyrażenia Cron'a", "disable_login": "Wyłącz logowanie", - "disabled": "Wyłączone", "duplicate_detection_job_description": "Włącz uczenie maszynowe na zasobie aby wykrywać podobne obrazy. Ta funkcja opiera się na inteligentnym wyszukiwaniu", "exclusion_pattern_description": "Wzory wykluczające pozwalają na ignorowanie plików i folderów podczas skanowania Twojej biblioteki. Są one przydatne na przykład gdy nie chcesz importować zdjęć w formacie RAW.", "external_library_created_at": "Biblioteka zewnętrzna (stworzona dnia {date})", @@ -63,22 +70,15 @@ "image_prefer_wide_gamut": "Preferuj szeroką paletę barw", "image_prefer_wide_gamut_setting_description": "Do wyświetlania miniatur użyj wyświetlacza P3. Dzięki temu lepiej zachowuje się intensywność obrazów o dużej ilości kolorów, ale obrazy mogą wyglądać inaczej na starych urządzeniach ze starą wersją przeglądarki. Obrazy sRGB są zachowywane jako sRGB, aby uniknąć przesunięć kolorów.", "image_preview_description": "Obraz średniej wielkości z wyciętymi metadanymi, używany podczas przeglądania pojedynczego zasobu i do uczenia maszynowego", - "image_preview_format": "Format podglądu", "image_preview_quality_description": "Jakość podglądu od 1 do 100. Wyższa jest lepsza, ale powoduje większe pliki i może zmniejszyć responsywność aplikacji. Ustawienie niskiej wartości może wpłynąć na jakość uczenia maszynowego.", - "image_preview_resolution": "Rozdzielczość podglądu", - "image_preview_resolution_description": "Używane podczas przeglądania pojedynczego zdjęcia i do uczenia maszynowego. Wyższe rozdzielczości pozwalają zachować więcej szczegółów, ale kodowanie zajmuje więcej czasu, powoduje to też większe rozmiary plików i może zmniejszyć czas reakcji aplikacji.", "image_preview_title": "Ustawienia podglądu", "image_quality": "Jakość", - "image_quality_description": "Jakość obrazu od 1 do 100. Wyższe wartości pozwalają uzyskać lepszą jakość ale skutkują większym rozmiarem pliku. Ta opcja wpływa na Podgląd i Miniaturki.", "image_resolution": "Rozdzielczość", "image_resolution_description": "Wyższe rozdzielczości pozwalają zachować więcej szczegółów, ale wymagają dłuższego kodowania, mają większy rozmiar pliku i mogą spowalniać reakcję aplikacji.", "image_settings": "Ustawienia Obrazu", "image_settings_description": "Zarządzaj jakością i rozdzielczością generowanych obrazów", "image_thumbnail_description": "Mała miniatura z wyciętymi metadanymi, używana podczas przeglądania grup zdjęć, takich jak główna oś czasu", - "image_thumbnail_format": "Format miniatury", "image_thumbnail_quality_description": "Jakość miniatur od 1 do 100. Im wyższa, tym lepsza, ale powoduje to większy rozmiar plików i może spowolnić reakcję aplikacji.", - "image_thumbnail_resolution": "Rozdzielczość miniatury", - "image_thumbnail_resolution_description": "Używane podczas przeglądania grup zdjęć (głównej osi czasu, widoku albumu itp.). Wyższe rozdzielczości pozwalają zachować więcej szczegółów, ale wyświetlenie ich zajmuje więcej czasu, powoduje też zwiększenie rozmiaru plików i może zmniejszyć czas reakcji aplikacji.", "image_thumbnail_title": "Ustawienia miniatur", "job_concurrency": "{job} współbieżność", "job_created": "Zadanie utworzone", @@ -89,9 +89,6 @@ "jobs_delayed": "{jobCount, plural, other {# oczekujących}}", "jobs_failed": "{jobCount, plural, other {# nieudane}}", "library_created": "Utworzono bibliotekę: {library}", - "library_cron_expression": "Wyrażenie Cron", - "library_cron_expression_description": "Ustaw interwał skanowania, używając formatu cron. Więcej informacji znajdziesz m.in. Crontab Guru", - "library_cron_expression_presets": "Proponowane wyrażenia Cron", "library_deleted": "Biblioteka usunięta", "library_import_path_description": "Określ folder do załadowania plików. Ten folder, łącznie z podfolderami, zostanie przeskanowany w poszukiwaniu obrazów i filmów.", "library_scanning": "Okresowe Skanowanie", @@ -134,7 +131,7 @@ "machine_learning_smart_search_description": "Szukaj obrazów semantycznie za pomocą CLIP", "machine_learning_smart_search_enabled": "Włącz inteligentne wyszukiwanie", "machine_learning_smart_search_enabled_description": "Jeżeli wyłączone, obrazy nie będą przygotowywane do inteligentnego wyszukiwania.", - "machine_learning_url_description": "URL serwera uczenia maszynowego", + "machine_learning_url_description": "URL serwera uczenia maszynowego. Jeżeli podano więcej niż jeden URL, do każdego serwera będzie wysłane żądanie do tej pory dopóki chociaż jeden nie odpowie, w kolejności od pierwszego do ostatniego.", "manage_concurrency": "Zarządzaj współbieżnością zadań", "manage_log_settings": "Zarządzaj ustawieniami logów", "map_dark_style": "Styl ciemny", @@ -215,7 +212,6 @@ "refreshing_all_libraries": "Wszystkie biblioteki zostaną odświeżone", "registration": "Rejestracja Administratora", "registration_description": "Jesteś pierwszym użytkownikiem aplikacji, więc twoje konto jest administratorem. Możesz zarządzać platformą, w tym dodawać nowych użytkowników.", - "removing_deleted_files": "Niedostępne pliki zostaną usunięte", "repair_all": "Napraw Wszystko", "repair_matched_items": "Powiązano {count, plural, one {# element} few {# elementy} other {# elementów}}", "repaired_items": "Naprawiono {count, plural, one {# element} few {# elementy} other {# elementów}}", @@ -223,12 +219,12 @@ "reset_settings_to_default": "Przywróć ustawienia fabryczne", "reset_settings_to_recent_saved": "Przywróć ustawienia do ostatnio zapisanych", "scanning_library": "Skanowanie biblioteki", - "scanning_library_for_changed_files": "Przeszukaj bibliotekę w poszukiwaniu zmian w plikach", - "scanning_library_for_new_files": "Przeszukaj bibliotekę w poszukiwaniu nowych plików", "search_jobs": "Zadania przeszukiwania...", "send_welcome_email": "Wyślij powitalny e-mail", "server_external_domain_settings": "Domena zewnętrzna", "server_external_domain_settings_description": "Domena dla publicznie udostępnionych linków, wraz z http(s)://", + "server_public_users": "Użytkownicy publiczni", + "server_public_users_description": "Wszyscy użytkownicy (nazwa i adres e-mail) są wymienieni podczas dodawania użytkownika do udostępnionych albumów. Po wyłączeniu lista użytkowników będzie dostępna tylko dla administratorów.", "server_settings": "Ustawienia Serwera", "server_settings_description": "Zarządzaj ustawieniami serwera", "server_welcome_message": "Wiadomość powitalna", @@ -254,6 +250,16 @@ "storage_template_user_label": "{label} to jest etykieta przechowywania użytkownika", "system_settings": "Ustawienia Systemowe", "tag_cleanup_job": "Porządkowanie etykiet", + "template_email_available_tags": "Możesz uzyć tych zmiennych w swoim szablonie: {tags}", + "template_email_if_empty": "Zostaw puste, aby użyć domyślny adres e-mail.", + "template_email_invite_album": "Szablon zaproszenia do albumu", + "template_email_preview": "Podgląd", + "template_email_settings": "Szablony e-mail", + "template_email_settings_description": "Zarządzaj niestandardowymi e-mail powiadomieniami", + "template_email_update_album": "Szablon aktualizacji albumu", + "template_email_welcome": "Szablon powitalnego e-mail", + "template_settings": "Szablony Powiadomień", + "template_settings_description": "Zarządzaj niestandardowymi szablonami powiadomień e-mail.", "theme_custom_css_settings": "Własny CSS", "theme_custom_css_settings_description": "Właśny CSS pozwala na zmianę wyglądu aplikacji Immich.", "theme_settings": "Ustawienia Motywu", @@ -261,7 +267,6 @@ "these_files_matched_by_checksum": "Pliki te są powiązane na podstawie ich sum kontrolnych", "thumbnail_generation_job": "Stwórz Miniaturki", "thumbnail_generation_job_description": "Generuj duże, małe i rozmyte miniatury dla każdego zasobu, a także miniatury dla każdej osoby", - "transcode_policy_description": "", "transcoding_acceleration_api": "API akceleracji", "transcoding_acceleration_api_description": "Interfejs API, używany w celu przyspieszenia transkodowania. W przypadku niepowodzenia zostanie użyte transkodowanie programowe. Format VP9 może, ale nie musi, działać w zależności od sprzętu.", "transcoding_acceleration_nvenc": "NVENC (wymaga NVIDIA GPU)", @@ -313,8 +318,6 @@ "transcoding_threads_description": "Wyższe wartości prowadzą do szybszego kodowania, ale pozostawiają mniej zasobów serwerowi na przetwarzanie innych zadań, gdy jest ono aktywne. Wartość ta nie powinna być większa niż liczba rdzeni procesora. Maksymalizuje wykorzystanie, jeśli jest ustawione na 0.", "transcoding_tone_mapping": "Mapowanie tonów", "transcoding_tone_mapping_description": "Próbuje zachować wygląd filmów HDR po konwersji do SDR. Każdy algorytm dokonuje różnych kompromisów w zakresie koloru, szczegółowości i jasności. Hable zachowuje szczegóły, Mobius kolor, a Reinhard jasność.", - "transcoding_tone_mapping_npl": "Mapowanie tonów NPL", - "transcoding_tone_mapping_npl_description": "Kolory zostaną dostosowane tak, aby wyglądały normalnie w przypadku wyświetlacza o tej jasności. Wbrew intuicji niższe wartości zwiększają jasność wideo i odwrotnie, ponieważ kompensują jasność wyświetlacza. 0 ustawia tę wartość automatycznie.", "transcoding_transcode_policy": "Zasady transkodowania", "transcoding_transcode_policy_description": "Zasady dotyczące transkodowania filmu. Filmy HDR będą zawsze transkodowane (z wyjątkiem sytuacji, gdy transkodowanie jest wyłączone).", "transcoding_two_pass_encoding": "Kodowanie dwuprzebiegowe", @@ -395,7 +398,6 @@ "archive_or_unarchive_photo": "Dodaj lub usuń zasób z archiwum", "archive_size": "Rozmiar archiwum", "archive_size_description": "Podziel pobierane pliki na więcej niż jedno archiwum, jeżeli rozmiar archiwum przekroczy tę wartość w GiB", - "archived": "Zarchiwizowano", "archived_count": "{count, plural, other {Zarchiwizowano #}}", "are_these_the_same_person": "Czy to jedna i ta sama osoba?", "are_you_sure_to_do_this": "Czy aby na pewno chcesz to zrobić?", @@ -416,7 +418,6 @@ "assets_added_to_album_count": "Dodano {count, plural, one {# zasób} few {# zasoby} many {# zasobów} other {# zasobów}} do albumu", "assets_added_to_name_count": "Dodano {count, plural, one {# zasób} few {# zasoby} many {# zasobów} other {# zasobów}} do {hasName, select, true {{name}} other {new album}}", "assets_count": "{count, plural, one {# zasób} few {# zasoby} many {# zasobów} other {# zasobów}}", - "assets_moved_to_trash": "{count, plural, one {# zasób został przeniesiony} few {# zasoby zostały przeniesione} other {# zasobów zostało przeniesione}} do kosza", "assets_moved_to_trash_count": "Przeniesiono {count, plural, one {# zasób} few {# zasoby} many {# zasobów} other {# zasobów}} do kosza", "assets_permanently_deleted_count": "Trwale usunięto {count, plural, one {# zasób} few {# zasoby} many {# zasobów} other {# zasobów}}", "assets_removed_count": "Usunięto {count, plural, one {# zasób} few {# zasoby} many {# zasobów} other {# zasobów}}", @@ -446,10 +447,6 @@ "cannot_merge_people": "Złączenie osób nie powiodło się", "cannot_undo_this_action": "Nie da się tego cofnąć!", "cannot_update_the_description": "Nie można zaktualizować opisu", - "cant_apply_changes": "Nie można zapisać zmian", - "cant_get_faces": "Nie można pobrać twarzy", - "cant_search_people": "Nie można wyszukiwać osób", - "cant_search_places": "Nie można wyszukiwać miejsc", "change_date": "Zmień datę", "change_expiration_time": "Zmień czas ważności", "change_location": "Zmień lokalizację", @@ -481,6 +478,7 @@ "confirm": "Potwierdź", "confirm_admin_password": "Potwierdź Hasło Administratora", "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_password": "Potwierdź hasło", "contain": "Zawiera", "context": "Kontekst", @@ -530,6 +528,7 @@ "delete_key": "Usuń klucz", "delete_library": "Usuń bibliotekę", "delete_link": "Usuń link", + "delete_others": "Usuń inne", "delete_shared_link": "Usuń udostępniony link", "delete_tag": "Usuń etykietę", "delete_tag_confirmation_prompt": "Czy na pewno chcesz usunąć etykietę {tagName}?", @@ -563,13 +562,6 @@ "duplicates": "Duplikaty", "duplicates_description": "Rozstrzygnij każdą grupę, określając, które zasoby, jeśli takie istnieją, są duplikatami", "duration": "Czas trwania", - "durations": { - "days": "{days, plural, one {dzień} other {{days, number} dni}}", - "hours": "{hours, plural, one {godzina} few {{hours, number} godziny} other {{hours, number} godzin}}", - "minutes": "{minutes, plural, one {minuta} few {{minutes, number} minuty} other {{minutes, number} minut}}", - "months": "{months, plural, one {miesiąc} few {{months, number} miesiące} other {{months, number} miesięcy}}", - "years": "{years, plural, one {rok} few {{years, number} lata} other {{years, number} lat}}" - }, "edit": "Edytuj", "edit_album": "Edytuj album", "edit_avatar": "Edytuj awatar", @@ -594,8 +586,6 @@ "editor_crop_tool_h2_aspect_ratios": "Proporcje obrazu", "editor_crop_tool_h2_rotation": "Obrót", "email": "E-mail", - "empty": "", - "empty_album": "Pusty Album", "empty_trash": "Opróżnij kosz", "empty_trash_confirmation": "Czy na pewno chcesz opróżnić kosz? Spowoduje to trwałe usunięcie wszystkich zasobów znajdujących się w koszu z Immich.\nNie można cofnąć tej operacji!", "enable": "Włącz", @@ -629,6 +619,7 @@ "failed_to_create_shared_link": "Nie udało się utworzyć udostępnionego linku", "failed_to_edit_shared_link": "Nie udało się edytować udostępnionego linku", "failed_to_get_people": "Nie udało się pozyskać osób", + "failed_to_keep_this_delete_others": "Nie udało się zachować tego zasobu i usunąć innych zasobów", "failed_to_load_asset": "Nie udało się załadować zasobu", "failed_to_load_assets": "Nie udało się załadować zasobów", "failed_to_load_people": "Błąd pobierania ludzi", @@ -656,8 +647,6 @@ "unable_to_change_location": "Nie można zmienić lokalizacji", "unable_to_change_password": "Nie można zmienić hasła", "unable_to_change_visibility": "Nie można zmienić widoczności dla {count, plural, one {# osoby} other {# osób}}", - "unable_to_check_item": "", - "unable_to_check_items": "", "unable_to_complete_oauth_login": "Nie można ukończyć logowania przy użyciu OAuth", "unable_to_connect": "Nie można się połączyć", "unable_to_connect_to_server": "Nie można się połączyć z serwerem", @@ -698,12 +687,10 @@ "unable_to_remove_album_users": "Usunięcie użytkowników z albumu nie powiodło się", "unable_to_remove_api_key": "Usunięcie Klucza API nie powiodło się", "unable_to_remove_assets_from_shared_link": "Nie można usunąć zasobów z udostępnionego linku", - "unable_to_remove_comment": "", "unable_to_remove_deleted_assets": "Usunięcie niedostępnych plików nie powiodło się", "unable_to_remove_library": "Usunięcie biblioteki nie powiodło się", "unable_to_remove_partner": "Nie można usunąć partnerów", "unable_to_remove_reaction": "Usunięcie reakcji nie powiodło się", - "unable_to_remove_user": "", "unable_to_repair_items": "Naprawianie elementów nie powiodło się", "unable_to_reset_password": "Nie można resetować hasła", "unable_to_resolve_duplicate": "Usuwanie duplikatów nie powiodło się", @@ -733,10 +720,6 @@ "unable_to_update_user": "Zmiana użytkownika nie powiodła się", "unable_to_upload_file": "Nie można przesłać pliku" }, - "every_day_at_onepm": "", - "every_night_at_midnight": "", - "every_night_at_twoam": "", - "every_six_hours": "", "exif": "Metadane EXIF", "exit_slideshow": "Zamknij Pokaz Slajdów", "expand_all": "Rozwiń wszystko", @@ -751,33 +734,28 @@ "external": "Zewnętrzny", "external_libraries": "Biblioteki Zewnętrzne", "face_unassigned": "Nieprzypisany", - "failed_to_get_people": "Pobieranie osób nie powiodło się", + "failed_to_load_assets": "Nie udało się załadować zasobów", "favorite": "Ulubione", "favorite_or_unfavorite_photo": "Dodaj lub usuń z ulubionych", "favorites": "Ulubione", - "feature": "", "feature_photo_updated": "Pomyślnie zmieniono główne zdjęcie", - "featurecollection": "", "features": "Funkcje", "features_setting_description": "Zarządzaj funkcjami aplikacji", "file_name": "Nazwa pliku", "file_name_or_extension": "Nazwie lub rozszerzeniu pliku", "filename": "Nazwa pliku", - "files": "", "filetype": "Typ pliku", "filter_people": "Szukaj osoby", "find_them_fast": "Wyszukuj szybciej przypisując nazwę", "fix_incorrect_match": "Napraw nieprawidłowe dopasowanie", "folders": "Foldery", "folders_feature_description": "Przeglądanie zdjęć i filmów w widoku folderów", - "force_re-scan_library_files": "Wymuś ponowne przeskanowanie wszystkich plików biblioteki", "forward": "Do przodu", "general": "Ogólne", "get_help": "Pomoc", "getting_started": "Pierwsze kroki", "go_back": "Wstecz", "go_to_search": "Przejdź do wyszukiwania", - "go_to_share_page": "Przejdź na udostępnioną stronę", "group_albums_by": "Grupuj albumy...", "group_no": "Brak grupowania", "group_owner": "Grupuj według właściciela", @@ -803,10 +781,6 @@ "image_alt_text_date_place_2_people": "{isVideo, select, true {Wideo} other {Zdjęcie}} zrobione w {city}, {country} z {person1} i {person2} dnia {date}", "image_alt_text_date_place_3_people": "{isVideo, select, true {Wideo} other {Zdjęcie}} zrobione w {city}, {country} z {person1}, {person2} i {person3} dnia {date}", "image_alt_text_date_place_4_or_more_people": "{isVideo, select, true {Wideo} other {Zdjęcie}} zrobione w {city}, {country} z {person1}, {person2} i {additionalCount, number} innymi dnia {date}", - "image_alt_text_people": "{count, plural, =1 {z {person1}} =2 {z {person1} i {person2}} =3 {z {person1}, {person2} i {person3}} other {z {person1}, {person2} i {others, number} innymi}}", - "image_alt_text_place": "w {city}, {country}", - "image_taken": "{isVideo, select, true {nagrany film} other {zrobione zdjęcie}}", - "img": "", "immich_logo": "Logo Immich", "immich_web_interface": "Interfejs internetowy Immich", "import_from_json": "Wczytaj z JSON", @@ -827,10 +801,11 @@ "invite_people": "Zaproś Osoby", "invite_to_album": "Zaproś do albumu", "items_count": "{count, plural, one {# element} other {# elementy}}", - "job_settings_description": "", "jobs": "Zadania", "keep": "Zachowaj", "keep_all": "Zachowaj wszystko", + "keep_this_delete_others": "Zachowaj to, usuń inne", + "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", "language_setting_description": "Wybierz swój preferowany język", @@ -946,7 +921,6 @@ "onboarding_welcome_user": "Witaj, {user}", "online": "Połączony", "only_favorites": "Tylko ulubione", - "only_refreshes_modified_files": "Odświeża tylko zmodyfikowane pliki", "open_in_map_view": "Otwórz w widoku mapy", "open_in_openstreetmap": "Otwórz w OpenStreetMap", "open_the_search_filters": "Otwórz filtry wyszukiwania", @@ -984,7 +958,6 @@ "people_edits_count": "Edytowano {count, plural, one {# osoba} few {# osoby} many {# osób} other {# osób}}", "people_feature_description": "Przeglądanie zdjęć i filmów pogrupowanych według osób", "people_sidebar_description": "Pokazuj link do Osób w panelu bocznym", - "perform_library_tasks": "", "permanent_deletion_warning": "Ostrzeżenie o trwałym usunięciu", "permanent_deletion_warning_setting_description": "Pokaż ostrzeżenie przy trwałym usuwaniu zasobów", "permanently_delete": "Usuń trwale", @@ -1006,7 +979,6 @@ "play_memories": "Odtwórz wspomnienia", "play_motion_photo": "Odtwórz Ruchome Zdjęcie", "play_or_pause_video": "Odtwórz lub wstrzymaj wideo", - "point": "", "port": "Port", "preset": "Ustawienie", "preview": "Podgląd", @@ -1051,12 +1023,10 @@ "purchase_server_description_2": "Status wspierającego", "purchase_server_title": "Serwer", "purchase_settings_server_activated": "Klucz produktu serwera jest zarządzany przez administratora", - "range": "", "rating": "Ocena gwiazdkowa", "rating_clear": "Wyczyść oceną", "rating_count": "{count, plural, one {# gwiazdka} other {# gwiazdek}}", "rating_description": "Wyświetl ocenę z EXIF w panelu informacji", - "raw": "", "reaction_options": "Opcje reakcji", "read_changelog": "Zobacz Zmiany", "reassign": "Przypisz ponownie", @@ -1064,6 +1034,7 @@ "reassigned_assets_to_new_person": "Przypisano ponownie {count, plural, one {# zasób} other {# zasobów}} do nowej osoby", "reassing_hint": "Przypisz wybrane zasoby do istniejącej osoby", "recent": "Ostatnie", + "recent-albums": "Ostatnie albumy", "recent_searches": "Ostatnie wyszukiwania", "refresh": "Odśwież", "refresh_encoded_videos": "Odśwież enkodowane wideo", @@ -1085,6 +1056,7 @@ "remove_from_album": "Usuń z albumu", "remove_from_favorites": "Usuń z ulubionych", "remove_from_shared_link": "Usuń z udostępnionego linku", + "remove_url": "Usuń URL", "remove_user": "Usuń użytkownika", "removed_api_key": "Usunięto Klucz API: {name}", "removed_from_archive": "Usunięto z archiwum", @@ -1101,7 +1073,6 @@ "reset": "Reset", "reset_password": "Resetuj hasło", "reset_people_visibility": "Zresetuj widoczność osób", - "reset_settings_to_default": "", "reset_to_default": "Przywróć ustawienia domyślne", "resolve_duplicates": "Rozwiąż problemy z duplikatami", "resolved_all_duplicates": "Rozwiązano wszystkie duplikaty", @@ -1121,9 +1092,7 @@ "saved_settings": "Zapisane ustawienia", "say_something": "Powiedz coś", "scan_all_libraries": "Skanuj wszystkie biblioteki", - "scan_all_library_files": "Przeskanuj ponownie wszystkie biblioteki", "scan_library": "Skanuj", - "scan_new_library_files": "Skanuj nowe pliki biblioteki", "scan_settings": "Ustawienia Skanowania", "scanning_for_album": "Skanuję album...", "search": "Szukaj", @@ -1166,7 +1135,6 @@ "selected_count": "{count, plural, other {# wybrane}}", "send_message": "Wyślij wiadomość", "send_welcome_email": "Wyślij e-mail powitalny", - "server": "Serwer", "server_offline": "Serwer Offline", "server_online": "Serwer Online", "server_stats": "Statystyki serwera", @@ -1271,6 +1239,7 @@ "they_will_be_merged_together": "Zostaną one ze sobą połączone", "third_party_resources": "Zasoby stron trzecich", "time_based_memories": "Wspomnienia oparte na czasie", + "timeline": "Oś czasu", "timezone": "Strefa czasowa", "to_archive": "Archiwum", "to_change_password": "Zmień hasło", @@ -1280,7 +1249,7 @@ "to_trash": "Kosz", "toggle_settings": "Przełącz ustawienia", "toggle_theme": "Przełącz ciemny motyw", - "toggle_visibility": "Zmień widoczność", + "total": "Całkowity", "total_usage": "Całkowite wykorzystanie", "trash": "Kosz", "trash_all": "Usuń wszystko", @@ -1290,12 +1259,10 @@ "trashed_items_will_be_permanently_deleted_after": "Wyrzucone zasoby zostaną trwale usunięte po {days, plural, one {jednym dniu} other {{days, number} dniach}}.", "type": "Typ", "unarchive": "Cofnij archiwizację", - "unarchived": "", "unarchived_count": "{count, plural, other {Niezarchiwizowane #}}", "unfavorite": "Usuń z ulubionych", "unhide_person": "Przywróć osobę", "unknown": "Nieznany", - "unknown_album": "Nieznany album", "unknown_year": "Rok nieznany", "unlimited": "Nieograniczony", "unlink_motion_video": "Rozłącz ruchome wideo", @@ -1332,6 +1299,8 @@ "user_purchase_settings_description": "Zarządzaj swoim zakupem", "user_role_set": "Ustaw {user} jako {role}", "user_usage_detail": "Szczegóły używania przez użytkownika", + "user_usage_stats": "Statystyki użytkowania konta", + "user_usage_stats_description": "Wyświetl statystyki użytkowania konta", "username": "Nazwa użytkownika", "users": "Użytkownicy", "utilities": "Narzędzia", @@ -1339,7 +1308,7 @@ "variables": "Zmienne", "version": "Wersja", "version_announcement_closing": "Twój przyjaciel Aleks", - "version_announcement_message": "Witaj przyjacielu, dostępna jest nowa wersja aplikacji. Poświęć trochę czasu na zapoznanie się z informacjami o wydaniu i upewnij się, że pliki docker-compose.yml i .env konfiguracja jest aktualna, aby zapobiec błędnym konfiguracjom, zwłaszcza jeśli używasz WatchTower lub dowolnego mechanizmu, który obsługuje automatyczne aktualizowanie aplikacji.", + "version_announcement_message": "Witaj! Dostępna jest nowa wersja Immich. Poświęć trochę czasu na zapoznanie się z informacjami o wydaniu, aby upewnić się, że twoja konfiguracja jest aktualna, aby uniknąć błędów, szczególnie jeśli używasz WatchTower lub jakiegokolwiek mechanizmu odpowiedzialnego za automatyczne aktualizowanie Immich.", "version_history": "Historia wersji", "version_history_item": "Zainstalowano {version} w {date}", "video": "Wideo", @@ -1353,10 +1322,10 @@ "view_all_users": "Pokaż wszystkich użytkowników", "view_in_timeline": "Pokaż na osi czasu", "view_links": "Pokaż łącza", + "view_name": "Widok", "view_next_asset": "Wyświetl następny zasób", "view_previous_asset": "Wyświetl poprzedni zasób", "view_stack": "Zobacz Ułożenie", - "viewer": "Oglądający", "visibility_changed": "Zmieniono widoczność dla {count, plural, one {# osoba} other {# osoby}}", "waiting": "Oczekiwanie", "warning": "Ostrzeżenie", diff --git a/i18n/pt.json b/i18n/pt.json index dda003243e4b6..d34e0424bc897 100644 --- a/i18n/pt.json +++ b/i18n/pt.json @@ -23,6 +23,7 @@ "add_to": "Adicionar a...", "add_to_album": "Adicionar ao álbum", "add_to_shared_album": "Adicionar ao álbum partilhado", + "add_url": "Adicionar URL", "added_to_archive": "Adicionado ao arquivo", "added_to_favorites": "Adicionado aos favoritos", "added_to_favorites_count": "{count, plural, one {{count, number} adicionado aos favoritos} other {{count, number} adicionados aos favoritos}}", @@ -34,6 +35,11 @@ "authentication_settings_disable_all": "Tem a certeza que deseja desativar todos os métodos de início de sessão? O início de sessão será completamente desativado.", "authentication_settings_reenable": "Para reativar, use um Comando de servidor.", "background_task_job": "Tarefas em segundo plano", + "backup_database": "Cópia de Segurança da Base de Dados", + "backup_database_enable_description": "Ativar cópias de segurança da base de dados", + "backup_keep_last_amount": "Quantidade de cópias de segurança anteriores a manter", + "backup_settings": "Definições de Cópia de Segurança", + "backup_settings_description": "Gerir definições de cópia de segurança da base de dados", "check_all": "Selecionar Tudo", "cleared_jobs": "Eliminadas as tarefas de: {job}", "config_set_by_file": "A configuração está atualmente definida por um ficheiro de configuração", @@ -43,9 +49,10 @@ "confirm_reprocess_all_faces": "Tem a certeza de que deseja reprocessar todos os rostos? Isto também limpará os nomes das pessoas.", "confirm_user_password_reset": "Tem a certeza de que deseja redefinir a palavra-passe de {user}?", "create_job": "Criar tarefa", - "crontab_guru": "Guru do Crontab", + "cron_expression": "Expressão Cron", + "cron_expression_description": "Definir o intervalo de análise utilizando o formato Cron. Para mais informações, por favor veja o Crontab Guru", + "cron_expression_presets": "Predefinições das expressões Cron", "disable_login": "Desativar inicio de sessão", - "disabled": "", "duplicate_detection_job_description": "Executa a aprendizagem de máquina em ficheiros para detetar imagens semelhantes. Depende da Pesquisa Inteligente", "exclusion_pattern_description": "Os padrões de exclusão permitem ignorar ficheiros e pastas ao analisar a sua biblioteca. Isto é útil se tiver pastas que contenham ficheiros que não deseja importar, como ficheiros RAW.", "external_library_created_at": "Biblioteca externa (criada em {date})", @@ -63,22 +70,15 @@ "image_prefer_wide_gamut": "Prefira ampla gama", "image_prefer_wide_gamut_setting_description": "Utilizar Display P3 para miniaturas. Isso preserva melhor a vibrância das imagens com espaços de cores amplos, mas as imagens podem aparecer de maneira diferente em dispositivos antigos com uma versão antiga do navegador. As imagens sRGB são mantidas como sRGB para evitar mudanças de cores.", "image_preview_description": "Imagem de tamanho médio sem metadados, utilizada ao visualizar um único ficheiro e pela aprendizagem de máquina", - "image_preview_format": "Formato de visualização", "image_preview_quality_description": "Qualidade de pré-visualização de 1 a 100. Maior é melhor, mas produz ficheiros maiores e pode reduzir a capacidade de resposta da aplicação. Definir um valor demasiado baixo pode afetar a qualidade da aprendizagem de máquina.", - "image_preview_resolution": "Resolução de visualização", - "image_preview_resolution_description": "Usado ao visualizar uma única foto e para aprendizagem de máquina. Resoluções mais altas podem preservar mais detalhes, mas demoram mais para codificar, têm tamanhos de ficheiro maiores e podem reduzir a capacidade de resposta da aplicação.", "image_preview_title": "Definições de Pré-visualização", "image_quality": "Qualidade", - "image_quality_description": "Qualidade de imagem de 1 a 100. Quanto maior, melhor para a qualidade, mas produz ficheiros maiores. Esta definição afeta as imagens de visualização e miniatura.", "image_resolution": "Resolução", "image_resolution_description": "Resoluções mais altas podem ajudar a preservar mais detalhes mas demoram mais a codificar, têm tamanhos de ficheiro maiores e podem reduzir a capacidade de resposta da aplicação.", "image_settings": "Definições de imagem", "image_settings_description": "Gerir a qualidade e resolução das imagens geradas", "image_thumbnail_description": "Miniatura de tamanho pequena e sem metadados, utilizada ao visualizar grupos de fotos como, por exemplo, na linha de tempo principal", - "image_thumbnail_format": "Formato de miniatura", "image_thumbnail_quality_description": "Qualidade das miniaturas de 1 a 100. Maior é melhor, mas produz tamanhos de ficheiro maiores e podem reduzir a capacidade de resposta da aplicação.", - "image_thumbnail_resolution": "Resolução de miniatura", - "image_thumbnail_resolution_description": "Utilizado ao visualizar grupos de fotos (linha do tempo principal, visualização de álbum, etc.). Resoluções mais altas podem preservar mais detalhes, mas demoram mais para codificar, têm tamanhos de ficheiro maiores e podem reduzir a capacidade de resposta da aplicação.", "image_thumbnail_title": "Definições de Miniaturas", "job_concurrency": "{job} em simultâneo", "job_created": "Tarefa criada", @@ -89,9 +89,6 @@ "jobs_delayed": "{jobCount, plural, one {# adiado} other {# adiados}}", "jobs_failed": "{jobCount, plural, one {# falhou} other {# falharam}}", "library_created": "Criada biblioteca: {library}", - "library_cron_expression": "Expressão Cron", - "library_cron_expression_description": "Defina o intervalo de procura utilizando o formato cron. Para mais informações consulte Guru Crontab", - "library_cron_expression_presets": "Predefinições de expressão Cron", "library_deleted": "Biblioteca eliminada", "library_import_path_description": "Especifique uma pasta para importar. Esta pasta, incluindo sub-pastas, será analisada por imagens e vídeos.", "library_scanning": "Análise periódica", @@ -134,7 +131,7 @@ "machine_learning_smart_search_description": "Pesquise imagens semanticamente utilizando embeddings CLIP", "machine_learning_smart_search_enabled": "Ativar a Pesquisa Inteligente", "machine_learning_smart_search_enabled_description": "Se desativado, as imagens não serão codificadas para Pesquisa Inteligente.", - "machine_learning_url_description": "URL do servidor de aprendizagem de máquina", + "machine_learning_url_description": "A URL do servidor de aprendizagem de máquina. Se for fornecido mais do que um URL, cada servidor será testado, um a um, até um deles responder com sucesso, por ordem do primeiro ao último.", "manage_concurrency": "Gerir simultaneidade", "manage_log_settings": "Gerir definições de registo", "map_dark_style": "Tema Escuro", @@ -215,7 +212,6 @@ "refreshing_all_libraries": "A atualizar todas as bibliotecas", "registration": "Registo de Administrador", "registration_description": "Como é o primeiro utilizador no sistema, será marcado como administrador, e será responsável pelas tarefas administrativas, sendo que utilizadores adicionais serão criados por si.", - "removing_deleted_files": "Removendo arquivos offline", "repair_all": "Reparar tudo", "repair_matched_items": "{count, plural, one {Encontrado # item} other {Encontrados # itens}}", "repaired_items": "{count, plural, one {Reparado # item} other {Reparados # itens}}", @@ -223,12 +219,12 @@ "reset_settings_to_default": "Redefinir as definições para o padrão", "reset_settings_to_recent_saved": "Redefinir as definições para as guardadas mais recentemente", "scanning_library": "A analisar biblioteca", - "scanning_library_for_changed_files": "A analisar a biblioteca por ficheiros alterados", - "scanning_library_for_new_files": "A analisar a biblioteca por ficheiros novos", "search_jobs": "Pesquisar tarefas...", "send_welcome_email": "Enviar e-mail de boas-vindas", "server_external_domain_settings": "Domínio externo", "server_external_domain_settings_description": "Domínio para links públicos partilhados, incluindo http(s)://", + "server_public_users": "Utilizadores Públicos", + "server_public_users_description": "Todos os utilizadores (nome e e-mail) serão listados quando adicionar um utilizador a álbuns partilhados. Quando desativado, a lista de utilizadores só será visível a administradores.", "server_settings": "Definições do Servidor", "server_settings_description": "Gerir definições do servidor", "server_welcome_message": "Mensagem de boas-vindas", @@ -254,6 +250,16 @@ "storage_template_user_label": "{label} é o Rótulo do Armazenamento do utilizador", "system_settings": "Definições de Sistema", "tag_cleanup_job": "Limpeza de etiquetas", + "template_email_available_tags": "Pode usar as seguintes variáveis no modelo: {tags}", + "template_email_if_empty": "Se o modelo estiver em branco, o modelo de e-mail padrão será utilizado.", + "template_email_invite_album": "Modelo do e-mail de convite para álbum", + "template_email_preview": "Pré-visualizar", + "template_email_settings": "Modelos de e-mail", + "template_email_settings_description": "Gerir modelos personalizados de e-mail de notificação", + "template_email_update_album": "Modelo do e-mail de atualização do álbum", + "template_email_welcome": "Modelos do email de boas vindas", + "template_settings": "Modelos de notificação", + "template_settings_description": "Gerir modelos personalizados para notificações.", "theme_custom_css_settings": "CSS Personalizado", "theme_custom_css_settings_description": "Folhas de estilo em cascata (CSS) permitem que o design do Immich seja personalizado.", "theme_settings": "Definições de Tema", @@ -261,7 +267,6 @@ "these_files_matched_by_checksum": "Estes ficheiros são correspondidos pelas suas somas de verificação", "thumbnail_generation_job": "Gerar miniaturas", "thumbnail_generation_job_description": "Gera miniaturas grandes, pequenas e desfocadas para cada ficheiro, bem como miniaturas para cada pessoa", - "transcode_policy_description": "", "transcoding_acceleration_api": "API de aceleração", "transcoding_acceleration_api_description": "A API que irá interagir com o seu dispositivo para acelerar a transcodificação. Esta definição é a 'melhor opção': ela voltará à transcodificação de software em caso de falha. O VP9 pode não funcionar dependendo do seu hardware.", "transcoding_acceleration_nvenc": "NVENC (requer GPU NVIDIA)", @@ -313,8 +318,6 @@ "transcoding_threads_description": "Valores mais altos levam a uma codificação mais rápida, mas deixam menos espaço para o servidor processar outras tarefas enquanto estiver ativo. Este valor não deve ser superior ao número de núcleos do CPU. Maximiza a utilização se definido como 0.", "transcoding_tone_mapping": "Mapeamento de tons", "transcoding_tone_mapping_description": "Tenta preservar a aparência dos vídeos HDR quando convertidos para SDR. Cada algoritmo faz compensações diferentes em termos de cor, detalhes e brilho. Hable preserva os detalhes, Mobius preserva as cores e Reinhard preserva o brilho.", - "transcoding_tone_mapping_npl": "NPL de mapeamento de tons", - "transcoding_tone_mapping_npl_description": "As cores serão ajustadas para parecerem normais para uma exibição com esse brilho. Contra-intuitivamente, valores mais baixos aumentam o brilho do vídeo e vice-versa, uma vez que compensam o brilho do ecrã. 0 define esse valor automaticamente.", "transcoding_transcode_policy": "Política de transcodificação", "transcoding_transcode_policy_description": "Política para quando um vídeo deve ser transcodificado. Os vídeos HDR serão sempre transcodificados (exceto se a transcodificação estiver desativada).", "transcoding_two_pass_encoding": "Codificação em duas passagens", @@ -395,7 +398,6 @@ "archive_or_unarchive_photo": "Arquivar ou desarquivar foto", "archive_size": "Tamanho do arquivo", "archive_size_description": "Configure o tamanho do arquivo para transferências (em GiB)", - "archived": "Arquivado", "archived_count": "{count, plural, one {#Arquivado # item} other {Arquivados # itens}}", "are_these_the_same_person": "Estas pessoas são a mesma pessoa?", "are_you_sure_to_do_this": "Tem a certeza de que quer fazer isto?", @@ -416,7 +418,6 @@ "assets_added_to_album_count": "{count, plural, one {# ficheiro adicionado} other {# ficheiros adicionados}} ao álbum", "assets_added_to_name_count": "{count, plural, one {# ficheiro adicionado} other {# ficheiros adicionados}} a {hasName, select, true {{name}} other {novo álbum}}", "assets_count": "{count, plural, one {# ficheiro} other {# ficheiros}}", - "assets_moved_to_trash": "{count, plural, one {# ativo enviado} other {# ativos enviados}} para a lixeira", "assets_moved_to_trash_count": "{count, plural, one {# ficheiro movido} other {# ficheiros movidos}} para a reciclagem", "assets_permanently_deleted_count": "{count, plural, one {# ficheiro} other {# ficheiros}} eliminados permanentemente", "assets_removed_count": "{count, plural, one {# ficheiro eliminado} other {# ficheiros eliminados}}", @@ -446,10 +447,6 @@ "cannot_merge_people": "Não foi possível unir pessoas", "cannot_undo_this_action": "Não é possível anular esta ação!", "cannot_update_the_description": "Não foi possível atualizar a descrição", - "cant_apply_changes": "Não é possível aplicar alterações", - "cant_get_faces": "Não foi possível obter faces", - "cant_search_people": "Não foi possível pesquisar pessoas", - "cant_search_places": "Não foi possível pesquisar lugares", "change_date": "Alterar data", "change_expiration_time": "Alterar o prazo de validade", "change_location": "Alterar localização", @@ -481,6 +478,7 @@ "confirm": "Confirmar", "confirm_admin_password": "Confirmar palavra-passe de administrador", "confirm_delete_shared_link": "Tem a certeza de que deseja eliminar este link partilhado?", + "confirm_keep_this_delete_others": "Todos os outros ficheiros na pilha serão eliminados, exceto este ficheiro. Tem a certeza de que deseja continuar?", "confirm_password": "Confirmar a palavra-passe", "contain": "Ajustar", "context": "Contexto", @@ -530,6 +528,7 @@ "delete_key": "Eliminar chave", "delete_library": "Eliminar Biblioteca", "delete_link": "Eliminar link", + "delete_others": "Excluir outros", "delete_shared_link": "Eliminar link de partilha", "delete_tag": "Eliminar etiqueta", "delete_tag_confirmation_prompt": "Tem a certeza de que pretende eliminar a etiqueta {tagName} ?", @@ -563,13 +562,6 @@ "duplicates": "Itens duplicados", "duplicates_description": "Marque cada grupo indicando quais ficheiros, se algum, são duplicados", "duration": "Duração", - "durations": { - "days": "", - "hours": "", - "minutes": "", - "months": "", - "years": "" - }, "edit": "Editar", "edit_album": "Editar álbum", "edit_avatar": "Editar imagem de perfil", @@ -594,8 +586,6 @@ "editor_crop_tool_h2_aspect_ratios": "Relação de aspeto", "editor_crop_tool_h2_rotation": "Rotação", "email": "E-mail", - "empty": "", - "empty_album": "", "empty_trash": "Esvaziar reciclagem", "empty_trash_confirmation": "Tem a certeza de que deseja esvaziar a reciclagem? Isto removerá todos os ficheiros da reciclagem do Immich permanentemente.\nNão é possível anular esta ação!", "enable": "Ativar", @@ -629,6 +619,7 @@ "failed_to_create_shared_link": "Não foi possível criar o link partilhado", "failed_to_edit_shared_link": "Não foi possível editar o link partilhado", "failed_to_get_people": "Não foi possível obter pessoas", + "failed_to_keep_this_delete_others": "Ocorreu um erro ao manter este ficheiro e eliminar os outros", "failed_to_load_asset": "Não foi possível ler o ficheiro", "failed_to_load_assets": "Não foi possível ler ficheiros", "failed_to_load_people": "Não foi possível carregar pessoas", @@ -656,8 +647,6 @@ "unable_to_change_location": "Não foi possível alterar a localização", "unable_to_change_password": "Não foi possível alterar a palavra-passe", "unable_to_change_visibility": "Não é possível alterar a visibilidade de {count, plural, one {# pessoa} other {# pessoas}}", - "unable_to_check_item": "", - "unable_to_check_items": "", "unable_to_complete_oauth_login": "Não foi possível completar o início de sessão com OAuth", "unable_to_connect": "Não é possível ligar", "unable_to_connect_to_server": "Não foi possível ligar ao servidor", @@ -698,12 +687,10 @@ "unable_to_remove_album_users": "Não foi possível remover utilizador do álbum", "unable_to_remove_api_key": "Não foi possível remover a Chave de API", "unable_to_remove_assets_from_shared_link": "Não foi possível remover os ficheiros do link partilhado", - "unable_to_remove_comment": "", "unable_to_remove_deleted_assets": "Não foi possível remover ficheiros indisponíveis", "unable_to_remove_library": "Não foi possível remover a biblioteca", "unable_to_remove_partner": "Não foi possível remover parceiro", "unable_to_remove_reaction": "Não foi possível remover a reação", - "unable_to_remove_user": "", "unable_to_repair_items": "Não foi possível reparar os itens", "unable_to_reset_password": "Não foi possível redefinir a palavra-passe", "unable_to_resolve_duplicate": "Não foi possível resolver as duplicidades", @@ -733,10 +720,6 @@ "unable_to_update_user": "Não foi possível atualizar o utilizador", "unable_to_upload_file": "Não foi possível carregar o ficheiro" }, - "every_day_at_onepm": "", - "every_night_at_midnight": "", - "every_night_at_twoam": "", - "every_six_hours": "", "exif": "Exif", "exit_slideshow": "Sair da apresentação", "expand_all": "Expandir tudo", @@ -751,33 +734,28 @@ "external": "Externo", "external_libraries": "Bibliotecas externas", "face_unassigned": "Sem atribuição", - "failed_to_get_people": "Falha ao carregar as pessoas", + "failed_to_load_assets": "Falha ao carregar ficheiros", "favorite": "Favorito", "favorite_or_unfavorite_photo": "Marcar ou desmarcar a foto como favorita", "favorites": "Favoritos", - "feature": "", "feature_photo_updated": "Foto principal atualizada", - "featurecollection": "", "features": "Funcionalidades", "features_setting_description": "Configurar as funcionalidades da aplicação", "file_name": "Nome do ficheiro", "file_name_or_extension": "Nome do ficheiro ou extensão", "filename": "Nome do ficheiro", - "files": "", "filetype": "Tipo de ficheiro", "filter_people": "Filtrar pessoas", "find_them_fast": "Encontre-as mais rapidamente pelo nome numa pesquisa", "fix_incorrect_match": "Corrigir correspondência incorreta", "folders": "Pastas", "folders_feature_description": "Navegar na vista de pastas por fotos e vídeos no sistema de ficheiros", - "force_re-scan_library_files": "Forçar uma nova análise de todos os ficheiros da biblioteca", "forward": "Para a frente", "general": "Geral", "get_help": "Obter Ajuda", "getting_started": "Primeiros Passos", "go_back": "Regressar", "go_to_search": "Ir para a pesquisa", - "go_to_share_page": "Ir para a página de compartilhamento", "group_albums_by": "Agrupar álbuns por...", "group_no": "Sem agrupamento", "group_owner": "Agrupar por dono", @@ -803,7 +781,6 @@ "image_alt_text_date_place_2_people": "{isVideo, select, true {Vídeo gravado} other {Foto tirada}} em {city}, {country} com {person1} e {person2} em {date}", "image_alt_text_date_place_3_people": "{isVideo, select, true {Vídeo gravado} other {Foto tirada}} em {city}, {country} com {person1}, {person2}, e {person3} em {date}", "image_alt_text_date_place_4_or_more_people": "{isVideo, select, true {Vídeo gravado} other {Foto tirada}} em {city}, {country} com {person1}, {person2}, e outras {additionalCount, number} pessoas em {date}", - "img": "", "immich_logo": "Logotipo do Immich", "immich_web_interface": "Interface Web do Immich", "import_from_json": "Importar a partir de JSON", @@ -824,10 +801,11 @@ "invite_people": "Convidar Pessoas", "invite_to_album": "Convidar para o álbum", "items_count": "{count, plural, one {item #} other {itens #}}", - "job_settings_description": "", "jobs": "Tarefas", "keep": "Manter", "keep_all": "Manter Todos", + "keep_this_delete_others": "Manter este ficheiro, eliminar os outros", + "kept_this_deleted_others": "Foi mantido ficheiro e {count, plural, one {eliminado # outro} other {eliminados # outros}}", "keyboard_shortcuts": "Atalhos do teclado", "language": "Idioma", "language_setting_description": "Selecione o seu Idioma preferido", @@ -943,7 +921,6 @@ "onboarding_welcome_user": "Bem-vindo(a), {user}", "online": "Online", "only_favorites": "Apenas favoritos", - "only_refreshes_modified_files": "Apenas recarrega ficheiros modificados", "open_in_map_view": "Abrir na visualização de mapa", "open_in_openstreetmap": "Abrir no OpenStreetMap", "open_the_search_filters": "Abrir os filtros de pesquisa", @@ -981,14 +958,12 @@ "people_edits_count": "{count, plural, one {# pessoa editada} other {# pessoas editadas}}", "people_feature_description": "Navegar por fotos e vídeos agrupados por pessoas", "people_sidebar_description": "Exibir o link Pessoas na barra lateral", - "perform_library_tasks": "", "permanent_deletion_warning": "Aviso de eliminação permanente", "permanent_deletion_warning_setting_description": "Exibir um aviso ao eliminar ficheiros de forma permanente", "permanently_delete": "Eliminar permanentemente", "permanently_delete_assets_count": "Eliminar permanentemente {count, plural, one {ficheiro} other {ficheiros}}", "permanently_delete_assets_prompt": "Tem a certeza de que deseja eliminar permanentemente {count, plural, one {este ficheiro?} other {estes # ficheiros?}} Esta ação também removerá {count, plural, one {isto do álbum} other {isto dos álbuns}}.", "permanently_deleted_asset": "Ficheiro eliminado permanentemente", - "permanently_deleted_assets": "{count, plural, one {# ativo deletado} other {# ativos deletados}} permanentemente", "permanently_deleted_assets_count": "{count, plural, one {# Ficheiro eliminado} other {# Ficheiros eliminados}} permanentemente", "person": "Pessoa", "person_hidden": "{name}{hidden, select, true { (oculto)} other {}}", @@ -1004,7 +979,6 @@ "play_memories": "Reproduzir memórias", "play_motion_photo": "Reproduzir foto em movimento", "play_or_pause_video": "Reproduzir ou Pausar vídeo", - "point": "", "port": "Porta", "preset": "Predefinição", "preview": "Pré-visualizar", @@ -1049,12 +1023,10 @@ "purchase_server_description_2": "Status de apoiante", "purchase_server_title": "Servidor", "purchase_settings_server_activated": "A chave de produto do servidor é gerida pelo administrador", - "range": "", "rating": "Classificação por estrelas", "rating_clear": "Limpar classificação", "rating_count": "{count, plural, one {# estrela} other {# estrelas}}", "rating_description": "Mostrar a classificação EXIF no painel de informações", - "raw": "", "reaction_options": "Opções de reação", "read_changelog": "Ler Novidades", "reassign": "Reatribuir", @@ -1062,6 +1034,7 @@ "reassigned_assets_to_new_person": "Reatribuído {count, plural, one {# ficheiro} other {# ficheiros}} a uma nova pessoa", "reassing_hint": "Atribuir ficheiros selecionados a uma pessoa existente", "recent": "Recentes", + "recent-albums": "Álbuns recentes", "recent_searches": "Pesquisas recentes", "refresh": "Atualizar", "refresh_encoded_videos": "Atualizar vídeos codificados", @@ -1083,6 +1056,7 @@ "remove_from_album": "Remover do álbum", "remove_from_favorites": "Remover dos favoritos", "remove_from_shared_link": "Remover do link partilhado", + "remove_url": "Remover URL", "remove_user": "Remover utilizador", "removed_api_key": "Foi removida a Chave de API: {name}", "removed_from_archive": "Removido do arquivo", @@ -1099,7 +1073,6 @@ "reset": "Redefinir", "reset_password": "Redefinir palavra-passe", "reset_people_visibility": "Redefinir pessoas ocultas", - "reset_settings_to_default": "", "reset_to_default": "Repor predefinições", "resolve_duplicates": "Resolver itens duplicados", "resolved_all_duplicates": "Todos os itens duplicados resolvidos", @@ -1119,9 +1092,7 @@ "saved_settings": "Definições guardadas", "say_something": "Diga alguma coisa", "scan_all_libraries": "Analisar todas as bibliotecas", - "scan_all_library_files": "Re-analisar todos os ficheiros da biblioteca", "scan_library": "Analisar", - "scan_new_library_files": "Analisar novos ficheiros na biblioteca", "scan_settings": "Opções de análise", "scanning_for_album": "A analisar por álbum...", "search": "Pesquisar", @@ -1164,7 +1135,6 @@ "selected_count": "{count, plural, other {# selecionados}}", "send_message": "Enviar mensagem", "send_welcome_email": "Enviar E-mail de boas vindas", - "server": "Servidor", "server_offline": "Servidor Offline", "server_online": "Servidor Online", "server_stats": "Estado do servidor", @@ -1269,6 +1239,7 @@ "they_will_be_merged_together": "Eles serão unidos", "third_party_resources": "Recursos de terceiros", "time_based_memories": "Memórias baseadas no tempo", + "timeline": "Linha de tempo", "timezone": "Fuso horário", "to_archive": "Arquivar", "to_change_password": "Alterar palavra-passe", @@ -1278,7 +1249,7 @@ "to_trash": "Reciclagem", "toggle_settings": "Alternar configurações", "toggle_theme": "Ativar modo escuro", - "toggle_visibility": "Alternar visibilidade", + "total": "Total", "total_usage": "Total utilizado", "trash": "Reciclagem", "trash_all": "Mover todos para a reciclagem", @@ -1288,12 +1259,10 @@ "trashed_items_will_be_permanently_deleted_after": "Os itens da reciclagem são eliminados permanentemente após {days, plural, one {# dia} other {# dias}}.", "type": "Tipo", "unarchive": "Desarquivar", - "unarchived": "Restaurado do arquivo", "unarchived_count": "{count, plural, other {Não arquivado #}}", "unfavorite": "Remover favorito", "unhide_person": "Exibir pessoa", "unknown": "Desconhecido", - "unknown_album": "", "unknown_year": "Ano desconhecido", "unlimited": "Ilimitado", "unlink_motion_video": "Remover relação com video animado", @@ -1330,6 +1299,8 @@ "user_purchase_settings_description": "Gerir a sua compra", "user_role_set": "Definir {user} como {role}", "user_usage_detail": "Detalhes de utilização do utilizador", + "user_usage_stats": "Estatísticas de utilização de conta", + "user_usage_stats_description": "Ver estatísticas de utilização de conta", "username": "Nome de utilizador", "users": "Utilizadores", "utilities": "Ferramentas", @@ -1337,7 +1308,7 @@ "variables": "Variáveis", "version": "Versão", "version_announcement_closing": "O seu amigo, Alex", - "version_announcement_message": "Olá amigo, há uma nova versão da aplicação. Reserve algum tempo para visitar o histórico de mudanças e garantir que as suas configurações do docker-compose.yml e .env estão atualizadas para evitar qualquer configuração incorreta, especialmente se usar o WatchTower ou qualquer mecanismo que lide com a atualização automática da aplicação.", + "version_announcement_message": "Olá! Está disponível uma nova versão do Immich. Por favor leia as notas de lançamento para garantir que as suas configurações estão atualizadas e para evitar quaisquer erros, especialmente se usar o WatchTower ou qualquer mecanismo que lide com a atualização automática do Immich.", "version_history": "Histórico de versões", "version_history_item": "Instalado {version} em {date}", "video": "Vídeo", @@ -1351,10 +1322,10 @@ "view_all_users": "Ver todos os utilizadores", "view_in_timeline": "Ver na linha do tempo", "view_links": "Ver links", + "view_name": "Ver", "view_next_asset": "Ver próximo ficheiro", "view_previous_asset": "Ver ficheiro anterior", "view_stack": "Ver pilha", - "viewer": "Visualizar", "visibility_changed": "Visibilidade alterada para {count, plural, one {# pessoa} other {# pessoas}}", "waiting": "Em fila", "warning": "Aviso", diff --git a/i18n/pt_BR.json b/i18n/pt_BR.json index 78f5ce71874e1..ccddd1cd3bbc2 100644 --- a/i18n/pt_BR.json +++ b/i18n/pt_BR.json @@ -23,6 +23,7 @@ "add_to": "Adicionar a...", "add_to_album": "Adicionar ao álbum", "add_to_shared_album": "Adicionar ao álbum compartilhado", + "add_url": "Adicionar URL", "added_to_archive": "Adicionado ao arquivo", "added_to_favorites": "Adicionado aos favoritos", "added_to_favorites_count": "{count, plural, one {{count, number} adicionado aos favoritos} other {{count, number} adicionados aos favoritos}}", @@ -34,18 +35,24 @@ "authentication_settings_disable_all": "Tem certeza de que deseja desativar todos os métodos de login? O login será completamente desativado.", "authentication_settings_reenable": "Para reabilitar, use um Comando do Servidor.", "background_task_job": "Tarefas em segundo plano", + "backup_database": "Backup do banco de dados", + "backup_database_enable_description": "Ativar backup do banco de dados", + "backup_keep_last_amount": "Quantidade de backups anteriores para manter salvo", + "backup_settings": "Configurações de backup", + "backup_settings_description": "Gerenciar configurações de backup", "check_all": "Selecionar Tudo", "cleared_jobs": "Tarefas removidas de: {job}", "config_set_by_file": "A configuração está atualmente definida por um arquivo de configuração", "confirm_delete_library": "Você tem certeza que deseja excluir a biblioteca {library} ?", "confirm_delete_library_assets": "Você tem certeza que deseja excluir esta biblioteca? Isso excluirá {count, plural, one {# arquivo contido do Immich e não poderá ser desfeito. O arquivo permanecerá no disco} other {todos os # arquivos contidos do Immich e não poderá ser desfeito. Os arquivos permanecerão no disco}}.", - "confirm_email_below": "Para confirmar, digite o {email} abaixo", + "confirm_email_below": "Para confirmar, digite \"{email}\" abaixo", "confirm_reprocess_all_faces": "Tem certeza de que deseja reprocessar todos os rostos? Isso também limpará as pessoas nomeadas.", "confirm_user_password_reset": "Tem certeza de que deseja redefinir a senha de {user}?", "create_job": "Criar tarefa", - "crontab_guru": "Guru do Crontab", + "cron_expression": "Expressão CRON", + "cron_expression_description": "Defina o intervalo de análise no formato Cron. Para mais informações, por favor veja o Crontab Guru", + "cron_expression_presets": "Sugestões de expressão Cron", "disable_login": "Desabilitar login", - "disabled": "", "duplicate_detection_job_description": "Execute a inteligência artificial em arquivos para detectar imagens semelhantes. Depende da Pesquisa Inteligente", "exclusion_pattern_description": "Os padrões de exclusão permitem ignorar arquivos e pastas ao escanear sua biblioteca. Isso é útil se você tiver pastas que contenham arquivos que não deseja importar, como arquivos RAW.", "external_library_created_at": "Biblioteca externa (criada em {date})", @@ -58,27 +65,20 @@ "forcing_refresh_library_files": "Forçando a atualização de todos os arquivos da biblioteca", "image_format": "Formato", "image_format_description": "WebP produz arquivos menores que JPEG, mas é mais lento para codificar.", - "image_prefer_embedded_preview": "Prefira visualização incorporada", + "image_prefer_embedded_preview": "Preferir visualização incorporada", "image_prefer_embedded_preview_setting_description": "Use visualizações incorporadas em fotos RAW como entrada para processamento de imagem, quando disponível. Isso pode produzir cores mais precisas para algumas imagens, mas a qualidade da visualização depende da câmera e a imagem pode ter mais artefatos de compactação.", "image_prefer_wide_gamut": "Prefira ampla gama", "image_prefer_wide_gamut_setting_description": "Use o Display P3 para miniaturas. Isso preserva melhor a vibração das imagens com espaços de cores amplos, mas as imagens podem aparecer de maneira diferente em dispositivos antigos com uma versão antiga do navegador. As imagens sRGB são mantidas como sRGB para evitar mudanças de cores.", "image_preview_description": "Imagem de tamanho médio sem os metadados, utilizado quando visualizar um único arquivo e também pela inteligência artificial", - "image_preview_format": "Formato de visualização", "image_preview_quality_description": "Qualidade da pré-visualização, de 1-100. Maior é melhor, mas produz arquivos maiores e pode reduzir a velocidade do aplicativo. Definir um valor muito baixo pode afetar a qualidade da inteligência artificial.", - "image_preview_resolution": "Resolução de visualização", - "image_preview_resolution_description": "Usado ao visualizar uma única foto e para aprendizado de máquina. Resoluções mais altas podem preservar mais detalhes, mas demoram mais para codificar, têm tamanhos de arquivo maiores e podem reduzir a capacidade de resposta do aplicativo.", "image_preview_title": "Configurações de pré-visualização", "image_quality": "Qualidade", - "image_quality_description": "Qualidade de imagem de 1 a 100. Quanto maior, melhor para a qualidade, mas produz arquivos maiores. Esta opção afeta as imagens de visualização e miniatura.", "image_resolution": "Resolução", "image_resolution_description": "Resoluções mais altas preservam mais detalhes, porém demoram mais para processar, tem um tamanho de arquivo maior e pode reduzir a velocidade do aplicativo.", "image_settings": "Configurações de imagem", "image_settings_description": "Gerenciar a qualidade e resolução das imagens geradas", "image_thumbnail_description": "Miniatura sem metadados, utilizado quando visualizar um grupos de fotos, como por exemplo, a linha do tempo principal", - "image_thumbnail_format": "Formato de miniatura", "image_thumbnail_quality_description": "Qualidade da miniatura, de 1 a 100. Maior é melhor, mas produz arquivos maiores e pode reduzir a velocidade do aplicativo.", - "image_thumbnail_resolution": "Resolução de miniatura", - "image_thumbnail_resolution_description": "Usado ao visualizar grupos de fotos (linha do tempo principal, visualização de álbum, etc.). Resoluções mais altas podem preservar mais detalhes, mas demoram mais para codificar, têm tamanhos de arquivo maiores e podem reduzir a capacidade de resposta do aplicativo.", "image_thumbnail_title": "Configurações de Miniaturas", "job_concurrency": "{job} simultâneo", "job_created": "Tarefa criada", @@ -89,14 +89,11 @@ "jobs_delayed": "{jobCount, plural, one {# atrasado} other {# atrasados}}", "jobs_failed": "{jobCount, plural, one {# falhou} other {# falharam}}", "library_created": "Criado biblioteca: {library}", - "library_cron_expression": "Expressão Cron", - "library_cron_expression_description": "Defina o intervalo de varredura usando o formato cron. Para mais informações, consulte, por exemplo, Crontab Guru", - "library_cron_expression_presets": "Predefinições de expressão Cron", "library_deleted": "Biblioteca excluída", "library_import_path_description": "Especifique uma pasta para importar. Esta pasta, incluindo subpastas, será escaneada em busca de imagens e vídeos.", - "library_scanning": "Escanear periódicamente", - "library_scanning_description": "Configurar o escaneamento periódico da biblioteca", - "library_scanning_enable_description": "Habilitar escaneamento periódico da biblioteca", + "library_scanning": "Verificação Periódica", + "library_scanning_description": "Configurar verificação periódica da biblioteca", + "library_scanning_enable_description": "Habilitar verificação periódica da biblioteca", "library_settings": "Biblioteca Externa", "library_settings_description": "Gerenciar configurações de biblioteca externa", "library_tasks_description": "Execute tarefas de biblioteca", @@ -134,7 +131,7 @@ "machine_learning_smart_search_description": "Buscar imagens semanticamente usando embeddings CLIP", "machine_learning_smart_search_enabled": "Habilitar a Pesquisa Inteligente", "machine_learning_smart_search_enabled_description": "Se desativado, as imagens não serão codificadas para pesquisa inteligente.", - "machine_learning_url_description": "URL do servidor de inteligência artificial", + "machine_learning_url_description": "A URL do servidor de inteligência artificial. Se mais de uma URL for configurada, o servidor irá tentar uma de cada vez até que uma delas responda com sucesso, em ordem sequencial igual a configurada.", "manage_concurrency": "Gerenciar simultaneidade", "manage_log_settings": "Gerenciar configurações de registro", "map_dark_style": "Tema Escuro", @@ -163,7 +160,7 @@ "note_apply_storage_label_previous_assets": "Observação: Para aplicar o rótulo de armazenamento a arquivos carregados anteriormente, execute o", "note_cannot_be_changed_later": "NOTA: Isto não pode ser alterado posteriormente!", "note_unlimited_quota": "Observação: insira 0 para cota ilimitada", - "notification_email_from_address": "A partir do endereço", + "notification_email_from_address": "E-mail de origem", "notification_email_from_address_description": "Endereço de e-mail do remetente, por exemplo: \"Immich Photo Server \"", "notification_email_host_description": "Host do servidor de e-mail (por exemplo, smtp.immich.app)", "notification_email_ignore_certificate_errors": "Ignorar erros de certificado", @@ -174,8 +171,8 @@ "notification_email_setting_description": "Configurações para envio de notificações por e-mail", "notification_email_test_email": "Enviar e-mail de teste", "notification_email_test_email_failed": "Falha ao enviar e-mail de teste. Verifique seus valores", - "notification_email_test_email_sent": "Um email de teste foi enviado para {email}. Por favor, verifique sua caixa de entrada.", - "notification_email_username_description": "Nome de usuário a ser usado ao autenticar com o servidor de e-mail", + "notification_email_test_email_sent": "Um e-mail de teste foi enviado para {email}. Por favor, verifique sua caixa de entrada.", + "notification_email_username_description": "Nome de usuário que será usado para autenticar com o servidor de e-mail", "notification_enable_email_notifications": "Habilitar notificações por e-mail", "notification_settings": "Configurações de notificação", "notification_settings_description": "Gerenciar configurações de notificação, incluindo e-mail", @@ -215,7 +212,6 @@ "refreshing_all_libraries": "Atualizando todas as bibliotecas", "registration": "Registro de Administrador", "registration_description": "Como você é o primeiro usuário no sistema, será designado como o Administrador e será responsável pelas tarefas administrativas. Você também poderá criar usuários adicionais.", - "removing_deleted_files": "Removendo arquivos offline", "repair_all": "Reparar tudo", "repair_matched_items": "{count, plural, one {# item encontrado} other {# itens encontrados}}", "repaired_items": "{count, plural, one {# item reparado} other {# itens reparados}}", @@ -223,12 +219,12 @@ "reset_settings_to_default": "Redefinir as configurações para o padrão", "reset_settings_to_recent_saved": "Redefinir as configurações para as configurações salvas recentemente", "scanning_library": "Analisando a biblioteca", - "scanning_library_for_changed_files": "Escaneando a biblioteca em busca de arquivos alterados", - "scanning_library_for_new_files": "Escaneando a biblioteca em busca de novos arquivos", "search_jobs": "Pesquisar tarefas...", "send_welcome_email": "Enviar e-mail de boas-vindas", "server_external_domain_settings": "Domínio externo", "server_external_domain_settings_description": "Domínio para links públicos compartilhados, incluindo http(s)://", + "server_public_users": "Usuários públicos", + "server_public_users_description": "Todos os usuários (nome e e-mail) serão exibidos na lista de adicionar usuários em álbuns compartilhados. Quando desativado, essa lista de usuários só será visível aos administradores.", "server_settings": "Configurações do servidor", "server_settings_description": "Gerenciar configurações do servidor", "server_welcome_message": "Mensagem de boas-vindas", @@ -254,6 +250,16 @@ "storage_template_user_label": "{label} é o Rótulo de Armazenamento do usuário", "system_settings": "Configurações do Sistema", "tag_cleanup_job": "Limpeza de tags", + "template_email_available_tags": "Você pode usar as seguintes variáveis no modelo: {tags}", + "template_email_if_empty": "Se o modelo estiver em branco, o modelo de e-mail padrão será usado.", + "template_email_invite_album": "Modelo do e-mail de convite para álbum", + "template_email_preview": "Pré visualização", + "template_email_settings": "Modelos de e-mail", + "template_email_settings_description": "Gerenciar modelos personalizados de e-mail de notificação", + "template_email_update_album": "Modelo do e-mail de atualização do álbum", + "template_email_welcome": "Modelo do e-mail de boas vindas", + "template_settings": "Modelos de notificação", + "template_settings_description": "Gerenciar modelos personalizados para notificações.", "theme_custom_css_settings": "CSS customizado", "theme_custom_css_settings_description": "Folhas de estilo em cascata permitem que o design do Immich seja personalizado.", "theme_settings": "Configurações de tema", @@ -261,7 +267,6 @@ "these_files_matched_by_checksum": "Esses arquivos são correspondidos por seus checksum", "thumbnail_generation_job": "Gerar Miniaturas", "thumbnail_generation_job_description": "Gere miniaturas grandes, pequenas e desfocadas para cada arquivo, bem como miniaturas para cada pessoa", - "transcode_policy_description": "", "transcoding_acceleration_api": "API de aceleração", "transcoding_acceleration_api_description": "A API que irá interagir com o seu dispositivo para acelerar a transcodificação. Esta configuração é a 'melhor opção': ela retornará à transcodificação de software em caso de falha. O VP9 pode não funcionar dependendo do seu hardware.", "transcoding_acceleration_nvenc": "NVENC (requer GPU NVIDIA)", @@ -313,8 +318,6 @@ "transcoding_threads_description": "Valores mais altos levam a uma codificação mais rápida, mas deixam menos espaço para o servidor processar outras tarefas enquanto estiver ativo. Este valor não deve ser superior ao número de núcleos da CPU. Maximiza a utilização se definido como 0.", "transcoding_tone_mapping": "Mapeamento de tons", "transcoding_tone_mapping_description": "Tenta preservar a aparência dos vídeos HDR quando convertidos para SDR. Cada algoritmo faz compensações diferentes em termos de cor, detalhes e brilho. Hable preserva os detalhes, Mobius preserva as cores e Reinhard preserva o brilho.", - "transcoding_tone_mapping_npl": "NPL de mapeamento de tons", - "transcoding_tone_mapping_npl_description": "As cores serão ajustadas para parecerem normais para uma exibição com esse brilho. Contra-intuitivamente, valores mais baixos aumentam o brilho do vídeo e vice-versa, uma vez que compensam o brilho da tela. 0 define esse valor automaticamente.", "transcoding_transcode_policy": "Política de transcodificação", "transcoding_transcode_policy_description": "Política para quando um vídeo deve ser transcodificado. Os vídeos HDR sempre serão transcodificados (exceto se a transcodificação estiver desativada).", "transcoding_two_pass_encoding": "Codificação de duas passagens", @@ -395,7 +398,6 @@ "archive_or_unarchive_photo": "Arquivar ou desarquivar foto", "archive_size": "Tamanho do arquivo", "archive_size_description": "Configure o tamanho do arquivo para baixar (em GiB)", - "archived": "Arquivado", "archived_count": "{count, plural, one {# Arquivado} other {# Arquivados}}", "are_these_the_same_person": "Essas pessoas são a mesma pessoa?", "are_you_sure_to_do_this": "Tem certeza de que deseja fazer isso?", @@ -416,7 +418,6 @@ "assets_added_to_album_count": "{count, plural, one {# arquivo adicionado} other {# arquivos adicionados}} ao álbum", "assets_added_to_name_count": "{count, plural, one {# arquivo adicionado} other {# arquivos adicionados}} {hasName, select, true {ao álbum {name}} other {em um novo álbum}}", "assets_count": "{count, plural, one {# arquivo} other {# arquivos}}", - "assets_moved_to_trash": "{count, plural, one {# ativo enviado} other {# ativos enviados}} para a lixeira", "assets_moved_to_trash_count": "{count, plural, one {# arquivo movido} other {# arquivos movidos}} para a lixeira", "assets_permanently_deleted_count": "{count, plural, one {# arquivo excluído permanentemente} other {# arquivos excluídos permanentemente}}", "assets_removed_count": "{count, plural, one {# arquivo removido} other {# arquivos removidos}}", @@ -446,10 +447,6 @@ "cannot_merge_people": "Não é possível mesclar pessoas", "cannot_undo_this_action": "Você não pode desfazer esta ação!", "cannot_update_the_description": "Não é possível atualizar a descrição", - "cant_apply_changes": "Não é possível aplicar alterações", - "cant_get_faces": "Não foi possível obter faces", - "cant_search_people": "Não foi possível pesquisar pessoas", - "cant_search_places": "Não foi possível pesquisar lugares", "change_date": "Alterar data", "change_expiration_time": "Alterar o prazo de validade", "change_location": "Alterar localização", @@ -481,6 +478,7 @@ "confirm": "Confirmar", "confirm_admin_password": "Confirmar senha de administrador", "confirm_delete_shared_link": "Tem certeza de que deseja excluir este link compartilhado?", + "confirm_keep_this_delete_others": "Todos os outros arquivos da pilha serão excluídos, exceto este arquivo. Tem certeza de que deseja continuar?", "confirm_password": "Confirme a senha", "contain": "Caber", "context": "Contexto", @@ -530,6 +528,7 @@ "delete_key": "Excluir chave", "delete_library": "Excluir biblioteca", "delete_link": "Excluir link", + "delete_others": "Excluir restante", "delete_shared_link": "Excluir link de compartilhamento", "delete_tag": "Remover tag", "delete_tag_confirmation_prompt": "Tem certeza que deseja excluir a tag {tagName} ?", @@ -563,13 +562,6 @@ "duplicates": "Duplicados", "duplicates_description": "Marque cada grupo indicando quais arquivos, se algum, são duplicados", "duration": "Duração", - "durations": { - "days": "", - "hours": "", - "minutes": "", - "months": "", - "years": "" - }, "edit": "Editar", "edit_album": "Editar álbum", "edit_avatar": "Editar foto de perfil", @@ -594,8 +586,6 @@ "editor_crop_tool_h2_aspect_ratios": "Proporções", "editor_crop_tool_h2_rotation": "Rotação", "email": "E-mail", - "empty": "", - "empty_album": "", "empty_trash": "Esvaziar lixo", "empty_trash_confirmation": "Tem certeza de que deseja esvaziar a lixeira? Isso removerá permanentemente do Immich todos os arquivos que estão na lixeira.\nVocê não pode desfazer esta ação!", "enable": "Habilitar", @@ -629,6 +619,7 @@ "failed_to_create_shared_link": "Falha ao criar o link compartilhado", "failed_to_edit_shared_link": "Falha ao editar o link compartilhado", "failed_to_get_people": "Falha na obtenção de pessoas", + "failed_to_keep_this_delete_others": "Falha ao manter este arquivo e excluir os outros", "failed_to_load_asset": "Não foi possível carregar o ativo", "failed_to_load_assets": "Não foi possível carregar os ativos", "failed_to_load_people": "Falha ao carregar pessoas", @@ -656,8 +647,6 @@ "unable_to_change_location": "Não foi possível alterar a localização", "unable_to_change_password": "Não foi possível alterar a senha", "unable_to_change_visibility": "Não foi possível alterar a visibilidade de {count, plural, one {# pessoa} other {# pessoas}}", - "unable_to_check_item": "", - "unable_to_check_items": "", "unable_to_complete_oauth_login": "Não foi possível concluir o login OAuth", "unable_to_connect": "Não foi possível conectar", "unable_to_connect_to_server": "Não foi possível se conectar ao servidor", @@ -698,12 +687,10 @@ "unable_to_remove_album_users": "Não foi possível remover usuários do álbum", "unable_to_remove_api_key": "Não foi possível a Chave de API", "unable_to_remove_assets_from_shared_link": "Não foi possível remover arquivos do link compartilhado", - "unable_to_remove_comment": "", "unable_to_remove_deleted_assets": "Não foi possível remover arquivos offline", "unable_to_remove_library": "Não foi possível remover a biblioteca", "unable_to_remove_partner": "Não foi possível remover parceiro", "unable_to_remove_reaction": "Não foi possível remover a reação", - "unable_to_remove_user": "", "unable_to_repair_items": "Não foi possível reparar os itens", "unable_to_reset_password": "Não foi possível resetar a senha", "unable_to_resolve_duplicate": "Não foi possível resolver a duplicidade", @@ -733,10 +720,6 @@ "unable_to_update_user": "Não foi possível atualizar o usuário", "unable_to_upload_file": "Não foi possível carregar o arquivo" }, - "every_day_at_onepm": "", - "every_night_at_midnight": "", - "every_night_at_twoam": "", - "every_six_hours": "", "exif": "Exif", "exit_slideshow": "Sair da apresentação", "expand_all": "Expandir tudo", @@ -751,33 +734,28 @@ "external": "Externo", "external_libraries": "Bibliotecas externas", "face_unassigned": "Sem nome", - "failed_to_get_people": "Falha ao carregar as pessoas", + "failed_to_load_assets": "Falha ao carregar arquivos", "favorite": "Favorito", "favorite_or_unfavorite_photo": "Marque ou desmarque a foto como favorita", "favorites": "Favoritos", - "feature": "", "feature_photo_updated": "Foto principal atualizada", - "featurecollection": "", "features": "Funcionalidades", "features_setting_description": "Gerenciar as funcionalidades da aplicação", "file_name": "Nome do arquivo", "file_name_or_extension": "Nome do arquivo ou extensão", "filename": "Nome do arquivo", - "files": "", "filetype": "Tipo de arquivo", "filter_people": "Filtrar pessoas", "find_them_fast": "Encontre pelo nome em uma pesquisa", "fix_incorrect_match": "Corrigir correspondência incorreta", "folders": "Pastas", "folders_feature_description": "Navegar pelas pastas das fotos e vídeos no sistema de arquivos", - "force_re-scan_library_files": "Força escanear novamente todos os arquivos da biblioteca", "forward": "Para frente", "general": "Geral", "get_help": "Obter Ajuda", "getting_started": "Primeiros passos", "go_back": "Voltar", "go_to_search": "Ir para a pesquisa", - "go_to_share_page": "Ir para a página de compartilhamento", "group_albums_by": "Agrupar álbuns por...", "group_no": "Sem agrupamento", "group_owner": "Agrupar por dono", @@ -803,10 +781,6 @@ "image_alt_text_date_place_2_people": "{isVideo, select, true {Vídeo gravado} other {Foto tirada}} em {city}, {country} com {person1} e {person2} em {date}", "image_alt_text_date_place_3_people": "{isVideo, select, true {Vídeo gravado} other {Foto tirada}} em {city}, {country} com {person1}, {person2}, e {person3} em {date}", "image_alt_text_date_place_4_or_more_people": "{isVideo, select, true {Vídeo gravado} other {Foto tirada}} em {city}, {country} com {person1}, {person2}, e {additionalCount, number} outros em {date}", - "image_alt_text_people": "{count, plural, =1 {com {person1}} =2 {com {person1} e {person2}} =3 {com {person1}, {person2}, e {person3}} other {com {person1}, {person2} e outras {others, number} pessoas}}", - "image_alt_text_place": "em {city}, {country}", - "image_taken": "{isVideo, select, true {Gravado} other {Fotografado}}", - "img": "", "immich_logo": "Logo do Immich", "immich_web_interface": "Interface Web do Immich", "import_from_json": "Importar do JSON", @@ -827,10 +801,11 @@ "invite_people": "Convidar Pessoas", "invite_to_album": "Convidar para o álbum", "items_count": "{count, plural, one {# item} other {# itens}}", - "job_settings_description": "", "jobs": "Tarefas", "keep": "Manter", "keep_all": "Manter Todos", + "keep_this_delete_others": "Manter este, excluir o resto", + "kept_this_deleted_others": "Este foi mantido e {count, plural, one {# arquivo foi excluído} other {# arquivos foram excluídos}}", "keyboard_shortcuts": "Atalhos do teclado", "language": "Idioma", "language_setting_description": "Selecione seu Idioma preferido", @@ -842,31 +817,6 @@ "level": "Nível", "library": "Biblioteca", "library_options": "Opções da biblioteca", - "license_account_info": "Sua conta está licenciada", - "license_activated_subtitle": "Obrigado por apoiar o Immich e o software de código aberto", - "license_activated_title": "Sua licença foi ativada com sucesso", - "license_button_activate": "Ativado", - "license_button_buy": "Compra", - "license_button_buy_license": "Comprar licença", - "license_button_select": "Selecione", - "license_failed_activation": "Falha ao ativar a licença. Verifique seu e-mail para obter a chave de licença correta!", - "license_individual_description_1": "1 licença por usuário em qualquer servidor", - "license_individual_title": "Licença individual", - "license_info_licensed": "Licenciado", - "license_info_unlicensed": "Sem licença", - "license_input_suggestion": "Tem licença? Digite a chave abaixo", - "license_license_subtitle": "Comprar uma licença para apoiar Immich", - "license_license_title": "LICENÇA", - "license_lifetime_description": "Licença Vitalícia", - "license_per_server": "Por servidor", - "license_per_user": "Por usuário", - "license_server_description_1": "1 licença por servidor", - "license_server_description_2": "Licença para todos os usuários no servidor", - "license_server_title": "Licença de servidor", - "license_trial_info_1": "Você está executando uma versão não licenciada do Immich", - "license_trial_info_2": "Você tem usado Immich por aproximadamente", - "license_trial_info_3": "{accountAge, plural, um {# dia} outro {# dias}}", - "license_trial_info_4": "Por favor, Considere adquirir uma licença para apoiar o desenvolvimento contínuo do serviço", "light": "Claro", "like_deleted": "Curtida excluída", "link_motion_video": "Relacionar video animado", @@ -971,7 +921,6 @@ "onboarding_welcome_user": "Bem-vindo, {user}", "online": "Online", "only_favorites": "Somente favoritos", - "only_refreshes_modified_files": "Somente atualize arquivos modificados", "open_in_map_view": "Mostrar no mapa", "open_in_openstreetmap": "Abrir no OpenStreetMap", "open_the_search_filters": "Abre os filtros de pesquisa", @@ -1009,14 +958,12 @@ "people_edits_count": "{count, plural, one {# pessoa editada} other {# pessoas editadas}}", "people_feature_description": "Navegar por fotos e vídeos agrupados por pessoas", "people_sidebar_description": "Exibe o link Pessoas na barra lateral", - "perform_library_tasks": "", "permanent_deletion_warning": "Aviso para deletar permanentemente", "permanent_deletion_warning_setting_description": "Exibe um aviso ao deletar arquivos de forma permanente", "permanently_delete": "Deletar permanentemente", "permanently_delete_assets_count": "Excluir permanentemente {count, plural, one {asset} other {assets}}", "permanently_delete_assets_prompt": "Você tem certeza de que deseja excluir permanentemente {count, plural, one {este ativo?} other {estes # ativos?}} Esta ação também removerá {count, plural, one {o ativo} other {os ativos}} de um ou mais álbuns.", "permanently_deleted_asset": "Arquivo deletado permanentemente", - "permanently_deleted_assets": "{count, plural, one {# ativo deletado} other {# ativos deletados}} permanentemente", "permanently_deleted_assets_count": "{count, plural, one {# arquivo permanentemente excluído} other {# arquivos permanentemente excluídos}}", "person": "Pessoa", "person_hidden": "{name}{hidden, select, true { (oculto)} other {}}", @@ -1032,7 +979,6 @@ "play_memories": "Reproduzir memórias", "play_motion_photo": "Reproduzir foto em movimento", "play_or_pause_video": "Reproduzir ou Pausar vídeo", - "point": "", "port": "Porta", "preset": "Predefinição", "preview": "Pré-visualizar", @@ -1077,12 +1023,10 @@ "purchase_server_description_2": "Status de Contribuidor", "purchase_server_title": "Servidor", "purchase_settings_server_activated": "A chave do produto para servidor é gerenciada pelo administrador", - "range": "", "rating": "Estrelas", "rating_clear": "Limpar classificação", "rating_count": "{count, plural, one {# estrela} other {# estrelas}}", "rating_description": "Exibir o EXIF de classificação no painel de informações", - "raw": "", "reaction_options": "Opções de reação", "read_changelog": "Ler Novidades", "reassign": "Reatribuir", @@ -1090,6 +1034,7 @@ "reassigned_assets_to_new_person": "{count, plural, one {# arquivo reatribuído} other {# arquivos reatribuídos}} a uma nova pessoa", "reassing_hint": "Atribuir arquivos selecionados a uma pessoa existente", "recent": "Recente", + "recent-albums": "Álbuns recentes", "recent_searches": "Pesquisas recentes", "refresh": "Atualizar", "refresh_encoded_videos": "Atualizar vídeos codificados", @@ -1111,6 +1056,7 @@ "remove_from_album": "Remover do álbum", "remove_from_favorites": "Remover dos favoritos", "remove_from_shared_link": "Remover do link compartilhado", + "remove_url": "Remover URL", "remove_user": "Remover usuário", "removed_api_key": "Removido a Chave de API: {name}", "removed_from_archive": "Removido do arquivo", @@ -1127,7 +1073,6 @@ "reset": "Resetar", "reset_password": "Resetar senha", "reset_people_visibility": "Resetar pessoas ocultas", - "reset_settings_to_default": "", "reset_to_default": "Redefinir para a configuração padrão", "resolve_duplicates": "Resolver duplicatas", "resolved_all_duplicates": "Todas duplicidades resolvidas", @@ -1147,9 +1092,7 @@ "saved_settings": "Configurações salvas", "say_something": "Diga algo", "scan_all_libraries": "Escanear Todas Bibliotecas", - "scan_all_library_files": "Re-escanear todos arquivos da biblioteca", "scan_library": "Analisar", - "scan_new_library_files": "Escanear novos arquivos na biblioteca", "scan_settings": "Opções de escanear", "scanning_for_album": "Escaneando por álbum...", "search": "Pesquisar", @@ -1192,7 +1135,6 @@ "selected_count": "{count, plural, one {# selecionado} other {# selecionados}}", "send_message": "Enviar mensagem", "send_welcome_email": "Enviar E-mail de boas vindas", - "server": "Servidor", "server_offline": "Servidor Indisponível", "server_online": "Servidor Disponível", "server_stats": "Status do servidor", @@ -1297,6 +1239,7 @@ "they_will_be_merged_together": "Eles serão mesclados", "third_party_resources": "Recursos de terceiros", "time_based_memories": "Memórias baseada no tempo", + "timeline": "Linha do tempo", "timezone": "Fuso horário", "to_archive": "Arquivar", "to_change_password": "Alterar senha", @@ -1306,7 +1249,7 @@ "to_trash": "Mover para a lixeira", "toggle_settings": "Alternar configurações", "toggle_theme": "Alternar tema escuro", - "toggle_visibility": "Alternar visibilidade", + "total": "Total", "total_usage": "Utilização total", "trash": "Lixeira", "trash_all": "Mover todos para o lixo", @@ -1316,12 +1259,10 @@ "trashed_items_will_be_permanently_deleted_after": "Os itens da lixeira serão deletados permanentemente após {days, plural, one {# dia} other {# dias}}.", "type": "Tipo", "unarchive": "Desarquivar", - "unarchived": "Restaurado do arquivo", "unarchived_count": "{count, plural, one {# desarquivado} other {# desarquivados}}", "unfavorite": "Remover favorito", "unhide_person": "Exibir pessoa", "unknown": "Desconhecido", - "unknown_album": "", "unknown_year": "Ano desconhecido", "unlimited": "Ilimitado", "unlink_motion_video": "Remover relação com video animado", @@ -1353,13 +1294,13 @@ "use_custom_date_range": "Usar intervalo de datas personalizado", "user": "Usuário", "user_id": "ID do usuário", - "user_license_settings": "Licença", - "user_license_settings_description": "Gerenciar sua licença", "user_liked": "{user} curtiu {type, select, photo {a foto} video {o vídeo} asset {o arquivo} other {isso}}", "user_purchase_settings": "Comprar", "user_purchase_settings_description": "Gerenciar sua compra", "user_role_set": "Definir {user} como {role}", "user_usage_detail": "Detalhes de uso do usuário", + "user_usage_stats": "Estatísticas de utilização de conta", + "user_usage_stats_description": "Ver estatísticas de utilização de conta", "username": "Nome do usuário", "users": "Usuários", "utilities": "Utilitários", @@ -1367,7 +1308,7 @@ "variables": "Variáveis", "version": "Versão", "version_announcement_closing": "De seu amigo, Alex", - "version_announcement_message": "Olá amigo! Uma nova versão do aplicativo está disponível. Para evitar configurações incorretas, por favor verifique com calma a página de notas da versão e certifique-se que os arquivos docker-compose.yml e .env estão configurados corretamente, principalmente se você usa o WatchTower ou qualquer outro mecanismo que faça atualizações automáticas.", + "version_announcement_message": "Olá! Uma nova versão do Immich está disponível. Para evitar configurações incorretas, leia com calma a página de notas da versão e verifique se é necessário alterar alguma configuração, principalmente se você usa o WatchTower ou qualquer outro mecanismo que faça atualizações automáticas do Immich.", "version_history": "Histórico de versões", "version_history_item": "Instalado {version} em {date}", "video": "Vídeo", @@ -1381,10 +1322,10 @@ "view_all_users": "Ver todos usuários", "view_in_timeline": "Ver na linha do tempo", "view_links": "Ver links", + "view_name": "Ver", "view_next_asset": "Ver próximo arquivo", "view_previous_asset": "Ver arquivo anterior", "view_stack": "Exibir Pilha", - "viewer": "Visualizar", "visibility_changed": "A visibilidade de {count, plural, one {# pessoa foi alterada} other {# pessoas foram alteradas}}", "waiting": "Aguardando", "warning": "Aviso", diff --git a/i18n/ro.json b/i18n/ro.json index 4078f656b965d..878bf9dd67bf3 100644 --- a/i18n/ro.json +++ b/i18n/ro.json @@ -23,18 +23,24 @@ "add_to": "Adaugă la...", "add_to_album": "Adaugă în album", "add_to_shared_album": "Adaugă la album partajat", + "add_url": "Adăugați adresa URL", "added_to_archive": "Adăugat la arhivă", "added_to_favorites": "Adaugă la favorite", "added_to_favorites_count": "Adăugat {count, number} la favorite", "admin": { "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/**”.", "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", - "check_all": "Bifează toate", + "background_task_job": "Activități de Fundal", + "backup_database": "Salvare Bază de Date", + "backup_database_enable_description": "Activare salvare bază de date", + "backup_keep_last_amount": "Cantitatea de copii de rezervă anterioare de păstrat", + "backup_settings": "Setări Copii de Rezervă", + "backup_settings_description": "Gestionați setările de salvare a bazei de date", + "check_all": "Bifează Toate", "cleared_jobs": "Activități eliminate pentru: {job}", "config_set_by_file": "Configurația este setată în prezent de un fișier de configurare", "confirm_delete_library": "Sigur doriți să ștergeți biblioteca {library}?", @@ -43,9 +49,10 @@ "confirm_reprocess_all_faces": "Sigur doriți să reprocesați toate fețele? Acest lucru va șterge și persoanele cu nume.", "confirm_user_password_reset": "Sigur doriți să resetați parola utilizatorului {user}?", "create_job": "Creează sarcină", - "crontab_guru": "", + "cron_expression": "Expresia cron", + "cron_expression_description": "Setați intervalul de scanare folosind formatul cron. Pentru mai multe informații, consultați de ex. Crontab Guru", + "cron_expression_presets": "Presetări de expresie cron", "disable_login": "Dezactivați autentificarea", - "disabled": "", "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_created_at": "Bibliotecă externă (creată pe {date})", @@ -63,35 +70,25 @@ "image_prefer_wide_gamut": "Preferă o gamă largă", "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_format": "Format de previzualizare", "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_resolution": "Previzualizare rezoluție", - "image_preview_resolution_description": "Folosit la vizualizarea unei singure fotografii și pentru învățarea automată. Rezoluțiile mai mari pot păstra mai multe detalii, dar codarea durează mai mult, au dimensiuni mai mari ale fișierelor și pot reduce capacitatea de răspuns a aplicației.", - "image_preview_title": "Previzualizeaza setarile", + "image_preview_title": "Previzualizați Setările", "image_quality": "Calitate", - "image_quality_description": "Calitatea imaginii de la 1 la 100. Număr mai mare este mai bun pentru calitate dar produce fișiere mai mari, această opțiune afectează imaginile Preview și Thumbnail.", "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ările imaginii", + "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_format": "Format imagini miniatură", "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_resolution": "Rezoluție imagini miniatură", - "image_thumbnail_resolution_description": "Folosit la vizualizarea unor grupuri de fotografii (cronologie principală, vizualizare album etc.). Rezoluțiile mai mari pot păstra mai multe detalii, dar codarea durează mai mult, au dimensiuni mai mari ale fișierelor și pot reduce capacitatea de răspuns a aplicației.", - "image_thumbnail_title": "Setari miniaturi", - "job_concurrency": "concurență {job}", + "image_thumbnail_title": "Setari Miniaturi", + "job_concurrency": "Concurență {job}", "job_created": "Sarcină creată", - "job_not_concurrency_safe": "Acest job nu este sigur pentru a rula în concurență.", - "job_settings": "Setări sarcină", + "job_not_concurrency_safe": "Această sarcină nu este sigură pentru a rula în concurență.", + "job_settings": "Setări Sarcină", "job_settings_description": "Administrează concurența sarcinilor", - "job_status": "Starea sarcinii", - "jobs_delayed": "{jobCount, plural, other {# delayed}}", + "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_cron_expression": "Expresie Cron", - "library_cron_expression_description": "Setează intervalul de scanare folosind formatul cron. Pentru mai multe informații, vă rugăm referiți-vă la pentru exemplu: Crontab Guru", - "library_cron_expression_presets": "presetări expresie cron", "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ă", @@ -104,68 +101,68 @@ "library_watching_settings": "Urmărirea bibliotecii (EXPERIMENTAL)", "library_watching_settings_description": "Urmărește automat fișierele schimbate", "logging_enable_description": "Activează înregistrarea log-urilor", - "logging_level_description": "Dacă setarea este activată, înregistrează evenimentele cu nivelul.", + "logging_level_description": "Dacă setarea este activată, înregistrează evenimentele cu nivelul de utilizat.", "logging_settings": "Înregistrare", "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": "Detectarea duplicatelor", + "machine_learning_duplicate_detection": "Detectare Duplicate", "machine_learning_duplicate_detection_enabled": "Activează detectarea duplicatelor", - "machine_learning_duplicate_detection_enabled_description": "Dacă este dezactivată, activele identice vor fi în continuare de-duplicate.", + "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", "machine_learning_enabled": "Activează algoritmii de învățare automată", "machine_learning_enabled_description": "Dacă este dezactivat, toate funcțiile ML vor fi dezactivate indiferent de setările de mai jos.", "machine_learning_facial_recognition": "Recunoaștere Facială", "machine_learning_facial_recognition_description": "Detectează, recunoaște și grupează fețe din imagini", "machine_learning_facial_recognition_model": "Model de recunoaștere facială", - "machine_learning_facial_recognition_model_description": "Modelele sunt aranjate descrescător după mărime. Modelele mai mari sunt lente și folosesc multă memorie, dar produc rezultate mai bune. Rețineți că va trebui să rulați din nou Recunoașterea Facială pentru toate imaginile dacă schimbați modelul.", - "machine_learning_facial_recognition_setting": "Activează Recunoașterea Facială", - "machine_learning_facial_recognition_setting_description": "Dacă este dezactivată, imaginile nu vor fi codificate pentru recunoașterea facială și nu vor popula secțiunea Persoane din pagina Explorare.", + "machine_learning_facial_recognition_model_description": "Modelele sunt aranjate descrescător după mărime. Modelele mai mari sunt lente și folosesc multă memorie, dar produc rezultate mai bune. Rețineți că va trebui să rulați din nou recunoașterea facială pentru toate imaginile dacă schimbați modelul.", + "machine_learning_facial_recognition_setting": "Activează recunoașterea facială", + "machine_learning_facial_recognition_setting_description": "Dacă este dezactivată, imaginile nu vor fi codificate pentru recunoașterea facială și nu vor popula secțiunea persoane din pagina explorare.", "machine_learning_max_detection_distance": "Distanța maximă pentru recunoaștere", "machine_learning_max_detection_distance_description": "Distanța maximă dintre două imagini pentru a le considera duplicate, variind între 0,001-0,1. Valorile mai mari vor detecta mai multe duplicate, dar pot duce la rezultate fals pozitive.", "machine_learning_max_recognition_distance": "Distanța maximă de recunoaștere", "machine_learning_max_recognition_distance_description": "Distanța maximă dintre două fețe pentru a fi considerate aceeași persoană, variind între 0-2. Reducerea acestui prag poate împiedica etichetarea a două persoane ca fiind aceeași persoană, în timp ce creșterea lui poate împiedica etichetarea aceleiași persoane ca fiind două persoane diferite. Rețineți că este mai ușor să unificați două persoane decât să împărțiți o persoană în două, deci, dacă este posibil, alegeți un prag mai mic.", "machine_learning_min_detection_score": "Scor minim de detecție", "machine_learning_min_detection_score_description": "Scorul minim de încredere pentru ca o față să fie detectată de la 0 la 1. Valorile mai mici vor detecta mai multe fețe, dar pot duce la fals pozitive.", - "machine_learning_min_recognized_faces": "Fețe minime recunoscute", + "machine_learning_min_recognized_faces": "Fețe minim recunoscute", "machine_learning_min_recognized_faces_description": "Numărul minim de fețe recunoscute pentru ca o persoană să fie creată. Creșterea acestui număr face ca recunoașterea facială să fie mai precisă, cu prețul creșterii șanselor ca o față să nu fie atribuită unei persoane.", - "machine_learning_settings": "Setări machine learning", + "machine_learning_settings": "Setări de învățare automată", "machine_learning_settings_description": "Gestionați caracteristicile și setările de învățare automată", "machine_learning_smart_search": "Căutare inteligentă", "machine_learning_smart_search_description": "Căutarea semantică a imaginilor utilizând încorporările CLIP", "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": "Adresa URL a serverului de învățare automată", - "manage_concurrency": "Gestionarea simultaneității", + "machine_learning_url_description": "Adresa URL a serverului de învățare automată. Dacă sunt furnizate mai multe adrese URL, fiecare server va fi încercat unul câte unul până când unul răspunde cu succes, în ordine de la primul până la ultimul.", + "manage_concurrency": "Gestionarea Simultaneității", "manage_log_settings": "Administrați setările jurnalului", "map_dark_style": "Mod întunecat", - "map_enable_description": "Activare hartă", + "map_enable_description": "Activați funcțiile hărții", "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", "map_manage_reverse_geocoding_settings": "Gestionare setări Localizare Inversă", - "map_reverse_geocoding": "Localizare Inversă", + "map_reverse_geocoding": "Localizare inversă", "map_reverse_geocoding_enable_description": "Activați geocodarea inversă", "map_reverse_geocoding_settings": "Setări geocodare inversă", "map_settings": "Hartă", "map_settings_description": "Gestionare setări hartă", "map_style_description": "URL-ul style.json către o temă pentru hartă", - "metadata_extraction_job": "Extragere metadata", - "metadata_extraction_job_description": "Extragere informații metadata din fiecare fișier cum ar fi localizare GPS, fețe și rezoluție,", + "metadata_extraction_job": "Extrageți metadatele", + "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 Metadata", - "metadata_settings_description": "Gestionează setările metadata", + "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", "no_paths_added": "Nicio cale adăugată", "no_pattern_added": "Niciun tipar adăugat", "note_apply_storage_label_previous_assets": "Notă: Pentru a aplica Eticheta de Stocare la elementele încărcate anterior, executați", "note_cannot_be_changed_later": "NOTĂ: Nu se va mai putea modifica ulterior!", - "note_unlimited_quota": "Notă: Introduceți 0 pentru cotă nelimitată", + "note_unlimited_quota": "Notă: Introduceți 0 pentru spațiu nelimitat", "notification_email_from_address": "De la adresa", "notification_email_from_address_description": "Adresa expeditorului, spre exemplu: „Immich Photo Server ”", - "notification_email_host_description": "Adresa serverului de email (e.g. smtp.immich.app)", + "notification_email_host_description": "Adresa serverului de email (ex. smtp.immich.app)", "notification_email_ignore_certificate_errors": "Ingnoră erorile de certificat", "notification_email_ignore_certificate_errors_description": "Ignoră erorile de validare a certificatului TLS (nerecomandat)", "notification_email_password_description": "Parola utilizată pentru autentificarea în serverul de email", @@ -174,10 +171,10 @@ "notification_email_setting_description": "Setări pentru trimiterea de notificări pe email", "notification_email_test_email": "Trimitere email de test", "notification_email_test_email_failed": "Eroare la trimiterea emailului de test, verificați setările", - "notification_email_test_email_sent": "Un email de test a fost trimis la adresa {email}. Vă rugăm să verificați.", + "notification_email_test_email_sent": "Un email de test a fost trimis la adresa {email}. Vă rugăm să vă verificați căsuța de e-mail.", "notification_email_username_description": "Numele de utilizator pentru autentificarea pe serverul de email", "notification_enable_email_notifications": "Activare notificări pe email", - "notification_settings": "Setări Notificare", + "notification_settings": "Setări notificare", "notification_settings_description": "Gestionează setările pentru notificări, inclusiv adresa de email", "oauth_auto_launch": "Pornire automată", "oauth_auto_launch_description": "Lansează automat autorizarea OAuth la accesarea paginii de login", @@ -185,7 +182,7 @@ "oauth_auto_register_description": "Înregistrează automat utilizatori noi după autentificarea cu OAuth", "oauth_button_text": "Text buton", "oauth_client_id": "ID Client", - "oauth_client_secret": "Secret Client", + "oauth_client_secret": "Secret client", "oauth_enable_description": "Autentifică-te cu OAuth", "oauth_issuer_url": "Emitentul URL", "oauth_mobile_redirect_uri": "URI de redirecționare mobilă", @@ -200,44 +197,43 @@ "oauth_signing_algorithm": "Algoritm de semnare", "oauth_storage_label_claim": "Revendicare eticheta de stocare", "oauth_storage_label_claim_description": "Setați automat eticheta de stocare a utilizatorului la valoarea acestei revendicări.", - "oauth_storage_quota_claim": "Revendicare cotă de stocare", - "oauth_storage_quota_claim_description": "Setează automat cota de stocare a utilizatorului la valoarea acestei cereri.", - "oauth_storage_quota_default": "Cota implicită de stocare (GiB)", - "oauth_storage_quota_default_description": "Cota în GiB ce urmează a fi utilizată atunci când nu este furnizată nicio solicitare (introduceți 0 pentru o cotă nelimitată).", - "offline_paths": "Cǎi invalide", + "oauth_storage_quota_claim": "Revendicare spațiu de stocare", + "oauth_storage_quota_claim_description": "Setează automat spațiul de stocare al utilizatorului la valoarea acestei cereri.", + "oauth_storage_quota_default": "Cota implicită a spațiului de stocare (GiB)", + "oauth_storage_quota_default_description": "Spațiul în GiB ce urmează a fi utilizat atunci când nu este furnizată nicio solicitare (introduceți 0 pentru spațiu nelimitat).", + "offline_paths": "Căi Offline", "offline_paths_description": "Acestea pot fi rezultate în urma ștergerii manuale a fișierelor ce nu fac parte dintr-o bibliotecǎ externǎ.", "password_enable_description": "Autentificare cu email și parolǎ", - "password_settings": "Autentificare cu parolǎ", + "password_settings": "Autentificare cu Parolǎ", "password_settings_description": "Gestioneazǎ setǎrile de autentificare cu parola", "paths_validated_successfully": "Toate cǎile au fost validate cu succes", "person_cleanup_job": "Ștergere persoane", "quota_size_gib": "Spațiu de stocare alocat (GiB)", "refreshing_all_libraries": "Bibliotecile sunt în curs de reîmprospǎtare", - "registration": "Înregistrare administratori", - "registration_description": "Deoarece sunteți primul utilizator de pe sistem, veți fi desemnat ca administrator și sunteți responsabil pentru sarcinile administrative, iar utilizatorii suplimentari vor fi creați de dumneavoastra.", - "removing_deleted_files": "Eliminarea fișierelor offline", - "repair_all": "Reparǎ toate", - "repair_matched_items": "{count, plural, one {Potrivit # obiect} other {Potrivite # obiecte}}", - "repaired_items": "{count, plural, one {Reparat # obiect} other {Reparate # obiecte}}", + "registration": "Înregistrare Administratori", + "registration_description": "Deoarece sunteți primul utilizator de pe sistem, veți fi desemnat ca administrator și sunteți responsabil pentru sarcinile administrative, iar utilizatorii suplimentari vor fi creați de dumneavoastră.", + "repair_all": "Reparǎ Toate", + "repair_matched_items": "S-au potrivit {count, plural, one {# element} other {# elemente}}", + "repaired_items": "S-au reparat {count, plural, one {# element} other {# elemente}}", "require_password_change_on_login": "Obligǎ utilizatorul sǎ își schimbe parola la prima autentificare", "reset_settings_to_default": "Reseteazǎ setǎrile la valorile implicite", "reset_settings_to_recent_saved": "Reseteazǎ setǎrile la valorile salvate recent", "scanning_library": "Se scanează biblioteca", - "scanning_library_for_changed_files": "Se scaneazǎ biblioteca pentru fișiere modificate", - "scanning_library_for_new_files": "Se scaneazǎ biblioteca pentru fișiere noi", - "search_jobs": "Caută în procesări...", + "search_jobs": "Caută sarcini...", "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_settings": "Setǎri server", + "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", "server_welcome_message": "Mesaj de bun-venit", "server_welcome_message_description": "Un mesaj ce este afișat pe pagina de autentificare.", - "sidecar_job": "Metadate Sidecar", + "sidecar_job": "Metadate sidecar", "sidecar_job_description": "Descoperirea sau sincronizarea metadatelor sidecar din sistemul de fișiere", "slideshow_duration_description": "Numǎrul de secunde pentru afișarea fiecǎrei imagini", - "smart_search_job_description": "Rulați machine learning pe active pentru a sprijini căutarea inteligentă", - "storage_template_date_time_description": "Momentul creării activului este utilizat pentru informațiile privind data și ora", + "smart_search_job_description": "Rulați învățarea automată pe elemente pentru a ajuta căutarea inteligentă", + "storage_template_date_time_description": "Momentul creării elementului este utilizat pentru informațiile privind data și ora", "storage_template_date_time_sample": "Eșantion de timp {date}", "storage_template_enable_description": "Activați motorul de șabloane de stocare", "storage_template_hash_verification_enabled": "Verificarea hash este activată", @@ -245,39 +241,48 @@ "storage_template_migration": "Migrarea șablonului de stocare", "storage_template_migration_description": "Aplicați {template} actual la elementele încărcate anterior", "storage_template_migration_info": "Modificările de șablon se vor aplica numai materialelor noi. Pentru a aplica retroactiv șablonul la materialele încărcate anterior, rulați {job}.", - "storage_template_migration_job": "Activitate migrare template stocare", + "storage_template_migration_job": "Sarcină Migrare Șablon Stocare", "storage_template_more_details": "Pentru mai multe detalii despre aceasta caracteristică, accesați Șablon stocare si implicațiile", - "storage_template_onboarding_description": "Atunci când este activată, această caracteristică va organiza automat fișierele pe baza unui șablon definit de utilizator. Din cauza unor probleme de stabilitate, aceasta caracteristică este dezactivată implicit. Pentru mai multe informații, te rog sa consulți documentația.", + "storage_template_onboarding_description": "Atunci când este activată, această caracteristică va organiza automat fișierele pe baza unui șablon definit de utilizator. Din cauza unor probleme de stabilitate, această caracteristică este dezactivată implicit. Pentru mai multe informații, te rog să consulți documentația.", "storage_template_path_length": "Limita de lungime pentru calea aproximativă: {length, number}/{limit, number}", - "storage_template_settings": "Șablon stocare", - "storage_template_settings_description": "Gestionează structura folderelor și numele fișierelor pentru activele încărcate", + "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", + "system_settings": "Setǎri de Sistem", "tag_cleanup_job": "Curățare etichete", + "template_email_available_tags": "Puteți utiliza următoarele variabile în șablonul dvs.: {tags}", + "template_email_if_empty": "Dacă șablonul este gol, va fi folosit e-mailul implicit.", + "template_email_invite_album": "Șablon de Album de Invitație", + "template_email_preview": "Previzualizare", + "template_email_settings": "Șabloane de E-mail", + "template_email_settings_description": "Gestionați șabloanele personalizate de notificare prin e-mail", + "template_email_update_album": "Actualizați Șablonul de Album", + "template_email_welcome": "Șablon de e-mail de bun venit", + "template_settings": "Șabloane de Notificare", + "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", "these_files_matched_by_checksum": "Aceste fișiere sunt comparate folosind sumele de control", - "thumbnail_generation_job": "Gerează 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ă", - "transcode_policy_description": "", "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 'best effort': va reveni la transcodarea software în caz de eșec. VP9 poate funcționa sau nu, în funcție de hardware-ul tău.", + "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.", "transcoding_acceleration_nvenc": "NVENC (necesitǎ GPU NVIDIA)", - "transcoding_acceleration_qsv": "Quick Sync (necesitǎ CPU Intel de generația a 7-a sau mai mare)", + "transcoding_acceleration_qsv": "Sincronizare Rapidă (necesitǎ CPU Intel de generația a 7-a sau mai mare)", "transcoding_acceleration_rkmpp": "RKMPP (doar pe SOC-uri Rockchip)", "transcoding_acceleration_vaapi": "VAAPI", - "transcoding_accepted_audio_codecs": "Codec-uri audio acceptate", - "transcoding_accepted_audio_codecs_description": "Selectează care codec-uri audio nu trebuie să fie transcodificate. Se utilizează doar pentru anumite politici de transcodare.", + "transcoding_accepted_audio_codecs": "Codecuri audio acceptate", + "transcoding_accepted_audio_codecs_description": "Selectează care codecuri audio nu trebuie să fie transcodificate. Se utilizează doar pentru anumite politici de transcodare.", "transcoding_accepted_containers": "Containere acceptate", - "transcoding_accepted_containers_description": "Selectează formatele de containere care nu trebuie să fie remuxate în MP4. Se utilizează doar pentru anumite politici de transcodare.", - "transcoding_accepted_video_codecs": "Codec-uri video acceptate", - "transcoding_accepted_video_codecs_description": "Selectează codec-urile video care nu trebuie să fie transcodificate. Se utilizează doar pentru anumite politici de transcodare.", + "transcoding_accepted_containers_description": "Selectează formatele de containere care nu trebuie să fie remixate în MP4. Se utilizează doar pentru anumite politici de transcodare.", + "transcoding_accepted_video_codecs": "Codecuri video acceptate", + "transcoding_accepted_video_codecs_description": "Selectează codecurile video care nu trebuie să fie transcodificate. Se utilizează doar pentru anumite politici de transcodare.", "transcoding_advanced_options_description": "Opțiuni pe care majoritatea utilizatorilor nu ar trebui să fie necesar să le schimbe", "transcoding_audio_codec": "Codec audio", "transcoding_audio_codec_description": "Opus este opțiunea cu cea mai bună calitate, dar are o compatibilitate mai scăzută cu dispozitivele sau software-ul mai vechi.", - "transcoding_bitrate_description": "Videoclipuri cu un bitrate mai mare decât maximul acceptat sau care nu sunt într-un format acceptat", + "transcoding_bitrate_description": "Videoclipuri cu rata de biți mai mare decât maximul acceptat sau care nu sunt într-un format acceptat", "transcoding_codecs_learn_more": "Pentru a afla mai multe despre terminologia folosită aici, consultă documentația FFmpeg pentru codec-ul H.264, codec-ul HEVC și codec-ul VP9.", "transcoding_constant_quality_mode": "Mod de calitate constantă", "transcoding_constant_quality_mode_description": "ICQ este mai bun decât CQP, dar unele dispozitive de accelerare hardware nu suportă acest mod. Setarea acestei opțiuni va prefera modul specificat atunci când folosești codificarea bazată pe calitate. Ignorat de NVENC deoarece nu suportă ICQ.", @@ -288,10 +293,10 @@ "transcoding_hardware_acceleration_description": "Experimental; mult mai rapid, dar va avea o calitate mai scăzută la același bitrate", "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.", - "transcoding_hevc_codec": "codec HEVC", + "transcoding_hevc_codec": "Codec HEVC", "transcoding_max_b_frames": "Număr maxim de cadre B", "transcoding_max_b_frames_description": "Valorile mai mari îmbunătățesc eficiența compresiei, dar încetinesc codarea. Este posibil să nu fie compatibile cu accelerarea hardware pe dispozitivele mai vechi. 0 dezactivează cadrele B, în timp ce -1 setează această valoare automat.", - "transcoding_max_bitrate": "Bitrate maxim", + "transcoding_max_bitrate": "Rata de biți maximă", "transcoding_max_bitrate_description": "Setarea unei rate maxime de biți poate face dimensiunile fișierelor mai previzibile, cu un cost minor asupra calității. La 720p, valorile tipice sunt 2600k pentru VP9 sau HEVC, sau 4500k pentru H.264. Dezactivat dacă este setat la 0.", "transcoding_max_keyframe_interval": "Interval maxim între cadre cheie", "transcoding_max_keyframe_interval_description": "Setează distanța maximă între cadrele cheie. Valorile mai mici reduc eficiența compresiei, dar îmbunătățesc timpii de căutare și pot îmbunătăți calitatea în scenele cu mișcare rapidă. 0 setează această valoare automat.", @@ -303,7 +308,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ă rezoluția și informațiile de codare ale fișierelor video", "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.", @@ -313,20 +318,18 @@ "transcoding_threads_description": "Valorile mai mari conduc la o codare mai rapidă, dar lasă mai puțin spațiu serverului pentru a procesa alte sarcini în timp ce este activ. Această valoare nu ar trebui să fie mai mare decât numărul de nuclee CPU. Maximizați utilizarea dacă este setat la 0.", "transcoding_tone_mapping": "Mapare tonuri", "transcoding_tone_mapping_description": "Încearcă să păstreze aspectul videoclipurilor HDR atunci când sunt convertite în SDR. Fiecare algoritm face compromisuri diferite pentru culoare, detalii și strălucire. Hable păstrează detaliile, Mobius păstrează culoarea, iar Reinhard păstrează strălucirea.", - "transcoding_tone_mapping_npl": "Mapare tonuri NPL", - "transcoding_tone_mapping_npl_description": "Culorile vor fi ajustate pentru a arăta normal pe un ecran cu această strălucire. În mod contraintuitiv, valorile mai mici cresc strălucirea videoclipului și invers, deoarece compensează pentru strălucirea ecranului. 0 setează această valoare automat.", "transcoding_transcode_policy": "Politica de transcodare", - "transcoding_transcode_policy_description": "Politica pentru când un videoclip ar trebui să fie transcodificat. Videoclipurile HDR vor fi întotdeauna transcodificate (cu excepția cazului în care transcodarea este dezactivată).", - "transcoding_two_pass_encoding": "Codare în două treceri", + "transcoding_transcode_policy_description": "Politica pentru momentul când un videoclip ar trebui să fie transcodificat. Videoclipurile HDR vor fi întotdeauna transcodificate (cu excepția cazului în care transcodarea este dezactivată).", + "transcoding_two_pass_encoding": "Codare în doi pași", "transcoding_two_pass_encoding_setting_description": "Transcodificare în două treceri pentru a produce videoclipuri codificate mai bine. Când rata maximă de biți este activată (necesară pentru a funcționa cu H.264 și HEVC), acest mod utilizează un interval de rată de biți bazat pe rata maximă de biți și ignoră CRF. Pentru VP9, CRF poate fi utilizat dacă rata maximă de biți este dezactivată.", - "transcoding_video_codec": "Codec video", + "transcoding_video_codec": "Codec Video", "transcoding_video_codec_description": "VP9 are eficiențǎ mare și compatibilitate web, însǎ transcodarea este de duratǎ mai mare. HEVC se comportǎ asemǎnǎtor, însǎ are compatibilitate web mai micǎ. H.264 este foarte compatibil și rapid în transcodare, însǎ genereazǎ fișiere mult mai mari. AV1 este cel mai eficient codec dar nu este compatibil cu dispozitivele mai vechi.", - "trash_enabled_description": "Activează funcțiile Coș de gunoi", + "trash_enabled_description": "Activează funcțiile Coșului de Gunoi", "trash_number_of_days": "Numǎr de zile", "trash_number_of_days_description": "Numǎr de zile pentru pǎstrarea fișierelor în coșul de gunoi pânǎ la ștergerea permanentǎ", - "trash_settings": "Setǎri coș de gunoi", + "trash_settings": "Setǎri Coș de Gunoi", "trash_settings_description": "Gestioneazǎ setǎrile coșului de gunoi", - "untracked_files": "Fișiere neurmărite", + "untracked_files": "Fișiere Neurmărite", "untracked_files_description": "Aceste fișiere nu sunt urmărite de aplicație. Ele pot fi rezultatul unor mutări eșuate, încărcări întrerupte sau pot rămâne în urmă din cauza unei erori", "user_cleanup_job": "Curățare utilizator", "user_delete_delay": "Contul și resursele utilizatorului {user} vor fi programate pentru ștergere permanentă în {delay, plural, one {# zi} other {# zile}}.", @@ -339,18 +342,18 @@ "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-mailul administratorului", - "admin_password": "Parolă administrator", + "admin_email": "E-mail Administrator", + "admin_password": "Parolă Administrator", "administration": "Administrare", "advanced": "Avansat", "age_months": "Vârstă {months, plural, one {# lună} other {# luni}}", @@ -362,9 +365,9 @@ "album_delete_confirmation": "Ești sigur că vrei să ștergi albumul {album}?", "album_delete_confirmation_description": "Dacă acest album este partajat, alți utilizatori nu vor mai putea accesa.", "album_info_updated": "Informații album actualizate", - "album_leave": "Lăsați albumul?", - "album_leave_confirmation": "Ești sigur că dorești să părăsești {album}?", - "album_name": "Nume album", + "album_leave": "Părăsiți albumul?", + "album_leave_confirmation": "Sigur doriți să părăsiți {album}?", + "album_name": "Nume Album", "album_options": "Opțiuni album", "album_remove_user": "Eliminare utilizator?", "album_remove_user_confirmation": "Ești sigur că dorești eliminarea {user}?", @@ -395,20 +398,19 @@ "archive_or_unarchive_photo": "Arhiveazǎ sau dezarhiveazǎ fotografia", "archive_size": "Mărime arhivă", "archive_size_description": "Configurează dimensiunea arhivei pentru descărcări (în GiB)", - "archived": "", "archived_count": "{count, plural, other {Arhivat/e#}}", "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_added_to_album": "Adăugat la album", "asset_adding_to_album": "Se adaugă la album...", - "asset_description_updated": "Descrierea activelor a fost actualizată", + "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": "Hașurare...", + "asset_hashing": "Se face hashing...", "asset_offline": "Resursă Offline", "asset_offline_description": "Această resursă externă nu mai este găsită pe disc. Contactează te rog administratorul tău Immich pentru ajutor.", "asset_skipped": "Sărit", - "asset_skipped_in_trash": "În gunoi", + "asset_skipped_in_trash": "În coșul de gunoi", "asset_uploaded": "Încărcat", "asset_uploading": "Se incarcă...", "assets": "Resurse", @@ -423,53 +425,50 @@ "assets_restored_count": "Restaurat {count, plural, one {# resursă} other {# resurse}}", "assets_trashed_count": "Mutat în coșul de gunoi {count, plural, one {# resursă} other {# resurse}}", "assets_were_part_of_album_count": "{count, plural, one {Resursa era} other {Resursele erau}} deja parte din album", - "authorized_devices": "Dispozitive autorizate", + "authorized_devices": "Dispozitive Autorizate", "back": "Înapoi", "back_close_deselect": "Înapoi, închidere sau deselectare", "backward": "În sens invers", "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", - "build": "Construiți", - "build_image": "Construiți imagine", + "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!", "bulk_keep_duplicates_confirmation": "Ești sigur că vrei să păstrezi {count, plural, one {# resursă duplicată} other {# resurse duplicate}}? Aceasta va rezolva toate grupurile duplicate fără a șterge nimic.", "bulk_trash_duplicates_confirmation": "Ești sigur că vrei să muți în coșul de gunoi {count, plural, one {# resursă duplicată} other {# resurse duplicate}}? Aceasta va păstra cea mai mare resursă din fiecare grup și va muta în coșul de gunoi toate celelalte duplicate.", - "buy": "Achiziționează Immich", + "buy": "Achiziționați Immich", "camera": "Camerǎ", "camera_brand": "Marcǎ cameră", "camera_model": "Model cameră", - "cancel": "Anulează", - "cancel_search": "Anulează căutarea", - "cannot_merge_people": "Nu se pot îmbina oamenii", + "cancel": "Anulați", + "cancel_search": "Anulați căutarea", + "cannot_merge_people": "Nu se pot îmbina persoanele", "cannot_undo_this_action": "Nu puteți anula această acțiune!", "cannot_update_the_description": "Nu se poate actualiza descrierea", - "cant_apply_changes": "", - "cant_get_faces": "", - "cant_search_people": "", - "cant_search_places": "", - "change_date": "Schimbă dată", - "change_expiration_time": "Shimbă dată expirare", - "change_location": "Schimbă locația", - "change_name": "Schimbă nume", + "change_date": "Schimbați data", + "change_expiration_time": "Schimbați data expirare", + "change_location": "Schimbați locația", + "change_name": "Schimbați nume", "change_name_successfully": "Schimbare nume cu succes", - "change_password": "Schimbă Parolă", + "change_password": "Schimbați parolă", "change_password_description": "Aceasta este fie prima dată când te conectezi în sistem, fie s-a făcut o solicitare pentru a schimba parola ta. Te rog să introduci noua parolă mai jos.", "change_your_password": "Schimbă-ți parola", "changed_visibility_successfully": "Schimbare vizibilitate cu succes", - "check_all": "Selectează Tot", - "check_logs": "Verifică Jurnale", + "check_all": "Selectați Tot", + "check_logs": "Verificați Jurnale", "choose_matching_people_to_merge": "Alegeți persoanele care se potrivesc pentru a le fuziona", "city": "Oraș", - "clear": "Curăță", - "clear_all": "Curăță tot", - "clear_all_recent_searches": "Curăță toate căutările recente", - "clear_message": "Șterge mesajul", - "clear_value": "Șterge valoare", + "clear": "Curățați", + "clear_all": "Curățați tot", + "clear_all_recent_searches": "Curățați toate căutările recente", + "clear_message": "Ștergeți mesajul", + "clear_value": "Ștergeți valoarea", "clockwise": "În sensul acelor de ceas", - "close": "Închide", - "collapse": "Restrânge", - "collapse_all": "Restrânge pe toate", + "close": "Închideți", + "collapse": "Restrângeți", + "collapse_all": "Restrângeți toate", "color": "Culoare", "color_theme": "Tema de culoare", "comment_deleted": "Comentariu șters", @@ -477,27 +476,28 @@ "comments_and_likes": "Comentarii & aprecieri", "comments_are_disabled": "Comentariile sunt dezactivate", "confirm": "Confirmați", - "confirm_admin_password": "Confirmați parola de administrator", + "confirm_admin_password": "Confirmați Parola de Administrator", "confirm_delete_shared_link": "Sunteți sigur că doriți să ștergeți acest link partajat?", + "confirm_keep_this_delete_others": "Toate celelalte active din stivă vor fi șterse, cu excepția acestui material. Sunteți sigur că doriți să continuați?", "confirm_password": "Confirmați parola", "contain": "Încadrează", "context": "Context", "continue": "Continuați", - "copied_image_to_clipboard": "Imaginea copiată în clipboard.", + "copied_image_to_clipboard": "Imagine copiată în clipboard.", "copied_to_clipboard": "Copiat în clipboard!", "copy_error": "Eroare de copiere", "copy_file_path": "Copiați calea fișierului", "copy_image": "Copiere imagine", "copy_link": "Copiere link", - "copy_link_to_clipboard": "Copiați link-ul în clipboard", - "copy_password": "Copiați parola", - "copy_to_clipboard": "Copiere în Clipboard", + "copy_link_to_clipboard": "Copiere link în clipboard", + "copy_password": "Copiere parola", + "copy_to_clipboard": "Copiere în clipboard", "country": "Țara", "cover": "Umple fereastra", "covers": "Acoperă", "create": "Creează", "create_album": "Creează album", - "create_library": "Creează bibliotecă", + "create_library": "Creează Bibliotecă", "create_link": "Creează link", "create_link_to_share": "Creează link pentru a distribui", "create_link_to_share_description": "Permiteți oricui are link-ul să vadă fotografia (fotografiile) selectată(e)", @@ -509,39 +509,40 @@ "create_user": "Creează utilizator", "created": "Creat", "current_device": "Dispozitiv curent", - "custom_locale": "Setare regională personalizată", + "custom_locale": "Setare Regională Personalizată", "custom_locale_description": "Formatați datele și numerele în funcție de limbă și regiune", "dark": "Întunecat", - "date_after": "Dată după", - "date_and_time": "Dată și Oră", - "date_before": "Dată anterioară", + "date_after": "După data", + "date_and_time": "Dată și oră", + "date_before": "Anterior datei", "date_of_birth_saved": "Data nașterii salvată cu succes", "date_range": "Interval de date", "day": "Zi", - "deduplicate_all": "Deduplicați toate", - "default_locale": "Setare regionlă implicită", + "deduplicate_all": "Deduplicați Toate", + "default_locale": "Setare Regională Implicită", "default_locale_description": "Formatați datele și numerele în funcție de regiunea browserului dvs", - "delete": "Șterge", - "delete_album": "Șterge album", + "delete": "Ștergere", + "delete_album": "Ștergere album", "delete_api_key_prompt": "Sunteți sigur că doriți să ștergeți această cheie API?", "delete_duplicates_confirmation": "Sunteți sigur că doriți să ștergeți permanent aceste duplicate?", - "delete_key": "Șterge cheie", - "delete_library": "Șterge Biblioteca", - "delete_link": "Șterge linkul", - "delete_shared_link": "Șterge link-ul partajat", - "delete_tag": "Șterge etichetă", + "delete_key": "Ștergere cheie", + "delete_library": "Ștergere biblioteca", + "delete_link": "Ștergere link", + "delete_others": "Ștergeți celelalte", + "delete_shared_link": "Ștergere link partajat", + "delete_tag": "Ștergere etichetă", "delete_tag_confirmation_prompt": "Ești sigur că vrei să ștergi eticheta {tagName} ?", - "delete_user": "Șterge utilizator", + "delete_user": "Ștergere utilizator", "deleted_shared_link": "Link partajat șters", - "deletes_missing_assets": "Șterge resursele lipsă de pe disc", + "deletes_missing_assets": "Ștergere resurse lipsă de pe disc", "description": "Descriere", "details": "Detalii", "direction": "Direcție", "disabled": "Dezactivat", "disallow_edits": "Interzice modificările", - "discord": "Discord", + "discord": "Server Discord", "discover": "Descoperiți", - "dismiss_all_errors": "Ignoră toate erorile", + "dismiss_all_errors": "Ignorați toate erorile", "dismiss_error": "Ignorați eroarea", "display_options": "Opțiuni de afișare", "display_order": "Ordine de afișare", @@ -550,86 +551,78 @@ "do_not_show_again": "Nu mai afișa acest mesaj", "documentation": "Documentație", "done": "Gata", - "download": "Descarcă", + "download": "Descărcați", "download_include_embedded_motion_videos": "Videoclipuri încorporate", "download_include_embedded_motion_videos_description": "Include videoclipurile încorporate în fotografiile în mișcare ca fișier separat", - "download_settings": "Descarcă", + "download_settings": "Descărcați", "download_settings_description": "Gestionați setările legate de descărcarea resurselor", "downloading": "Se descarcă", "downloading_asset_filename": "Se descarcă resursa {filename}", - "drop_files_to_upload": "Trage fișierele aici pentru a le încărca", + "drop_files_to_upload": "Trageți fișierele aici pentru a le încărca", "duplicates": "Duplicate", "duplicates_description": "Rezolvați fiecare grup indicând care sunt duplicate, dacă există", "duration": "Durată", - "durations": { - "days": "", - "hours": "", - "minutes": "", - "months": "", - "years": "" - }, - "edit": "Modifică", - "edit_album": "Modificare album", - "edit_avatar": "Modificare avatar", - "edit_date": "Modifică data", - "edit_date_and_time": "Modifică data și ora", + "edit": "Editare", + "edit_album": "Editare album", + "edit_avatar": "Editare avatar", + "edit_date": "Editare dată", + "edit_date_and_time": "Editare dată și oră", "edit_exclusion_pattern": "Editarea modelului de excludere", - "edit_faces": "Modifică fețele", - "edit_import_path": "Editarea căii de import", - "edit_import_paths": "Editarea căilor de import", + "edit_faces": "Editare fețe", + "edit_import_path": "Editare cale de import", + "edit_import_paths": "Editare căi de import", "edit_key": "Tastă de editare", - "edit_link": "Modifică link", - "edit_location": "Editează locație", - "edit_name": "Editează nume", - "edit_people": "Editează persoane", - "edit_tag": "Modifică etichetă", - "edit_title": "Editează Titlul", - "edit_user": "Modifică utilizator", + "edit_link": "Editare link", + "edit_location": "Editare locație", + "edit_name": "Editare nume", + "edit_people": "Editare persoane", + "edit_tag": "Editare etichetă", + "edit_title": "Editare Titlu", + "edit_user": "Editare utilizator", "edited": "Editat", "editor": "Editor", "editor_close_without_save_prompt": "Schimbările nu vor fi salvate", - "editor_close_without_save_title": "Închizi editorul?", + "editor_close_without_save_title": "Închideți editorul?", "editor_crop_tool_h2_aspect_ratios": "Raporturi de aspect", "editor_crop_tool_h2_rotation": "Rotire", "email": "Email", - "empty": "", - "empty_album": "", - "empty_trash": "Golește coșul", - "empty_trash_confirmation": "Sunteți sigur că doriți să goliți coșul de gunoi? Acest lucru va elimina definitiv din Immich toate bunurile din coșul de gunoi.\nNu puteți anula această acțiune!", - "enable": "Activează", + "empty_trash": "Goliți coșul de gunoi", + "empty_trash_confirmation": "Sunteți sigur că doriți să goliți coșul de gunoi? Acest lucru va elimina definitiv din Immich toate resursele din coșul de gunoi.\nNu puteți anula această acțiune!", + "enable": "Permite", "enabled": "Activat", "end_date": "Data de încheiere", "error": "Eroare", - "error_loading_image": "Eroare la incarcarea fotografiei", - "error_title": "Eroare - Ceva nu a mers", + "error_loading_image": "Eroare la încărcarea imaginii", + "error_title": "Eroare - ceva nu a mers", "errors": { - "cannot_navigate_next_asset": "Nu se poate naviga către următorul activ", - "cannot_navigate_previous_asset": "Nu se poate naviga la activul anterior", + "cannot_navigate_next_asset": "Nu se poate naviga către următoarea resursă", + "cannot_navigate_previous_asset": "Nu se poate naviga la resursa anterioară", "cant_apply_changes": "Nu se pot aplica schimbări", "cant_change_activity": "Nu se poate {enabled, select, true {dezactiva} other {activa}} activitatea", - "cant_change_asset_favorite": "Nu pot schimba favoritul pentru activ", - "cant_change_metadata_assets_count": "Nu se pot modifica metadatele pentru {count, plural, one {# element} other {# elemente}}", + "cant_change_asset_favorite": "Nu pot schimba favoritul pentru resursa", + "cant_change_metadata_assets_count": "Nu se pot modifica metadatele pentru {count, plural, one {# resursa} other {# resurse}}", "cant_get_faces": "Nu pot obține fețe", "cant_get_number_of_comments": "Nu pot obține numărul de comentarii", "cant_search_people": "Nu pot căuta oameni", "cant_search_places": "Nu se pot căuta locații", - "cleared_jobs": "Joburi terminate pentru: {job}", - "error_adding_assets_to_album": "Eroare la adăugarea activelor la album", + "cleared_jobs": "Sarcini terminate pentru: {job}", + "error_adding_assets_to_album": "Eroare la adăugarea resurselor la album", "error_adding_users_to_album": "Eroare la adăugarea utilizatorilor la album", "error_deleting_shared_user": "Eroare la ștergerea utilizatorului partajat", "error_downloading": "Eroare la descărcarea {filename}", "error_hiding_buy_button": "Eroare la ascunderea butonului de cumpărare", - "error_removing_assets_from_album": "Eroare la eliminarea activelor din album, verificați consola pentru mai multe detalii", - "error_selecting_all_assets": "Eroare la selectarea tuturor activelor", + "error_removing_assets_from_album": "Eroare la eliminarea resurselor din album, verificați consola pentru mai multe detalii", + "error_selecting_all_assets": "Eroare la selectarea tuturor resurselor", "exclusion_pattern_already_exists": "Acest model de excludere există deja.", - "failed_job_command": "Comanda {command} a eșuat pentru job: {job}", + "failed_job_command": "Comanda {command} a eșuat pentru sarcina: {job}", "failed_to_create_album": "A eșuat crearea albumului", "failed_to_create_shared_link": "A eșuat crearea legăturii partajate", "failed_to_edit_shared_link": "A eșuat editarea legăturii partajate", "failed_to_get_people": "Eșec la obținerea persoanelor", + "failed_to_keep_this_delete_others": "Nu s-a putut păstra acest material respectiv nu s-au putut șterge celelalte materiale", "failed_to_load_asset": "Eșec la încărcarea resursei", "failed_to_load_assets": "Eșec la încărcarea resurselor", - "failed_to_load_people": "Eșec la încărcarea oamenilor", + "failed_to_load_people": "Eșec la încărcarea persoanelor", "failed_to_remove_product_key": "Eșec la eliminarea cheii de produs", "failed_to_stack_assets": "Eșec la combinarea resurselor", "failed_to_unstack_assets": "Eșec la desfășurarea resurselor", @@ -637,26 +630,24 @@ "incorrect_email_or_password": "E-mail sau parolă incorect/ă", "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": "Ai stabilit o cotă mai mare decât dimensiunea discului", + "quota_higher_than_disk_size": "Ați stabilit o valoare a spațiului de stocare mai mare decât dimensiunea discului", "repair_unable_to_check_items": "Imposibil de verificat {count, select, one {element} other {elemente}}", "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", - "unable_to_add_exclusion_pattern": "Nu se poate adăuga modelul de excluziune", + "unable_to_add_exclusion_pattern": "Nu se poate adăuga modelul de excludere", "unable_to_add_import_path": "Imposibil de adăugat calea de import", - "unable_to_add_partners": "Nu se poate de adăuga parteneri", + "unable_to_add_partners": "Nu se pot adăuga parteneri", "unable_to_add_remove_archive": "Nu se poate {archived, select, true {îndepărta resursa din} other {adăuga resursa în}} arhivă", "unable_to_add_remove_favorites": "Nu se poate {favorite, select, true {adăuga resursa în} other {îndepărta resursa din}} favorite", "unable_to_archive_unarchive": "Nu se poate {archived, select, true {arhiva} other {dezarhiva}}", "unable_to_change_album_user_role": "Nu se poate schimba rolul utilizatorului de album", "unable_to_change_date": "Imposibil de schimbat data", - "unable_to_change_favorite": "Nu se poate modifica favoritele pentru resursă", + "unable_to_change_favorite": "Nu se pot modifica favoritele pentru resursa", "unable_to_change_location": "Imposibil de schimbat locația", "unable_to_change_password": "Imposibil de schimbat parola", "unable_to_change_visibility": "Nu se poate schimba vizibilitatea pentru {count, plural, one {# persoană} other {# persoane}}", - "unable_to_check_item": "", - "unable_to_check_items": "", - "unable_to_complete_oauth_login": "Nu putut fi realizată logarea prin OAuth", + "unable_to_complete_oauth_login": "Nu s-a realizat logarea prin OAuth", "unable_to_connect": "Nu se poate conecta", "unable_to_connect_to_server": "Nu se poate conecta la server", "unable_to_copy_to_clipboard": "Nu poate fi copiat, asigură-te că accesezi pagina prin https", @@ -667,429 +658,683 @@ "unable_to_delete_album": "Nu se poate șterge albumul", "unable_to_delete_asset": "Nu poate fi ștearsă resursa", "unable_to_delete_assets": "Eroare la ștergerea resurselor", + "unable_to_delete_exclusion_pattern": "Nu se poate șterge modelul de excludere", + "unable_to_delete_import_path": "Nu se poate șterge calea de import", + "unable_to_delete_shared_link": "Nu se poate șterge linkul partajat", "unable_to_delete_user": "Nu se poate șterge userul", "unable_to_download_files": "Nu se pot descărca fișierele", - "unable_to_empty_trash": "", - "unable_to_enter_fullscreen": "", - "unable_to_exit_fullscreen": "", + "unable_to_edit_exclusion_pattern": "Nu se poate edita modelul de excludere", + "unable_to_edit_import_path": "Nu se poate edita calea de import", + "unable_to_empty_trash": "Nu se poate goli coșul de gunoi", + "unable_to_enter_fullscreen": "Nu se poate accesa ecranul complet", + "unable_to_exit_fullscreen": "Imposibil de părăsit ecranul complet", + "unable_to_get_comments_number": "Nu se poate obține numărul de comentarii", + "unable_to_get_shared_link": "Nu s-a putut obține linkul partajat", "unable_to_hide_person": "Nu se poate ascunde persoana", + "unable_to_link_motion_video": "Imposibil de conectat videoclipul în mișcare", + "unable_to_link_oauth_account": "Nu se poate conecta contul OAuth", "unable_to_load_album": "Nu se poate încărca albumul", - "unable_to_load_asset_activity": "", - "unable_to_load_items": "", - "unable_to_load_liked_status": "", + "unable_to_load_asset_activity": "Nu se poate încărca activitatea cu materiale", + "unable_to_load_items": "Nu se pot încărca articole", + "unable_to_load_liked_status": "Nu se poate încărca starea de apreciat", + "unable_to_log_out_all_devices": "Nu se pot deconecta toate dispozitivele", + "unable_to_log_out_device": "Nu se poate deconecta dispozitivul", + "unable_to_login_with_oauth": "Nu se poate autentifica cu OAuth", "unable_to_play_video": "Nu se poate reda videoul", - "unable_to_refresh_user": "", + "unable_to_reassign_assets_existing_person": "Nu se pot reatribui elementele către {name, select, null {o persoană existentă} other {{name}}}", + "unable_to_reassign_assets_new_person": "Nu se pot reatribui resurse unei persoane noi", + "unable_to_refresh_user": "Nu se poate reîmprospăta utilizatorul", "unable_to_remove_album_users": "Nu se pot șterge userii din album", "unable_to_remove_api_key": "Nu se poate șterge cheia API", - "unable_to_remove_comment": "", + "unable_to_remove_assets_from_shared_link": "Nu se pot elimina resursele din linkul partajat", "unable_to_remove_deleted_assets": "Nu se pot șterge fișierele offline", "unable_to_remove_library": "Nu se poate șterge biblioteca", - "unable_to_remove_offline_files": "Nu se pot șterge fișierele offline", "unable_to_remove_partner": "Imposibil de eliminat partenerul", - "unable_to_remove_reaction": "Nu se poate elimina reația", - "unable_to_remove_user": "", - "unable_to_repair_items": "Imposibil de a repara elementele", - "unable_to_reset_password": "Imposibil de a reseta parola", - "unable_to_resolve_duplicate": "Nu se poate de rezolvat duplicatul", + "unable_to_remove_reaction": "Nu se poate elimina reacția", + "unable_to_repair_items": "Imposibil de reparat elementele", + "unable_to_reset_password": "Imposibil de resetat parola", + "unable_to_resolve_duplicate": "Nu se poate rezolva duplicatul", "unable_to_restore_assets": "Nu se pot restaura resursele", "unable_to_restore_trash": "Nu se poate restaura coșul de gunoi", "unable_to_restore_user": "Nu se poate restaura utilizatorul", "unable_to_save_album": "Imposibil de salvat albumul", "unable_to_save_api_key": "Imposibil de salvat cheia API", - "unable_to_save_date_of_birth": "Imposibil de a salva data de naștere", - "unable_to_save_name": "Imposibil de a salva numele", - "unable_to_save_profile": "Imposibil de a salva profilul", + "unable_to_save_date_of_birth": "Imposibil de salvat data de naștere", + "unable_to_save_name": "Imposibil de salvat numele", + "unable_to_save_profile": "Imposibil de salvat profilul", "unable_to_save_settings": "Nu se pot salva setările", "unable_to_scan_libraries": "Nu se pot scana librăriile", - "unable_to_scan_library": "Nu se poate de scanat librăria", + "unable_to_scan_library": "Nu se poate scana librăria", "unable_to_set_feature_photo": "Nu se poate seta fotografia principală", "unable_to_set_profile_picture": "Nu se poate seta fotografia de profil", - "unable_to_submit_job": "", - "unable_to_trash_asset": "", - "unable_to_unlink_account": "", + "unable_to_submit_job": "Imposibil de trimis sarcina", + "unable_to_trash_asset": "Nu se poate elimina resursa", + "unable_to_unlink_account": "Nu se poate deconecta contul", + "unable_to_unlink_motion_video": "Imposibil de deconectat videoclipul în mișcare", "unable_to_update_album_cover": "Nu se poate actualiza coperta de album", + "unable_to_update_album_info": "Nu se pot actualiza informațiile albumului", "unable_to_update_library": "Nu se poate actualiza biblioteca", "unable_to_update_location": "Nu se poate actualiza locația", "unable_to_update_settings": "Nu se pot actualiza setările", - "unable_to_update_user": "Nu se poate actualiza utilizatorul" + "unable_to_update_timeline_display_status": "Nu se poate actualiza starea de afișare a cronologiei", + "unable_to_update_user": "Nu se poate actualiza utilizatorul", + "unable_to_upload_file": "Nu se poate încărca fișierul" }, - "every_day_at_onepm": "", - "every_night_at_midnight": "", - "every_night_at_twoam": "", - "every_six_hours": "", - "exit_slideshow": "", - "expand_all": "", + "exif": "Format comutabil pentru fișiere imagine", + "exit_slideshow": "Ieșire din Prezentare", + "expand_all": "Extindeți-le pe toate", "expire_after": "Expiră după", "expired": "Expirat", + "expires_date": "Expiră la {date}", "explore": "Exploreazǎ", + "explorer": "Explorator", + "export": "Exportare", + "export_as_json": "Exportare ca JSON", "extension": "Extensie", "external": "Extern", - "external_libraries": "", - "failed_to_get_people": "", - "favorite": "", - "favorite_or_unfavorite_photo": "", + "external_libraries": "Biblioteci Externe", + "face_unassigned": "Nealocat", + "failed_to_load_assets": "Nu s-au încărcat activele", + "favorite": "Favorit", + "favorite_or_unfavorite_photo": "Fotografie preferată sau nepreferată", "favorites": "Favorite", - "feature": "", - "feature_photo_updated": "", - "featurecollection": "", - "file_name": "", - "file_name_or_extension": "", - "filename": "", - "files": "", - "filetype": "", - "filter_people": "", - "fix_incorrect_match": "", - "force_re-scan_library_files": "", - "forward": "", - "general": "", - "get_help": "", - "getting_started": "", - "go_back": "", - "go_to_search": "", - "go_to_share_page": "", - "group_albums_by": "", - "has_quota": "", - "hide_gallery": "", - "hide_password": "", - "hide_person": "", - "host": "", - "hour": "", - "image": "", - "img": "", - "immich_logo": "", - "import_path": "", - "in_archive": "", + "feature_photo_updated": "Fotografie caracteristică actualizată", + "features": "Caracteristici", + "features_setting_description": "Gestionați funcțiile aplicației", + "file_name": "Nume de fișier", + "file_name_or_extension": "Numele sau extensia fișierului", + "filename": "Numele fișierului", + "filetype": "Tipul fișierului", + "filter_people": "Filtrați persoanele", + "find_them_fast": "Găsiți-le rapid prin căutare după nume", + "fix_incorrect_match": "Remediați potrivirea incorectă", + "folders": "Foldere", + "folders_feature_description": "Răsfoire în conținutul folderului pentru fotografiile și videoclipurile din sistemul de fișiere", + "forward": "Redirecționare", + "general": "General", + "get_help": "Obțineți Ajutor", + "getting_started": "Noțiuni de Bază", + "go_back": "Întoarcere", + "go_to_search": "Spre căutare", + "group_albums_by": "Grupați albume de...", + "group_no": "Fără grupare", + "group_owner": "Grupați după proprietar", + "group_year": "Grupați după an", + "has_quota": "Are spațiu de stocare", + "hi_user": "Bună {name} ({email})", + "hide_all_people": "Ascundeți toate persoanele", + "hide_gallery": "Ascundeți galeria", + "hide_named_person": "Ascundeți persoana {name}", + "hide_password": "Ascundeți parola", + "hide_person": "Ascundeți persoana", + "hide_unnamed_people": "Ascundeți persoanele fără nume", + "host": "Gazdă", + "hour": "Oră", + "image": "Imagine", + "image_alt_text_date": "{isVideo, select, true {Video} other {imagine}} preluată în {date}", + "image_alt_text_date_1_person": "{isVideo, select, true {Video} other {imagine}} preluată cu {person1} în {date}", + "image_alt_text_date_2_people": "{isVideo, select, true {Video} other {imagine}} preluată cu {person1} și {person2} în {date}", + "image_alt_text_date_3_people": "{isVideo, select, true {Video} other {imagine}} preluată cu {person1}, {person2}, și {person3} în {date}", + "image_alt_text_date_4_or_more_people": "{isVideo, select, true {Video} other {imagine}} preluată cu {person1}, {person2}, și {additionalCount, number} alții în {date}", + "image_alt_text_date_place": "{isVideo, select, true {Video} other {imagine}} preluată în {city}, {country} în {date}", + "image_alt_text_date_place_1_person": "{isVideo, select, true {Video} other {imagine}} preluată în {city}, {country} cu {person1} în {date}", + "image_alt_text_date_place_2_people": "{isVideo, select, true {Video} other {imagine}} preluată în {city}, {country} cu {person1} și {person2} în {date}", + "image_alt_text_date_place_3_people": "{isVideo, select, true {Video} other {imagine}} preluată în {city}, {country} cu {person1}, {person2}, și {person3} în {date}", + "image_alt_text_date_place_4_or_more_people": "{isVideo, select, true {Video} other {imagine}} preluată în {city}, {country} cu {person1}, {person2}, și {additionalCount, number} alții în {date}", + "immich_logo": "Logo Immich", + "immich_web_interface": "Interfața Web Immich", + "import_from_json": "Importă din JSON", + "import_path": "Calea de import", + "in_albums": "În {count, plural, one {# album} other {# albume}}", + "in_archive": "În arhivă", "include_archived": "Include resursele arhivate", - "include_shared_albums": "", - "include_shared_partner_assets": "", - "individual_share": "", - "info": "", + "include_shared_albums": "Include albumele partajate", + "include_shared_partner_assets": "Include resursele partenerilor partajați", + "individual_share": "Cota individuală", + "info": "Informație", "interval": { - "day_at_onepm": "", - "hours": "", - "night_at_midnight": "", - "night_at_twoam": "" + "day_at_onepm": "În fiecare zi la ora 13.00", + "hours": "La fiecare {hours, plural, one {oră} other {{hours, number} ore}}", + "night_at_midnight": "În fiecare noapte la miezul nopții", + "night_at_twoam": "În fiecare noapte la 2 dimineața" }, - "invite_people": "", - "invite_to_album": "Invită în album", - "job_settings_description": "", - "jobs": "", - "keep": "", - "keyboard_shortcuts": "", - "language": "", - "language_setting_description": "", - "last_seen": "", - "leave": "", + "invite_people": "Invitați Persoane", + "invite_to_album": "Invitați în album", + "items_count": "{count, plural, one {# element} other{# elemente}}", + "jobs": "Sarcini", + "keep": "Păstrați", + "keep_all": "Păstrați Tot", + "keep_this_delete_others": "Păstrați asta, ștergeți celelalte", + "kept_this_deleted_others": "S-a păstrat acest material și s-au șters {count, plural, one {# material} other {# materiale}}", + "keyboard_shortcuts": "Comenzi rapide de tastatură", + "language": "Limbă", + "language_setting_description": "Selectați limba preferată", + "last_seen": "Văzut ultima dată", + "latest_version": "Ultima Versiune", + "latitude": "Latitudine", + "leave": "Părăsiți", "let_others_respond": "Permite altora să răspundă", - "level": "", + "level": "Nivel", "library": "Librărie", - "library_options": "", - "light": "", - "link_options": "", - "link_to_oauth": "", - "linked_oauth_account": "", - "list": "", - "loading": "", - "loading_search_results_failed": "", + "library_options": "Opțiuni de bibliotecă", + "light": "Lumină", + "like_deleted": "Preferat șters", + "link_motion_video": "Link video în mișcare", + "link_options": "Opțiuni de link", + "link_to_oauth": "Link către OAuth", + "linked_oauth_account": "Cont OAuth conectat", + "list": "Listă", + "loading": "Încărcare", + "loading_search_results_failed": "Încărcarea rezultatelor căutării nu a reușit", "log_out": "Deconectare", - "log_out_all_devices": "", - "login_has_been_disabled": "", - "look": "", - "loop_videos": "", - "loop_videos_description": "", - "make": "", - "manage_shared_links": "Administrează link-urile distribuite", - "manage_sharing_with_partners": "", - "manage_the_app_settings": "", - "manage_your_account": "", - "manage_your_api_keys": "", - "manage_your_devices": "", - "manage_your_oauth_connection": "", - "map": "", - "map_marker_with_image": "", + "log_out_all_devices": "Deconectați-vă de la toate dispozitivele", + "logged_out_all_devices": "S-au deconectat toate dispozitivele", + "logged_out_device": "Dispozitiv deconectat", + "login": "Conectare", + "login_has_been_disabled": "Conectarea a fost dezactivată.", + "logout_all_device_confirmation": "Sigur doriți să deconectați toate dispozitivele?", + "logout_this_device_confirmation": "Sigur doriți să deconectați acest dispozitiv?", + "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!", + "make": "Face", + "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", + "manage_your_account": "Gestionați-vă contul", + "manage_your_api_keys": "Gestionați-vă cheile API", + "manage_your_devices": "Gestionați-vă dispozitivele conectate", + "manage_your_oauth_connection": "Gestionați-vă conexiunea OAuth", + "map": "Hartă", + "map_marker_for_images": "Marcator de hartă pentru imaginile realizate în {city}, {country}", + "map_marker_with_image": "Marcator de hartă cu imagine", "map_settings": "Setările hărții", - "media_type": "Tip fișier", + "matches": "Corespunde", + "media_type": "Tip media", "memories": "Amintiri", - "memories_setting_description": "Administreazǎ ce vezi în amintiri", + "memories_setting_description": "Administrați ce vedeți în amintiri", "memory": "Amintire", + "memory_lane_title": "Banda Memoriei {title}", "menu": "Meniu", - "merge": "", - "merge_people": "", - "merge_people_successfully": "", - "minimize": "", - "minute": "", - "missing": "Absente", + "merge": "Îmbinați", + "merge_people": "Îmbinați persoane", + "merge_people_limit": "Puteți îmbina până la 5 fețe simultan", + "merge_people_prompt": "Vreți să îmbinați aceste persoane? Această acțiune este ireversibilă.", + "merge_people_successfully": "Persoane îmbinate cu succes", + "merged_people_count": "Imbinate {count, plural, one {# persoană} other {# persoane}}", + "minimize": "Minimizare", + "minute": "Minute", + "missing": "Lipsă", "model": "Model", "month": "Lună", - "more": "Mai multe", - "moved_to_trash": "", + "more": "Mai mult", + "moved_to_trash": "Mutat în coșul de gunoi", "my_albums": "Albumele mele", "name": "Nume", "name_or_nickname": "Nume sau poreclǎ", "never": "Niciodată", + "new_album": "Album Nou", "new_api_key": "Cheie API nouǎ", "new_password": "Parolă nouă", "new_person": "Persoanǎ nouǎ", "new_user_created": "Utilizator nou creat", - "newest_first": "", + "new_version_available": "VERSIUNE NOUĂ DISPONIBILĂ", + "newest_first": "Cel mai nou primul", "next": "Următorul", - "next_memory": "", - "no": "", - "no_albums_message": "", - "no_archived_assets_message": "", - "no_assets_message": "", - "no_exif_info_available": "", - "no_explore_results_message": "", - "no_favorites_message": "", - "no_libraries_message": "", - "no_name": "", - "no_places": "", - "no_results": "", - "no_shared_albums_message": "", - "not_in_any_album": "", - "notes": "", - "notification_toggle_setting_description": "", + "next_memory": "Următoarea amintire", + "no": "Nu", + "no_albums_message": "Creați un album pentru a vă organiza fotografiile și videoclipurile", + "no_albums_with_name_yet": "Se pare că nu aveți încă niciun album cu acest nume.", + "no_albums_yet": "Se pare că nu aveți încă niciun album.", + "no_archived_assets_message": "Arhivați fotografii și videoclipuri pentru a le ascunde din vizualizarea fotografii", + "no_assets_message": "CLICK PENTRU A ÎNCĂRCA PRIMA TA FOTOGRAFIE", + "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_name": "Fără Nume", + "no_places": "Nu există locuri", + "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", + "not_in_any_album": "Nu există în niciun album", + "note_apply_storage_label_to_previously_uploaded assets": "Notă: Pentru a aplica eticheta de stocare la resursele încărcate anterior, rulați", + "note_unlimited_quota": "Notă: Introduceți 0 pentru spațiu pe disc nelimitat", + "notes": "Note", + "notification_toggle_setting_description": "Activați notificările prin email", "notifications": "Notificări", - "notifications_setting_description": "", - "oauth": "", - "offline": "", - "ok": "", - "oldest_first": "", - "online": "", - "only_favorites": "", - "only_refreshes_modified_files": "", - "open_the_search_filters": "", + "notifications_setting_description": "Gestionați notificările", + "oauth": "OAuth", + "official_immich_resources": "Resurse Oficiale Immich", + "offline": "Offline", + "offline_paths": "Căi offline", + "offline_paths_description": "Aceste rezultate se pot datora ștergerii manuale a fișierelor care nu fac parte dintr-o bibliotecă externă.", + "ok": "Bine", + "oldest_first": "Cel mai vechi mai întâi", + "onboarding": "Integrare", + "onboarding_privacy_description": "Următoarele caracteristici (opționale) se bazează pe servicii externe și pot fi dezactivate în orice moment din setările de administrare.", + "onboarding_theme_description": "Alegeți o temă de culoare pentru exemplul dvs. Puteți modifica acest lucru mai târziu în setări.", + "onboarding_welcome_description": "Să vă setăm instanța cu câteva setări comune.", + "onboarding_welcome_user": "Bun venit, {user}", + "online": "Online", + "only_favorites": "Doar favorite", + "open_in_map_view": "Deschideți în vizualizarea hărții", + "open_in_openstreetmap": "Deschideți în OpenStreetMap", + "open_the_search_filters": "Deschideți filtrele de căutare", "options": "Opțiuni", - "organize_your_library": "", - "other": "", - "other_devices": "", - "other_variables": "", + "or": "sau", + "organize_your_library": "Organizează-ți biblioteca", + "original": "original", + "other": "Alte", + "other_devices": "Alte dispozitive", + "other_variables": "Alte variabile", "owned": "Deținut", - "owner": "Admin", + "owner": "Proprietar", "partner": "Partener", - "partner_sharing": "", - "partners": "", + "partner_can_access": "{partner} poate accesa", + "partner_can_access_assets": "Toate fotografiile și videoclipurile tale, cu excepția celor din arhivate și sterse", + "partner_can_access_location": "Locația în care au fost făcute fotografiile dvs", + "partner_sharing": "Partajarea Partenerilor", + "partners": "Parteneri", "password": "Parolă", - "password_does_not_match": "", - "password_required": "", - "password_reset_success": "", + "password_does_not_match": "Parola nu se potrivește", + "password_required": "Parola Obligatorie", + "password_reset_success": "Resetarea parolei efectuată cu succes", "past_durations": { - "days": "", - "hours": "", - "years": "" + "days": "Ultimele {days, plural, one {zi} other {# zile}}", + "hours": "Ultimele {hours, plural, one {oră} other {# ore}}", + "years": "Ultimii {years, plural, one {an} other {# ani}}" }, - "path": "", - "pattern": "", - "pause": "", - "pause_memories": "", - "paused": "", - "pending": "", + "path": "Cale", + "pattern": "Tipar", + "pause": "Pauză", + "pause_memories": "Opriți amintirile", + "paused": "Întrerupt", + "pending": "În așteptare", "people": "Persoane", - "people_sidebar_description": "", - "perform_library_tasks": "", - "permanent_deletion_warning": "", - "permanent_deletion_warning_setting_description": "", - "permanently_delete": "", - "permanently_deleted_asset": "", + "people_edits_count": "Editat {count, plural, one {# persoană} other {# persoane}}", + "people_feature_description": "Răsfoiți fotografii și videoclipuri grupate după persoane", + "people_sidebar_description": "Afișează un link către persoane în bara laterală", + "permanent_deletion_warning": "Avertisment de ștergere permanentă", + "permanent_deletion_warning_setting_description": "Afișează un avertisment la ștergerea definitivă a resurselor", + "permanently_delete": "Ștergeți definitiv", + "permanently_delete_assets_count": "Ștergeți definitiv {count, plural, one {resursă} other {resurse}}", + "permanently_delete_assets_prompt": "Sigur doriți să ștergeți definitiv {count, plural, one {această resursă?} other {aceste # resurse?}} Acest lucru va elimina și {count, plural, one {din ea} other {din ele}} album(e).", + "permanently_deleted_asset": "Resursă ștearsă definitiv", + "permanently_deleted_assets_count": "S-au șters definitiv {count, plural, one {# resursă} other {# resurse}}", "person": "Persoanǎ", + "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.", "photos": "Fotografii", - "photos_from_previous_years": "", - "pick_a_location": "", - "place": "", + "photos_and_videos": "Fotografii și Videoclipuri", + "photos_count": "{count, plural, one {{count, number} imagine} other{{count, number} imagini}}", + "photos_from_previous_years": "Fotografii din anii anteriori", + "pick_a_location": "Alegeți o locație", + "place": "Loc", "places": "Locații", - "play": "", - "play_memories": "", - "play_motion_photo": "", - "play_or_pause_video": "", - "point": "", - "port": "", - "preset": "", - "preview": "", - "previous": "", - "previous_memory": "", - "previous_or_next_photo": "", - "primary": "", - "profile_picture_set": "", - "public_share": "", - "range": "", - "raw": "", - "reaction_options": "", - "read_changelog": "", - "recent": "", - "recent_searches": "", - "refresh": "", - "refreshed": "", - "refreshes_every_file": "", - "remove": "", - "remove_deleted_assets": "", - "remove_from_album": "Șterge din album", - "remove_from_favorites": "", - "remove_from_shared_link": "", - "repair": "", - "repair_no_results_message": "", - "replace_with_upload": "", - "require_password": "", - "reset": "", - "reset_password": "", - "reset_people_visibility": "", - "reset_settings_to_default": "", - "restore": "Restaurează", - "restore_user": "", - "retry_upload": "", - "review_duplicates": "", - "role": "", - "save": "Salvează", - "saved_profile": "", - "saved_settings": "", - "say_something": "Spune ceva", - "scan_all_libraries": "", - "scan_all_library_files": "", - "scan_new_library_files": "", - "scan_settings": "", - "search": "Caută", - "search_albums": "", - "search_by_context": "", - "search_camera_make": "", - "search_camera_model": "", - "search_city": "", - "search_country": "", - "search_for_existing_person": "", - "search_people": "", - "search_places": "", - "search_state": "", - "search_timezone": "", + "play": "Redare", + "play_memories": "Redare amintiri", + "play_motion_photo": "Redare Fotografie în Mișcare", + "play_or_pause_video": "Redați sau întrerupeți videoclipul", + "port": "Port", + "preset": "Presetat", + "preview": "Previzualizare", + "previous": "Anterior", + "previous_memory": "Memoria anterioară", + "previous_or_next_photo": "Poza anterioară sau următoare", + "primary": "Primar", + "privacy": "Confidențialitate", + "profile_image_of_user": "Imagine de profil a lui {user}", + "profile_picture_set": "Poză de profil setată.", + "public_album": "Album public", + "public_share": "Distribuire Publică", + "purchase_account_info": "Suporter", + "purchase_activated_subtitle": "Vă mulțumim că susțineți Immich și software-ul open-source", + "purchase_activated_time": "Activat pe data de {date, date}", + "purchase_activated_title": "Cheia dvs. a fost activată cu succes", + "purchase_button_activate": "Activați", + "purchase_button_buy": "Cumpărați", + "purchase_button_buy_immich": "Cumpărați Immich", + "purchase_button_never_show_again": "Nu mai arăta niciodată", + "purchase_button_reminder": "Amintește-mi în 30 de zile", + "purchase_button_remove_key": "Eliminați cheia", + "purchase_button_select": "Selectare", + "purchase_failed_activation": "Activare eșuată! Vă rugăm să vă verificați e-mailul pentru cheia de produs corectă!", + "purchase_individual_description_1": "Pentru un individ", + "purchase_individual_description_2": "Statutul de suporter", + "purchase_individual_title": "Individual", + "purchase_input_suggestion": "Aveți o cheie de produs? Introduceți cheia mai jos", + "purchase_license_subtitle": "Cumpărați Immich pentru a sprijini dezvoltarea continuă a serviciului", + "purchase_lifetime_description": "Achiziție pe viață", + "purchase_option_title": "OPȚIUNI DE CUMPĂRARE", + "purchase_panel_info_1": "Dezvoltarea Immich necesită mult timp și efort și avem ingineri cu normă întreagă care lucrează la ea pentru a o face cât se poate de bună. Misiunea noastră este ca software-ul open-source și practicile de afaceri etice să devină o sursă de venit durabilă pentru dezvoltatori și să se creeze un ecosistem care să respecte confidențialitatea, cu alternative reale la serviciile cloud care exploatează.", + "purchase_panel_info_2": "Deoarece ne-am angajat să nu adăugăm planuri de plată, această achiziție nu vă va oferi nicio funcție suplimentară în Immich. Ne bazăm pe utilizatori ca dvs. pentru a sprijini dezvoltarea continuă a lui Immich.", + "purchase_panel_title": "Susțineți proiectul", + "purchase_per_server": "Per server", + "purchase_per_user": "Per user", + "purchase_remove_product_key": "Eliminați Cheia Produsului", + "purchase_remove_product_key_prompt": "Sigur doriți să eliminați cheia de produs?", + "purchase_remove_server_product_key": "Eliminați cheia de produs a Serverului", + "purchase_remove_server_product_key_prompt": "Sigur doriți să eliminați cheia de produs a Serverului?", + "purchase_server_description_1": "Pentru tot serverul", + "purchase_server_description_2": "Statutul de suporter", + "purchase_server_title": "Server", + "purchase_settings_server_activated": "Cheia de produs a serverului este gestionată de administrator", + "rating": "Evaluare cu stele", + "rating_clear": "Anulați evaluare", + "rating_count": "{count, plural, one {# stea} other {# stele}}", + "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", + "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", + "reassing_hint": "Atribuiți resursele selectate unei persoane existente", + "recent": "Recent", + "recent-albums": "Albume recente", + "recent_searches": "Căutări recente", + "refresh": "Reîmprospătare", + "refresh_encoded_videos": "Actualizează videoclipurile codificate", + "refresh_faces": "Reîmprospătați fețele", + "refresh_metadata": "Actualizați metadatele", + "refresh_thumbnails": "Reîmprospătați miniaturile", + "refreshed": "Reîmprospătat", + "refreshes_every_file": "Recitește toate fișierele existente și noi", + "refreshing_encoded_video": "Se reîmprospătează videoclipul codificat", + "refreshing_faces": "Se reîmprospătează fețele", + "refreshing_metadata": "Se reîmprospătează metadatele", + "regenerating_thumbnails": "Se regenerează miniaturile", + "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?", + "remove_assets_title": "Eliminați resursele?", + "remove_custom_date_range": "Eliminați intervalul de date personalizat", + "remove_deleted_assets": "Eliminați Resursele Șterse", + "remove_from_album": "Ștergeți din album", + "remove_from_favorites": "Eliminați din favorite", + "remove_from_shared_link": "Eliminați din linkul partajat", + "remove_url": "Eliminați adresa URL", + "remove_user": "Eliminați utilizatorul", + "removed_api_key": "Cheie API eliminată: {name}", + "removed_from_archive": "Eliminat din arhivă", + "removed_from_favorites": "Eliminat din favorite", + "removed_from_favorites_count": "{count, plural, other {Eliminat #}} din favorite", + "removed_tagged_assets": "Eticheta a fost eliminată din {count, plural, one {# resursă} other {# resurse}}", + "rename": "Redenumiți", + "repair": "Reparați", + "repair_no_results_message": "Fișierele neurmărite și lipsă vor apărea aici", + "replace_with_upload": "Înlocuiți cu încărcare", + "repository": "Repertoriu", + "require_password": "Necesită parolă", + "require_user_to_change_password_on_first_login": "Solicitați utilizatorului să schimbe parola la prima conectare", + "reset": "Resetare", + "reset_password": "Resetare parolă", + "reset_people_visibility": "Resetați vizibilitatea persoanelor", + "reset_to_default": "Resetați la valoarea implicită", + "resolve_duplicates": "Rezolvați duplicatele", + "resolved_all_duplicates": "Rezolvați toate duplicatele", + "restore": "Restaurați", + "restore_all": "Restaurați toate", + "restore_user": "Restabiliți utilizatorul", + "restored_asset": "Resursă restaurată", + "resume": "Reluare", + "retry_upload": "Reîncercați încărcarea", + "review_duplicates": "Examinați duplicatele", + "role": "Rol", + "role_editor": "Editor", + "role_viewer": "Vizualizator", + "save": "Salvați", + "saved_api_key": "Cheie API salvată", + "saved_profile": "Profil salvat", + "saved_settings": "Setări salvate", + "say_something": "Spuneți ceva", + "scan_all_libraries": "Scanați Toate Bibliotecile", + "scan_library": "Scanare", + "scan_settings": "Setări Scanare", + "scanning_for_album": "Se scanează după album...", + "search": "Căutați", + "search_albums": "Căutați albume", + "search_by_context": "Căutați după context", + "search_by_filename": "Căutați după numele fișierului sau extensie", + "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_for_existing_person": "Se caută o persoană existentă", + "search_no_people": "Fără persoane", + "search_no_people_named": "Nicio persoană numită \"{name}\"", + "search_options": "Opțiuni de căutare", + "search_people": "Căutați oameni", + "search_places": "Căutați locuri", + "search_settings": "Setări de căutare", + "search_state": "Starea căutării...", + "search_tags": "Căutați etichete...", + "search_timezone": "Căutați fusul orar...", "search_type": "Tip cǎutare", - "search_your_photos": "Căutare fotografii", - "searching_locales": "", + "search_your_photos": "Căutarea fotografiilor dvs", + "searching_locales": "Se caută regionale...", "second": "Secundǎ", - "select_album_cover": "", - "select_all": "", - "select_all_duplicates": "Selecteazǎ toate duplicatele", - "select_avatar_color": "", - "select_face": "Selecteazǎ fațǎ", - "select_featured_photo": "", - "select_from_computer": "Selecteazǎ din calculator", - "select_keep_all": "Selecteazǎ tot pentru salvare", - "select_library_owner": "Selecteazǎ proprietarul bibliotecii", - "select_new_face": "Selecteazǎ o nouǎ fațǎ", - "select_photos": "Selectează fotografii", - "select_trash_all": "Selecteazǎ tot pentru ștergere", - "selected": "Selectați", - "send_message": "", - "server": "", - "server_stats": "", - "set": "", - "set_as_album_cover": "", - "set_as_profile_picture": "", - "set_date_of_birth": "", - "set_profile_picture": "", - "set_slideshow_to_fullscreen": "", + "see_all_people": "Vizualizați toate persoanele", + "select_album_cover": "Selectați coperta albumului", + "select_all": "Selectați tot", + "select_all_duplicates": "Selectați toate duplicatele", + "select_avatar_color": "Selectați culoarea avatarului", + "select_face": "Selectați fața", + "select_featured_photo": "Selectați fotografia recomandată", + "select_from_computer": "Selectați din calculator", + "select_keep_all": "Selectați tot pentru păstrare", + "select_library_owner": "Selectați proprietarul bibliotecii", + "select_new_face": "Selectați o nouǎ fațǎ", + "select_photos": "Selectați fotografii", + "select_trash_all": "Selectați tot pentru ștergere", + "selected": "Selectat", + "selected_count": "{count, plural, other {# selectat}}", + "send_message": "Trimiteți mesaj", + "send_welcome_email": "Trimiteți email de bun venit", + "server_offline": "Server Offline", + "server_online": "Server Online", + "server_stats": "Statistici Server", + "server_version": "Versiune Server", + "set": "Setați", + "set_as_album_cover": "Setați ca și copertă a albumului", + "set_as_profile_picture": "Setați ca imagine de profil", + "set_date_of_birth": "Setați data nașterii", + "set_profile_picture": "Setați poza de profil", + "set_slideshow_to_fullscreen": "Setați Prezentare de Diapozitive la ecran complet", "settings": "Setări", - "settings_saved": "", - "share": "Distribuie", - "shared": "Distribuit", - "shared_by": "", - "shared_by_you": "", + "settings_saved": "Setările au fost salvate", + "share": "Distribuiți", + "shared": "Partajat", + "shared_by": "Partajat de", + "shared_by_user": "Partajat de {user}", + "shared_by_you": "Partajat de tine", + "shared_from_partner": "Fotografii de la {partner}", + "shared_link_options": "Opțiuni de link partajat", "shared_links": "Link-uri distribuite", + "shared_photos_and_videos_count": "{assetCount, plural, other {# fotografii și videoclipuri partajate.}}", + "shared_with_partner": "Partajat cu {partner}", "sharing": "Distribuire", - "sharing_sidebar_description": "", - "show_album_options": "", - "show_file_location": "", - "show_gallery": "", - "show_hidden_people": "", - "show_in_timeline": "", - "show_in_timeline_setting_description": "", - "show_keyboard_shortcuts": "", - "show_metadata": "Arată metadata", - "show_or_hide_info": "", - "show_password": "", - "show_person_options": "", - "show_progress_bar": "", - "show_search_options": "", - "shuffle": "", - "sign_up": "", - "size": "", - "skip_to_content": "", - "slideshow": "", - "slideshow_settings": "", - "sort_albums_by": "", - "stack": "Grup", - "stack_selected_photos": "", - "stacktrace": "", - "start_date": "", - "state": "", - "status": "", - "stop_motion_photo": "", - "stop_photo_sharing": "Încetezi distribuirea fotografiilor?", + "sharing_enter_password": "Vă rugăm să introduceți parola pentru a vizualiza această pagină.", + "sharing_sidebar_description": "Afișați un link către Partajare în bara laterală", + "shift_to_permanent_delete": "apăsați ⇧ pentru a șterge definitiv elementul", + "show_album_options": "Afișați opțiunile de album", + "show_albums": "Afișați albume", + "show_all_people": "Aratați toate persoanele", + "show_and_hide_people": "Afișați și ascundeți persoane", + "show_file_location": "Afișați locația fișierului", + "show_gallery": "Afișați galeria", + "show_hidden_people": "Arătați persoanele ascunse", + "show_in_timeline": "Afișați în cronologie", + "show_in_timeline_setting_description": "Afișați fotografii și videoclipuri de la acest utilizator în cronologia dvs", + "show_keyboard_shortcuts": "Afișați comenzile rapide de la tastatură", + "show_metadata": "Arătați metadatele", + "show_or_hide_info": "Afișați sau ascundeți informații", + "show_password": "Afișați parola", + "show_person_options": "Afișați opțiunile persoanelor", + "show_progress_bar": "Afișați Bara de Progres", + "show_search_options": "Afișați opțiunile de căutare", + "show_slideshow_transition": "Afișați tranziția de prezentare", + "show_supporter_badge": "Insigna suporterului", + "show_supporter_badge_description": "Arată o insignă de suporter", + "shuffle": "Amestecați", + "sidebar": "Bara laterală", + "sidebar_display_description": "Afișați un link către vizualizare în bara laterală", + "sign_out": "Vă deconectați", + "sign_up": "Vă înregistrați", + "size": "Dimensiune", + "skip_to_content": "Treceți la conținut", + "skip_to_folders": "Treceți la foldere", + "skip_to_tags": "Treceți la etichete", + "slideshow": "Prezentare de diapozitive", + "slideshow_settings": "Setări pentru prezentarea de diapozitive", + "sort_albums_by": "Sortați albumele după...", + "sort_created": "Data creării", + "sort_items": "Numărul de articole", + "sort_modified": "Data modificării", + "sort_oldest": "Cea mai veche fotografie", + "sort_recent": "Cea mai recentă fotografie", + "sort_title": "Titlu", + "source": "Sursă", + "stack": "Stivă", + "stack_duplicates": "Duplicate stive", + "stack_select_one_photo": "Selectați o fotografie principală pentru stivă", + "stack_selected_photos": "Fotografie stivă selectată", + "stacked_assets_count": "Stivuite {count, plural, one {# resursă} other {# resurse}}", + "stacktrace": "Urmă stivă", + "start": "Început", + "start_date": "Data de începere", + "state": "Situaţie", + "status": "Stare", + "stop_motion_photo": "Opriți Fotografia in Mișcare", + "stop_photo_sharing": "Încetați distribuirea fotografiilor?", + "stop_photo_sharing_description": "{partner} nu va mai putea accesa fotografiile dvs.", + "stop_sharing_photos_with_user": "Nu mai partajați fotografiile cu acest utilizator", "storage": "Spațiu de stocare", - "storage_label": "", + "storage_label": "Eticheta de depozitare", "storage_usage": "{used} din {available} utilizați", - "submit": "", + "submit": "Trimiteți", "suggestions": "Sugestii", "sunrise_on_the_beach": "Rǎsǎrit pe plajǎ", - "swap_merge_direction": "", + "support": "Suport tehnic", + "support_and_feedback": "Suport tehnic și feedback", + "support_third_party_description": "Instalarea dvs. Immich a fost pregătită de o terță parte. Problemele pe care le întâmpinați pot fi cauzate de acel pachet, așa că vă rugăm să ridicați probleme cu ei în primă instanță utilizând linkurile de mai jos.", + "swap_merge_direction": "Schimbați direcția de îmbinare", "sync": "Sincronizare", - "template": "", + "tag": "Etichetă", + "tag_assets": "Eticheta resurselor", + "tag_created": "Etichetă creată: {tag}", + "tag_feature_description": "Răsfoirea fotografiilor și videoclipurilor grupate după subiecte de etichete logice", + "tag_not_found_question": "Nu puteți găsi o etichetă? Creați o etichetă nouă.", + "tag_updated": "Etichetă actualizată: {tag}", + "tagged_assets": "Etichetat {count, plural, one {# resursă} other {# resurse}}", + "tags": "Etichete", + "template": "Șablon", "theme": "Temă", - "theme_selection": "", - "theme_selection_description": "", - "time_based_memories": "", + "theme_selection": "Selectarea temei", + "theme_selection_description": "Setați automat tema la mod luminos sau întunecată, în funcție de preferințele de sistem ale browserului dvs", + "they_will_be_merged_together": "Vor fi îmbinate împreună", + "third_party_resources": "Resurse Terță Parte", + "time_based_memories": "Amintiri bazate pe timp", + "timeline": "Cronologie", "timezone": "Fus orar", + "to_archive": "Arhivă", + "to_change_password": "Schimbaţi parola", "to_favorite": "Favorit", - "toggle_settings": "", - "toggle_theme": "", - "toggle_visibility": "", - "total_usage": "", - "trash": "Coș", - "trash_all": "Șterge tot", - "trash_count": "Șterge {count, number}", - "trash_no_results_message": "", - "type": "", - "unarchive": "Șterge din arhivă", - "unarchived": "", - "unfavorite": "Șterge din favorite", - "unhide_person": "", - "unknown": "", - "unknown_album": "", - "unknown_year": "", - "unlink_oauth": "", - "unlinked_oauth_account": "", - "unselect_all": "", - "unstack": "Anulează grup", - "up_next": "", - "updated_password": "", - "upload": "Încarcă", - "upload_concurrency": "", - "url": "", - "usage": "", - "user": "", - "user_id": "", - "user_usage_detail": "", - "username": "", + "to_login": "Conectare", + "to_parent": "Du-te la părinte", + "to_trash": "Coș de gunoi", + "toggle_settings": "Activați setările", + "toggle_theme": "Activați tema întunecată", + "total": "Total", + "total_usage": "Utilizare totală", + "trash": "Coș de gunoi", + "trash_all": "Ștergeți Tot", + "trash_count": "Ștergeți {count, number}", + "trash_delete_asset": "Coș de gunoi/Ștergeți resursa", + "trash_no_results_message": "Fotografiile și videoclipurile mutate în coșul de gunoi vor apărea aici.", + "trashed_items_will_be_permanently_deleted_after": "Elementele din coșul de gunoi vor fi șterse definitiv după {days, plural, one {# zi} other {# zile}}.", + "type": "Tip", + "unarchive": "Dezarhivați", + "unarchived_count": "{count, plural, other {dezarhivat #}}", + "unfavorite": "Ștergeți din favorite", + "unhide_person": "Dezvăluie persoana", + "unknown": "Necunoscut", + "unknown_year": "An Necunoscut", + "unlimited": "Nelimitat", + "unlink_motion_video": "Deconectați videoclipul în mișcare", + "unlink_oauth": "Deconectați OAuth", + "unlinked_oauth_account": "Cont OAuth deconectat", + "unnamed_album": "Album fără Nume", + "unnamed_album_delete_confirmation": "Sigur doriți să ștergeți acest album?", + "unnamed_share": "Partajare fără Nume", + "unsaved_change": "Modificare nesalvată", + "unselect_all": "Deselectați toate", + "unselect_all_duplicates": "Deselectați toate duplicatele", + "unstack": "Dezasamblați", + "unstacked_assets_count": "Nestivuit {count, plural, one {# resursă} other {# resurse}}", + "untracked_files": "Fișiere neurmărite", + "untracked_files_decription": "Aceste fișiere nu sunt urmărite de aplicație. Acestea pot fi rezultatele unor mișcări eșuate, încărcări întrerupte sau rămase din cauza unei erori", + "up_next": "Mai departe", + "updated_password": "Parolă actualizată", + "upload": "Încărcați", + "upload_concurrency": "Încărcați simultan", + "upload_errors": "Încărcare finalizată cu {count, plural, one {# eroare} other {# erori}}, reîmprospătați pagina pentru a reîncărca noile resurse.", + "upload_progress": "Rămas {remaining, number} - Procesat {processed, number}/{total, number}", + "upload_skipped_duplicates": "Sărit {count, plural, one {# duplicat resursă} other {# duplicate resurse}}", + "upload_status_duplicates": "Duplicate", + "upload_status_errors": "Erori", + "upload_status_uploaded": "Încărcat", + "upload_success": "Încărcare reușită, reîmprospătați pagina pentru a vedea resursele noi încărcate.", + "url": "URL", + "usage": "Utilizare", + "use_custom_date_range": "Utilizați în schimb un interval de date personalizat", + "user": "Utilizator", + "user_id": "ID utilizator", + "user_liked": "{user} a apreciat {type, select, photo {această imagine} video {acest video} asset {această resursă} other {it}}", + "user_purchase_settings": "Cumpărare", + "user_purchase_settings_description": "Gestionați-vă achiziția", + "user_role_set": "Setați {user} ca {role}", + "user_usage_detail": "Detalii despre utilizare", + "user_usage_stats": "Statistici de utilizare a contului", + "user_usage_stats_description": "Vedeți statisticile de utilizare a contului", + "username": "Nume de utilizator", "users": "Utilizatori", "utilities": "Utilitǎți", - "validate": "Valideazǎ", + "validate": "Validați", "variables": "Variabile", "version": "Versiune", "version_announcement_closing": "Prietenul tǎu, Alex", + "version_announcement_message": "Bună! Este disponibilă o nouă versiune de Immich. Vă rugăm să vă faceți timp să citiți notele de lansare pentru a vă asigura că configurația dvs. este actualizată pentru a preveni orice configurare greșită, mai ales dacă utilizați WatchTower sau orice mecanism care se ocupă de actualizarea automată a instanței dvs. Immich.", + "version_history": "Istoric Versiuni", + "version_history_item": "Instalat {version} pe data de {date}", "video": "Videoclip", - "video_hover_setting_description": "", + "video_hover_setting": "Redați miniatura video la trecerea cursorului", + "video_hover_setting_description": "Redați miniatura video când mouse-ul trece peste element. Chiar și atunci când este dezactivată, redarea poate fi pornită trecând cu mouse-ul peste pictograma de redare.", "videos": "Videoclipuri", - "view_album": "Vezi album", - "view_all": "Vezi toate", - "view_all_users": "Vezi toți utilizatorii", - "view_links": "Vezi scurtǎturi", - "view_next_asset": "", - "view_previous_asset": "", - "viewer": "", - "waiting": "În așteptare", + "videos_count": "{count, plural, one {# Videoclip} other {# Videoclipuri}}", + "view": "Vizualizați", + "view_album": "Vizualizați Album", + "view_all": "Vizualizați Tot", + "view_all_users": "Vizulizați toți utilizatorii", + "view_in_timeline": "Vizualizați în cronologie", + "view_links": "Vizualizați scurtǎturi", + "view_name": "Vizualizare", + "view_next_asset": "Vizualizați următoarea resursă", + "view_previous_asset": "Vizualizați resursa anterioară", + "view_stack": "Vizualizați Stiva", + "visibility_changed": "Vizibilitatea schimbată pentru {count, plural, one {# persoană} other {# persoane}}", + "waiting": "Așteptați", "warning": "Avertisment", "week": "Sǎptǎmânǎ", - "welcome": "Salutare", - "welcome_to_immich": "Bun venit în Immich", + "welcome": "Bun venit", + "welcome_to_immich": "Bun venit la Immich", "year": "An", - "years_ago": "acum {years, plural, one {# an} other {# ani}}", + "years_ago": "acum {years, plural, one {# an} other {# ani}} în urmă", "yes": "Da", - "you_dont_have_any_shared_links": "Nu aveți niciun link partajat", - "zoom_image": "Mărește imaginea" + "you_dont_have_any_shared_links": "Nu aveți linkuri partajate", + "zoom_image": "Măriți Imaginea" } diff --git a/i18n/ru.json b/i18n/ru.json index fd4be156ebc0c..520a84406ce8e 100644 --- a/i18n/ru.json +++ b/i18n/ru.json @@ -23,6 +23,7 @@ "add_to": "Добавить в...", "add_to_album": "Добавить в альбом", "add_to_shared_album": "Добавить в общий альбом", + "add_url": "Добавить URL", "added_to_archive": "Добавлено в архив", "added_to_favorites": "Добавлено в избранное", "added_to_favorites_count": "Добавлено{count, number} в избранное", @@ -34,6 +35,11 @@ "authentication_settings_disable_all": "Вы уверены, что хотите отключить все методы входа? Вход будет полностью отключен.", "authentication_settings_reenable": "Чтобы снова включить, используйте Команда Сервера.", "background_task_job": "Фоновые задачи", + "backup_database": "Резервное копирование базы данных", + "backup_database_enable_description": "Включить резервное копирование базы данных", + "backup_keep_last_amount": "Количество хранимых резервных копий", + "backup_settings": "Настройки резервного копирования", + "backup_settings_description": "Управление настройками резервного копирования базы данных", "check_all": "Проверить все", "cleared_jobs": "Очищены задачи для: {job}", "config_set_by_file": "Настроено с помощью файла конфигурации", @@ -43,9 +49,10 @@ "confirm_reprocess_all_faces": "Вы уверены, что хотите повторно определить все лица? Будут также удалены имена со всех лиц.", "confirm_user_password_reset": "Вы уверены, что хотите сбросить пароль пользователя {user}?", "create_job": "Создать задание", - "crontab_guru": "Crontab Guru", + "cron_expression": "Выражение cron", + "cron_expression_description": "Задайте интервал сканирований в формате cron. Для получения дополнительной информации, ознакомьтесь с Crontab Guru", + "cron_expression_presets": "Предустановки выражений cron", "disable_login": "Отключить вход", - "disabled": "Выключено", "duplicate_detection_job_description": "Запускает определение похожих изображений при помощи машинного зрения (зависит от умного поиска)", "exclusion_pattern_description": "Шаблоны исключения позволяют игнорировать файлы и папки при сканировании вашей библиотеки. Это полезно, если у вас есть папки, содержащие файлы, которые вы не хотите импортировать, например, RAW-файлы.", "external_library_created_at": "Внешняя библиотека (создана {date})", @@ -63,22 +70,15 @@ "image_prefer_wide_gamut": "Предпочитаю широкую гамму", "image_prefer_wide_gamut_setting_description": "Используйте Display P3 для миниатюр. Это лучше сохраняет яркость изображений с широким цветовым пространством, но изображения могут выглядеть по-другому на старых устройствах со старой версией браузера. Изображения sRGB сохраняются в формате sRGB, что позволяет избежать цветовых сдвигов.", "image_preview_description": "Изображение среднего размера без метаданных, используемое при отдельном просмотре и для машинного обучения", - "image_preview_format": "Формат превью", "image_preview_quality_description": "Качество предварительного просмотра от 1 до 100. Чем выше, тем лучше, но при этом создаются файлы большего размера и может снизиться скорость отклика приложения. Установка низкого значения может повлиять на качество машинного обучения.", - "image_preview_resolution": "Разрешение превью", - "image_preview_resolution_description": "Используется при просмотре одной фотографии и для машинного обучения. Более высокие разрешения позволяют сохранить больше деталей, но требуют больше времени для кодирования, имеют больший размер файлов и могут снизить скорость отклика приложения.", "image_preview_title": "Настройки предварительного просмотра", "image_quality": "Качество", - "image_quality_description": "Качество изображения от 1 до 100. Чем выше число, тем лучше качество и больше вес изображения.", "image_resolution": "Разрешение", "image_resolution_description": "Более высокое разрешение позволяет сохранить больше деталей, но требует больше времени для кодирования, приводит к увеличению размера файлов и может снизить скорость отклика приложения.", "image_settings": "Настройки изображений", "image_settings_description": "Управление качеством и разрешением создаваемых изображений", "image_thumbnail_description": "Маленькая миниатюра с удаленными метаданными, используемая при просмотре групп фотографий, таких как основная временная шкала", - "image_thumbnail_format": "Формат миниатюр", "image_thumbnail_quality_description": "Качество миниатюр от 1 до 100. Чем выше качество, тем лучше, но при этом создаются файлы большего размера и может снизиться скорость отклика приложения.", - "image_thumbnail_resolution": "Разрешение миниатюр", - "image_thumbnail_resolution_description": "Используется при просмотре групп фотографий (на временной шкале, при просмотре альбомов и т.д.). Миниатюры с более высоким разрешением сохраняют больше деталей, но требуют больше времени для кодирования, имеют больший вес и могут снизить скорость отклика приложения.", "image_thumbnail_title": "Настройки миниатюр", "job_concurrency": "Параллельная обработка задания - {job}", "job_created": "Задание создано", @@ -89,9 +89,6 @@ "jobs_delayed": "{jobCount, plural, one {# отложена} other {# отложено}}", "jobs_failed": "{jobCount, plural, other {# не удалось выполнить}}", "library_created": "Созданная библиотека: {library}", - "library_cron_expression": "Выражение планировщика", - "library_cron_expression_description": "Установите интервал сканирования, используя формат планировщика. Для получения дополнительной информации, пожалуйста, обратитесь к примеру на Crontab Guru", - "library_cron_expression_presets": "Шаблоны настройки планировщика", "library_deleted": "Библиотека удалена", "library_import_path_description": "Укажите папку для импорта. Эта папка, включая вложенные папки, будет проверена на наличие изображений и видео.", "library_scanning": "Периодическое сканирование", @@ -134,7 +131,7 @@ "machine_learning_smart_search_description": "Семантический поиск изображений с использованием вложений CLIP", "machine_learning_smart_search_enabled": "Включить интеллектуальный поиск", "machine_learning_smart_search_enabled_description": "Если этот параметр отключен, изображения не будут кодироваться для интеллектуального поиска.", - "machine_learning_url_description": "URL-адрес сервера машинного обучения", + "machine_learning_url_description": "URL-адрес сервера машинного обучения. Если указаны несколько, запросы будут посланы на каждый, с первого до последнего, по очереди, пока не будет получен успешный ответ.", "manage_concurrency": "Управление параллельностью заданий", "manage_log_settings": "Управление настройками журнала", "map_dark_style": "Тёмный стиль", @@ -215,7 +212,6 @@ "refreshing_all_libraries": "Обновление всех библиотек", "registration": "Регистрация Администратора", "registration_description": "Поскольку вы являетесь первым пользователем в системе, вам будет присвоена роль администратора, и вы будете отвечать за административные задачи. Дополнительных пользователей будете создавать вы.", - "removing_deleted_files": "Удаление недоступных файлов", "repair_all": "Починить всё", "repair_matched_items": "Соответствует {count, plural, one {# элементу} few {# элементам} many {# элементам} other {# элементам}}", "repaired_items": "Восстановлено {count, plural, one {# элемент} few {# элемента} many {# элементов} other {# элемента}}", @@ -223,12 +219,12 @@ "reset_settings_to_default": "Сброс настроек до значений по умолчанию", "reset_settings_to_recent_saved": "Сбросьте настройки к последним сохраненным настройкам", "scanning_library": "Сканирование библиотеки", - "scanning_library_for_changed_files": "Поиск измененных файлов", - "scanning_library_for_new_files": "Поиск новых файлов", "search_jobs": "Поиск заданий...", "send_welcome_email": "Отправить приветственное письмо", "server_external_domain_settings": "Внешний домен", "server_external_domain_settings_description": "Домен для публичных ссылок, включая http(s)://", + "server_public_users": "Публичные пользователи", + "server_public_users_description": "Отображать всех пользователей (имена и email) для добавления в общие альбомы. Когда отключено, список пользователей будет доступен только администраторам.", "server_settings": "Настройки сервера", "server_settings_description": "Управление настройками сервера", "server_welcome_message": "Приветственное сообщение", @@ -254,6 +250,16 @@ "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_settings_description": "Настройте шаблоны уведомлений по эл. почте", + "template_email_update_album": "Шаблон изменения альбома", + "template_email_welcome": "Шаблон приветствия", + "template_settings": "Шаблоны уведомлений", + "template_settings_description": "Настройте шаблоны уведомлений.", "theme_custom_css_settings": "Пользовательские CSS", "theme_custom_css_settings_description": "Каскадные таблицы стилей позволяют настраивать дизайн Immich.", "theme_settings": "Настройки темы", @@ -261,7 +267,6 @@ "these_files_matched_by_checksum": "Эти файлы сопоставляются по их контрольным суммам", "thumbnail_generation_job": "Создание миниатюр", "thumbnail_generation_job_description": "Создает большие, маленькие и размытые миниатюры для каждого файла и человека", - "transcode_policy_description": "", "transcoding_acceleration_api": "API ускорителя", "transcoding_acceleration_api_description": "API, который будет взаимодействовать с вашим устройством для ускорения транскодирования. Эта настройка является «наилучшим вариантом»: при сбое она будет возвращаться к программному транскодированию. VP9 может работать или не работать в зависимости от вашего оборудования.", "transcoding_acceleration_nvenc": "NVENC (требуется графический процессор NVIDIA)", @@ -313,8 +318,6 @@ "transcoding_threads_description": "Более высокие значения приводят к более быстрому кодированию, но оставляют серверу меньше места для обработки других задач во время активности. Это значение не должно превышать количество ядер процессора. Максимизирует использование, если установлено значение 0.", "transcoding_tone_mapping": "Отображение тонов", "transcoding_tone_mapping_description": "Пытается сохранить внешний вид HDR-видео при преобразовании в SDR. Каждый алгоритм делает разные компромиссы между цветом, детализацией и яркостью. Hable сохраняет детали, Mobius сохраняет цвет, а Reinhard сохраняет яркость.", - "transcoding_tone_mapping_npl": "Отображение тонов NPL", - "transcoding_tone_mapping_npl_description": "Цвета будут отрегулированы так, чтобы выглядеть нормально для дисплея такой яркости. Как ни странно, более низкие значения увеличивают яркость видео и наоборот, поскольку компенсируют яркость дисплея. 0 устанавливает это значение автоматически.", "transcoding_transcode_policy": "Политика перекодирования", "transcoding_transcode_policy_description": "Правила, определяющие когда видео должно быть перекодировано. HDR-видео всегда будут перекодироваться (за исключением случаев, когда перекодирование отключено).", "transcoding_two_pass_encoding": "Двухпроходное кодирование", @@ -395,7 +398,6 @@ "archive_or_unarchive_photo": "Архивировать или разархивировать фото", "archive_size": "Размер архива", "archive_size_description": "Настройка размера архива для скачивания (в GiB)", - "archived": "Заархивировано", "archived_count": "{count, plural, other {Архивировано #}}", "are_these_the_same_person": "Это один и тот же человек?", "are_you_sure_to_do_this": "Вы уверены, что хотите это сделать?", @@ -416,7 +418,6 @@ "assets_added_to_album_count": "В альбом добавлено {count, plural, one {# объект} few {# объекта} other {# объектов}}", "assets_added_to_name_count": "Добавлено {count, plural, one {# объект} few {# объекта} other {# объектов}} в {hasName, select, true {{name}} other {новый альбом}}", "assets_count": "{count, plural, one {# объект} few {# объекта} other {# объектов}}", - "assets_moved_to_trash": "Перемещено {count, plural, one {# объект} few {# объекта} many {# объектов} 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 {# объектов}} удалено", @@ -446,10 +447,6 @@ "cannot_merge_people": "Невозможно объединить людей", "cannot_undo_this_action": "Это действие нельзя отменить!", "cannot_update_the_description": "Невозможно обновить описание", - "cant_apply_changes": "Невозможно применить изменения", - "cant_get_faces": "Невозможно получить лица", - "cant_search_people": "Невозможно искать людей", - "cant_search_places": "Невозможно искать места", "change_date": "Изменить дату", "change_expiration_time": "Изменить время окончания", "change_location": "Изменить местоположение", @@ -481,6 +478,7 @@ "confirm": "Подтвердить", "confirm_admin_password": "Подтвердите пароль Администратора", "confirm_delete_shared_link": "Вы уверены, что хотите удалить эту публичную ссылку?", + "confirm_keep_this_delete_others": "Все остальные объекты в серии будут удалены, кроме этого объекта. Вы уверены, что хотите продолжить?", "confirm_password": "Подтвердите пароль", "contain": "Вместить", "context": "Контекст", @@ -530,6 +528,7 @@ "delete_key": "Удалить ключ", "delete_library": "Удалить библиотеку", "delete_link": "Удалить ссылку", + "delete_others": "Удалить остальные", "delete_shared_link": "Удалить публичную ссылку", "delete_tag": "Удалить тег", "delete_tag_confirmation_prompt": "Вы уверены, что хотите удалить тег {tagName}?", @@ -541,7 +540,7 @@ "direction": "Направление", "disabled": "Отключено", "disallow_edits": "Запретить редактирование", - "discord": "Discord", + "discord": "Общение в Discord", "discover": "Обнаружить", "dismiss_all_errors": "Сбросить все ошибки", "dismiss_error": "Сбросить ошибку", @@ -563,13 +562,6 @@ "duplicates": "Дубликаты", "duplicates_description": "Разберитесь с каждой группой, указав, какие из них являются дубликатами, если таковые имеются", "duration": "Продолжительность", - "durations": { - "days": "{days, plural, one {день} few {# дня} many {# дней} other {# дня}}", - "hours": "{hours, plural, one {час} few {# часа} many {# часов} other {# часа}}", - "minutes": "{minutes, plural, one {минута} other {{minutes, number} минут}}", - "months": "{months, plural, one {месяц} other {{months, number} месяца}}", - "years": "{years, plural, one {год} few {# года} many {# лет} other {# года}}" - }, "edit": "Редактировать", "edit_album": "Редактировать альбом", "edit_avatar": "Редактировать аватар", @@ -594,8 +586,6 @@ "editor_crop_tool_h2_aspect_ratios": "Соотношения сторон", "editor_crop_tool_h2_rotation": "Вращение", "email": "Электронная почта", - "empty": "", - "empty_album": "Пустой альбом", "empty_trash": "Очистить корзину", "empty_trash_confirmation": "Вы уверены, что хотите очистить корзину? Все объекты в корзине будут навсегда удалены из Immich.\nВы не сможете отменить это действие!", "enable": "Включить", @@ -629,8 +619,9 @@ "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_assets": "Не удалось загрузить объекты", "failed_to_load_people": "Не удалось загрузить людей", "failed_to_remove_product_key": "Не удалось удалить ключ продукта", "failed_to_stack_assets": "Не удалось сгруппировать объекты", @@ -656,8 +647,6 @@ "unable_to_change_location": "Невозможно изменить местоположение", "unable_to_change_password": "Невозможно изменить пароль", "unable_to_change_visibility": "Не удалось изменить видимость для {count, plural, one {# человека} few {# людей} many {# людей} other {# людей}}", - "unable_to_check_item": "", - "unable_to_check_items": "", "unable_to_complete_oauth_login": "Не удалось выполнить вход с помощью OAuth", "unable_to_connect": "Не удается подключиться", "unable_to_connect_to_server": "Не удалось подключиться к серверу", @@ -698,12 +687,10 @@ "unable_to_remove_album_users": "Не удалось удалить пользователей из альбома", "unable_to_remove_api_key": "Не удается удалить ключ API", "unable_to_remove_assets_from_shared_link": "Невозможно удалить объекты из публичной ссылки", - "unable_to_remove_comment": "", "unable_to_remove_deleted_assets": "Не удается удалить автономные файлы", "unable_to_remove_library": "Не удается удалить библиотеку", "unable_to_remove_partner": "Не удается удалить партнера", "unable_to_remove_reaction": "Не удается удалить реакцию", - "unable_to_remove_user": "", "unable_to_repair_items": "Не удалось восстановить элементы", "unable_to_reset_password": "Не удается сбросить пароль", "unable_to_resolve_duplicate": "Не удалось разрешить дубликат", @@ -733,10 +720,6 @@ "unable_to_update_user": "Не удалось обновить пользователя", "unable_to_upload_file": "Невозможно загрузить файл" }, - "every_day_at_onepm": "", - "every_night_at_midnight": "", - "every_night_at_twoam": "", - "every_six_hours": "", "exif": "Exif", "exit_slideshow": "Выйти из слайд-шоу", "expand_all": "Развернуть всё", @@ -751,33 +734,28 @@ "external": "Внешний", "external_libraries": "Внешние библиотеки", "face_unassigned": "Не назначено", - "failed_to_get_people": "Ошибка при получении людей", + "failed_to_load_assets": "Не удалось загрузить объекты", "favorite": "Избранное", "favorite_or_unfavorite_photo": "Добавить или удалить фотографию из избранного", "favorites": "Избранное", - "feature": "", "feature_photo_updated": "Избранное фото обновлено", - "featurecollection": "", "features": "Дополнительные возможности", "features_setting_description": "Управление дополнительными возможностями приложения", "file_name": "Имя файла", "file_name_or_extension": "Имя файла или расширение", "filename": "Имя файла", - "files": "", "filetype": "Тип файла", "filter_people": "Фильтр по людям", "find_them_fast": "Быстро найдите их по имени с помощью поиска", "fix_incorrect_match": "Исправить неправильное соответствие", "folders": "Папки", "folders_feature_description": "Просмотр папок с фотографиями и видео в файловой системе", - "force_re-scan_library_files": "Принудительное повторное сканирование всех файлов библиотеки", - "forward": "Переслать", + "forward": "Вперёд", "general": "Общие", "get_help": "Получить помощь", "getting_started": "Приступая к работе", "go_back": "Назад", "go_to_search": "Перейти к поиску", - "go_to_share_page": "Перейти на страницу для обмена", "group_albums_by": "Группировать альбомы по...", "group_no": "Без группировки", "group_owner": "Группировать по владельцу", @@ -803,10 +781,6 @@ "image_alt_text_date_place_2_people": "{isVideo, select, true {Video} other {Image}} снятое в {city}, {country} с {person1} и {person2} {date}", "image_alt_text_date_place_3_people": "{isVideo, select, true {Video} other {Image}} снятое в {city}, {country} с {person1}, {person2}, и {person3} {date}", "image_alt_text_date_place_4_or_more_people": "{isVideo, select, true {Video} other {Image}} снятое в {city}, {country} с {person1}, {person2}, и еще с {additionalCount, number} людьми {date}", - "image_alt_text_people": "{count, plural, =1 {с {person1}} =2 {с {person1} и {person2}} =3 {с {person1}, {person2}, и {person3}} other {с {person1}, {person2}, и {others, number} др.}}", - "image_alt_text_place": "в {city}, {country}", - "image_taken": "{isVideo, select, true {Снято видео} other {Сделано фото}}", - "img": "", "immich_logo": "Лого Immich", "immich_web_interface": "Веб интерфейс Immich", "import_from_json": "Импорт из JSON", @@ -827,10 +801,11 @@ "invite_people": "Пригласить", "invite_to_album": "Пригласить в альбом", "items_count": "{count, plural, one {# элемент} two {# элемента} few {# элемента} other {# элементов}}", - "job_settings_description": "", "jobs": "Задачи", "keep": "Оставить", "keep_all": "Сохранить всё", + "keep_this_delete_others": "Оставить этот, удалить остальные", + "kept_this_deleted_others": "Сохранил этот объект и удалил {count, plural, one {# объект} other {# объектов}}", "keyboard_shortcuts": "Сочетания клавиш", "language": "Язык", "language_setting_description": "Выберите предпочитаемый вами язык", @@ -842,31 +817,6 @@ "level": "Уровень", "library": "Библиотека", "library_options": "Опции библиотеки", - "license_account_info": "Ваш аккаунт лицензирован", - "license_activated_subtitle": "Спасибо за поддержку Immich и open-source ПО", - "license_activated_title": "Ваша лицензия была успешно активирована", - "license_button_activate": "Активировать", - "license_button_buy": "Купить", - "license_button_buy_license": "Купить лицензию", - "license_button_select": "Выбрать", - "license_failed_activation": "Не удалось активировать лицензию. Проверьте корректный лицензионный ключ в электронной почте!", - "license_individual_description_1": "1 лицензия на пользователя на любом сервере", - "license_individual_title": "Индивидуальная лицензия", - "license_info_licensed": "Лицензированный", - "license_info_unlicensed": "Нет лицензии", - "license_input_suggestion": "Уже есть лицензия? Введите ключ ниже", - "license_license_subtitle": "Купить лицензию для поддержки Immich", - "license_license_title": "ЛИЦЕНЗИЯ", - "license_lifetime_description": "Пожизненная лицензия", - "license_per_server": "за сервер", - "license_per_user": "за пользователя", - "license_server_description_1": "1 лицензия на сервер", - "license_server_description_2": "Лицензия для всех пользователей сервера", - "license_server_title": "Серверная Лицензия", - "license_trial_info_1": "Вы используете Immich без лицензии", - "license_trial_info_2": "Вы используете Immich примерно", - "license_trial_info_3": "{accountAge, plural, one {# день} other {# дней}}", - "license_trial_info_4": "Пожалуйста, рассмотрите возможность приобретения лицензии для поддержки дальнейшего развития проекта", "light": "Светлая", "like_deleted": "Лайк удален", "link_motion_video": "Ссылка на движущееся видео", @@ -971,7 +921,6 @@ "onboarding_welcome_user": "Добро пожаловать, {user}", "online": "Доступен", "only_favorites": "Только избранное", - "only_refreshes_modified_files": "Обновляет только измененные файлы", "open_in_map_view": "Открыть в режиме просмотра карты", "open_in_openstreetmap": "Открыть в OpenStreetMap", "open_the_search_filters": "Открыть фильтры поиска", @@ -1009,14 +958,12 @@ "people_edits_count": "Изменено {count, plural, one {# человек} few {# человека} many {# людей} other {# человек}}", "people_feature_description": "Просмотр фотографий и видео, сгруппированных по людям", "people_sidebar_description": "Отображать пункт меню \"Люди\" в боковой панели", - "perform_library_tasks": "", "permanent_deletion_warning": "Предупреждение об удалении", "permanent_deletion_warning_setting_description": "Предупреждать перед безвозвратным удалением ресурсов", "permanently_delete": "Удалить навсегда", "permanently_delete_assets_count": "Безвозвратно удалить {count, plural, one {ресурс} few {ресурса} many {ресурсов} other {ресурсов}}", "permanently_delete_assets_prompt": "Вы действительно хотите навсегда удалить {count, plural, one {этот объект?} other {эти # объектов?}} Это так же удалит {count, plural, one {его} other {их}} из альбома(ов).", "permanently_deleted_asset": "Удалить навсегда", - "permanently_deleted_assets": "Безвозвратно удалено {count, plural, one {# ресурс} few {# ресурса} many {# ресурсов} other {# ресурса}}", "permanently_deleted_assets_count": "Безвозвратно удалено {count, plural, one {# файл} few {# файла} many {# файлов} other {# файлов}}", "person": "Человек", "person_hidden": "{name}{hidden, select, true { (скрыт)} other {}}", @@ -1032,7 +979,6 @@ "play_memories": "Воспроизвести воспоминания", "play_motion_photo": "Воспроизводить движущиеся фото", "play_or_pause_video": "Воспроизведение или приостановка видео", - "point": "", "port": "Порт", "preset": "Предустановка", "preview": "Предварительный просмотр", @@ -1077,12 +1023,10 @@ "purchase_server_description_2": "Состояние поддержки", "purchase_server_title": "Сервер", "purchase_settings_server_activated": "Ключ продукта сервера управляется администратором", - "range": "", "rating": "Рейтинг звёзд", "rating_clear": "Очистить рейтинг", "rating_count": "{count, plural, one {# звезда} other {# звезд}}", "rating_description": "Показывать рейтинг в панели информации", - "raw": "", "reaction_options": "Опции реакций", "read_changelog": "Прочитать список изменений", "reassign": "Переназначить", @@ -1090,6 +1034,7 @@ "reassigned_assets_to_new_person": "Переназначен{count, plural, one { # ресурс} few {о # ресурса} many {о # ресурсов} other {о # ресурсов}} новому человеку", "reassing_hint": "Назначить выбранные ресурсы существующему пользователю", "recent": "Недавние", + "recent-albums": "Недавние альбомы", "recent_searches": "Недавние поисковые запросы", "refresh": "Обновить", "refresh_encoded_videos": "Обновить закодированные видео", @@ -1111,6 +1056,7 @@ "remove_from_album": "Удалить из альбома", "remove_from_favorites": "Удалить из избранного", "remove_from_shared_link": "Удалить из публичной ссылки", + "remove_url": "Удалить URL", "remove_user": "Удалить пользователя", "removed_api_key": "Удален ключ API: {name}", "removed_from_archive": "Удален из архива", @@ -1127,7 +1073,6 @@ "reset": "Сброс", "reset_password": "Сброс пароля", "reset_people_visibility": "Восстановить видимость людей", - "reset_settings_to_default": "", "reset_to_default": "Восстановление значений по умолчанию", "resolve_duplicates": "Устранить дубликаты", "resolved_all_duplicates": "Все дубликаты устранены", @@ -1147,9 +1092,7 @@ "saved_settings": "Настройки сохранены", "say_something": "Скажите что-нибудь", "scan_all_libraries": "Сканировать все библиотеки", - "scan_all_library_files": "Повторное сканирование всех файлов библиотеки", "scan_library": "Сканировать", - "scan_new_library_files": "Сканировать новые файлы в библиотеке", "scan_settings": "Настройки сканирования", "scanning_for_album": "Сканирование альбома...", "search": "Поиск", @@ -1192,7 +1135,6 @@ "selected_count": "{count, plural, one {# выбран} other {# выбрано}}", "send_message": "Отправить сообщение", "send_welcome_email": "Отправить приветственное письмо", - "server": "Сервер", "server_offline": "Сервер не в сети", "server_online": "Сервер в сети", "server_stats": "Статистика сервера", @@ -1256,12 +1198,12 @@ "sort_oldest": "Старые фото", "sort_recent": "Недавние фото", "sort_title": "Заголовок", - "source": "Источник", - "stack": "В стопку", - "stack_duplicates": "Стек дубликатов", - "stack_select_one_photo": "Выберите одну главную фотографию для стека", - "stack_selected_photos": "Сложить выбранные фотографии в стопку", - "stacked_assets_count": "{count, plural, one {# объект добавлен} few {# объекта добавлено} other {# объектов добавлено}} в стек", + "source": "Исходный код", + "stack": "Превратить в серию", + "stack_duplicates": "Превратить дубликаты в серию", + "stack_select_one_photo": "Выберите главную фотографию для серии", + "stack_selected_photos": "Объединить выбранные объекты в серию", + "stacked_assets_count": "{count, plural, one {# объект добавлен} few {# объекта добавлено} other {# объектов добавлено}} в серию", "stacktrace": "Трассировка стека", "start": "Старт", "start_date": "Дата начала", @@ -1297,17 +1239,17 @@ "they_will_be_merged_together": "Они будут объединены вместе", "third_party_resources": "Сторонние ресурсы", "time_based_memories": "Воспоминания, основанные на времени", + "timeline": "Временная шкала", "timezone": "Часовой пояс", "to_archive": "В архив", "to_change_password": "Изменить пароль", "to_favorite": "Добавить в избранное", "to_login": "Вход", "to_parent": "Вернуться назад", - "to_root": "В начало", "to_trash": "Корзина", "toggle_settings": "Переключение настроек", "toggle_theme": "Переключение темы", - "toggle_visibility": "Переключение видимости", + "total": "Всего", "total_usage": "Общее использование", "trash": "Корзина", "trash_all": "Удалить всё", @@ -1317,12 +1259,10 @@ "trashed_items_will_be_permanently_deleted_after": "Элементы в корзине будут автоматически удалены через {days, plural, one {# день} other {# дней}}.", "type": "Тип", "unarchive": "Восстановить", - "unarchived": "Разархивирован", "unarchived_count": "{count, plural, other {Возвращено из архива #}}", "unfavorite": "Удалить из избранного", "unhide_person": "Показать персону", "unknown": "Неизвестно", - "unknown_album": "Неизвестный альбом", "unknown_year": "Неизвестный Год", "unlimited": "Не ограничено", "unlink_motion_video": "Отсоединить движущееся видео", @@ -1334,8 +1274,8 @@ "unsaved_change": "Не сохраненное изменение", "unselect_all": "Снять всё", "unselect_all_duplicates": "Отменить выбор всех дубликатов", - "unstack": "Разобрать стек", - "unstacked_assets_count": "{count, plural, one {# объект извлечен} few {# объекта извлечено} other {# объектов извлечено}} из стека", + "unstack": "Разгруппировать серию", + "unstacked_assets_count": "{count, plural, one {# объект извлечен} few {# объекта извлечено} other {# объектов извлечено}} из серии", "untracked_files": "НЕОТСЛЕЖИВАЕМЫЕ ФАЙЛЫ", "untracked_files_decription": "Приложение не отслеживает эти файлы. Они могут быть результатом неудачных перемещений, прерванных загрузок или пропущены из-за ошибки", "up_next": "Следующее", @@ -1354,13 +1294,13 @@ "use_custom_date_range": "Использовать пользовательский диапазон дат", "user": "Пользователь", "user_id": "ID пользователя", - "user_license_settings": "Лицензия", - "user_license_settings_description": "Управление лицензией", "user_liked": "{user} отметил(а) {type, select, photo {это фото} video {это видео} asset {этот ресурс} other {этот альбом}}", "user_purchase_settings": "Покупка", "user_purchase_settings_description": "Управление покупкой", "user_role_set": "Установить {user} в качестве {role}", "user_usage_detail": "Подробная информация об использовании пользователем", + "user_usage_stats": "Статистика использования аккаунта", + "user_usage_stats_description": "Посмотреть статистику использования аккаунта", "username": "Имя пользователя", "users": "Пользователи", "utilities": "Утилиты", @@ -1368,7 +1308,7 @@ "variables": "Переменные", "version": "Версия", "version_announcement_closing": "Твой друг Алекс", - "version_announcement_message": "Привет, друг! Доступна новая версия приложения. Пожалуйста, посетите заметки к выпуску и убедитесь, что ваши параметры docker-compose.yml и .env актуальны, чтобы избежать ошибок конфигурации, особенно если вы используете WatchTower или другой механизм автоматического обновления приложения.", + "version_announcement_message": "Здравствуйте! Доступна новая версия приложения. Пожалуйста, прочтите заметки к выпуску и убедитесь, что ваши параметры docker-compose.yml и .env актуальны, чтобы избежать ошибок в конфигурации, особенно если вы используете WatchTower или другой механизм автоматического обновления приложения.", "version_history": "История версий", "version_history_item": "Версия {version} установлена {date}", "video": "Видео", @@ -1382,10 +1322,10 @@ "view_all_users": "Показать всех пользователей", "view_in_timeline": "Показать на временной шкале", "view_links": "Показать ссылки", + "view_name": "Посмотреть", "view_next_asset": "Показать следующий объект", "view_previous_asset": "Показать предыдущий объект", "view_stack": "Показать стек", - "viewer": "Наблюдатель", "visibility_changed": "Видимость изменена для {count, plural, one {# человека} other {# людей}}", "waiting": "В очереди", "warning": "Предупреждение", diff --git a/i18n/sk.json b/i18n/sk.json index 975229b51da81..bf67b8ab122e3 100644 --- a/i18n/sk.json +++ b/i18n/sk.json @@ -1,8 +1,8 @@ { - "about": "O aplikácií", + "about": "Obnoviť", "account": "Účet", "account_settings": "Nastavenia účtu", - "acknowledge": "Potvrdiť", + "acknowledge": "Rozumiem", "action": "Akcia", "actions": "Akcie", "active": "Aktívny", @@ -23,6 +23,7 @@ "add_to": "Pridať do...", "add_to_album": "Pridať do albumu", "add_to_shared_album": "Pridať do zdieľaného albumu", + "add_url": "Pridaj URL", "added_to_archive": "Pridané do archívu", "added_to_favorites": "Pridané do obľúbených", "added_to_favorites_count": "Pridané {count, number} do obľúbených", @@ -34,17 +35,24 @@ "authentication_settings_disable_all": "Naozaj chcete zakázať všetky spôsoby prihlásenia? Prihlásenie bude úplne zakázané.", "authentication_settings_reenable": "Pre opätovné povolenie použite Serverový príkaz.", "background_task_job": "Úlohy na pozadí", + "backup_database": "Zálohovať databázu", + "backup_database_enable_description": "Povoliť zálohovanie databázy", + "backup_keep_last_amount": "Množtvo predošlých záloh, ktoré sa majú zachovať", + "backup_settings": "Nastavenia zálohovania", + "backup_settings_description": "Spravovať nastavenia záloh", "check_all": "Skontrolovať všetko", "cleared_jobs": "Hotové úlohy pre: {job}", "config_set_by_file": "Konfigurácia je v súčasnosti nastavená konfiguračným súborom", "confirm_delete_library": "Naozaj chcete vymazať knižnicu {library}?", + "confirm_delete_library_assets": "Ste si istí, že chcete vymazať túto knižnicu? Tato operácia nenávratne odstráni {count, plural, one {# contained asset} other {all # contained assets}} súborov z Immich. Súbory budú ponechané na disku.", "confirm_email_below": "Pre potvrdenie zadajte \"{email}\" nižšie", "confirm_reprocess_all_faces": "Naozaj chcete spracovať všetky tváre znova? Tento proces vymaže pomenovaných ľudí.", "confirm_user_password_reset": "Naozaj chcete resetovať heslo pre {user}?", "create_job": "Vytvoriť úlohu", - "crontab_guru": "", + "cron_expression": "Výraz cron", + "cron_expression_description": "Nastavte interval skenovania pomocou formátu cron. Pre viac informácií navštívte Crontab Guru", + "cron_expression_presets": "Presety cron výrazov", "disable_login": "Zakázať prihlásenie", - "disabled": "", "duplicate_detection_job_description": "Spustiť strojové učenie na položkách pre detekciu podobných obrázkov. Spolieha sa na inteligentné vyhľadávanie", "exclusion_pattern_description": "Vylučovacie vzory Vám umožňujú ignorovať súbory a priečinky pri skenovaní Vašej knižnice. Toto je užitočné, ak máte priečinky obsahujúce súbory, ktoré nechcete importovať, napríklad RAW súbory.", "external_library_created_at": "Externá knižnica (vytvorená {date})", @@ -62,35 +70,25 @@ "image_prefer_wide_gamut": "Uprednostňovať široký farebný rozsah", "image_prefer_wide_gamut_setting_description": "Použiť Display P3 pre miniatúry. Toto lepšie zachováva živosť obrázkov so širokým farebným rozsahom. Obrázky sa môžu zobraziť odlišne na starších zariadeniach so starou verziou prehliadača. sRGB obrázky zostávajú sRGB, aby sa zabránilo farebným posunom.", "image_preview_description": "Stredne veľký obrázok s odstránenými metadátami, používaný pri prezeraní jednej položky a na strojové učenie", - "image_preview_format": "Formát ukážky", "image_preview_quality_description": "Kvalita náhľadu v stupnici od 1 do 100. Vyššia hodnota znamená lepšiu kvalitu, ale produkuje väčšie súbory a môže znížiť odozvu aplikácie. Nastavenie nižšej hodnoty môže ovplyvniť kvalitu strojového učenia.", - "image_preview_resolution": "Rozlíšenie náhľadu", - "image_preview_resolution_description": "Používa sa pri prezeraní jednej fotografie a pre strojové učenie. Vyššie rozlíšenie zachová viac detailov, ale kódovanie trvá dlhšie, súbory sú väčšie, a môže znížiť rýchlosť aplikácie.", "image_preview_title": "Nastavenia Náhľadov", "image_quality": "Kvalita", - "image_quality_description": "", "image_resolution": "Rozlíšenie", "image_resolution_description": "Vyššie rozlíšenie môže zachovať viac detailov, ale kódovanie trvá dlhšie, súbory sú väčšie a môže to znížiť rýchlosť odozvy aplikácie.", "image_settings": "Nastavenia Obrázkov", "image_settings_description": "Spravovať kvalitu a rozlíšenie generovaných obrázkov", "image_thumbnail_description": "Malá miniatúra s odstránenými metadátami, používané pri zobrazovaní skupín fotiek ako na hlavnej časovej osi", - "image_thumbnail_format": "Formát náhľadu", "image_thumbnail_quality_description": "Kvalita miniatúry v stupnici od 1 do 100. Vyššia hodnota znamená lepšiu kvalitu, ale produkuje väčšie súbory a môže znížiť odozvu aplikácie.", - "image_thumbnail_resolution": "", - "image_thumbnail_resolution_description": "", "image_thumbnail_title": "Nastavenia miniatúr", "job_concurrency": "Súbežnosť úlohy - {job}", "job_created": "Úloha bola vytvorená", - "job_not_concurrency_safe": "Táto úloha nie je bezpečná pre súbežné spracovanie", + "job_not_concurrency_safe": "Táto úloha nie je bezpečná pre súbežné spracovanie.", "job_settings": "Nastavenia Úloh", "job_settings_description": "Spravovať súbežnosť úloh", "job_status": "Stav Úloh", "jobs_delayed": "{jobCount, plural, one {# oneskorený} few {# oneskorené} other {# oneskorených}}", "jobs_failed": "{jobCount, plural, one {# neúspešný} few {# neúspešné} other {# neúspešných}}", "library_created": "Vytvorená knižnica: {library}", - "library_cron_expression": "Výraz pre Cron", - "library_cron_expression_description": "Nastaviť skenovací interval pomocou formátu cron. Viac informácií nájdete napr. na Crontab Guru", - "library_cron_expression_presets": "Predvoľby výrazu pre Cron", "library_deleted": "Knižnica bola vymazaná", "library_import_path_description": "Zvoľte priečinok na importovanie. Tento priečinok vrátane podpriečinkov bude skenovaný pre obrázky a videá.", "library_scanning": "Pravidelné skenovanie", @@ -130,34 +128,44 @@ "machine_learning_settings": "Nastavenia strojového učenia", "machine_learning_settings_description": "Spravovať funkcie a nastavenia strojového učenia", "machine_learning_smart_search": "Inteligentné vyhľadávanie", - "machine_learning_smart_search_description": "", + "machine_learning_smart_search_description": "Významové vyhľadávanie v obrázkoch pomocou CLIP vzorov", "machine_learning_smart_search_enabled": "Povoliť inteligentné vyhľadávanie", - "machine_learning_smart_search_enabled_description": "", - "machine_learning_url_description": "URL adresa servera pre strojové učenie", + "machine_learning_smart_search_enabled_description": "Ak je vypnuté, obrázky nebudú spracované pre inteligentné vyhľadávanie.", + "machine_learning_url_description": "URL adresa machine-learning servera. Ak je poskytnutých viacero URL adries, budú servery postupne testované od prvého po posledný, až kým jeden z nich úspešne odpovie.", + "manage_concurrency": "Správa súbežnosti", "manage_log_settings": "Spravovať nastavenia logovania", "map_dark_style": "Tmavý štýl", "map_enable_description": "Povoliť funkcie mapy", "map_gps_settings": "Nastavenia Mapy & GPS", + "map_gps_settings_description": "Správa nastavení máp a GPS reverzného geokódovania", + "map_implications": "Táto funkčnosť sa spolieha na externý servis spracovania mapových dlaždíc (tiles.immich.cloud)", "map_light_style": "Svetlý štýl", - "map_reverse_geocoding": "", + "map_manage_reverse_geocoding_settings": "Správa nastavení Reverzného geokódovania", + "map_reverse_geocoding": "Reverzné Geokódovanie", "map_reverse_geocoding_enable_description": "Povoliť reverzné geokódovanie", - "map_reverse_geocoding_settings": "", + "map_reverse_geocoding_settings": "Nastavenia reverzného geokódovania", "map_settings": "Mapa", "map_settings_description": "Spravovať nastavenia mapy", - "map_style_description": "", + "map_style_description": "URL na motív style.json", "metadata_extraction_job": "Extrahovať metadáta", - "metadata_extraction_job_description": "", + "metadata_extraction_job_description": "Získaj informácie metadátach z každej položky, ako napríklad GPS, tváre a rozlíšenie", "metadata_faces_import_setting": "Povoliť import tváre", + "metadata_faces_import_setting_description": "Importuj tváre z EXIF dát obrázkov a sidecar súborov", "metadata_settings": "Nastavenia metadát", "metadata_settings_description": "Spravovať nastavenia metadát", "migration_job": "Migrácia", - "migration_job_description": "", + "migration_job_description": "Migrácia miniatúr položiek a tvárí na najnovšiu štruktúru priečinkov", + "no_paths_added": "Neboli pridané žiadne cesty", + "no_pattern_added": "Nebol pridaný žiadny vzor", + "note_apply_storage_label_previous_assets": "Poznámka: Ak chcete použiť Štítkovanie úložiska na predtým nahrané aktíva, spustite príkaz", + "note_cannot_be_changed_later": "POZNÁMKA: Toto nie je možné neskôr zmeniť!", + "note_unlimited_quota": "Poznámka: Použite 0 pre neobmedzený limit", "notification_email_from_address": "Z adresy", - "notification_email_from_address_description": "", - "notification_email_host_description": "", + "notification_email_from_address_description": "E-mailová adresa odosielateľa, príklad: \"Immich Photo Server \"", + "notification_email_host_description": "Adresa emailového serveru (príklad: smtp.immich.app)", "notification_email_ignore_certificate_errors": "Ignorovať chyby certifikátu", - "notification_email_ignore_certificate_errors_description": "", - "notification_email_password_description": "", + "notification_email_ignore_certificate_errors_description": "Ignorovať chyby pri overení TLS certifikátu (neodporúča sa)", + "notification_email_password_description": "Heslo pre autentifikáciu s emailovým serverom", "notification_email_port_description": "Porty e-mailového servera (napr. 25, 465, alebo 587)", "notification_email_sent_test_email_button": "Odoslať testovací e-mail a uložiť", "notification_email_setting_description": "Nastavenie pre odosielanie e-mailových upozornení", @@ -168,143 +176,194 @@ "notification_enable_email_notifications": "Povoliť e-mailové upozornenia", "notification_settings": "Nastavenia upozornení", "notification_settings_description": "Spravovať nastavenia upozornení, vrátane emailu", - "oauth_auto_launch": "", - "oauth_auto_launch_description": "", - "oauth_auto_register": "", - "oauth_auto_register_description": "", - "oauth_button_text": "", + "oauth_auto_launch": "Automatické spustenie", + "oauth_auto_launch_description": "Automatické spustenie OAuth prihlasovacieho toku pri otvorení prihlasovacej stránky", + "oauth_auto_register": "Automatická regristrácia", + "oauth_auto_register_description": "Automatické zaregistrovanie nového požívateľa pri prihlásení pomocou OAuth", + "oauth_button_text": "Text tlačítka", "oauth_client_id": "Client ID", "oauth_client_secret": "Client Secret", "oauth_enable_description": "Prihlásiť sa pomocou OAuth", - "oauth_issuer_url": "", - "oauth_mobile_redirect_uri": "", - "oauth_mobile_redirect_uri_override": "", - "oauth_mobile_redirect_uri_override_description": "", - "oauth_scope": "", + "oauth_issuer_url": "Adresa URL vydavateľa", + "oauth_mobile_redirect_uri": "URI mobilného presmerovania", + "oauth_mobile_redirect_uri_override": "Prepísanie URI mobilného presmerovania", + "oauth_mobile_redirect_uri_override_description": "Povoľte, keď poskytovateľ protokolu OAuth nepovoľuje identifikátor URI pre mobilné zariadenia, napríklad '{callback}'", + "oauth_profile_signing_algorithm": "Algoritmus podpisovania profilu", + "oauth_profile_signing_algorithm_description": "Algoritmus používaný na prihlásenie užívateľského profilu.", + "oauth_scope": "Rozsah", "oauth_settings": "OAuth", "oauth_settings_description": "Spravovať nastavenia prihlásenia OAuth", - "oauth_signing_algorithm": "", - "oauth_storage_label_claim": "", - "oauth_storage_label_claim_description": "", - "oauth_storage_quota_claim": "", - "oauth_storage_quota_claim_description": "", - "oauth_storage_quota_default": "", - "oauth_storage_quota_default_description": "", + "oauth_settings_more_details": "Pre viac informácii o tejto funkcii, prejdite na docs.", + "oauth_signing_algorithm": "Algoritmus podpisovania", + "oauth_storage_label_claim": "Nárokovať Štítok úložiska", + "oauth_storage_label_claim_description": "Automaticky nastaviť Štítok úložiska používateľa na hodnotu tohto nároku.", + "oauth_storage_quota_claim": "Deklarácia kvóty úložiska", + "oauth_storage_quota_claim_description": "Automaticky nastaviť kvótu úložiska používateľa na hodnotu tejto deklarácie.", + "oauth_storage_quota_default": "Predvolený limit úložiska (GiB)", + "oauth_storage_quota_default_description": "Kvóta v GiB, ktorá sa má použiť, keď nie je poskytnutý žiadna deklarácia (zadajte 0 pre neobmedzenú kvótu).", + "offline_paths": "Offline cesty", + "offline_paths_description": "Tieto výsledky môžu byť spôsobené ručným odstránením súborov, ktoré nie sú súčasťou externej knižnice.", "password_enable_description": "Prihlásiť sa pomocou emailu a hesla", "password_settings": "Prihlásenie cez heslo", "password_settings_description": "Spravovať nastavenia prihlásenia cez heslo", + "paths_validated_successfully": "Všetky cesty boli úspešne overené", + "person_cleanup_job": "Premazanie osôb", + "quota_size_gib": "Veľkosť kvóty (GiB)", "refreshing_all_libraries": "Obnovujú sa všetky knižnice", "registration": "Registrácia administrátora", + "registration_description": "Keďže ste prvým používateľom v systéme, budú vám pridelené správcovské práva na vykonávanie všetkých úloh a vrátane tvorby nových používateľov.", "repair_all": "Opraviť Všetko", + "repair_matched_items": "Zhody {count, plural, one {# item} other {# items}}", + "repaired_items": "Opravených {count, plural, one {# item} other {# items}}", "require_password_change_on_login": "Vyžadovať od používateľa zmenu hesla pri prvom prihlásení", "reset_settings_to_default": "Obnoviť pôvodné nastavenia", + "reset_settings_to_recent_saved": "Obnoviť naposledy uložené nastavenia", "scanning_library": "Knižnica sa skenuje", "search_jobs": "Vyhľadať úlohy...", "send_welcome_email": "Odoslať uvítací e-mail", "server_external_domain_settings": "Externá doména", - "server_external_domain_settings_description": "", + "server_external_domain_settings_description": "Verejná doména pre zdieľané odkazy, vrátane http(s)://", + "server_public_users": "Verejní užívatelia", + "server_public_users_description": "Všetci užívatelia (meno a email) sú uvedení pri pridávaní užívateľa do zdieľaných albumov. Ak je táto funkcia vypnutá, zoznam užívateľov bude dostupný iba správcom.", "server_settings": "Nastavenia servera", "server_settings_description": "Spravovať nastavenia servera", "server_welcome_message": "Uvítacia správa", "server_welcome_message_description": "Správa, ktorá sa zobrazí na prihlasovacej stránke.", - "sidecar_job_description": "", - "slideshow_duration_description": "", - "smart_search_job_description": "", - "storage_template_enable_description": "", - "storage_template_hash_verification_enabled": "", - "storage_template_hash_verification_enabled_description": "", - "storage_template_migration_job": "", - "storage_template_settings": "", - "storage_template_settings_description": "", + "sidecar_job": "Sidecar metadáta", + "sidecar_job_description": "Objavte alebo synchronizujte metadáta Sidecar zo súborového systému", + "slideshow_duration_description": "Čas zobrazenia obrázku v sekundách", + "smart_search_job_description": "Spustite strojové učenie na médiách na podporu inteligentného vyhľadávania", + "storage_template_date_time_description": "Časová pečiatka vytvorenia médií sa používa pre informácie o dátume a čase", + "storage_template_date_time_sample": "Čas vzorky {date}", + "storage_template_enable_description": "Povoliť nástroj šablóny úložiska", + "storage_template_hash_verification_enabled": "Overenie hash povolené", + "storage_template_hash_verification_enabled_description": "Povolí overenie hash, nezakazujte to, pokiaľ si nie ste istí dôsledkami", + "storage_template_migration": "Migrácia šablóny úložiska", + "storage_template_migration_description": "Použite aktuálnu {template} na predtým nahrané médiá", + "storage_template_migration_info": "Zmeny šablón sa budú vzťahovať iba na nové diela. Ak chcete šablónu spätne použiť na predtým nahrané médiá, spustite {job}.", + "storage_template_migration_job": "Úloha migrácie šablóny úložiska", + "storage_template_more_details": "Ďalšie podrobnosti o tejto funkcii nájdete v Šablóna úložiska a jej dôsledky", + "storage_template_onboarding_description": "Keď je táto funkcia povolená, automaticky usporiada súbory na základe šablóny definovanej používateľom. Kvôli problémom so stabilitou bola funkcia predvolene vypnutá. Viac informácií nájdete v dokumentácii.", + "storage_template_path_length": "Približný limit dĺžky cesty: {length, number}/{limit, number}", + "storage_template_settings": "Šablóna úložiska", + "storage_template_settings_description": "Spravujte štruktúru priečinkov a názov súboru odovzdaného média", + "storage_template_user_label": "{label} je Štítok úložiska používateľa", "system_settings": "Nastavenia systému", + "tag_cleanup_job": "Premazanie značiek", + "template_email_available_tags": "V šablóne môžeš použiť nasledujúce premenné: {tags}", + "template_email_if_empty": "Ak nie je zadaná žiadna šablóna, bude použitá predvolená šablóna.", + "template_email_invite_album": "Šablóna pre Pozvánka do albumu", + "template_email_preview": "Ukážka", + "template_email_settings": "Emailové šablóny", + "template_email_settings_description": "Spravovanie vlastných šablón pre emailové upozornenia", + "template_email_update_album": "Upraviť šablónu albumu", + "template_email_welcome": "Šablóna uvítajúceho emailu", + "template_settings": "Šablóna upozornení", + "template_settings_description": "Spravovanie vlastných šablón upozornení.", "theme_custom_css_settings": "Vlastné CSS", - "theme_custom_css_settings_description": "", + "theme_custom_css_settings_description": "CSS štýly umožňujú prispôsobiť dizajn Immich.", "theme_settings": "Nastavenia témovania", "theme_settings_description": "Spravovať prispôsobenie webového rozhrania Immich", + "these_files_matched_by_checksum": "Tieto súbory zodpovedajú kontrolným súčtom", "thumbnail_generation_job": "Generovať Miniatúry", - "thumbnail_generation_job_description": "", - "transcode_policy_description": "", - "transcoding_acceleration_api": "", - "transcoding_acceleration_api_description": "", + "thumbnail_generation_job_description": "Generujte veľké, malé a rozmazané miniatúry pre každé médium, ako aj miniatúry pre každú osobu", + "transcoding_acceleration_api": "API pre akceleráciu", + "transcoding_acceleration_api_description": "Rozhranie API, ktoré bude interagovať s vaším zariadením s cieľom urýchliť prekódovanie. Toto nastavenie je „najlepšie úsilie“: pri zlyhaní sa vráti k softvérovému prekódovaniu. VP9 môže alebo nemusí fungovať v závislosti od vášho hardvéru.", "transcoding_acceleration_nvenc": "NVENC (vyžaduje grafickú kartu NVIDIA)", "transcoding_acceleration_qsv": "Quick Sync (vyžaduje 7. generáciu Intel procesora alebo novšie)", - "transcoding_acceleration_rkmpp": "", + "transcoding_acceleration_rkmpp": "RKMPP (iba na Rockchip SOC)", "transcoding_acceleration_vaapi": "VAAPI", - "transcoding_accepted_audio_codecs": "", - "transcoding_accepted_audio_codecs_description": "", - "transcoding_accepted_video_codecs": "", - "transcoding_accepted_video_codecs_description": "", + "transcoding_accepted_audio_codecs": "Akceptované zvukové kodeky", + "transcoding_accepted_audio_codecs_description": "Vyberte, ktoré zvukové kodeky nie je potrebné prekódovať. Používa sa len pre určité zásady prekódovania.", + "transcoding_accepted_containers": "Akceptované kontajnery", + "transcoding_accepted_containers_description": "Vyberte, ktoré formáty kontajnerov nie je potrebné remuxovať na MP4. Používa sa len pre určité zásady prekódovania.", + "transcoding_accepted_video_codecs": "Akceptované video kodeky", + "transcoding_accepted_video_codecs_description": "Vyberte, ktoré video kodeky nie je potrebné prekódovať. Používa sa len pre určité zásady prekódovania.", "transcoding_advanced_options_description": "Možnosti, ktoré by väčšina používateľov nemala meniť", - "transcoding_audio_codec": "", - "transcoding_audio_codec_description": "", - "transcoding_bitrate_description": "", - "transcoding_constant_quality_mode": "", - "transcoding_constant_quality_mode_description": "", - "transcoding_constant_rate_factor": "", - "transcoding_constant_rate_factor_description": "", - "transcoding_disabled_description": "", + "transcoding_audio_codec": "Zvukový kodek", + "transcoding_audio_codec_description": "Opus je najkvalitnejšia možnosť, ale má nižšiu kompatibilitu so starými zariadeniami alebo softvérom.", + "transcoding_bitrate_description": "Videá presahujúce maximálnu bitovú rýchlosť alebo videá, ktoré nie sú v akceptovanom formáte", + "transcoding_codecs_learn_more": "Ak sa chcete dozvedieť viac o tu použitej terminológii, pozrite si dokumentáciu FFmpeg pre kodek H.264, kodek HEVC a VP9 kodek.", + "transcoding_constant_quality_mode": "Režim konštantnej kvality", + "transcoding_constant_quality_mode_description": "ICQ je lepšie ako CQP, ale niektoré zariadenia na hardvérovú akceleráciu tento režim nepodporujú. Nastavenie tejto možnosti uprednostní špecifikovaný režim pri použití kódovania založeného na kvalite. Ignorované spoločnosťou NVENC, pretože nepodporuje ICQ.", + "transcoding_constant_rate_factor": "Faktor konštantnej rýchlosti (-crf)", + "transcoding_constant_rate_factor_description": "Úroveň kvality videa. Typické hodnoty sú 23 pre H.264, 28 pre HEVC, 31 pre VP9 a 35 pre AV1. Nižšie je lepšie, ale vytvára väčšie súbory.", + "transcoding_disabled_description": "Neprekódujte žiadne videá, na niektorých klientoch môže prerušiť prehrávanie", "transcoding_hardware_acceleration": "Hardvérová akcelerácia", - "transcoding_hardware_acceleration_description": "", - "transcoding_hardware_decoding": "", - "transcoding_hardware_decoding_setting_description": "", - "transcoding_hevc_codec": "", - "transcoding_max_b_frames": "", - "transcoding_max_b_frames_description": "", - "transcoding_max_bitrate": "", - "transcoding_max_bitrate_description": "", - "transcoding_max_keyframe_interval": "", - "transcoding_max_keyframe_interval_description": "", - "transcoding_optimal_description": "", - "transcoding_preferred_hardware_device": "", - "transcoding_preferred_hardware_device_description": "", - "transcoding_preset_preset": "", - "transcoding_preset_preset_description": "", - "transcoding_reference_frames": "", - "transcoding_reference_frames_description": "", - "transcoding_required_description": "", + "transcoding_hardware_acceleration_description": "Experimentálne; oveľa rýchlejšie, ale bude mať nižšiu kvalitu pri rovnakej bitovej rýchlosti", + "transcoding_hardware_decoding": "Hardvérové dekódovanie", + "transcoding_hardware_decoding_setting_description": "Umožňuje end-to-end zrýchlenie namiesto iba zrýchlenia kódovania. Nemusí fungovať na všetkých videách.", + "transcoding_hevc_codec": "Kodek HEVC", + "transcoding_max_b_frames": "Maximálny počet B-snímkov", + "transcoding_max_b_frames_description": "Vyššie hodnoty zvyšujú účinnosť kompresie, ale spomaľujú kódovanie. Nemusí byť kompatibilný s hardvérovou akceleráciou na starších zariadeniach. Hodnota 0 zakáže B-snímky, zatiaľ čo -1 nastaví túto hodnotu automaticky.", + "transcoding_max_bitrate": "Maximálna bitová rýchlosť", + "transcoding_max_bitrate_description": "Nastavenie maximálneho dátového toku môže zvýšiť predvídateľnosť veľkosti súborov za cenu menšieho zníženia kvality. Pri rozlíšení 720p sú typické hodnoty 2600k pre VP9 alebo HEVC alebo 4500k pre H.264. Zakázané, ak je nastavená hodnota 0.", + "transcoding_max_keyframe_interval": "Maximálny interval medzi kľúčovými snímkami", + "transcoding_max_keyframe_interval_description": "Nastavuje maximálnu vzdialenosť medzi kľúčovými snímkami. Nižšie hodnoty zhoršujú účinnosť kompresie, ale zlepšujú časy vyhľadávania a môžu zlepšiť kvalitu v scénach s rýchlym pohybom. Hodnota 0 nastavuje túto hodnotu automaticky.", + "transcoding_optimal_description": "Videá s vyšším ako cieľovým rozlíšením alebo videá, ktoré nie sú v prijateľnom formáte", + "transcoding_preferred_hardware_device": "Uprednostňované hardvérové zariadenie", + "transcoding_preferred_hardware_device_description": "Platí len pre VAAPI a QSV. Nastavuje uzol dri, ktorý sa používa na hardvérové prekódovanie.", + "transcoding_preset_preset": "Prednastavenie (-preset)", + "transcoding_preset_preset_description": "Rýchlosť kompresie. Pomalšie predvoľby vytvárajú menšie súbory a zvyšujú kvalitu, keď sa zameriavajú na určitý dátový tok. VP9 ignoruje rýchlosti vyššie ako „rýchlejšie“.", + "transcoding_reference_frames": "Referenčné snímky", + "transcoding_reference_frames_description": "Počet snímok, na ktoré sa má odkazovať pri kompresii daného snímku. Vyššie hodnoty zvyšujú účinnosť kompresie, ale spomaľujú kódovanie. Hodnota 0 sa nastavuje automaticky.", + "transcoding_required_description": "Iba videá, ktoré nie sú v prijatom formáte", "transcoding_settings": "Nastavenia video transkódovania", - "transcoding_settings_description": "", - "transcoding_target_resolution": "", - "transcoding_target_resolution_description": "", - "transcoding_temporal_aq": "", - "transcoding_temporal_aq_description": "", + "transcoding_settings_description": "Správa informácií o rozlíšení a kódovaní videosúborov", + "transcoding_target_resolution": "Cieľové rozlíšenie", + "transcoding_target_resolution_description": "Vyššie rozlíšenia môžu zachovať viac detailov, ale ich kódovanie trvá dlhšie, majú väčšiu veľkosť súborov a môžu znížiť odozvu aplikácie.", + "transcoding_temporal_aq": "Časové AQ", + "transcoding_temporal_aq_description": "Platí len pre NVENC. Zvyšuje kvalitu scén s vysokým počtom detailov a nízkym počtom pohybov. Nemusí byť kompatibilný so staršími zariadeniami.", "transcoding_threads": "Vlákna", - "transcoding_threads_description": "", - "transcoding_tone_mapping": "", - "transcoding_tone_mapping_description": "", - "transcoding_tone_mapping_npl": "", - "transcoding_tone_mapping_npl_description": "", - "transcoding_transcode_policy": "", - "transcoding_two_pass_encoding": "", - "transcoding_two_pass_encoding_setting_description": "", - "transcoding_video_codec": "", - "transcoding_video_codec_description": "", + "transcoding_threads_description": "Vyššie hodnoty vedú k rýchlejšiemu kódovaniu, ale ponechávajú serveru menej priestoru na spracovanie iných úloh počas aktivity. Táto hodnota by nemala byť väčšia ako počet jadier CPU. Maximalizuje využitie, ak je nastavená na hodnotu 0.", + "transcoding_tone_mapping": "Tónové mapovanie", + "transcoding_tone_mapping_description": "Snaží sa zachovať vzhľad videí HDR pri konverzii na SDR. Každý algoritmus robí rôzne kompromisy v oblasti farieb, detailov a jasu. Hable zachováva detaily, Mobius zachováva farby a Reinhard zachováva jas.", + "transcoding_transcode_policy": "Politika prekódovania", + "transcoding_transcode_policy_description": "Zásady, kedy sa má video prekódovať. Videá HDR sa vždy prekódujú (okrem prípadov, keď je prekódovanie vypnuté).", + "transcoding_two_pass_encoding": "Dvojpriechodové kódovanie", + "transcoding_two_pass_encoding_setting_description": "Prekladajte v dvoch priechodoch, aby ste vytvorili lepšie zakódované videá. Keď je povolený maximálny dátový tok (vyžaduje sa na prácu s formátmi H.264 a HEVC), tento režim používa rozsah dátového toku na základe maximálneho dátového toku a ignoruje CRF. V prípade VP9 sa CRF môže použiť, ak je max bitrate vypnutý.", + "transcoding_video_codec": "Video kodek", + "transcoding_video_codec_description": "VP9 má vysokú účinnosť a kompatibilitu s webom, ale prekódovanie trvá dlhšie. HEVC má podobnú výkonnosť, ale nižšiu kompatibilitu s webom. H.264 je široko kompatibilný a rýchlo sa prekódováva, ale vytvára oveľa väčšie súbory. AV1 je najúčinnejší kodek, ale chýba mu podpora v starších zariadeniach.", "trash_enabled_description": "Povoliť funkcie koša", "trash_number_of_days": "Počet dní", - "trash_number_of_days_description": "", + "trash_number_of_days_description": "Počet dní, počas ktorých sa má majetok ponechať v koši pred jeho trvalým odstránením", "trash_settings": "Nastavenia koša", "trash_settings_description": "Spravovať nastavenia koša", + "untracked_files": "Nesledované súbory", + "untracked_files_description": "Tieto súbory aplikácia nesleduje. Môžu byť výsledkom neúspešných presunov, prerušeného odosielania alebo môžu zostať v dôsledku chyby", + "user_cleanup_job": "Premazanie používateľov", + "user_delete_delay": "Konto {user} a jeho médiá budú podľa plánu natrvalo vymazané za {delay, plural, one {# day} other {# days}}.", "user_delete_delay_settings": "Odstrániť oneskorenie", - "user_delete_delay_settings_description": "", + "user_delete_delay_settings_description": "Počet dní po odstránení na trvalé vymazanie účtu a aktív používateľa. Úloha odstraňovania používateľov sa spúšťa o polnoci, aby sa skontrolovali používatelia, ktorí sú pripravení na odstránenie. Zmeny tohto nastavenia sa vyhodnotia pri ďalšom spustení.", + "user_delete_immediately": "Konto a médiá {user} budú zaradené do frontu na trvalé vymazanie okamžite.", + "user_delete_immediately_checkbox": "Používateľ a médiá budú zaradení do frontu na okamžité vymazanie", "user_management": "Správa používateľov", "user_password_has_been_reset": "Heslo používateľa bolo resetované:", + "user_password_reset_description": "Poskytnite používateľovi dočasné heslo a informujte ho, že si ho bude musieť zmeniť pri ďalšom prihlásení.", + "user_restore_description": "{user} bude účet obnovený.", + "user_restore_scheduled_removal": "Obnoviť používateľa - plánované odstránenie na {date, date, long}", "user_settings": "Nastavenia používateľa", "user_settings_description": "Spravovať používateľské nastavenia", "user_successfully_removed": "Používateľ {email} bol úspešne odstránený.", "version_check_enabled_description": "Povoliť kontrolu verzie", + "version_check_implications": "Funkcia kontroly verzie sa spolieha na pravidelnú komunikáciu s github.com", "version_check_settings": "Kontrola verzie", "version_check_settings_description": "Povoliť/zakázať upozornenia na novú verziu", "video_conversion_job": "Prekódovať videá", - "video_conversion_job_description": "" + "video_conversion_job_description": "Prekódovanie videí pre širšiu kompatibilitu s prehliadačmi a zariadeniami" }, "admin_email": "Administrátorský email", "admin_password": "Administrátorské heslo", "administration": "Administrácia", "advanced": "Pokročilé", + "age_months": "Vek {months, plural, one {# month} other {# months}}", + "age_year_months": "Vek 1 rok, {months, plural, one {# month} other {# months}}", + "age_years": "{years, plural, other {Vek #}}", "album_added": "Album bol pridaný", "album_added_notification_setting_description": "Obdržať upozornenie emailom, keď ste pridaní do zdieľaného albumu", - "album_cover_updated": "", + "album_cover_updated": "Obal albumu aktualizovaný", "album_delete_confirmation": "Ste si istý, že chcete odstrániť album {album}?", + "album_delete_confirmation_description": "Ak je tento album zdieľaný, ostatní používatelia k nemu už nebudú mať prístup.", "album_info_updated": "Informácie albumu aktualizované", "album_leave": "Opustiť album?", "album_leave_confirmation": "Ste si istý, že chcete opustiť album {album}?", @@ -312,62 +371,94 @@ "album_options": "Nastavenia albumu", "album_remove_user": "Odstrániť používateľa?", "album_remove_user_confirmation": "Ste si istý, že chcete odstrániť používateľa {user}?", + "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_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}", + "album_user_removed": "Odstránený {user}", "album_with_link_access": "Umožnite komukoľvek s odkazom pozrieť si fotky a ľudí v tomto albume.", "albums": "Albumy", + "albums_count": "{count, plural, one {{count, number} Album} other {{count, number} Albumov}}", "all": "Všetko", "all_albums": "Všetky albumy", "all_people": "Všetci ľudia", "all_videos": "Všetky videa", "allow_dark_mode": "Povoliť tmavý režim", "allow_edits": "Povoliť úpravy", + "allow_public_user_to_download": "Povoľte verejnému používateľovi sťahovať", + "allow_public_user_to_upload": "Umožniť verejnému používateľovi nahrávať", "anti_clockwise": "Proti smeru hodinových ručičiek", "api_key": "API Klúč", + "api_key_description": "Táto hodnota sa zobrazí iba raz. Pred zatvorením okna ju určite skopírujte.", "api_key_empty": "Názov vášho API kĺuča by nemal byť prázdny", "api_keys": "API Kľúče", "app_settings": "Nastavenia Aplikácie", - "appears_in": "", + "appears_in": "Vyskytuje sa v", "archive": "Archivovať", - "archive_or_unarchive_photo": "", - "archived": "", + "archive_or_unarchive_photo": "Archivácia alebo odarchivovanie fotografie", + "archive_size": "Veľkosť archívu", + "archive_size_description": "Konfigurácia veľkosti archívu na stiahnutie (v GiB)", + "archived_count": "{count, plural, other {Archivovaných #}}", + "are_these_the_same_person": "Ide o tú istú osobu?", "are_you_sure_to_do_this": "Ste si istý, že to chcete urobiť?", "asset_added_to_album": "Pridané do albumu", "asset_adding_to_album": "Pridáva sa do albumu...", - "asset_offline": "", + "asset_description_updated": "Popis média bol aktualizovaný", + "asset_filename_is_offline": "Médium {filename} je offline", + "asset_has_unassigned_faces": "Položka má nepriradené tváre", + "asset_hashing": "Hašovanie...", + "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_skipped": "Preskočené", "asset_skipped_in_trash": "V koši", "asset_uploaded": "Nahrané", "asset_uploading": "Nahráva sa...", "assets": "Položky", + "assets_added_count": "{count, plural, one {Pridaná # položka} few {Pridané # položky} other {Pridaných # položek}}", + "assets_added_to_album_count": "Do albumu {count, plural, one {bola pridaná # položka} few {boli pridané # položky} other {bolo pridaných # položiek}}", + "assets_added_to_name_count": "{count, plural, one {Pridaná # položka} few {Pridané # položky} other {Pridaných # položiek}} do {hasName, select, true {alba {name}} other {nového albumu}}", + "assets_count": "{count, plural, one {# položka} few {# položky} other {# položiek}}", + "assets_moved_to_trash_count": "Do koša {count, plural, one {bola presunutá # položka} few {boli presunuté # položky} other {bolo presunutých # položiek}}", + "assets_permanently_deleted_count": "Trvalo {count, plural, one {vymazaná # položka} few {vymazané # položky} other {vymazaných # položiek}}", + "assets_removed_count": "{count, plural, one {Odstránená # položka} few {Odstránené # položky} other {Odstránených # položiek}}", + "assets_restore_confirmation": "Naozaj chcete obnoviť všetky vyhodené položky? Túto akciu nie je možné vrátiť späť! Upozorňujeme, že týmto spôsobom nie je možné obnoviť žiadne offline položky.", + "assets_restored_count": "{count, plural, one {Obnovená # položka} few {Obnovené # položky} other {Obnovených # položiek}}", + "assets_trashed_count": "{count, plural, one {Odstránená # položka} few {Odstránené # položky} other {Odstránených # položiek}}", + "assets_were_part_of_album_count": "{count, plural, one {Položka bola} other {Položky boli}} súčasťou albumu", "authorized_devices": "Autorizované zariadenia", "back": "Späť", - "backward": "", + "back_close_deselect": "Späť, zavrieť alebo zrušiť výber", + "backward": "Spätne", "birthdate_saved": "Dátum narodenia bol úspešne uložený", - "blurred_background": "", + "birthdate_set_description": "Dátum narodenia sa používa na výpočet veku tejto osoby v čase fotografie.", + "blurred_background": "Rozmazané pozadie", + "bugs_and_feature_requests": "Chyby a požiadavky na funkcie", + "build": "Budovať", + "build_image": "Vytvoriť obrázok", + "bulk_delete_duplicates_confirmation": "Naozaj chcete hromadne odstrániť {count, plural, one {# duplikátnu položku} few {# duplikáte položky} other {# duplikátnych položiek}}? Týmto sa zachová najväčšia položka z každej skupiny a všetky ostatné duplikáty sa natrvalo odstránia. Túto akciu nie je možné vrátiť späť!", + "bulk_keep_duplicates_confirmation": "Naozaj chceš ponechať {count, plural, one {# duplicitný súbor} other {# duplicitné súbory}}? Týmto sa vysporiadaš so všetkými duplicitnými skupinami bez mazania súborov.", + "bulk_trash_duplicates_confirmation": "Naozaj chcete hromadne vymazať {count, plural, one {# duplicitný súbor} other {# duplicitné súbory}}? Týmto si ponecháš z každej skupiny najväčší súbor a vymažeš všetky ostatné duplicitné súbory v skupine.", "buy": "Kúpiť Immich", "camera": "Fotoaparát", "camera_brand": "Výrobca fotoaparátu", "camera_model": "Model fotoaparátu", "cancel": "Zrušiť", "cancel_search": "Zrušiť vyhľadávanie", - "cannot_merge_people": "", + "cannot_merge_people": "Nie je možné zlúčiť ľudí", + "cannot_undo_this_action": "Túto akciu nemôžete vrátiť späť!", "cannot_update_the_description": "Popis nie je možné aktualizovať", - "cant_apply_changes": "", - "cant_get_faces": "", - "cant_search_people": "", - "cant_search_places": "", "change_date": "Upraviť dátum", "change_expiration_time": "Zmeniť čas vypršania", "change_location": "Upraviť lokáciu", "change_name": "Upraviť meno", - "change_name_successfully": "", + "change_name_successfully": "Meno bolo zmenené", "change_password": "Zmeniť Heslo", - "change_your_password": "", - "changed_visibility_successfully": "", + "change_password_description": "Buď sa do systému prihlasujete prvýkrát, alebo bola podaná žiadosť o zmenu hesla. Nižšie zadajte nové heslo.", + "change_your_password": "Zmeňte si heslo", + "changed_visibility_successfully": "Viditeľnosť bola úspešne zmenená", "check_all": "Skontrolovať Všetko", "check_logs": "Skontrolovať logy", + "choose_matching_people_to_merge": "Vyberte rovnakých ľudí na zlúčenie", "city": "Mesto", "clear": "VYMAZAŤ", "clear_all": "Vymazať všetko", @@ -376,14 +467,18 @@ "clear_value": "Vymazať hodnotu", "clockwise": "V smere hodinových ručičiek", "close": "Zatvoriť", - "collapse_all": "", - "color_theme": "", + "collapse": "Zbaliť", + "collapse_all": "Zbaliť všetko", + "color": "Farba", + "color_theme": "Farba témy", "comment_deleted": "Komentár bol odstránený", "comment_options": "Možnosti komentára", + "comments_and_likes": "Komentáre a páči sa mi to", "comments_are_disabled": "Komentáre sú vypnuté", "confirm": "Potvrdiť", "confirm_admin_password": "Potvrdiť Administrátorské Heslo", "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_password": "Potvrdiť heslo", "contain": "", "context": "Kontext", @@ -391,20 +486,21 @@ "copied_image_to_clipboard": "Obrázok skopírovaný do schránky.", "copied_to_clipboard": "Skopírované do schránky!", "copy_error": "Chyba pri kopírovaní", - "copy_file_path": "", + "copy_file_path": "Kopírovať cestu odkazu", "copy_image": "Skopírovať obrázok", "copy_link": "Skopírovať odkaz", "copy_link_to_clipboard": "Skopírovať do schránky", "copy_password": "Skopírovať heslo", "copy_to_clipboard": "Skopírovať do schránky", "country": "Štát", - "cover": "", - "covers": "", + "cover": "Titulka", + "covers": "Dlaždice", "create": "Vytvoriť", "create_album": "Vytvoriť album", "create_library": "Vytvoriť knižnicu", "create_link": "Vytvoriť odkaz", "create_link_to_share": "Vytvoriť odkaz na zdieľanie", + "create_link_to_share_description": "Umožniť každému kto má odkaz zobraziť vybrané fotografie", "create_new_person": "Vytvoriť novú osobu", "create_new_user": "Vytvorenie nového používateľa", "create_tag": "Vytvoriť značku", @@ -454,13 +550,6 @@ "downloading_asset_filename": "Stahovanie súboru {filename}", "duplicates": "Duplikáty", "duration": "Trvanie", - "durations": { - "days": "", - "hours": "", - "minutes": "", - "months": "", - "years": "" - }, "edit": "Upraviť", "edit_album": "Upraviť album", "edit_avatar": "Upraviť postavu", @@ -484,8 +573,6 @@ "editor_crop_tool_h2_aspect_ratios": "Pomer strán", "editor_crop_tool_h2_rotation": "Rotácia", "email": "E-mail", - "empty": "", - "empty_album": "", "empty_trash": "Vyprázdniť kôš", "enable": "Aktivovať", "enabled": "Aktivovaný", @@ -500,8 +587,6 @@ "unable_to_change_album_user_role": "", "unable_to_change_date": "", "unable_to_change_location": "", - "unable_to_check_item": "", - "unable_to_check_items": "", "unable_to_create_admin_account": "", "unable_to_create_library": "", "unable_to_create_user": "", @@ -519,11 +604,9 @@ "unable_to_play_video": "", "unable_to_refresh_user": "", "unable_to_remove_album_users": "", - "unable_to_remove_comment": "", "unable_to_remove_library": "", "unable_to_remove_partner": "", "unable_to_remove_reaction": "", - "unable_to_remove_user": "", "unable_to_repair_items": "", "unable_to_reset_password": "", "unable_to_resolve_duplicate": "", @@ -545,10 +628,6 @@ "unable_to_update_settings": "", "unable_to_update_user": "" }, - "every_day_at_onepm": "", - "every_night_at_midnight": "", - "every_night_at_twoam": "", - "every_six_hours": "", "exif": "Exif", "exit_slideshow": "Opustiť Slideshow", "expand_all": "", @@ -561,30 +640,24 @@ "extension": "Rozšírenie", "external": "Externý", "external_libraries": "", - "failed_to_get_people": "", "favorite": "Obľúbené", "favorite_or_unfavorite_photo": "", "favorites": "Obľúbené", - "feature": "", "feature_photo_updated": "", - "featurecollection": "", "features": "Funkcie", "file_name": "Meno súboru", "file_name_or_extension": "", "filename": "Meno súboru", - "files": "", "filetype": "Typ súboru", "filter_people": "Filtrovať ľudí", "find_them_fast": "Nájdite ich rýchlejšie podľa mena", "fix_incorrect_match": "", - "force_re-scan_library_files": "", "forward": "", "general": "Všeobecné", "get_help": "", "getting_started": "", "go_back": "", "go_to_search": "", - "go_to_share_page": "", "group_albums_by": "", "has_quota": "", "hide_gallery": "", @@ -593,7 +666,6 @@ "host": "", "hour": "", "image": "", - "img": "", "immich_logo": "", "import_path": "", "in_archive": "", @@ -610,7 +682,6 @@ }, "invite_people": "", "invite_to_album": "Pozvať do albumu", - "job_settings_description": "", "jobs": "", "keep": "", "keyboard_shortcuts": "", @@ -685,6 +756,7 @@ "no_results": "", "no_shared_albums_message": "", "not_in_any_album": "", + "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", "notes": "", "notification_toggle_setting_description": "Povoliť e-mailové upozornenia", "notifications": "Oznámenia", @@ -696,7 +768,6 @@ "onboarding_welcome_user": "Vitaj, {user}", "online": "", "only_favorites": "", - "only_refreshes_modified_files": "", "open_the_search_filters": "", "options": "Nastavenia", "or": "alebo", @@ -725,7 +796,6 @@ "pending": "", "people": "Ľudia", "people_sidebar_description": "", - "perform_library_tasks": "", "permanent_deletion_warning": "", "permanent_deletion_warning_setting_description": "", "permanently_delete": "", @@ -740,7 +810,6 @@ "play_memories": "", "play_motion_photo": "", "play_or_pause_video": "", - "point": "", "port": "", "preset": "", "preview": "", @@ -755,8 +824,6 @@ "purchase_button_activate": "Aktivovať", "purchase_button_never_show_again": "Už viac nezobrazovať", "purchase_panel_title": "Podporiť projekt", - "range": "", - "raw": "", "reaction_options": "", "read_changelog": "", "recent": "Nedávne", @@ -779,7 +846,6 @@ "reset": "Resetovať", "reset_password": "Obnoviť heslo", "reset_people_visibility": "", - "reset_settings_to_default": "", "restore": "Obnoviť", "restore_user": "Obnoviť používateľa", "resume": "Pokračovať", @@ -791,8 +857,6 @@ "saved_settings": "", "say_something": "Napíšte niečo", "scan_all_libraries": "", - "scan_all_library_files": "", - "scan_new_library_files": "", "scan_settings": "Nastavenia skenovania", "search": "Vyhľadávanie", "search_albums": "Hľadať albumy", @@ -823,7 +887,6 @@ "selected": "Vybraté", "send_message": "Odoslať správu", "send_welcome_email": "Odoslať uvítací e-mail", - "server": "", "server_stats": "Štatistiky servera", "server_version": "Verzia servera", "set": "Nastaviť", @@ -881,7 +944,7 @@ "stop_motion_photo": "", "stop_photo_sharing": "Zastaviť zdieľanie vašich fotiek?", "storage": "Ukladací priestor", - "storage_label": "", + "storage_label": "Štítok úložiska", "submit": "Odoslať", "suggestions": "Návrhy", "sunrise_on_the_beach": "", @@ -899,18 +962,15 @@ "to_trash": "Kôš", "toggle_settings": "", "toggle_theme": "", - "toggle_visibility": "", "total_usage": "", "trash": "Kôš", "trash_all": "", "trash_no_results_message": "Vymazané fotografie a videá sa zobrazia tu.", "type": "", "unarchive": "Odarchivovať", - "unarchived": "", "unfavorite": "Odznačiť ako obľúbené", "unhide_person": "", "unknown": "", - "unknown_album": "", "unknown_year": "Neznámy rok", "unlink_oauth": "", "unlinked_oauth_account": "", @@ -932,6 +992,8 @@ "user_id": "Používateľské ID", "user_role_set": "Nastav {user} ako {role}", "user_usage_detail": "", + "user_usage_stats": "Štatistiky využitia účtu", + "user_usage_stats_description": "Zobraziť štatistiky využitia účtu", "username": "Používateľské meno", "users": "Používatelia", "utilities": "Nástroje", @@ -951,12 +1013,11 @@ "view_links": "Zobraziť odkazy", "view_next_asset": "Zobraziť nasledujúci súbor", "view_previous_asset": "Zobraziť predchádzajúci súbor", - "viewer": "", "waiting": "", "warning": "Varovanie", "week": "Týždeň", "welcome": "Vitajte", - "welcome_to_immich": "Vytajte v immich", + "welcome_to_immich": "Vitajte v Immich", "year": "Rok", "yes": "Áno", "you_dont_have_any_shared_links": "Nemáte žiadne zdielané linky", diff --git a/i18n/sl.json b/i18n/sl.json index dd14e5ef947ed..b9a1d24d5332d 100644 --- a/i18n/sl.json +++ b/i18n/sl.json @@ -2,7 +2,7 @@ "about": "O programu", "account": "Račun", "account_settings": "Nastavitve računa", - "acknowledge": "Potrdi", + "acknowledge": "Sem seznanjen", "action": "Dejanje", "actions": "Dejanja", "active": "Aktivno", @@ -16,34 +16,43 @@ "add_exclusion_pattern": "Dodaj vzorec izključitve", "add_import_path": "Dodaj pot uvoza", "add_location": "Dodaj lokacijo", - "add_more_users": "Dodaj še več uporabnikov", + "add_more_users": "Dodaj več uporabnikov", "add_partner": "Dodaj partnerja", "add_path": "Dodaj pot", "add_photos": "Dodaj fotografije", - "add_to": "Dodaj k...", + "add_to": "Dodaj v...", "add_to_album": "Dodaj v album", "add_to_shared_album": "Dodaj k deljenemu albumu", + "add_url": "Dodaj URL", "added_to_archive": "Dodano v arhiv", "added_to_favorites": "Dodano med priljubljene", "added_to_favorites_count": "{count, number} dodanih med priljubljene", "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/**\".", + "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.", "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 Server Command.", + "authentication_settings_reenable": "Ponovno omogoči z uporabo strežniškega ukaza.", "background_task_job": "Opravila v ozadju", + "backup_database": "Varnostna kopija baze", + "backup_database_enable_description": "Omogoči varnostno kopiranje baze", + "backup_keep_last_amount": "Število prejšnjih obdržanih varnostnih kopij", + "backup_settings": "Nastavitve varnostnega kopiranja", + "backup_settings_description": "Upravljanje nastavitev varnostnih kopij", "check_all": "Označi vse", - "cleared_jobs": "Razčiščeno delo za: {job}", + "cleared_jobs": "Razčiščeno opravilo za: {job}", "config_set_by_file": "Konfiguracija je trenutno nastavljena s konfiguracijsko datoteko", "confirm_delete_library": "Ali ste prepričani, da želite izbrisati knjižnico {library}?", - "confirm_delete_library_assets": "Ali ste prepričani, da želite izbrisati to knjižnico? S tem boste iz Immicha izbrisali vsa {count} vsebovana sredstva in tega dejanja ni mogoče razveljaviti. Datoteke bodo ostale na disku.", + "confirm_delete_library_assets": "Ali ste prepričani, da želite izbrisati to knjižnico? To bo iz Immicha izbrisalo {count, plural, one {# contained asset} other {all # vsebovanih virov}} in tega ni možno razveljaviti. Datoteke bodo ostale na disku.", "confirm_email_below": "Za potrditev vnesite \"{email}\" spodaj", "confirm_reprocess_all_faces": "Ali ste prepričani, da želite znova obdelati vse obraze? S tem boste počistili tudi že imenovane osebe.", "confirm_user_password_reset": "Ali ste prepričani, da želite ponastaviti geslo uporabnika {user}?", - "crontab_guru": "Crontab guru", + "create_job": "Ustvari opravilo", + "cron_expression": "Nastavitveni izraz Cron", + "cron_expression_description": "Nastavite interval skeniranja z uporabo zapisa cron. Za več informacij poglej npr. Crontab Guru", + "cron_expression_presets": "Prednastavitve izraza Cron", "disable_login": "Onemogoči prijavo", - "disabled": "", "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_created_at": "Zunanja knjižnica (ustvarjena dne {date})", @@ -54,31 +63,32 @@ "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.", "forcing_refresh_library_files": "Vsiljena osvežitev vseh datotek knjižnice", + "image_format": "Format", "image_format_description": "WebP ustvari manjše datoteke kot JPEG, vendar je počasnejši za kodiranje.", "image_prefer_embedded_preview": "Uporabi raje vdelan predogled", "image_prefer_embedded_preview_setting_description": "Uporabite vdelane predoglede v fotografije RAW kot vhod za obdelavo slik, ko so na voljo. To lahko ustvari natančnejše barve za nekatere slike, vendar je kakovost predogleda odvisna od kamere in slika ima lahko več artefaktov stiskanja.", "image_prefer_wide_gamut": "Uporabi raje širok razpon", "image_prefer_wide_gamut_setting_description": "Uporabite P3 Display za sličice. To bolje ohranja živahnost slik s širokimi barvnimi prostori, vendar so lahko slike videti drugače na starih napravah s staro različico brskalnika. Slike sRGB se ohranijo kot sRGB, da se izognejo barvnim zamikom.", - "image_preview_format": "Oblika predogleda", - "image_preview_resolution": "Ločljivost predogleda", - "image_preview_resolution_description": "Uporablja se pri ogledu ene fotografije in za strojno učenje. Višje ločljivosti lahko ohranijo več podrobnosti, vendar kodiranje traja dlje, imajo večje velikosti datotek in lahko zmanjšajo odzivnost aplikacije.", + "image_preview_description": "Slika srednje velikosti z odstranjenimi metapodatki, ki se uporablja pri ogledu posameznega sredstva in za strojno učenje", + "image_preview_quality_description": "Kakovost predogleda od 1-100. Višje je boljše, vendar ustvarja večje datoteke in lahko zmanjša odzivnost aplikacije. Nastavitev nizke vrednosti lahko vpliva na kakovost strojnega učenja.", + "image_preview_title": "Nastavitve predogleda", "image_quality": "Kvaliteta", - "image_quality_description": "Kakovost slike od 1-100. Višja je boljša za kakovost, vendar ustvarja večje datoteke in ta možnost lahko vpliva na predogled in sličice.", + "image_resolution": "Resolucija", + "image_resolution_description": "Višje ločljivosti lahko ohranijo več podrobnosti, vendar kodiranje traja dlje, imajo večje velikosti datotek in lahko zmanjšajo odzivnost aplikacije.", "image_settings": "Nastavitve slike", "image_settings_description": "Upravljajte kakovost in ločljivost ustvarjenih slik", - "image_thumbnail_format": "Oblika sličic", - "image_thumbnail_resolution": "Ločljivost sličic", - "image_thumbnail_resolution_description": "Uporablja se pri ogledovanju skupin fotografij (glavna časovnica, pogled albuma itd.). Višje ločljivosti lahko ohranijo več podrobnosti, vendar kodiranje traja dlje, imajo večje velikosti datotek in lahko zmanjšajo odzivnost aplikacije.", + "image_thumbnail_description": "Majhna sličica z odstranjenimi metapodatki, ki se uporablja pri ogledovanju skupin fotografij, kot je glavna časovnica", + "image_thumbnail_quality_description": "Kakovost sličic od 1-100. Višje je boljše, vendar ustvarja večje datoteke in lahko zmanjša odzivnost aplikacije.", + "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_settings": "Nastavitve opravil", "job_settings_description": "Upravljaj sočasnost opravil", "job_status": "Status opravila", - "jobs_delayed": "{jobCount} zadržan", - "jobs_failed": "{jobCount} neuspešen", + "jobs_delayed": "{jobCount, plural, other {# zadržan}}", + "jobs_failed": "{jobCount, plural, other {# neuspešen}}", "library_created": "Ustvarjena knjižnica: {library}", - "library_cron_expression": "", - "library_cron_expression_presets": "", "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.", "library_scanning": "Periodični pregledi", @@ -94,7 +104,7 @@ "logging_level_description": "Nivo dnevnika, ko je le-ta omogočen.", "logging_settings": "Dnevnik", "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 delo za 'Pametno iskanje' za vse slike.", + "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", "machine_learning_duplicate_detection_enabled": "Omogoči zaznavanje dvojnikov", "machine_learning_duplicate_detection_enabled_description": "Če je onemogočeno, bodo popolnoma enaki posnetki še vedno obravnavani.", @@ -102,732 +112,1229 @@ "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_description": "", - "machine_learning_facial_recognition_model": "", - "machine_learning_facial_recognition_model_description": "", - "machine_learning_facial_recognition_setting_description": "", - "machine_learning_max_detection_distance": "", - "machine_learning_max_detection_distance_description": "", - "machine_learning_max_recognition_distance": "", - "machine_learning_max_recognition_distance_description": "", - "machine_learning_min_detection_score": "", - "machine_learning_min_detection_score_description": "", - "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": "", - "machine_learning_smart_search_enabled_description": "", - "machine_learning_url_description": "", - "manage_log_settings": "", - "map_dark_style": "", - "map_enable_description": "", - "map_light_style": "", - "map_reverse_geocoding": "", - "map_reverse_geocoding_enable_description": "", - "map_reverse_geocoding_settings": "", - "map_settings": "", - "map_settings_description": "", - "map_style_description": "", - "metadata_extraction_job_description": "", - "migration_job_description": "", - "notification_email_from_address": "", - "notification_email_from_address_description": "", - "notification_email_host_description": "", - "notification_email_ignore_certificate_errors": "", - "notification_email_ignore_certificate_errors_description": "", - "notification_email_password_description": "", - "notification_email_port_description": "", - "notification_email_sent_test_email_button": "", - "notification_email_setting_description": "", - "notification_email_test_email_failed": "", - "notification_email_test_email_sent": "", - "notification_email_username_description": "", - "notification_enable_email_notifications": "", - "notification_settings": "", - "notification_settings_description": "", - "oauth_auto_launch": "", - "oauth_auto_launch_description": "", - "oauth_auto_register": "", - "oauth_auto_register_description": "", - "oauth_button_text": "", - "oauth_client_id": "", - "oauth_client_secret": "", - "oauth_enable_description": "", - "oauth_issuer_url": "", - "oauth_mobile_redirect_uri": "", - "oauth_mobile_redirect_uri_override": "", - "oauth_mobile_redirect_uri_override_description": "", - "oauth_scope": "", - "oauth_settings": "", - "oauth_settings_description": "", - "oauth_signing_algorithm": "", - "oauth_storage_label_claim": "", - "oauth_storage_label_claim_description": "", - "oauth_storage_quota_claim": "", - "oauth_storage_quota_claim_description": "", - "oauth_storage_quota_default": "", - "oauth_storage_quota_default_description": "", - "password_enable_description": "", - "password_settings": "", - "password_settings_description": "", - "server_external_domain_settings": "", - "server_external_domain_settings_description": "", - "server_settings": "", - "server_settings_description": "", - "server_welcome_message": "", - "server_welcome_message_description": "", - "sidecar_job_description": "", - "slideshow_duration_description": "", - "smart_search_job_description": "", - "storage_template_enable_description": "", - "storage_template_hash_verification_enabled": "", - "storage_template_hash_verification_enabled_description": "", - "storage_template_migration_job": "", - "storage_template_settings": "", - "storage_template_settings_description": "", - "theme_custom_css_settings": "", - "theme_custom_css_settings_description": "", - "theme_settings": "", - "theme_settings_description": "", - "thumbnail_generation_job_description": "", - "transcode_policy_description": "", - "transcoding_acceleration_api": "", - "transcoding_acceleration_api_description": "", - "transcoding_acceleration_nvenc": "", - "transcoding_acceleration_qsv": "", - "transcoding_acceleration_rkmpp": "", - "transcoding_acceleration_vaapi": "", - "transcoding_accepted_audio_codecs": "", - "transcoding_accepted_audio_codecs_description": "", - "transcoding_accepted_video_codecs": "", - "transcoding_accepted_video_codecs_description": "", - "transcoding_advanced_options_description": "", - "transcoding_audio_codec": "", - "transcoding_audio_codec_description": "", - "transcoding_bitrate_description": "", - "transcoding_constant_quality_mode": "", - "transcoding_constant_quality_mode_description": "", - "transcoding_constant_rate_factor": "", - "transcoding_constant_rate_factor_description": "", - "transcoding_disabled_description": "", - "transcoding_hardware_acceleration": "", - "transcoding_hardware_acceleration_description": "", - "transcoding_hardware_decoding": "", - "transcoding_hardware_decoding_setting_description": "", - "transcoding_hevc_codec": "", - "transcoding_max_b_frames": "", - "transcoding_max_b_frames_description": "", - "transcoding_max_bitrate": "", - "transcoding_max_bitrate_description": "", - "transcoding_max_keyframe_interval": "", - "transcoding_max_keyframe_interval_description": "", - "transcoding_optimal_description": "", - "transcoding_preferred_hardware_device": "", - "transcoding_preferred_hardware_device_description": "", - "transcoding_preset_preset": "", - "transcoding_preset_preset_description": "", - "transcoding_reference_frames": "", - "transcoding_reference_frames_description": "", - "transcoding_required_description": "", - "transcoding_settings": "", - "transcoding_settings_description": "", - "transcoding_target_resolution": "", - "transcoding_target_resolution_description": "", - "transcoding_temporal_aq": "", - "transcoding_temporal_aq_description": "", - "transcoding_threads": "", - "transcoding_threads_description": "", - "transcoding_tone_mapping": "", - "transcoding_tone_mapping_description": "", - "transcoding_tone_mapping_npl": "", - "transcoding_tone_mapping_npl_description": "", - "transcoding_transcode_policy": "", - "transcoding_two_pass_encoding": "", - "transcoding_two_pass_encoding_setting_description": "", - "transcoding_video_codec": "", - "transcoding_video_codec_description": "", - "trash_enabled_description": "", - "trash_number_of_days": "", - "trash_number_of_days_description": "", - "trash_settings": "", - "trash_settings_description": "", - "user_delete_delay_settings": "", - "user_delete_delay_settings_description": "", - "user_settings": "", - "user_settings_description": "", - "version_check_enabled_description": "", - "version_check_settings": "", - "version_check_settings_description": "", - "video_conversion_job_description": "" + "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.", + "machine_learning_facial_recognition_setting": "Omogoči prepoznavanje obraza", + "machine_learning_facial_recognition_setting_description": "Če je onemogočeno, slike ne bodo kodirane za prepoznavanje obraza in ne bodo zapolnile razdelka Ljudje na strani Razišči.", + "machine_learning_max_detection_distance": "Največja razdalja zaznavanja", + "machine_learning_max_detection_distance_description": "Največja razdalja med dvema slikama za dvojnike, ki se giblje od 0,001 do 0,1. Višje vrednosti bodo zaznale več dvojnikov, vendar lahko povzročijo lažne pozitivne rezultate.", + "machine_learning_max_recognition_distance": "Največja razdalja za prepoznavanje", + "machine_learning_max_recognition_distance_description": "Največja razdalja med dvema obrazoma za isto osebo, ki se giblje od 0-2. Znižanje lahko prepreči označevanje dveh oseb kot iste osebe, zvišanje pa lahko prepreči označevanje iste osebe kot dve različni osebi. Upoštevajte, da je lažje združiti dve osebi kot eno osebo razdeliti na dva dela, zato se zmotite pri nižjem pragu, kadar je to mogoče.", + "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_settings": "Nastavitve strojnega učenja", + "machine_learning_settings_description": "Upravljajte funkcije in nastavitve strojnega učenja", + "machine_learning_smart_search": "Pametno iskanje", + "machine_learning_smart_search_description": "Semantično poiščite slike z uporabo vdelav CLIP", + "machine_learning_smart_search_enabled": "Omogoči pametno iskanje", + "machine_learning_smart_search_enabled_description": "Če je onemogočeno, slike ne bodo kodirane za pametno iskanje.", + "machine_learning_url_description": "URL strežnika za strojno učenje. Če je na voljo več kot en URL, bo vsak strežnik poskusen posamično, dokler se eden ne odzove uspešno, v vrstnem redu od prvega do zadnjega.", + "manage_concurrency": "Upravljanje sočasnosti", + "manage_log_settings": "Upravljanje nastavitev dnevnika", + "map_dark_style": "Temni način", + "map_enable_description": "Omogoči funkcije zemljevida", + "map_gps_settings": "Nastavitve zemljevida in GPS", + "map_gps_settings_description": "Upravljajte nastavitve zemljevida in GPS (povratno geokodiranje)", + "map_implications": "Funkcija zemljevida se opira na zunanjo storitev ploščic (tiles.immich.cloud)", + "map_light_style": "Svetli način", + "map_manage_reverse_geocoding_settings": "Upravljanje nastavitev Povratno geokodiranje", + "map_reverse_geocoding": "Povratno geokodiranje", + "map_reverse_geocoding_enable_description": "Omogoči povratno geokodiranje", + "map_reverse_geocoding_settings": "Nastavitve povratnega geokodiranja", + "map_settings": "Zemljevid", + "map_settings_description": "Upravljanje nastavitev zemljevida", + "map_style_description": "URL do teme zemljevida style.json", + "metadata_extraction_job": "Izvleči metapodatke", + "metadata_extraction_job_description": "Izvleči informacije iz metapodatkov iz vseh virov, kot so GPS, obrazi in resolucija", + "metadata_faces_import_setting": "Omogoči uvoz obraza", + "metadata_faces_import_setting_description": "Uvozite obraze iz slikovnih podatkov EXIF in stranskih datotek", + "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", + "no_paths_added": "Ni dodanih poti", + "no_pattern_added": "Brez 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!", + "note_unlimited_quota": "Opomba: Vnesite 0 za neomejeno kvoto", + "notification_email_from_address": "Iz naslova", + "notification_email_from_address_description": "E-poštni naslov pošiljatelja, na primer: \"Immich Photo Server \"", + "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_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_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", + "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", + "oauth_auto_register_description": "Samodejna registracija novih uporabnikov po prijavi z OAuth", + "oauth_button_text": "Besedilo gumba", + "oauth_client_id": "ID stranke", + "oauth_client_secret": "Skrivnost stranke", + "oauth_enable_description": "Prijava z OAuth", + "oauth_issuer_url": "URL izdajatelja", + "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_profile_signing_algorithm": "Algoritem za podpisovanje profila", + "oauth_profile_signing_algorithm_description": "Algoritem, ki se uporablja za podpisovanje uporabniškega profila.", + "oauth_scope": "Področje uporabe", + "oauth_settings": "OAuth", + "oauth_settings_description": "Upravljanje nastavitev prijave OAuth", + "oauth_settings_more_details": "Za več podrobnosti o tej funkciji glejte dokumentacijo.", + "oauth_signing_algorithm": "Algoritem podpisovanja", + "oauth_storage_label_claim": "Zahtevek za nalepko za shranjevanje", + "oauth_storage_label_claim_description": "Samodejno nastavi uporabnikovo oznako za shranjevanje na vrednost tega zahtevka.", + "oauth_storage_quota_claim": "Zahtevek za kvoto prostora za shranjevanje", + "oauth_storage_quota_claim_description": "Samodejno nastavi uporabnikovo kvoto shranjevanja na vrednost tega zahtevka.", + "oauth_storage_quota_default": "Privzeta kvota za shranjevanje (GiB)", + "oauth_storage_quota_default_description": "Kvota v GiB, ki se uporabi, ko ni predložen noben zahtevek (vnesite 0 za neomejeno kvoto).", + "offline_paths": "Poti brez povezave", + "offline_paths_description": "Ti rezultati so morda posledica ročnega brisanja datotek, ki niso del zunanje knjižnice.", + "password_enable_description": "Prijava z e-pošto in geslom", + "password_settings": "Prijava z geslom", + "password_settings_description": "Upravljajte nastavitve prijave z geslom", + "paths_validated_successfully": "Vse poti so bile uspešno potrjene", + "person_cleanup_job": "Čiščenje osebe", + "quota_size_gib": "Velikost kvote (GiB)", + "refreshing_all_libraries": "Osveževanje vseh knjižnic", + "registration": "Administratorska registracija", + "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.", + "repair_all": "Popravi vse", + "repair_matched_items": "Ujemanje {count, plural, one {# predmet} two {# predmeta} few {# predmeti} other {# predmetov}}", + "repaired_items": "Popravljeno {count, plural, one {# predmet} two {# predmeta} few {# predmeti} other {# predmetov}}", + "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": "Iskalna 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)://", + "server_public_users": "Javni uporabniki", + "server_public_users_description": "Vsi uporabniki (ime in e-pošta) so navedeni pri dodajanju uporabnika v albume v skupni rabi. Ko je onemogočen, bo seznam uporabnikov na voljo samo skrbniškim uporabnikom.", + "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.", + "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", + "smart_search_job_description": "Izvedite strojno učenje na sredstvih za podporo pametnega iskanja", + "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_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", + "storage_template_migration_info": "Spremembe predloge bodo veljale samo za nova sredstva. Če želite retroaktivno uporabiti predlogo za predhodno naložena sredstva, zaženite {job}.", + "storage_template_migration_job": "Opravilo selitve predloge za shranjevanje", + "storage_template_more_details": "Za več podrobnosti o tej funkciji si oglejte Predlogo za shranjevanje in njene posledice", + "storage_template_onboarding_description": "Ko je omogočena, bo ta funkcija samodejno organizirala datoteke na podlagi uporabniško določene predloge. Zaradi težav s stabilnostjo je bila funkcija privzeto izklopljena. Za več informacij si oglejte dokumentacijo.", + "storage_template_path_length": "Približna omejitev dolžine poti: {length, number}/{limit, number}", + "storage_template_settings": "Predloga za shranjevanje", + "storage_template_settings_description": "Upravljajte strukturo map in ime datoteke sredstva za nalaganje", + "storage_template_user_label": "{label} je uporabniška oznaka za shranjevanje", + "system_settings": "Sistemske nastavitve", + "tag_cleanup_job": "Čiščenje oznak", + "template_email_available_tags": "V svoji predlogi lahko uporabite naslednje spremenljivke: {tags}", + "template_email_if_empty": "Če je predloga prazna, bo uporabljena privzeta e-pošta.", + "template_email_invite_album": "Predloga povabila v album", + "template_email_preview": "Predogled", + "template_email_settings": "E-poštne predloge", + "template_email_settings_description": "Upravljajte predloge e-poštnih obvestil po meri", + "template_email_update_album": "Predloga posodobitve albuma", + "template_email_welcome": "Predloga pozdravnega e-poštnega sporočila", + "template_settings": "Predloge obvestil", + "template_settings_description": "Upravljajte predloge po meri za obvestila.", + "theme_custom_css_settings": "CSS po meri", + "theme_custom_css_settings_description": "Kaskadni slogovni listi (CSS) omogočajo prilagajanje oblikovanja Immicha.", + "theme_settings": "Nastavitve teme", + "theme_settings_description": "Upravljanje prilagajanja spletnega vmesnika Immich", + "these_files_matched_by_checksum": "Te datoteke se ujemajo z njihovimi kontrolnimi vsotami", + "thumbnail_generation_job": "Ustvarite sličice", + "thumbnail_generation_job_description": "Ustvari velike, majhne in zamegljene sličice za vsako sredstvo ter sličice za vsako osebo", + "transcoding_acceleration_api": "API za pospeševanje", + "transcoding_acceleration_api_description": "API, ki bo sodeloval z vašo napravo za pospešitev prekodiranja. Ta nastavitev je 'po najboljših močeh': v primeru napake se bo vrnila k programskemu prekodiranju. VP9 lahko deluje ali ne deluje, odvisno od vaše strojne opreme.", + "transcoding_acceleration_nvenc": "NVENC (zahteva NVIDIA GPE)", + "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_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_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.", + "transcoding_constant_quality_mode": "Način stalne kakovosti", + "transcoding_constant_quality_mode_description": "ICQ je boljši od CQP, vendar nekatere naprave za pospeševanje strojne opreme ne podpirajo tega načina. Če nastavite to možnost, bo pri uporabi kodiranja na podlagi kakovosti izbran izbran način. NVENC ga ignorira, ker ne podpira ICQ.", + "transcoding_constant_rate_factor": "Faktor konstantne stopnje (-crf)", + "transcoding_constant_rate_factor_description": "Raven kakovosti videa. Tipične vrednosti so 23 za H.264, 28 za HEVC, 31 za VP9 in 35 za AV1. Nižje je boljše, vendar ustvarja večje datoteke.", + "transcoding_disabled_description": "Ne prekodirajte nobenih videoposnetkov, lahko prekine predvajanje na nekaterih odjemalcih", + "transcoding_hardware_acceleration": "Strojno pospeševanje", + "transcoding_hardware_acceleration_description": "Eksperimentalno; veliko hitreje, vendar bo imel slabšo kakovost pri isti bitni hitrosti", + "transcoding_hardware_decoding": "Strojno dekodiranje", + "transcoding_hardware_decoding_setting_description": "Omogoča pospeševanje od konca do konca namesto samo pospeševanja kodiranja. Morda ne bo delovalo na vseh videoposnetkih.", + "transcoding_hevc_codec": "Kodek HEVC", + "transcoding_max_b_frames": "Največji B-okvirji", + "transcoding_max_b_frames_description": "Višje vrednosti izboljšajo učinkovitost stiskanja, vendar upočasnijo kodiranje. Morda ni združljivo s strojnim pospeševanjem na starejših napravah. 0 onemogoči okvirje B, medtem ko -1 samodejno nastavi to vrednost.", + "transcoding_max_bitrate": "Največja bitna hitrost", + "transcoding_max_bitrate_description": "Z nastavitvijo največje bitne hitrosti so lahko velikosti datotek bolj predvidljive ob manjši ceni kakovosti. Pri 720p so tipične vrednosti 2600k za VP9 ali HEVC ali 4500k za H.264. Onemogočeno, če je nastavljeno na 0.", + "transcoding_max_keyframe_interval": "Največji interval ključnih sličic", + "transcoding_max_keyframe_interval_description": "Nastavi največjo razdaljo med ključnimi slikami. Nižje vrednosti poslabšajo učinkovitost stiskanja, vendar izboljšajo čas iskanja in lahko izboljšajo kakovost prizorov s hitrim gibanjem. 0 samodejno nastavi to vrednost.", + "transcoding_optimal_description": "Videoposnetki, ki so višji od ciljne ločljivosti ali niso v sprejemljivem formatu", + "transcoding_preferred_hardware_device": "Prednostna strojna naprava", + "transcoding_preferred_hardware_device_description": "Velja samo za VAAPI in QSV. Nastavi dri vozlišče, ki se uporablja za strojno prekodiranje.", + "transcoding_preset_preset": "Prednastavitev (-preset)", + "transcoding_preset_preset_description": "Hitrost stiskanja. Počasnejše prednastavitve ustvarijo manjše datoteke in povečajo kakovost pri ciljanju na določeno bitno hitrost. VP9 ignorira hitrosti nad 'hitreje'.", + "transcoding_reference_frames": "Referenčni okvirji", + "transcoding_reference_frames_description": "Število okvirjev, na katere se sklicujete pri stiskanju danega okvira. Višje vrednosti izboljšajo učinkovitost stiskanja, vendar upočasnijo kodiranje. 0 samodejno nastavi to vrednost.", + "transcoding_required_description": "Samo videoposnetki, ki niso v sprejemljivi obliki", + "transcoding_settings": "Nastavitve video transkodiranja", + "transcoding_settings_description": "Upravljajte podatke o ločljivosti in kodiranju video datotek", + "transcoding_target_resolution": "Ciljna ločljivost", + "transcoding_target_resolution_description": "Višje ločljivosti lahko ohranijo več podrobnosti, vendar kodiranje traja dlje, imajo večje velikosti datotek in lahko zmanjšajo odzivnost aplikacije.", + "transcoding_temporal_aq": "Časovni AQ", + "transcoding_temporal_aq_description": "Velja samo za NVENC. Poveča kakovost prizorov z veliko podrobnosti in malo gibanja. Morda ni združljiv s starejšimi napravami.", + "transcoding_threads": "Niti", + "transcoding_threads_description": "Višje vrednosti vodijo do hitrejšega kodiranja, vendar pustijo manj prostora strežniku za obdelavo drugih nalog, ko je aktiven. Ta vrednost ne sme biti večja od števila jeder procesorja. Maksimira uporabo, če je nastavljeno na 0.", + "transcoding_tone_mapping": "Tonska preslikava", + "transcoding_tone_mapping_description": "Poskuša ohraniti videz videoposnetkov HDR pri pretvorbi v SDR. Vsak algoritem naredi različne kompromise glede barve, podrobnosti in svetlosti. Hable ohrani podrobnosti, Mobius ohrani barvo, Reinhard pa svetlost.", + "transcoding_transcode_policy": "Politika prekodiranja", + "transcoding_transcode_policy_description": "Pravilnik o tem, kdaj je treba videoposnetek prekodirati. Videoposnetki HDR bodo vedno prekodirani (razen če je transkodiranje onemogočeno).", + "transcoding_two_pass_encoding": "Dvohodno kodiranje", + "transcoding_two_pass_encoding_setting_description": "Prekodirajte v dveh prehodih za ustvarjanje bolje kodiranih videoposnetkov. Ko je omogočena največja bitna hitrost (ki je potrebna za delovanje s H.264 in HEVC), ta način uporablja obseg bitne hitrosti, ki temelji na največji bitni hitrosti, in ignorira CRF. Za VP9 je mogoče uporabiti CRF, če je največja bitna hitrost onemogočena.", + "transcoding_video_codec": "Video kodek", + "transcoding_video_codec_description": "VP9 ima visoko učinkovitost in spletno združljivost, vendar traja dalj časa za prekodiranje. HEVC deluje podobno, vendar ima slabšo spletno združljivost. H.264 je široko združljiv in se hitro prekodira, vendar ustvarja veliko večje datoteke. AV1 je najučinkovitejši kodek, vendar nima podpore na starejših napravah.", + "trash_enabled_description": "Omogoči funkcije smetnjaka", + "trash_number_of_days": "Število dni", + "trash_number_of_days_description": "Število dni za shranjevanje sredstev v smetnjaku, preden jih trajno odstranite", + "trash_settings": "Nastavitve smetnjaka", + "trash_settings_description": "Upravljanje nastavitev smetnjaka", + "untracked_files": "Nesledene datoteke", + "untracked_files_description": "Tem datotekam aplikacija ne sledi. Lahko so posledica neuspelih premikov, prekinjenih nalaganj ali zaostalih zaradi hrošča", + "user_cleanup_job": "Čiščenje uporabnika", + "user_delete_delay": "Račun in sredstva {user} bodo načrtovani za trajno brisanje čez {delay, plural, one {# day} other {# days}}.", + "user_delete_delay_settings": "Zamakni izbris", + "user_delete_delay_settings_description": "Število dni po odstranitvi za trajno brisanje uporabnikovega računa in sredstev. Opravilo za brisanje uporabnikov se izvaja ob polnoči, da se preveri, ali so uporabniki pripravljeni na izbris. Spremembe te nastavitve bodo ovrednotene pri naslednji izvedbi.", + "user_delete_immediately": "Račun in sredstva uporabnika {user} bodo v čakalni vrsti za trajno brisanje takoj.", + "user_delete_immediately_checkbox": "Uporabnika in sredstva postavite v čakalno vrsto za takojšnje brisanje", + "user_management": "Upravljanje uporabnikov", + "user_password_has_been_reset": "Geslo uporabnika je bilo ponastavljeno:", + "user_password_reset_description": "Uporabniku posredujte začasno geslo in ga obvestite, da bo moral ob naslednji prijavi spremeniti geslo.", + "user_restore_description": "Račun {user} bo obnovljen.", + "user_restore_scheduled_removal": "Obnovi uporabnika – načrtovana odstranitev na {date, date, long}", + "user_settings": "Uporabniške nastavitve", + "user_settings_description": "Upravljanje uporabniških nastavitev", + "user_successfully_removed": "Uporabnik {email} je bil uspešno odstranjen.", + "version_check_enabled_description": "Omogoči preverjanje različice", + "version_check_implications": "Funkcija preverjanja različic se opira na občasno komunikacijo z github.com", + "version_check_settings": "Preverjanje različice", + "version_check_settings_description": "Omogoči/onemogoči obvestilo o novi različici", + "video_conversion_job": "Prekodiranje videoposnetkov", + "video_conversion_job_description": "Prekodirajte videoposnetke za večjo združljivost z brskalniki in napravami" }, - "admin_email": "", - "admin_password": "", - "administration": "", + "admin_email": "Skrbniška e-pošta", + "admin_password": "Skrbniško geslo", + "administration": "Administracija", "advanced": "Napredno", - "album_added": "", - "album_added_notification_setting_description": "", - "album_cover_updated": "", - "album_info_updated": "", - "album_name": "", - "album_options": "", - "album_updated": "", - "album_updated_setting_description": "", + "age_months": "Starost {months, plural, one {# month} other {# months}}", + "age_year_months": "Starost 1 leto, {months, plural, one {# month} other {# months}}", + "age_years": "{years, plural, other {starost #}}", + "album_added": "Album dodan", + "album_added_notification_setting_description": "Prejmite e-poštno obvestilo, ko ste dodani v album v skupni rabi", + "album_cover_updated": "Naslovnica albuma posodobljena", + "album_delete_confirmation": "Ali ste prepričani, da želite izbrisati album {album}?", + "album_delete_confirmation_description": "Če je ta album v skupni rabi, drugi uporabniki ne bodo mogli več dostopati do njega.", + "album_info_updated": "Podatki o albumu posodobljeni", + "album_leave": "Zapusti album?", + "album_leave_confirmation": "Ali ste prepričani, da želite zapustiti {album}?", + "album_name": "Ime albuma", + "album_options": "Možnosti albuma", + "album_remove_user": "Odstrani uporabnika?", + "album_remove_user_confirmation": "Ali ste prepričani, da želite odstraniti {user}?", + "album_share_no_users": "Videti je, da ste ta album dali v skupno rabo z vsemi uporabniki ali pa nimate nobenega uporabnika, s katerim bi ga lahko delili.", + "album_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}", + "album_user_removed": "Odstranjen {user}", + "album_with_link_access": "Omogočite vsem s povezavo ogled fotografij in ljudi v tem albumu.", "albums": "Albumi", + "albums_count": "{count, plural, one {{count, number} Album} other {{count, number} Albumi}}", "all": "Vse", - "all_people": "", - "allow_dark_mode": "", - "allow_edits": "", - "api_key": "", - "api_keys": "", - "app_settings": "", - "appears_in": "", + "all_albums": "Vsi albumi", + "all_people": "Vsi ljudje", + "all_videos": "Vsi videi", + "allow_dark_mode": "Dovoli temni način", + "allow_edits": "Dovoli urejanja", + "allow_public_user_to_download": "Dovoli javnemu uporabniku prenos", + "allow_public_user_to_upload": "Dovolite javnemu uporabniku nalaganje", + "anti_clockwise": "V nasprotni smeri urnega kazalca", + "api_key": "API ključ", + "api_key_description": "Ta vrednost bo prikazana samo enkrat. Ne pozabite jo kopirati, preden zaprete okno.", + "api_key_empty": "Ime ključa API ne sme biti prazno", + "api_keys": "API ključi", + "app_settings": "Nastavitve aplikacije", + "appears_in": "Pojavi se v", "archive": "Arhiv", - "archive_or_unarchive_photo": "", - "archived": "", - "asset_offline": "", - "assets": "sredstva", - "authorized_devices": "", + "archive_or_unarchive_photo": "Arhivirajte ali odstranite fotografijo iz arhiva", + "archive_size": "Velikost arhiva", + "archive_size_description": "Konfigurirajte velikost arhiva za prenose (v GiB)", + "archived_count": "{count, plural, other {arhivirano #}}", + "are_these_the_same_person": "Ali je to ista oseba?", + "are_you_sure_to_do_this": "Ste prepričani, da želite to narediti?", + "asset_added_to_album": "Dodano v album", + "asset_adding_to_album": "Dodajanje v album ...", + "asset_description_updated": "Opis sredstva je posodobljen", + "asset_filename_is_offline": "Sredstvo {filename} je brez povezave", + "asset_has_unassigned_faces": "Sredstvo ima nedodeljene obraze", + "asset_hashing": "Zgoščevanje ...", + "asset_offline": "Sredstvo brez povezave", + "asset_offline_description": "Tega zunanjega sredstva ni več mogoče najti na disku. Za pomoč kontaktirajte Immich skrbnika.", + "asset_skipped": "Preskočeno", + "asset_skipped_in_trash": "V smetnjak", + "asset_uploaded": "Naloženo", + "asset_uploading": "Nalaganje ...", + "assets": "Sredstva", + "assets_added_count": "Dodano{count, plural, one {# sredstvo} other {# sredstev}}", + "assets_added_to_album_count": "Dodano{count, plural, one {# sredstvo} other {# sredstev}} v album", + "assets_added_to_name_count": "Dodano {count, plural, one {# sredstvo} other {# sredstev}} v {hasName, select, true {{name}} other {new album}}", + "assets_count": "{count, plural, one {# sredstvo} other {# sredstev}}", + "assets_moved_to_trash_count": "Premaknjeno {count, plural, one {# sredstev} other {# sredstev}} v smetnjak", + "assets_permanently_deleted_count": "Trajno izbrisano {count, plural, one {# sredstvo} other {# sredstev}}", + "assets_removed_count": "Odstranjeno {count, plural, one {# sredstvo} other {# sredstev}}", + "assets_restore_confirmation": "Ali ste prepričani, da želite obnoviti vsa sredstva, ki ste jih odstranili? Tega dejanja ne morete razveljaviti! Upoštevajte, da sredstev brez povezave ni mogoče obnoviti na ta način.", + "assets_restored_count": "Obnovljeno {count, plural, one {# sredstvo} other {# sredstev}}", + "assets_trashed_count": "V smetnjak {count, plural, one {# sredstvo} other {# sredstev}}", + "assets_were_part_of_album_count": "{count, plural, one {sredstvo je} other {sredstev je}} že del albuma", + "authorized_devices": "Pooblaščene naprave", "back": "Nazaj", - "backward": "", - "blurred_background": "", - "camera": "", - "camera_brand": "", - "camera_model": "", + "back_close_deselect": "Nazaj, zaprite ali prekličite izbiro", + "backward": "Nazaj", + "birthdate_saved": "Datum rojstva je uspešno shranjen", + "birthdate_set_description": "Datum rojstva se uporablja za izračun starosti te osebe v času fotografije.", + "blurred_background": "Zamegljeno ozadje", + "bugs_and_feature_requests": "Napake in zahteve po funkcijah", + "build": "Različica", + "build_image": "Različica slike", + "bulk_delete_duplicates_confirmation": "Ali ste prepričani, da želite množično izbrisati {count, plural, one {# dvojnik} other {# dvojnikov}}? S tem boste ohranili največje sredstvo vsake skupine in trajno izbrisali vse druge dvojnike. Tega dejanja ne morete razveljaviti!", + "bulk_keep_duplicates_confirmation": "Ali ste prepričani, da želite obdržati {count, plural, one {# dvojnik} other {# dvojnikov}}? S tem boste razrešili vse podvojene skupine, ne da bi karkoli izbrisali.", + "bulk_trash_duplicates_confirmation": "Ali ste prepričani, da želite množično vreči v smetnjak {count, plural, one {# dvojnik} other {# dvojnikov}}? S tem boste obdržali največje sredstvo vsake skupine in odstranili vse druge dvojnike.", + "buy": "Kupi Immich", + "camera": "Kamera", + "camera_brand": "Znamka kamere", + "camera_model": "Model kamere", "cancel": "Prekliči", - "cancel_search": "", - "cannot_merge_people": "", - "cannot_update_the_description": "", - "cant_apply_changes": "", - "cant_get_faces": "", - "cant_search_people": "", - "cant_search_places": "", - "change_date": "", + "cancel_search": "Prekliči iskanje", + "cannot_merge_people": "Oseb ni mogoče združiti", + "cannot_undo_this_action": "Tega dejanja ne morete razveljaviti!", + "cannot_update_the_description": "Opisa ni mogoče posodobiti", + "change_date": "Spremeni datum", "change_expiration_time": "Spremeni čas poteka", - "change_location": "", - "change_name": "", - "change_name_successfully": "", + "change_location": "Spremeni lokacijo", + "change_name": "Spremeni ime", + "change_name_successfully": "Sprememba imena uspešna", "change_password": "Zamenjaj geslo", - "change_your_password": "", - "changed_visibility_successfully": "", - "check_logs": "", + "change_password_description": "To je bodisi prvič, da se vpisujete v sistem ali pa je bila podana zahteva za spremembo vašega gesla. Spodaj vnesite novo geslo.", + "change_your_password": "Spremenite geslo", + "changed_visibility_successfully": "Uspešno spremenjena vidnost", + "check_all": "Označite vse", + "check_logs": "Preverite dnevnike", + "choose_matching_people_to_merge": "Izberite ujemajoče se osebe za združitev", "city": "Mesto", "clear": "Počisti", - "clear_all": "", - "clear_message": "", - "clear_value": "", - "close": "", - "collapse_all": "", - "color_theme": "", - "comment_options": "", - "comments_are_disabled": "", + "clear_all": "Počisti vse", + "clear_all_recent_searches": "Počisti vsa nedavna iskanja", + "clear_message": "Počisti sporočilo", + "clear_value": "Počisti vrednost", + "clockwise": "V smeri urinega kazalca", + "close": "Zapri", + "collapse": "Strni", + "collapse_all": "Strni vse", + "color": "Barva", + "color_theme": "Barva teme", + "comment_deleted": "Komentar izbrisan", + "comment_options": "Možnosti komentiranja", + "comments_and_likes": "Komentarji in všečki", + "comments_are_disabled": "Komentarji so onemogočeni", "confirm": "Potrdi", - "confirm_admin_password": "", + "confirm_admin_password": "Potrdite skrbniško geslo", + "confirm_delete_shared_link": "Ali ste prepričani, da želite izbrisati to skupno povezavo?", + "confirm_keep_this_delete_others": "Vsa druga sredstva v skladu bodo izbrisana, razen tega sredstva. Ste prepričani, da želite nadaljevati?", "confirm_password": "Potrdi geslo", - "contain": "", - "context": "", - "continue": "", - "copied_image_to_clipboard": "", - "copy_error": "", - "copy_file_path": "", - "copy_image": "", - "copy_link": "", - "copy_link_to_clipboard": "", - "copy_password": "", - "copy_to_clipboard": "", + "contain": "Vsebuje", + "context": "Kontekst", + "continue": "Nadaljuj", + "copied_image_to_clipboard": "Slika kopirana v odložišče.", + "copied_to_clipboard": "Kopirano v odložišče!", + "copy_error": "Napaka pri kopiranju", + "copy_file_path": "Kopiraj pot datoteke", + "copy_image": "Kopiraj sliko", + "copy_link": "Kopiraj povezavo", + "copy_link_to_clipboard": "Kopiraj povezavo v odložišče", + "copy_password": "Kopiraj geslo", + "copy_to_clipboard": "Kopiraj v odložišče", "country": "Država", - "cover": "", - "covers": "", + "cover": "Prekrij", + "covers": "Prekrivanja", "create": "Ustvari", "create_album": "Ustvari album", - "create_library": "", + "create_library": "Ustvari knjižnico", "create_link": "Ustvari povezavo", "create_link_to_share": "Ustvari povezavo za skupno rabo", - "create_new_person": "", - "create_new_user": "", - "create_user": "", - "created": "", - "current_device": "", - "custom_locale": "", - "custom_locale_description": "", - "dark": "", - "date_after": "", + "create_link_to_share_description": "Omogoči vsem s povezavo ogled izbranih fotografij", + "create_new_person": "Ustvari novo osebo", + "create_new_person_hint": "Dodeli izbrana sredstva novi osebi", + "create_new_user": "Ustvari novega uporabnika", + "create_tag": "Ustvari oznako", + "create_tag_description": "Ustvarite novo oznako. Za ugnezdene oznake vnesite celotno pot oznake, vključno s poševnicami.", + "create_user": "Ustvari uporabnika", + "created": "Ustvarjeno", + "current_device": "Trenutna naprava", + "custom_locale": "Jezik po meri", + "custom_locale_description": "Oblikujte datume in številke glede na jezik in regijo", + "dark": "Temno", + "date_after": "Datum po", "date_and_time": "Datum in ura", - "date_before": "", + "date_before": "Datum pred", + "date_of_birth_saved": "Datum rojstva je uspešno shranjen", "date_range": "Časovno obdobje", - "day": "", - "default_locale": "", - "default_locale_description": "", + "day": "Dan", + "deduplicate_all": "Odstrani vse podvojene", + "default_locale": "Privzeti jezik", + "default_locale_description": "Oblikujte datume in številke glede na lokalne nastavitve brskalnika", "delete": "Izbriši", "delete_album": "Izbriši album", - "delete_key": "", - "delete_library": "", - "delete_link": "", + "delete_api_key_prompt": "Ali ste prepričani, da želite izbrisati ta API ključ?", + "delete_duplicates_confirmation": "Ali ste prepričani, da želite trajno izbrisati te dvojnike?", + "delete_key": "Izbriši ključ", + "delete_library": "Izbriši knjižnico", + "delete_link": "Izbriši povezavo", + "delete_others": "Izbriši ostale", "delete_shared_link": "Izbriši povezavo skupne rabe", - "delete_user": "", - "deleted_shared_link": "", + "delete_tag": "Izbriši oznako", + "delete_tag_confirmation_prompt": "Ali ste prepričani, da želite izbrisati oznako {tagName}?", + "delete_user": "Izbriši uporabnika", + "deleted_shared_link": "Izbrisana skupna povezava", + "deletes_missing_assets": "Izbriše sredstva, ki manjkajo na disku", "description": "Opis", "details": "PODROBNOSTI", - "direction": "", - "disallow_edits": "", - "discover": "", - "dismiss_all_errors": "", - "dismiss_error": "", - "display_options": "", - "display_order": "", - "display_original_photos": "", - "display_original_photos_setting_description": "", + "direction": "Usmeritev", + "disabled": "Onemogočeno", + "disallow_edits": "Onemogoči urejanje", + "discord": "Discord", + "discover": "Odkrij", + "dismiss_all_errors": "Opusti vse napake", + "dismiss_error": "Opusti napako", + "display_options": "Možnosti prikaza", + "display_order": "Vrstni red prikaza", + "display_original_photos": "Prikaži izvirne fotografije", + "display_original_photos_setting_description": "Pri ogledu sredstva raje prikažite izvirno fotografijo kot sličice, če je izvirno sredstvo združljivo s spletom. To lahko povzroči počasnejše hitrosti prikaza fotografij.", + "do_not_show_again": "Ne pokaži več tega sporočila", + "documentation": "Dokumentacija", "done": "Končano", "download": "Prenesi", - "downloading": "", - "duration": "", - "durations": { - "days": "", - "hours": "", - "minutes": "", - "months": "", - "years": "" - }, - "edit_album": "", - "edit_avatar": "", - "edit_date": "", - "edit_date_and_time": "", - "edit_exclusion_pattern": "", - "edit_faces": "", - "edit_import_path": "", - "edit_import_paths": "", - "edit_key": "", + "download_include_embedded_motion_videos": "Vdelani videoposnetki", + "download_include_embedded_motion_videos_description": "Videoposnetke, vdelane v fotografije gibanja, vključite kot ločeno datoteko", + "download_settings": "Prenos", + "download_settings_description": "Upravljajte nastavitve, povezane s prenosom sredstev", + "downloading": "Prenašanje", + "downloading_asset_filename": "Prenašanje sredstva {filename}", + "drop_files_to_upload": "Spustite datoteke kamor koli, da jih naložite", + "duplicates": "Dvojniki", + "duplicates_description": "Razrešite vsako skupino tako, da navedete, kateri so dvojniki, če obstajajo", + "duration": "Trajanje", + "edit": "Uredi", + "edit_album": "Uredi album", + "edit_avatar": "Uredi avatar", + "edit_date": "Uredi datum", + "edit_date_and_time": "Uredi datum in uro", + "edit_exclusion_pattern": "Uredi vzorec izključitve", + "edit_faces": "Uredi obraze", + "edit_import_path": "Uredi uvozno pot", + "edit_import_paths": "Uredi uvozne poti", + "edit_key": "Uredi ključ", "edit_link": "Uredi povezavo", "edit_location": "Uredi lokacijo", "edit_name": "Uredi ime", - "edit_people": "", - "edit_title": "", - "edit_user": "", - "edited": "", - "editor": "", + "edit_people": "Uredi osebe", + "edit_tag": "Uredi oznako", + "edit_title": "Uredi naslov", + "edit_user": "Uredi uporabnika", + "edited": "Urejeno", + "editor": "Urejevalnik", + "editor_close_without_save_prompt": "Spremembe ne bodo shranjene", + "editor_close_without_save_title": "Zapri urejevalnik?", + "editor_crop_tool_h2_aspect_ratios": "Razmerja stranic", + "editor_crop_tool_h2_rotation": "Vrtenje", "email": "E-pošta", - "empty": "", - "empty_album": "", "empty_trash": "Izprazni smeti", - "enable": "", - "enabled": "", - "end_date": "", - "error": "", - "error_loading_image": "", + "empty_trash_confirmation": "Ste prepričani, da želite izprazniti smetnjak? S tem boste iz Immicha trajno odstranili vsa sredstva v smetnjaku.\nTega dejanja ne morete razveljaviti!", + "enable": "Omogoči", + "enabled": "Omogočeno", + "end_date": "Končni datum", + "error": "Napaka", + "error_loading_image": "Napaka pri nalaganju slike", + "error_title": "Napaka - nekaj je šlo narobe", "errors": { - "unable_to_add_album_users": "", - "unable_to_add_comment": "", - "unable_to_add_partners": "", - "unable_to_change_album_user_role": "", - "unable_to_change_date": "", - "unable_to_change_location": "", - "unable_to_check_item": "", - "unable_to_check_items": "", - "unable_to_create_admin_account": "", - "unable_to_create_library": "", - "unable_to_create_user": "", - "unable_to_delete_album": "", - "unable_to_delete_asset": "", - "unable_to_delete_user": "", - "unable_to_empty_trash": "", - "unable_to_enter_fullscreen": "", - "unable_to_exit_fullscreen": "", - "unable_to_hide_person": "", - "unable_to_load_album": "", - "unable_to_load_asset_activity": "", - "unable_to_load_items": "", - "unable_to_load_liked_status": "", - "unable_to_play_video": "", - "unable_to_refresh_user": "", - "unable_to_remove_album_users": "", - "unable_to_remove_comment": "", - "unable_to_remove_library": "", - "unable_to_remove_partner": "", - "unable_to_remove_reaction": "", - "unable_to_remove_user": "", - "unable_to_repair_items": "", - "unable_to_reset_password": "", - "unable_to_resolve_duplicate": "", - "unable_to_restore_assets": "", - "unable_to_restore_trash": "", - "unable_to_restore_user": "", - "unable_to_save_album": "", - "unable_to_save_name": "", - "unable_to_save_profile": "", - "unable_to_save_settings": "", - "unable_to_scan_libraries": "", - "unable_to_scan_library": "", - "unable_to_set_profile_picture": "", - "unable_to_submit_job": "", - "unable_to_trash_asset": "", - "unable_to_unlink_account": "", - "unable_to_update_library": "", - "unable_to_update_location": "", - "unable_to_update_settings": "", - "unable_to_update_user": "" + "cannot_navigate_next_asset": "Ni mogoče krmariti do naslednjega sredstva", + "cannot_navigate_previous_asset": "Ni mogoče krmariti na prejšnje sredstvo", + "cant_apply_changes": "Sprememb ni mogoče uporabiti", + "cant_change_activity": "Ni mogoče {enabled, select, true {disable} other {enable}} dejavnosti", + "cant_change_asset_favorite": "Ni možno spremeniti priljubljeno za sredstvo", + "cant_change_metadata_assets_count": "Ni mogoče spremeniti metapodatkov za {count, plural, one {# sredstvo} two {# sredstvi} few {# sredstva} other {# sredstev}}", + "cant_get_faces": "Ne morem dobiti obrazov", + "cant_get_number_of_comments": "Ni mogoče pridobiti števila komentarjev", + "cant_search_people": "Ni mogoče iskati ljudi", + "cant_search_places": "Ne morem iskati mest", + "cleared_jobs": "Počiščena opravila za: {job}", + "error_adding_assets_to_album": "Napaka pri dodajanju sredstev v album", + "error_adding_users_to_album": "Napaka pri dodajanju uporabnikov v album", + "error_deleting_shared_user": "Napaka pri brisanju uporabnika v skupni rabi", + "error_downloading": "Napaka pri prenosu datoteke {filename}", + "error_hiding_buy_button": "Napaka pri skrivanju gumba za nakup", + "error_removing_assets_from_album": "Napaka pri odstranjevanju sredstev iz albuma, preverite konzolo za več podrobnosti", + "error_selecting_all_assets": "Napaka pri izbiri vseh sredstev", + "exclusion_pattern_already_exists": "Ta vzorec izključitve že obstaja.", + "failed_job_command": "Ukaz {command} ni uspel za opravilo: {job}", + "failed_to_create_album": "Albuma ni bilo mogoče ustvariti", + "failed_to_create_shared_link": "Povezave v skupni rabi ni bilo mogoče ustvariti", + "failed_to_edit_shared_link": "Povezave v skupni rabi ni bilo mogoče urediti", + "failed_to_get_people": "Oseb ni bilo mogoče pridobiti", + "failed_to_keep_this_delete_others": "Tega sredstva ni bilo mogoče obdržati in izbrisati ostalih sredstev", + "failed_to_load_asset": "Sredstva ni bilo mogoče naložiti", + "failed_to_load_assets": "Sredstev ni bilo mogoče naložiti", + "failed_to_load_people": "Oseb ni bilo mogoče naložiti", + "failed_to_remove_product_key": "Ključa izdelka ni bilo mogoče odstraniti", + "failed_to_stack_assets": "Zlaganje sredstev ni uspelo", + "failed_to_unstack_assets": "Sredstev ni bilo mogoče razložiti", + "import_path_already_exists": "Ta uvozna pot že obstaja.", + "incorrect_email_or_password": "Napačen e-poštni naslov ali geslo", + "paths_validation_failed": "{paths, plural, one {# pot} other {# poti}} ni bilo uspešno preverjeno", + "profile_picture_transparent_pixels": "Profilne slike ne smejo imeti prosojnih slikovnih pik. Povečajte in/ali premaknite sliko.", + "quota_higher_than_disk_size": "Nastavili ste kvoto, ki je višja od velikosti diska", + "repair_unable_to_check_items": "Ni mogoče preveriti {count, select, one {predmeta} other {predmetov}}", + "unable_to_add_album_users": "Uporabnikov ni mogoče dodati v album", + "unable_to_add_assets_to_shared_link": "Povezavi v skupni rabi ni mogoče dodati sredstev", + "unable_to_add_comment": "Ni mogoče dodati komentarja", + "unable_to_add_exclusion_pattern": "Vzorca izključitve ni mogoče dodati", + "unable_to_add_import_path": "Uvozne poti ni mogoče dodati", + "unable_to_add_partners": "Partnerjev ni mogoče dodati", + "unable_to_add_remove_archive": "Ni mogoče {archived, select, true {odstraniti sredstva iz} other {ter dodati sredstvo v}} archive", + "unable_to_add_remove_favorites": "Ni mogoče {favorite, select, true {dodati sredstva v} other {ter ga odstraniti iz}} priljubljenih", + "unable_to_archive_unarchive": "Ni mogoče {archived, select, true {arhivirano} other {nearhivirano}}", + "unable_to_change_album_user_role": "Ni mogoče spremeniti vloge uporabnika albuma", + "unable_to_change_date": "Datuma ni mogoče spremeniti", + "unable_to_change_favorite": "Ni mogoče spremeniti priljubljenega za sredstvo", + "unable_to_change_location": "Lokacije ni mogoče spremeniti", + "unable_to_change_password": "Gesla ni mogoče spremeniti", + "unable_to_change_visibility": "Ni mogoče spremeniti vidnosti za {count, plural, one {# osebo} other {# oseb}}", + "unable_to_complete_oauth_login": "Prijave OAuth ni mogoče dokončati", + "unable_to_connect": "Ni mogoče vzpostaviti povezave", + "unable_to_connect_to_server": "Ni mogoče vzpostaviti povezave s strežnikom", + "unable_to_copy_to_clipboard": "Ni mogoče kopirati v odložišče, preverite, ali dostopate do strani prek https", + "unable_to_create_admin_account": "Ni mogoče ustvariti skrbniškega računa", + "unable_to_create_api_key": "Ni mogoče ustvariti novega API ključa", + "unable_to_create_library": "Ni mogoče ustvariti knjižnice", + "unable_to_create_user": "Uporabnika ni mogoče ustvariti", + "unable_to_delete_album": "Albuma ni mogoče izbrisati", + "unable_to_delete_asset": "Sredstva ni mogoče izbrisati", + "unable_to_delete_assets": "Napaka pri brisanju sredstev", + "unable_to_delete_exclusion_pattern": "Vzorca izključitve ni mogoče izbrisati", + "unable_to_delete_import_path": "Uvozne poti ni mogoče izbrisati", + "unable_to_delete_shared_link": "Povezave v skupni rabi ni mogoče izbrisati", + "unable_to_delete_user": "Uporabnika ni mogoče izbrisati", + "unable_to_download_files": "Ni mogoče prenesti datotek", + "unable_to_edit_exclusion_pattern": "Vzorca izključitve ni mogoče urediti", + "unable_to_edit_import_path": "Uvozne poti ni mogoče urediti", + "unable_to_empty_trash": "Smetnjaka ni mogoče izprazniti", + "unable_to_enter_fullscreen": "Celozaslonski način ni mogoč", + "unable_to_exit_fullscreen": "Ni mogoče zapreti celozaslonskega načina", + "unable_to_get_comments_number": "Ni mogoče pridobiti števila komentarjev", + "unable_to_get_shared_link": "Povezave v skupni rabi ni bilo mogoče pridobiti", + "unable_to_hide_person": "Osebe ni mogoče skriti", + "unable_to_link_motion_video": "Ni mogoče povezati videa gibanja", + "unable_to_link_oauth_account": "Računa OAuth ni mogoče povezati", + "unable_to_load_album": "Albuma ni mogoče naložiti", + "unable_to_load_asset_activity": "Dejavnosti sredstva ni mogoče naložiti", + "unable_to_load_items": "Elementov ni mogoče naložiti", + "unable_to_load_liked_status": "Ni mogoče naložiti statusa všečka", + "unable_to_log_out_all_devices": "Ni mogoče odjaviti vseh naprav", + "unable_to_log_out_device": "Naprave ni mogoče odjaviti", + "unable_to_login_with_oauth": "Prijava z OAuth ni mogoča", + "unable_to_play_video": "Videoposnetka ni mogoče predvajati", + "unable_to_reassign_assets_existing_person": "Ni mogoče dodeliti sredstev {name, select, null {obstoječi osebi} other {{name}}}", + "unable_to_reassign_assets_new_person": "Ponovna dodelitev sredstev novi osebi ni možna", + "unable_to_refresh_user": "Uporabnika ni mogoče osvežiti", + "unable_to_remove_album_users": "Uporabnikov ni mogoče odstraniti iz albuma", + "unable_to_remove_api_key": "Ključa API ni mogoče odstraniti", + "unable_to_remove_assets_from_shared_link": "Ni mogoče odstraniti sredstev iz skupne povezave", + "unable_to_remove_deleted_assets": "Datotek brez povezave ni mogoče odstraniti", + "unable_to_remove_library": "Knjižnice ni mogoče odstraniti", + "unable_to_remove_partner": "Partnerja ni mogoče odstraniti", + "unable_to_remove_reaction": "Reakcije ni mogoče odstraniti", + "unable_to_repair_items": "Elementov ni mogoče popraviti", + "unable_to_reset_password": "Gesla ni mogoče ponastaviti", + "unable_to_resolve_duplicate": "Dvojnika ni mogoče razrešiti", + "unable_to_restore_assets": "Sredstev ni mogoče obnoviti", + "unable_to_restore_trash": "Smetnjaka ni mogoče obnoviti", + "unable_to_restore_user": "Uporabnika ni mogoče obnoviti", + "unable_to_save_album": "Albuma ni mogoče shraniti", + "unable_to_save_api_key": "Ključa API ni mogoče shraniti", + "unable_to_save_date_of_birth": "Datuma rojstva ni mogoče shraniti", + "unable_to_save_name": "Imena ni mogoče shraniti", + "unable_to_save_profile": "Profila ni mogoče shraniti", + "unable_to_save_settings": "Nastavitev ni mogoče shraniti", + "unable_to_scan_libraries": "Ni mogoče pregledati knjižnic", + "unable_to_scan_library": "Knjižnice ni mogoče pregledati", + "unable_to_set_feature_photo": "Ni mogoče nastaviti glavne fotografije", + "unable_to_set_profile_picture": "Profilne slike ni mogoče nastaviti", + "unable_to_submit_job": "Naloga ni mogoče oddati", + "unable_to_trash_asset": "Sredstva ni mogoče odstraniti v smetnjak", + "unable_to_unlink_account": "Povezave računa ni mogoče prekiniti", + "unable_to_unlink_motion_video": "Ni mogoče prekiniti povezave z videoposnetkom gibanja", + "unable_to_update_album_cover": "Naslovnice albuma ni mogoče posodobiti", + "unable_to_update_album_info": "Podatkov o albumu ni mogoče posodobiti", + "unable_to_update_library": "Knjižnice ni mogoče posodobiti", + "unable_to_update_location": "Lokacije ni mogoče posodobiti", + "unable_to_update_settings": "Nastavitev ni mogoče posodobiti", + "unable_to_update_timeline_display_status": "Ni mogoče posodobiti stanja prikaza časovnice", + "unable_to_update_user": "Uporabnika ni mogoče posodobiti", + "unable_to_upload_file": "Datoteke ni mogoče naložiti" }, - "every_day_at_onepm": "", - "every_night_at_midnight": "", - "every_night_at_twoam": "", - "every_six_hours": "", - "exit_slideshow": "", - "expand_all": "", + "exif": "Exif", + "exit_slideshow": "Zapustite diaprojekcijo", + "expand_all": "Razširi vse", "expire_after": "Poteče čez", "expired": "Poteklo", - "explore": "", - "extension": "", - "external_libraries": "", - "failed_to_get_people": "", + "expires_date": "Poteče {date}", + "explore": "Razišči", + "explorer": "Raziskovalec", + "export": "Izvoz", + "export_as_json": "Izvozi kot JSON", + "extension": "Razširitev", + "external": "Zunanji", + "external_libraries": "Zunanje knjižnice", + "face_unassigned": "Nedodeljen", + "failed_to_load_assets": "Sredstev ni bilo mogoče naložiti", "favorite": "Priljubljen", - "favorite_or_unfavorite_photo": "", + "favorite_or_unfavorite_photo": "Priljubljena ali nepriljubljena fotografija", "favorites": "Priljubljene", - "feature": "", - "feature_photo_updated": "", - "featurecollection": "", - "file_name": "", - "file_name_or_extension": "", - "filename": "", - "files": "", - "filetype": "", - "filter_people": "", - "fix_incorrect_match": "", - "force_re-scan_library_files": "", - "forward": "", - "general": "", - "get_help": "", - "getting_started": "", - "go_back": "", - "go_to_search": "", - "go_to_share_page": "", - "group_albums_by": "", - "has_quota": "", - "hide_gallery": "", - "hide_password": "", - "hide_person": "", - "host": "", - "hour": "", + "feature_photo_updated": "Funkcijska fotografija je posodobljena", + "features": "Funkcije", + "features_setting_description": "Upravljaj funkcije aplikacije", + "file_name": "Ime datoteke", + "file_name_or_extension": "Ime ali končnica datoteke", + "filename": "Ime datoteke", + "filetype": "Vrsta datoteke", + "filter_people": "Filtriraj ljudi", + "find_them_fast": "Z iskanjem jih hitro poiščite po imenu", + "fix_incorrect_match": "Popravi napačno ujemanje", + "folders": "Mape", + "folders_feature_description": "Brskanje po pogledu mape za fotografije in videoposnetke v datotečnem sistemu", + "forward": "Naprej", + "general": "Splošno", + "get_help": "Poiščite pomoč", + "getting_started": "Začetek", + "go_back": "Pojdi nazaj", + "go_to_search": "Pojdi na iskanje", + "group_albums_by": "Združi albume po ...", + "group_no": "Brez združevanja", + "group_owner": "Združi po lastniku", + "group_year": "Združi po letih", + "has_quota": "Ima kvoto", + "hi_user": "Živijo {name} ({email})", + "hide_all_people": "Skrij vse ljudi", + "hide_gallery": "Skrij galerijo", + "hide_named_person": "Skrij osebo {name}", + "hide_password": "Skrij geslo", + "hide_person": "Skrij osebo", + "hide_unnamed_people": "Skrij osebe brez imen", + "host": "Gostitelj", + "hour": "Ura", "image": "Slika", - "img": "", - "immich_logo": "", - "import_path": "", - "in_archive": "", + "image_alt_text_date": "{isVideo, select, true {Video} other {Image}} zajet {date}", + "image_alt_text_date_1_person": "{isVideo, select, true {Video} other {Image}} zajet z osebo {person1} dne {date}", + "image_alt_text_date_2_people": "{isVideo, select, true {Video} other {Image}} zajet z osebo {person1} in osebo {person2} dne {date}", + "image_alt_text_date_3_people": "{isVideo, select, true {Video} other {Image}} zajet z osebami {person1}, {person2}, in {person3} dne {date}", + "image_alt_text_date_4_or_more_people": "{isVideo, select, true {Video} other {Image}} zajet z osebami {person1}, {person2} in ostalimi {additionalCount, number} osebami dne {date}", + "image_alt_text_date_place": "{isVideo, select, true {Video} other {Image}} zajet/a v/na {city}, {country} dne {date}", + "image_alt_text_date_place_1_person": "{isVideo, select, true {Video} other {Image}} zajet/a/e v/na {city}, {country} s/z {person1} dne {date}", + "image_alt_text_date_place_2_people": "{isVideo, select, true {Video} other {Image}}zajet/a/e/i v/na {city}, {country} s/z {person1} in {person2} dne {date}", + "image_alt_text_date_place_3_people": "{isVideo, select, true {Video} other {Image}} zajet/a/e/i v/na {city}, {country} s/z {person1}, {person2} in {person3} dne {date}", + "image_alt_text_date_place_4_or_more_people": "{isVideo, select, true {Video} other {Image}} zajet/a/e/i v/na {city}, {country} s/z {person1}, {person2} on ostalimi {additionalCount, number} osebami dne {date}", + "immich_logo": "Immich logo", + "immich_web_interface": "Immich spletni vmesnik", + "import_from_json": "Uvoz iz JSON", + "import_path": "Pot uvoza", + "in_albums": "V {count, plural, one {# album} other {# albumov}}", + "in_archive": "V arhiv", "include_archived": "Vključi arhivirane", - "include_shared_albums": "", - "include_shared_partner_assets": "", - "individual_share": "", - "info": "", + "include_shared_albums": "Vključite skupne albume", + "include_shared_partner_assets": "Vključite partnerjeva skupna sredstva", + "individual_share": "Samostojna delitev", + "info": "Info", "interval": { - "day_at_onepm": "", - "hours": "", - "night_at_midnight": "", - "night_at_twoam": "" + "day_at_onepm": "Vsak dan ob 13h", + "hours": "Vsakih {hours, plural, one {uro} other {{hours, number} ur/e}}", + "night_at_midnight": "Vsak večer ob polnoči", + "night_at_twoam": "Vsako noč ob 2h" }, - "invite_people": "", + "invite_people": "Povabi ljudi", "invite_to_album": "Povabi v album", - "job_settings_description": "", - "jobs": "", - "keep": "", - "keyboard_shortcuts": "", - "language": "", - "language_setting_description": "", - "last_seen": "", - "leave": "", + "items_count": "{count, plural, one {# predmet} other {# predmetov}}", + "jobs": "Opravila", + "keep": "Obdrži", + "keep_all": "Obdrži vse", + "keep_this_delete_others": "Obdrži to, izbriši ostalo", + "kept_this_deleted_others": "Obdrži to sredstvo in izbriši {count, plural, one {# sredstvo} other {# sredstev}}", + "keyboard_shortcuts": "Bližnjice na tipkovnici", + "language": "Jezik", + "language_setting_description": "Izberite želeni jezik", + "last_seen": "Nazadnje viden", + "latest_version": "Najnovejša različica", + "latitude": "Zemljepisna širina", + "leave": "Zapusti", "let_others_respond": "Naj drugi odgovorijo", - "level": "", + "level": "Raven", "library": "Knjižnica", - "library_options": "", - "light": "", - "link_options": "", - "link_to_oauth": "", - "linked_oauth_account": "", - "list": "", - "loading": "", - "loading_search_results_failed": "", + "library_options": "Možnosti knjižnice", + "light": "Svetlo", + "like_deleted": "Všeček izbrisan", + "link_motion_video": "Povezava videa gibanja", + "link_options": "Možnosti povezave", + "link_to_oauth": "Povezava do OAuth", + "linked_oauth_account": "Povezan račun OAuth", + "list": "Seznam", + "loading": "Nalaganje", + "loading_search_results_failed": "Nalaganje rezultatov iskanja ni uspelo", "log_out": "Odjava", - "log_out_all_devices": "", - "login_has_been_disabled": "", - "look": "", - "loop_videos": "", + "log_out_all_devices": "Odjava vseh naprav", + "logged_out_all_devices": "Odjavljene so vse naprave", + "logged_out_device": "Odjavljena naprava", + "login": "Prijava", + "login_has_been_disabled": "Prijava je bila onemogočena.", + "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?", + "longitude": "Zemljepisna dolžina", + "look": "Izgled", + "loop_videos": "Zanka videoposnetkov", "loop_videos_description": "Omogočite samodejno ponavljanje videoposnetka v pregledovalniku podrobnosti.", + "main_branch_warning": "Uporabljate razvojno različico; močno priporočamo uporabo izdajne različice!", "make": "Izdelava", "manage_shared_links": "Upravljanje povezav v skupni rabi", - "manage_sharing_with_partners": "", - "manage_the_app_settings": "", - "manage_your_account": "", - "manage_your_api_keys": "", - "manage_your_devices": "", - "manage_your_oauth_connection": "", - "map": "", - "map_marker_with_image": "", + "manage_sharing_with_partners": "Upravljajte skupno rabo s partnerji", + "manage_the_app_settings": "Upravljajte nastavitve aplikacije", + "manage_your_account": "Upravljajte svoj račun", + "manage_your_api_keys": "Upravljajte svoje API ključe", + "manage_your_devices": "Upravljajte svoje prijavljene naprave", + "manage_your_oauth_connection": "Upravljajte svojo OAuth povezavo", + "map": "Zemljevid", + "map_marker_for_images": "Oznaka zemljevida za slike, posnete v {city}, {country}", + "map_marker_with_image": "Oznaka zemljevida s sliko", "map_settings": "Nastavitve zemljevida", - "media_type": "", - "memories": "", - "memories_setting_description": "", - "menu": "", - "merge": "", - "merge_people": "", - "merge_people_successfully": "", - "minimize": "", - "minute": "", - "missing": "", - "model": "", + "matches": "Ujemanja", + "media_type": "Vrsta medija", + "memories": "Spomini", + "memories_setting_description": "Upravljajte s tem, kar vidite v svojih spominih", + "memory": "Spomin", + "memory_lane_title": "Spominski trak {title}", + "menu": "Meni", + "merge": "Združi", + "merge_people": "Združi osebe", + "merge_people_limit": "Hkrati lahko združite največ 5 obrazov", + "merge_people_prompt": "Ali želite združiti te osebe? To dejanje je nepovratno.", + "merge_people_successfully": "Združitev ljudi uspešno", + "merged_people_count": "Združeno {count, plural, one {# oseba} two {# osebi} few {# osebe} other {# oseb}}", + "minimize": "Zmanjšaj", + "minute": "minuta", + "missing": "manjka", + "model": "Model", "month": "Mesec", - "more": "", - "moved_to_trash": "", - "my_albums": "", + "more": "Več", + "moved_to_trash": "Premaknjeno v smetnjak", + "my_albums": "Moji albumi", "name": "Ime", - "name_or_nickname": "", + "name_or_nickname": "Ime ali vzdevek", "never": "nikoli", - "new_api_key": "", + "new_album": "Nov album", + "new_api_key": "Nov API ključ", "new_password": "Novo geslo", - "new_person": "", - "new_user_created": "", - "newest_first": "", + "new_person": "Nova oseba", + "new_user_created": "Nov uporabnik ustvarjen", + "new_version_available": "NA VOLJO JE NOVA RAZLIČICA", + "newest_first": "Najprej najnovejše", "next": "Naslednji", - "next_memory": "", - "no": "", - "no_albums_message": "", - "no_archived_assets_message": "", - "no_assets_message": "", - "no_exif_info_available": "", - "no_explore_results_message": "", - "no_favorites_message": "", - "no_libraries_message": "", - "no_name": "", - "no_places": "", - "no_results": "", - "no_shared_albums_message": "", - "not_in_any_album": "", - "notes": "", - "notification_toggle_setting_description": "", + "next_memory": "Naslednji spomin", + "no": "Ne", + "no_albums_message": "Ustvarite album za organiziranje svojih fotografij in videoposnetkov", + "no_albums_with_name_yet": "Videti je, da še nimate nobenega albuma s tem imenom.", + "no_albums_yet": "Videti je, da še nimate nobenega albuma.", + "no_archived_assets_message": "Arhivirajte fotografije in videoposnetke, da jih skrijete v pogledu fotografij", + "no_assets_message": "KLIKNITE ZA NALOŽITEV SVOJE PRVE FOTOGRAFIJE", + "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_name": "Brez imena", + "no_places": "Ni krajev", + "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", + "not_in_any_album": "Ni v nobenem albumu", + "note_apply_storage_label_to_previously_uploaded assets": "Opomba: Če želite oznako za shranjevanje uporabiti za predhodno naložena sredstva, zaženite", + "note_unlimited_quota": "Opomba: Vnesite 0 za neomejeno kvoto", + "notes": "Opombe", + "notification_toggle_setting_description": "Omogoči e-poštna obvestila", "notifications": "Obvestila", - "notifications_setting_description": "", - "oauth": "", - "offline": "", + "notifications_setting_description": "Upravljanje obvestil", + "oauth": "OAuth", + "official_immich_resources": "Immich uradni viri", + "offline": "Brez povezave", + "offline_paths": "Poti brez povezave", + "offline_paths_description": "Ti rezultati so morda posledica ročnega brisanja datotek, ki niso del zunanje knjižnice.", "ok": "V redu", - "oldest_first": "", - "online": "", - "only_favorites": "", - "only_refreshes_modified_files": "", - "open_the_search_filters": "", + "oldest_first": "Najprej najstarejši", + "onboarding": "Vkrcanje", + "onboarding_privacy_description": "Naslednje (neobvezne) funkcije so odvisne od zunanjih storitev in jih je mogoče kadar koli onemogočiti v skrbniških nastavitvah.", + "onboarding_theme_description": "Izberite barvno temo za svoj primer. To lahko pozneje spremenite v nastavitvah.", + "onboarding_welcome_description": "Nastavimo vaš primerek z nekaj običajnimi nastavitvami.", + "onboarding_welcome_user": "Pozdravljen/a, {user}", + "online": "Povezano", + "only_favorites": "Samo priljubljene", + "open_in_map_view": "Odpri v pogledu zemljevida", + "open_in_openstreetmap": "Odpri v OpenStreetMap", + "open_the_search_filters": "Odpri iskalne filtre", "options": "Možnosti", - "organize_your_library": "", - "other": "", - "other_devices": "", - "other_variables": "", + "or": "ali", + "organize_your_library": "Organiziraj svojo knjižnico", + "original": "izvirnik", + "other": "drugo", + "other_devices": "Druge naprave", + "other_variables": "Druge spremenljivke", "owned": "V lasti", "owner": "Lastnik", - "partner_sharing": "", - "partners": "", + "partner": "Partner", + "partner_can_access": "{partner} ima dostop", + "partner_can_access_assets": "Vse vaše fotografije in videoposnetki, razen tistih v arhivu in izbrisanih", + "partner_can_access_location": "Lokacija, kjer so bile vaše fotografije posnete", + "partner_sharing": "Skupna raba s partnerjem", + "partners": "Partnerji", "password": "Geslo", - "password_does_not_match": "", - "password_required": "", - "password_reset_success": "", + "password_does_not_match": "Geslo se ne ujema", + "password_required": "Zahtevano je geslo", + "password_reset_success": "Ponastavitev gesla je uspela", "past_durations": { - "days": "", - "hours": "", - "years": "" + "days": "Pretek-el/-lih {days, plural, one {dan} other {# dni}}", + "hours": "Pretek-lo/-lih {hours, plural, one {uro} other {# ur}}", + "years": "Pretek-lo/-lih {years, plural, one {leto} other {# let}}" }, - "path": "", - "pattern": "", - "pause": "", - "pause_memories": "", - "paused": "", - "pending": "", - "people": "Ljudje", - "people_sidebar_description": "", - "perform_library_tasks": "", - "permanent_deletion_warning": "", - "permanent_deletion_warning_setting_description": "", - "permanently_delete": "", - "permanently_deleted_asset": "", + "path": "Pot", + "pattern": "Vzorec", + "pause": "Premor", + "pause_memories": "Zaustavi spomine", + "paused": "Zaustavljeno", + "pending": "V teku", + "people": "Osebe", + "people_edits_count": "Urejen-a/-ih {count, plural, one {# oseba} other {# oseb}}", + "people_feature_description": "Brskanje po fotografijah in videoposnetkih, razvrščenih po osebah", + "people_sidebar_description": "Prikažite povezavo do Ljudje v stranski vrstici", + "permanent_deletion_warning": "Opozorilo o trajnem izbrisu", + "permanent_deletion_warning_setting_description": "Pokaži opozorilo pri trajnem brisanju sredstev", + "permanently_delete": "Trajno izbriši", + "permanently_delete_assets_count": "Trajno izbriši {count, plural, one {sredstvo} other {sredstev}}", + "permanently_delete_assets_prompt": "Ali ste prepričani, da želite trajno izbrisati {count, plural, one {to sredstvo?} other {ta # sredstva?}} S tem boste odstranili tudi {count, plural, one {tega od teh} other {telih iz telih}} album- /-ov.", + "permanently_deleted_asset": "Trajno izbrisano sredstvo", + "permanently_deleted_assets_count": "Trajno izbrisano {count, plural, one {# sredstvo} two {# sredstvi} few {# sredstva} other {# sredstev}}", + "person": "Oseba", + "person_hidden": "{name}{hidden, select, true { (skrita)} other {}}", + "photo_shared_all_users": "Videti je, da ste svoje fotografije delili z vsemi uporabniki ali pa nimate nobenega uporabnika, s katerim bi jih delili.", "photos": "Slike", - "photos_from_previous_years": "", - "pick_a_location": "", - "place": "", + "photos_and_videos": "Fotografije & videi", + "photos_count": "{count, plural, one {{count, number} slika} other {{count, number} slik}}", + "photos_from_previous_years": "Fotografije iz prejšnjih let", + "pick_a_location": "Izberi lokacijo", + "place": "Lokacija", "places": "Lokacije", - "play": "", - "play_memories": "", - "play_motion_photo": "", - "play_or_pause_video": "", - "point": "", - "port": "", - "preset": "", - "preview": "", - "previous": "", - "previous_memory": "", - "previous_or_next_photo": "", - "primary": "", - "profile_picture_set": "", - "public_share": "", - "range": "", - "raw": "", - "reaction_options": "", - "read_changelog": "", - "recent": "", - "recent_searches": "", - "refresh": "", - "refreshed": "", - "refreshes_every_file": "", - "remove": "", - "remove_deleted_assets": "", + "play": "Predvajaj", + "play_memories": "Predvajaj spomine", + "play_motion_photo": "Predvajaj premikajočo fotografijo", + "play_or_pause_video": "Predvajaj ali zaustavi video", + "port": "Vrata", + "preset": "Prednastavitev", + "preview": "Predogled", + "previous": "Prejšnj-a/-i", + "previous_memory": "Prejšnji spomin", + "previous_or_next_photo": "Prejšnja ali naslednja fotografija", + "primary": "Primarni", + "privacy": "Zasebnost", + "profile_image_of_user": "Profilna slika uporabnika {user}", + "profile_picture_set": "Profilna slika nastavljena.", + "public_album": "Javni album", + "public_share": "Javno deljenje", + "purchase_account_info": "Podpornik", + "purchase_activated_subtitle": "Hvala, ker podpirate Immich in odprtokodno programsko opremo", + "purchase_activated_time": "Aktivirano {date, date}", + "purchase_activated_title": "Vaš ključ je bil uspešno aktiviran", + "purchase_button_activate": "Aktiviraj", + "purchase_button_buy": "Kupi", + "purchase_button_buy_immich": "Kupi Immich", + "purchase_button_never_show_again": "Nikoli več ne pokaži", + "purchase_button_reminder": "Opomni me čez 30 dni", + "purchase_button_remove_key": "Odstrani ključ", + "purchase_button_select": "Izberi", + "purchase_failed_activation": "Aktivacija ni uspela! Preverite svojo e-pošto za pravilen ključ izdelka!", + "purchase_individual_description_1": "Za posameznika", + "purchase_individual_description_2": "Status podpornika", + "purchase_individual_title": "Posamezno", + "purchase_input_suggestion": "Ali imate ključ izdelka? Spodaj vnesite ključ", + "purchase_license_subtitle": "Kupite Immich, da podprete nadaljnji razvoj storitve", + "purchase_lifetime_description": "Doživljenjski nakup", + "purchase_option_title": "MOŽNOSTI NAKUPA", + "purchase_panel_info_1": "Gradnja Immicha zahteva veliko časa in truda, zato imamo zaposlene inženirje, ki delajo na tem, da bi bil čim boljši. Naše poslanstvo je, da odprtokodna programska oprema in etične poslovne prakse, ki bi postale trajnostni vir dohodka za razvijalce in ustvarjanje ekosistema, ki spoštuje zasebnost z resničnimi alternativami izkoriščevalskim storitvam v oblaku.", + "purchase_panel_info_2": "Ker se zavezujemo, da ne bomo dodajali plačilnih storitev, vam ta nakup ne bo omogočil nobenih dodatnih funkcij v Immichu. Zanašamo se na uporabnike, kot ste vi, ki podpirajo nenehni razvoj Immicha.", + "purchase_panel_title": "Podpri projekt", + "purchase_per_server": "Na strežnik", + "purchase_per_user": "Na uporabnika", + "purchase_remove_product_key": "Odstrani ključ izdelka", + "purchase_remove_product_key_prompt": "Ali ste prepričani, da želite odstraniti ključ izdelka?", + "purchase_remove_server_product_key": "Odstranite ključ izdelka strežnika", + "purchase_remove_server_product_key_prompt": "Ali ste prepričani, da želite odstraniti ključ izdelka strežnika?", + "purchase_server_description_1": "Za celoten strežnik", + "purchase_server_description_2": "Status podpornika", + "purchase_server_title": "Strežnik", + "purchase_settings_server_activated": "Ključ izdelka strežnika upravlja skrbnik", + "rating": "Ocena z zvezdicami", + "rating_clear": "Počisti oceno", + "rating_count": "{count, plural, one {# zvezdica} two {# zvezdici} few {# zvezdice} other {# zvezdic}}", + "rating_description": "Prikažite oceno EXIF v informacijski plošči", + "reaction_options": "Možnosti reakcije", + "read_changelog": "Preberi dnevnik sprememb", + "reassign": "Prerazporedi", + "reassigned_assets_to_existing_person": "Ponovno dodeljeno {count, plural, one {# sredstvo} other {# sredstev}} za {name, select, null {an existing person} other {{name}}}", + "reassigned_assets_to_new_person": "Ponovno dodeljeno {count, plural, one {# sredstvo} two {# sredstvi} few {# sredstva} other {# sredstev}} za novo osebo", + "reassing_hint": "Dodeli izbrana sredstva obstoječi osebi", + "recent": "Nedavno", + "recent-albums": "Zadnji albumi", + "recent_searches": "Nedavna iskanja", + "refresh": "Osveži", + "refresh_encoded_videos": "Osveži kodirane videoposnetke", + "refresh_faces": "Osveži obraze", + "refresh_metadata": "Osveži metapodatke", + "refresh_thumbnails": "Osveži sličice", + "refreshed": "Osveženo", + "refreshes_every_file": "Ponovno prebere vse obstoječe in nove datoteke", + "refreshing_encoded_video": "Osveževanje kodiranega videa", + "refreshing_faces": "Osveževanje obrazev", + "refreshing_metadata": "Osveževanje metapodatkov", + "regenerating_thumbnails": "Obnavljanje sličic", + "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?", + "remove_assets_title": "Odstrani sredstva?", + "remove_custom_date_range": "Odstrani časovno obdobje po meri", + "remove_deleted_assets": "Odstrani izbrisana sredstva", "remove_from_album": "Odstrani iz albuma", - "remove_from_favorites": "", - "remove_from_shared_link": "", - "repair": "", - "repair_no_results_message": "", - "replace_with_upload": "", - "require_password": "", - "reset": "", - "reset_password": "", - "reset_people_visibility": "", - "reset_settings_to_default": "", + "remove_from_favorites": "Odstrani iz priljubljenih", + "remove_from_shared_link": "Odstrani iz skupne povezave", + "remove_url": "Odstrani URL", + "remove_user": "Odstrani uporabnika", + "removed_api_key": "Odstranjen ključ API-ja: {name}", + "removed_from_archive": "Odstranjeno iz arhiva", + "removed_from_favorites": "Odstranjeno iz priljubljenih", + "removed_from_favorites_count": "{count, plural, other {odstranen/ih #}} iz priljubljenih", + "removed_tagged_assets": "Odstranjena oznaka iz {count, plural, one {# sredstva} other {# sredstev}}", + "rename": "Preimenuj", + "repair": "Popravi", + "repair_no_results_message": "Datoteke, ki jim ni sledi in manjkajo, bodo prikazane tukaj", + "replace_with_upload": "Zamenjaj z nalaganjem", + "repository": "Repozitorij", + "require_password": "Zahtevaj geslo", + "require_user_to_change_password_on_first_login": "Od uporabnika zahtevajte spremembo gesla ob prvi prijavi", + "reset": "Ponastavi", + "reset_password": "Ponastavi geslo", + "reset_people_visibility": "Ponastavi vidnost ljudi", + "reset_to_default": "Ponastavi na privzeto", + "resolve_duplicates": "Razreši dvojnike", + "resolved_all_duplicates": "Razrešeni vsi dvojniki", "restore": "Obnovi", - "restore_user": "", - "retry_upload": "", - "review_duplicates": "", - "role": "", + "restore_all": "Obnovi vse", + "restore_user": "Obnovi uporabnika", + "restored_asset": "Obnovljeno sredstvo", + "resume": "Nadaljuj", + "retry_upload": "Poskusite znova naložiti", + "review_duplicates": "Pregled dvojnikov", + "role": "Dovoljenje", + "role_editor": "Urejevalec", + "role_viewer": "Gledalec", "save": "Shrani", - "saved_profile": "", - "saved_settings": "", + "saved_api_key": "Shranjen API ključ", + "saved_profile": "Shranjen profil", + "saved_settings": "Shranjene nastavitve", "say_something": "Reci kaj", - "scan_all_libraries": "", - "scan_all_library_files": "", - "scan_new_library_files": "", - "scan_settings": "", + "scan_all_libraries": "Preglej vse knjižnice", + "scan_library": "Pregled", + "scan_settings": "Nastavitve pregleda", + "scanning_for_album": "Iskanje albuma...", "search": "Iskanje", - "search_albums": "", - "search_by_context": "", - "search_camera_make": "", - "search_camera_model": "", - "search_city": "", - "search_country": "", - "search_for_existing_person": "", - "search_people": "", - "search_places": "", - "search_state": "", - "search_timezone": "", - "search_type": "", + "search_albums": "Iskanje albumov", + "search_by_context": "Iskanje po kontekstu", + "search_by_filename": "Iskanje po imenu datoteke ali priponi", + "search_by_filename_example": "na primer IMG_1234.JPG ali PNG", + "search_camera_make": "Iskanje proizvajalca kamere...", + "search_camera_model": "Išči model kamere...", + "search_city": "Iskanje mesta...", + "search_country": "Iskanje države...", + "search_for_existing_person": "Iskanje obstoječe osebe", + "search_no_people": "Brez oseb", + "search_no_people_named": "Ni oseb z imenom \"{name}\"", + "search_options": "Možnosti iskanja", + "search_people": "Iskanje oseb", + "search_places": "Iskanje krajev", + "search_settings": "Nastavitve iskanja", + "search_state": "Iskanje dežele...", + "search_tags": "Iskanje oznak...", + "search_timezone": "Iskanje časovnega pasu...", + "search_type": "Vrsta iskanja", "search_your_photos": "Poišči svoje fotografije", - "searching_locales": "", - "second": "", - "select_album_cover": "", - "select_all": "", - "select_avatar_color": "", - "select_face": "", - "select_featured_photo": "", - "select_library_owner": "", - "select_new_face": "", + "searching_locales": "Iskanje krajev...", + "second": "Sekunda", + "see_all_people": "Oglejte si vse ljudi", + "select_album_cover": "Izberi naslovnico albuma", + "select_all": "Izberi vse", + "select_all_duplicates": "Izberi vse dvojnike", + "select_avatar_color": "Izberi barvo avatarja", + "select_face": "Izberi obraz", + "select_featured_photo": "Izberi predstavljeno fotografijo", + "select_from_computer": "Izberi iz računalnika", + "select_keep_all": "Izberi obdrži vse", + "select_library_owner": "Izberi lastnika knjižnice", + "select_new_face": "Izberi nov obraz", "select_photos": "Izberi fotografije", - "selected": "", - "send_message": "", - "server": "", - "server_stats": "", - "set": "", - "set_as_album_cover": "", - "set_as_profile_picture": "", - "set_date_of_birth": "", - "set_profile_picture": "", - "set_slideshow_to_fullscreen": "", + "select_trash_all": "Izberi vse v smetnjak", + "selected": "Izbrano", + "selected_count": "{count, plural, other {# izbranih}}", + "send_message": "Pošlji sporočilo", + "send_welcome_email": "Pošlji pozdravno e-pošto", + "server_offline": "Strežnik nima povezave", + "server_online": "Strežnik povezan", + "server_stats": "Statistika strežnika", + "server_version": "Različica strežnika", + "set": "Nastavi", + "set_as_album_cover": "Nastavi kot naslovnico albuma", + "set_as_profile_picture": "Nastavi kot profilno sliko", + "set_date_of_birth": "Nastavi datum rojstva", + "set_profile_picture": "Nastavi profilno sliko", + "set_slideshow_to_fullscreen": "Nastavi diaprojekcijo na celozaslonski način", "settings": "Nastavitve", - "settings_saved": "", + "settings_saved": "Nastavitve shranjene", "share": "Deli", "shared": "V skupni rabi", - "shared_by": "", - "shared_by_you": "", + "shared_by": "Skupna raba s/z", + "shared_by_user": "Skupna raba s/z {user}", + "shared_by_you": "Deliš", + "shared_from_partner": "Fotografije od {partner}", + "shared_link_options": "Možnosti skupne povezave", "shared_links": "Povezave v skupni rabi", + "shared_photos_and_videos_count": "{assetCount, plural, other {# deljenih fotografij & videoposnetkov.}}", + "shared_with_partner": "V skupni rabi s/z {partner}", "sharing": "Skupna raba", - "sharing_sidebar_description": "", - "show_album_options": "", - "show_file_location": "", - "show_gallery": "", - "show_hidden_people": "", - "show_in_timeline": "", - "show_in_timeline_setting_description": "", - "show_keyboard_shortcuts": "", + "sharing_enter_password": "Za ogled te strani vnesi geslo.", + "sharing_sidebar_description": "Prikažite povezavo do skupne rabe v stranski vrstici", + "shift_to_permanent_delete": "pritisni ⇧ za trajno brisanje sredstva", + "show_album_options": "Prikaži možnosti albuma", + "show_albums": "Prikaži albume", + "show_all_people": "Prikaži vse osebe", + "show_and_hide_people": "Prikaži & skrij osebe", + "show_file_location": "Pokaži lokacijo datoteke", + "show_gallery": "Prikaži galerijo", + "show_hidden_people": "Prikaži skrite osebe", + "show_in_timeline": "Pokaži na časovnici", + "show_in_timeline_setting_description": "Prikaži fotografije in videoposnetke tega uporabnika na svoji časovnici", + "show_keyboard_shortcuts": "Prikaži bližnjice na tipkovnici", "show_metadata": "Pokaži metapodatke", - "show_or_hide_info": "", - "show_password": "", - "show_person_options": "", - "show_progress_bar": "", - "show_search_options": "", - "shuffle": "", - "sign_up": "", - "size": "", - "skip_to_content": "", - "slideshow": "", - "slideshow_settings": "", - "sort_albums_by": "", + "show_or_hide_info": "Pokaži ali skrij podatke", + "show_password": "Prikaži geslo", + "show_person_options": "Prikaži možnosti osebe", + "show_progress_bar": "Prikaži vrstico napredka", + "show_search_options": "Prikaži možnosti iskanja", + "show_slideshow_transition": "Prikaži prehod diaprojekcije", + "show_supporter_badge": "Značka podpornika", + "show_supporter_badge_description": "Prikaži značko podpornika", + "shuffle": "Naključno", + "sidebar": "Stranska vrstica", + "sidebar_display_description": "Prikaži povezavo do pogleda v stranski vrstici", + "sign_out": "Odjavi se", + "sign_up": "Prijavi se", + "size": "Velikost", + "skip_to_content": "Preskoči na vsebino", + "skip_to_folders": "Preskoči na mape", + "skip_to_tags": "Preskoči na oznake", + "slideshow": "Diaprojekcija", + "slideshow_settings": "Nastavitve diaprojekcije", + "sort_albums_by": "Razvrsti albume po...", + "sort_created": "Datum nastanka", + "sort_items": "Število predmetov", + "sort_modified": "Datum spremembe", + "sort_oldest": "Najstarejša fotografija", + "sort_recent": "Najnovejša fotografija", + "sort_title": "Naslov", + "source": "Vir", "stack": "Sklad", - "stack_selected_photos": "", - "stacktrace": "", - "start_date": "", + "stack_duplicates": "Nabor dvojnikov", + "stack_select_one_photo": "Izberite eno glavno fotografijo za nabor", + "stack_selected_photos": "Nabor izbranih fotografij", + "stacked_assets_count": "Nabor {count, plural, one {# sredstvo} two {# sredstvi} few {# sredstva} other {# sredstev}}", + "stacktrace": "Sled nabora", + "start": "Začetek", + "start_date": "Datum začetka", "state": "Dežela", - "status": "", - "stop_motion_photo": "", + "status": "Status", + "stop_motion_photo": "Zaustavi gibljivo fotografijo", "stop_photo_sharing": "Želite prenehati deliti svoje fotografije?", - "storage": "", - "storage_label": "", - "submit": "", + "stop_photo_sharing_description": "{partner} ne bo mogel več dostopati do vaših fotografij.", + "stop_sharing_photos_with_user": "Prenehaj deliti svoje fotografije s tem uporabnikom", + "storage": "Prostor za shranjevanje", + "storage_label": "Oznaka za shranjevanje", + "storage_usage": "uporabljeno {used} od {available}", + "submit": "Predloži", "suggestions": "Predlogi", - "sunrise_on_the_beach": "", - "swap_merge_direction": "", - "sync": "", - "template": "", + "sunrise_on_the_beach": "Sončni vzhod na plaži", + "support": "Podpora", + "support_and_feedback": "Podpora in povratne informacije", + "support_third_party_description": "Vašo namestitev Immich je pakirala tretja oseba. Težave, ki jih imate, lahko povzroči ta paket, zato prosimo, da težave najprej izpostavite njim, tako da uporabite spodnje povezave.", + "swap_merge_direction": "Zamenjaj smer združevanja", + "sync": "Sinhronizacija", + "tag": "Oznaka", + "tag_assets": "Označi sredstva", + "tag_created": "Ustvarjena oznaka: {tag}", + "tag_feature_description": "Brskanje po fotografijah in videoposnetkih, razvrščenih po temah logičnih oznak", + "tag_not_found_question": "Ne najdete oznake? Ustvarite novo oznako.", + "tag_updated": "Posodobljena oznaka: {tag}", + "tagged_assets": "Označeno {count, plural, one {# sredstvo} two {# sredstvi} few {# sredstva} other {# sredstev}}", + "tags": "Oznake", + "template": "Predloga", "theme": "Tema", - "theme_selection": "", - "theme_selection_description": "", - "time_based_memories": "", + "theme_selection": "Izbira teme", + "theme_selection_description": "Samodejno nastavi temo na svetlo ali temno glede na sistemske nastavitve brskalnika", + "they_will_be_merged_together": "Združeni bodo skupaj", + "third_party_resources": "Viri tretjih oseb", + "time_based_memories": "Časovni spomini", + "timeline": "Časovnica", "timezone": "Časovni pas", - "toggle_settings": "", - "toggle_theme": "", - "toggle_visibility": "", - "total_usage": "", + "to_archive": "Arhiv", + "to_change_password": "Spremeni geslo", + "to_favorite": "Priljubljen", + "to_login": "Prijava", + "to_parent": "Pojdi na prvotno", + "to_trash": "Smetnjak", + "toggle_settings": "Preklopi na nastavitve", + "toggle_theme": "Preklopi na temno temo", + "total": "Skupno", + "total_usage": "Skupna poraba", "trash": "Smetnjak", - "trash_all": "", - "trash_no_results_message": "", - "type": "", + "trash_all": "Vse v smetnjak", + "trash_count": "Smetnjak {count, number}", + "trash_delete_asset": "V smetnjak/izbriši sredstvo", + "trash_no_results_message": "Fotografije in videoposnetki, ki so v smetnjaku, bodo prikazani tukaj.", + "trashed_items_will_be_permanently_deleted_after": "Elementi v smetnjaku bodo trajno izbrisani po {days, plural, one {# dnevu} two {# dnevih} few {# dnevih} other {# dneh}}.", + "type": "Vrsta", "unarchive": "Odstrani iz arhiva", - "unarchived": "", - "unfavorite": "Odstrani iz priljubljeno", - "unhide_person": "", - "unknown": "", - "unknown_album": "", - "unknown_year": "", - "unlink_oauth": "", - "unlinked_oauth_account": "", - "unselect_all": "", - "unstack": "Razkladi", - "up_next": "", - "updated_password": "", + "unarchived_count": "{count, plural, other {nearhiviranih #}}", + "unfavorite": "Odznači priljubljeno", + "unhide_person": "Prikaži osebo", + "unknown": "Neznano", + "unknown_year": "Neznano leto", + "unlimited": "Neomejeno", + "unlink_motion_video": "Prekini povezavo videoposnetka gibanja", + "unlink_oauth": "Prekini povezavo OAuth", + "unlinked_oauth_account": "Nepovezan račun OAuth", + "unnamed_album": "Neimenovan album", + "unnamed_album_delete_confirmation": "Ali ste prepričani, da želite izbrisati ta album?", + "unnamed_share": "Neimenovana skupna raba", + "unsaved_change": "Neshranjena sprememba", + "unselect_all": "Odznači vse", + "unselect_all_duplicates": "Odznači vse dvojnike", + "unstack": "Razklad", + "unstacked_assets_count": "Razloži {count, plural, one {# sredstvo} two {# sredstvi} few {# sredstva} other {# sredstev}}", + "untracked_files": "Nesledene datoteke", + "untracked_files_decription": "Tem datotekam aplikacija ne sledi. Lahko so posledica neuspelih premikov, prekinjenih ali zaostalih nalaganj zaradi hrošča", + "up_next": "Naslednja", + "updated_password": "Posodobljeno geslo", "upload": "Naloži", - "upload_concurrency": "", - "url": "", - "usage": "", - "user": "", - "user_id": "", - "user_usage_detail": "", - "username": "", - "users": "", - "utilities": "", - "validate": "", - "variables": "", - "version": "", - "video": "", - "video_hover_setting_description": "", + "upload_concurrency": "Sočasnost nalaganja", + "upload_errors": "Nalaganje je končano s/z {count, plural, one {# napako} two {# napakama} other {# napakami}}, osvežite stran, da vidite nova sredstva za nalaganje.", + "upload_progress": "Preostalo {remaining, number} - Obdelano {processed, number}/{total, number}", + "upload_skipped_duplicates": "Preskočeno {count, plural, one {# podvojeno sredstvo} two {# podvojeni sredstvi} few {# podvojena sredstva} other {# podvojenih sredstev}}", + "upload_status_duplicates": "Dvojniki", + "upload_status_errors": "Napake", + "upload_status_uploaded": "Naloženo", + "upload_success": "Nalaganje je uspelo, osvežite stran, da vidite nova sredstva za nalaganje.", + "url": "URL", + "usage": "Uporaba", + "use_custom_date_range": "Namesto tega uporabite časovno obdobje po meri", + "user": "Uporabnik", + "user_id": "ID uporabnika", + "user_liked": "{user} je všeč {type, select, photo {ta fotografija} video {ta video} asset {to sredstvo} other {to}}", + "user_purchase_settings": "Nakup", + "user_purchase_settings_description": "Upravljajte svoj nakup", + "user_role_set": "Nastavi {user} kot {role}", + "user_usage_detail": "Podrobnosti o uporabi uporabnika", + "user_usage_stats": "Statistika uporabe računa", + "user_usage_stats_description": "Oglejte si statistiko uporabe računa", + "username": "Uporabniško ime", + "users": "Uporabniki", + "utilities": "Pripomočki", + "validate": "Potrdi", + "variables": "Spremenljivke", + "version": "Različica", + "version_announcement_closing": "Tvoj prijatelj, Alex", + "version_announcement_message": "Pozdravljeni! Na voljo je nova različica Immich. Vzemite si nekaj časa in preberite opombe ob izdaji, da zagotovite, da so vaše nastavitve posodobljene, da preprečite morebitne napačne konfiguracije, zlasti če uporabljate WatchTower ali kateri koli mehanizem, ki samodejno posodablja vaš primerek Immich.", + "version_history": "Zgodovina različic", + "version_history_item": "{version} nameščena {date}", + "video": "Video", + "video_hover_setting": "Predvajaj sličico videoposnetka ob lebdenju", + "video_hover_setting_description": "Predvajaj sličico videoposnetka, ko se miška pomakne nad element. Tudi ko je onemogočeno, lahko predvajanje začnete tako, da miškin kazalec premaknete nad ikono za predvajanje.", "videos": "Videoposnetki", + "videos_count": "{count, plural, one {# video} two {# videa} few {# videi} other {# videov}}", + "view": "Ogled", + "view_album": "Ogled albuma", "view_all": "Poglej vse", - "view_all_users": "", - "view_links": "", - "view_next_asset": "", - "view_previous_asset": "", - "viewer": "", - "waiting": "", - "week": "", + "view_all_users": "Ogled vseh uporabnikov", + "view_in_timeline": "Ogled na časovnici", + "view_links": "Ogled povezav", + "view_name": "Pogled", + "view_next_asset": "Ogled naslednjega sredstva", + "view_previous_asset": "Ogled prejšnjega sredstva", + "view_stack": "Ogled sklada", + "visibility_changed": "Vidnost spremenjena za {count, plural, one {# osebo} two {# osebi} few {# osebe} other {# oseb}}", + "waiting": "Čakanje", + "warning": "Opozorilo", + "week": "Teden", "welcome": "Dobrodošli", - "welcome_to_immich": "", + "welcome_to_immich": "Dobrodošli v Immich", "year": "Leto", + "years_ago": "{years, plural, one {# leto} two {# leti} few {# leta} other {# let}} nazaj", "yes": "Da", + "you_dont_have_any_shared_links": "Nimate nobenih skupnih povezav", "zoom_image": "Povečava slike" } diff --git a/i18n/sr_Cyrl.json b/i18n/sr_Cyrl.json index a14c5bbee4c05..e80ea463350eb 100644 --- a/i18n/sr_Cyrl.json +++ b/i18n/sr_Cyrl.json @@ -1,5 +1,5 @@ { - "about": "О апликацији", + "about": "О Апликацији", "account": "Профил", "account_settings": "Подешавања за Профил", "acknowledge": "Потврди", @@ -23,6 +23,7 @@ "add_to": "Додај у...", "add_to_album": "Додај у албум", "add_to_shared_album": "Додај у дељен албум", + "add_url": "Додајте URL", "added_to_archive": "Додато у архиву", "added_to_favorites": "Додато у фаворите", "added_to_favorites_count": "Додато {count, number} у фаворите", @@ -34,6 +35,11 @@ "authentication_settings_disable_all": "Да ли сте сигурни да желите да oneмогућите све методе пријављивања? Пријава ће бити потпуно oneмогућена.", "authentication_settings_reenable": "Да бисте поново омогућили, користите команду сервера.", "background_task_job": "Позадински задаци", + "backup_database": "Резервна копија базе података", + "backup_database_enable_description": "Омогућите резервне копије базе података", + "backup_keep_last_amount": "Количина претходних резервних копија за чување", + "backup_settings": "Подешавања резервне копије", + "backup_settings_description": "Управљајте поставкама резервне копије базе података", "check_all": "Провери све", "cleared_jobs": "Очишћени послови за {job}", "config_set_by_file": "Конфигурацију тренутно поставља конфигурациони фајл", @@ -43,9 +49,10 @@ "confirm_reprocess_all_faces": "Да ли сте сигурни да желите да поново обрадите сва лица? Ово ће такође обрисати именоване особе.", "confirm_user_password_reset": "Да ли сте сигурни да желите да ресетујете лозинку корисника {user}?", "create_job": "Креирајте посао", - "crontab_guru": "Guru servisnih zadataka", + "cron_expression": "Cron израз (expression)", + "cron_expression_description": "Подесите интервал скенирања користећи cron формат. За више информација погледајте нпр. Crontab Guru", + "cron_expression_presets": "Предефинисана подешавања Cron израза (expression)", "disable_login": "oneмогући пријаву", - "disabled": "", "duplicate_detection_job_description": "Покрените машинско учење на средствима да бисте открили сличне слике. Ослања се на паметну претрагу", "exclusion_pattern_description": "Обрасци изузимања вам омогућавају да игноришете датотеке и фасцикле када скенирате библиотеку. Ово је корисно ако имате фасцикле које садрже датотеке које не желите да увезете, као што су RAW датотеке.", "external_library_created_at": "Екстерна библиотека (направљена {date})", @@ -63,22 +70,15 @@ "image_prefer_wide_gamut": "Преферирајте широк спектар", "image_prefer_wide_gamut_setting_description": "Користите Display П3 за сличице. Ово боље чува живописност слика са широким просторима боја, али слике могу изгледати другачије на старим уређајима са старом верзијом претраживача. сРГБ слике се чувају као сРГБ да би се избегле промене боја.", "image_preview_description": "Слика средње величине са уклоњеним метаподацима, која се користи приликом прегледа једног елемента и за машинско учење", - "image_preview_format": "Преглед формата", "image_preview_quality_description": "Квалитет прегледа од 1-100. Више је боље, али производи веће датотеке и може смањити одзив апликације. Постављање ниске вредности може утицати на квалитет машинског учења.", - "image_preview_resolution": "Преглед резолуције", - "image_preview_resolution_description": "Користи се за гледање једне фотографије и за машинско учење. Веће резолуције могу да сачувају више детаља, али им је потребно више времена за кодирање, имају веће величине датотека и могу да смање брзину апликације.", "image_preview_title": "Подешавања прегледа", "image_quality": "Квалитет", - "image_quality_description": "Квалитет слике од 1-100. Више је боље за квалитет, али производи веће датотеке, ова опција утиче на преглед и сличице.", "image_resolution": "Резолуција", "image_resolution_description": "Веће резолуције могу да сачувају више детаља, али им је потребно више времена за кодирање, имају веће величине датотека и могу да смање одзив апликације.", "image_settings": "Подешавања слике", "image_settings_description": "Управљајте квалитетом и резолуцијом генерисаних слика", "image_thumbnail_description": "Мала сличица са огољеним метаподацима, која се користи приликом прегледа група фотографија као што је главна временска линија", - "image_thumbnail_format": "Формат сличице", "image_thumbnail_quality_description": "Квалитет сличица од 1-100. Више је боље, али производи веће датотеке и може смањити одзив апликације.", - "image_thumbnail_resolution": "Резолуција сличице", - "image_thumbnail_resolution_description": "Користи се приликом прегледа група фотографија (главна временска линија, приказ албума, итд.). Веће резолуције могу да сачувају више детаља, али им је потребно више времена за кодирање, имају веће величине датотека и могу да смање брзину апликације.", "image_thumbnail_title": "Подешавања сличица", "job_concurrency": "{job} паралелност", "job_created": "Посао креиран", @@ -89,9 +89,6 @@ "jobs_delayed": "{jobCount, plural, other {# одложених}}", "jobs_failed": "{jobCount, plural, other {# неуспешних}}", "library_created": "Направљена библиотека {library}", - "library_cron_expression": "Системски посао", - "library_cron_expression_description": "Подесите интервал скенирања користећи црон формат. За више информација погледајте нпр. Цронтаб Гуру", - "library_cron_expression_presets": "Унапред подешене поставке системског посла", "library_deleted": "Библиотека је избрисана", "library_import_path_description": "Одредите фасциклу за увоз. Ова фасцикла, укључујући подфасцикле, биће скенирана за слике и видео записе.", "library_scanning": "Периодично скенирање", @@ -134,7 +131,7 @@ "machine_learning_smart_search_description": "Потражите слике семантички користећи уграђени ЦЛИП", "machine_learning_smart_search_enabled": "Омогућите паметну претрагу", "machine_learning_smart_search_enabled_description": "Ако је oneмогућено, слике неће бити кодиране за паметну претрагу.", - "machine_learning_url_description": "УРЛ сервера за машинско учење", + "machine_learning_url_description": "URL сервера за машинско учење. Ако је наведено више од једне URL адресе, сваки сервер ће се покушавати један по један док један не одговори успешно, редом од првог до последњег.", "manage_concurrency": "Управљање паралелношћу", "manage_log_settings": "Управљајте подешавањима евиденције", "map_dark_style": "Тамни стил", @@ -215,7 +212,6 @@ "refreshing_all_libraries": "Освежавање свих библиотека", "registration": "Регистрација администратора", "registration_description": "Пошто сте први корисник на систему, бићете додељени као Админ и одговорни сте за административне задатке, а додатне кориснике ћете креирати ви.", - "removing_deleted_files": "Уклањање ванмрежних датотека", "repair_all": "Поправи све", "repair_matched_items": "Поклапа се са {count, plural, one {1 ставком} few {# ставке} other {# ставки}}", "repaired_items": "{count, plural, one {Поправљена 1 ставка} few {Поправљене # ставке} other {Поправљене # ставки}}", @@ -223,12 +219,12 @@ "reset_settings_to_default": "Ресетујте подешавања на подразумеване вредности", "reset_settings_to_recent_saved": "Ресетујте подешавања на недавно сачувана подешавања", "scanning_library": "Скенирање библиотеке", - "scanning_library_for_changed_files": "Скенирање библиотеке за промењене датотеке", - "scanning_library_for_new_files": "Скенирање библиотеке за нове датотеке", "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": "Порука добродошлице", @@ -254,6 +250,16 @@ "storage_template_user_label": "{label} је ознака за складиштење корисника", "system_settings": "Подешавања система", "tag_cleanup_job": "Чишћење ознака (tags)", + "template_email_available_tags": "Можете да користите следеће променљиве у свом шаблону: {tags}", + "template_email_if_empty": "Ако је шаблон празан, користиће се подразумевана адреса е-поште.", + "template_email_invite_album": "Шаблон албума позива", + "template_email_preview": "Преглед", + "template_email_settings": "Шаблони е-поште", + "template_email_settings_description": "Управљајте прилагођеним шаблонима обавештења путем е-поште", + "template_email_update_album": "Ажурирајте шаблон албума", + "template_email_welcome": "Шаблон е-поште добродошлице", + "template_settings": "Шаблони обавештења", + "template_settings_description": "Управљајте прилагођеним шаблонима за обавештења.", "theme_custom_css_settings": "Прилагођени CSS", "theme_custom_css_settings_description": "Каскадни листови стилова (CSS) омогућавају прилагођавање дизајна Immich-a.", "theme_settings": "Подешавање тема", @@ -261,7 +267,6 @@ "these_files_matched_by_checksum": "Овим датотекама се подударају њихови контролни-збирови", "thumbnail_generation_job": "Генеришите сличице", "thumbnail_generation_job_description": "Генеришите велике, мале и замућене сличице за свако средство, као и сличице за сваку особу", - "transcode_policy_description": "", "transcoding_acceleration_api": "АПИ за убрзање", "transcoding_acceleration_api_description": "АПИ који ће комуницирати са вашим уређајем да би убрзао транскодирање. Ово подешавање је 'најбољи напор': vraća se na softversko transkodiranje u slučaju neuspeha. VP9 može ili ne mora da radi u zavisnosti od vašeg hardvera.", "transcoding_acceleration_nvenc": "НВЕНЦ (захтева NVIDIA ГПУ)", @@ -313,8 +318,6 @@ "transcoding_threads_description": "Више вредности доводе до бржег кодирања, али остављају мање простора серверу за обраду других задатака док је активан. Ова вредност не би требало да буде већа од броја CPU језгара. Максимизира искоришћеност ако је подешено на 0.", "transcoding_tone_mapping": "Мапирање (tone-mapping)", "transcoding_tone_mapping_description": "Покушава да се сачува изглед ХДР видео записа када се конвертују у СДР. Сваки алгоритам прави различите компромисе за боју, детаље и осветљеност. Хабле чува детаље, Мобиус чува боју, а Раеинхард светлину.", - "transcoding_tone_mapping_npl": "Tone-mapping-NPL", - "transcoding_tone_mapping_npl_description": "Боје ће бити подешене тако да изгледају нормално за приказ ове осветљености. Контраинтуитивно, ниже вредности повећавају осветљеност видеа и обрнуто, јер компензују осветљеност екрана. 0 аутоматски поставља ову вредност.", "transcoding_transcode_policy": "Услови транскодирања", "transcoding_transcode_policy_description": "Услови о томе када видео треба транскодирати. ХДР видео снимци ће увек бити транскодирани (осим ако је транскодирање oneмогућено).", "transcoding_two_pass_encoding": "Двопролазно кодирање", @@ -395,7 +398,6 @@ "archive_or_unarchive_photo": "Архивирајте или поништите архивирање фотографије", "archive_size": "Величина архиве", "archive_size_description": "Подеси величину архиве за преузимање (у ГиБ)", - "archived": "Arhivirano", "archived_count": "{count, plural, other {Архивирано #}}", "are_these_the_same_person": "Да ли су ово иста особа?", "are_you_sure_to_do_this": "Јесте ли сигурни да желите ово да урадите?", @@ -416,7 +418,6 @@ "assets_added_to_album_count": "Додато је {count, plural, one {# датотека} other {# датотека}} у албум", "assets_added_to_name_count": "Додато {count, plural, one {# датотека} other {# датотекa}} у {hasName, select, true {{name}} other {нови албум}}", "assets_count": "{count, plural, one {# датотека} few {# датотеке} other {# датотека}}", - "assets_moved_to_trash": "{count, plural, one {Premeštena # datoteka} few {Premeštene # datoteke} other {Premeštene # datoteka}} u otpad", "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 {# датотека}}", @@ -446,10 +447,6 @@ "cannot_merge_people": "Не може спојити особе", "cannot_undo_this_action": "Не можете поништити ову радњу!", "cannot_update_the_description": "Не може ажурирати опис", - "cant_apply_changes": "Ne može primeniti promene", - "cant_get_faces": "Ne može preuzeti lica", - "cant_search_people": "Ne može pretražiti osobe", - "cant_search_places": "Ne može pretražiti mesta", "change_date": "Промени датум", "change_expiration_time": "Промени време истека", "change_location": "Промени место", @@ -481,6 +478,7 @@ "confirm": "Потврдите", "confirm_admin_password": "Потврди Административну Лозинку", "confirm_delete_shared_link": "Да ли сте сигурни да желите да избришете овај дељени link?", + "confirm_keep_this_delete_others": "Свe осталe датотекe у групи ће бити избрисанe осим овe датотекe. Да ли сте сигурни да желите да наставите?", "confirm_password": "Поново унеси шифру", "contain": "Обухвати", "context": "Контекст", @@ -530,6 +528,7 @@ "delete_key": "Избриши кључ", "delete_library": "Обриши библиотеку", "delete_link": "Обриши везу", + "delete_others": "Избришите друге", "delete_shared_link": "Обриши дељену везу", "delete_tag": "Обриши ознаку (tag)", "delete_tag_confirmation_prompt": "Да ли стварно желите да избришете ознаку (tag) {tagName}?", @@ -563,13 +562,6 @@ "duplicates": "Дупликати", "duplicates_description": "Разрешите сваку групу тако што ћете навести дупликате, ако их има", "duration": "Трајање", - "durations": { - "days": "{days, plural, one {dan} other {{days, number} dana}}", - "hours": "{hours, plural, one {sat} other {{hours, number} sata}}", - "minutes": "{minutes, plural, one {minut} other {{minutes, number} minuta}}", - "months": "{months, plural, one {mesec} other {{months, number} meseci}}", - "years": "{years, plural, one {godina} other {{years, number} godina}}" - }, "edit": "Уреди", "edit_album": "Уреди албум", "edit_avatar": "Уреди аватар", @@ -594,8 +586,6 @@ "editor_crop_tool_h2_aspect_ratios": "Пропорције (aspect ratios)", "editor_crop_tool_h2_rotation": "Ротација", "email": "Е-пошта", - "empty": "", - "empty_album": "Isprazni album", "empty_trash": "Испразните смеће", "empty_trash_confirmation": "Да ли сте сигурни да желите да испразните смеће? Ово ће трајно уклонити све датотеке у смећу из Immich-a.\nNe можете поништити ову радњу!", "enable": "Омогући (Енабле)", @@ -629,6 +619,7 @@ "failed_to_create_shared_link": "Прављење дељеног linkа није успело", "failed_to_edit_shared_link": "Уређивање дељеног linkа није успело", "failed_to_get_people": "Неуспело позивање особа", + "failed_to_keep_this_delete_others": "Није успело задржавање овог дела и брисање осталих датотека", "failed_to_load_asset": "Учитавање датотека није успело", "failed_to_load_assets": "Није успело учитавање датотека", "failed_to_load_people": "Учитавање особа није успело", @@ -656,8 +647,6 @@ "unable_to_change_location": "Није могуће променити локацију", "unable_to_change_password": "Није могуће променити лозинку", "unable_to_change_visibility": "Није могуће променити видљивост за {count, plural, one {# особу} other {# особе}}", - "unable_to_check_item": "", - "unable_to_check_items": "", "unable_to_complete_oauth_login": "Није могуће довршити OAuth пријаву", "unable_to_connect": "Није могуће повезати се", "unable_to_connect_to_server": "Немогуће је повезати се са сервером", @@ -698,12 +687,10 @@ "unable_to_remove_album_users": "Није могуће уклонити кориснике из албума", "unable_to_remove_api_key": "Није могуће уклонити АПИ кључ (key)", "unable_to_remove_assets_from_shared_link": "Није могуће уклонити елементе са дељеног linkа", - "unable_to_remove_comment": "", "unable_to_remove_deleted_assets": "Није могуће уклонити ванмрежне датотеке", "unable_to_remove_library": "Није могуће уклонити библиотеку", "unable_to_remove_partner": "Није могуће уклонити партнера", "unable_to_remove_reaction": "Није могуће уклонити реакцију", - "unable_to_remove_user": "", "unable_to_repair_items": "Није могуће поправити ставке", "unable_to_reset_password": "Није могуће ресетовати лозинку", "unable_to_resolve_duplicate": "Није могуће разрешити дупликат", @@ -733,10 +720,6 @@ "unable_to_update_user": "Није могуће ажурирати корисника", "unable_to_upload_file": "Није могуће отпремити датотеку" }, - "every_day_at_onepm": "", - "every_night_at_midnight": "", - "every_night_at_twoam": "", - "every_six_hours": "", "exif": "EXIF", "exit_slideshow": "Изађи из пројекције слајдова", "expand_all": "Прошири све", @@ -751,33 +734,28 @@ "external": "Спољашњи", "external_libraries": "Спољашње Библиотеке", "face_unassigned": "Нераспоређени", - "failed_to_get_people": "Neuspešno isčitavanje osoba", + "failed_to_load_assets": "Учитавање средстава није успело", "favorite": "Фаворит", "favorite_or_unfavorite_photo": "Омиљена или неомиљена фотографија", "favorites": "Фаворити", - "feature": "", "feature_photo_updated": "Главна фотографија је ажурирана", - "featurecollection": "", "features": "Функције", "features_setting_description": "Управљајте функцијама апликације", "file_name": "Назив документа", "file_name_or_extension": "Име датотеке или екстензија", "filename": "Име датотеке", - "files": "", "filetype": "Врста документа", "filter_people": "Филтрирање особа", "find_them_fast": "Брзо их пронађите по имену помоћу претраге", "fix_incorrect_match": "Исправите нетачно подударање", "folders": "Фасцикле (Folders)", "folders_feature_description": "Прегледавање приказа фасцикле за фотографије и видео записе у систему датотека", - "force_re-scan_library_files": "Принудно поново скенирајте све датотеке библиотеке", "forward": "Напред", "general": "Генерално", "get_help": "Нађи помоћ", "getting_started": "Почињем", "go_back": "Врати се", "go_to_search": "Иди на претрагу", - "go_to_share_page": "Иди на страницу за дељење", "group_albums_by": "Групни албуми по...", "group_no": "Без груписања", "group_owner": "Групирајте по власнику", @@ -803,10 +781,6 @@ "image_alt_text_date_place_2_people": "{isVideo, select, true {Video} other {Image}} снимљено у {city}, {country} са {person1} и {person2} {date}", "image_alt_text_date_place_3_people": "{isVideo, select, true {Video} other {Image}} снимљено у {city}, {country} са {person1}, {person2}, и {person3} {date}", "image_alt_text_date_place_4_or_more_people": "{isVideo, select, true {Video} other {Image}} снимљено у {city}, {country} са {person1}, {person2}, и {additionalCount, number} других {date}", - "image_alt_text_people": "{count, plural, =1 {са {person1}} =2 {са {person1} и {person2}} =3 {са {person1}, {person2}, и {person3}} other {са {person1}, {person2}, и {others, number} остали}}", - "image_alt_text_place": "у {city}, {country}", - "image_taken": "{isVideo, select, true {Видео запис снимљен} other {Фотографија усликана}}", - "img": "", "immich_logo": "Лого Immich-a", "immich_web_interface": "Web интерфејс Immich-a", "import_from_json": "Увези из ЈСОН-а", @@ -827,10 +801,11 @@ "invite_people": "Позовите људе", "invite_to_album": "Позови на албум", "items_count": "{count, plural, one {# датотека} other {# датотека}}", - "job_settings_description": "", "jobs": "Послови", "keep": "Задржи", "keep_all": "Задржи све", + "keep_this_delete_others": "Задржи ово, избриши друге", + "kept_this_deleted_others": "Задржана је ова датотека и избрисано {count, plural, one {# датотека} other {# датотека}}", "keyboard_shortcuts": "Пречице на тастатури", "language": "Језик", "language_setting_description": "Изаберите жељени језик", @@ -842,31 +817,6 @@ "level": "Ниво", "library": "Библиотека", "library_options": "Опције библиотеке", - "license_account_info": "Ваш налог је лиценциран", - "license_activated_subtitle": "Хвала вам што подржавате Имич (Immich) и софтвер отвореног кода", - "license_activated_title": "Ваша лиценца је успешно активирана", - "license_button_activate": "Активираj", - "license_button_buy": "Купи", - "license_button_buy_license": "Купи лиценцу", - "license_button_select": "Изаберите", - "license_failed_activation": "Активација лиценце није успела. Проверите своју е-пошту да бисте пронашли исправан кључ лиценце!", - "license_individual_description_1": "1 лиценца по кориснику на било ком серверу", - "license_individual_title": "Индивидуална лиценца", - "license_info_licensed": "Лиценцирано", - "license_info_unlicensed": "Без лиценце", - "license_input_suggestion": "Имате лиценцу? Унесите кључ испод", - "license_license_subtitle": "Купите лиценцу за подршку Имич-a", - "license_license_title": "ЛИЦЕНЦA", - "license_lifetime_description": "Доживотна лиценца", - "license_per_server": "По серверу", - "license_per_user": "По кориснику", - "license_server_description_1": "1 лиценца по серверу", - "license_server_description_2": "Лиценца за све кориснике на серверу", - "license_server_title": "Сервер Лиценцa", - "license_trial_info_1": "Користите нелиценцирану верзију Имич-а", - "license_trial_info_2": "Користили сте Имич отприлике", - "license_trial_info_3": "{accountAge, plural, one {# дан} other {# данa}}", - "license_trial_info_4": "Молимо вас да размислите о куповини лиценце за подршку континуираном развоју услуге", "light": "Светло", "like_deleted": "Лајкуј избрисано", "link_motion_video": "Направи везу за видео запис", @@ -971,7 +921,6 @@ "onboarding_welcome_user": "Добродошли, {user}", "online": "Доступан (Онлине)", "only_favorites": "Само фаворити", - "only_refreshes_modified_files": "Освежава само измењене датотеке", "open_in_map_view": "Отвори у приказу мапе", "open_in_openstreetmap": "Отворите у ОпенСтреетМап-у", "open_the_search_filters": "Отворите филтере за претрагу", @@ -1009,14 +958,12 @@ "people_edits_count": "Измењено {count, plural, one {# особа} other {# особе}}", "people_feature_description": "Прегледавање фотографија и видео снимака груписаних по особама", "people_sidebar_description": "Прикажите везу до особа на бочној траци", - "perform_library_tasks": "", "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": "Trajno izbrisano {count, plural, one {# datoteka} other {# datoteke}}", "permanently_deleted_assets_count": "Трајно избрисано {count, plural, one {# датотека} other {# датотеке}}", "person": "Особа", "person_hidden": "{name}{hidden, select, true { (скривено)} other {}}", @@ -1032,7 +979,6 @@ "play_memories": "Покрени сећања", "play_motion_photo": "Покрени покретну фотографију", "play_or_pause_video": "Покрени или паузирај видео запис", - "point": "", "port": "порт", "preset": "Унапред подешено", "preview": "Преглед", @@ -1077,12 +1023,10 @@ "purchase_server_description_2": "Значка подршке", "purchase_server_title": "Сервер", "purchase_settings_server_activated": "Кључем производа сервера управља администратор", - "range": "", "rating": "Оцена звездица", "rating_clear": "Обриши оцену", "rating_count": "{count, plural, one {# звезда} other {# звезде}}", "rating_description": "Прикажите EXIF оцену у инфо панелу", - "raw": "", "reaction_options": "Опције реакције", "read_changelog": "Прочитајте дневник промена", "reassign": "Поново додај", @@ -1090,6 +1034,7 @@ "reassigned_assets_to_new_person": "Поново додељено {count, plural, one {# датотека} other {# датотеке}} новој особи", "reassing_hint": "Доделите изабрана средства постојећој особи", "recent": "Скорашњи", + "recent-albums": "Недавни албуми", "recent_searches": "Скорашње претраге", "refresh": "Освежи", "refresh_encoded_videos": "Освежите кодиране (енцодед) видео записе", @@ -1111,6 +1056,7 @@ "remove_from_album": "Обриши из албума", "remove_from_favorites": "Уклони из фаворита", "remove_from_shared_link": "Уклоните са дељене везе", + "remove_url": "Уклони URL", "remove_user": "Уклони корисника", "removed_api_key": "Уклоњен АПИ кључ (key): {name}", "removed_from_archive": "Уклоњено из архиве", @@ -1127,7 +1073,6 @@ "reset": "Ресетовати", "reset_password": "Ресетовати лозинку", "reset_people_visibility": "Ресетујте видљивост особа", - "reset_settings_to_default": "", "reset_to_default": "Ресетујте на подразумеване вредности", "resolve_duplicates": "Реши дупликате", "resolved_all_duplicates": "Сви дупликати су разрешени", @@ -1147,9 +1092,7 @@ "saved_settings": "Сачувана подешавања", "say_something": "Реци нешто", "scan_all_libraries": "Скенирај све библиотеке", - "scan_all_library_files": "Поново скенирајте све датотеке библиотеке", "scan_library": "Скенирај", - "scan_new_library_files": "Скенирајте нове датотеке библиотеке", "scan_settings": "Подешавања скенирања", "scanning_for_album": "Скенирање албума...", "search": "Претрага", @@ -1192,7 +1135,6 @@ "selected_count": "{count, plural, other {# изабрано}}", "send_message": "Пошаљи поруку", "send_welcome_email": "Пошаљите е-пошту добродошлице", - "server": "Сервер", "server_offline": "Сервер ван мреже (offline)", "server_online": "Сервер нa мрежи (online)", "server_stats": "Статистика сервера", @@ -1297,17 +1239,17 @@ "they_will_be_merged_together": "Они ће бити спојени заједно", "third_party_resources": "Ресурси трећих страна", "time_based_memories": "Сећања заснована на времену", + "timeline": "Временска линија", "timezone": "Временска зона", "to_archive": "Архивирај", "to_change_password": "Промени лозинку", "to_favorite": "Постави као фаворит", "to_login": "Пријава", "to_parent": "Врати се назад", - "to_root": "На почетак", "to_trash": "Смеће", "toggle_settings": "Намести подешавања", "toggle_theme": "Намести тамну тему", - "toggle_visibility": "Namesti vidljivost", + "total": "Укупно", "total_usage": "Укупна употреба", "trash": "Отпад", "trash_all": "Баци све у отпад", @@ -1317,12 +1259,10 @@ "trashed_items_will_be_permanently_deleted_after": "Датотеке у отпаду ће бити трајно избрисане након {days, plural, one {# дан} few {# дана} other {# дана}}.", "type": "Врста", "unarchive": "Врати из архиве", - "unarchived": "Vraćeno iz arhive", "unarchived_count": "{count, plural, other {Nearhivirano#}}", "unfavorite": "Избаци из омиљених (унфаворите)", "unhide_person": "Откриј особу", "unknown": "Непознат", - "unknown_album": "Nepoznat Album", "unknown_year": "Непозната Година", "unlimited": "Неограничено", "unlink_motion_video": "Прекините везу са видео снимком", @@ -1354,13 +1294,13 @@ "use_custom_date_range": "Уместо тога користите прилагођени период", "user": "Корисник", "user_id": "ИД корисника", - "user_license_settings": "Лиценца", - "user_license_settings_description": "Управљајте својом лиценцом", "user_liked": "{user} је лајковао {type, select, photo {ову фотографију} video {овај видео запис} asset {ову датотеку} other {ово}}", "user_purchase_settings": "Куповина", "user_purchase_settings_description": "Управљајте куповином", "user_role_set": "Постави {user} као {role}", "user_usage_detail": "Детаљи коришћења корисника", + "user_usage_stats": "Статистика коришћења налога", + "user_usage_stats_description": "Погледајте статистику коришћења налога", "username": "Корисничко име", "users": "Корисници", "utilities": "Алати", @@ -1368,7 +1308,7 @@ "variables": "Променљиве (вариаблес)", "version": "Верзија", "version_announcement_closing": "Твој пријатељ, Алекс", - "version_announcement_message": "Здраво пријатељу, постоји нова верзија апликације, молимо вас да одвојите време да посетите напомене о издању и уверите се у своје docker-compose.yml, и .env подешавање је ажурирано како би се спречиле било какве погрешне конфигурације, посебно ако користите WatchTower или било који механизам који аутоматски управља ажурирањем ваше апликације.", + "version_announcement_message": "Здраво пријатељу, постоји нова верзија апликације, молимо вас да одвојите време да посетите напомене о издању и уверите се да је сервер ажуриран како би се спречиле било какве погрешне конфигурације, посебно ако користите WatchTower или било који механизам који аутоматски управља ажурирањем ваше апликације.", "version_history": "Историја верзија", "version_history_item": "Инсталирано {version} on {date}", "video": "Видео запис", @@ -1382,10 +1322,10 @@ "view_all_users": "Прикажи све кориснике", "view_in_timeline": "Прикажи у временској линији", "view_links": "Прикажи везе", + "view_name": "Погледати", "view_next_asset": "Погледајте следећу датотеку", "view_previous_asset": "Погледај претходну датотеку", "view_stack": "Прикажи гомилу", - "viewer": "Preglednik (viewer)", "visibility_changed": "Видљивост је промењена за {count, plural, one {# особу} other {# особе}}", "waiting": "Чекам", "warning": "Упозорење", diff --git a/i18n/sr_Latn.json b/i18n/sr_Latn.json index f871cb12b0f6e..09baf5ff9dcd5 100644 --- a/i18n/sr_Latn.json +++ b/i18n/sr_Latn.json @@ -1,5 +1,5 @@ { - "about": "O aplikaciji", + "about": "O Aplikaciji", "account": "Profil", "account_settings": "Podešavanja za Profil", "acknowledge": "Potvrdi", @@ -23,6 +23,7 @@ "add_to": "Dodaj u...", "add_to_album": "Dodaj u album", "add_to_shared_album": "Dodaj u deljen album", + "add_url": "Dodajte URL", "added_to_archive": "Dodato u arhivu", "added_to_favorites": "Dodato u favorite", "added_to_favorites_count": "Dodato {count, number} u favorite", @@ -34,6 +35,11 @@ "authentication_settings_disable_all": "Da li ste sigurni da želite da onemogućite sve metode prijavljivanja? Prijava će biti potpuno onemogućena.", "authentication_settings_reenable": "Da biste ponovo omogućili, koristite komandu servera.", "background_task_job": "Pozadinski zadaci", + "backup_database": "Rezervna kopija baze podataka", + "backup_database_enable_description": "Omogućite rezervne kopije baze podataka", + "backup_keep_last_amount": "Količina prethodnih rezervnih kopija za čuvanje", + "backup_settings": "Podešavanja rezervne kopije", + "backup_settings_description": "Upravljajte postavkama rezervne kopije baze podataka", "check_all": "Proveri sve", "cleared_jobs": "Očišćeni poslovi za: {job}", "config_set_by_file": "Konfiguraciju trenutno postavlja konfiguracioni fajl", @@ -43,9 +49,10 @@ "confirm_reprocess_all_faces": "Da li ste sigurni da želite da ponovo obradite sva lica? Ovo će takođe obrisati imenovane osobe.", "confirm_user_password_reset": "Da li ste sigurni da želite da resetujete lozinku korisnika {user}?", "create_job": "Kreirajte posao", - "crontab_guru": "Guru servisnih zadataka", + "cron_expression": "Cron izraz (expression)", + "cron_expression_description": "Podesite interval skeniranja koristeći cron format. Za više informacija pogledajte npr. Crontab Guru", + "cron_expression_presets": "Predefinisana podešavanja Cron izraza (expression)", "disable_login": "Onemogući prijavu", - "disabled": "", "duplicate_detection_job_description": "Pokrenite mašinsko učenje na sredstvima da biste otkrili slične slike. Oslanja se na pametnu pretragu", "exclusion_pattern_description": "Obrasci izuzimanja vam omogućavaju da ignorišete datoteke i fascikle kada skenirate biblioteku. Ovo je korisno ako imate fascikle koje sadrže datoteke koje ne želite da uvezete, kao što su RAW datoteke.", "external_library_created_at": "Eksterna biblioteka (napravljena {date})", @@ -63,22 +70,15 @@ "image_prefer_wide_gamut": "Preferirajte širok spektar", "image_prefer_wide_gamut_setting_description": "Koristite Display P3 za sličice. Ovo bolje čuva živopisnost slika sa širokim prostorima boja, ali slike mogu izgledati drugačije na starim uređajima sa starom verzijom pretraživača. sRGB slike se čuvaju kao sRGB da bi se izbegle promene boja.", "image_preview_description": "Slika srednje veličine sa uklonjenim metapodacima, koja se koristi prilikom pregleda jednog elementa i za mašinsko učenje", - "image_preview_format": "Pregled formata", "image_preview_quality_description": "Kvalitet pregleda od 1-100. Više je bolje, ali proizvodi veće datoteke i može smanjiti odziv aplikacije. Postavljanje niske vrednosti može uticati na kvalitet mašinskog učenja.", - "image_preview_resolution": "Pregled rezolucije", - "image_preview_resolution_description": "Koristi se za gledanje jedne fotografije i za mašinsko učenje. Veće rezolucije mogu da sačuvaju više detalja, ali im je potrebno više vremena za kodiranje, imaju veće veličine datoteka i mogu da smanje brzinu aplikacije.", "image_preview_title": "Podešavanja pregleda", "image_quality": "Kvalitet", - "image_quality_description": "Kvalitet slike od 1-100. Više je bolje za kvalitet, ali proizvodi veće datoteke, ova opcija utiče na pregled i sličice.", "image_resolution": "Rezolucija", "image_resolution_description": "Veće rezolucije mogu da sačuvaju više detalja, ali im je potrebno više vremena za kodiranje, imaju veće veličine datoteka i mogu da smanje odziv aplikacije.", "image_settings": "Podešavanja slike", "image_settings_description": "Upravljajte kvalitetom i rezolucijom generisanih slika", "image_thumbnail_description": "Mala sličica sa ogoljenim metapodacima, koja se koristi prilikom pregleda grupa fotografija kao što je glavna vremenska linija", - "image_thumbnail_format": "Format sličice", "image_thumbnail_quality_description": "Kvalitet sličica od 1-100. Više je bolje, ali proizvodi veće datoteke i može smanjiti odziv aplikacije.", - "image_thumbnail_resolution": "Rezolucija sličice", - "image_thumbnail_resolution_description": "Koristi se prilikom pregleda grupa fotografija (glavna vremenska linija, prikaz albuma, itd.). Veće rezolucije mogu da sačuvaju više detalja, ali im je potrebno više vremena za kodiranje, imaju veće veličine datoteka i mogu da smanje brzinu aplikacije.", "image_thumbnail_title": "Podešavanja sličica", "job_concurrency": "{job} paralelnost", "job_created": "Posao kreiran", @@ -89,9 +89,6 @@ "jobs_delayed": "{jobCount, plural, one {# odloženi} few {# odložena} other {# odloženih}}", "jobs_failed": "{jobCount, plural, one {# neuspešni} few {# neuspešna} other {# neuspešnih}}", "library_created": "Napravljena biblioteka: {library}", - "library_cron_expression": "Sistemski posao", - "library_cron_expression_description": "Podesite interval skeniranja koristeći cron format. Za više informacija pogledajte npr. Crontab Guru", - "library_cron_expression_presets": "Unapred podešene postavke sistemskog posla", "library_deleted": "Biblioteka je izbrisana", "library_import_path_description": "Odredite fasciklu za uvoz. Ova fascikla, uključujući podfascikle, biće skenirana za slike i video zapise.", "library_scanning": "Periodično skeniranje", @@ -134,7 +131,7 @@ "machine_learning_smart_search_description": "Potražite slike semantički koristeći ugrađeni CLIP", "machine_learning_smart_search_enabled": "Omogućite pametnu pretragu", "machine_learning_smart_search_enabled_description": "Ako je onemogućeno, slike neće biti kodirane za pametnu pretragu.", - "machine_learning_url_description": "URL servera za mašinsko učenje", + "machine_learning_url_description": "URL servera za mašinsko učenje. Ako je obezbeđeno više URL-ova, svaki server će biti pokušan redom, jedan po jedan, dok jedan ne odgovori uspešno, po redosledu od prvog do poslednjeg.", "manage_concurrency": "Upravljanje paralelnošću", "manage_log_settings": "Upravljajte podešavanjima evidencije", "map_dark_style": "Tamni stil", @@ -215,7 +212,6 @@ "refreshing_all_libraries": "Osvežavanje svih biblioteka", "registration": "Registracija administratora", "registration_description": "Pošto ste prvi korisnik na sistemu, bićete dodeljeni kao Admin i odgovorni ste za administrativne zadatke, a dodatne korisnike ćete kreirati vi.", - "removing_deleted_files": "Uklanjanje vanmrežnih datoteka", "repair_all": "Popravi sve", "repair_matched_items": "Poklapa se sa {count, plural, one {1 stavkom} few {# stavke} other {# stavki}}", "repaired_items": "{count, plural, one {Popravljena 1 stavka} few {Popravljene # stavke} other {Popravljene # stavki}}", @@ -223,12 +219,12 @@ "reset_settings_to_default": "Resetujte podešavanja na podrazumevane vrednosti", "reset_settings_to_recent_saved": "Resetujte podešavanja na nedavno sačuvana podešavanja", "scanning_library": "Skeniranje biblioteke", - "scanning_library_for_changed_files": "Skeniranje biblioteke za promenjene datoteke", - "scanning_library_for_new_files": "Skeniranje biblioteke za nove datoteke", "search_jobs": "Traži poslove...", "send_welcome_email": "Pošaljite e-poštu dobrodošlice", "server_external_domain_settings": "Eksterni domain", "server_external_domain_settings_description": "Domain za javne deljene veze, uključujući http(s)://", + "server_public_users": "Javni korisnici", + "server_public_users_description": "Svi korisnici (ime i adresa e-pošte) su navedeni prilikom dodavanja korisnika u deljene albume. Kada je onemogućena, lista korisnika će biti dostupna samo administratorima.", "server_settings": "Podešavanja servera", "server_settings_description": "Upravljajte podešavanjima servera", "server_welcome_message": "Poruka dobrodošlice", @@ -254,6 +250,16 @@ "storage_template_user_label": "{label} je oznaka za skladištenje korisnika", "system_settings": "Podešavanja sistema", "tag_cleanup_job": "Čišćenje oznaka (tags)", + "template_email_available_tags": "Možete da koristite sledeće promenljive u svom šablonu: {tags}", + "template_email_if_empty": "Ako je šablon prazan, koristiće se podrazumevana adresa e-pošte.", + "template_email_invite_album": "Šablon za poziv u album", + "template_email_preview": "Pregled", + "template_email_settings": "Šabloni e-pošte", + "template_email_settings_description": "Upravljajte prilagođenim šablonima obaveštenja putem e-pošte", + "template_email_update_album": "Ažurirajte šablon albuma", + "template_email_welcome": "Šablon e-pošte dobrodošlice", + "template_settings": "Šabloni obaveštenja", + "template_settings_description": "Upravljajte prilagođenim šablonima za obaveštenja.", "theme_custom_css_settings": "Prilagođeni CSS", "theme_custom_css_settings_description": "Kaskadni listovi stilova (CSS) omogućavaju prilagođavanje dizajna Immich-a.", "theme_settings": "Podešavanje tema", @@ -261,7 +267,6 @@ "these_files_matched_by_checksum": "Ovim datotekama se podudaraju njihovi kontrolni-zbirovi", "thumbnail_generation_job": "Generišite sličice", "thumbnail_generation_job_description": "Generišite velike, male i zamućene sličice za svako sredstvo, kao i sličice za svaku osobu", - "transcode_policy_description": "", "transcoding_acceleration_api": "API za ubrzanje", "transcoding_acceleration_api_description": "API koji će komunicirati sa vašim uređajem da bi ubrzao transkodiranje. Ovo podešavanje je 'najbolji napor': vraća se na softversko transkodiranje u slučaju neuspeha. VP9 može ili ne mora da radi u zavisnosti od vašeg hardvera.", "transcoding_acceleration_nvenc": "NVENC (zahteva NVIDIA GPU)", @@ -313,8 +318,6 @@ "transcoding_threads_description": "Više vrednosti dovode do bržeg kodiranja, ali ostavljaju manje prostora serveru za obradu drugih zadataka dok je aktivan. Ova vrednost ne bi trebalo da bude veća od broja CPU jezgara. Maksimizira iskorišćenost ako je podešeno na 0.", "transcoding_tone_mapping": "Mapiranje (tone-mapping)", "transcoding_tone_mapping_description": "Pokušava da se sačuva izgled HDR video zapisa kada se konvertuju u SDR. Svaki algoritam pravi različite kompromise za boju, detalje i osvetljenost. Hable čuva detalje, Mobius čuva boju, a Raeinhard svetlinu.", - "transcoding_tone_mapping_npl": "Tone-mapping-NPL", - "transcoding_tone_mapping_npl_description": "Boje će biti podešene tako da izgledaju normalno za prikaz ove osvetljenosti. Kontraintuitivno, niže vrednosti povećavaju osvetljenost videa i obrnuto, jer kompenzuju osvetljenost ekrana. 0 automatski postavlja ovu vrednost.", "transcoding_transcode_policy": "Uslovi transkodiranja", "transcoding_transcode_policy_description": "Uslovi o tome kada video treba transkodirati. HDR video snimci će uvek biti transkodirani (osim ako je transkodiranje onemogućeno).", "transcoding_two_pass_encoding": "Dvoprolazno kodiranje", @@ -395,7 +398,6 @@ "archive_or_unarchive_photo": "Arhivirajte ili poništite arhiviranje fotografije", "archive_size": "Veličina arhive", "archive_size_description": "Podesi veličinu arhive za preuzimanje (u GiB)", - "archived": "Arhivirano", "archived_count": "{count, plural, other {Arhivirano #}}", "are_these_the_same_person": "Da li su ovo ista osoba?", "are_you_sure_to_do_this": "Jeste li sigurni da želite ovo da uradite?", @@ -416,7 +418,6 @@ "assets_added_to_album_count": "Dodato je {count, plural, one {# datoteka} other {# datoteka}} u album", "assets_added_to_name_count": "Dodato {count, plural, one {# datoteka} other {# datoteke}} u {hasName, select, true {{name}} other {novi album}}", "assets_count": "{count, plural, one {# datoteka} few {# datoteke} other {# datoteka}}", - "assets_moved_to_trash": "{count, plural, one {Premeštena # datoteka} few {Premeštene # datoteke} other {Premeštene # datoteka}} u otpad", "assets_moved_to_trash_count": "Premešteno {count, plural, one {# datoteka} few {# datoteke} other {# datoteka}} u otpad", "assets_permanently_deleted_count": "Trajno izbrisano {count, plural, one {# datoteka} few {# datoteke} other {# datoteka}}", "assets_removed_count": "Uklonjeno {count, plural, one {# datoteka} few {# datoteke} other {# datoteka}}", @@ -446,10 +447,6 @@ "cannot_merge_people": "Ne može spojiti osobe", "cannot_undo_this_action": "Ne možete poništiti ovu radnju!", "cannot_update_the_description": "Ne može ažurirati opis", - "cant_apply_changes": "Ne može primeniti promene", - "cant_get_faces": "Ne može preuzeti lica", - "cant_search_people": "Ne može pretražiti osobe", - "cant_search_places": "Ne može pretražiti mesta", "change_date": "Promeni datum", "change_expiration_time": "Promeni vreme isteka", "change_location": "Promeni mesto", @@ -481,6 +478,7 @@ "confirm": "Potvrdi", "confirm_admin_password": "Potvrdi Administrativnu Lozinku", "confirm_delete_shared_link": "Da li ste sigurni da želite da izbrišete ovaj deljeni link?", + "confirm_keep_this_delete_others": "Sve ostale datoteke u grupi će biti izbrisane osim ove datoteke. Da li ste sigurni da želite da nastavite?", "confirm_password": "Ponovo unesi šifru", "contain": "Obuhvati", "context": "Kontekst", @@ -530,6 +528,7 @@ "delete_key": "Izbriši ključ", "delete_library": "Obriši biblioteku", "delete_link": "Obriši vezu", + "delete_others": "Izbrišite druge", "delete_shared_link": "Obriši deljenu vezu", "delete_tag": "Obriši oznaku (tag)", "delete_tag_confirmation_prompt": "Da li stvarno želite da izbrišete oznaku {tagName}?", @@ -563,13 +562,6 @@ "duplicates": "Duplikati", "duplicates_description": "Razrešite svaku grupu tako što ćete navesti duplikate, ako ih ima", "duration": "Trajanje", - "durations": { - "days": "{days, plural, one {dan} other {{days, number} dana}}", - "hours": "{hours, plural, one {sat} other {{hours, number} sata}}", - "minutes": "{minutes, plural, one {minut} other {{minutes, number} minuta}}", - "months": "{months, plural, one {mesec} other {{months, number} meseci}}", - "years": "{years, plural, one {godina} other {{years, number} godina}}" - }, "edit": "Uredi", "edit_album": "Uredi album", "edit_avatar": "Uredi avatar", @@ -594,8 +586,6 @@ "editor_crop_tool_h2_aspect_ratios": "Proporcije (aspect ratios)", "editor_crop_tool_h2_rotation": "Rotacija", "email": "E-pošta", - "empty": "", - "empty_album": "Isprazni album", "empty_trash": "Ispraznite smeće", "empty_trash_confirmation": "Da li ste sigurni da želite da ispraznite smeće? Ovo će trajno ukloniti sve datoteke u smeću iz Immich-a.\nNe možete poništiti ovu radnju!", "enable": "Omogući (Enable)", @@ -629,6 +619,7 @@ "failed_to_create_shared_link": "Pravljenje deljenog linka nije uspelo", "failed_to_edit_shared_link": "Uređivanje deljenog linka nije uspelo", "failed_to_get_people": "Neuspelo pozivanje osoba", + "failed_to_keep_this_delete_others": "Nije uspelo zadržavanje ovog dela i brisanje ostalih datoteka", "failed_to_load_asset": "Učitavanje datoteka nije uspelo", "failed_to_load_assets": "Nije uspelo učitavanje datoteka", "failed_to_load_people": "Učitavanje osoba nije uspelo", @@ -656,8 +647,6 @@ "unable_to_change_location": "Nije moguće promeniti lokaciju", "unable_to_change_password": "Nije moguće promeniti lozinku", "unable_to_change_visibility": "Nije moguće promeniti vidljivost za {count, plural, one {# osobu} other {# osobe}}", - "unable_to_check_item": "", - "unable_to_check_items": "", "unable_to_complete_oauth_login": "Nije moguće dovršiti OAuth prijavu", "unable_to_connect": "Nije moguće povezati se", "unable_to_connect_to_server": "Nemoguće je povezati se sa serverom", @@ -698,12 +687,10 @@ "unable_to_remove_album_users": "Nije moguće ukloniti korisnike iz albuma", "unable_to_remove_api_key": "Nije moguće ukloniti API ključ (key)", "unable_to_remove_assets_from_shared_link": "Nije moguće ukloniti elemente sa deljenog linka", - "unable_to_remove_comment": "", "unable_to_remove_deleted_assets": "Nije moguće ukloniti vanmrežne datoteke", "unable_to_remove_library": "Nije moguće ukloniti biblioteku", "unable_to_remove_partner": "Nije moguće ukloniti partnera", "unable_to_remove_reaction": "Nije moguće ukloniti reakciju", - "unable_to_remove_user": "", "unable_to_repair_items": "Nije moguće popraviti stavke", "unable_to_reset_password": "Nije moguće resetovati lozinku", "unable_to_resolve_duplicate": "Nije moguće razrešiti duplikat", @@ -733,10 +720,6 @@ "unable_to_update_user": "Nije moguće ažurirati korisnika", "unable_to_upload_file": "Nije moguće otpremiti datoteku" }, - "every_day_at_onepm": "", - "every_night_at_midnight": "", - "every_night_at_twoam": "", - "every_six_hours": "", "exif": "EXIF", "exit_slideshow": "Izađi iz projekcije slajdova", "expand_all": "Proširi sve", @@ -751,33 +734,28 @@ "external": "Spoljašnji", "external_libraries": "Spoljašnje Biblioteke", "face_unassigned": "Neraspoređeni", - "failed_to_get_people": "Neuspešno isčitavanje osoba", + "failed_to_load_assets": "Datoteke nisu uspešno učitane", "favorite": "Favorit", "favorite_or_unfavorite_photo": "Omiljena ili neomiljena fotografija", "favorites": "Favoriti", - "feature": "", "feature_photo_updated": "Glavna fotografija je ažurirana", - "featurecollection": "", "features": "Funkcije (features)", "features_setting_description": "Upravljajte funkcijama aplikacije", "file_name": "Naziv dokumenta", "file_name_or_extension": "Ime datoteke ili ekstenzija", "filename": "Ime datoteke", - "files": "", "filetype": "Vrsta dokumenta", "filter_people": "Filtriranje osoba", "find_them_fast": "Brzo ih pronađite po imenu pomoću pretrage", "fix_incorrect_match": "Ispravite netačno podudaranje", "folders": "Fascikle (Folders)", "folders_feature_description": "Pregledavanje prikaza fascikle za fotografije i video zapisa u sistemu datoteka", - "force_re-scan_library_files": "Prinudno ponovo skenirajte sve datoteke biblioteke", "forward": "Napred", "general": "Generalno", "get_help": "Nađi pomoć", "getting_started": "Počinjem", "go_back": "Vrati se", "go_to_search": "Idi na pretragu", - "go_to_share_page": "Idi na stranicu za deljenje", "group_albums_by": "Grupni albumi po...", "group_no": "Bez grupisanja", "group_owner": "Grupirajte po vlasniku", @@ -803,10 +781,6 @@ "image_alt_text_date_place_2_people": "{isVideo, select, true {Video} other {Image}} snimljeno u {city}, {country} sa {person1} i {person2} {date}", "image_alt_text_date_place_3_people": "{isVideo, select, true {Video} other {Image}} snimljenou {city}, {country} sa {person1}, {person2} i {person3} {date}", "image_alt_text_date_place_4_or_more_people": "{isVideo, select, true {Video} other {Image}} snimljeno u {city}, {country} sa {person1}, {person2} i još {additionalCount, number} drugih {date}", - "image_alt_text_people": "{count, plural, =1 {sa {person1}} =2 {sa {person1} i {person2}} =3 {sa {person1}, {person2}, i {person3}} other {sa {person1}, {person2}, i {others, number} others}}", - "image_alt_text_place": "u {city}, {country}", - "image_taken": "{isVideo, select, true {Video zapis snimljen} other {Fotografija uslikana}}", - "img": "", "immich_logo": "Logo Immich-a", "immich_web_interface": "Web interfejs Immich-a", "import_from_json": "Uvezi iz JSON-a", @@ -827,10 +801,11 @@ "invite_people": "Pozovite ljude", "invite_to_album": "Pozovi na album", "items_count": "{count, plural, one {# datoteka} other {# datoteka}}", - "job_settings_description": "", "jobs": "Poslovi", "keep": "Zadrži", "keep_all": "Zadrži sve", + "keep_this_delete_others": "Zadrži ovo, izbriši druge", + "kept_this_deleted_others": "Zadržana je ova datoteka i izbrisano {count, plural, one {# datoteka} other {# datoteka}}", "keyboard_shortcuts": "Prečice na tastaturi", "language": "Jezik", "language_setting_description": "Izaberite željeni jezik", @@ -842,31 +817,6 @@ "level": "Nivo", "library": "Biblioteka", "library_options": "Opcije biblioteke", - "license_account_info": "Vaš nalog je licenciran", - "license_activated_subtitle": "Hvala vam što podržavate Immich i softver otvorenog koda", - "license_activated_title": "Vaša licenca je uspešno aktivirana", - "license_button_activate": "Aktiviraj", - "license_button_buy": "Kupi", - "license_button_buy_license": "Kupi Licencu", - "license_button_select": "Odaberi", - "license_failed_activation": "Aktivacija licence nije uspela. Proverite svoju e-poštu da biste pronašli ispravan ključ licence!", - "license_individual_description_1": "1 licenca po korisniku na bilo kom serveru", - "license_individual_title": "Individualna licenca", - "license_info_licensed": "Licencirano", - "license_info_unlicensed": "Bez licence", - "license_input_suggestion": "Imate licencu? Unesite ključ ispod", - "license_license_subtitle": "Kupite licencu za podršku Immich-a", - "license_license_title": "LICENCA", - "license_lifetime_description": "Doživotna licenca", - "license_per_server": "Po serveru", - "license_per_user": "Po korisniku", - "license_server_description_1": "1 licenca po serveru", - "license_server_description_2": "Licenca za sve korisnike na serveru", - "license_server_title": "Serverska licenca", - "license_trial_info_1": "Koristite nelicenciranu verziju Immich-a", - "license_trial_info_2": "Koristili ste Immich otprilike", - "license_trial_info_3": "{accountAge, plural, one {# dan} other {# dana}}", - "license_trial_info_4": "Molimo vas da razmislite o kupovini licence za podršku kontinuiranom razvoju usluge", "light": "Svetlo", "like_deleted": "Lajkuj izbrisano", "link_motion_video": "Napravi vezu za video zapis", @@ -971,7 +921,6 @@ "onboarding_welcome_user": "Dobrodošli, {user}", "online": "Dostupan (Online)", "only_favorites": "Samo favoriti", - "only_refreshes_modified_files": "Osvežava samo izmenjene datoteke", "open_in_map_view": "Otvorite u prikaz karte", "open_in_openstreetmap": "Otvorite u OpenStreetMap-u", "open_the_search_filters": "Otvorite filtere za pretragu", @@ -1009,14 +958,12 @@ "people_edits_count": "Izmenjeno {count, plural, one {# osoba} other {# osobe}}", "people_feature_description": "Pregledavanje fotografija i video snimaka grupisanih po osobama", "people_sidebar_description": "Prikažite vezu do osoba na bočnoj traci", - "perform_library_tasks": "", "permanent_deletion_warning": "Upozorenje za trajno brisanje", "permanent_deletion_warning_setting_description": "Prikaži upozorenje kada trajno brišete datoteke", "permanently_delete": "Trajno izbrisati", "permanently_delete_assets_count": "Trajno izbriši {count, plural, one {datoteku} other {datoteke}}", "permanently_delete_assets_prompt": "Da li ste sigurni da želite da trajno izbrišete {count, plural, one {ovu datoteku?} other {ove # datoteke?}}Ovo će ih takođe ukloniti {count, plural, one {iz njihovog} other {iz njihovih}} albuma.", "permanently_deleted_asset": "Trajno izbrisana datoteka", - "permanently_deleted_assets": "Trajno izbrisano {count, plural, one {# datoteka} other {# datoteke}}", "permanently_deleted_assets_count": "Trajno izbrisano {count, plural, one {# datoteka} other {# datoteke}}", "person": "Osoba", "person_hidden": "{name}{hidden, select, true { (skriveno)} other {}}", @@ -1032,7 +979,6 @@ "play_memories": "Pokreni sećanja", "play_motion_photo": "Pokreni pokretnu fotografiju", "play_or_pause_video": "Pokreni ili pauziraj video zapis", - "point": "", "port": "port", "preset": "Unapred podešeno", "preview": "Pregled", @@ -1077,12 +1023,10 @@ "purchase_server_description_2": "Status podrške", "purchase_server_title": "Server", "purchase_settings_server_activated": "Ključem proizvoda servera upravlja administrator", - "range": "", "rating": "Ocena zvezdica", "rating_clear": "Obriši ocenu", "rating_count": "{count, plural, one {# zvezda} other {# zvezde}}", "rating_description": "Prikažite EXIF ocenu u info panelu", - "raw": "", "reaction_options": "Opcije reakcije", "read_changelog": "Pročitajte dnevnik promena", "reassign": "Ponovo dodaj", @@ -1090,6 +1034,7 @@ "reassigned_assets_to_new_person": "Ponovo dodeljeno {count, plural, one {# datoteka} other {# datoteke}} novoj osobi", "reassing_hint": "Dodelite izabrana sredstva postojećoj osobi", "recent": "Skorašnji", + "recent-albums": "Nedavni albumi", "recent_searches": "Skorašnje pretrage", "refresh": "Osveži", "refresh_encoded_videos": "Osvežite kodirane (encoded) video zapise", @@ -1111,6 +1056,7 @@ "remove_from_album": "Obriši iz albuma", "remove_from_favorites": "Ukloni iz favorita", "remove_from_shared_link": "Uklonite sa deljene veze", + "remove_url": "Ukloni URL", "remove_user": "Ukloni korisnika", "removed_api_key": "Uklonjen API ključ (key): {name}", "removed_from_archive": "Uklonjeno iz arhive", @@ -1127,7 +1073,6 @@ "reset": "Resetovati", "reset_password": "Resetovati lozinku", "reset_people_visibility": "Resetujte vidljivost osoba", - "reset_settings_to_default": "", "reset_to_default": "Resetujte na podrazumevane vrednosti", "resolve_duplicates": "Reši duplikate", "resolved_all_duplicates": "Svi duplikati su razrešeni", @@ -1147,9 +1092,7 @@ "saved_settings": "Sačuvana podešavanja", "say_something": "Reci nešto", "scan_all_libraries": "Skeniraj sve biblioteke", - "scan_all_library_files": "Ponovo skenirajte sve datoteke biblioteke", "scan_library": "Skeniraj", - "scan_new_library_files": "Skenirajte nove datoteke biblioteke", "scan_settings": "Podešavanja skeniranja", "scanning_for_album": "Skeniranje albuma...", "search": "Pretraga", @@ -1192,7 +1135,6 @@ "selected_count": "{count, plural, other {# izabrano}}", "send_message": "Pošalji poruku", "send_welcome_email": "Pošaljite e-poštu dobrodošlice", - "server": "Server", "server_offline": "Server van mreže (offline)", "server_online": "Server na mreži (online)", "server_stats": "Statistika servera", @@ -1297,17 +1239,17 @@ "they_will_be_merged_together": "Oni će biti spojeni zajedno", "third_party_resources": "Resursi trećih strana", "time_based_memories": "Sećanja zasnovana na vremenu", + "timeline": "Vremenska linija", "timezone": "Vremenska zona", "to_archive": "Arhiviraj", "to_change_password": "Promeni lozinku", "to_favorite": "Postavi kao favorit", "to_login": "Prijava", "to_parent": "Vrati se nazad", - "to_root": "Na početak", "to_trash": "Smeće", "toggle_settings": "Namesti podešavanja", "toggle_theme": "Namesti tamnu temu", - "toggle_visibility": "Namesti vidljivost", + "total": "Ukupno", "total_usage": "Ukupna upotreba", "trash": "Otpad", "trash_all": "Baci sve u otpad", @@ -1317,12 +1259,10 @@ "trashed_items_will_be_permanently_deleted_after": "Datoteke u otpadu će biti trajno izbrisane nakon {days, plural, one {# dan} few {# dana} other {# dana}}.", "type": "Vrsta", "unarchive": "Vrati iz arhive", - "unarchived": "Vraćeno iz arhive", "unarchived_count": "{count, plural, other {Nearhivirano#}}", "unfavorite": "Izbaci iz omiljenih (unfavorite)", "unhide_person": "Otkrij osobu", "unknown": "Nepoznat", - "unknown_album": "Nepoznat Album", "unknown_year": "Nepoznata Godina", "unlimited": "Neograničeno", "unlink_motion_video": "Odveži video od slike", @@ -1354,13 +1294,13 @@ "use_custom_date_range": "Umesto toga koristite prilagođeni period", "user": "Korisnik", "user_id": "ID korisnika", - "user_license_settings": "Licenca", - "user_license_settings_description": "Upravljajte svojom licencom", "user_liked": "{user} je lajkovao {type, select, photo {ovu fotografiju} video {ovaj video zapis} asset {ovu datoteku} other {ovo}}", "user_purchase_settings": "Kupovina", "user_purchase_settings_description": "Upravljajte kupovinom", "user_role_set": "Postavi {user} kao {role}", "user_usage_detail": "Detalji korišćenja korisnika", + "user_usage_stats": "Statistika korišćenja naloga", + "user_usage_stats_description": "Pogledajte statistiku korišćenja naloga", "username": "Korisničko ime", "users": "Korisnici", "utilities": "Alati", @@ -1368,7 +1308,7 @@ "variables": "Promenljive (variables)", "version": "Verzija", "version_announcement_closing": "Tvoj prijatelj, Aleks", - "version_announcement_message": "Zdravo prijatelju, postoji nova verzija aplikacije, molimo vas da odvojite vreme da posetite napomene o izdanju i uverite se u svoje docker-compose.yml, i .env podešavanje je ažurirano kako bi se sprečile bilo kakve pogrešne konfiguracije, posebno ako koristite WatchTower ili bilo koji mehanizam koji automatski upravlja ažuriranjem vaše aplikacije.", + "version_announcement_message": "Zdravo prijatelju, postoji nova verzija aplikacije, molimo vas da odvojite vreme da posetite napomene o izdanju i uverite se da je server ažuriran kako bi se sprečile bilo kakve pogrešne konfiguracije, posebno ako koristite WatchTower ili bilo koji mehanizam koji automatski upravlja ažuriranjem vaše aplikacije.", "version_history": "Istorija verzija", "version_history_item": "Instalirano {version} {date}", "video": "Video zapis", @@ -1382,10 +1322,10 @@ "view_all_users": "Prikaži sve korisnike", "view_in_timeline": "Prikaži u vremenskoj liniji", "view_links": "Prikaži veze", + "view_name": "Pogledati", "view_next_asset": "Pogledajte sledeću datoteku", "view_previous_asset": "Pogledaj prethodnu datoteku", "view_stack": "Prikaži gomilu", - "viewer": "Preglednik (viewer)", "visibility_changed": "Vidljivost je promenjena za {count, plural, one {# osobu} other {# osobe}}", "waiting": "Čekam", "warning": "Upozorenje", diff --git a/i18n/sv.json b/i18n/sv.json index 804ff50b2e17b..f774f3a01dbdf 100644 --- a/i18n/sv.json +++ b/i18n/sv.json @@ -1,5 +1,5 @@ { - "about": "Om", + "about": "Uppdatera", "account": "Konto", "account_settings": "Kontoinställningar", "acknowledge": "Bekräfta", @@ -23,6 +23,7 @@ "add_to": "Lägg till...", "add_to_album": "Lägg till i album", "add_to_shared_album": "Lägg till i delat album", + "add_url": "Lägg till URL", "added_to_archive": "Tillagd i arkiv", "added_to_favorites": "Tillagd till favoriter", "added_to_favorites_count": "{count, number} tillagda till favoriter", @@ -34,6 +35,11 @@ "authentication_settings_disable_all": "Är du säker på att du vill inaktivera alla inloggningsmetoder? Inloggning kommer att helt inaktiveras.", "authentication_settings_reenable": "För att återaktivera, använd Server Command.", "background_task_job": "Bakgrundsaktiviteter", + "backup_database": "Databassäkerhetskopia", + "backup_database_enable_description": "Slå på säkerhetskopia", + "backup_keep_last_amount": "Antal säkerhetskopior att behålla", + "backup_settings": "Säkerhetskopieringsinställningar", + "backup_settings_description": "Hantera inställningar för säkerhetskopiering av databas", "check_all": "Välj alla", "cleared_jobs": "Rensade jobben för:{job}", "config_set_by_file": "Konfigurationen är satt av en konfigurationsfil", @@ -43,9 +49,10 @@ "confirm_reprocess_all_faces": "Är du säker på att du vill återprocessa alla ansikten? Detta kommer också rensa namngivna personer.", "confirm_user_password_reset": "Är du säker på att du vill återställa {user}’s lösenord?", "create_job": "Skapa jobb", - "crontab_guru": "Crontab-guru", + "cron_expression": "Cron uttryck", + "cron_expression_description": "Sätt skanningsintervall genom att använda cron format. För mer information se Crontab Guru", + "cron_expression_presets": "Cron uttryck förinställningar", "disable_login": "Inaktivera inloggning", - "disabled": "Inaktiverad", "duplicate_detection_job_description": "Kör maskininlärning på objekt för att upptäcka liknande bilder. Bygger på Smart Search", "exclusion_pattern_description": "Exkluderingsmönster tillåter dig att ignorera filer och mappar när skanning görs av ditt album. Detta är användbart om du har mappar som innehåller filer som du inte vill importera, t.ex. RAW-filer.", "external_library_created_at": "Externt bibliotek (skapat den {date})", @@ -63,22 +70,15 @@ "image_prefer_wide_gamut": "Föredrar brett spektrum", "image_prefer_wide_gamut_setting_description": "Använd Display P3 för miniatyrer. Detta bevarar livfullheten bättre hos bilder med bred färgrymd, men bilder kan se annorlunda ut på gamla enheter med en gammal webbläsarversion. Med sRGB-bilder behålls i sitt format sRGB för att undvika färgskiftningar.", "image_preview_description": "Mellanstor bild med avskalad metadata, används vid visning av en enskild tillgång och för maskininlärning", - "image_preview_format": "Förhandsgranskningsformat", "image_preview_quality_description": "Förhandsgranska kvalitet från 1-100. Högre är bättre, men ger större filer och kan minska appens känslighet. Att ställa in ett lågt värde kan påverka kvaliteten på maskininlärning.", - "image_preview_resolution": "Förhandsgranska upplösning", - "image_preview_resolution_description": "Används vid visning av ett enstaka foto och för maskininlärning. Högre upplösningar kan bevara fler detaljer men tar längre tid att koda, har större filstorlekar och kan minska appens responsiva känsla.", "image_preview_title": "Förhandsvisningsinställningar", "image_quality": "Kvalitet", - "image_quality_description": "Bildkvalitet från 1-100. Högre är bättre för kvaliteten men ger större filer, det här alternativet påverkar förhandsgranskningen och miniatyrbilderna.", "image_resolution": "Upplösning", "image_resolution_description": "Högre upplösningar kan bevara fler detaljer men tar längre tid att koda, har större filstorlekar och kan minska appens känslighet.", "image_settings": "Bildinställningar", "image_settings_description": "Hantera kvalitet och upplösning på genererade bilder", "image_thumbnail_description": "Liten miniatyrbild med avskalad metadata, används när du tittar på grupper av foton som huvudtidslinjen", - "image_thumbnail_format": "Miniatyrformat", "image_thumbnail_quality_description": "Miniatyrkvalitet från 1-100. Högre är bättre, men ger större filer och kan minska appens känslighet.", - "image_thumbnail_resolution": "Miniatyrbildsupplösning", - "image_thumbnail_resolution_description": "Används när du tittar på grupper av foton (huvudtidslinje, albumvy, etc.). Högre upplösningar kan bevara fler detaljer men tar längre tid att koda, har större filstorlekar och kan minska appens responsiva känsla.", "image_thumbnail_title": "Miniatyrbildsinställningar", "job_concurrency": "{job} Samtidighet", "job_created": "Jobb skapat", @@ -89,9 +89,6 @@ "jobs_delayed": "{jobCount, plural, other {# försenad}}", "jobs_failed": "{jobCount, plural, other {# misslyckades}}", "library_created": "Skapat bibliotek: {library}", - "library_cron_expression": "Cron-uttryck", - "library_cron_expression_description": "Ställ in intervallet för skanningen med cron-formatet. För mer information gå till t.ex. Crontab Guru ", - "library_cron_expression_presets": "Cron-uttrycksförinställningar", "library_deleted": "Biblioteket har tagits bort", "library_import_path_description": "Ange en mapp att importera. Den här mappen, inklusive undermappar, skannas efter bilder och videor.", "library_scanning": "Periodisk skanning", @@ -134,7 +131,7 @@ "machine_learning_smart_search_description": "Sök semantiskt efter bilder med hjälp av CLIP-inbäddningar", "machine_learning_smart_search_enabled": "Aktivera smart sökning", "machine_learning_smart_search_enabled_description": "Om inaktiverat kommer bilder inte att kodas för smart sökning.", - "machine_learning_url_description": "Maskininlärningsserverns URL", + "machine_learning_url_description": "Maskininlärningsserverns URL. Om det är mer än en URL tillagd så kommer ett försök per URL att utföras tills någon av dom svarar, försöken görs i kronologisk ordning.", "manage_concurrency": "Hantera samtidighet", "manage_log_settings": "Hantera logginställningar", "map_dark_style": "Mörk stil", @@ -215,7 +212,6 @@ "refreshing_all_libraries": "Samtliga bibliotek uppdateras", "registration": "Administratörsregistrering", "registration_description": "Du utses till administratör eftersom du är systemets första användare. Du ansvarar för administration och kan skapa ytterligare användare.", - "removing_deleted_files": "Tar bort offline-filer", "repair_all": "Reparera alla", "repair_matched_items": "Matchade {count, plural, one {# föremål} other {# föremål}}", "repaired_items": "Reparerade {count, plural, one {# item} other {# items}}", @@ -223,12 +219,12 @@ "reset_settings_to_default": "Återställ inställningar till standard", "reset_settings_to_recent_saved": "Återställ inställningar till de senaste sparade", "scanning_library": "Skanna bibliotek", - "scanning_library_for_changed_files": "Scannar bibliotek efter ändrade filer", - "scanning_library_for_new_files": "Skannar biblioteket efter nya filer", "search_jobs": "Sök Jobb...", "send_welcome_email": "Skicka välkomstmail", "server_external_domain_settings": "Extern domän", "server_external_domain_settings_description": "Domän för publikt delade länkar, inklusive http(s)://", + "server_public_users": "Vanlig användare", + "server_public_users_description": "Alla användare (namn och e-post) är listade när man lägger till en användare till ett delat album. Om inaktiverat, kommer användarlistan endast vara synlig för administratörer.", "server_settings": "Serverinställningar", "server_settings_description": "Hantera serverinställningar", "server_welcome_message": "Välkomstmeddelande", @@ -254,6 +250,16 @@ "storage_template_user_label": "{label} är användarens lagringsmärkning", "system_settings": "Systeminställningar", "tag_cleanup_job": "Markera för rensning", + "template_email_available_tags": "Du kan använda följande variablar i din mall: {tags}", + "template_email_if_empty": "Om mallen är tom, kommer standard e-post att användas.", + "template_email_invite_album": "Inbjudan Album Mall", + "template_email_preview": "Förhandsgranskning", + "template_email_settings": "E-post mall", + "template_email_settings_description": "Hantera anpassad e-postavisering mall.", + "template_email_update_album": "Uppdatera Album Mall", + "template_email_welcome": "Välkommen e-post mall", + "template_settings": "Notifikations Mall", + "template_settings_description": "Hantera anpassade mallar för notifikationer.", "theme_custom_css_settings": "Anpassad CSS", "theme_custom_css_settings_description": "Cascading Style Sheets möjliggör designanpassningar av Immich", "theme_settings": "Temainställningar", @@ -261,7 +267,6 @@ "these_files_matched_by_checksum": "Dessa filer matchas av deras kontrollsummor", "thumbnail_generation_job": "Generera Miniatyrer", "thumbnail_generation_job_description": "Generera stora, små och suddiga miniatyrer för varje objekt, samt för varje person", - "transcode_policy_description": "", "transcoding_acceleration_api": "Accelerations-API", "transcoding_acceleration_api_description": "API som kommer att interagera med din enhet för att accelerera omkodning. Inställning är 'best effort': vid fel kommer den att återgå till mjukvarubaserad omkodning. VP9 kan fungera eller inte, beroende på din hårdvara.", "transcoding_acceleration_nvenc": "NVENC (kräver NVIDIA GPU)", @@ -307,14 +312,12 @@ "transcoding_settings_description": "Hantera upplösningen och kodningen av videofiler", "transcoding_target_resolution": "Förväntad upplösning", "transcoding_target_resolution_description": "En högre upplösning kan bevara fler detaljer men kan ta längre tid at koda, ha större fil storlek och kan försämra appens svarstid.", - "transcoding_temporal_aq": "", + "transcoding_temporal_aq": "Temporär AQ", "transcoding_temporal_aq_description": "Gäller endast NVENC. Ökar kvaliteten på scener med hög detaljrikedom och låg rörelse. Kanske inte är kompatibel med äldre enheter.", "transcoding_threads": "Trådar", "transcoding_threads_description": "Högre värden leder till snabbare kodning, men lämnar mindre utrymme för servern att bearbeta andra uppgifter medan den är aktiv. Detta värde bör inte vara mer än antalet CPU-kärnor. Maximerar användningen om den är inställd på 0.", - "transcoding_tone_mapping": "", + "transcoding_tone_mapping": "Ton mappning", "transcoding_tone_mapping_description": "Försöker att bevara utseendet på HDR-videor när de konverteras till SDR. Varje algoritm gör olika avvägningar för färg, detaljer och ljusstyrka. Hable bevarar detaljer, Mobius bevarar färg och Reinhard bevarar ljusstyrkan.", - "transcoding_tone_mapping_npl": "", - "transcoding_tone_mapping_npl_description": "Färgerna kommer att justeras för att se normala ut för en visning av denna ljusstyrka. Kontraintuitivt ökar lägre värden videons ljusstyrka och vice versa eftersom det kompenserar för skärmens ljusstyrka. 0 ställer in detta värde automatiskt.", "transcoding_transcode_policy": "Omkodningspolicy", "transcoding_transcode_policy_description": "Policy för när en video ska omkodas. HDR-videor kommer alltid att omkodas (förutom om omkodning är inaktiverad).", "transcoding_two_pass_encoding": "Två-pass kodning", @@ -355,6 +358,7 @@ "advanced": "Avancerat", "age_months": "Ålder {months, plural, one {# month} other {# months}}", "age_year_months": "Ålder 1 år, {months, plural, one {# month} other {# months}}", + "age_years": "{years, plural, other {Age #}}", "album_added": "Albumet har lagts till", "album_added_notification_setting_description": "Få ett e-postmeddelande när du läggs till i ett delat album", "album_cover_updated": "Albumomslaget uppdaterat", @@ -374,6 +378,7 @@ "album_user_removed": "Tog bort {user}", "album_with_link_access": "Låt alla med länken se foton och personer i det här albumet.", "albums": "Album", + "albums_count": "{count, plural, one {{count, number} Album} other {{count, number} Albums}}", "all": "Allt", "all_albums": "Alla album", "all_people": "Alla personer", @@ -393,7 +398,7 @@ "archive_or_unarchive_photo": "Arkivera eller oarkivera fotot", "archive_size": "Arkivstorlek", "archive_size_description": "Konfigurera arkivstorleken för nedladdningar (i GiB)", - "archived": "", + "archived_count": "{count, plural, other {Archived #}}", "are_these_the_same_person": "Är det samma person?", "are_you_sure_to_do_this": "Är du säker på att du vill göra det här?", "asset_added_to_album": "Lades till i album", @@ -412,6 +417,7 @@ "assets_added_count": "La till {count, plural, one {# asset} other {# assets}}", "assets_added_to_album_count": "Lade till {count, plural, one {# asset} other {# assets}} i albumet", "assets_added_to_name_count": "Lade till {count, plural, one {# asset} other {# assets}} till {hasName, select, true {{name}} other {new album}}", + "assets_count": "{count, plural, one {# asset} other {# assets}}", "assets_moved_to_trash_count": "Flyttade {count, plural, one {# asset} other {# assets}} till papperskorgen", "assets_permanently_deleted_count": "Raderad permanent {count, plural, one {# asset} other {# assets}}", "assets_removed_count": "Tog bort {count, plural, one {# asset} other {# assets}}", @@ -441,10 +447,6 @@ "cannot_merge_people": "Kan inte slå samman personer", "cannot_undo_this_action": "Du kan inte ångra den här åtgärden!", "cannot_update_the_description": "Det går inte att uppdatera beskrivningen", - "cant_apply_changes": "", - "cant_get_faces": "", - "cant_search_people": "", - "cant_search_places": "", "change_date": "Ändra datum", "change_expiration_time": "Ändra utgångstid", "change_location": "Ändra plats", @@ -476,6 +478,7 @@ "confirm": "Bekräfta", "confirm_admin_password": "Bekräfta administratörslösenord", "confirm_delete_shared_link": "Är du säker på att du vill ta bort den här delade länken?", + "confirm_keep_this_delete_others": "Alla andra tillgångar i stacken tas bort förutom den här tillgången. Är du säker på att du vill fortsätta.", "confirm_password": "Bekräfta lösenord", "contain": "Anpassa", "context": "Sammanhang", @@ -525,6 +528,7 @@ "delete_key": "Ta bort nyckel", "delete_library": "Ta bort bibliotek", "delete_link": "Ta bort länk", + "delete_others": "Radera fler", "delete_shared_link": "Ta bort delad länk", "delete_tag": "Ta bort tagg", "delete_tag_confirmation_prompt": "Är du säker på att du vill ta bort {tagName}-taggen?", @@ -536,6 +540,7 @@ "direction": "Riktning", "disabled": "Inaktiverad", "disallow_edits": "Tillåt inte redigeringar", + "discord": "Discord", "discover": "Upptäck", "dismiss_all_errors": "Avvisa alla fel", "dismiss_error": "Avvisa fel", @@ -557,13 +562,6 @@ "duplicates": "Dubletter", "duplicates_description": "Lös varje grupp genom att ange vilka, om några, är dubbletter", "duration": "Varaktighet", - "durations": { - "days": "", - "hours": "", - "minutes": "", - "months": "", - "years": "" - }, "edit": "Redigera", "edit_album": "Redigera album", "edit_avatar": "Redigera avatar", @@ -588,8 +586,6 @@ "editor_crop_tool_h2_aspect_ratios": "Bildförhållande", "editor_crop_tool_h2_rotation": "Rotation", "email": "Epost", - "empty": "", - "empty_album": "", "empty_trash": "Töm papperskorg", "empty_trash_confirmation": "Är du säker på att du vill tömma papperskorgen? Detta tar bort alla objekt i papperskorgen permanent från Immich.\nDu kan inte ångra den här åtgärden!", "enable": "Aktivera", @@ -623,6 +619,7 @@ "failed_to_create_shared_link": "Det gick inte att skapa delad länk", "failed_to_edit_shared_link": "Det gick inte att redigera delad länk", "failed_to_get_people": "Det gick inte att hämta personer", + "failed_to_keep_this_delete_others": "Misslyckades att behålla detta objekt radera övriga objekt", "failed_to_load_asset": "Det gick inte att ladda objekt", "failed_to_load_assets": "Det gick inte att ladda objekten", "failed_to_load_people": "Det gick inte att ladda personer", @@ -650,8 +647,6 @@ "unable_to_change_location": "Kunde inte ändra plats", "unable_to_change_password": "Det går inte att ändra lösenord", "unable_to_change_visibility": "Det gick inte att ändra synligheten för {count, plural, one {# person} other {# people}}", - "unable_to_check_item": "", - "unable_to_check_items": "", "unable_to_complete_oauth_login": "Det gick inte att slutföra OAuth-inloggning", "unable_to_connect": "Det går inte att ansluta", "unable_to_connect_to_server": "Det går inte att ansluta till servern", @@ -679,46 +674,52 @@ "unable_to_link_motion_video": "Det går inte att länka rörlig video", "unable_to_link_oauth_account": "Det gick inte att länka OAuth-kontot", "unable_to_load_album": "Det gick inte att ladda albumet", - "unable_to_load_asset_activity": "", - "unable_to_load_items": "", - "unable_to_load_liked_status": "", + "unable_to_load_asset_activity": "Det går inte att läsa in tillgångsaktivitet", + "unable_to_load_items": "Kunde inte ladda objekt", + "unable_to_load_liked_status": "kunde inte ladda gillade status", "unable_to_log_out_all_devices": "Det gick inte att logga ut alla enheter", "unable_to_log_out_device": "Det gick inte att logga ut enheten", "unable_to_login_with_oauth": "Det gick inte att logga in med OAuth", "unable_to_play_video": "Kunde inte spela upp video", - "unable_to_refresh_user": "", - "unable_to_remove_album_users": "", + "unable_to_reassign_assets_existing_person": "Det går inte att tilldela om tillgångar till {name, select, null {an existing person} other {{name}}}", + "unable_to_reassign_assets_new_person": "Kunde inte tilldela objekt till en annan person", + "unable_to_refresh_user": "Kunde inte ladda om användaren", + "unable_to_remove_album_users": "Kunde inte ta bort personen från albumet", "unable_to_remove_api_key": "Det gick inte att ta bort API Keyet", - "unable_to_remove_comment": "", + "unable_to_remove_assets_from_shared_link": "Kunde inte ta bort objekt från delade länkar", + "unable_to_remove_deleted_assets": "Kunde inte ta bort offline filer", "unable_to_remove_library": "Kunde inte ta bort bibliotek", "unable_to_remove_partner": "Kunde inte ta bort partner", "unable_to_remove_reaction": "Kunde inte ta bort reaktion", - "unable_to_remove_user": "", - "unable_to_repair_items": "", + "unable_to_repair_items": "kunde inte reparera objekt", "unable_to_reset_password": "Kunde inte återställa lösenord", - "unable_to_resolve_duplicate": "", - "unable_to_restore_assets": "", - "unable_to_restore_trash": "", + "unable_to_resolve_duplicate": "Det går inte att lösa dubbletter", + "unable_to_restore_assets": "Det går inte att återställa tillgångar", + "unable_to_restore_trash": "Det gick inte att återställa papperskorgen", "unable_to_restore_user": "Kunde inte återställa användare", "unable_to_save_album": "Kunde inte spara album", + "unable_to_save_api_key": "Det går inte att spara API Nyckel", + "unable_to_save_date_of_birth": "Det går inte att spara födelsedatum", "unable_to_save_name": "Kunde inte spara namn", "unable_to_save_profile": "Kunde inte spara profil", "unable_to_save_settings": "Kunde inte spara inställningar", - "unable_to_scan_libraries": "", - "unable_to_scan_library": "", - "unable_to_set_profile_picture": "", - "unable_to_submit_job": "", - "unable_to_trash_asset": "", - "unable_to_unlink_account": "", + "unable_to_scan_libraries": "Det går inte att söka igenom bibliotek", + "unable_to_scan_library": "Det går inte att skanna biblioteket", + "unable_to_set_feature_photo": "Det går inte att ställa in funktionsfoto", + "unable_to_set_profile_picture": "Det går inte att ställa in profilbilden", + "unable_to_submit_job": "Det går inte att skicka jobbet", + "unable_to_trash_asset": "Det går inte att slänga resursen", + "unable_to_unlink_account": "Det går inte att ta bort länken till kontot", + "unable_to_unlink_motion_video": "Det går inte att ta bort länken till rörelsevideo", + "unable_to_update_album_cover": "Det går inte att uppdatera albumomslaget", + "unable_to_update_album_info": "Det går inte att uppdatera albuminformationen", "unable_to_update_library": "Kunde inte uppdatera bibliotek", "unable_to_update_location": "Kunde inte uppdatera plats", "unable_to_update_settings": "Kunde inte uppdatera inställningar", - "unable_to_update_user": "Kunde inte uppdatera användare" + "unable_to_update_timeline_display_status": "Det går inte att uppdatera visningsstatus för tidslinjen", + "unable_to_update_user": "Kunde inte uppdatera användare", + "unable_to_upload_file": "Det går inte att ladda upp filen" }, - "every_day_at_onepm": "", - "every_night_at_midnight": "", - "every_night_at_twoam": "", - "every_six_hours": "", "exif": "Exif", "exit_slideshow": "Avsluta bildspel", "expand_all": "Expandera alla", @@ -729,84 +730,118 @@ "explorer": "Utforskare", "export": "Exportera", "export_as_json": "Exportera som JSON", - "extension": "", + "extension": "Tillägg", + "external": "Externt", "external_libraries": "Externa Bibliotek", - "failed_to_get_people": "", + "face_unassigned": "Otilldelade", + "failed_to_load_assets": "Det gick inte att läsa in resurser", "favorite": "Favorit", - "favorite_or_unfavorite_photo": "", + "favorite_or_unfavorite_photo": "Favoritfoto eller icke-favoritfoto", "favorites": "Favoriter", - "feature": "", - "feature_photo_updated": "", - "featurecollection": "", + "feature_photo_updated": "Funktionsfoto uppdaterad", + "features": "Funktioner", + "features_setting_description": "Hantera appens funktioner", "file_name": "Filnamn", "file_name_or_extension": "Filnamn eller -tillägg", "filename": "Filnamn", - "files": "", "filetype": "Filtyp", "filter_people": "Filtrera personer", - "fix_incorrect_match": "", - "force_re-scan_library_files": "", + "find_them_fast": "Hitta dem snabbt efter namn med sök", + "fix_incorrect_match": "Fixa inkorrekt matchning", + "folders": "Mappar", + "folders_feature_description": "Bläddra i mappvyn för foton och videoklipp i filsystemet", "forward": "Framåt", - "general": "", - "get_help": "", - "getting_started": "", + "general": "Allmänt", + "get_help": "Få hjälp", + "getting_started": "Komma igång", "go_back": "Gå tillbaka", "go_to_search": "Gå till sök", - "go_to_share_page": "", - "group_albums_by": "", - "has_quota": "", + "group_albums_by": "Gruppera album efter...", + "group_no": "Ingen gruppering", + "group_owner": "Grupper efter ägare", + "group_year": "Gruppera efter årtal", + "has_quota": "Har kvot", + "hi_user": "Hej {name} ({email})", + "hide_all_people": "Göm alla personer", "hide_gallery": "Dölj galleri", + "hide_named_person": "Göm personen {name}", "hide_password": "Dölj lösenord", "hide_person": "Dölj person", + "hide_unnamed_people": "Göm personer utan namn", "host": "Värd", "hour": "Timme", "image": "Bild", - "img": "", + "image_alt_text_date": "{isVideo, select, true {Video} other {Image}} tagen {date}", + "image_alt_text_date_1_person": "{isVideo, select, true {Video} other {Image}} tagen med {person1} den {date}", + "image_alt_text_date_2_people": "{isVideo, select, true {Video} other {Image}} tagen med {person1} och {person2} den {date}", + "image_alt_text_date_3_people": "{isVideo, select, true {Video} other {Image}} tagen med {person1}, {person2}, och {person3} den {date}", + "image_alt_text_date_4_or_more_people": "{isVideo, select, true {Video} other {Image}} tagen med {person1}, {person2}, och {additionalCount, number} andra den {date}", + "image_alt_text_date_place": "{isVideo, select, true {Video} other {Image}} tagen i {city}, {country} den {date}", + "image_alt_text_date_place_1_person": "{isVideo, select, true {Video} other {Image}} tagen i {city}, {country} med {person1} den {date}", + "image_alt_text_date_place_2_people": "{isVideo, select, true {Video} other {Image}} tagen i {city}, {country} med {person1} och {person2} den {date}", + "image_alt_text_date_place_3_people": "{isVideo, select, true {Video} other {Image}} tagen i {city}, {country} med {person1}, {person2}, och {person3} den {date}", + "image_alt_text_date_place_4_or_more_people": "{isVideo, select, true {Video} other {Image}} tagen i {city}, {country} med {person1}, {person2}, och {additionalCount, number} andre den {date}", "immich_logo": "Immich Logo", + "immich_web_interface": "Immich Web gränssnitt", "import_from_json": "Importera från JSON", "import_path": "Importsökväg", - "in_archive": "", + "in_albums": "I {count, plural, one {# album} other {# albums}}", + "in_archive": "I arkivet", "include_archived": "Inkludera arkiverade", "include_shared_albums": "Inkludera delade album", - "include_shared_partner_assets": "", - "individual_share": "", - "info": "", + "include_shared_partner_assets": "Inkludera delade partners tillgångar", + "individual_share": "Enskild delning", + "info": "Information", "interval": { - "day_at_onepm": "", - "hours": "", - "night_at_midnight": "", - "night_at_twoam": "" + "day_at_onepm": "Alla dagar vid kl 13.00", + "hours": "Vid varje {hours, plural, one {hour} other {{hours, number} hours}}", + "night_at_midnight": "Varje natt vid midnatt.", + "night_at_twoam": "Varje natt vid kl 02.00" }, - "invite_people": "", + "invite_people": "Bjud in personer", "invite_to_album": "Bjuder in till album", - "job_settings_description": "", + "items_count": "{count, plural, one {# item} other {# items}}", "jobs": "Jobb", - "keep": "", - "keyboard_shortcuts": "", - "language": "", - "language_setting_description": "", - "last_seen": "", - "leave": "", + "keep": "Behåll", + "keep_all": "Behåll alla", + "keep_this_delete_others": "Behåll denna, radera övriga", + "kept_this_deleted_others": "Behåll denna tillgång och borttagna {count, plural, one {# asset} other {# assets}}", + "keyboard_shortcuts": "Kortkommandon", + "language": "Språk", + "language_setting_description": "Välj önskat språk", + "last_seen": "Senast sedd", + "latest_version": "Senaste versionen", + "latitude": "Latitud", + "leave": "Lämna", "let_others_respond": "Låt andra svara", - "level": "", + "level": "Nivå", "library": "Bibliotek", - "library_options": "", - "light": "", - "link_options": "", - "link_to_oauth": "", - "linked_oauth_account": "", - "list": "", - "loading": "", - "loading_search_results_failed": "", + "library_options": "Nivå alternativ", + "light": "Ljus", + "like_deleted": "Gilla borttagen", + "link_motion_video": "Länka rörlig video", + "link_options": "Alternativ för länk", + "link_to_oauth": "Länk till OAuth", + "linked_oauth_account": "Länkat OAuth konto", + "list": "Lista", + "loading": "Laddar", + "loading_search_results_failed": "Det gick inte att läsa in sökresultat", "log_out": "Logga ut", - "log_out_all_devices": "", - "login_has_been_disabled": "", - "look": "", - "loop_videos": "", + "log_out_all_devices": "Logga ut alla enheter", + "logged_out_all_devices": "Loggat ut från alla enheter", + "logged_out_device": "Loggat ut enheten", + "login": "Logga in", + "login_has_been_disabled": "Inloggning har blivit inaktiverat.", + "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?", + "longitude": "Longitud", + "look": "Titta", + "loop_videos": "Loopa videor", "loop_videos_description": "Aktivera för att automatiskt loopa en video i detaljvisaren.", + "main_branch_warning": "Du använder en utvecklingsversion. Vi rekommenderar starkt att du använder en utgiven version!", "make": "Tillverkare", "manage_shared_links": "Hantera Delade länkar", - "manage_sharing_with_partners": "", + "manage_sharing_with_partners": "Hantera delning med partner", "manage_the_app_settings": "", "manage_your_account": "Hantera ditt konto", "manage_your_api_keys": "", @@ -863,7 +898,6 @@ "oldest_first": "", "online": "", "only_favorites": "", - "only_refreshes_modified_files": "", "open_the_search_filters": "", "options": "Val", "organize_your_library": "Organisera ditt bibliotek", @@ -891,7 +925,6 @@ "pending": "", "people": "Personer", "people_sidebar_description": "", - "perform_library_tasks": "", "permanent_deletion_warning": "", "permanent_deletion_warning_setting_description": "", "permanently_delete": "", @@ -906,7 +939,6 @@ "play_memories": "", "play_motion_photo": "", "play_or_pause_video": "", - "point": "", "port": "", "preset": "", "preview": "", @@ -916,8 +948,6 @@ "primary": "", "profile_picture_set": "", "public_share": "", - "range": "", - "raw": "", "reaction_options": "", "read_changelog": "", "recent": "", @@ -937,7 +967,6 @@ "reset": "", "reset_password": "", "reset_people_visibility": "", - "reset_settings_to_default": "", "restore": "Återställ", "restore_user": "", "retry_upload": "", @@ -948,8 +977,6 @@ "saved_settings": "", "say_something": "Säg något", "scan_all_libraries": "Skanna alla bibliotek", - "scan_all_library_files": "", - "scan_new_library_files": "", "scan_settings": "", "search": "Sök", "search_albums": "", @@ -978,7 +1005,6 @@ "select_photos": "Välj foton", "selected": "", "send_message": "", - "server": "Server", "server_stats": "Serverstatistik", "set": "", "set_as_album_cover": "", @@ -1037,35 +1063,35 @@ "theme": "Tema", "theme_selection": "Val av tema", "theme_selection_description": "Ställ in temat automatiskt till ljust eller mörkt baserat på din webbläsares inställningar", + "they_will_be_merged_together": "De kommer att slås samman", + "third_party_resources": "Tredjepartsresurser", "time_based_memories": "Tidsbaserade minnen", "timezone": "Tidszon", "to_archive": "Arkivera", "to_change_password": "Ändra lösenord", "to_favorite": "Favorit", "to_login": "Logga in", + "to_trash": "Papperskorg", "toggle_settings": "", "toggle_theme": "Växla tema", - "toggle_visibility": "Växla synlighet", "total_usage": "Total användning", "trash": "Papperskorg", - "trash_all": "", + "trash_all": "Kasta alla", "trash_no_results_message": "Borttagna foton och videor kommer att visas här.", "trashed_items_will_be_permanently_deleted_after": "Objekt i papperskorgen raderas permanent efter {days, plural, one {# dag} other {# dagar}}.", "type": "Typ", "unarchive": "Ångra arkivering", - "unarchived": "", "unfavorite": "Avfavorisera", "unhide_person": "", "unknown": "Okänd", - "unknown_album": "Okänt album", "unknown_year": "Okänt år", "unlimited": "Obegränsat", - "unlink_oauth": "", + "unlink_oauth": "Ta bort länken till OAuth", "unlinked_oauth_account": "", "unsaved_change": "Osparade ändringar", "unselect_all": "", "unstack": "Stapla Av", - "up_next": "", + "up_next": "Nästa", "updated_password": "Lösenordet har uppdaterats", "upload": "Ladda upp", "upload_concurrency": "", @@ -1078,6 +1104,8 @@ "user_purchase_settings": "Köp", "user_purchase_settings_description": "Hantera dina köp", "user_usage_detail": "", + "user_usage_stats": "Kontoinformation - statistik", + "user_usage_stats_description": "Se statistik - kontoanvändande", "username": "Användarnamn", "users": "Användare", "utilities": "Verktyg", @@ -1097,7 +1125,6 @@ "view_links": "Visa länkar", "view_next_asset": "Visa nästa objekt", "view_previous_asset": "Visa föregående objekt", - "viewer": "", "waiting": "Väntar", "warning": "Varning", "week": "Vecka", diff --git a/i18n/ta.json b/i18n/ta.json index e4201806f70c9..8525308e332f0 100644 --- a/i18n/ta.json +++ b/i18n/ta.json @@ -58,16 +58,9 @@ "image_prefer_embedded_preview_setting_description": "", "image_prefer_wide_gamut": "அகன்ற வண்ணவரம்பு தேர்வு", "image_prefer_wide_gamut_setting_description": "", - "image_preview_format": "", - "image_preview_resolution": "", - "image_preview_resolution_description": "", "image_quality": "தரம்", - "image_quality_description": "படத்தின் தரம் 1-100 வரை. உயர்வானது தரத்திற்கு சிறந்தது, ஆனால் பெரிய கோப்புகளை உருவாக்குகிறது, இந்த விருப்பம் முன்னோட்டம் மற்றும் சிறுபடங்களைப் பாதிக்கிறது.", "image_settings": "பட அமைப்புகள்", "image_settings_description": "உருவாக்கப்பட்ட படங்களின் தரம் மற்றும் தெளிவுத்திறனை நிர்வகிக்கவும்", - "image_thumbnail_format": "சிறுபட வடிவம்", - "image_thumbnail_resolution": "", - "image_thumbnail_resolution_description": "", "job_concurrency": "{job} ஒத்திசைவு", "job_not_concurrency_safe": "இந்த வேலை ஒரே நேரத்தில் பாதுகாப்பானது அல்ல.", "job_settings": "", @@ -76,9 +69,6 @@ "jobs_delayed": "", "jobs_failed": "", "library_created": "உருவாக்கப்பட்ட புகைப்பட நூலகம்: {library}", - "library_cron_expression": "கிரான் வடிவம்", - "library_cron_expression_description": "கிரான் வடிவமைப்பைப் பயன்படுத்தி ஸ்கேனிங் இடைவெளியை அமைக்கவும். மேலும் தகவலுக்கு, எ.கா. Crontab Guru", - "library_cron_expression_presets": "கிரான் வடிவமைப்பு முன்னமைவுகள்", "library_deleted": "புகைப்பட நூலகம் நீக்கப்பட்டது", "library_import_path_description": "இறக்குமதி செய்ய ஒரு கோப்புறையைக் குறிப்பிடவும். துணைக் கோப்புறைகள் உட்பட இந்தக் கோப்புறை படங்கள் மற்றும் வீடியோக்களுக்காக ஸ்கேன் செய்யப்படும்.", "library_scanning": "அவ்வப்போது ஸ்கேனிங்", @@ -192,15 +182,12 @@ "refreshing_all_libraries": "அனைத்து நூலகங்களையும் புதுப்பிக்கிறது", "registration": "நிர்வாக பதிவு", "registration_description": "நீங்கள் கணினியில் முதல் பயனராக இருப்பதால், நீங்கள் நிர்வாகியாக நியமிக்கப்படுவீர்கள் மற்றும் நிர்வாகப் பணிகளுக்குப் பொறுப்பாவீர்கள், மேலும் உங்களால் கூடுதல் பயனர்கள் உருவாக்கப்படுவார்கள்.", - "removing_deleted_files": "ஆஃப்லைன் கோப்புகளை நீக்குகிறது", "repair_all": "அனைத்தையும் பழுதுபார்க்கவும்", "repair_matched_items": "பொருந்தியது {count, plural, one {# உருப்படி} other {# உருப்படிகள்}}", "repaired_items": "பழுதுபார்க்கப்பட்டது {count, plural, one {# உருப்படி} other {# உருப்படிகள்}}", "require_password_change_on_login": "முதல் உள்நுழைவில் பயனர் கடவுச்சொல்லை மாற்ற வேண்டும்", "reset_settings_to_default": "", "reset_settings_to_recent_saved": "", - "scanning_library_for_changed_files": "", - "scanning_library_for_new_files": "", "send_welcome_email": "", "server_external_domain_settings": "", "server_external_domain_settings_description": "", @@ -284,8 +271,6 @@ "transcoding_threads_description": "", "transcoding_tone_mapping": "", "transcoding_tone_mapping_description": "", - "transcoding_tone_mapping_npl": "", - "transcoding_tone_mapping_npl_description": "", "transcoding_transcode_policy": "", "transcoding_transcode_policy_description": "", "transcoding_two_pass_encoding": "", @@ -342,10 +327,8 @@ "archive_or_unarchive_photo": "", "archive_size": "", "archive_size_description": "", - "archived": "", "asset_offline": "", "assets": "", - "assets_moved_to_trash": "", "authorized_devices": "", "back": "", "backward": "", @@ -360,10 +343,6 @@ "cancel_search": "", "cannot_merge_people": "", "cannot_update_the_description": "", - "cant_apply_changes": "", - "cant_get_faces": "", - "cant_search_people": "", - "cant_search_places": "", "change_date": "", "change_expiration_time": "", "change_location": "", @@ -554,7 +533,6 @@ "extension": "", "external": "", "external_libraries": "", - "failed_to_get_people": "", "favorite": "", "favorite_or_unfavorite_photo": "", "favorites": "", @@ -566,14 +544,12 @@ "filter_people": "", "find_them_fast": "", "fix_incorrect_match": "", - "force_re-scan_library_files": "", "forward": "", "general": "", "get_help": "", "getting_started": "", "go_back": "", "go_to_search": "", - "go_to_share_page": "", "group_albums_by": "", "has_quota": "", "hide_gallery": "", @@ -694,7 +670,6 @@ "oldest_first": "", "online": "", "only_favorites": "", - "only_refreshes_modified_files": "", "open_the_search_filters": "", "options": "", "organize_your_library": "", @@ -730,7 +705,6 @@ "permanent_deletion_warning_setting_description": "", "permanently_delete": "", "permanently_deleted_asset": "", - "permanently_deleted_assets": "", "person": "", "photos": "", "photos_count": "", @@ -787,8 +761,6 @@ "saved_settings": "", "say_something": "", "scan_all_libraries": "", - "scan_all_library_files": "", - "scan_new_library_files": "", "scan_settings": "", "scanning_for_album": "", "search": "", @@ -820,7 +792,6 @@ "selected": "", "send_message": "", "send_welcome_email": "", - "server": "", "server_stats": "", "set": "", "set_as_album_cover": "", @@ -892,7 +863,6 @@ "to_trash": "", "toggle_settings": "", "toggle_theme": "", - "toggle_visibility": "", "total_usage": "", "trash": "", "trash_all": "", @@ -901,7 +871,6 @@ "trashed_items_will_be_permanently_deleted_after": "", "type": "", "unarchive": "", - "unarchived": "", "unfavorite": "", "unhide_person": "", "unknown": "", @@ -942,7 +911,6 @@ "view_links": "", "view_next_asset": "", "view_previous_asset": "", - "viewer": "", "waiting": "", "week": "", "welcome": "", diff --git a/i18n/te.json b/i18n/te.json index dc92a56d57b93..3f0f6ff546704 100644 --- a/i18n/te.json +++ b/i18n/te.json @@ -57,16 +57,9 @@ "image_prefer_embedded_preview_setting_description": "అందుబాటులో ఉన్నప్పుడు ఇమేజ్ ప్రాసెసింగ్‌కు ఇన్‌పుట్‌గా RAW ఫోటోలలో ఎంబెడెడ్ ప్రివ్యూలను ఉపయోగించండి. ఇది కొన్ని చిత్రాలకు మరింత ఖచ్చితమైన రంగులను ఉత్పత్తి చేయగలదు, అయితే ప్రివ్యూ నాణ్యత కెమెరాపై ఆధారపడి ఉంటుంది మరియు చిత్రం మరిన్ని కుదింపు కళాఖండాలను కలిగి ఉండవచ్చు.", "image_prefer_wide_gamut": "విస్తృత స్వరసప్తకానికి ప్రాధాన్యత ఇవ్వండి", "image_prefer_wide_gamut_setting_description": "థంబ్‌నెయిల్‌ల కోసం డిస్‌ప్లే P3ని ఉపయోగించండి. ఇది విస్తృత రంగుల ఖాళీలతో చిత్రాల వైబ్రెన్స్‌ను మెరుగ్గా భద్రపరుస్తుంది, అయితే పాత బ్రౌజర్ వెర్షన్‌తో పాత పరికరాల్లో చిత్రాలు విభిన్నంగా కనిపించవచ్చు. రంగు మార్పులను నివారించడానికి sRGB చిత్రాలు sRGB వలె ఉంచబడతాయి.", - "image_preview_format": "ప్రివ్యూ ఫార్మాట్", - "image_preview_resolution": "ప్రివ్యూ రిజల్యూషన్", - "image_preview_resolution_description": "ఒకే ఫోటోను చూసేటప్పుడు మరియు మెషిన్ లెర్నింగ్ కోసం ఉపయోగించబడుతుంది. అధిక రిజల్యూషన్‌లు మరింత వివరాలను భద్రపరుస్తాయి కానీ ఎన్‌కోడ్ చేయడానికి ఎక్కువ సమయం పడుతుంది, పెద్ద ఫైల్ పరిమాణాలను కలిగి ఉంటాయి మరియు యాప్ ప్రతిస్పందనను తగ్గించవచ్చు.", "image_quality": "నాణ్యత", - "image_quality_description": "1-100 నుండి చిత్ర నాణ్యత. నాణ్యత కోసం అధికమైనది ఉత్తమం కానీ పెద్ద ఫైల్‌లను ఉత్పత్తి చేస్తుంది, ఈ ఎంపిక ప్రివ్యూ మరియు థంబ్‌నెయిల్ చిత్రాలను ప్రభావితం చేస్తుంది.", "image_settings": "చిత్రం సెట్టింగ్‌లు", "image_settings_description": "రూపొందించబడిన చిత్రాల నాణ్యత మరియు రిజల్యూషన్‌ను నిర్వహించండి", - "image_thumbnail_format": "థంబ్‌నెయిల్ ఫార్మాట్", - "image_thumbnail_resolution": "థంబ్‌నెయిల్ రిజల్యూషన్", - "image_thumbnail_resolution_description": "ఫోటోల సమూహాలను వీక్షిస్తున్నప్పుడు ఉపయోగించబడుతుంది (ప్రధాన టైమ్‌లైన్, ఆల్బమ్ వీక్షణ మొదలైనవి). అధిక రిజల్యూషన్‌లు మరింత వివరాలను భద్రపరుస్తాయి కానీ ఎన్‌కోడ్ చేయడానికి ఎక్కువ సమయం పడుతుంది, పెద్ద ఫైల్ పరిమాణాలను కలిగి ఉంటాయి మరియు యాప్ ప్రతిస్పందనను తగ్గించవచ్చు.", "job_concurrency": "{job} సమ్మతి", "job_not_concurrency_safe": "ఈ ఉద్యోగం సమ్మతి-సురక్షితమైనది కాదు.", "job_settings": "ఉద్యోగ సెట్టింగ్‌లు", @@ -75,9 +68,6 @@ "jobs_delayed": "{jobCount, plural, other {# ఆలస్యమైంది}}", "jobs_failed": "{jobCount, plural, other {# విఫలమైంది}}", "library_created": "లైబ్రరీ సృష్టించబడింది: {library}", - "library_cron_expression": "క్రాన్ వ్యక్తీకరణ", - "library_cron_expression_description": "క్రాన్ ఆకృతిని ఉపయోగించి స్కానింగ్ విరామాన్ని సెట్ చేయండి. మరింత సమాచారం కోసం దయచేసి చూడండి ఉదా. Crontab Guru", - "library_cron_expression_presets": "క్రాన్ వ్యక్తీకరణ ప్రీసెట్లు", "library_deleted": "లైబ్రరీ తొలగించబడింది", "library_import_path_description": "దిగుమతి చేయడానికి ఫోల్డర్‌ను పేర్కొనండి. సబ్ ఫోల్డర్‌లతో సహా ఈ ఫోల్డర్ చిత్రాలు మరియు వీడియోల కోసం స్కాన్ చేయబడుతుంది.", "library_scanning": "ఆవర్తన స్కానింగ్", diff --git a/i18n/th.json b/i18n/th.json index e964bdd1980b7..0abeb549dc8d4 100644 --- a/i18n/th.json +++ b/i18n/th.json @@ -1,5 +1,5 @@ { - "about": "เกี่ยวกับ", + "about": "รีเฟรช", "account": "บัญชี", "account_settings": "การตั้งค่าบัญชี", "acknowledge": "รับทราบ", @@ -23,6 +23,7 @@ "add_to": "เพิ่มเข้า...", "add_to_album": "เพิ่มเข้าอัลบั้ม", "add_to_shared_album": "เพิ่มลงในอัลบั้มที่แชร์กัน", + "add_url": "เพิ่ม URL", "added_to_archive": "เพิ่มเข้าที่เก็บถาวร", "added_to_favorites": "เพิ่มเข้ารายการโปรด", "added_to_favorites_count": "{count, number} รูปถูกเพิ่มเข้ารายการโปรด", @@ -34,17 +35,24 @@ "authentication_settings_disable_all": "คุณแน่ใจว่าต้องการปิดวิธีการล็อกอินทั้งหมดหรือไม่? ล็อกอินจะถูกปิดทั้งหมด", "authentication_settings_reenable": "เพื่อเปิดใหม่ ให้ใช้คำสั่งเซิร์ฟเวอร์", "background_task_job": "งานเบื้องหลัง", + "backup_database": "สำรองฐานข้อมูล", + "backup_database_enable_description": "เปิดใช้งานการสำรองฐานข้อมูล", + "backup_keep_last_amount": "จำนวนข้อมูลสำรองก่อนหน้าที่ต้องเก็บไว้", + "backup_settings": "ตั้งค่ารการสำรองข้อมูล", + "backup_settings_description": "จัดการการตั้งค่าการสำรองฐานข้อมูล", "check_all": "ตรวจสอบทั้งหมด", "cleared_jobs": "เคลียร์งานสำหรับ: {job}", "config_set_by_file": "ปัจจุบันการกำหนดค่าถูกตั้งค่าโดยไฟล์กำหนดค่า", "confirm_delete_library": "คุณแน่ใจว่าอยากลบคลังภาพ {library} หรือไม่?", - "confirm_delete_library_assets": "คุณแน่ใจว่าอยากลบคลังภาพนี้หรือไม่? สี่อทั้งหมด {count} สี่อในคลังจะถูกลบออกจาก Immich โดยถาวร ไฟล์จะยังคงอยู่บนดิสก์", + "confirm_delete_library_assets": "คุณแน่ใจว่าอยากลบคลังภาพนี้หรือไม่? สี่อทั้งหมด {count, plural, one {# สื่อ} other {all # สื่อ}} สี่อในคลังจะถูกลบออกจาก Immich โดยถาวร ไฟล์จะยังคงอยู่บนดิสก์", "confirm_email_below": "เพื่อยืนยัน พิมพ์ \"{email}\" ข้างล่าง", "confirm_reprocess_all_faces": "คุณแน่ใจว่าคุณต้องการประมวลผลใบหน้าทั้งหมดใหม่? ชื่อคนจะถูกลบไปด้วย", "confirm_user_password_reset": "คุณแน่ใจว่าต้องการรีเซ็ตรหัสผ่านของ {user} หรือไม่?", - "crontab_guru": "Crontab Guru", + "create_job": "สร้างงาน", + "cron_expression": "รูปแบบ cron", + "cron_expression_description": "ตั้งช่วงเวลาในการสแกนโดยใช้รูปแบบ cron สำหรับข้อมูลเพิ่มเติมกรุณาอิง Crontab Guru", + "cron_expression_presets": "พรีเซ็ตรูปแบบ cron", "disable_login": "ปิดการล็อกอิน", - "disabled": "", "duplicate_detection_job_description": "ใช้ machine learning กับสี่อเพื่อตรวจจับรูปภาพที่คล้ายกัน โดยใช้การค้นหาอัจฉริยะ", "exclusion_pattern_description": "ข้อยกเว้นสามารถละเว้นไฟล์และโฟลเดอร์ขณะสแกนคลังภาพของคุณ มีประโยชน์เมื่อโฟลเดอร์มีไฟล์ที่ไม่อยากนำเข้า เช่นไฟล์ RAW", "external_library_created_at": "คลังภาพภายนอก (ถูกสร้างเมื่อ {date})", @@ -61,27 +69,23 @@ "image_prefer_embedded_preview_setting_description": "ใช้พรีวิวฝังตัวในรูปภาพ RAW ในการวิเคราะห์รูปภาพถ้ามี แต่คุณภาพรูปภาพขึ้นอยู่กับกล้อง และอาจจะมีสิ่งตกค้างจากการย่อขนาดไฟล์", "image_prefer_wide_gamut": "ใช้ช่วงสีกว้าง", "image_prefer_wide_gamut_setting_description": "ใช้การแสดงผลแบบ P3 สําหรับภาพตัวอย่าง คงความเข้มและความกว้างขอบเขตสี แต่ภาพอาจดูแตกต่างกันในอุปกรณ์เก่าที่มีเว็บเบราว์เซอร์รุ่นเก่า ภาพ sRGB จะถูกเก็บในรูปแบบ sRGB เพื่อลดการเคลื่อนของสี", - "image_preview_format": "รูปแบบพรีวิว", - "image_preview_resolution": "ความละเอียดพรีวิว", - "image_preview_resolution_description": "ใช้เมื่อดูรูปเดียวและสำหรับ machine learning ความละเอียดสูงสามารถเก็บรายละเอียดดีกว่าแต่ใช้เวลา encode นานกว่า ขนาดไฟล์ใหญ่กว่า และลดการตอบสนองของแอป", + "image_preview_quality_description": "คุณภาพการแสดงตัวอย่างตั้งแต่ 1-100 ยิ่งสูงก็ยิ่งดี แต่จะทำให้ไฟล์มีขนาดใหญ่ขึ้นและอาจทำให้แอปตอบสนองช้าลง การตั้งค่าต่ำอาจส่งผลต่อคุณภาพ Machine Learning", + "image_preview_title": "ตั้งค่าพรีวิว", "image_quality": "คุณภาพ", - "image_quality_description": "คุณภาพรูปจาก 1-100 ค่าสูงมีคุณภาพสูงกว่าแต่ขนาดไฟล์ใหญ่กว่า ตัวเลือกนี้ส่งผลต่อภาพพรีวิวและภาพขนาดย่อ", + "image_resolution": "ความละเอียด", + "image_resolution_description": "ความละเอียดสูกว่าสามารถเก็บรายละเอียดได้มากกว่าแต่ใช้เวลา encode นานกว่า ไฟล์ใหญ่กว่า และลดความตอบสนองของแอป", "image_settings": "การตั้งค่ารูปภาพ", "image_settings_description": "จัดการคุณภาพและความคมชัดของภาพที่สร้างขึ้น", - "image_thumbnail_format": "รูปแบบภาพย่อ", - "image_thumbnail_resolution": "ความละเอียดภาพย่อ", - "image_thumbnail_resolution_description": "ใช้เมื่อดูกลุ่มรูปภาพ (ไทม์ไลน์หลัก, หน้าอัลบั้ม, ฯลฯ) ความสะเอียดที่สูงกว่าจะเก็บรายละเอียดได้มากกว่าแต่ใช้เวลา encode นานกว่า ขนาดไฟล์ใหญ่กว่า และลดการตอบสนองของแอป", + "image_thumbnail_title": "ตั้งค่า Thumbnail", "job_concurrency": "{job} งานพร้อมกัน", + "job_created": "สร้างงานเรียบร้อย", "job_not_concurrency_safe": "งานนี้ทำงานพร้อมกันแบบปลอดภัยไม่ได้", "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_cron_expression": "รูปแบบ Cron", - "library_cron_expression_description": "ตั้งช่วงเวลาสแกนโดยใช้รูปแบบ cron สามารถดูข้อมูลเพิ่มเติมได้ที่ Crontab Guru", - "library_cron_expression_presets": "แม่แบบรูปแบบ Cron", "library_deleted": "คลังภาพถูกลบ", "library_import_path_description": "ระบุโฟลเดอร์เพื่อนําเข้า โฟลเดอร์นี้และโฟลเดอร์ย่อยจะถูกค้นหาภาพและวิดีโอ.", "library_scanning": "การสแกนเป็นระยะ", @@ -204,18 +208,18 @@ "refreshing_all_libraries": "รีเฟรชคลังภาพทั้งหมด", "registration": "ลงทะเบียนผู้จัดการ", "registration_description": "เนื่องจากคุณเป็นผู้ใช้งานแรกของระบบ คุณจะถูกแต่งตั้งเป็นผู้จัดการและรับผิดชอบงานบริหาร ผู้ใช้งานเพิ่มเติมจะถูกสร้างโดยคุณ", - "removing_deleted_files": "กำลังลบไฟล์ออฟไลน์", "repair_all": "ซ่อมแซมทั้งหมด", "repair_matched_items": "จับคู่ {count, plural, one {# รายการ} other {# รายการ}}", "repaired_items": "ซ่อมแซม {count, plural, one {# รายการ} other {# รายการ}}", "require_password_change_on_login": "บังคับผู้ใช้งานให้เปลี่ยนรหัสผ่านเมื่อเข้าสู่ระบบครั้งแรก", "reset_settings_to_default": "ตั้งค่าการตั้งค่าเป็นค่าเริ่มต้น", "reset_settings_to_recent_saved": "ตั้งค่าการตั้งค่าเป็นค่าล่าสุด", - "scanning_library_for_changed_files": "สแกนคลังภาพสำหรับไฟล์ที่เปลี่ยนไป", - "scanning_library_for_new_files": "สแกนคลังภาพสำหรับไฟล์ใหม่", + "scanning_library": "แสกนคลัง", + "search_jobs": "ค้นหางาน", "send_welcome_email": "ส่งอีเมลต้อนรับ", "server_external_domain_settings": "โดเมนภายนอก", "server_external_domain_settings_description": "โดเมนสำหรับลิงก์แชร์สาธารณะ แบบมี http(s)://", + "server_public_users": "ผู้ใช้สาธารณะ", "server_settings": "การตั้งค่าเซิร์ฟเวอร์", "server_settings_description": "จัดการการตั้งค่าเซิร์ฟเวอร์", "server_welcome_message": "ข้อความต้อนรับ", @@ -242,7 +246,6 @@ "these_files_matched_by_checksum": "ไฟล์เหล่านี้เหมือนกันจาก checksums", "thumbnail_generation_job": "สร้างภาพตัวอย่าง", "thumbnail_generation_job_description": "สร้างภาพตัวอย่างขนาดใหญ่ ขนาดเล็กและแบบเบลอ สําหรับแต่ละสื่อและบุคคล", - "transcode_policy_description": "", "transcoding_acceleration_api": "API เร่งความเร็วแปลงสื่อ", "transcoding_acceleration_api_description": "", "transcoding_acceleration_nvenc": "NVENC (ต้องมีการ์ดจอ NVIDIA)", @@ -284,15 +287,13 @@ "transcoding_settings": "", "transcoding_settings_description": "จัดการข้อมูลความคมชัดและแบบไฟล์วิดีโอ", "transcoding_target_resolution": "เป้าหมายความคมชัด", - "transcoding_target_resolution_description": "ความคมชัดที่สูงกว่าจะเก็บรายละเอียดดีกว่าแต่ใช้เวลาแปลงไฟล์นานกว่า ขนาดไฟล์ใหญ่กว่า และลดการตอบสนองของแอพ", + "transcoding_target_resolution_description": "ความคมชัดที่สูงกว่าจะเก็บรายละเอียดดีกว่าแต่ใช้เวลาแปลงไฟล์นานกว่า ขนาดไฟล์ใหญ่กว่า และลดการตอบสนองของแอป", "transcoding_temporal_aq": "", "transcoding_temporal_aq_description": "", "transcoding_threads": "เธรด", "transcoding_threads_description": "ค่ายิ่งเยอะจะแปลงไฟล์เร็วกว่า แต่จะเหลือพื้นที่ให้เซิร์ฟเวอร์ประมวลผลงานอื่นน้อยลงเมื่อทํางานนี้ ค่านี้ไม่ควรมากกว่าจํานวน CPU core จะประมวลผลเต็มที่เมื่อตั้งเป็น 0", "transcoding_tone_mapping": "การฉายโทนสี", "transcoding_tone_mapping_description": "", - "transcoding_tone_mapping_npl": "", - "transcoding_tone_mapping_npl_description": "", "transcoding_transcode_policy": "กฎการแปลงไฟล์", "transcoding_two_pass_encoding": "การแปลงไฟล์สองรอบ", "transcoding_two_pass_encoding_setting_description": "การแปลงไฟล์สองรอบจะช่วยให้ได้วิดีโอที่ดีขึ้น เมื่อเปิดใช้งาน bitrate สูงสุด (จำเป็นสำหรับไฟล์ H.264 และ HEVC) โหมดนี้จะใช้ช่วง bitrate ที่ขึ้นอยู่กับค่า bitrate สูงสุดและไม่สนใจ CRF สำหรับ VP9 สามารถใช้ค่า CRF ได้ถ้าปิดใช้งาน bitrate สูงสุด", @@ -336,11 +337,10 @@ "allow_edits": "อนุญาตให้แก้ไขได้", "api_key": "กุญแจ API", "api_keys": "กุญแจ API", - "app_settings": "การตั้งค่าแอพ", + "app_settings": "การตั้งค่าแอป", "appears_in": "อยู่ใน", "archive": "เก็บถาวร", "archive_or_unarchive_photo": "เก็บ/ไม่เก็บภาพถาวร", - "archived": "เก็บถาวร", "are_these_the_same_person": "เป็นคนเดียวกันหรือไม่?", "asset_offline": "สื่อออฟไลน์", "asset_skipped": "ข้ามแล้ว", @@ -358,10 +358,6 @@ "cancel_search": "ยกเลิกการค้นหา", "cannot_merge_people": "ไม่สามารถรวมกลุ่มคนได้", "cannot_update_the_description": "ไม่สามารถอัพเดทรายละเอียดได้", - "cant_apply_changes": "", - "cant_get_faces": "", - "cant_search_people": "", - "cant_search_places": "", "change_date": "เปลี่ยนวันที่", "change_expiration_time": "เปลี่ยนเวลาหมดอายุ", "change_location": "เปลี่ยนตําแหน่ง", @@ -441,13 +437,6 @@ "download": "ดาวน์โหลด", "downloading": "กำลังดาวน์โหลด", "duration": "ระยะเวลา", - "durations": { - "days": "", - "hours": "", - "minutes": "", - "months": "", - "years": "" - }, "edit_album": "แก้ไขอัลบั้ม", "edit_avatar": "แก้ไขตัวละคร", "edit_date": "แก้ไขวันที่", @@ -466,8 +455,6 @@ "edited": "แก้ไขแล้ว", "editor": "ผู้แก้ไข", "email": "อีเมล", - "empty": "", - "empty_album": "", "empty_trash": "ทิ้งจากถังขยะ", "enable": "เปิดใช้งาน", "enabled": "เปิดใช้งาน", @@ -482,8 +469,6 @@ "unable_to_change_album_user_role": "ไม่สามารถเปลี่ยนบทบาทผู้ใช้ในอัลบั้มได้", "unable_to_change_date": "ไม่สามารถเปลี่ยนวันที่ได้", "unable_to_change_location": "ไม่สามารถเปลี่ยนตําแหน่งได้", - "unable_to_check_item": "", - "unable_to_check_items": "", "unable_to_create_admin_account": "", "unable_to_create_library": "ไม่สามารถสร้างคลังภาพได้", "unable_to_create_user": "ไม่สามารถสร้างผู้ใช้ได้", @@ -501,11 +486,9 @@ "unable_to_play_video": "ไม่สามารถเล่นวิดีโอได้", "unable_to_refresh_user": "ไม่สามารถรีเฟรชผู้ใช้ได้", "unable_to_remove_album_users": "ไม่สามารถลบผู้ใช้ออกจากอัลบั้มได้", - "unable_to_remove_comment": "", "unable_to_remove_library": "ไม่สามารถลบคลังภาพได้", "unable_to_remove_partner": "ไม่สามารถลบคู่หูได้", "unable_to_remove_reaction": "ไม่สามารถลบ reaction ได้", - "unable_to_remove_user": "", "unable_to_repair_items": "ไม่สามารถซ่อมแซมรายการได้", "unable_to_reset_password": "ไม่สามารถตั้งรหัสผ่านใหม่ได้", "unable_to_resolve_duplicate": "ไม่สามารถแก้ไขของซ้ำได้", @@ -527,10 +510,6 @@ "unable_to_update_settings": "ไม่สามารถอัพเดทการตั้งค่าได้", "unable_to_update_user": "ไม่สามารถอัพเดทผู้ใช้ได้" }, - "every_day_at_onepm": "", - "every_night_at_midnight": "", - "every_night_at_twoam": "", - "every_six_hours": "", "exit_slideshow": "", "expand_all": "", "expire_after": "หมดอายุหลังจาก", @@ -538,28 +517,22 @@ "explore": "สํารวจ", "extension": "ส่วนต่อขยาย", "external_libraries": "ภายนอกคลังภาพ", - "failed_to_get_people": "", "favorite": "รายการโปรด", "favorite_or_unfavorite_photo": "โปรดหรือไม่โปรดภาพ", "favorites": "รายการโปรด", - "feature": "", "feature_photo_updated": "อัพเดทภาพเด่นแล้ว", - "featurecollection": "", "file_name": "", "file_name_or_extension": "", "filename": "ชื่อไฟล์", - "files": "", "filetype": "ชนิดไฟล์", "filter_people": "กรองผู้คน", "fix_incorrect_match": "", - "force_re-scan_library_files": "", "forward": "ไปข้างหน้า", "general": "ทั่วไป", "get_help": "", "getting_started": "", "go_back": "", "go_to_search": "", - "go_to_share_page": "", "group_albums_by": "", "has_quota": "", "hide_gallery": "ซ่อนคลังภาพ", @@ -568,7 +541,6 @@ "host": "โฮสต์", "hour": "ชั่วโมง", "image": "รูปภาพ", - "img": "", "immich_logo": "", "import_path": "นำเข้าพาธ", "in_archive": "ในที่เก็บถาวร", @@ -585,13 +557,13 @@ }, "invite_people": "เชิญผู้คน", "invite_to_album": "เชิญเข้าอัลบั้ม", - "job_settings_description": "", "jobs": "งาน", "keep": "เก็บ", "keyboard_shortcuts": "ปุ่มพิมพ์ลัด", "language": "ภาษา", "language_setting_description": "เลือกภาษาที่ต้องการ", "last_seen": "เห็นล่าสุด", + "latest_version": "เวอร์ชันล่าสุด", "leave": "ทิ้ง", "let_others_respond": "ให้คนอื่นตอบ", "level": "ระดับ", @@ -613,20 +585,26 @@ "make": "สร้าง", "manage_shared_links": "จัดการลิงก์ที่แชร์", "manage_sharing_with_partners": "จัดการการแชร์กับคู่หู", - "manage_the_app_settings": "จัดการการตั้งค่าแอพ", + "manage_the_app_settings": "จัดการการตั้งค่าแอป", "manage_your_account": "จัดการบัญชีของคุณ", "manage_your_api_keys": "จัดการกุญแจ API ของคุณ", "manage_your_devices": "จัดการอุปกรณ์ของคุณ", "manage_your_oauth_connection": "จัดการการเชื่อมต่อ OAuth ของคุณ", "map": "แผนที่", - "map_marker_with_image": "", + "map_marker_for_images": "หมุดแผนที่สำหรับรูปถ่ายที่ {city}, {country}", + "map_marker_with_image": "หมุดแผนที่กับรูปถ่าย", "map_settings": "การตั้งค่าแผนที่", + "matches": "ตรงกัน", "media_type": "ชนิดสื่อ", "memories": "ความทรงจำ", "memories_setting_description": "จัดการสิ่งที่คุณเห็นในความทรงจําของคุณ", + "memory": "ความทรงจำ", + "memory_lane_title": "ความทรงจำ {title}", "menu": "เมนู", "merge": "รวม", "merge_people": "รวมผู้คน", + "merge_people_limit": "คุณรวมใบหน้าได้มากถึง 5 รูปต่อครั้ง", + "merge_people_prompt": "คุณต้องการรวมคนพวกนี้หรือไม่ การกระทำนี้ไม่สามารถย้อนกลับได้", "merge_people_successfully": "รวมผู้คนเรียบร้อยแล้ว", "minimize": "ย่อลง", "minute": "นาที", @@ -639,18 +617,22 @@ "name": "ชื่อ", "name_or_nickname": "ชื่อหรือชื่อเล่น", "never": "ไม่เคย", + "new_album": "อัลบั้มใหม่", "new_api_key": "กุญแจ API ใหม่", "new_password": "รหัสผ่านใหม่", "new_person": "คนใหม่", "new_user_created": "สร้างผู้ใช้ใหม่แล้ว", + "new_version_available": "มีเวอร์ชันใหม่ให้ใช้งาน", "newest_first": "ใหม่สุดก่อน", "next": "ต่อไป", - "next_memory": "", + "next_memory": "ความทรงจำต่อไป", "no": "ไม่", - "no_albums_message": "", + "no_albums_message": "สร้างอัลบั้มเพื่อจัดการรูปภาพและวิดีโอของคุณ", + "no_albums_with_name_yet": "ดูเหมือนว่าไม่มีอัลบั้มไหนที่ใช้ชื่อนี้", "no_archived_assets_message": "จัดเก็บรูปภาพและวีดิโอถาวรเพื่อซ่อนจากมุมมองคุณ", "no_assets_message": "กดเพื่อใส่ภาพคุณภาพแรก", - "no_exif_info_available": "", + "no_duplicates_found": "ไม่พบรายการที่ซ้ำกัน", + "no_exif_info_available": "ไม่มีข้อมูล exif", "no_explore_results_message": "", "no_favorites_message": "เพิ่มรายการโปรดเพื่อค้นหาภาพและวิดีโอที่ดีที่สุดของคุณอย่างรวดเร็ว", "no_libraries_message": "สร้างคลังภาพภายนอกเพื่อดูภาพถ่ายและวิดีโอต่าง ๆ ของคุณ", @@ -659,35 +641,44 @@ "no_results": "ไม่มีผลลัพธ์", "no_shared_albums_message": "สร้างอัลบั้มเพื่อแชร์รูปภาพและวิดีโอกับคนในเครือข่ายของคุณ", "not_in_any_album": "ไม่อยู่ในอัลบั้มใด ๆ", + "note_unlimited_quota": "หมายเหตุ: กรอก 0 สำหรับโควตาแบบไม่จำกัด", "notes": "หมายเหตุ", "notification_toggle_setting_description": "เปิด/ปิด การแจ้งเตือนอีเมล", "notifications": "การแจ้งเตือน", "notifications_setting_description": "จัดการการแจ้งเตือน", "oauth": "OAuth", + "official_immich_resources": "แหล่งข้อมูล Immich อย่างเป็นทางการ", "offline": "ออฟไลน์", "ok": "โอเค", "oldest_first": "เก่าสุดก่อน", + "onboarding_welcome_user": "ยินดีต้อนรับ {user}", "online": "ออนไลน์", "only_favorites": "รายการโปรดเท่านั้น", - "only_refreshes_modified_files": "", + "open_in_openstreetmap": "เปิดใน OpenStreetMap", "open_the_search_filters": "เปิดตัวกรองการค้นหา", "options": "ตัวเลือก", + "or": "หรือ", "organize_your_library": "จัดเรียงคลังภาพของคุณ", + "original": "ต้นฉบับ", "other": "อื่น ๆ", - "other_devices": "", - "other_variables": "", + "other_devices": "เครื่องอื่น", + "other_variables": "ตัวแปรอื่น", "owned": "เป็นเจ้าของ", "owner": "เจ้าของ", + "partner": "คู่หู", + "partner_can_access": "{partner} สามารถเข้าถึง", + "partner_can_access_assets": "รูปภาพและวิดีโอทั้งหมดยกเว้นที่อยู่ในเก็บถาวรและถูกลบทิ้ง", + "partner_can_access_location": "ตำแหน่งที่รูปถูกถ่าย", "partner_sharing": "การแชร์แบบคู่หู", "partners": "คู่หู", "password": "รหัสผ่าน", - "password_does_not_match": "", - "password_required": "", - "password_reset_success": "", + "password_does_not_match": "รหัสผ่านไม่ตรงกัน", + "password_required": "จำเป็นต้องมีรหัสผ่าน", + "password_reset_success": "รีเซ็ตรหัสผ่านสำเร็จ", "past_durations": { - "days": "", - "hours": "", - "years": "" + "days": "{days, plural, one {วัน} other {# วัน}}ที่ผ่านมา", + "hours": "{hours, plural, one {ชั่วโมง} other {# ชั่วโมง}}ที่ผ่านมา", + "years": "{years, plural, one {ปี} other {# ปี}}ที่ผ่านมา" }, "path": "", "pattern": "", @@ -697,7 +688,6 @@ "pending": "กำลังรอ", "people": "ผู้คน", "people_sidebar_description": "แสดงลิงก์ไปยังผู้คนในแถบด้านข้าง", - "perform_library_tasks": "", "permanent_deletion_warning": "แจ้งเตือนการลบถาวร", "permanent_deletion_warning_setting_description": "เตือนเมื่อจะลบสื่อถาวร", "permanently_delete": "ลบถาวร", @@ -711,7 +701,6 @@ "play_memories": "เล่นความทรงจํา", "play_motion_photo": "เล่นภาพวัตถุเคลื่อนไหว", "play_or_pause_video": "เล่นหรือหยุดวิดีโอ", - "point": "", "port": "พอร์ต", "preset": "", "preview": "ตัวอย่าง", @@ -721,8 +710,6 @@ "primary": "หลัก", "profile_picture_set": "ตั้งภาพโปรไฟล์แล้ว", "public_share": "แชร์แบบสาธารณะ", - "range": "", - "raw": "", "reaction_options": "ตัวเลือก reaction", "read_changelog": "อ่านบันทึกการเปลี่ยนแปลง", "recent": "ล่าสุด", @@ -742,7 +729,6 @@ "reset": "รีเซ็ต", "reset_password": "ตั้งค่ารหัสผ่านใหม่", "reset_people_visibility": "ปรับการมองเห็นใหม่", - "reset_settings_to_default": "", "restore": "เรียกคืน", "restore_user": "เรียกคืนผู้ใช้", "retry_upload": "ลองอัพโหลดใหม่", @@ -753,8 +739,6 @@ "saved_settings": "การตั้งค่าที่บันทึกไว้", "say_something": "พูดอะไรสักอย่าง", "scan_all_libraries": "สแกนคลังภาพทั้งหมด", - "scan_all_library_files": "", - "scan_new_library_files": "", "scan_settings": "ตั้งค่าการสแกน", "search": "ค้นหา", "search_albums": "", @@ -782,7 +766,6 @@ "select_photos": "เลือกรูปภาพ", "selected": "เลือก", "send_message": "", - "server": "เซิร์ฟเวอร์", "server_stats": "", "set": "", "set_as_album_cover": "", @@ -842,18 +825,15 @@ "timezone": "เขตเวลา", "toggle_settings": "สลับการตั้งค่า", "toggle_theme": "สลับธีม", - "toggle_visibility": "", "total_usage": "การใช้งานรวม", "trash": "ขยะ", "trash_all": "ทิ้งทั้งหมด", "trash_no_results_message": "รูปและวีดีโอที่ถูกทิ้งจะมาโผล่ที่นี่", "type": "ประเภท", "unarchive": "นำออกจากที่เก็บถาวร", - "unarchived": "", "unfavorite": "นำออกจากรายการโปรด", "unhide_person": "ยกเลิกซ่อนบุคคล", "unknown": "ไม่ทราบ", - "unknown_album": "", "unknown_year": "ไม่ทราบปี", "unlink_oauth": "", "unlinked_oauth_account": "", @@ -868,6 +848,8 @@ "user": "ผู้ใช้", "user_id": "ไอดีผู้ใช้", "user_usage_detail": "รายละเอียดการใช้งานของผู้ใช้", + "user_usage_stats": "สถิติการใช้งานบัญชี", + "user_usage_stats_description": "ดูสถิติการใช้งานบัญชี", "username": "ชื่อผู้ใช้", "users": "ผู้ใช้", "utilities": "", @@ -883,7 +865,6 @@ "view_links": "ดูลิงก์", "view_next_asset": "ดูสื่อถัดไป", "view_previous_asset": "ดูสื่อก่อนหน้า", - "viewer": "", "waiting": "กำลังรอ", "week": "สัปดาห์", "welcome": "ยินดีต้อนรับ", diff --git a/i18n/tr.json b/i18n/tr.json index b2f0559ce89a3..b1e918afef75b 100644 --- a/i18n/tr.json +++ b/i18n/tr.json @@ -1,5 +1,5 @@ { - "about": "Hakkında", + "about": "Yenile", "account": "Hesap", "account_settings": "Hesap Ayarları", "acknowledge": "Onayla", @@ -23,6 +23,7 @@ "add_to": "Şuraya ekle...", "add_to_album": "Albüme ekle", "add_to_shared_album": "Paylaşılan albüme 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", @@ -34,6 +35,11 @@ "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": "Yedek Veritabanı", + "backup_database_enable_description": "Veritabanı Yedeklerinş Etkinleştir", + "backup_keep_last_amount": "Önceki yedeklemeden saklanacak miktar", + "backup_settings": "Yedekleme Ayarları", + "backup_settings_description": "Veritabanı Yedekleme Ayarlarını Yönet", "check_all": "Hepsini Kontrol Et", "cleared_jobs": "{job} için işler temizlendi", "config_set_by_file": "Ayarlar şuanda config dosyası tarafından ayarlanmıştır", @@ -43,7 +49,9 @@ "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?", "create_job": "Görev oluştur", - "crontab_guru": "", + "cron_expression": "Cron İfadesi", + "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ı", "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.", @@ -62,22 +70,15 @@ "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_format": "Biçimi önizle", "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_resolution": "Çözünürlüğü önizle", - "image_preview_resolution_description": "Makine öğrenmesi ve tekil fotoğrafları görüntülerken kullanılır. Yüksek çözünürlük daha fazla detayı korur fakat işlemesi daha uzun sürer, daha fazla boyuta sahip olur ve uygulamanın performansını düşürebilir.", "image_preview_title": "Ön izleme Ayarları", "image_quality": "Kalite", - "image_quality_description": "Fotoğraf kalitesi 1-100. Yüksek değer, daha yüksek kalite demektir fakat boyutu arttırır. Bu özellik Önizlemeyi etkiler.", "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_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_format": "Önizleme biçimi", "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.", - "image_thumbnail_resolution": "Önizleme çözünürlüğü", - "image_thumbnail_resolution_description": "Fotoğrafların grup hâlinde gösteriminde kullanılır (ana zaman akışı, albümler, vb.). Daha yüksek çözünürlükler daha fazla detayı koruyabilir ama kodlamaları daha uzun sürer, daha fazla yer kaplarlar, ve uygulamanın akıcılığını azaltabilirler.", "image_thumbnail_title": "Küçük Fotoğraf Ayarları", "job_concurrency": "{job} eş zamanlılık", "job_created": "Görev oluşturuldu", @@ -88,9 +89,6 @@ "jobs_delayed": "{jobCount, plural, other {# gecikmeli}}", "jobs_failed": "{jobCount, plural, other {# Başarısız}}", "library_created": "{library} kütüphanesi oluşturuldu", - "library_cron_expression": "Cron zamanlaması", - "library_cron_expression_description": "Cron zamanlaması kullanarak tarama aralığını belirleyin. Daha fazla bilgi için Crontab Guru", - "library_cron_expression_presets": "Cron zamanlaması ön ayarları", "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", @@ -183,13 +181,13 @@ "oauth_auto_register": "Otomatik kayıt", "oauth_auto_register_description": "OAuth ile giriş yapan yeni kullanıcıları otomatik kaydet", "oauth_button_text": "Buton yazısı", - "oauth_client_id": "Kullanıcı ID", + "oauth_client_id": "İstemci ID", "oauth_client_secret": "Gizli İstemci Anahtarı", "oauth_enable_description": "OAuth ile giriş yap", "oauth_issuer_url": "Yayınlayıcı URL", "oauth_mobile_redirect_uri": "Mobil yönlendirme URL'si", "oauth_mobile_redirect_uri_override": "Mobilde zorla kullanılacak Yönlendirme Adresi", - "oauth_mobile_redirect_uri_override_description": "OAuth sağlayıcısı '{callback}'gibi bir mobil URI'ye izin vermediğinde etkinleştir.", + "oauth_mobile_redirect_uri_override_description": "Mobil URI'ye izin vermeyen OAuth sağlayıcısı olduğunda etkinleştir, örneğin '{callback}'", "oauth_profile_signing_algorithm": "Profil imzalama algoritması", "oauth_profile_signing_algorithm_description": "Kullanıcının profilini imzalarken kullanılacak güvenlik algoritması.", "oauth_scope": "Kapsam", @@ -214,20 +212,19 @@ "refreshing_all_libraries": "Tüm kütüphaneler yenileniyor", "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.", - "removing_deleted_files": "Çevrimdışı dosyalar kaldırılıyor", "repair_all": "Tümünü onar", - "repair_matched_items": "Eşleşen {sayı, çoğul, bir {# öğe} diğer {# öğeler}}", + "repair_matched_items": "{count, plural, one {# öğe eşleşti} other {# öğeler eşleşti}}", "repaired_items": "{count, plural, one {# item} other {# items}} tamir edildi", "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", "reset_settings_to_recent_saved": "Ayarları kaydedilmiş önceki ayarlara döndür", "scanning_library": "Kütüphaneyi tarama", - "scanning_library_for_changed_files": "Değişen dosyalar için kütüphane taranıyor", - "scanning_library_for_new_files": "Yeni dosyalar için kütüphane taranıyor", "search_jobs": "Görevleri Ara...", "send_welcome_email": "Hoş geldin e-postası gönder", "server_external_domain_settings": "Dış domain", "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_description": "Sunucu ayarlarını yönet", "server_welcome_message": "Hoş geldin mesajı", @@ -245,7 +242,7 @@ "storage_template_migration_description": "Geçerli {template} ayarlarını daha önce yüklenmiş olan varlıklara uygula", "storage_template_migration_info": "Ş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_job": "Depolama Adreslerini Değiştirme Görevi", - "storage_template_more_details": "Bu özellik hakkında daha fazla bilgi edinmek için Depolama Şablonu linkini, bunun neticesi için ise Netice linkini ziyaret edin", + "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": "Bu özellik açıldığında, dosyaları kullanıcı için belirlenen depolama adresi taslağına göre otomatik olarak düzenler. Bu özellik bazen sorun çıkarabildiğini için kapalı gelmektedir. Daha fazla bilgi için dokümantasyona bakabilirsiniz.", "storage_template_path_length": "Tahmini dosya adresi uzunluğu: {length, number}/{limit, number}", "storage_template_settings": "Depolama Şablonu", @@ -253,6 +250,14 @@ "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", + "template_email_available_tags": "Şablonunuzda şu değişkenler kullanılabilir: {tags}", + "template_email_if_empty": "Şablon boş ise, varsayılan e-posta kullanılacak.", + "template_email_preview": "Ön izleme", + "template_email_settings": "Eposta Taslakları", + "template_email_settings_description": "Özel e-posta bildirim şablonlarını yönet", + "template_email_update_album": "Albüm Şablonunu Güncelle", + "template_settings": "Bildirim Şablonları", + "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ı", @@ -311,8 +316,6 @@ "transcoding_threads_description": "Daha yüksek değerler daha hızlı kodlamaya yol açar, ancak sunucunun etkin durumdayken diğer görevleri işlemesi için daha az alan bırakır. Bu değer İşlemci çekirdeği sayısından fazla olmamalıdır. 0'a ayarlanırsa kullanımı en üst düzeye çıkarır.", "transcoding_tone_mapping": "Ton-haritalama", "transcoding_tone_mapping_description": "HDR videoların SDR'ye dönüştürülürken görünümünü korumayı amaçlar. Her algoritma renk, detay ve parlaklık için farklı dengeleme yapar. Hable detayları korur, Mobius renkleri korur ve Reinhard parlaklığı korur.", - "transcoding_tone_mapping_npl": "Ton eşleme NPL", - "transcoding_tone_mapping_npl_description": "Renkler, bu parlaklıkta bir ekran için normal görünecek şekilde ayarlanacaktır. Karşıt olarak, daha düşük değerler videonun parlaklığını artırır ve tersi de geçerlidir çünkü ekranın parlaklığını telafi eder. 0 bu değeri otomatik olarak ayarlar.", "transcoding_transcode_policy": "Dönüştürme (çevirme) politikası", "transcoding_transcode_policy_description": "Bir videonun ne zaman kod dönüştürülmesi gerektiğine ilişkin ilke. Dönüştürme devre dışı bırakılmadığı sürece HDR videolar her zaman dönüştürülür.", "transcoding_two_pass_encoding": "İki geçişli kodlama", @@ -393,7 +396,6 @@ "archive_or_unarchive_photo": "Fotoğrafı arşivle/arşivden çıkar", "archive_size": "Arşiv boyutu", "archive_size_description": "İndirmeler için arşiv boyutunu yapılandırın (GiB cinsinden)", - "archived": "", "archived_count": "{count, plural, other {# arşivlendi}}", "are_these_the_same_person": "Bunlar aynı kişi mi?", "are_you_sure_to_do_this": "Bunu yapmak istediğinize emin misiniz?", @@ -413,8 +415,8 @@ "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_added_to_name_count": "{count, plural, one {# varlık} other {# varlık}} {hasName, select, true {{name}} other {yeni albüm}} içine eklendi", - "assets_count": "{say, çoğul, bir {#varlık} diğer {#varlık}}", - "assets_moved_to_trash_count": "{say, çoğul, bir {#varlık} diğer {#varlık}} çöp kutusuna taşındı", + "assets_count": "{count, plural, one {# varlık} other {# varlıklar}}", + "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_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.", @@ -443,10 +445,6 @@ "cannot_merge_people": "Kişiler birleştirilemiyor", "cannot_undo_this_action": "Bu işlem geri alınamaz!", "cannot_update_the_description": "Açıklama güncellenemiyor", - "cant_apply_changes": "", - "cant_get_faces": "", - "cant_search_people": "", - "cant_search_places": "", "change_date": "Tarihi değiştir", "change_expiration_time": "Son kullanma süresini değiştir", "change_location": "Konumu değiştir", @@ -478,6 +476,7 @@ "confirm": "Onayla", "confirm_admin_password": "Yönetici Şifresini Onayla", "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_password": "Şifreyi onayla", "contain": "İçermek", "context": "Bağlam", @@ -527,6 +526,7 @@ "delete_key": "Anahtarı sil", "delete_library": "Kütüphaneyi sil", "delete_link": "Bağlantıyı sil", + "delete_others": "Diğerlerini sil", "delete_shared_link": "Paylaşılmış linki sil", "delete_tag": "Etiketi sil", "delete_tag_confirmation_prompt": "{tagName} etiketini silmek istediğinizden emin misiniz?", @@ -560,13 +560,6 @@ "duplicates": "Kopyalar", "duplicates_description": "Her grubu çözmek için, varsa hangilerinin kopya olduğunu belirtin", "duration": "Süre", - "durations": { - "days": "", - "hours": "", - "minutes": "", - "months": "", - "years": "" - }, "edit": "Düzenle", "edit_album": "Albümü düzenle", "edit_avatar": "Avatarı Düzenle", @@ -591,7 +584,6 @@ "editor_crop_tool_h2_aspect_ratios": "En boy oranları", "editor_crop_tool_h2_rotation": "Rotasyon", "email": "E-posta", - "empty_album": "", "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!", "enable": "Etkinleştir", @@ -604,242 +596,310 @@ "cannot_navigate_next_asset": "Sonraki varlığa geçiş yapılamıyor", "cannot_navigate_previous_asset": "Önceki varlığa geçiş yapılamıyor", "cant_apply_changes": "Değişiklikler uygulanamıyor", - "cant_change_activity": "Etkinliği {etkinleştiremiyor, seçemiyor, doğru {devre dışı bırakamıyor} diğer durumda {etkinleştiremiyor}}", + "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} varlığın metadatası (meta verisi) değiştirilemiyor", + "cant_change_metadata_assets_count": "{count, plural, one {# varlığın} other {# varlıkların}} 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", "cleared_jobs": "İşler temizlendi: {job}", - "exclusion_pattern_already_exists": "", - "failed_job_command": "", + "error_adding_assets_to_album": "Albüme varlık 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ı", + "exclusion_pattern_already_exists": "Bu dışlama modeli halihazırda mevcut.", + "failed_job_command": "{command} komutu iş: {job} için tamamlanamadı", "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_people": "Kişiler yüklenemedi", "failed_to_remove_product_key": "Ürün anahtarı kaldırılamadı", - "import_path_already_exists": "", + "failed_to_stack_assets": "Varlıklar yığınlanamadı", + "failed_to_unstack_assets": "Varlıkların yığını kaldırılamadı", + "import_path_already_exists": "Bu içe aktarma yolu halihazırda mevcut.", "incorrect_email_or_password": "Yanlış e-posta veya şifre", - "paths_validation_failed": "", + "paths_validation_failed": "{paths, plural, one {# Yol} other {# Yollar}} doğrulanamadı", "profile_picture_transparent_pixels": "Profil resimleri şeffaf piksele sahip olamaz. Lütfen resme yakınlaştırın ve/veya resmi hareket ettirin.", - "quota_higher_than_disk_size": "", - "repair_unable_to_check_items": "", + "quota_higher_than_disk_size": "Disk boyutundan daha yüksek bir kota belirlediniz", + "repair_unable_to_check_items": "{count, select, one {Öğe} other {Öğeler}} kontrol edilemedi", "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_comment": "Yorum eklenemiyor", - "unable_to_add_exclusion_pattern": "", - "unable_to_add_import_path": "", - "unable_to_add_partners": "", - "unable_to_change_album_user_role": "", + "unable_to_add_exclusion_pattern": "Hariç tutma modeli eklenemiyor", + "unable_to_add_import_path": "İçe aktarma yolu eklenemiyor", + "unable_to_add_partners": "Ortaklar eklenemiyor", + "unable_to_add_remove_archive": "Arşive {archived, select, true {dosyayı kaldır} other {dosya ekle}} işlemi yapılamıyor", + "unable_to_add_remove_favorites": "Favorilere {favorite, select, true {dosya ekle} other {dosyayı kaldır}} işlemi yapılamıyor", + "unable_to_archive_unarchive": "{archived, select, true {Arşivleme} other {Arşivden çıkarma}} işlemi yapılamıyor", + "unable_to_change_album_user_role": "Albüm kullanıcı rolü değiştirilemiyor", "unable_to_change_date": "Tarih değiştirilemiyor", - "unable_to_change_location": "", - "unable_to_change_password": "", + "unable_to_change_favorite": "Favori durumu değiştirilemiyor", + "unable_to_change_location": "Konum değiştirilemiyor", + "unable_to_change_password": "Şifre değiştirilemiyor", + "unable_to_change_visibility": "{count, plural, one {# kişi} other {# kişi}} için görünürlük değiştirilemedi", + "unable_to_complete_oauth_login": "OAuth giriş işlemi tamamlanamadı", "unable_to_connect": "Bağlanılamıyor", "unable_to_connect_to_server": "Sunucuya bağlanılamıyor", "unable_to_copy_to_clipboard": "Panoya kopyalanamıyor, sayfaya https üzerinden eriştiğinizden emin olun", "unable_to_create_admin_account": "Yönetici hesabı oluşturulamıyor", "unable_to_create_api_key": "Yeni API anahtarı oluşturulamıyor", - "unable_to_create_library": "", + "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": "", - "unable_to_delete_exclusion_pattern": "", - "unable_to_delete_import_path": "", + "unable_to_delete_asset": "Varlık silinemiyor", + "unable_to_delete_assets": "Varlıklar 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", "unable_to_delete_user": "Kullanıcı silinemiyor", "unable_to_download_files": "Dosyalar indirilemiyor", - "unable_to_edit_exclusion_pattern": "", - "unable_to_edit_import_path": "", + "unable_to_edit_exclusion_pattern": "Hariç tutma deseni düzenlenemiyor", + "unable_to_edit_import_path": "İçe aktarma yolu düzenlenemiyor", "unable_to_empty_trash": "Çöp boşaltılamıyor", "unable_to_enter_fullscreen": "Tam ekran yapılamıyor", "unable_to_exit_fullscreen": "Tam ekrandan çıkılamıyor", "unable_to_get_comments_number": "Yorum sayısı alınamıyor", "unable_to_get_shared_link": "Paylaşılan bağlantı alınamadı", "unable_to_hide_person": "Kişi gizlenemiyor", - "unable_to_link_oauth_account": "", - "unable_to_load_album": "", - "unable_to_load_asset_activity": "", - "unable_to_load_items": "", - "unable_to_load_liked_status": "", - "unable_to_play_video": "", - "unable_to_refresh_user": "", - "unable_to_remove_album_users": "", - "unable_to_remove_api_key": "", - "unable_to_remove_deleted_assets": "", + "unable_to_link_motion_video": "Hareket videosu bağlanamıyor", + "unable_to_link_oauth_account": "OAuth hesabı bağlanamıyor", + "unable_to_load_album": "Albüm yüklenemiyor", + "unable_to_load_asset_activity": "Varlık aktivitesi yüklenemiyor", + "unable_to_load_items": "Öğeler yüklenemiyor", + "unable_to_load_liked_status": "Beğenilen durum yüklenemiyor", + "unable_to_log_out_all_devices": "Tüm cihazlardan çıkış yapılamıyor", + "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_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_deleted_assets": "Silinmiş varlıklar kaldırılamıyor", "unable_to_remove_library": "Kütüphane kaldırılamadı", - "unable_to_remove_partner": "", - "unable_to_remove_reaction": "", + "unable_to_remove_partner": "Ortak kaldırılamıyor", + "unable_to_remove_reaction": "Reaksiyon kaldırılamıyor", "unable_to_repair_items": "Ögeler onarılamadı", - "unable_to_reset_password": "", - "unable_to_resolve_duplicate": "", - "unable_to_restore_assets": "", - "unable_to_restore_trash": "", - "unable_to_restore_user": "", + "unable_to_reset_password": "Şifre sıfırlanamıyor", + "unable_to_resolve_duplicate": "Çiftler çözümlenemiyor", + "unable_to_restore_assets": "Varlıklar 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", - "unable_to_save_api_key": "", + "unable_to_save_api_key": "API anahtarı kaydedilemiyor", "unable_to_save_date_of_birth": "Doğum günü kaydedilemiyor", "unable_to_save_name": "İsim kaydedilemyor", "unable_to_save_profile": "Profil kaydedilemiyor", "unable_to_save_settings": "Ayarlar kaydedilemiyor", "unable_to_scan_libraries": "Kütüphaneler taranamıyor", "unable_to_scan_library": "Kütüphane taranamıyor", + "unable_to_set_feature_photo": "Özellikli fotoğraf ayarlanamıyor", "unable_to_set_profile_picture": "Profil resmi ayarlanamıyor", - "unable_to_submit_job": "", - "unable_to_trash_asset": "", - "unable_to_unlink_account": "", + "unable_to_submit_job": "Görev gönderilemiyor", + "unable_to_trash_asset": "Varlık çö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", "unable_to_update_album_info": "Albüm açıklaması güncellenemiyor", "unable_to_update_library": "Kütüphane güncellenemiyor", "unable_to_update_location": "Konum güncellenemiyor", "unable_to_update_settings": "Ayarlar güncellenemiyor", - "unable_to_update_timeline_display_status": "", - "unable_to_update_user": "", + "unable_to_update_timeline_display_status": "Zaman çizelgesi görüntüleme durumu güncellenemiyor", + "unable_to_update_user": "Kullanıcı güncellenemiyor", "unable_to_upload_file": "Dosya yüklenemiyor" }, + "exif": "EXIF", "exit_slideshow": "Slayt gösterisinden çık", - "expand_all": "", - "expire_after": "", - "expired": "", + "expand_all": "Hepsini genişlet", + "expire_after": "Sonlanma süresi", + "expired": "Süresi dolmuş", + "expires_date": "{date} tarihinde sona eriyor", "explore": "Keşfet", + "explorer": "Geçmiş", "export": "Dışa Aktar", "export_as_json": "JSON olarak Dışa Aktar", "extension": "Uzantı", - "external": "", - "external_libraries": "", - "failed_to_get_people": "", - "favorite": "", - "favorite_or_unfavorite_photo": "", + "external": "Harici", + "external_libraries": "Harici kütüphaneler", + "face_unassigned": "Yüz atanmadı", + "failed_to_load_assets": "Varlıklar yüklenemedi", + "favorite": "Favori", + "favorite_or_unfavorite_photo": "Favoriye ekle veya çıkar", "favorites": "Favoriler", - "feature_photo_updated": "", + "feature_photo_updated": "Özellikli fotoğraf güncellendi", + "features": "Özellikler", + "features_setting_description": "Uygulamanın özelliklerini yönet", "file_name": "Dosya adı", "file_name_or_extension": "Dosya adı veya uzantı", - "filename": "", - "filetype": "", - "filter_people": "", - "find_them_fast": "", + "filename": "Dosya adı", + "filetype": "Dosya tipi", + "filter_people": "Kişileri filtrele", + "find_them_fast": "Adlarına göre hızlıca bul", "fix_incorrect_match": "Yanlış eşleştirmeyi düzelt", - "force_re-scan_library_files": "Tüm Kütüphane Dosyalarını Yeniden Taramaya Zorla", - "forward": "", + "folders": "Klasörler", + "folders_feature_description": "Dosya sistemindeki fotoğraf ve videoları klasör görünümüyle keşfedin", + "forward": "İleri", "general": "Genel", "get_help": "Yardım Al", - "getting_started": "", + "getting_started": "Başlarken", "go_back": "Geri git", - "go_to_search": "", - "go_to_share_page": "Paylaşma ekranına git", - "group_albums_by": "", + "go_to_search": "Aramaya git", + "group_albums_by": "Albümleri gruplandır...", + "group_no": "Gruplama yok", + "group_owner": "Sahibe göre gruplandır", "group_year": "Yıla göre grupla", - "has_quota": "", + "has_quota": "Kota var", "hi_user": "Merhaba {name} {email}", "hide_all_people": "Tüm kişileri gizle", - "hide_gallery": "", + "hide_gallery": "Galeriyi gizle", + "hide_named_person": "{name} adlı kişiyi gizle", "hide_password": "Şifreyi gizle", - "hide_person": "", + "hide_person": "Kişiyi gizle", "hide_unnamed_people": "İsimsiz kişileri gizle", - "host": "", + "host": "Host", "hour": "Saat", - "image": "", - "immich_logo": "", - "immich_web_interface": "", + "image": "Resim", + "image_alt_text_date": "{isVideo, select, true {Video} other {Fotoğraf}} {date} tarihinde çekildi", + "image_alt_text_date_1_person": "{isVideo, select, true {Video} other {Fotoğraf}} {person1} ile {date} tarihinde çekildi", + "image_alt_text_date_2_people": "{isVideo, select, true {Video} other {Fotoğraf}} {person1} ve {person2} ile {date} tarihinde çekildi", + "image_alt_text_date_3_people": "{isVideo, select, true {Video} other {Fotoğraf}} {person1}, {person2} ve {person3} ile {date} tarihinde çekildi", + "image_alt_text_date_4_or_more_people": "{isVideo, select, true {Video} other {Fotoğraf}} {person1}, {person2} ve diğer {additionalCount, number} kişi ile {date} tarihinde çekildi", + "image_alt_text_date_place": "{isVideo, select, true {Video} other {Fotoğraf}} {city}, {country} şehrinde {date} tarihinde çekildi", + "image_alt_text_date_place_1_person": "{isVideo, select, true {Video} other {Fotoğraf}} {city}, {country} şehrinde {person1} ile {date} tarihinde çekildi", + "image_alt_text_date_place_2_people": "{isVideo, select, true {Video} other {Fotoğraf}} {city}, {country} şehrinde {person1} ve {person2} ile {date} tarihinde çekildi", + "image_alt_text_date_place_3_people": "{isVideo, select, true {Video} other {Fotoğraf}} {city}, {country} şehrinde {person1}, {person2} ve {person3} ile {date} tarihinde çekildi", + "image_alt_text_date_place_4_or_more_people": "{isVideo, select, true {Video} other {Fotoğraf}} {city}, {country} şehrinde {person1}, {person2} ve diğer {additionalCount, number} kişi ile {date} tarihinde çekildi", + "immich_logo": "Immich Logosu", + "immich_web_interface": "Immich Web Arayüzü", "import_from_json": "JSON'dan İçe Aktar", - "import_path": "", + "import_path": "İçe aktarma yolu", + "in_albums": "{count, plural, one {# Albüm} other {# Albümde}}", "in_archive": "Arşivde", "include_archived": "Arşivlenenleri dahil et", "include_shared_albums": "Paylaşılmış albümleri dahil et", - "include_shared_partner_assets": "", - "individual_share": "", + "include_shared_partner_assets": "Paylaşılan ortak varlıkları dahil et", + "individual_share": "Bireysel paylaşım", "info": "Bilgi", "interval": { - "day_at_onepm": "", - "hours": "", + "day_at_onepm": "Her gün saat 13:00'te", + "hours": "{hours, plural, one {Her saat} other {Her {hours, number} saatte}}", "night_at_midnight": "Her akşam geceyarısında", - "night_at_twoam": "" + "night_at_twoam": "Her gün gece 2:00'de" }, "invite_people": "Kişileri Davet Et", "invite_to_album": "Albüme davet et", - "jobs": "", - "keep": "", + "items_count": "{count, plural, one {# Öğe} other {# Öğe}}", + "jobs": "Görevler", + "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", "keyboard_shortcuts": "Klavye kısayolları", "language": "Dil", "language_setting_description": "Tercih ettiğiniz dili seçiniz", "last_seen": "Son görülme", "latest_version": "En son versiyon", - "leave": "", - "let_others_respond": "", - "level": "", + "latitude": "Enlem", + "leave": "Ayrıl", + "let_others_respond": "Diğerlerinin yanıt vermesine izin ver", + "level": "Seviye", "library": "Kütüphane", "library_options": "Kütüphane ayarları", - "light": "", - "link_options": "", - "link_to_oauth": "", - "linked_oauth_account": "", - "list": "", - "loading": "", - "loading_search_results_failed": "", + "light": "Açık", + "like_deleted": "Beğeni silindi", + "link_motion_video": "Hareket videosunu bağla", + "link_options": "Bağlantı seçenekleri", + "link_to_oauth": "OAuth'a bağla", + "linked_oauth_account": "Bağlı OAuth hesabı", + "list": "Liste", + "loading": "Yükleniyor", + "loading_search_results_failed": "Arama sonuçları yüklenemedi", "log_out": "Oturumu kapat", "log_out_all_devices": "Tüm Cihazlarda Oturumu Kapat", "logged_out_all_devices": "Tüm cihazlarda oturum kapatıldı", "logged_out_device": "Oturum kapatılmış cihaz", - "login_has_been_disabled": "", + "login": "Giriş yap", + "login_has_been_disabled": "Giriş devre dışı bırakıldı.", "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?", - "look": "", - "loop_videos": "", - "loop_videos_description": "", - "make": "", - "manage_shared_links": "", - "manage_sharing_with_partners": "", - "manage_the_app_settings": "", + "longitude": "Boylam", + "look": "Görünüm", + "loop_videos": "Videoları döngüye al", + "loop_videos_description": "Ayrıntı görünümünde videoların otomatik döngüye alınmasını etkinleştir.", + "main_branch_warning": "Geliştirme sürümü kullanıyorsunuz. Yayınlanan bir sürüm kullanmanızı önemle tavsiye ederiz!", + "make": "Marka", + "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", "manage_your_account": "Hesabınızı yönetin", - "manage_your_api_keys": "", - "manage_your_devices": "", - "manage_your_oauth_connection": "", + "manage_your_api_keys": "API anahtarlarınızı yönetin", + "manage_your_devices": "Cihazlarınızı yönetin", + "manage_your_oauth_connection": "OAuth bağlantınızı yönetin", "map": "Harita", - "map_marker_with_image": "", + "map_marker_for_images": "{city}, {country} şehrinde çekilen fotoğraflar için harita işaretleyicisi", + "map_marker_with_image": "Resimli harita işaretleyicisi", "map_settings": "Harita ayarları", "matches": "Eşleşenler", - "media_type": "", + "media_type": "Medya türü", "memories": "Anılar", - "memories_setting_description": "", + "memories_setting_description": "Anılarınızda görmek istediklerinizi yönetin", "memory": "Anı", "memory_lane_title": "Anılara Yolculuk {title}", "menu": "Menü", "merge": "Birleştir", - "merge_people": "", + "merge_people": "Kişileri birleştir", "merge_people_limit": "Aynı anda 5 yüzü birleştirebilirsiniz", + "merge_people_prompt": "Bu kişileri birleştirmek istiyor musunuz? Bu işlem geri alınamaz.", "merge_people_successfully": "Kişiler başarılı bir şekilde birleştirildi", + "merged_people_count": "{count, plural, one {# kişi} other {# kişi}} birleştirildi", "minimize": "Küçült", "minute": "Dakika", "missing": "Eksik", "model": "Model", "month": "Ay", - "more": "", - "moved_to_trash": "", + "more": "Daha fazla", + "moved_to_trash": "Çöp kutusuna taşındı", "my_albums": "Albümlerim", "name": "İsim", "name_or_nickname": "İsim veya takma isim", "never": "Asla", + "new_album": "Yeni albüm", "new_api_key": "Yeni API Anahtarı", "new_password": "Yeni şifre", "new_person": "Yeni kişi", "new_user_created": "Yeni kullanıcı oluşturuldu", "new_version_available": "YENİ VERSİYON MEVCUT", - "newest_first": "", + "newest_first": "Önce en yeniler", "next": "Sonraki", - "next_memory": "", + "next_memory": "Sonraki anı", "no": "Hayır", "no_albums_message": "Fotoğraf ve videolarınızı düzenlemek için yeni bir albüm oluşturun", "no_albums_with_name_yet": "Henüz bu isimde bir albümünüz bulunmuyor.", - "no_archived_assets_message": "", + "no_albums_yet": "Henüz albüm oluşturmadınız.", + "no_archived_assets_message": "Fotoğraf görünümünüzden kaldırmak için fotoğrafları ve videoları arşivleyin", "no_assets_message": "İLK FOTOĞRAFINIZI YÜKLEMEK İÇİN TIKLAYIN", - "no_duplicates_found": "", - "no_exif_info_available": "", - "no_explore_results_message": "", - "no_favorites_message": "", - "no_libraries_message": "", - "no_name": "", - "no_places": "", - "no_results": "", + "no_duplicates_found": "Çift 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 favoriler ekleyin", + "no_libraries_message": "Fotoğraf ve videolarınızı görmek için bir harici kütüphane oluşturun", + "no_name": "İsim yok", + "no_places": "Yer yok", + "no_results": "Sonuç bulunamadı", "no_results_description": "Eş anlamlı ya da daha genel anlamlı bir kelime deneyin", - "no_shared_albums_message": "", - "not_in_any_album": "", - "note_apply_storage_label_to_previously_uploaded assets": "", + "no_shared_albums_message": "Fotoğrafları ve videoları ağınızdaki kişilerle paylaşmak için bir albüm oluşturun", + "not_in_any_album": "Hiçbir albümde değil", + "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_unlimited_quota": "Not: Sınırsız kota için 0 yazın", "notes": "Notlar", "notification_toggle_setting_description": "E-posta bildirimlerine izin ver", @@ -859,279 +919,420 @@ "onboarding_welcome_user": "Hoş geldin, {user}", "online": "Çevrimiçi", "only_favorites": "Sadece favoriler", - "only_refreshes_modified_files": "", + "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": "Ayarlar", + "options": "Seçenekler", "or": "veya", "organize_your_library": "Kütüphanenizi düzenleyin", "original": "orijinal", "other": "Diğer", "other_devices": "Diğer cihazlar", "other_variables": "Diğer değişkenler", - "owned": "", - "owner": "", + "owned": "Sahip olunan", + "owner": "Sahip", + "partner": "Ortak", "partner_can_access": "{partner} erişebilir", "partner_can_access_assets": "Arşivlenenler ve Silinenler dışındaki tüm fotoğraf ve videolarınız", "partner_can_access_location": "Fotoğraf ve videolarınızın çekildiği konum", - "partner_sharing": "", - "partners": "", + "partner_sharing": "Ortak paylaşımı", + "partners": "Ortaklar", "password": "Şifre", - "password_does_not_match": "", - "password_required": "", - "password_reset_success": "", + "password_does_not_match": "Şifreler eşleşmiyor", + "password_required": "Şifre gereklidir", + "password_reset_success": "Şifre başarıyla sıfırlandı", "past_durations": { - "days": "", - "hours": "", - "years": "" + "days": "{days, plural, one {Dün} other {Son # gün}}", + "hours": "Son {hours, plural, one {saat} other {# saat}}", + "years": "{years, plural, one {Geçen yıl} other {Son # yıl}}" }, - "path": "", - "pattern": "", - "pause": "", - "pause_memories": "", + "path": "Yol", + "pattern": "Desen", + "pause": "Duraklat", + "pause_memories": "Anıları duraklat", "paused": "Durduruldu", - "pending": "", + "pending": "Beklemede", "people": "Kişiler", - "people_sidebar_description": "", - "permanent_deletion_warning": "", - "permanent_deletion_warning_setting_description": "", + "people_edits_count": "{count, plural, one {# kişi} other {# kişi}} düzenlendi", + "people_feature_description": "Kişilere göre gruplanmış fotoğrafları ve videoları inceleyin", + "people_sidebar_description": "Yan panelde kişilere hızlı erişim bağlantısı göster", + "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", "person": "Kişi", + "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.", "photos": "Fotoğraflar", "photos_and_videos": "Fotoğraflar & Videolar", - "photos_count": "", + "photos_count": "{count, plural, one {{count, number} fotoğraf} other {{count, number} fotoğraf}}", "photos_from_previous_years": "Önceki yıllardan fotoğraflar", "pick_a_location": "Bir konum seçin", "place": "Konum", "places": "Konumlar", "play": "Oynat", - "play_memories": "", - "play_motion_photo": "", + "play_memories": "Anıları oynat", + "play_motion_photo": "Hareketli fotoğrafı oynat", "play_or_pause_video": "Videoyu oynat ya da durdur", - "port": "", - "preset": "", - "preview": "", + "port": "Port", + "preset": "Ön ayar", + "preview": "Önizleme", "previous": "Önceki", "previous_memory": "Önceki anı", "previous_or_next_photo": "Önceki ya da sonraki fotoğraf", - "primary": "", - "profile_picture_set": "", - "public_share": "", - "reaction_options": "", - "read_changelog": "", - "recent": "", + "primary": "Birincil", + "privacy": "Gizlilik", + "profile_image_of_user": "{user} kullanıcısının profil resmi", + "profile_picture_set": "Profil resmi ayarlandı.", + "public_album": "Herkese açık albüm", + "public_share": "Genel paylaşım", + "purchase_account_info": "Destekçi", + "purchase_activated_subtitle": "Immich ve açık kaynak yazılıma destek olduğunuz için teşekkür ederiz", + "purchase_activated_time": "{date, date} tarihinde etkinleştirildi", + "purchase_activated_title": "Anahtarınız başarıyla etkinleştirildi", + "purchase_button_activate": "Aktifleştir", + "purchase_button_buy": "Satın al", + "purchase_button_buy_immich": "Immich satın al", + "purchase_button_never_show_again": "Bir daha gösterme", + "purchase_button_reminder": "30 gün içinde bana hatırlat", + "purchase_button_remove_key": "Anahtarı kaldır", + "purchase_button_select": "Seç", + "purchase_failed_activation": "Etkinleştirme başarısız oldu! Lütfen e-postadaki ürün anahtarını kontrol edin!", + "purchase_individual_description_1": "Bireysel kullanım için", + "purchase_individual_description_2": "Destekçi statüsü", + "purchase_individual_title": "Bireysel", + "purchase_input_suggestion": "Zaten bir ürün anahtarınız var mı? Lütfen aşağıya girin", + "purchase_license_subtitle": "Immich'i satın alarak devam eden gelişimini destekleyin", + "purchase_lifetime_description": "Ömür boyu geçerli", + "purchase_option_title": "SATIN ALMA SEÇENEKLERİ", + "purchase_panel_info_1": "Immich'in gelişimi zaman ve çaba gerektiriyor ve tam zamanlı geliştiricilerimiz var. Amacımız, açık kaynak yazılımı sürdürülebilir bir gelir kaynağı haline getirmek.", + "purchase_panel_info_2": "Bu satın alma işlemi Immich'te ek işlevsellik açmayacak. Immich'in gelişimini desteklemek için size güveniyoruz.", + "purchase_panel_title": "Projeyi destekleyin", + "purchase_per_server": "Sunucu başına", + "purchase_per_user": "Kullanıcı başına", + "purchase_remove_product_key": "Ürün anahtarını kaldır", + "purchase_remove_product_key_prompt": "Ürün anahtarını kaldırmak istediğinize emin misiniz?", + "purchase_remove_server_product_key": "Sunucu ürün anahtarını kaldır", + "purchase_remove_server_product_key_prompt": "Sunucu ürün anahtarını kaldırmak istediğinize emin misiniz?", + "purchase_server_description_1": "Tüm sunucu için", + "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", + "rating": "Derecelendirme", + "rating_clear": "Derecelendirmeyi temizle", + "rating_count": "{count, plural, one {# yıldız} other {# yıldız}}", + "rating_description": "EXIF derecelendirmesini bilgi panelinde göster", + "reaction_options": "Tepki seçenekleri", + "read_changelog": "Değişiklik günlüğünü oku", + "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", + "recent": "Son", + "recent-albums": "Son kaydedilen albümler", "recent_searches": "Son aramalar", "refresh": "Yenile", - "refreshed": "", - "refreshes_every_file": "", + "refresh_encoded_videos": "Kodlanmış videoları yenile", + "refresh_faces": "Yüzleri yenile", + "refresh_metadata": "Meta verileri yenile", + "refresh_thumbnails": "Küçük resimleri yenile", + "refreshed": "Yenilendi", + "refreshes_every_file": "Tüm mevcut ve yeni dosyaları tekrar yükler", + "refreshing_encoded_video": "Kodlanmış videolar yenileniyor", + "refreshing_faces": "Yüzler yenileniyor", + "refreshing_metadata": "Meta veriler yenileniyor", + "regenerating_thumbnails": "Küçük resimler yeniden oluşturuluyor", "remove": "Kaldır", - "remove_deleted_assets": "", - "remove_from_album": "", - "remove_from_favorites": "", - "remove_from_shared_link": "", - "removed_api_key": "", + "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_custom_date_range": "Özel tarih aralığını kaldır", + "remove_deleted_assets": "Çevrimdışı dosyaları kaldır", + "remove_from_album": "Albümden çıkar", + "remove_from_favorites": "Favorilerden çıkar", + "remove_from_shared_link": "Paylaşılan bağlantıdan çıkar", + "remove_url": "Bağlantıyı kaldır", + "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": "Favorilerden kaldırıldı", + "removed_from_favorites_count": "{count, plural, other {#}} favorilerden çıkarıldı", + "removed_tagged_assets": "{count, plural, one {# dosya} other {# dosya}} etiketleri kaldırıldı", "rename": "Yeniden adlandır", "repair": "Onar", - "repair_no_results_message": "", - "replace_with_upload": "", - "require_password": "", - "require_user_to_change_password_on_first_login": "", - "reset": "", - "reset_password": "", - "reset_people_visibility": "", - "restore": "", - "restore_all": "", - "restore_user": "", + "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_user_to_change_password_on_first_login": "Kullanıcı ilk girişte şifreyi değiştirmeli", + "reset": "Sıfırla", + "reset_password": "Şifreyi sıfırla", + "reset_people_visibility": "Kişilerin görünürlüğünü sıfırla", + "reset_to_default": "Varsayılana sıfırla", + "resolve_duplicates": "Çiftleri çöz", + "resolved_all_duplicates": "Tüm çiftler çözüldü", + "restore": "Geri yükle", + "restore_all": "Tümünü geri yükle", + "restore_user": "Kullanıcıyı geri yükle", + "restored_asset": "Dosya geri yüklendi", "resume": "Devam et", "retry_upload": "Yeniden yüklemeyi dene", - "review_duplicates": "", - "role": "", + "review_duplicates": "Çiftleri gözden geçir", + "role": "Rol", + "role_editor": "Düzenleyici", + "role_viewer": "Görüntüleyici", "save": "Kaydet", - "saved_api_key": "", - "saved_profile": "", - "saved_settings": "", + "saved_api_key": "API anahtarı kaydedildi", + "saved_profile": "Profil kaydedildi", + "saved_settings": "Kaydedilen ayarlar", "say_something": "Bir şey söyle", "scan_all_libraries": "Tüm Kütüphaneleri Tara", - "scan_all_library_files": "Tüm Kütüphaneleri Yeniden Tara", - "scan_new_library_files": "", + "scan_library": "Kütüphaneyi tara", "scan_settings": "Ayarları Tara", "scanning_for_album": "Albüm için taranıyor...", "search": "Ara", - "search_albums": "", - "search_by_context": "", - "search_camera_make": "", - "search_camera_model": "", - "search_city": "", - "search_country": "", - "search_for_existing_person": "", + "search_albums": "Albüm ara", + "search_by_context": "Bağlama göre ara", + "search_by_filename": "Dosya adına göre ara", + "search_by_filename_example": "Örn. IMG_1234.JPG veya PNG", + "search_camera_make": "Kamera markasına göre ara...", + "search_camera_model": "Kamera modeline göre ara...", + "search_city": "Şehre göre ara...", + "search_country": "Ülkeye göre ara...", + "search_for_existing_person": "Mevcut bir kişiyi ara", + "search_no_people": "Kişi yok", "search_no_people_named": "\"{name}\" isimli bir kişi yok", - "search_people": "", - "search_places": "", - "search_state": "", - "search_timezone": "", + "search_options": "Arama seçenekleri", + "search_people": "Kişilere göre ara", + "search_places": "Yerleri ara", + "search_settings": "Ayarları ara", + "search_state": "Eyalet/İl ara...", + "search_tags": "Etiketleri ara...", + "search_timezone": "Saat dilimi ara...", "search_type": "Arama türü", "search_your_photos": "Fotoğraflarınızı arayın", - "searching_locales": "", - "second": "", + "searching_locales": "Yerleri arıyor...", + "second": "Saniye", "see_all_people": "Tüm kişileri gör", - "select_album_cover": "", - "select_all": "", - "select_avatar_color": "", - "select_face": "", - "select_featured_photo": "", + "select_album_cover": "Albüm kapağı seç", + "select_all": "Tümünü seç", + "select_all_duplicates": "Tüm çiftleri seç", + "select_avatar_color": "Avatar rengini seç", + "select_face": "Yüzü seç", + "select_featured_photo": "Öne çıkan fotoğrafı seç", "select_from_computer": "Bilgisayardan seç", - "select_keep_all": "", + "select_keep_all": "Hepsini sakla", "select_library_owner": "Kütüphane sahibini seç", - "select_new_face": "", - "select_photos": "", - "select_trash_all": "", - "selected": "", - "send_message": "", - "send_welcome_email": "", - "server": "", - "server_stats": "", - "set": "", + "select_new_face": "Yeni yüz seç", + "select_photos": "Fotoğrafları seç", + "select_trash_all": "Hepsini çöpe at", + "selected": "Seçildi", + "selected_count": "{count, plural, other {# seçildi}}", + "send_message": "Mesaj gönder", + "send_welcome_email": "Hoş geldin e-postası gönder", + "server_offline": "Sunucu çevrimdışı", + "server_online": "Sunucu çevrimiçi", + "server_stats": "Sunucu istatistikleri", + "server_version": "Sunucu versiyonu", + "set": "Ayarla", "set_as_album_cover": "Albüm resmi olarak ayarla", "set_as_profile_picture": "Profil resmi olarak ayarla", - "set_date_of_birth": "", - "set_profile_picture": "", - "set_slideshow_to_fullscreen": "", + "set_date_of_birth": "Doğum tarihini ayarla", + "set_profile_picture": "Profil resmini ayarla", + "set_slideshow_to_fullscreen": "Slayt gösterisini tam ekran yap", "settings": "Ayarlar", "settings_saved": "Ayarlar kaydedildi", "share": "Paylaş", - "shared": "", - "shared_by": "", + "shared": "Paylaşılan", + "shared_by": "Tarafından paylaşılan", "shared_by_user": "{user} tarafından paylaşıldı", - "shared_by_you": "", - "shared_from_partner": "", - "shared_links": "", - "shared_photos_and_videos_count": "", + "shared_by_you": "Senin tarafından paylaşıldı", + "shared_from_partner": "{partner} tarafından paylaşılan fotoğraflar", + "shared_link_options": "Paylaşılan bağlantı seçenekleri", + "shared_links": "Paylaşılan bağlantılar", + "shared_photos_and_videos_count": "{assetCount, plural, one {# paylaşılan fotoğraf veya video.} other {# paylaşılan fotoğraf & video.}}", "shared_with_partner": "{partner} ile paylaşıldı", "sharing": "Paylaşılıyor", "sharing_enter_password": "Bu sayfayı görebilmek için lütfen şifreyi giriniz.", - "sharing_sidebar_description": "", + "sharing_sidebar_description": "Yan panelde paylaşılanlara kısa yol göster", + "shift_to_permanent_delete": "Dosyayı 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", - "show_and_hide_people": "", - "show_file_location": "", - "show_gallery": "", - "show_hidden_people": "", - "show_in_timeline": "", - "show_in_timeline_setting_description": "", + "show_and_hide_people": "Kişileri göster ve gizle", + "show_file_location": "Dosya konumunu göster", + "show_gallery": "Galeriyi göster", + "show_hidden_people": "Gizli kişileri göster", + "show_in_timeline": "Zaman çizelgesinde göster", + "show_in_timeline_setting_description": "Bu kullanıcının fotoğraf ve videolarını zaman çizelgenizde göster", "show_keyboard_shortcuts": "Klavye kısayollarını göster", - "show_metadata": "", - "show_or_hide_info": "", + "show_metadata": "Meta verileri göster", + "show_or_hide_info": "Bilgiyi göster veya gizle", "show_password": "Şifreyi göster", "show_person_options": "Kişi ayarlarını göster", - "show_progress_bar": "", + "show_progress_bar": "İlerleme çubuğunu göster", "show_search_options": "Arama ayarlarını göster", + "show_slideshow_transition": "Slayt geçişini göster", + "show_supporter_badge": "Destekçi rozeti", + "show_supporter_badge_description": "Destekçi rozetini göster", "shuffle": "Karıştır", + "sidebar": "Yan panel", + "sidebar_display_description": "Yan panelde görünüme kısa yol göster", "sign_out": "Oturumu Kapat", "sign_up": "Kaydol", - "size": "", - "skip_to_content": "", + "size": "Boyut", + "skip_to_content": "İçeriğe atla", + "skip_to_folders": "Klasörlere atla", + "skip_to_tags": "Etiketlere atla", "slideshow": "Slayt gösteriisi", "slideshow_settings": "Slayt gösterisi ayarları", - "sort_albums_by": "", + "sort_albums_by": "Albümleri sırala...", "sort_created": "Oluşturulma tarihi", + "sort_items": "Öğe sayısı", + "sort_modified": "Değişiklik tarihi", + "sort_oldest": "En eski fotoğraf", + "sort_recent": "En yeni fotoğraf", "sort_title": "Başlık", "source": "Kaynak", - "stack": "", - "stack_selected_photos": "", - "stacktrace": "", - "start": "", - "start_date": "", - "state": "", + "stack": "Yığın", + "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ı", + "stacktrace": "Yığın izi", + "start": "Başlat", + "start_date": "Başlangıç tarihi", + "state": "Eyalet/İl", "status": "Durum", - "stop_motion_photo": "", - "stop_photo_sharing": "", - "stop_photo_sharing_description": "", + "stop_motion_photo": "Hareketli fotoğrafı durdur", + "stop_photo_sharing": "Fotoğraflarınızı paylaşmayı durdurmak mı istiyorsunuz?", + "stop_photo_sharing_description": "{partner} artık fotoğraflarınıza erişemeyecek.", "stop_sharing_photos_with_user": "Bu kullanıcı ile fotoğraflarınızı paylaşmayı durdurun", "storage": "Depolama alanı", - "storage_label": "", - "storage_usage": "", - "submit": "", + "storage_label": "Depolama yolu", + "storage_usage": "{used} / {available} kullanıldı", + "submit": "Gönder", "suggestions": "Öneriler", "sunrise_on_the_beach": "Plajda gün doğumu", - "swap_merge_direction": "", - "sync": "", + "support": "Destek", + "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", + "tag": "Etiket", + "tag_assets": "Dosyaları 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_updated": "Etiket güncellendi: {tag}", + "tagged_assets": "{count, plural, one {# dosya} other {# dosya}} etiketlendi", + "tags": "Etiketler", "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", - "time_based_memories": "", + "they_will_be_merged_together": "Birlikte birleştirilecekler", + "third_party_resources": "Üçüncü taraf kaynaklar", + "time_based_memories": "Zaman bazlı anılar", + "timeline": "Zaman Çizelgesi", "timezone": "Zaman dilimi", "to_archive": "Arşivle", "to_change_password": "Şifreyi değiştir", - "to_favorite": "", + "to_favorite": "Favorilere ekle", "to_login": "Oturum aç", - "to_trash": "", - "toggle_settings": "", - "toggle_theme": "", - "toggle_visibility": "", - "total_usage": "", + "to_parent": "Üst öğeye git", + "to_trash": "Çöpe taşı", + "toggle_settings": "Ayarları değiştir", + "toggle_theme": "Tema değiştir", + "total": "Toplam", + "total_usage": "Toplam kullanım", "trash": "Çöp", - "trash_all": "", + "trash_all": "Hepsini sil", + "trash_count": "Çöp kutusu {count, number}", "trash_delete_asset": "Ögeyi Sil/Çöpe gönder", - "trash_no_results_message": "", - "trashed_items_will_be_permanently_deleted_after": "", - "type": "", + "trash_no_results_message": "Silinen fotoğraf ve videolar burada listelenecektir.", + "trashed_items_will_be_permanently_deleted_after": "Silinen öğeler {days, plural, one {# gün} other {# gün}} sonra kalıcı olarak silinecek.", + "type": "Tür", "unarchive": "Arşivden çıkar", - "unarchived": "", - "unfavorite": "", - "unhide_person": "", + "unarchived_count": "{count, plural, other {# arşivden çıkarıldı}}", + "unfavorite": "Favorilerden kaldır", + "unhide_person": "Kişiyi göster", "unknown": "Bilinmeyen", - "unknown_album": "", "unknown_year": "Bilinmeyen YIl", "unlimited": "Sınırsız", - "unlink_oauth": "", - "unlinked_oauth_account": "", + "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ı", "unnamed_album": "İsimsiz Albüm", - "unselect_all": "", - "unstack": "", - "untracked_files": "", - "untracked_files_decription": "", - "up_next": "", + "unnamed_album_delete_confirmation": "Bu albümü silmek istediğinizden emin misiniz?", + "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", + "unstack": "Yığını kaldır", + "unstacked_assets_count": "{count, plural, one {# dosya} other {# dosya}} yığını kaldırıldı", + "untracked_files": "İzlenmeyen dosyalar", + "untracked_files_decription": "Bu dosyalar uygulama tarafından izlenmiyor. Başarısız taşıma işlemlerinin, kesintiye uğrayan yüklemelerin sonuçları olabilir veya bir hata nedeniyle geride kalmış olabilirler", + "up_next": "Sıradaki", "updated_password": "Şifreyi güncelle", "upload": "Yükle", - "upload_concurrency": "", + "upload_concurrency": "Yükleme eşzamanlılığı", + "upload_errors": "{count, plural, one {# hata} other {# hatayla}} yükleme tamamlandı, yeni yüklenen dosyaları görmek için sayfayı güncelleyin.", + "upload_progress": "{remaining, number} kalan - {processed, number}/{total, number} işlendi", + "upload_skipped_duplicates": "{count, plural, one {# çift dosya} other {# çift dosya}} 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.", - "url": "", - "usage": "", + "url": "URL", + "usage": "Kullanım", + "use_custom_date_range": "Bunun yerine özel tarih aralığını kullan", "user": "Kullanıcı", - "user_id": "", - "user_license_settings": "Lisans", + "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_purchase_settings": "Satın Alma", + "user_purchase_settings_description": "Satın alma işlemlerini yönet", + "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", "username": "Kullanıcı adı", "users": "Kullanıcılar", - "utilities": "", - "validate": "", - "variables": "", + "utilities": "Yardımcılar", + "validate": "Doğrula", + "variables": "Değişkenler", "version": "Versiyon", "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_item": "{version}, {date} tarihinde kuruldu", "video": "Video", - "video_hover_setting": "", - "video_hover_setting_description": "", + "video_hover_setting": "Üzerinde durulduğunda video önizlemesi 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": "", + "videos_count": "{count, plural, one {# video} other {# video}}", "view": "Görüntüle", "view_album": "Albümü görüntüle", - "view_all": "", + "view_all": "Tümünü gör", "view_all_users": "Tüm kullanıcıları görüntüle", - "view_links": "", - "view_next_asset": "", - "view_previous_asset": "", - "viewer": "", + "view_in_timeline": "Zaman çizelgesinde görüntüle", + "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_stack": "Yığını görüntüle", + "visibility_changed": "Görünürlük {count, plural, one {# kişi} other {# kişi}} için değiştirildi", "waiting": "Bekleniyor", "warning": "Uyarı", "week": "Hafta", "welcome": "Hoş geldiniz", "welcome_to_immich": "Immich'e hoş geldiniz", "year": "Yıl", + "years_ago": "{years, plural, one {bir yıl} other {# yıl}} önce", "yes": "Evet", - "you_dont_have_any_shared_links": "", - "zoom_image": "" + "you_dont_have_any_shared_links": "Herhangi bir paylaşılan bağlantınız yok", + "zoom_image": "Görüntüyü yakınlaştır" } diff --git a/i18n/uk.json b/i18n/uk.json index 39415765201bf..806ae394f86ec 100644 --- a/i18n/uk.json +++ b/i18n/uk.json @@ -23,6 +23,7 @@ "add_to": "Додати у...", "add_to_album": "Додати у альбом", "add_to_shared_album": "Додати у спільний альбом", + "add_url": "Додати URL", "added_to_archive": "Додано до архіву", "added_to_favorites": "Додано до обраного", "added_to_favorites_count": "Додано {count, number} до обраного", @@ -34,6 +35,11 @@ "authentication_settings_disable_all": "Ви впевнені, що хочете вимкнути всі методи входу? Вхід буде повністю вимкнений.", "authentication_settings_reenable": "Для повторного ввімкнення використовуйте Команду сервера.", "background_task_job": "Фонові Завдання", + "backup_database": "Резервна копія бази даних", + "backup_database_enable_description": "Увімкнути резервне копіювання бази даних", + "backup_keep_last_amount": "Кількість резервних копій для зберігання", + "backup_settings": "Налаштування резервного копіювання", + "backup_settings_description": "Керування налаштуваннями резервного копіювання бази даних", "check_all": "Перевірити все", "cleared_jobs": "Очищені завдання для: {job}", "config_set_by_file": "Налаштовано за допомогою конфіг-файлу", @@ -43,9 +49,10 @@ "confirm_reprocess_all_faces": "Ви впевнені, що хочете повторно визначити всі обличчя? Це також призведе до видалення імен з усіх облич.", "confirm_user_password_reset": "Ви впевнені, що хочете скинути пароль користувача {user}?", "create_job": "Створити завдання", - "crontab_guru": "", + "cron_expression": "Cron вираз", + "cron_expression_description": "Встановіть інтервал сканування, використовуючи формат cron. Для отримання додаткової інформації зверніться до напр. Crontab Guru", + "cron_expression_presets": "Попередні налаштування cron виразів", "disable_login": "Вимкнути вхід", - "disabled": "", "duplicate_detection_job_description": "Запустити машинне навчання на активах для виявлення схожих зображень. Залежить від інтелектуального пошуку", "exclusion_pattern_description": "Шаблони виключень дозволяють ігнорувати файли та папки під час сканування вашої бібліотеки. Це корисно, якщо у вас є папки, які містять файли, які ви не хочете імпортувати, наприклад, RAW-файли.", "external_library_created_at": "Зовнішня бібліотека (створена {date})", @@ -63,22 +70,15 @@ "image_prefer_wide_gamut": "Віддають перевагу широкій гамі", "image_prefer_wide_gamut_setting_description": "Для мініатюр використовуйте дисплей P3. Це краще зберігає яскравість зображень з широким колірним простором, але на старих пристроях зі старою версією браузера зображення можуть виглядати інакше. sRGB-зображення зберігаються у форматі sRGB, щоб уникнути зсуву кольорів.", "image_preview_description": "Зображення середнього розміру з видаленими метаданими, яке використовується при перегляді одного об'єкта та для машинного навчання", - "image_preview_format": "Формат прев'ю", "image_preview_quality_description": "Якість попереднього перегляду від 1 до 100. Вища оцінка означає кращу якість, але створює більші файли та може зменшити швидкість роботи програми. Встановлення низького значення може вплинути на якість машинного навчання.", - "image_preview_resolution": "Роздільність прев'ю", - "image_preview_resolution_description": "Використовується при перегляді окремої фотографії та для машинного навчання. Вища роздільність може зберігати більше деталей, але потребує більше часу на кодування, має більший розмір файлу і може знижувати реакцію програми.", "image_preview_title": "Налаштування попереднього перегляду", "image_quality": "Якість", - "image_quality_description": "Якість зображення від 1 до 100. Чим вище, тим краще якість, але створюються більші файли, цей параметр впливає на прев'ю і мініатюри зображень.", "image_resolution": "Роздільність", "image_resolution_description": "Вища роздільність може зберігати більше деталей, але займає більше часу для кодування, має більші розміри файлів і може зменшити швидкість роботи програми.", "image_settings": "Налаштування зображення", "image_settings_description": "Керуйте якістю та роздільною здатністю згенерованих зображень", "image_thumbnail_description": "Маленька мініатюра із видаленими метаданими, що використовується для перегляду груп фотографій, наприклад, на основній лінії часу", - "image_thumbnail_format": "Формат ескізу", "image_thumbnail_quality_description": "Якість мініатюри від 1 до 100. Вища оцінка означає кращу якість, але створює більші файли та може зменшити швидкість роботи програми.", - "image_thumbnail_resolution": "Розмір ескізу", - "image_thumbnail_resolution_description": "Використовується при перегляді груп фотографій (основна стрічка, перегляд альбому тощо). Вища роздільна здатність може зберегти більше деталей, але вимагає більше часу для кодування, має більший розмір файлів і може знижувати чутливість додатку.", "image_thumbnail_title": "Налаштування мініатюр", "job_concurrency": "{job} одночасно", "job_created": "Завдання створено", @@ -89,9 +89,6 @@ "jobs_delayed": "{jobCount, plural, other {# відкладено}}", "jobs_failed": "{jobCount, plural, other {# не вдалося}}", "library_created": "Створена бібліотека: {library}", - "library_cron_expression": "Вираз Cron", - "library_cron_expression_description": "Встановіть інтервал сканування за допомогою формату Cron. Для отримання додаткової інформації дивіться, наприклад, на Crontab Guru", - "library_cron_expression_presets": "Шаблони виразів Cron", "library_deleted": "Бібліотеку видалено", "library_import_path_description": "Вкажіть папку для імпорту. Цю папку, включно з підпапками, буде проскановано на наявність зображень і відео.", "library_scanning": "Періодичне сканування", @@ -134,7 +131,7 @@ "machine_learning_smart_search_description": "Пошук зображень за допомогою семантичних вбудовувань CLIP", "machine_learning_smart_search_enabled": "Увімкнути розумний пошук", "machine_learning_smart_search_enabled_description": "Якщо ця функція вимкнена, зображення не будуть кодуватися для розумного пошуку.", - "machine_learning_url_description": "URL сервера машинного навчання", + "machine_learning_url_description": "URL сервера машинного навчання. Якщо надано більше одного URL, сервери будуть опитуватися по черзі, поки один з них не відповість успішно, у порядку від першого до останнього.", "manage_concurrency": "Керування паралельністю завдань", "manage_log_settings": "Керування налаштуваннями журналу", "map_dark_style": "Темний стиль", @@ -215,7 +212,6 @@ "refreshing_all_libraries": "Оновлення всіх бібліотек", "registration": "Реєстрація адміністратора", "registration_description": "Оскільки ви перший користувач в системі, ви будете призначені Адміністратором і відповідатимете за адміністративні завдання, а додаткові користувачі будуть створені вами.", - "removing_deleted_files": "Видалення недоступних файлів", "repair_all": "Відремонтуйте все", "repair_matched_items": "Відповідає {count, plural, one {# елемент} few {# елементи} many {# елементів} other {# елементів}}", "repaired_items": "Відновлено {count, plural, one {# елемент} few {# елементи} many {# елементів} other {# елементів}}", @@ -223,12 +219,12 @@ "reset_settings_to_default": "Скинути налаштування до заводських значень", "reset_settings_to_recent_saved": "Скинути налаштування до недавно збережених налаштувань", "scanning_library": "Сканування бібліотеки", - "scanning_library_for_changed_files": "Сканування бібліотеки на наявність змінених файлів", - "scanning_library_for_new_files": "Сканування бібліотеки на наявність нових файлів", "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": "Вітальне повідомлення", @@ -254,6 +250,16 @@ "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_settings_description": "Керувати шаблонами сповіщень ел. пошти", + "template_email_update_album": "Оновити шаблон альбому", + "template_email_welcome": "Шаблон вітального ел. листа", + "template_settings": "Шаблони сповіщень", + "template_settings_description": "Керувати шаблонами для сповіщень.", "theme_custom_css_settings": "Власний CSS", "theme_custom_css_settings_description": "Каскадні таблиці стилів дозволяють настроювати дизайн Immich.", "theme_settings": "Налаштування теми", @@ -261,7 +267,6 @@ "these_files_matched_by_checksum": "Ці файли відповідають своїм контрольним сумам", "thumbnail_generation_job": "Створення мініатюр", "thumbnail_generation_job_description": "Створити великі, малі та розмиті мініатюри для кожного ресурсу, а також мініатюри для кожної особи", - "transcode_policy_description": "", "transcoding_acceleration_api": "API прискорення", "transcoding_acceleration_api_description": "API, яка буде взаємодіяти з вашим пристроєм для прискорення транскодування. Ця настройка працює у \"найкращих умовах\" і, в разі невдачі, перейде на програмне транскодування. Підтримка VP9 може або не може працювати, залежно від вашого обладнання.", "transcoding_acceleration_nvenc": "NVENC (вимагає графічного процесора NVIDIA)", @@ -313,8 +318,6 @@ "transcoding_threads_description": "Вищі значення прискорюють кодування, але залишають менше місця для обробки інших завдань сервером під час активності. Це значення не повинно бути більше кількості ядер процесора. Максимізує використання, якщо встановлено на 0.", "transcoding_tone_mapping": "Тонова картографія", "transcoding_tone_mapping_description": "Намагається зберегти вигляд HDR-відео при конвертації в SDR. Кожен алгоритм робить різні компроміси щодо кольору, деталізації та яскравості. Алгоритм Hable зберігає деталі, Mobius - кольори, Reinhard - яскравість.", - "transcoding_tone_mapping_npl": "Тонова картографія NPL", - "transcoding_tone_mapping_npl_description": "Кольори будуть налаштовані для нормального вигляду на дисплеї цього яскравості. Протилежно до інтуїтивного, менші значення збільшують яскравість відео, а вищі - навпаки, оскільки вони компенсують яскравість дисплея. Значення 0 автоматично налаштовує це значення.", "transcoding_transcode_policy": "Політика перекодування", "transcoding_transcode_policy_description": "Політика транскодування для відео. HDR відео завжди буде транскодуватись (крім випадків, коли транскодування вимкнено).", "transcoding_two_pass_encoding": "Кодування з двома проходами", @@ -330,7 +333,7 @@ "untracked_files_description": "Ці файли не відстежуються програмою. Вони можуть бути результатом невдалого переміщення, перерваного завантаження або залишитися через помилку програми", "user_cleanup_job": "Очищення користувача", "user_delete_delay": "Акаунт {user} і його ресурси будуть заплановані для остаточного видалення через {delay, plural, one {# день} few {# дні} many {# днів} other {# днів}}.", - "user_delete_delay_settings": "Видалити затримку", + "user_delete_delay_settings": "Відкладене видалення", "user_delete_delay_settings_description": "Кількість днів після видалення для остаточного видалення акаунта користувача та його ресурсів. Задача видалення користувача запускається опівночі для перевірки користувачів, готових до видалення. Зміни цього налаштування будуть оцінені під час наступного виконання.", "user_delete_immediately": "Акаунт та ресурси користувача {user} будуть негайно поставлені в чергу на остаточне видалення.", "user_delete_immediately_checkbox": "Поставити користувача та ресурси в чергу для негайного видалення", @@ -395,7 +398,6 @@ "archive_or_unarchive_photo": "Архівувати або розархівувати фото", "archive_size": "Розмір архіву", "archive_size_description": "Налаштувати розмір архіву для завантаження (у GiB)", - "archived": "", "archived_count": "{count, plural, other {Архівовано #}}", "are_these_the_same_person": "Це та сама людина?", "are_you_sure_to_do_this": "Ви впевнені, що хочете це зробити?", @@ -430,7 +432,7 @@ "birthdate_saved": "Дата народження успішно збережена", "birthdate_set_description": "Дата народження використовується для обчислення віку цієї особи на момент фотографії.", "blurred_background": "Розмитий фон", - "bugs_and_feature_requests": "Помилки та запити на функції", + "bugs_and_feature_requests": "Помилки та Запити", "build": "Збірка", "build_image": "Створити зображення", "bulk_delete_duplicates_confirmation": "Ви впевнені, що хочете масово видалити {count, plural, one {# дубльований ресурс} few {# дубльовані ресурси} other {# дубльованих ресурсів}}? Це дія залишить найбільший ресурс у кожній групі і остаточно видалить всі інші дублікати. Цю дію неможливо скасувати!", @@ -445,10 +447,6 @@ "cannot_merge_people": "Неможливо об'єднати людей", "cannot_undo_this_action": "Ви не можете скасувати цю дію!", "cannot_update_the_description": "Неможливо оновити опис", - "cant_apply_changes": "", - "cant_get_faces": "", - "cant_search_people": "", - "cant_search_places": "", "change_date": "Змінити дату", "change_expiration_time": "Змінити термін дії", "change_location": "Змінити місцезнаходження", @@ -480,6 +478,7 @@ "confirm": "Підтвердіть", "confirm_admin_password": "Підтвердити пароль адміністратора", "confirm_delete_shared_link": "Ви впевнені, що хочете видалити це спільне посилання?", + "confirm_keep_this_delete_others": "Усі інші ресурси в стеку буде видалено, окрім цього ресурсу. Ви впевнені, що хочете продовжити?", "confirm_password": "Підтвердити пароль", "contain": "Містити", "context": "Контекст", @@ -529,6 +528,7 @@ "delete_key": "Видалити ключ", "delete_library": "Видалити бібліотеку", "delete_link": "Видалити посилання", + "delete_others": "Видалити інші", "delete_shared_link": "Видалити спільне посилання", "delete_tag": "Видалити тег", "delete_tag_confirmation_prompt": "Ви впевнені, що хочете видалити тег {tagName}?", @@ -562,13 +562,6 @@ "duplicates": "Дублікати", "duplicates_description": "Визначити, які групи є дублікатами", "duration": "Тривалість", - "durations": { - "days": "{days, plural, one {день} few {{days, number} дні} many {{days, number} днів} other {{days, number} днів}}", - "hours": "{hours, plural, one {година} few {{hours, number} години} many {{hours, number} годин} other {{hours, number} години}}", - "minutes": "{minutes, plural, one {хвилина} few {{minutes, number} хвилини} many {{minutes, number} хвилин} other {{minutes, number} хвилин}}", - "months": "{months, plural, one {місяць} few {{months, number} місяці} many {{months, number} місяців} other {{months, number} місяців}}", - "years": "{years, plural, one {рік} few {{years, number} роки} many {{years, number} років} other {{years, number} років}}" - }, "edit": "Редагувати", "edit_album": "Редагувати альбом", "edit_avatar": "Редагувати аватар", @@ -593,8 +586,6 @@ "editor_crop_tool_h2_aspect_ratios": "Пропорції зображення", "editor_crop_tool_h2_rotation": "Орієнтація", "email": "Електронна пошта", - "empty": "", - "empty_album": "", "empty_trash": "Очистити кошик", "empty_trash_confirmation": "Ви впевнені, що хочете очистити кошик? Це остаточно видалить всі ресурси в кошику з Immich.\nЦю дію не можна скасувати!", "enable": "Увімкнути", @@ -628,6 +619,7 @@ "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_people": "Не вдалося завантажити людей", @@ -655,8 +647,6 @@ "unable_to_change_location": "Неможливо змінити місцезнаходження", "unable_to_change_password": "Не вдається змінити пароль", "unable_to_change_visibility": "Неможливо змінити видимість для {count, plural, one {# особи} few {# осіб} other {# людей}}", - "unable_to_check_item": "", - "unable_to_check_items": "", "unable_to_complete_oauth_login": "Неможливо завершити вхід через OAuth", "unable_to_connect": "Не вдається підключитися", "unable_to_connect_to_server": "Не вдається підключитися до сервера", @@ -697,12 +687,10 @@ "unable_to_remove_album_users": "Неможливо видалити користувачів з альбому", "unable_to_remove_api_key": "Не вдається видалити ключ API", "unable_to_remove_assets_from_shared_link": "Не вдається видалити ресурси зі спільного посилання", - "unable_to_remove_comment": "", "unable_to_remove_deleted_assets": "Неможливо видалити автономні файли", "unable_to_remove_library": "Не вдається видалити бібліотеку", "unable_to_remove_partner": "Не вдається видалити партнера", "unable_to_remove_reaction": "Не вдалося видалити реакцію", - "unable_to_remove_user": "", "unable_to_repair_items": "Не вдалося відновити елементи", "unable_to_reset_password": "Не вдається скинути пароль", "unable_to_resolve_duplicate": "Не вдається вирішити дублікат", @@ -732,10 +720,6 @@ "unable_to_update_user": "Неможливо оновити дані користувача", "unable_to_upload_file": "Не вдалося завантажити файл" }, - "every_day_at_onepm": "", - "every_night_at_midnight": "", - "every_night_at_twoam": "", - "every_six_hours": "", "exif": "Exif", "exit_slideshow": "Вийти зі слайд-шоу", "expand_all": "Розгорнути все", @@ -750,37 +734,32 @@ "external": "Зовнішні", "external_libraries": "Зовнішні бібліотеки", "face_unassigned": "Не призначено", - "failed_to_get_people": "", + "failed_to_load_assets": "Не вдалося завантажити ресурси", "favorite": "До улюблених", "favorite_or_unfavorite_photo": "Додати до обраних або видалити з обраних фото", "favorites": "Улюблені", - "feature": "", "feature_photo_updated": "Вибране фото оновлено", - "featurecollection": "", "features": "Додаткові можливості", "features_setting_description": "Керування додатковими можливостями додатка", "file_name": "Ім'я файлу", "file_name_or_extension": "Ім'я файлу або розширення", "filename": "Ім'я файлу", - "files": "", "filetype": "Тип файлу", "filter_people": "Фільтр по людях", "find_them_fast": "Швидко знаходьте їх за назвою за допомогою пошуку", "fix_incorrect_match": "Виправити неправильний збіг", "folders": "Папки", "folders_feature_description": "Перегляд перегляду папок для фотографій і відео у файловій системі", - "force_re-scan_library_files": "Примусово пересканувати всі файли бібліотеки", "forward": "Переслати", "general": "Загальні", "get_help": "Отримати допомогу", "getting_started": "Початок", "go_back": "Повернутися назад", "go_to_search": "Перейти до пошуку", - "go_to_share_page": "Перейдіть на сторінку спільного доступу", "group_albums_by": "Групувати альбоми за...", "group_no": "Без групування", - "group_owner": "Групування за власником", - "group_year": "Групувати за роками", + "group_owner": "За власником", + "group_year": "За роком", "has_quota": "Квота", "hi_user": "Привіт {name} ({email})", "hide_all_people": "Сховати всіх", @@ -802,10 +781,6 @@ "image_alt_text_date_place_2_people": "{isVideo, select, true {Відео} other {Зображення}} зроблено в {city}, {country} з {person1} та {person2} {date}", "image_alt_text_date_place_3_people": "{isVideo, select, true {Відео} other {Зображення}} зроблено в {city}, {country} з {person1}, {person2} та {person3} {date}", "image_alt_text_date_place_4_or_more_people": "{isVideo, select, true {Відео} other {Зображення}} зроблено в {city}, {country} з {person1}, {person2} та ще {additionalCount, number} особами {date}", - "image_alt_text_people": "{count, plural, =1 {з {person1}} =2 {з {person1} та {person2}} =3 {з {person1}, {person2}, та {person3}} other {з {person1}, {person2}, та {others, number} ін.}}", - "image_alt_text_place": "у {city}, {country}", - "image_taken": "{isVideo, select, true {Зняте відео} other {Зроблений знімок}}", - "img": "", "immich_logo": "Логотип Immich", "immich_web_interface": "Веб інтерфейс Immich", "import_from_json": "Імпорт з JSON", @@ -826,10 +801,11 @@ "invite_people": "Запросити", "invite_to_album": "Запросити в альбом", "items_count": "{count, plural, one {# елемент} few {# елементи} many {# елементів} other {# елемента}}", - "job_settings_description": "", "jobs": "Завдання", "keep": "Залишити", "keep_all": "Зберегти все", + "keep_this_delete_others": "Залишити цей ресурс, видалити інші", + "kept_this_deleted_others": "Збережено цей ресурс і видалено {count, plural, one {# ресурс} few {# ресурси} many {# ресурсів} other {# ресурсу}}", "keyboard_shortcuts": "Сполучення клавіш", "language": "Мова", "language_setting_description": "Виберіть мову, якій ви надаєте перевагу", @@ -841,31 +817,6 @@ "level": "Рівень", "library": "Бібліотека", "library_options": "Параметри бібліотеки", - "license_account_info": "Ваш обліковий запис має ліцензію", - "license_activated_subtitle": "Дякуємо за підтримку Immich та програмного забезпечення з відкритим кодом", - "license_activated_title": "Ваша ліцензія успішно активована", - "license_button_activate": "Активувати", - "license_button_buy": "Купити", - "license_button_buy_license": "Купити ліцензію", - "license_button_select": "Оберіть", - "license_failed_activation": "Не вдалося активувати ліцензію. Будь ласка, перевірте свою електронну пошту, щоб отримати правильний ліцензійний ключ!", - "license_individual_description_1": "1 ліцензія на користувача на будь-якому сервері", - "license_individual_title": "Індивідуальна ліцензія", - "license_info_licensed": "Ліцензовано", - "license_info_unlicensed": "Без ліцензії", - "license_input_suggestion": "Маєте ліцензію? Введіть ключ нижче", - "license_license_subtitle": "Придбайте ліцензію на підтримку Immich", - "license_license_title": "ЛІЦЕНЗІЯ", - "license_lifetime_description": "Довічна ліцензія", - "license_per_server": "На один сервер", - "license_per_user": "На одного користувача", - "license_server_description_1": "1 ліцензія на сервер", - "license_server_description_2": "Ліцензія для всіх користувачів на сервері", - "license_server_title": "Ліцензія на сервер", - "license_trial_info_1": "Ви використовуєте неліцензійну версію Immich", - "license_trial_info_2": "Ви використовуєте Immich приблизно", - "license_trial_info_3": "{accountAge, plural, one {# день} few {# дні} many {# днів} other {# дня}}", - "license_trial_info_4": "Будь ласка, розгляньте можливість придбання ліцензії для підтримки подальшого розвитку сервісу", "light": "Світла", "like_deleted": "Лайк видалено", "link_motion_video": "Посилання на рухоме відео", @@ -970,7 +921,6 @@ "onboarding_welcome_user": "Ласкаво просимо, {user}", "online": "Доступний", "only_favorites": "Лише обрані", - "only_refreshes_modified_files": "Оновлює лише змінені файли", "open_in_map_view": "Відкрити у перегляді мапи", "open_in_openstreetmap": "Відкрити в OpenStreetMap", "open_the_search_filters": "Відкрийте фільтри пошуку", @@ -1008,13 +958,12 @@ "people_edits_count": "Відредаговано {count, plural, one {# особу} few {# особи} many {# осіб} other {# людей}}", "people_feature_description": "Перегляд фотографій і відео, згрупованих за людьми", "people_sidebar_description": "Відображення посилання на людей у бічній панелі", - "perform_library_tasks": "", "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_asset": "Видалити назавжди", "permanently_deleted_assets_count": "Видалено остаточно {count, plural, one {# ресурс} few {# ресурси} many {# ресурсів} other {# ресурсів}}", "person": "Людина", "person_hidden": "{name}{hidden, select, true { (приховано)} other {}}", @@ -1030,7 +979,6 @@ "play_memories": "Відтворити спогади", "play_motion_photo": "Відтворювати рухомі фото", "play_or_pause_video": "Відтворення або призупинення відео", - "point": "", "port": "Порт", "preset": "Передвстановлення", "preview": "Прев'ю", @@ -1075,12 +1023,10 @@ "purchase_server_description_2": "Статус підтримки", "purchase_server_title": "Сервер", "purchase_settings_server_activated": "Ключ продукту сервера керується адміністратором", - "range": "", "rating": "Зоряний рейтинг", "rating_clear": "Очистити рейтинг", "rating_count": "{count, plural, one {# зірка} few {# зірки} many {# зірок} other {# зірок}}", "rating_description": "Показувати рейтинг EXIF на інформаційній панелі", - "raw": "", "reaction_options": "Опції реакції", "read_changelog": "Прочитати зміни в оновленні", "reassign": "Перепризначити", @@ -1088,6 +1034,7 @@ "reassigned_assets_to_new_person": "Перепризначено {count, plural, one {# ресурс} other {# ресурси}} новій особі", "reassing_hint": "Призначити обрані ресурси існуючій особі", "recent": "Нещодавно", + "recent-albums": "Останні альбоми", "recent_searches": "Нещодавні пошукові запити", "refresh": "Оновити", "refresh_encoded_videos": "Оновити закодовані відео", @@ -1109,6 +1056,7 @@ "remove_from_album": "Видалити з альбому", "remove_from_favorites": "Видалити з обраного", "remove_from_shared_link": "Видалити зі спільного посилання", + "remove_url": "Видалити URL", "remove_user": "Видалити користувача", "removed_api_key": "Видалено ключ API: {name}", "removed_from_archive": "Видалено з архіву", @@ -1125,7 +1073,6 @@ "reset": "Скидання", "reset_password": "Скинути пароль", "reset_people_visibility": "Відновити видимість людей", - "reset_settings_to_default": "", "reset_to_default": "Скидання до налаштувань за замовчуванням", "resolve_duplicates": "Усунути дублікати", "resolved_all_duplicates": "Усі дублікати усунуто", @@ -1145,9 +1092,7 @@ "saved_settings": "Налаштування збережено", "say_something": "Скажіть що-небудь", "scan_all_libraries": "Сканувати всі бібліотеки", - "scan_all_library_files": "Повторне сканування всіх файлів бібліотеки", "scan_library": "Сканувати", - "scan_new_library_files": "Сканування нових файлів бібліотеки", "scan_settings": "Налаштування сканування", "scanning_for_album": "Сканування альбому...", "search": "Пошук", @@ -1190,7 +1135,6 @@ "selected_count": "{count, plural, one {# обраний} other {# обраних}}", "send_message": "Надіслати повідомлення", "send_welcome_email": "Надішліть вітальний лист", - "server": "Сервер", "server_offline": "Сервер офлайн", "server_online": "Сервер онлайн", "server_stats": "Статистика сервера", @@ -1254,7 +1198,7 @@ "sort_oldest": "Старі фото", "sort_recent": "Нещодавні", "sort_title": "Заголовок", - "source": "Джерело", + "source": "Вихідний код", "stack": "У стопку", "stack_duplicates": "Групувати дублікати", "stack_select_one_photo": "Вибрати одне основне фото для групи", @@ -1295,17 +1239,17 @@ "they_will_be_merged_together": "Вони будуть об'єднані разом", "third_party_resources": "Ресурси третіх сторін", "time_based_memories": "Спогади, що базуються на часі", + "timeline": "Хронологія", "timezone": "Часовий пояс", "to_archive": "Архів", "to_change_password": "Змінити пароль", "to_favorite": "Обране", "to_login": "Вхід", "to_parent": "Повернутись назад", - "to_root": "На початок", "to_trash": "Смітник", "toggle_settings": "Перемикання налаштувань", "toggle_theme": "Перемикання теми", - "toggle_visibility": "Перемикання видимості", + "total": "Усього", "total_usage": "Загальне використання", "trash": "Кошик", "trash_all": "Видалити все", @@ -1315,12 +1259,10 @@ "trashed_items_will_be_permanently_deleted_after": "Видалені елементи будуть остаточно видалені через {days, plural, one {# день} few {# дні} many {# днів} other {# днів}}.", "type": "Тип", "unarchive": "Розархівувати", - "unarchived": "", "unarchived_count": "{count, plural, other {Повернуто з архіву #}}", "unfavorite": "Видалити з улюблених", "unhide_person": "Розкрити особу", "unknown": "Невідомо", - "unknown_album": "", "unknown_year": "Невідомий рік", "unlimited": "Без обмежень", "unlink_motion_video": "Від'єднати рухоме відео", @@ -1352,13 +1294,13 @@ "use_custom_date_range": "Використовувати користувацький діапазон дат", "user": "Користувач", "user_id": "ID Користувача", - "user_license_settings": "Ліцензія", - "user_license_settings_description": "Керування ліцензією", "user_liked": "{user} вподобав {type, select, photo {це фото} video {це відео} asset {цей ресурс} other {це}}", "user_purchase_settings": "Придбати", "user_purchase_settings_description": "Керувати вашою покупкою", "user_role_set": "Призначити {user} на роль {role}", "user_usage_detail": "Деталі використання користувача", + "user_usage_stats": "Статистика використання акаунта", + "user_usage_stats_description": "Переглянути статистику використання акаунта", "username": "Ім'я користувача", "users": "Користувачі", "utilities": "Утиліти", @@ -1366,7 +1308,7 @@ "variables": "Змінні", "version": "Версія", "version_announcement_closing": "Твій друг, Алекс", - "version_announcement_message": "Привіт, друг! В нас є нова версія додатку. Будь ласка, відвідайте релізні нотатки і переконайтеся, що ваші файли docker-compose.yml та .env актуальні, щоб уникнути будь-яких помилок конфігурації, особливо якщо ви використовуєте WatchTower або інші механізми автоматичного оновлення додатку.", + "version_announcement_message": "Привіт! Доступна нова версія Immich. Будь ласка, приділіть трохи часу для ознайомлення з примітками до випуску, щоб переконатися, що ваша установка оновлена і уникнути можливих помилок у налаштуваннях, особливо якщо ви використовуєте WatchTower або будь-який інший механізм, який автоматично оновлює ваш екземпляр Immich.", "version_history": "Історія версій", "version_history_item": "Встановлено {version} {date}", "video": "Відео", @@ -1380,10 +1322,10 @@ "view_all_users": "Переглянути всіх користувачів", "view_in_timeline": "Переглянути в хронології", "view_links": "Переглянути посилання", + "view_name": "Переглянути", "view_next_asset": "Переглянути наступний ресурс", "view_previous_asset": "Переглянути попередній ресурс", "view_stack": "Перегляд стеку", - "viewer": "", "visibility_changed": "Видимість змінено для {count, plural, one {# особи} few {# осіб} many {# осіб} other {# осіб}}", "waiting": "Очікують", "warning": "Попередження", diff --git a/i18n/ur.json b/i18n/ur.json new file mode 100644 index 0000000000000..0967ef424bce6 --- /dev/null +++ b/i18n/ur.json @@ -0,0 +1 @@ +{} diff --git a/i18n/vi.json b/i18n/vi.json index 2152814fb9b7e..9c30ea29356e8 100644 --- a/i18n/vi.json +++ b/i18n/vi.json @@ -1,5 +1,5 @@ { - "about": "Giới thiệu", + "about": "Làm mới", "account": "Tài khoản", "account_settings": "Cài đặt tài khoản", "acknowledge": "Ghi nhận", @@ -34,6 +34,11 @@ "authentication_settings_disable_all": "Bạn có chắc chắn muốn vô hiệu hoá tất cả các phương thức đăng nhập? Đăng nhập sẽ bị vô hiệu hóa hoàn toàn.", "authentication_settings_reenable": "Để bật lại, dùng Lệnh Máy chủ.", "background_task_job": "Các tác vụ nền", + "backup_database": "Sao lưu dữ liệu", + "backup_database_enable_description": "Kích hoạt Sao lưu dữ liệu", + "backup_keep_last_amount": "Số lượng các bản Sao lưu được giữ lại", + "backup_settings": "Cài đặt sao lưu", + "backup_settings_description": "Quản lý các thông số cài đặt của Sao lưu dữ liệu", "check_all": "Chọn tất cả", "cleared_jobs": "Đã xoá các tác vụ: {job}", "config_set_by_file": "Cấu hình hiện tại đang được đặt bởi một tập tin cấu hình", @@ -43,9 +48,10 @@ "confirm_reprocess_all_faces": "Bạn có chắc chắn muốn xử lý lại tất cả các khuôn mặt? Thao tác này sẽ xoá tên người đã được gán.", "confirm_user_password_reset": "Bạn có chắc chắn muốn đặt lại mật khẩu của {user}?", "create_job": "Tạo tác vụ", - "crontab_guru": "Crontab Guru", + "cron_expression": "Biểu thức Cron", + "cron_expression_description": "Thiết lập khoảng thời gian để quét bằng biểu thức cron. Tham khảo Crontab Guru để biết thêm thông tin.", + "cron_expression_presets": "Mẫu biểu thức Cron", "disable_login": "Vô hiệu hoá đăng nhập", - "disabled": "", "duplicate_detection_job_description": "Sử dụng Học máy để phát hiện các hình ảnh giống nhau. Dựa vào Tìm kiếm Thông Minh", "exclusion_pattern_description": "Quy tắc loại trừ cho bạn bỏ qua các tập tin và thư mục khi quét thư viện của bạn. Điều này hữu ích nếu bạn có các thư mục chứa tập tin bạn không muốn nhập, chẳng hạn như các tập tin RAW.", "external_library_created_at": "Thư viện bên ngoài (được tạo vào {date})", @@ -63,22 +69,15 @@ "image_prefer_wide_gamut": "Ưu tiên gam màu mở rộng", "image_prefer_wide_gamut_setting_description": "Hiển thị hình thu nhỏ ở gam màu Display P3. Điều này giúp giữ màu sắc rực rỡ của những hình ảnh có gam màu rộng, nhưng hình ảnh có thể trông khác trên các thiết bị cũ và trình duyệt cũ. Hình ảnh sRGB được giữ nguyên để tránh thay đổi màu sắc.", "image_preview_description": "Hình ảnh kích thước trung bình đã loại bỏ metadata, được sử dụng khi xem một hình duy nhất và cho Học máy", - "image_preview_format": "Định dạng xem trước", "image_preview_quality_description": "Chất lượng xem trước từ 1-100. Càng cao càng tốt, nhưng sẽ tạo ra các tập tin lớn hơn có thể làm giảm khả năng phản hồi của ứng dụng. Sử dụng giá trị thấp có thể ảnh hưởng đến chất lượng tác vụ Học máy.", - "image_preview_resolution": "Độ phân giải xem trước", - "image_preview_resolution_description": "Được sử dụng khi xem một bức ảnh và cho machine learning. Độ phân giải cao hơn có thể giữ lại nhiều chi tiết hơn nhưng mất nhiều thời gian mã hóa, có kích thước lớn hơn và có thể làm giảm khả năng phản hồi của ứng dụng.", "image_preview_title": "Cài đặt Xem trước", "image_quality": "Chất lượng", - "image_quality_description": "Chất lượng hình ảnh từ 1 - 100. Giá trị càng cao hình ảnh đẹp hơn nhưng kích thước tập tin sẽ lớn, lựa chọn này ảnh hưởng tới ảnh xem trước và ảnh thu nhỏ.", "image_resolution": "Độ phân giải", "image_resolution_description": "Độ phân giải cao hơn sẽ rõ nét hơn nhưng tốn nhiều thời gian hơn để mã hóa, kích thước tập tin lớn hơn và có thể làm giảm khả năng phản hồi của ứng dụng.", "image_settings": "Hình ảnh", "image_settings_description": "Quản lý chất lượng và độ phân giải của hình ảnh được tạo", "image_thumbnail_description": "Hình thu nhỏ kích thước nhỏ đã loại bỏ metadata, dùng khi xem nhiều ảnh cùng lúc, ví dụ như xem Dòng Thời gian chính", - "image_thumbnail_format": "Định dạng ảnh thu nhỏ", "image_thumbnail_quality_description": "Chất lượng hình thu nhỏ từ 1-100. Càng cao càng tốt, nhưng sẽ tạo ra các tập tin lớn hơn có thể làm giảm khả năng phản hồi của ứng dụng.", - "image_thumbnail_resolution": "Độ phân giải ảnh thu nhỏ", - "image_thumbnail_resolution_description": "Dùng khi xem một nhóm các ảnh (dòng thời gian chính, xem album, v.v.). Độ phân giải cao hơn có thể giữ lại nhiều chi tiết hơn nhưng mất nhiều thời gian mã hóa, có kích thước lớn hơn và có thể làm giảm khả năng phản hồi của ứng dụng.", "image_thumbnail_title": "Cài đặt hình thu nhỏ", "job_concurrency": "{job} thực hiện đồng thời", "job_created": "Tác vụ đã được tạo", @@ -89,9 +88,6 @@ "jobs_delayed": "{jobCount, plural, other {# tác vụ bị hoãn lại}}", "jobs_failed": "{jobCount, plural, other {# tác vụ bị thất bại}}", "library_created": "Đã tạo thư viện: {library}", - "library_cron_expression": "Cú pháp Cron", - "library_cron_expression_description": "Đặt lịch quét bằng định dạng Cron. Để biết thêm về định dạng hãy tham khảo Crontab Guru", - "library_cron_expression_presets": "Các mẫu biểu thức Cron", "library_deleted": "Thư viện đã bị xoá", "library_import_path_description": "Chọn thư mục để nhập. Ứng dụng sẽ quét tất cả hình ảnh và video trong thư mục này bao gồm các thư mục con.", "library_scanning": "Quét định kỳ", @@ -215,7 +211,6 @@ "refreshing_all_libraries": "Làm mới tất cả các thư viện", "registration": "Đăng ký Quản trị viên", "registration_description": "Vì bạn là người dùng đầu tiên, bạn sẽ trở thành Quản trị viên và chịu trách nhiệm cho việc quản lý hệ thống. Ngoài ra, bạn có thể thêm các người dùng khác.", - "removing_deleted_files": "Đang xoá các tập tin ngoại tuyến", "repair_all": "Sửa chữa tất cả", "repair_matched_items": "Đã tìm thấy {count, plural, one {# mục} other {# mục}} trùng khớp", "repaired_items": "Đã sửa chữa {count, plural, one{# mục} other {# mục}}", @@ -223,8 +218,6 @@ "reset_settings_to_default": "Đặt lại cài đặt về mặc định", "reset_settings_to_recent_saved": "Đặt lại cài đặt về cài đặt trước đó", "scanning_library": "Quét thư viện", - "scanning_library_for_changed_files": "Đang quét thư viện để tìm các tập tin đã thay đổi", - "scanning_library_for_new_files": "Đang quét thư viện để tìm các tập tin mới", "search_jobs": "Tìm kiếm tác vụ...", "send_welcome_email": "Gửi email chào mừng", "server_external_domain_settings": "Tên miền công khai", @@ -261,7 +254,6 @@ "these_files_matched_by_checksum": "Các tập tin này khớp với các giá trị băm của chúng", "thumbnail_generation_job": "Tạo hình thu nhỏ", "thumbnail_generation_job_description": "Tạo hình thu nhỏ lớn, nhỏ và mờ cho mỗi ảnh, cũng như hình thu nhỏ cho mỗi người", - "transcode_policy_description": "", "transcoding_acceleration_api": "API Tăng tốc", "transcoding_acceleration_api_description": "API này sẽ tương tác với thiết bị của bạn để tăng tốc quá trình chuyển mã. Cài đặt này hoạt động theo nguyên tắc 'cố gắng hết sức'': nó sẽ quay lại chuyển mã phần mềm nếu gặp lỗi. VP9 có thể hoạt động hoặc không tùy thuộc vào phần cứng của bạn.", "transcoding_acceleration_nvenc": "NVENC (yêu cầu GPU NVIDIA)", @@ -313,8 +305,6 @@ "transcoding_threads_description": "Giá trị cao hơn dẫn đến mã hóa nhanh hơn nhưng để lại ít không gian hơn cho máy chủ xử lý các tác vụ khác khi đang hoạt động. Giá trị này không nên vượt quá số lượng lõi CPU. Tối đa hóa sử dụng nếu đặt thành 0.", "transcoding_tone_mapping": "Ánh Xạ Sắc Thái (Tone-mapping)", "transcoding_tone_mapping_description": "Cố gắng duy trì chất lượng video tốt nhất khi chuyển đổi từ HDR sang SDR. Mỗi thuật toán có sự đánh đổi khác nhau về màu sắc, chi tiết và độ sáng. Hable giữ chi tiết, Mobius giữ màu sắc và Reinhard giữ độ sáng.", - "transcoding_tone_mapping_npl": "Ánh Xạ Sắc Thái NPL (Tone-mapping NPL)", - "transcoding_tone_mapping_npl_description": "Màu sắc sẽ được điều chỉnh để trông bình thường với độ sáng của màn hình này. Theo cách trái ngược, giá trị thấp hơn sẽ tăng độ sáng của video và ngược lại vì nó bù đắp cho độ sáng của màn hình. Giá trị 0 để tự động thiết lập giá trị này.", "transcoding_transcode_policy": "Quy tắc chuyển mã", "transcoding_transcode_policy_description": "Quy tắc khi nào video nên được chuyển mã. Các video HDR luôn được chuyển mã (ngoại trừ khi tính năng chuyển mã bị tắt).", "transcoding_two_pass_encoding": "Mã hóa hai lần", @@ -395,7 +385,6 @@ "archive_or_unarchive_photo": "Lưu trữ hoặc huỷ lưu trữ ảnh", "archive_size": "Kích thước gói nén", "archive_size_description": "Cấu hình kích thước nén cho các tập tin tải xuống (đơn vị GiB)", - "archived": "", "archived_count": "{count, plural, other {Đã lưu trữ # mục}}", "are_these_the_same_person": "Đây có phải cùng một người không?", "are_you_sure_to_do_this": "Bạn có chắc chắn muốn thực hiện điều này không?", @@ -445,10 +434,6 @@ "cannot_merge_people": "Không thể hợp nhất người", "cannot_undo_this_action": "Bạn không thể hoàn tác hành động này!", "cannot_update_the_description": "Không thể cập nhật mô tả", - "cant_apply_changes": "", - "cant_get_faces": "", - "cant_search_people": "", - "cant_search_places": "", "change_date": "Thay đổi ngày", "change_expiration_time": "Thay đổi thời gian hết hạn", "change_location": "Thay đổi vị trí", @@ -480,6 +465,7 @@ "confirm": "Xác nhận", "confirm_admin_password": "Xác nhận mật khẩu quản trị viên", "confirm_delete_shared_link": "Bạn có chắc chắn muốn xóa liên kết chia sẻ này không?", + "confirm_keep_this_delete_others": "Các hình còn lại trong stack này sẽ bị xoá ngoại trừ hình này. Bạn có chắc chắn tiếp tục không?", "confirm_password": "Xác nhận mật khẩu", "contain": "Chứa", "context": "Ngữ cảnh", @@ -529,6 +515,7 @@ "delete_key": "Xóa khóa", "delete_library": "Xóa Thư viện", "delete_link": "Xóa liên kết", + "delete_others": "Xoá các hình còn lại", "delete_shared_link": "Xóa liên kết chia sẻ", "delete_tag": "Xóa thẻ", "delete_tag_confirmation_prompt": "Bạn có chắc chắn muốn xóa thẻ {tagName} không?", @@ -562,13 +549,6 @@ "duplicates": "Mục trùng lặp", "duplicates_description": "Xem lại các nhóm ảnh bị nghi ngờ trùng lặp và chọn những mục bạn muốn giữ hoặc xóa", "duration": "Thời gian", - "durations": { - "days": "", - "hours": "", - "minutes": "", - "months": "", - "years": "" - }, "edit": "Chỉnh sửa", "edit_album": "Chỉnh sửa album", "edit_avatar": "Chỉnh sửa ảnh đại diện", @@ -593,8 +573,6 @@ "editor_crop_tool_h2_aspect_ratios": "Tỷ lệ khung hình", "editor_crop_tool_h2_rotation": "Xoay", "email": "Email", - "empty": "", - "empty_album": "", "empty_trash": "Dọn sạch thùng rác", "empty_trash_confirmation": "Bạn có chắc chắn muốn dọn sạch thùng rác không? Điều này sẽ xóa vĩnh viễn tất cả các mục trong thùng rác khỏi Immich.\nBạn không thể hoàn tác hành động này!", "enable": "Bật", @@ -628,6 +606,7 @@ "failed_to_create_shared_link": "Không thể tạo liên kết chia sẻ", "failed_to_edit_shared_link": "Không thể chỉnh sửa liên kết chia sẻ", "failed_to_get_people": "Không thể tải người", + "failed_to_keep_this_delete_others": "Có lỗi trong quá trình xoá các hình", "failed_to_load_asset": "Không thể tải ảnh", "failed_to_load_assets": "Không thể tải các ảnh", "failed_to_load_people": "Không thể tải người", @@ -655,8 +634,6 @@ "unable_to_change_location": "Không thể thay đổi vị trí", "unable_to_change_password": "Không thể thay đổi mật khẩu", "unable_to_change_visibility": "Không thể thay đổi trạng thái hiển thị cho {count, plural, one {# người} other {# người}}", - "unable_to_check_item": "", - "unable_to_check_items": "", "unable_to_complete_oauth_login": "Không thể hoàn tất đăng nhập OAuth", "unable_to_connect": "Không thể kết nối", "unable_to_connect_to_server": "Không thể kết nối đến máy chủ", @@ -697,12 +674,10 @@ "unable_to_remove_album_users": "Không thể xóa người dùng khỏi album", "unable_to_remove_api_key": "Không thể xóa khóa API", "unable_to_remove_assets_from_shared_link": "Không thể xóa các mục đã chọn khỏi liên kết chia sẻ", - "unable_to_remove_comment": "", "unable_to_remove_deleted_assets": "Không thể xóa tập tin ngoại tuyến", "unable_to_remove_library": "Không thể xóa thư viện", "unable_to_remove_partner": "Không thể xóa người thân", "unable_to_remove_reaction": "Không thể xóa phản ứng", - "unable_to_remove_user": "", "unable_to_repair_items": "Không thể sửa chữa các mục", "unable_to_reset_password": "Không thể đặt lại mật khẩu", "unable_to_resolve_duplicate": "Không thể xử lý trùng lặp", @@ -732,10 +707,6 @@ "unable_to_update_user": "Không thể cập nhật người dùng", "unable_to_upload_file": "Không thể tải tập tin lên" }, - "every_day_at_onepm": "", - "every_night_at_midnight": "", - "every_night_at_twoam": "", - "every_six_hours": "", "exif": "Exif", "exit_slideshow": "Thoát trình chiếu", "expand_all": "Mở rộng tất cả", @@ -750,33 +721,27 @@ "external": "Bên ngoài", "external_libraries": "Thư viện bên ngoài", "face_unassigned": "Chưa được gán", - "failed_to_get_people": "", "favorite": "Yêu thích", "favorite_or_unfavorite_photo": "Yêu thích hoặc bỏ yêu thích ảnh", "favorites": "Ảnh yêu thích", - "feature": "", "feature_photo_updated": "Đã cập nhật ảnh nổi bật", - "featurecollection": "", "features": "Tính năng", "features_setting_description": "Quản lý các tính năng ứng dụng", "file_name": "Tên tập tin", "file_name_or_extension": "Tên hoặc phần mở rộng tập tin", "filename": "Tên tập tin", - "files": "", "filetype": "Loại tập tin", "filter_people": "Lọc người", "find_them_fast": "Tìm nhanh bằng tên với tìm kiếm", "fix_incorrect_match": "Sửa lỗi trùng khớp không chính xác", "folders": "Thư mục", "folders_feature_description": "Duyệt ảnh và video theo thư mục trên hệ thống tập tin", - "force_re-scan_library_files": "Yêu cầu quét lại tất cả các tập tin thư viện", "forward": "Tiến về phía trước", "general": "Chung", "get_help": "Nhận trợ giúp", "getting_started": "Bắt đầu", "go_back": "Quay lại", "go_to_search": "Đi đến tìm kiếm", - "go_to_share_page": "Đi đến trang chia sẻ", "group_albums_by": "Nhóm album theo...", "group_no": "Không nhóm", "group_owner": "Nhóm theo chủ sở hữu", @@ -802,7 +767,6 @@ "image_alt_text_date_place_2_people": "{isVideo, select, true {Video} other {Hình ảnh}} được chụp tại {city}, {country} với {person1} và {person2} vào {date}", "image_alt_text_date_place_3_people": "{isVideo, select, true {Video} other {Hình ảnh}} được chụp tại {city}, {country} với {person1}, {person2}, và {person3} vào {date}", "image_alt_text_date_place_4_or_more_people": "{isVideo, select, true {Video} other {Hình ảnh}} được chụp tại {city}, {country} với {person1}, {person2}, và {additionalCount, number} người khác vào {date}", - "img": "", "immich_logo": "Logo Immich", "immich_web_interface": "Giao diện web Immich", "import_from_json": "Nhập từ JSON", @@ -823,10 +787,10 @@ "invite_people": "Mời mọi người", "invite_to_album": "Mời vào album", "items_count": "{count, plural, one {# mục} other {# mục}}", - "job_settings_description": "", "jobs": "Tác vụ", "keep": "Giữ", "keep_all": "Giữ tất cả", + "keep_this_delete_others": "Giữ tấm này và xoá tất cả còn lại", "keyboard_shortcuts": "Phím tắt", "language": "Ngôn ngữ", "language_setting_description": "Chọn ngôn ngữ ưa thích của bạn", @@ -942,7 +906,6 @@ "onboarding_welcome_user": "Chào mừng, {user}", "online": "Trực tuyến", "only_favorites": "Chỉ yêu thích", - "only_refreshes_modified_files": "Chỉ làm mới các tập tin đã thay đổi", "open_in_map_view": "Mở trong bản đồ", "open_in_openstreetmap": "Mở trong OpenStreetMap", "open_the_search_filters": "Mở bộ lọc tìm kiếm", @@ -980,7 +943,6 @@ "people_edits_count": "Đã chỉnh sửa {count, plural, one {# người} other {# người}}", "people_feature_description": "Duyệt ảnh và video được nhóm theo người", "people_sidebar_description": "Hiển thị mục Mọi người trong thanh bên", - "perform_library_tasks": "", "permanent_deletion_warning": "Cảnh báo xóa vĩnh viễn", "permanent_deletion_warning_setting_description": "Hiển thị cảnh báo khi xóa vĩnh viễn ảnh", "permanently_delete": "Xóa vĩnh viễn", @@ -1002,7 +964,6 @@ "play_memories": "Phát kỷ niệm", "play_motion_photo": "Phát ảnh chuyển động", "play_or_pause_video": "Phát hoặc tạm dừng video", - "point": "", "port": "Cổng", "preset": "Mẫu có sẵn", "preview": "Xem trước", @@ -1047,12 +1008,10 @@ "purchase_server_description_2": "Trạng thái người hỗ trợ", "purchase_server_title": "Máy chủ", "purchase_settings_server_activated": "Khóa sản phẩm máy chủ được quản lý bởi quản trị viên", - "range": "", "rating": "Xếp hạng sao", "rating_clear": "Xóa đánh giá", "rating_count": "{count, plural, one {# sao} other {# sao}}", "rating_description": "Hiển thị xếp hạng EXIF trong bảng thông tin", - "raw": "", "reaction_options": "Tùy chọn phản ứng", "read_changelog": "Đọc nhật ký thay đổi", "reassign": "Gán lại", @@ -1097,7 +1056,6 @@ "reset": "Đặt lại", "reset_password": "Đặt lại mật khẩu", "reset_people_visibility": "Đặt lại trạng thái hiển thị của mọi người", - "reset_settings_to_default": "", "reset_to_default": "Đặt lại về mặc định", "resolve_duplicates": "Xử lý các bản trùng lặp", "resolved_all_duplicates": "Đã xử lý tất cả các bản trùng lặp", @@ -1117,9 +1075,7 @@ "saved_settings": "Cài đặt đã lưu", "say_something": "Nói điều gì đó", "scan_all_libraries": "Quét tất cả thư viện", - "scan_all_library_files": "Quét lại tất cả các tập tin thư viện", "scan_library": "Quét", - "scan_new_library_files": "Quét các tập tin thư viện mới", "scan_settings": "Cài đặt quét", "scanning_for_album": "Đang quét album...", "search": "Tìm kiếm", @@ -1162,7 +1118,6 @@ "selected_count": "{count, plural, other {Đã chọn # mục}}", "send_message": "Gửi tin nhắn", "send_welcome_email": "Gửi email chào mừng", - "server": "", "server_offline": "Máy chủ ngoại tuyến", "server_online": "Máy chủ trực tuyến", "server_stats": "Thống kê máy chủ", @@ -1273,11 +1228,9 @@ "to_favorite": "Yêu thích", "to_login": "Đăng nhập", "to_parent": "Đến thư mục cha", - "to_root": "Tới thư mục gốc", "to_trash": "Xóa", "toggle_settings": "Chuyển đổi cài đặt", "toggle_theme": "Chuyển đổi chủ đề tối", - "toggle_visibility": "", "total_usage": "Tổng dung lượng đã sử dụng", "trash": "Thùng rác", "trash_all": "Xóa hết", @@ -1287,12 +1240,10 @@ "trashed_items_will_be_permanently_deleted_after": "Các mục đã xóa sẽ bị xóa vĩnh viễn sau {days, plural, one {# ngày} other {# ngày}}.", "type": "Loại", "unarchive": "Huỷ lưu trữ", - "unarchived": "", "unarchived_count": "{count, plural, other {Đã huỷ lưu trữ # mục}}", "unfavorite": "Bỏ yêu thích", "unhide_person": "Hiện người", "unknown": "Không xác định", - "unknown_album": "", "unknown_year": "Năm không xác định", "unlimited": "Không giới hạn", "unlink_motion_video": "Hủy liên kết video chuyển động", @@ -1336,7 +1287,7 @@ "variables": "Các tham số", "version": "Phiên bản", "version_announcement_closing": "Bạn của bạn, Alex", - "version_announcement_message": "Chào bạn, có một phiên bản mới của ứng dụng. Vui lòng dành thời gian để xem ghi chú phát hành và đảm bảo rằng cấu hình docker-compose.yml.env của bạn được cập nhật để tránh bất kỳ cấu hình sai nào, đặc biệt nếu bạn sử dụng WatchTower hoặc bất kỳ cơ chế nào tự động cập nhật ứng dụng của bạn.", + "version_announcement_message": "Chào bạn! Một phiên bản mới của Immich đã phát hành. Vui lòng dành thời gian để xem danh sách thay đổi để đảm bảo cấu hình của bạn được cập nhật để tránh lỗi cấu hình sai, đặc biệt nếu bạn sử dụng WatchTower hoặc bất kỳ cơ chế tự động cập nhật Immich của bạn.", "version_history": "Lịch sử phiên bản", "version_history_item": "Đã cài đặt {version} vào {date}", "video": "Video", @@ -1353,13 +1304,12 @@ "view_next_asset": "Xem ảnh tiếp theo", "view_previous_asset": "Xem ảnh trước đó", "view_stack": "Xem nhóm ảnh", - "viewer": "", "visibility_changed": "Đã thay đổi trạng thái hiển thị cho {count, plural, one {# người} other {# người}}", "waiting": "Đang chờ", "warning": "Cảnh báo", "week": "Tuần", "welcome": "Chào mừng", - "welcome_to_immich": "Chào mừng đến với immich", + "welcome_to_immich": "Chào mừng đến với Immich", "year": "Năm", "years_ago": "{years, plural, one {# năm} other {# năm}} trước", "yes": "Có", diff --git a/i18n/zh_Hant.json b/i18n/zh_Hant.json index 8b1e1e5e15aeb..d343f8954466e 100644 --- a/i18n/zh_Hant.json +++ b/i18n/zh_Hant.json @@ -1,60 +1,67 @@ { - "about": "關於", - "account": "賬號", - "account_settings": "賬號設定", + "about": "重新整理", + "account": "帳號", + "account_settings": "帳號設定", "acknowledge": "收到", "action": "操作", "actions": "操作", - "active": "活躍", - "activity": "活動", - "activity_changed": "活動已{enabled, select, true {啟用} other {停用}}", - "add": "新增", - "add_a_description": "新增敘述", - "add_a_location": "新增位置", - "add_a_name": "新增名稱", + "active": "處理中", + "activity": "動態", + "activity_changed": "動態已{enabled, select, true {啟用} other {停用}}", + "add": "加入", + "add_a_description": "加入文字說明", + "add_a_location": "新增地點", + "add_a_name": "加入姓名", "add_a_title": "新增標題", - "add_exclusion_pattern": "新增排除規則", - "add_import_path": "新增引入路徑", + "add_exclusion_pattern": "加入篩選條件", + "add_import_path": "新增匯入路徑", "add_location": "新增地點", - "add_more_users": "新增更多使用者", - "add_partner": "新增同伴", + "add_more_users": "新增其他使用者", + "add_partner": "新增親朋好友", "add_path": "新增路徑", - "add_photos": "增加照片", - "add_to": "新增至…", - "add_to_album": "加入相簿", - "add_to_shared_album": "加入共享相簿", - "added_to_archive": "已加入歸檔", - "added_to_favorites": "已加入收藏", - "added_to_favorites_count": "已把 {count, number} 個項目加入收藏", + "add_photos": "加入照片", + "add_to": "加入到…", + "add_to_album": "加入到相簿", + "add_to_shared_album": "加到共享相簿", + "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/**」。", - "asset_offline_description": "磁碟上找不到此外部圖庫檔案,且已移至垃圾桶。如果檔案在圖庫內被移動,請檢查時間軸中是否有新的相應的檔案。若要還原這份檔案,請確保 Immich 可以寫入下列檔案路徑,並讀取掃描圖庫內容。", + "add_exclusion_pattern_description": "新增排除條件。支援使用「*」、「 **」、「?」來找尋符合規則的字串。如果要在任何名為「Raw」的目錄內排除所有符合條件的檔案,請使用「**/Raw/**」。如果要排除所有「.tif」結尾的檔案,請使用「**/*.tif」。如果要排除某個絕對路徑,請使用「/path/to/ignore/**」。", + "asset_offline_description": "磁碟上找不到此外部相簿檔案,且已移至垃圾桶。如果檔案在相簿內被移動,請檢查時間軸中是否有新的相應的檔案。若要還原這份檔案,請確保 Immich 可以寫入下列檔案路徑,並讀取掃描相簿內容。", "authentication_settings": "驗證設定", "authentication_settings_description": "管理密碼、OAuth 與其他驗證設定", "authentication_settings_disable_all": "確定要停用所有登入方式嗎?這樣會完全無法登入。", "authentication_settings_reenable": "如需重新啟用,請使用 伺服器指令。", - "background_task_job": "背景任務", + "background_task_job": "背景執行", + "backup_database": "備份資料庫", + "backup_database_enable_description": "啟用資料庫備份", + "backup_keep_last_amount": "保留先前備份的數量", + "backup_settings": "備份設定", + "backup_settings_description": "管理資料庫備份設定", "check_all": "全選", - "cleared_jobs": "已為「{job}」清除作業", - "config_set_by_file": "目前的設定已透過配置文檔調整", - "confirm_delete_library": "確定要刪除「{library}」(圖庫)嗎?", - "confirm_delete_library_assets": "您確定要移除此圖庫嗎?這將從 Immich 中刪除{count, plural, one {個項目} other {個項目}},且無法復原。檔案仍會保留在硬碟中。", + "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} 的密碼嗎?", "create_job": "建立作業", - "crontab_guru": "", + "cron_expression": "Cron 運算式", + "cron_expression_description": "以 Cron 格式設定掃描時段。詳細資訊請參閱 Crontab Guru", + "cron_expression_presets": "現成的 Cron 運算式", "disable_login": "停用登入", - "disabled": "已禁用", "duplicate_detection_job_description": "對檔案執行機器學習來偵測相似圖片。(此功能仰賴智慧搜尋)", "exclusion_pattern_description": "排除規則讓您在掃描資料庫時忽略特定文件和文件夾。用於當您有不想導入的文件(例如 RAW 文件)或文件夾。", - "external_library_created_at": "外部圖庫(於 {date} 建立)", - "external_library_management": "外部圖庫管理", + "external_library_created_at": "外部相簿(於 {date} 建立)", + "external_library_management": "外部相簿管理", "face_detection": "臉孔偵測", "face_detection_description": "使用機器學習偵測檔案中的臉孔(影片只會偵測縮圖中的臉孔)。選擇「重新整理」會重新處理所有檔案。選擇「重設」會清除目前所有的臉孔資料。選擇「遺失的」會把尚未處理的檔案排入處理佇列。臉孔偵測完成後,會把偵測到的臉孔排入臉部辨識佇列,將其分組到現有的或新的人物中。", "facial_recognition_job_description": "將偵測到的臉孔依照人物分組。此步驟會在臉孔偵測完成後執行。選擇「重設」會重新分組所有臉孔。選擇「遺失的」會把尚未指定人物的臉孔排入佇列。", "failed_job_command": "{job} 任務的 {command} 指令執行失敗", - "force_delete_user_warning": "警告:這將立即移除使用者及其資料。操作後無法反悔且移除的檔案無法恢復。", + "force_delete_user_warning": "警告:這將立即刪除使用者及其資料。操作後無法反悔且刪除的檔案無法恢復。", "forcing_refresh_library_files": "強制重新整理所有圖庫檔案", "image_format": "格式", "image_format_description": "WebP 能產生相對於 JPEG 更小的檔案,但編碼速度較慢。", @@ -62,23 +69,16 @@ "image_prefer_embedded_preview_setting_description": "優先使用 RAW 的嵌入預覧作影像處理。可以提升某些影像的顏色精確度,但嵌入預覧的影像品質依相機而異,且可能壓縮較多。", "image_prefer_wide_gamut": "偏好廣色域", "image_prefer_wide_gamut_setting_description": "使用 Display P3 來製作縮圖。這可以更好地保留廣色域圖片的鮮豔度,但在舊版瀏覽器或舊設備上,圖片可能會顯示不同。sRGB 圖片會維持 sRGB 以避免顏色變化。", - "image_preview_description": "除去元資料的中型圖片,在查看單一檔案和機器學習時使用", - "image_preview_format": "預覽格式", + "image_preview_description": "刪除中等尺寸圖片的詳細資料,當選擇看指定項目和機器學習時使用", "image_preview_quality_description": "預覽品質爲 1 ~ 100。數值越大品質越高,但會產生較大的檔案,且可能降低應用程式的響應速度。而數值較小可能會影響機器學習品質。", - "image_preview_resolution": "預覽解析度", - "image_preview_resolution_description": "觀賞單張照片及機器學習時用。較高的解析度可以保留更多細節,但編碼時間較長,檔案也較大,且可能降低應用程式的響應速度。", "image_preview_title": "預覽設定", "image_quality": "品質", - "image_quality_description": "圖片品質從1到100,數值越高代表品質越好但檔案也越大,此選項影響預覽和縮圖圖片。", "image_resolution": "解析度", "image_resolution_description": "較高的解析度可以保留更多細節,但編碼時間較長,檔案較大且可能降低應用程式的響應速度。", "image_settings": "圖片設定", "image_settings_description": "管理產生圖片的品質和解析度", - "image_thumbnail_description": "除去元資料的小型縮圖,在查看主時間軸等大量照片時使用", - "image_thumbnail_format": "縮圖格式", + "image_thumbnail_description": "刪除縮圖的詳細資料,在快速瀏覽重要時間軸時或大量照片時使用", "image_thumbnail_quality_description": "縮圖品質爲 1 ~ 100。數值越大品質越高,但會產生較大的檔案,且可能降低應用程式的響應速度。", - "image_thumbnail_resolution": "縮圖解析度", - "image_thumbnail_resolution_description": "觀賞多張照片時(時間軸、相簿等)用。較高的解析度可以保留更多細節,但編碼時間較長,檔案也較大,且可能降低應用程式的響應速度。", "image_thumbnail_title": "縮圖設定", "job_concurrency": "{job}並行", "job_created": "已建立作業", @@ -89,10 +89,7 @@ "jobs_delayed": "已延後 {jobCount, plural, other {# 項作業}}", "jobs_failed": "{jobCount, plural, other {# 項}}作業失敗", "library_created": "已建立圖庫:{library}", - "library_cron_expression": "Cron 運算式", - "library_cron_expression_description": "以 Cron 格式設定掃描時段。詳細資訊請參閱 Crontab Guru", - "library_cron_expression_presets": "現成的 Cron 運算式", - "library_deleted": "圖庫已刪除", + "library_deleted": "相簿已刪除", "library_import_path_description": "選取要載入的資料夾。以掃描資料夾(含子資料夾)內的影像和影片。", "library_scanning": "定期掃描", "library_scanning_description": "定期圖庫掃描設定", @@ -134,7 +131,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": "機器學習伺服器的網址,如果提供多個 URL,則將按依序嘗試連接每個伺服器,直到有一個伺服器成功回應為止。", "manage_concurrency": "管理並行", "manage_log_settings": "管理日誌設定", "map_dark_style": "深色樣式", @@ -151,11 +148,11 @@ "map_settings_description": "管理地圖設定", "map_style_description": "地圖主題(style.json)的網址", "metadata_extraction_job": "擷取元資料", - "metadata_extraction_job_description": "擷取每個檔案的 GPS、臉孔、解析度等元資料資訊", + "metadata_extraction_job_description": "擷取所有檔案的 GPS、臉孔、解析度等原始詳細資料", "metadata_faces_import_setting": "啟用臉孔匯入", "metadata_faces_import_setting_description": "從圖片的 EXIF 資料和側接檔案匯入臉孔", - "metadata_settings": "元資料設定", - "metadata_settings_description": "管理元資料設定", + "metadata_settings": "詳細資料設定", + "metadata_settings_description": "管理詮釋資料設定", "migration_job": "遷移", "migration_job_description": "將照片和人臉的縮圖遷移到最新的文件夾結構", "no_paths_added": "未添加路徑", @@ -215,7 +212,6 @@ "refreshing_all_libraries": "正在重新整理所有圖庫", "registration": "管理者註冊", "registration_description": "由於您是本系統的首位使用者,因此將您指派爲負責管理本系統的管理者,其他使用者須由您協助建立帳號。", - "removing_deleted_files": "移除離線檔案中", "repair_all": "全部糾正", "repair_matched_items": "有 {count, plural, other {# 個項目相符}}", "repaired_items": "已糾正 {count, plural, other {# 個項目}}", @@ -223,18 +219,18 @@ "reset_settings_to_default": "將設定重設回預設", "reset_settings_to_recent_saved": "已設回最後儲存的設定", "scanning_library": "掃描圖庫", - "scanning_library_for_changed_files": "掃描圖庫中變更的檔案", - "scanning_library_for_new_files": "掃描圖庫中的新檔案", "search_jobs": "搜尋作業…", "send_welcome_email": "傳送歡迎電子郵件", "server_external_domain_settings": "外部網域", - "server_external_domain_settings_description": "公開分享鏈結的網域(包含「http(s)://」)", + "server_external_domain_settings_description": "公開網址,,包含 http(s)://", + "server_public_users": "訪客使用者", + "server_public_users_description": "將使用者新增至共用相簿時,會列出所有使用者(姓名、email)。關閉時,使用者列表僅對管理者生效。", "server_settings": "伺服器", "server_settings_description": "管理伺服器設定", "server_welcome_message": "歡迎訊息", "server_welcome_message_description": "在登入頁面顯示的訊息。", - "sidecar_job": "側接元資料", - "sidecar_job_description": "從檔案系統探索或同步側接(Sidecar)元資料", + "sidecar_job": "邊車模式詮釋資料", + "sidecar_job_description": "從檔案系統搜索或同步邊車模式詮釋資料", "slideshow_duration_description": "每張圖片放映的秒數", "smart_search_job_description": "對檔案執行機器學習,以利智慧搜尋", "storage_template_date_time_description": "檔案的創建時戳會用於判斷時間資訊", @@ -254,6 +250,13 @@ "storage_template_user_label": "{label} 是使用者的儲存標籤", "system_settings": "系統設定", "tag_cleanup_job": "清理標記", + "template_email_invite_album": "邀請項目範本", + "template_email_preview": "預覽", + "template_email_settings": "Email範本", + "template_email_settings_description": "管理自定義Email通知模板", + "template_email_update_album": "更新向本範本", + "template_email_welcome": "歡迎Email範本", + "template_settings": "通知範本", "theme_custom_css_settings": "自訂 CSS", "theme_custom_css_settings_description": "可以用層疊樣式表(CSS)來自訂 Immich 的設計。", "theme_settings": "主題", @@ -261,7 +264,6 @@ "these_files_matched_by_checksum": "這些檔案的核對和(Checksum)是相符的", "thumbnail_generation_job": "產生縮圖", "thumbnail_generation_job_description": "爲每個檔案產生大、小及模糊縮圖,也爲每位人物產生縮圖", - "transcode_policy_description": "", "transcoding_acceleration_api": "加速 API", "transcoding_acceleration_api_description": "該 API 將用您的設備加速轉碼。設置是“盡力而為”:如果失敗,它將退回到軟件轉碼。VP9 轉碼是否可行取決於您的硬件。", "transcoding_acceleration_nvenc": "NVENC(需要 NVIDIA GPU)", @@ -313,8 +315,6 @@ "transcoding_threads_description": "較高的值會加快編碼速度,但會減少伺服器在運行過程中處理其他任務的空間。此值不應超過 CPU 核心數。設置為 0 可以最大化利用率。", "transcoding_tone_mapping": "色調映射", "transcoding_tone_mapping_description": "在將 HDR 視頻轉換為 SDR 時,嘗試保留其外觀。每種算法在顏色、細節和亮度方面都有不同的權衡。Hable 保留細節,Mobius 保留顏色,Reinhard 保留亮度。", - "transcoding_tone_mapping_npl": "色調映射 NPL", - "transcoding_tone_mapping_npl_description": "顏色將調整為在此亮度顯示器上看起來正常。反直觀地,較低的值會增加視頻的亮度,反之亦然,因為它會補償顯示器的亮度。0 會自動設置此值。", "transcoding_transcode_policy": "轉碼策略", "transcoding_transcode_policy_description": "視頻何時應進行轉碼的策略。HDR 視頻將始終進行轉碼(除非禁用轉碼)。", "transcoding_two_pass_encoding": "雙通道編碼", @@ -329,7 +329,7 @@ "untracked_files": "未被追蹤的檔案", "untracked_files_description": "這些檔案不會被追蹤。它們可能是移動失誤、上傳中斷或遇到漏洞而遺留的產物", "user_cleanup_job": "清理使用者", - "user_delete_delay": "{user} 的帳號和檔案將於 {delay, plural, other {# 天}}後永久刪除。", + "user_delete_delay": "{user} 的帳號和項目將於 {delay, plural, other {# 天}}後永久刪除。", "user_delete_delay_settings": "延後刪除", "user_delete_delay_settings_description": "移除後,永久刪除使用者帳號和檔案的天數。使用者刪除作業會在午夜檢查是否有可以刪除的使用者。變更這項設定後,會在下次執行時檢查。", "user_delete_immediately": "{user} 的帳戶和資產將被立即排隊進行永久刪除。", @@ -373,7 +373,7 @@ "album_updated_setting_description": "當共享相簿有新檔案時,用電子郵件通知我", "album_user_left": "已離開 {album}", "album_user_removed": "已移除 {user}", - "album_with_link_access": "讓知道鏈結的任何人都可以看到此相簿中的照片及人物。", + "album_with_link_access": "知道連結的使用者都可以查看這本相簿中的相片和使用者。", "albums": "相簿", "albums_count": "{count, plural, one {{count, number} 本相簿} other {{count, number} 本相簿}}", "all": "全部", @@ -395,7 +395,6 @@ "archive_or_unarchive_photo": "封存或取消封存照片", "archive_size": "封存量", "archive_size_description": "設定要下載的封存量(單位:GiB)", - "archived": "", "archived_count": "{count, plural, other {已封存 # 個項目}}", "are_these_the_same_person": "這也是同一個人嗎?", "are_you_sure_to_do_this": "您確定要這麼做嗎?", @@ -445,10 +444,6 @@ "cannot_merge_people": "無法合併人物", "cannot_undo_this_action": "此步驟無法取消喔!", "cannot_update_the_description": "無法更新描述", - "cant_apply_changes": "", - "cant_get_faces": "", - "cant_search_people": "", - "cant_search_places": "", "change_date": "更改日期", "change_expiration_time": "更改失效期限", "change_location": "更改位置", @@ -479,7 +474,8 @@ "comments_are_disabled": "評論已禁用", "confirm": "確認", "confirm_admin_password": "確認管理者密碼", - "confirm_delete_shared_link": "確定要刪除這條分享鏈結嗎?", + "confirm_delete_shared_link": "確定刪除連結嗎?", + "confirm_keep_this_delete_others": "所有的其他堆疊項目將被刪除。確定繼續嗎?", "confirm_password": "確認密碼", "contain": "包含", "context": "情境", @@ -489,8 +485,8 @@ "copy_error": "複製錯誤", "copy_file_path": "複製檔案路徑", "copy_image": "複製圖片", - "copy_link": "複製鏈結", - "copy_link_to_clipboard": "將鏈結複製到剪貼簿", + "copy_link": "複製連結", + "copy_link_to_clipboard": "複製連結到剪貼簿", "copy_password": "複製密碼", "copy_to_clipboard": "複製到剪貼簿", "country": "國家", @@ -499,14 +495,14 @@ "create": "建立", "create_album": "建立相簿", "create_library": "建立圖庫", - "create_link": "建立鏈結", - "create_link_to_share": "建立分享鏈結", - "create_link_to_share_description": "允許任何擁有連結的人查看所選的照片", + "create_link": "建立連結", + "create_link_to_share": "建立共享連結", + "create_link_to_share_description": "知道連結的使用者都可以查看這本相簿中的相片", "create_new_person": "創建新人物", "create_new_person_hint": "將選定的檔案分配給新人物", "create_new_user": "建立新使用者", "create_tag": "建立標記", - "create_tag_description": "建立新的標記。若要建立巢狀標記,請輸入完整的標記路徑(包括正斜線 / )。", + "create_tag_description": "建立新的標籤。若要建立不同群組分類標籤,請輸入完整的標籤路徑(包括正斜線 / )。", "create_user": "建立使用者", "created": "建立於", "current_device": "此裝置", @@ -522,18 +518,19 @@ "deduplicate_all": "刪除所有重複項目", "default_locale": "預設區域", "default_locale_description": "依瀏覽器區域設定日期和數字格式", - "delete": "删除", + "delete": "刪除", "delete_album": "刪除相簿", "delete_api_key_prompt": "您確定要刪除這個 API Key嗎?", "delete_duplicates_confirmation": "您確定要永久刪除這些重複項嗎?", "delete_key": "刪除密鑰", "delete_library": "刪除圖庫", "delete_link": "刪除鏈結", - "delete_shared_link": "刪除分享鏈結", + "delete_others": "刪除其他", + "delete_shared_link": "刪除共享鏈結", "delete_tag": "刪除標記", "delete_tag_confirmation_prompt": "確定要刪除「{tagName}」(標記)嗎?", "delete_user": "刪除使用者", - "deleted_shared_link": "已刪除分享鏈結", + "deleted_shared_link": "已刪除共享鏈結", "deletes_missing_assets": "刪除磁碟中遺失的檔案", "description": "描述", "details": "詳情", @@ -562,13 +559,6 @@ "duplicates": "重複項目", "duplicates_description": "通過指示每一組重複的檔案(如果有)來解決問題", "duration": "時長", - "durations": { - "days": "", - "hours": "", - "minutes": "", - "months": "", - "years": "" - }, "edit": "編輯", "edit_album": "編輯相簿", "edit_avatar": "編輯形象", @@ -593,8 +583,6 @@ "editor_crop_tool_h2_aspect_ratios": "長寬比", "editor_crop_tool_h2_rotation": "旋轉", "email": "電子郵件", - "empty": "", - "empty_album": "", "empty_trash": "清空垃圾桶", "empty_trash_confirmation": "確定要清空垃圾桶嗎?這會永久刪除 Immich 垃圾桶中所有的檔案。\n此步驟無法取消喔!", "enable": "啟用", @@ -609,7 +597,7 @@ "cant_apply_changes": "無法套用更改", "cant_change_activity": "無法{enabled, select, true {禁用} other {啟用}}活動", "cant_change_asset_favorite": "無法更改檔案的收藏狀態", - "cant_change_metadata_assets_count": "無法更改 {count, plural, other {# 個檔案}}的元資料", + "cant_change_metadata_assets_count": "無法更改 {count, plural, other {# 個檔案}}的詳細資料", "cant_get_faces": "無法取得臉孔", "cant_get_number_of_comments": "無法獲取評論數量", "cant_search_people": "無法搜尋人", @@ -625,9 +613,10 @@ "exclusion_pattern_already_exists": "此排除模式已存在。", "failed_job_command": "命令 {command} 執行失敗,作業:{job}", "failed_to_create_album": "相簿建立失敗", - "failed_to_create_shared_link": "建立分享鏈結失敗", - "failed_to_edit_shared_link": "編輯分享鏈結失敗", + "failed_to_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_people": "無法載入人物", @@ -641,7 +630,7 @@ "quota_higher_than_disk_size": "您定的配額高於磁碟容量", "repair_unable_to_check_items": "無法檢查 {count, select, other { 個項目}}", "unable_to_add_album_users": "無法將使用者加入相簿", - "unable_to_add_assets_to_shared_link": "無法將檔案加上分享鏈結", + "unable_to_add_assets_to_shared_link": "無法加入項目到共享連結", "unable_to_add_comment": "無法添加評論", "unable_to_add_exclusion_pattern": "無法添加排除模式", "unable_to_add_import_path": "無法添加匯入路徑", @@ -655,8 +644,6 @@ "unable_to_change_location": "無法更改位置", "unable_to_change_password": "無法更改密碼", "unable_to_change_visibility": "無法更改 {count, plural, one {# 位人士} other {# 位人士}} 的可見性", - "unable_to_check_item": "", - "unable_to_check_items": "", "unable_to_complete_oauth_login": "無法完成 OAuth 登入", "unable_to_connect": "無法連接", "unable_to_connect_to_server": "無法連接到伺服器", @@ -670,7 +657,7 @@ "unable_to_delete_assets": "刪除檔案時發生錯誤", "unable_to_delete_exclusion_pattern": "無法刪除排除模式", "unable_to_delete_import_path": "無法刪除匯入路徑", - "unable_to_delete_shared_link": "無法刪除分享鏈結", + "unable_to_delete_shared_link": "刪除共享連結失敗", "unable_to_delete_user": "無法刪除使用者", "unable_to_download_files": "無法下載檔案", "unable_to_edit_exclusion_pattern": "無法編輯排除模式", @@ -679,10 +666,10 @@ "unable_to_enter_fullscreen": "無法進入全螢幕", "unable_to_exit_fullscreen": "無法退出全螢幕", "unable_to_get_comments_number": "無法獲取評論數量", - "unable_to_get_shared_link": "取得分享鏈結失敗", + "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_load_album": "無法載入相簿", "unable_to_load_asset_activity": "無法載入檔案活動", "unable_to_load_items": "無法載入項目", @@ -696,13 +683,11 @@ "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_comment": "", + "unable_to_remove_assets_from_shared_link": "刪除共享連結中檔案失敗", "unable_to_remove_deleted_assets": "無法移除離線檔案", "unable_to_remove_library": "無法移除資料庫", "unable_to_remove_partner": "無法移除夥伴", "unable_to_remove_reaction": "無法移除反應", - "unable_to_remove_user": "", "unable_to_repair_items": "無法糾正項目", "unable_to_reset_password": "無法重設密碼", "unable_to_resolve_duplicate": "無法解決重複項", @@ -732,11 +717,7 @@ "unable_to_update_user": "無法更新使用者", "unable_to_upload_file": "無法上傳檔案" }, - "every_day_at_onepm": "", - "every_night_at_midnight": "", - "every_night_at_twoam": "", - "every_six_hours": "", - "exif": "Exif", + "exif": "EXIF", "exit_slideshow": "退出幻燈片", "expand_all": "展開全部", "expire_after": "失效時間", @@ -750,13 +731,10 @@ "external": "外部", "external_libraries": "外部圖庫", "face_unassigned": "未指定", - "failed_to_get_people": "", "favorite": "收藏", "favorite_or_unfavorite_photo": "收藏或取消收藏照片", "favorites": "收藏", - "feature": "", "feature_photo_updated": "特色照片已更新", - "featurecollection": "", "features": "功能", "features_setting_description": "管理應用程式功能", "file_name": "檔名", @@ -768,15 +746,13 @@ "fix_incorrect_match": "修復不相符的", "folders": "資料夾", "folders_feature_description": "以資料夾瀏覽檔案系統中的照片和影片", - "force_re-scan_library_files": "強制重新掃描所有圖庫檔案", "forward": "順序", "general": "一般", "get_help": "線上求助", "getting_started": "開始使用", "go_back": "返回", "go_to_search": "前往搜尋", - "go_to_share_page": "前往分享頁面", - "group_albums_by": "相簿分組方式", + "group_albums_by": "分類群組的方式...", "group_no": "無分組", "group_owner": "按擁有者分組", "group_year": "按年份分組", @@ -801,7 +777,6 @@ "image_alt_text_date_place_2_people": "{isVideo, select, true {影片} other {圖片}} 在 {city}、{country},與 {person1} 和 {person2} 一同於 {date} 拍攝", "image_alt_text_date_place_3_people": "{isVideo, select, true {影片} other {圖片}} 在 {city}、{country},與 {person1}、{person2} 和 {person3} 一同於 {date} 拍攝", "image_alt_text_date_place_4_or_more_people": "{isVideo, select, true {影片} other {圖片}} 在 {city}、{country},與 {person1}、{person2} 和其他 {additionalCount, number} 人於 {date} 拍攝", - "img": "", "immich_logo": "Immich 標誌", "immich_web_interface": "Immich 網頁介面", "import_from_json": "匯入 JSON", @@ -822,10 +797,11 @@ "invite_people": "邀請人員", "invite_to_album": "邀請至相簿", "items_count": "{count, plural, other {# 個項目}}", - "job_settings_description": "", "jobs": "作業", "keep": "保留", "keep_all": "全部保留", + "keep_this_delete_others": "保留這個,刪除其他", + "kept_this_deleted_others": "保留這個項目並刪除{count, plural, one {# asset} other {# assets}}", "keyboard_shortcuts": "鍵盤快捷鍵", "language": "語言", "language_setting_description": "選擇您的首選語言", @@ -860,7 +836,7 @@ "loop_videos_description": "啟用後,影片結束會自動重播。", "main_branch_warning": "現在使用的是開發版本;我們強烈建議使用正式發行版!", "make": "製造商", - "manage_shared_links": "管理分享鏈結", + "manage_shared_links": "管理共享連結", "manage_sharing_with_partners": "管理與夥伴的分享", "manage_the_app_settings": "管理應用程式設定", "manage_your_account": "管理您的帳號", @@ -941,7 +917,6 @@ "onboarding_welcome_user": "歡迎,{user}", "online": "在線", "only_favorites": "僅顯示己收藏", - "only_refreshes_modified_files": "只重新整理修改過的檔案", "open_in_map_view": "開啟地圖檢視", "open_in_openstreetmap": "用 OpenStreetMap 開啟", "open_the_search_filters": "開啟搜尋篩選器", @@ -1000,7 +975,6 @@ "play_memories": "播放回憶", "play_motion_photo": "播放動態照片", "play_or_pause_video": "播放或暫停影片", - "point": "", "port": "埠口", "preset": "預設", "preview": "預覽", @@ -1045,12 +1019,10 @@ "purchase_server_description_2": "擁護者狀態", "purchase_server_title": "伺服器", "purchase_settings_server_activated": "伺服器產品金鑰是由管理者管理的", - "range": "", "rating": "評星", "rating_clear": "清除評等", "rating_count": "{count, plural, other {# 星}}", "rating_description": "在資訊面板中顯示 EXIF 評等", - "raw": "", "reaction_options": "反應選項", "read_changelog": "閱覽變更日誌", "reassign": "重新指定", @@ -1062,23 +1034,23 @@ "refresh": "重新整理", "refresh_encoded_videos": "重新整理已編碼的影片", "refresh_faces": "重整面部資料", - "refresh_metadata": "重新整理元資料", + "refresh_metadata": "重新整理詳細資料", "refresh_thumbnails": "重新整理縮圖", "refreshed": "重新整理完畢", "refreshes_every_file": "重新讀取現有的所有檔案和新檔案", "refreshing_encoded_video": "正在重新整理已編碼的影片", "refreshing_faces": "重整面部資料中", - "refreshing_metadata": "正在重新整理元資料", + "refreshing_metadata": "正在重新整理詳細資料", "regenerating_thumbnails": "重新產生縮圖中", "remove": "移除", "remove_assets_album_confirmation": "確定要從相簿中移除 {count, plural, other {# 個檔案}}嗎?", - "remove_assets_shared_link_confirmation": "確定要從此分享鏈結中移除{count, plural, other {# 個檔案}}嗎?", + "remove_assets_shared_link_confirmation": "確定刪除共享連結中{count, plural, other {# 個項目}}嗎?", "remove_assets_title": "移除檔案?", "remove_custom_date_range": "移除自訂日期範圍", "remove_deleted_assets": "移除離線檔案", "remove_from_album": "從相簿中移除", "remove_from_favorites": "從收藏中移除", - "remove_from_shared_link": "從分享鏈結中移除", + "remove_from_shared_link": "從共享連結中移除", "remove_user": "移除用戶", "removed_api_key": "已移除 API 金鑰:{name}", "removed_from_archive": "從封存中移除", @@ -1095,7 +1067,6 @@ "reset": "重設", "reset_password": "重設密碼", "reset_people_visibility": "重設人物可見性", - "reset_settings_to_default": "", "reset_to_default": "重設回預設", "resolve_duplicates": "解決重複項", "resolved_all_duplicates": "已解決所有重複項目", @@ -1115,9 +1086,7 @@ "saved_settings": "已儲存設定", "say_something": "说些什么", "scan_all_libraries": "掃描所有圖庫", - "scan_all_library_files": "重新掃描所有圖庫文件", "scan_library": "掃描", - "scan_new_library_files": "掃描新圖庫", "scan_settings": "掃描設定", "scanning_for_album": "掃描相簿中……", "search": "搜尋", @@ -1137,7 +1106,7 @@ "search_places": "搜尋地點", "search_settings": "搜尋設定", "search_state": "搜尋地區…", - "search_tags": "搜尋標記…", + "search_tags": "搜尋標籤...", "search_timezone": "搜尋時區…", "search_type": "搜尋類型", "search_your_photos": "搜尋照片", @@ -1160,7 +1129,6 @@ "selected_count": "{count, plural, other {選了 # 項}}", "send_message": "傳訊息", "send_welcome_email": "傳送歡迎電子郵件", - "server": "", "server_offline": "伺服器離線", "server_online": "伺服器在線", "server_stats": "伺服器統計", @@ -1179,8 +1147,8 @@ "shared_by_user": "由 {user} 分享", "shared_by_you": "由你分享", "shared_from_partner": "來自 {partner} 的照片", - "shared_link_options": "分享鏈結選項", - "shared_links": "分享鏈結", + "shared_link_options": "共享連結選項", + "shared_links": "共享連結", "shared_photos_and_videos_count": "{assetCount, plural, other {已分享 # 張照片及影片。}}", "shared_with_partner": "與 {partner} 共享", "sharing": "共享", @@ -1197,7 +1165,7 @@ "show_in_timeline": "在時間軸中顯示", "show_in_timeline_setting_description": "在您的時間軸中顯示這位使用者的照片和影片", "show_keyboard_shortcuts": "顯示鍵盤快捷鍵", - "show_metadata": "顯示元資料", + "show_metadata": "顯示詳細資料", "show_or_hide_info": "顯示或隱藏資訊", "show_password": "顯示密碼", "show_person_options": "顯示人物選項", @@ -1214,10 +1182,10 @@ "size": "用量", "skip_to_content": "跳至內容", "skip_to_folders": "跳到資料夾", - "skip_to_tags": "跳到標記", + "skip_to_tags": "跳轉到標籤", "slideshow": "幻燈片", "slideshow_settings": "幻燈片設定", - "sort_albums_by": "相簿排序方式", + "sort_albums_by": "排序相簿", "sort_created": "建立日期", "sort_items": "項目數量", "sort_modified": "日期已修改", @@ -1257,7 +1225,7 @@ "tag_not_found_question": "找不到標記?建立新標記吧。", "tag_updated": "已更新標記:{tag}", "tagged_assets": "已標記 {count, plural, other {# 個檔案}}", - "tags": "標記", + "tags": "標籤", "template": "模板", "theme": "主題", "theme_selection": "主題選項", @@ -1265,17 +1233,17 @@ "they_will_be_merged_together": "它們將會被合併在一起", "third_party_resources": "第三方資源", "time_based_memories": "依時間回憶", + "timeline": "時間軸", "timezone": "時區", "to_archive": "封存", "to_change_password": "更改密碼", "to_favorite": "收藏", "to_login": "登入", "to_parent": "到上一級", - "to_root": "到根", "to_trash": "垃圾桶", "toggle_settings": "切換設定", "toggle_theme": "切換深色主題", - "toggle_visibility": "", + "total": "統計", "total_usage": "總用量", "trash": "垃圾桶", "trash_all": "全部丟掉", @@ -1285,12 +1253,10 @@ "trashed_items_will_be_permanently_deleted_after": "垃圾桶中的項目會在 {days, plural, other {# 天}}後永久刪除。", "type": "類型", "unarchive": "取消封存", - "unarchived": "", "unarchived_count": "{count, plural, other {已取消封存 # 個項目}}", "unfavorite": "取消收藏", "unhide_person": "取消隱藏人物", "unknown": "未知", - "unknown_album": "", "unknown_year": "不知年份", "unlimited": "不限制", "unlink_motion_video": "取消鏈結動態影片", @@ -1327,6 +1293,8 @@ "user_purchase_settings_description": "管理你的購買", "user_role_set": "設 {user} 爲{role}", "user_usage_detail": "使用者用量詳情", + "user_usage_stats": "帳號使用量統計", + "user_usage_stats_description": "查看帳號使用量", "username": "使用者名稱", "users": "使用者", "utilities": "工具", @@ -1334,7 +1302,7 @@ "variables": "變數", "version": "版本", "version_announcement_closing": "敬祝順心,Alex", - "version_announcement_message": "嗨~本應用程式可以更新了,爲防止配置出錯,請花點時間閱讀發行說明,並確保 docker-compose.yml.env 設置是最新的,特別是使用 WatchTower 等自動更新工具時。", + "version_announcement_message": "嗨~新版本的 Immich 推出了。爲防止配置出錯,請花點時間閱讀發行說明,並確保設定是最新的,特別是使用 WatchTower 等自動更新工具時。", "version_history": "版本紀錄", "version_history_item": "{date} 安裝了 {version}", "video": "影片", @@ -1348,10 +1316,10 @@ "view_all_users": "查看所有使用者", "view_in_timeline": "在時間軸中查看", "view_links": "檢視鏈結", + "view_name": "查看", "view_next_asset": "查看下一項", "view_previous_asset": "查看上一項", "view_stack": "查看堆疊", - "viewer": "", "visibility_changed": "已更改 {count, plural, other {# 位人物}}的可見性", "waiting": "待處理", "warning": "警告", @@ -1361,6 +1329,6 @@ "year": "年", "years_ago": "{years, plural, other {# 年}}前", "yes": "是", - "you_dont_have_any_shared_links": "您沒有分享鏈結", + "you_dont_have_any_shared_links": "您沒有任何共享連結", "zoom_image": "縮放圖片" } diff --git a/i18n/zh_SIMPLIFIED.json b/i18n/zh_SIMPLIFIED.json index c2e1a873500e7..d2f7a3b90cda4 100644 --- a/i18n/zh_SIMPLIFIED.json +++ b/i18n/zh_SIMPLIFIED.json @@ -23,17 +23,23 @@ "add_to": "添加到...", "add_to_album": "添加到相册", "add_to_shared_album": "添加到共享相册", + "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/**”。", - "asset_offline_description": "此外部库项目已无法从磁盘中找到,并已移至回收站。如果文件已在库中移动,请检查时间线中是否有新的对应项目。要恢复此项目,请确保 Immich 可以访问以下文件路径并执行扫描库任务。", + "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_settings": "备份设置", + "backup_settings_description": "管理数据库备份设置", "check_all": "检查全部", "cleared_jobs": "已清理任务:{job}", "config_set_by_file": "当前配置已通过配置文件设置", @@ -41,20 +47,21 @@ "confirm_delete_library_assets": "确定要删除该图库吗?这将删除所有包含在Immich中的{count, plural, one {#个项目} other {#个项目}},且无法撤销。但文件仍将保留在磁盘中。", "confirm_email_below": "输入“{email}”来确认", "confirm_reprocess_all_faces": "确定要对全部照片重新进行面部识别吗?这将同时清除所有已命名人物。", - "confirm_user_password_reset": "确定要重置用户{user}的密码吗?", + "confirm_user_password_reset": "确定要重置用户“{user}”的密码吗?", "create_job": "创建任务", - "crontab_guru": "Crontab Guru", + "cron_expression": "Cron表达式", + "cron_expression_description": "使用 cron 格式设置扫描间隔。更多详细信息请参阅 Crontab Guru", + "cron_expression_presets": "Cron 表达式预设", "disable_login": "禁用登录", - "disabled": "已禁用", "duplicate_detection_job_description": "对照片进行机器学习处理来检测相似项目,依赖于智能搜索", "exclusion_pattern_description": "排除规则允许在扫描图库时忽略文件和文件夹。如果有包含不想导入的文件的文件夹,例如RAW文件,排除规则将非常有用。", "external_library_created_at": "外部图库(创建于{date})", "external_library_management": "外部图库管理", "face_detection": "人脸检测", - "face_detection_description": "使用机器学习检测项目中的人脸(视频只检测其缩略图中的人脸)。选择“刷新”项将会(重新)处理所有项目。选择“重置”还会清除所有当前面部数据。选择“缺失”项将尚未处理的项目进行排队处理。人脸检测完成后,检测到的人脸将排队进行面部识别,将它们分组到现有的或新的人物中。", - "facial_recognition_job_description": "将检测到的人脸按照人物分组。这一步将在人脸检测完成后执行。选择“重置”项将会(重新)分组所有面孔。选择“缺失”项将尚未分配的人脸置于队列中。", + "face_detection_description": "使用机器学习检测项目中的人脸(视频只检测其缩略图中的人脸)。选择“刷新”将会(重新)处理所有项目。选择“重置”还会清除所有当前面部数据。选择“缺失”将尚未处理的项目进行排队处理。人脸检测完成后,检测到的人脸将排队进行面部识别,将它们分组到现有的或新的人物中。", + "facial_recognition_job_description": "将检测到的人脸按照人物分组。这一步将在人脸检测完成后执行。选择“重置”将会(重新)分组所有面孔。选择“缺失”将尚未分配的人脸置于队列中。", "failed_job_command": "{command}命令执行失败的任务:{job}", - "force_delete_user_warning": "警告:这将立即移除用户以及所有项目。该操作无法撤销且文件无法恢复。", + "force_delete_user_warning": "警告:这将立即移除用户以及其所有项目。该操作无法撤销且文件无法恢复。", "forcing_refresh_library_files": "强制刷新所有图库文件", "image_format": "格式", "image_format_description": "WebP 文件比 JPEG 文件小,但编码速度较慢。", @@ -63,22 +70,15 @@ "image_prefer_wide_gamut": "广色域", "image_prefer_wide_gamut_setting_description": "对缩略图使用 Display P3。这可以更好地保留宽色域图像的鲜艳度,但在旧设备和旧版浏览器上图像可能会显得不同。sRGB 图像保持为 sRGB 以避免颜色偏移。", "image_preview_description": "去除元数据的中尺寸图像,用于单一项目查看和机器学习", - "image_preview_format": "预览格式", "image_preview_quality_description": "预览质量从 1 到 100。越高越好,但会产生更大的文件,并且会降低系统的响应能力。设置较低的值可能会影响机器学习的质量。", - "image_preview_resolution": "预览分辨率", - "image_preview_resolution_description": "在查看单张照片和进行机器学习时使用。更高的分辨率可以保留更多细节,但编码时间更长,文件体积更大,且可能降低应用程序的响应速度。", "image_preview_title": "预览设置", "image_quality": "质量", - "image_quality_description": "图像质量从1到100。数字越高,质量越好,但生成的文件也越大,此选项会同时影响预览和缩略图。", "image_resolution": "分辨率", "image_resolution_description": "更高的分辨率可以保留更多细节,但编码时间更长,文件体积更大,而且会降低系统的响应速度。", "image_settings": "图片设置", "image_settings_description": "管理生成图像的质量和分辨率", "image_thumbnail_description": "去除元数据的小缩略图,用于浏览主时间线等照片组", - "image_thumbnail_format": "缩略图格式", "image_thumbnail_quality_description": "缩略图质量从 1 到 100。越高越好,但会产生更大的文件,并且会降低系统的响应能力。", - "image_thumbnail_resolution": "缩略图分辨率", - "image_thumbnail_resolution_description": "用于查看照片组(主时间轴、相册视图等)。更高的分辨率可以保留更多的细节,但编码时间更长,文件体积更大,并会降低应用程序的响应速度。", "image_thumbnail_title": "缩略图设置", "job_concurrency": "{job}并发", "job_created": "任务已创建", @@ -89,9 +89,6 @@ "jobs_delayed": "{jobCount, plural, other {#项任务已推迟}}", "jobs_failed": "{jobCount, plural, other {#项失败}}", "library_created": "已创建图库:{library}", - "library_cron_expression": "Cron 表达式", - "library_cron_expression_description": "使用 cron 格式设置扫描间隔。关于 cron 格式请参阅Crontab Guru", - "library_cron_expression_presets": "Cron 表达式预设", "library_deleted": "图库已删除", "library_import_path_description": "指定一个要导入的文件夹。将扫描此文件夹(包括子文件夹)中的图像和视频。", "library_scanning": "定期扫描", @@ -134,7 +131,7 @@ "machine_learning_smart_search_description": "使用CLIP以文搜图、智能搜图", "machine_learning_smart_search_enabled": "启用智能搜索", "machine_learning_smart_search_enabled_description": "如果禁用,则不会对图像编码以用于智能搜索。", - "machine_learning_url_description": "机器学习服务器的URL", + "machine_learning_url_description": "机器学习服务器的 URL。如果提供多个 URL,则将按依次尝试连接每个服务器,直到有一个服务器成功响应为止。", "manage_concurrency": "管理任务并发", "manage_log_settings": "管理日志设置", "map_dark_style": "深色模式", @@ -164,7 +161,7 @@ "note_cannot_be_changed_later": "注意:此项一旦设定,以后无法更改!", "note_unlimited_quota": "提示:输入0表示无限制", "notification_email_from_address": "发件人地址", - "notification_email_from_address_description": "发件人邮箱地址,例如:“张三 <12345@qq.com>”", + "notification_email_from_address_description": "发件人邮箱,例如:“张三 <12345@qq.com>”", "notification_email_host_description": "服务器地址(例如:smtp.qq.com)", "notification_email_ignore_certificate_errors": "忽略证书错误", "notification_email_ignore_certificate_errors_description": "忽略TLS证书验证错误(不建议)", @@ -196,7 +193,7 @@ "oauth_scope": "范围", "oauth_settings": "OAuth", "oauth_settings_description": "管理OAuth登录设置", - "oauth_settings_more_details": "关于本功能的更多详细信息,请查看相关文档。", + "oauth_settings_more_details": "关于此功能的更多详细信息,请查看相关文档。", "oauth_signing_algorithm": "签名算法", "oauth_storage_label_claim": "存储标签声明", "oauth_storage_label_claim_description": "自动将用户的存储标签设置为此项的值。", @@ -215,7 +212,6 @@ "refreshing_all_libraries": "刷新所有图库", "registration": "注册管理员", "registration_description": "由于您是系统上的第一个用户,您将被指定为管理员并负责管理任务,由您来创建新的用户。", - "removing_deleted_files": "移除离线文件", "repair_all": "修复所有", "repair_matched_items": "匹配到 {count, plural, one {#个项目} other {#个项目}}", "repaired_items": "已修复{count, plural, one {#个项目} other {#个项目}}", @@ -223,12 +219,12 @@ "reset_settings_to_default": "恢复默认设置", "reset_settings_to_recent_saved": "恢复到最近保存的设置", "scanning_library": "扫描图库", - "scanning_library_for_changed_files": "扫描图库变更的文件", - "scanning_library_for_new_files": "扫描图库新增的文件", "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": "欢迎消息", @@ -254,6 +250,16 @@ "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_settings_description": "管理自定义邮件通知模板", + "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": "主题设置", @@ -261,11 +267,10 @@ "these_files_matched_by_checksum": "这些文件与校验匹配", "thumbnail_generation_job": "生成缩略图", "thumbnail_generation_job_description": "为每个项目生成不同尺寸的缩略图,并为每个人物生成缩略图", - "transcode_policy_description": "视频转码的策略。HDR视频将始终进行转码(除非禁用了转码功能)。", "transcoding_acceleration_api": "加速器API", "transcoding_acceleration_api_description": "这个API将与您的设备交互,以加速转码过程。此设置为“尽力而为”——如果转码失败,将回到软件转码。VP9是否工作取决于您的硬件配置。", "transcoding_acceleration_nvenc": "NVENC(需要 NVIDIA GPU)", - "transcoding_acceleration_qsv": "快速同步(需要Intel 7代及以上的 CPU)", + "transcoding_acceleration_qsv": "Quick Sync(需要Intel 7代及以上的 CPU)", "transcoding_acceleration_rkmpp": "RKMPP(仅适用于 Rockchip SOCs)", "transcoding_acceleration_vaapi": "VAAPI", "transcoding_accepted_audio_codecs": "支持的音频编解码器", @@ -313,8 +318,6 @@ "transcoding_threads_description": "设定值越高,编码速度越快,留给其它任务(Docker外宿主机的任务等)的计算能力越少。此值不应大于CPU核心的数量。0表示最大限度地提高利用率。", "transcoding_tone_mapping": "色调映射", "transcoding_tone_mapping_description": "在将HDR视频转换为SDR时,尝试保持其外观。每种算法在颜色、细节和亮度方面做出了不同的权衡。Hable算法保留细节,Mobius算法保留颜色,而Reinhard算法保留亮度。", - "transcoding_tone_mapping_npl": "NPL色调映射", - "transcoding_tone_mapping_npl_description": "对于这种亮度的显示器,颜色将被调整到显示正常。与直觉相反,较低的值会增加视频的亮度,反之亦然,因为它会补偿显示器的亮度。0表示将自动设置此值。", "transcoding_transcode_policy": "转码策略", "transcoding_transcode_policy_description": "视频转码策略。HDR视频将始终进行转码(除非禁用了转码功能)。", "transcoding_two_pass_encoding": "二次编码", @@ -326,8 +329,8 @@ "trash_number_of_days_description": "回收站中项目永久删除的天数", "trash_settings": "回收站设置", "trash_settings_description": "管理回收站设置", - "untracked_files": "未被追踪的文件", - "untracked_files_description": "这些文件未被系统追踪。 这可能是移动失败、上传中断或因bug而落下", + "untracked_files": "未被扫描的文件", + "untracked_files_description": "这些文件未被系统扫描。 这可能是移动失败、上传中断或因bug而落下", "user_cleanup_job": "清理用户", "user_delete_delay": "{user}的账户及项目将在{delay, plural, one {#天} other {#天}}后自动永久删除。", "user_delete_delay_settings": "延期删除", @@ -341,7 +344,7 @@ "user_restore_scheduled_removal": "恢复用户 - 计划于{date, date, long}删除", "user_settings": "用户设置", "user_settings_description": "管理用户设置", - "user_successfully_removed": "用户{email}已被成功删除。", + "user_successfully_removed": "用户“{email}”已被成功删除。", "version_check_enabled_description": "启用版本检测", "version_check_implications": "版本检查功能依赖于与 github.com 的定期通信", "version_check_settings": "版本检查", @@ -357,22 +360,22 @@ "age_year_months": "1岁{months, plural, one {#个月} other {#个月}}", "age_years": "{years, plural, other {#岁}}", "album_added": "相册已添加", - "album_added_notification_setting_description": "当您被添加到共享相册时,接收电子邮件通知", + "album_added_notification_setting_description": "当您被添加到共享相册时,接收邮箱通知", "album_cover_updated": "相册封面已更新", "album_delete_confirmation": "确定要删除相册“{album}”吗?", "album_delete_confirmation_description": "如果该相册是共享的,其他用户将无法再访问它。", "album_info_updated": "相册信息已更新", "album_leave": "退出相册?", - "album_leave_confirmation": "确定要退出相册{album}吗?", + "album_leave_confirmation": "确定要退出相册“{album}”吗?", "album_name": "相册名称", "album_options": "相册设置", "album_remove_user": "移除用户?", - "album_remove_user_confirmation": "你确定要移除{user}吗?", + "album_remove_user_confirmation": "你确定要移除“{user}”吗?", "album_share_no_users": "看起来您已与所有用户共享了此相册,或者您根本没有任何用户可共享。", "album_updated": "相册已更新", "album_updated_setting_description": "当共享相册有新项目时接收邮件通知", - "album_user_left": "离开{album}", - "album_user_removed": "已移除{user}", + "album_user_left": "离开“{album}”", + "album_user_removed": "已移除“{user}”", "album_with_link_access": "拥有此链接的任何人均可查看本相册中的照片和人物。", "albums": "相册", "albums_count": "{count, plural, one {{count, number} 个相册} other {{count, number} 个相册}}", @@ -386,7 +389,7 @@ "allow_public_user_to_upload": "允许所有用户上传", "anti_clockwise": "逆时针", "api_key": "API 密钥", - "api_key_description": "该应用密钥只会展示一次。请确保在关闭窗口前复制下来。", + "api_key_description": "该应用密钥只会显示一次。请确保在关闭窗口前复制下来。", "api_key_empty": "API Key的名称不可以为空", "api_keys": "API 密钥", "app_settings": "应用设置", @@ -395,14 +398,13 @@ "archive_or_unarchive_photo": "归档或取消归档照片", "archive_size": "归档大小", "archive_size_description": "配置下载归档大小(GB)", - "archived": "已归档", "archived_count": "{count, plural, other {已归档 # 项}}", "are_these_the_same_person": "是同一个人吗?", "are_you_sure_to_do_this": "确定要这样做吗?", "asset_added_to_album": "已添加至相册", "asset_adding_to_album": "正在添加至相册...", "asset_description_updated": "项目描述已更新", - "asset_filename_is_offline": "项目{filename}已离线", + "asset_filename_is_offline": "项目“{filename}”已离线", "asset_has_unassigned_faces": "项目中有未分配的人脸", "asset_hashing": "哈希校验中...", "asset_offline": "项目离线", @@ -416,7 +418,6 @@ "assets_added_to_album_count": "已添加{count, plural, one {#个项目} other {#个项目}}到相册", "assets_added_to_name_count": "已添加{count, plural, one {#个项目} other {#个项目}}到{hasName, select, true {{name}} other {新相册}}", "assets_count": "{count, plural, one {#个项目} other {#个项目}}", - "assets_moved_to_trash": "将{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 {#个项目}}", @@ -446,10 +447,6 @@ "cannot_merge_people": "无法合并人物", "cannot_undo_this_action": "注意:该操作无法被撤消!", "cannot_update_the_description": "无法更新描述", - "cant_apply_changes": "无法应用更改", - "cant_get_faces": "找不到人脸", - "cant_search_people": "找不到人物", - "cant_search_places": "找不到地点", "change_date": "更改日期", "change_expiration_time": "更改过期时间", "change_location": "更改位置", @@ -481,6 +478,7 @@ "confirm": "确认", "confirm_admin_password": "确认管理员密码", "confirm_delete_shared_link": "您确定要删除此共享链接吗?", + "confirm_keep_this_delete_others": "除此项目外,堆叠中的所有其它项目都将被删除。您确定要继续吗?", "confirm_password": "确认密码", "contain": "包含", "context": "以文搜图", @@ -530,6 +528,7 @@ "delete_key": "删除密钥", "delete_library": "删除图库", "delete_link": "删除链接", + "delete_others": "删除其它", "delete_shared_link": "删除共享链接", "delete_tag": "删除标签", "delete_tag_confirmation_prompt": "您确定要删除“{tagName}”标签吗?", @@ -558,18 +557,11 @@ "download_settings": "下载", "download_settings_description": "管理项目下载相关设置", "downloading": "下载中", - "downloading_asset_filename": "下载项目{filename}", + "downloading_asset_filename": "下载项目“{filename}”", "drop_files_to_upload": "拖放文件以上传", "duplicates": "重复项", "duplicates_description": "审查每组疑似重复项并标记哪些是重复的(如果有的话)", "duration": "时长", - "durations": { - "days": "{days, plural, one {天} other {{days, number} 天}}", - "hours": "{hours, plural, one {小时} other {{hours, number} 小时}}", - "minutes": "{minutes, plural, one {分钟} other {{minutes, number} 分钟}}", - "months": "{months, plural, one {月} other {{months, number} 月}}", - "years": "{years, plural, one {年} other {{years, number} 年}}" - }, "edit": "编辑", "edit_album": "编辑相册", "edit_avatar": "编辑头像", @@ -594,8 +586,6 @@ "editor_crop_tool_h2_aspect_ratios": "长宽比", "editor_crop_tool_h2_rotation": "旋转", "email": "邮箱", - "empty": "空", - "empty_album": "清空相册", "empty_trash": "清空回收站", "empty_trash_confirmation": "确定要清空回收站?这将永久删除回收站中的所有项目。\n注意:该操作无法撤消!", "enable": "启用", @@ -603,7 +593,7 @@ "end_date": "结束日期", "error": "错误", "error_loading_image": "加载图片时出错", - "error_title": "错误 - 出了点问题", + "error_title": "错误 - 好像出了问题", "errors": { "cannot_navigate_next_asset": "无法导航到下一个项目", "cannot_navigate_previous_asset": "无法导航到上一个项目", @@ -629,6 +619,7 @@ "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_people": "加载人物失败", @@ -656,8 +647,6 @@ "unable_to_change_location": "无法更改位置", "unable_to_change_password": "无法修改密码", "unable_to_change_visibility": "无法修改{count, plural, one {#个人} other {#个人}}的可见性", - "unable_to_check_item": "无法选中项目", - "unable_to_check_items": "无法选中项目", "unable_to_complete_oauth_login": "无法完成OAuth登录", "unable_to_connect": "无法连接", "unable_to_connect_to_server": "无法连接至服务器", @@ -698,12 +687,10 @@ "unable_to_remove_album_users": "无法从相册中移除用户", "unable_to_remove_api_key": "无法移除API Key", "unable_to_remove_assets_from_shared_link": "无法从共享链接中移除项目", - "unable_to_remove_comment": "无法移除评论", "unable_to_remove_deleted_assets": "无法移除离线文件", "unable_to_remove_library": "无法移除图库", "unable_to_remove_partner": "无法移除同伴", "unable_to_remove_reaction": "无法移除回应", - "unable_to_remove_user": "无法移除用户", "unable_to_repair_items": "无法修复项目", "unable_to_reset_password": "无法重置密码", "unable_to_resolve_duplicate": "无法解决重复项", @@ -733,10 +720,6 @@ "unable_to_update_user": "无法更新用户", "unable_to_upload_file": "无法上传文件" }, - "every_day_at_onepm": "每天下午一点", - "every_night_at_midnight": "每天午夜", - "every_night_at_twoam": "每天凌晨两点", - "every_six_hours": "每6小时", "exif": "Exif信息", "exit_slideshow": "退出幻灯片放映", "expand_all": "全部展开", @@ -751,33 +734,28 @@ "external": "外部的", "external_libraries": "外部图库", "face_unassigned": "未指派", - "failed_to_get_people": "无法获取人物", + "failed_to_load_assets": "加载项目失败", "favorite": "收藏", "favorite_or_unfavorite_photo": "收藏或取消收藏照片", "favorites": "收藏夹", - "feature": "功能", "feature_photo_updated": "人物头像已更新", - "featurecollection": "功能合集", "features": "功能", "features_setting_description": "管理App功能", "file_name": "文件名", - "file_name_or_extension": "文件名或扩展名", + "file_name_or_extension": "文件名", "filename": "文件名", - "files": "", "filetype": "文件类型", "filter_people": "过滤人物", "find_them_fast": "按名称快速搜索", "fix_incorrect_match": "修复不正确的匹配", "folders": "文件夹", "folders_feature_description": "在文件夹视图中浏览文件系统上的照片和视频", - "force_re-scan_library_files": "强制重新扫描所有图库文件", "forward": "向前", "general": "通用", "get_help": "获取帮助", "getting_started": "入门", "go_back": "返回", "go_to_search": "前往搜索", - "go_to_share_page": "转到共享页面", "group_albums_by": "相册分组依据...", "group_no": "未分组", "group_owner": "按所有者分组", @@ -803,10 +781,6 @@ "image_alt_text_date_place_2_people": "{date}在{country}{city}拍摄的包含{person1}和{person2}的{isVideo, select, true {视频} other {照片}}", "image_alt_text_date_place_3_people": "{date}在{country}{city}拍摄的包含{person1}、{person2}和{person3}的{isVideo, select, true {视频} other {照片}}", "image_alt_text_date_place_4_or_more_people": "{date}在{country}{city}拍摄的包含{person1}、{person2}及其他{additionalCount, number}个人物的{isVideo, select, true {视频} other {照片}}", - "image_alt_text_people": "{count, plural, =1 {和{person1}在一起} =2 {和{person1}及{person2}在一起} =3 {和{person1}、{person2}及{person3}在一起} other {和{person1}、{person2}及其他{others, number}个人在一起}}", - "image_alt_text_place": "在{country} {city}", - "image_taken": "{isVideo, select, true {选择视频} other {选择图片}}", - "img": "图片", "immich_logo": "Immich Logo", "immich_web_interface": "Immich Web界面", "import_from_json": "从JSON导入", @@ -821,16 +795,17 @@ "interval": { "day_at_onepm": "每天下午1点", "hours": "每 {hours, plural, one {小时} other {{hours, number} 小时}}", - "night_at_midnight": "每晚24点", + "night_at_midnight": "每晚0点", "night_at_twoam": "每晚凌晨2点" }, "invite_people": "邀请人员", "invite_to_album": "邀请加入相册", "items_count": "{count, plural, one {#个项目} other {#个项目}}", - "job_settings_description": "管理任务并发", "jobs": "任务", "keep": "保留", "keep_all": "保留所有", + "keep_this_delete_others": "保留这个,删除其它", + "kept_this_deleted_others": "保留该项目并删除 {count, plural, one {# 个项目} other {# 个项目}}", "keyboard_shortcuts": "键盘快捷键", "language": "语言", "language_setting_description": "选择您的语言偏好", @@ -842,31 +817,6 @@ "level": "等级", "library": "图库", "library_options": "图库选项", - "license_account_info": "您的帐户已授权", - "license_activated_subtitle": "感谢您对Immich和开源软件的支持", - "license_activated_title": "您的授权已激活成功", - "license_button_activate": "激活", - "license_button_buy": "购买", - "license_button_buy_license": "购买授权", - "license_button_select": "选择", - "license_failed_activation": "授权激活失败。请检查邮件获取正确的授权码!", - "license_individual_description_1": "1个用于任意服务的授权用户", - "license_individual_title": "个人授权", - "license_info_licensed": "已授权", - "license_info_unlicensed": "未授权", - "license_input_suggestion": "已有授权?请在下方输入授权码", - "license_license_subtitle": "购买授权来支持Immich", - "license_license_title": "授权", - "license_lifetime_description": "永久授权", - "license_per_server": "每台服务器", - "license_per_user": "每个用户", - "license_server_description_1": "1台授权服务器", - "license_server_description_2": "授权给本服务器中的所有用户", - "license_server_title": "服务器授权", - "license_trial_info_1": "您运行的是未授权的Immich版本", - "license_trial_info_2": "您已经使用Immich大概", - "license_trial_info_3": "{accountAge, plural, one {#天} other {#天}}", - "license_trial_info_4": "请考虑购买授权来支持此服务的持续开发", "light": "浅色", "like_deleted": "已删除的收藏", "link_motion_video": "链接动态视频", @@ -971,7 +921,6 @@ "onboarding_welcome_user": "欢迎你,{user}", "online": "在线", "only_favorites": "仅显示已收藏", - "only_refreshes_modified_files": "仅刷新修改的文件", "open_in_map_view": "在地图视图中打开", "open_in_openstreetmap": "在OpenStreetMap中打开", "open_the_search_filters": "打开搜索过滤器", @@ -1009,14 +958,12 @@ "people_edits_count": "{count, plural, one {#个人物} other {#个人物}}已编辑", "people_feature_description": "按人物分组进行浏览照片和视频", "people_sidebar_description": "在侧边栏中显示“人物”链接", - "perform_library_tasks": "", "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, plural, one {# 个项目} other {# 个项目}}", "permanently_deleted_assets_count": "{count, plural, one {#个项目} other {#个项目}}已删除", "person": "人物", "person_hidden": "{name}{hidden, select, true {(已隐藏)} other {}}", @@ -1032,7 +979,6 @@ "play_memories": "播放回忆", "play_motion_photo": "播放动态图片", "play_or_pause_video": "播放或暂停视频", - "point": "点", "port": "端口", "preset": "预设", "preview": "预览", @@ -1077,12 +1023,10 @@ "purchase_server_description_2": "支持者状态", "purchase_server_title": "服务器", "purchase_settings_server_activated": "服务器产品密钥正在由管理员管理", - "range": "范围", "rating": "星级", "rating_clear": "删除星级", "rating_count": "{count, plural, one {#星} other {#星}}", "rating_description": "在信息面板中展示EXIF星级", - "raw": "Raw", "reaction_options": "回应选项", "read_changelog": "阅读更新日志", "reassign": "重新指派", @@ -1090,6 +1034,7 @@ "reassigned_assets_to_new_person": "重新指派{count, plural, one {#个项目} other {#个项目}}到新的人物", "reassing_hint": "指派选择的项目到已存在的人物", "recent": "最近", + "recent-albums": "最近的相册", "recent_searches": "最近搜索", "refresh": "刷新", "refresh_encoded_videos": "刷新已编码的视频", @@ -1111,6 +1056,7 @@ "remove_from_album": "从相册中移除", "remove_from_favorites": "移出收藏", "remove_from_shared_link": "从共享链接中移除", + "remove_url": "移除URL", "remove_user": "移除用户", "removed_api_key": "移除的API Key:{name}", "removed_from_archive": "从归档中移除", @@ -1127,7 +1073,6 @@ "reset": "重置", "reset_password": "重置密码", "reset_people_visibility": "重置人物可见性", - "reset_settings_to_default": "恢复到默认设置", "reset_to_default": "恢复默认值", "resolve_duplicates": "处理重复项", "resolved_all_duplicates": "解决所有重复问题", @@ -1147,15 +1092,13 @@ "saved_settings": "已保存设置", "say_something": "说点什么", "scan_all_libraries": "扫描所有图库", - "scan_all_library_files": "重新扫描所有图库文件", "scan_library": "扫描", - "scan_new_library_files": "扫描新的图库文件", "scan_settings": "扫描设置", "scanning_for_album": "扫描相册中...", "search": "搜索", "search_albums": "搜索相册", "search_by_context": "搜索内容", - "search_by_filename": "通过文件名或扩展名搜索", + "search_by_filename": "通过文件名搜索", "search_by_filename_example": "如 IMG_1234.JPG 或 PNG", "search_camera_make": "搜索相机品牌...", "search_camera_model": "搜索相机型号...", @@ -1192,7 +1135,6 @@ "selected_count": "{count, plural, other {#项已选择}}", "send_message": "发送消息", "send_welcome_email": "发送欢迎邮件", - "server": "服务器", "server_offline": "服务器离线", "server_online": "服务器在线", "server_stats": "服务统计", @@ -1297,17 +1239,17 @@ "they_will_be_merged_together": "项目将会合并到一起", "third_party_resources": "第三方资源", "time_based_memories": "基于时间的回忆", + "timeline": "时间线", "timezone": "时区", "to_archive": "归档", "to_change_password": "修改密码", "to_favorite": "收藏", "to_login": "登录", "to_parent": "返回上一级", - "to_root": "返回到根目录", "to_trash": "放入回收站", "toggle_settings": "切换设置", "toggle_theme": "切换深色主题", - "toggle_visibility": "切换可见性", + "total": "总计", "total_usage": "总用量", "trash": "回收站", "trash_all": "全部删除", @@ -1317,12 +1259,10 @@ "trashed_items_will_be_permanently_deleted_after": "回收站中的项目将在{days, plural, one {#天} other {#天}}后被永久删除。", "type": "种类", "unarchive": "取消归档", - "unarchived": "已取消归档", "unarchived_count": "{count, plural, other {取消归档 # 项}}", "unfavorite": "取消收藏", "unhide_person": "显示人物", "unknown": "未知", - "unknown_album": "未知相册", "unknown_year": "未知年份", "unlimited": "无限制", "unlink_motion_video": "取消链接动态视频", @@ -1354,13 +1294,13 @@ "use_custom_date_range": "自定义日期范围", "user": "用户", "user_id": "用户ID", - "user_license_settings": "授权", - "user_license_settings_description": "管理你的授权", "user_liked": "“{user}”点赞了{type, select, photo {该照片} video {该视频} asset {该项目} other {它}}", "user_purchase_settings": "购买", "user_purchase_settings_description": "管理购买订单", "user_role_set": "设置“{user}”为“{role}”", "user_usage_detail": "用户用量详情", + "user_usage_stats": "帐户使用统计", + "user_usage_stats_description": "查看帐户使用统计信息", "username": "用户名", "users": "用户", "utilities": "实用工具", @@ -1368,9 +1308,9 @@ "variables": "变量", "version": "版本", "version_announcement_closing": "你的朋友,Alex", - "version_announcement_message": "嗨,朋友,当前应用出新版本了,请抽空阅读一下发行说明,并及时更新你的docker-compose.yml.env文件,避免存在配置错误,特别是当你是使用WatchTower或其它类似的自动升级工具时。", - "version_history": "版本历史", - "version_history_item": "在 {date} 安装版本 {version}", + "version_announcement_message": "你好!已经检测到Immich有新版本。请抽空阅读一下发行说明,以确保您的配置文件是最新的,避免存在配置错误,特别是当你是使用WatchTower或其它类似的自动升级工具时。", + "version_history": "版本更新历史记录", + "version_history_item": "在 {date} 安装 {version} 版本", "video": "视频", "video_hover_setting": "鼠标悬停时播放视频缩略图", "video_hover_setting_description": "当鼠标悬停在项目上时播放视频缩略图。即使禁用了这个功能,也可以通过将鼠标悬停在播放图标上来开始播放。", @@ -1382,10 +1322,10 @@ "view_all_users": "查看全部用户", "view_in_timeline": "在时间轴中查看", "view_links": "查看链接", + "view_name": "查看", "view_next_asset": "查看下一项", "view_previous_asset": "查看上一项", "view_stack": "查看堆叠项目", - "viewer": "预览", "visibility_changed": "{count, plural, one {#个人物} other {#个人物}}的可见性已修改", "waiting": "准备处理", "warning": "警告", diff --git a/machine-learning/Dockerfile b/machine-learning/Dockerfile index fa654d70b7e9c..bca9244fa111b 100644 --- a/machine-learning/Dockerfile +++ b/machine-learning/Dockerfile @@ -1,6 +1,6 @@ ARG DEVICE=cpu -FROM python:3.11-bookworm@sha256:70f1eb2927a8ef72840254b17024d3a8aa8c3c9715a625d426a2861b5899bc62 AS builder-cpu +FROM python:3.11-bookworm@sha256:2c80c66d876952e04fa74113864903198b7cfb36b839acb7a8fef82e94ed067c AS builder-cpu FROM builder-cpu AS builder-openvino @@ -34,7 +34,7 @@ RUN python3 -m venv /opt/venv COPY poetry.lock pyproject.toml ./ RUN poetry install --sync --no-interaction --no-ansi --no-root --with ${DEVICE} --without dev -FROM python:3.11-slim-bookworm@sha256:5148c0e4bbb64271bca1d3322360ebf4bfb7564507ae32dd639322e4952a6b16 AS prod-cpu +FROM python:3.11-slim-bookworm@sha256:370c586a6ffc8c619e6d652f81c094b34b14b8f2fb9251f092de23f16e299b78 AS prod-cpu FROM prod-cpu AS prod-openvino diff --git a/machine-learning/poetry.lock b/machine-learning/poetry.lock index a2da285750336..eb8fe31dffcf7 100644 --- a/machine-learning/poetry.lock +++ b/machine-learning/poetry.lock @@ -575,63 +575,73 @@ test-no-images = ["pytest", "pytest-cov", "pytest-xdist", "wurlitzer"] [[package]] name = "coverage" -version = "7.4.0" +version = "7.6.4" description = "Code coverage measurement for Python" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" files = [ - {file = "coverage-7.4.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:36b0ea8ab20d6a7564e89cb6135920bc9188fb5f1f7152e94e8300b7b189441a"}, - {file = "coverage-7.4.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0676cd0ba581e514b7f726495ea75aba3eb20899d824636c6f59b0ed2f88c471"}, - {file = "coverage-7.4.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d0ca5c71a5a1765a0f8f88022c52b6b8be740e512980362f7fdbb03725a0d6b9"}, - {file = "coverage-7.4.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a7c97726520f784239f6c62506bc70e48d01ae71e9da128259d61ca5e9788516"}, - {file = "coverage-7.4.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:815ac2d0f3398a14286dc2cea223a6f338109f9ecf39a71160cd1628786bc6f5"}, - {file = "coverage-7.4.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:80b5ee39b7f0131ebec7968baa9b2309eddb35b8403d1869e08f024efd883566"}, - {file = "coverage-7.4.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:5b2ccb7548a0b65974860a78c9ffe1173cfb5877460e5a229238d985565574ae"}, - {file = "coverage-7.4.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:995ea5c48c4ebfd898eacb098164b3cc826ba273b3049e4a889658548e321b43"}, - {file = "coverage-7.4.0-cp310-cp310-win32.whl", hash = "sha256:79287fd95585ed36e83182794a57a46aeae0b64ca53929d1176db56aacc83451"}, - {file = "coverage-7.4.0-cp310-cp310-win_amd64.whl", hash = "sha256:5b14b4f8760006bfdb6e08667af7bc2d8d9bfdb648351915315ea17645347137"}, - {file = "coverage-7.4.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:04387a4a6ecb330c1878907ce0dc04078ea72a869263e53c72a1ba5bbdf380ca"}, - {file = "coverage-7.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ea81d8f9691bb53f4fb4db603203029643caffc82bf998ab5b59ca05560f4c06"}, - {file = "coverage-7.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:74775198b702868ec2d058cb92720a3c5a9177296f75bd97317c787daf711505"}, - {file = "coverage-7.4.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:76f03940f9973bfaee8cfba70ac991825611b9aac047e5c80d499a44079ec0bc"}, - {file = "coverage-7.4.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:485e9f897cf4856a65a57c7f6ea3dc0d4e6c076c87311d4bc003f82cfe199d25"}, - {file = "coverage-7.4.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:6ae8c9d301207e6856865867d762a4b6fd379c714fcc0607a84b92ee63feff70"}, - {file = "coverage-7.4.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:bf477c355274a72435ceb140dc42de0dc1e1e0bf6e97195be30487d8eaaf1a09"}, - {file = "coverage-7.4.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:83c2dda2666fe32332f8e87481eed056c8b4d163fe18ecc690b02802d36a4d26"}, - {file = "coverage-7.4.0-cp311-cp311-win32.whl", hash = "sha256:697d1317e5290a313ef0d369650cfee1a114abb6021fa239ca12b4849ebbd614"}, - {file = "coverage-7.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:26776ff6c711d9d835557ee453082025d871e30b3fd6c27fcef14733f67f0590"}, - {file = "coverage-7.4.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:13eaf476ec3e883fe3e5fe3707caeb88268a06284484a3daf8250259ef1ba143"}, - {file = "coverage-7.4.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:846f52f46e212affb5bcf131c952fb4075b55aae6b61adc9856222df89cbe3e2"}, - {file = "coverage-7.4.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:26f66da8695719ccf90e794ed567a1549bb2644a706b41e9f6eae6816b398c4a"}, - {file = "coverage-7.4.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:164fdcc3246c69a6526a59b744b62e303039a81e42cfbbdc171c91a8cc2f9446"}, - {file = "coverage-7.4.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:316543f71025a6565677d84bc4df2114e9b6a615aa39fb165d697dba06a54af9"}, - {file = "coverage-7.4.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:bb1de682da0b824411e00a0d4da5a784ec6496b6850fdf8c865c1d68c0e318dd"}, - {file = "coverage-7.4.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:0e8d06778e8fbffccfe96331a3946237f87b1e1d359d7fbe8b06b96c95a5407a"}, - {file = "coverage-7.4.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:a56de34db7b7ff77056a37aedded01b2b98b508227d2d0979d373a9b5d353daa"}, - {file = "coverage-7.4.0-cp312-cp312-win32.whl", hash = "sha256:51456e6fa099a8d9d91497202d9563a320513fcf59f33991b0661a4a6f2ad450"}, - {file = "coverage-7.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:cd3c1e4cb2ff0083758f09be0f77402e1bdf704adb7f89108007300a6da587d0"}, - {file = "coverage-7.4.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:e9d1bf53c4c8de58d22e0e956a79a5b37f754ed1ffdbf1a260d9dcfa2d8a325e"}, - {file = "coverage-7.4.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:109f5985182b6b81fe33323ab4707011875198c41964f014579cf82cebf2bb85"}, - {file = "coverage-7.4.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3cc9d4bc55de8003663ec94c2f215d12d42ceea128da8f0f4036235a119c88ac"}, - {file = "coverage-7.4.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cc6d65b21c219ec2072c1293c505cf36e4e913a3f936d80028993dd73c7906b1"}, - {file = "coverage-7.4.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5a10a4920def78bbfff4eff8a05c51be03e42f1c3735be42d851f199144897ba"}, - {file = "coverage-7.4.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:b8e99f06160602bc64da35158bb76c73522a4010f0649be44a4e167ff8555952"}, - {file = "coverage-7.4.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:7d360587e64d006402b7116623cebf9d48893329ef035278969fa3bbf75b697e"}, - {file = "coverage-7.4.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:29f3abe810930311c0b5d1a7140f6395369c3db1be68345638c33eec07535105"}, - {file = "coverage-7.4.0-cp38-cp38-win32.whl", hash = "sha256:5040148f4ec43644702e7b16ca864c5314ccb8ee0751ef617d49aa0e2d6bf4f2"}, - {file = "coverage-7.4.0-cp38-cp38-win_amd64.whl", hash = "sha256:9864463c1c2f9cb3b5db2cf1ff475eed2f0b4285c2aaf4d357b69959941aa555"}, - {file = "coverage-7.4.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:936d38794044b26c99d3dd004d8af0035ac535b92090f7f2bb5aa9c8e2f5cd42"}, - {file = "coverage-7.4.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:799c8f873794a08cdf216aa5d0531c6a3747793b70c53f70e98259720a6fe2d7"}, - {file = "coverage-7.4.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e7defbb9737274023e2d7af02cac77043c86ce88a907c58f42b580a97d5bcca9"}, - {file = "coverage-7.4.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a1526d265743fb49363974b7aa8d5899ff64ee07df47dd8d3e37dcc0818f09ed"}, - {file = "coverage-7.4.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf635a52fc1ea401baf88843ae8708591aa4adff875e5c23220de43b1ccf575c"}, - {file = "coverage-7.4.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:756ded44f47f330666843b5781be126ab57bb57c22adbb07d83f6b519783b870"}, - {file = "coverage-7.4.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:0eb3c2f32dabe3a4aaf6441dde94f35687224dfd7eb2a7f47f3fd9428e421058"}, - {file = "coverage-7.4.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:bfd5db349d15c08311702611f3dccbef4b4e2ec148fcc636cf8739519b4a5c0f"}, - {file = "coverage-7.4.0-cp39-cp39-win32.whl", hash = "sha256:53d7d9158ee03956e0eadac38dfa1ec8068431ef8058fe6447043db1fb40d932"}, - {file = "coverage-7.4.0-cp39-cp39-win_amd64.whl", hash = "sha256:cfd2a8b6b0d8e66e944d47cdec2f47c48fef2ba2f2dff5a9a75757f64172857e"}, - {file = "coverage-7.4.0-pp38.pp39.pp310-none-any.whl", hash = "sha256:c530833afc4707fe48524a44844493f36d8727f04dcce91fb978c414a8556cc6"}, - {file = "coverage-7.4.0.tar.gz", hash = "sha256:707c0f58cb1712b8809ece32b68996ee1e609f71bd14615bd8f87a1293cb610e"}, + {file = "coverage-7.6.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5f8ae553cba74085db385d489c7a792ad66f7f9ba2ee85bfa508aeb84cf0ba07"}, + {file = "coverage-7.6.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8165b796df0bd42e10527a3f493c592ba494f16ef3c8b531288e3d0d72c1f6f0"}, + {file = "coverage-7.6.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c7c8b95bf47db6d19096a5e052ffca0a05f335bc63cef281a6e8fe864d450a72"}, + {file = "coverage-7.6.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8ed9281d1b52628e81393f5eaee24a45cbd64965f41857559c2b7ff19385df51"}, + {file = "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"}, + {file = "coverage-7.6.4-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:d541423cdd416b78626b55f123412fcf979d22a2c39fce251b350de38c15c15b"}, + {file = "coverage-7.6.4-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:58809e238a8a12a625c70450b48e8767cff9eb67c62e6154a642b21ddf79baea"}, + {file = "coverage-7.6.4-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:c9b8e184898ed014884ca84c70562b4a82cbc63b044d366fedc68bc2b2f3394a"}, + {file = "coverage-7.6.4-cp310-cp310-win32.whl", hash = "sha256:6bd818b7ea14bc6e1f06e241e8234508b21edf1b242d49831831a9450e2f35fa"}, + {file = "coverage-7.6.4-cp310-cp310-win_amd64.whl", hash = "sha256:06babbb8f4e74b063dbaeb74ad68dfce9186c595a15f11f5d5683f748fa1d172"}, + {file = "coverage-7.6.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:73d2b73584446e66ee633eaad1a56aad577c077f46c35ca3283cd687b7715b0b"}, + {file = "coverage-7.6.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:51b44306032045b383a7a8a2c13878de375117946d68dcb54308111f39775a25"}, + {file = "coverage-7.6.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0b3fb02fe73bed561fa12d279a417b432e5b50fe03e8d663d61b3d5990f29546"}, + {file = "coverage-7.6.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ed8fe9189d2beb6edc14d3ad19800626e1d9f2d975e436f84e19efb7fa19469b"}, + {file = "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"}, + {file = "coverage-7.6.4-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:ade3ca1e5f0ff46b678b66201f7ff477e8fa11fb537f3b55c3f0568fbfe6e718"}, + {file = "coverage-7.6.4-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:27fb4a050aaf18772db513091c9c13f6cb94ed40eacdef8dad8411d92d9992db"}, + {file = "coverage-7.6.4-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:4f704f0998911abf728a7783799444fcbbe8261c4a6c166f667937ae6a8aa522"}, + {file = "coverage-7.6.4-cp311-cp311-win32.whl", hash = "sha256:29155cd511ee058e260db648b6182c419422a0d2e9a4fa44501898cf918866cf"}, + {file = "coverage-7.6.4-cp311-cp311-win_amd64.whl", hash = "sha256:8902dd6a30173d4ef09954bfcb24b5d7b5190cf14a43170e386979651e09ba19"}, + {file = "coverage-7.6.4-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:12394842a3a8affa3ba62b0d4ab7e9e210c5e366fbac3e8b2a68636fb19892c2"}, + {file = "coverage-7.6.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2b6b4c83d8e8ea79f27ab80778c19bc037759aea298da4b56621f4474ffeb117"}, + {file = "coverage-7.6.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d5b8007f81b88696d06f7df0cb9af0d3b835fe0c8dbf489bad70b45f0e45613"}, + {file = "coverage-7.6.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b57b768feb866f44eeed9f46975f3d6406380275c5ddfe22f531a2bf187eda27"}, + {file = "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"}, + {file = "coverage-7.6.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:0b58c672d14f16ed92a48db984612f5ce3836ae7d72cdd161001cc54512571f2"}, + {file = "coverage-7.6.4-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:2fdef0d83a2d08d69b1f2210a93c416d54e14d9eb398f6ab2f0a209433db19e1"}, + {file = "coverage-7.6.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:8cf717ee42012be8c0cb205dbbf18ffa9003c4cbf4ad078db47b95e10748eec5"}, + {file = "coverage-7.6.4-cp312-cp312-win32.whl", hash = "sha256:7bb92c539a624cf86296dd0c68cd5cc286c9eef2d0c3b8b192b604ce9de20a17"}, + {file = "coverage-7.6.4-cp312-cp312-win_amd64.whl", hash = "sha256:1032e178b76a4e2b5b32e19d0fd0abbce4b58e77a1ca695820d10e491fa32b08"}, + {file = "coverage-7.6.4-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:023bf8ee3ec6d35af9c1c6ccc1d18fa69afa1cb29eaac57cb064dbb262a517f9"}, + {file = "coverage-7.6.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:b0ac3d42cb51c4b12df9c5f0dd2f13a4f24f01943627120ec4d293c9181219ba"}, + {file = "coverage-7.6.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f8fe4984b431f8621ca53d9380901f62bfb54ff759a1348cd140490ada7b693c"}, + {file = "coverage-7.6.4-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5fbd612f8a091954a0c8dd4c0b571b973487277d26476f8480bfa4b2a65b5d06"}, + {file = "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"}, + {file = "coverage-7.6.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:dab4d16dfef34b185032580e2f2f89253d302facba093d5fa9dbe04f569c4f4b"}, + {file = "coverage-7.6.4-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:862264b12ebb65ad8d863d51f17758b1684560b66ab02770d4f0baf2ff75da21"}, + {file = "coverage-7.6.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:5beb1ee382ad32afe424097de57134175fea3faf847b9af002cc7895be4e2a5a"}, + {file = "coverage-7.6.4-cp313-cp313-win32.whl", hash = "sha256:bf20494da9653f6410213424f5f8ad0ed885e01f7e8e59811f572bdb20b8972e"}, + {file = "coverage-7.6.4-cp313-cp313-win_amd64.whl", hash = "sha256:182e6cd5c040cec0a1c8d415a87b67ed01193ed9ad458ee427741c7d8513d963"}, + {file = "coverage-7.6.4-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:a181e99301a0ae128493a24cfe5cfb5b488c4e0bf2f8702091473d033494d04f"}, + {file = "coverage-7.6.4-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:df57bdbeffe694e7842092c5e2e0bc80fff7f43379d465f932ef36f027179806"}, + {file = "coverage-7.6.4-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0bcd1069e710600e8e4cf27f65c90c7843fa8edfb4520fb0ccb88894cad08b11"}, + {file = "coverage-7.6.4-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:99b41d18e6b2a48ba949418db48159d7a2e81c5cc290fc934b7d2380515bd0e3"}, + {file = "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"}, + {file = "coverage-7.6.4-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:53d202fd109416ce011578f321460795abfe10bb901b883cafd9b3ef851bacfc"}, + {file = "coverage-7.6.4-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:c48167910a8f644671de9f2083a23630fbf7a1cb70ce939440cd3328e0919f70"}, + {file = "coverage-7.6.4-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:cc8ff50b50ce532de2fa7a7daae9dd12f0a699bfcd47f20945364e5c31799fef"}, + {file = "coverage-7.6.4-cp313-cp313t-win32.whl", hash = "sha256:b8d3a03d9bfcaf5b0141d07a88456bb6a4c3ce55c080712fec8418ef3610230e"}, + {file = "coverage-7.6.4-cp313-cp313t-win_amd64.whl", hash = "sha256:f3ddf056d3ebcf6ce47bdaf56142af51bb7fad09e4af310241e9db7a3a8022e1"}, + {file = "coverage-7.6.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9cb7fa111d21a6b55cbf633039f7bc2749e74932e3aa7cb7333f675a58a58bf3"}, + {file = "coverage-7.6.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:11a223a14e91a4693d2d0755c7a043db43d96a7450b4f356d506c2562c48642c"}, + {file = "coverage-7.6.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a413a096c4cbac202433c850ee43fa326d2e871b24554da8327b01632673a076"}, + {file = "coverage-7.6.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:00a1d69c112ff5149cabe60d2e2ee948752c975d95f1e1096742e6077affd376"}, + {file = "coverage-7.6.4-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1f76846299ba5c54d12c91d776d9605ae33f8ae2b9d1d3c3703cf2db1a67f2c0"}, + {file = "coverage-7.6.4-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:fe439416eb6380de434886b00c859304338f8b19f6f54811984f3420a2e03858"}, + {file = "coverage-7.6.4-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:0294ca37f1ba500667b1aef631e48d875ced93ad5e06fa665a3295bdd1d95111"}, + {file = "coverage-7.6.4-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:6f01ba56b1c0e9d149f9ac85a2f999724895229eb36bd997b61e62999e9b0901"}, + {file = "coverage-7.6.4-cp39-cp39-win32.whl", hash = "sha256:bc66f0bf1d7730a17430a50163bb264ba9ded56739112368ba985ddaa9c3bd09"}, + {file = "coverage-7.6.4-cp39-cp39-win_amd64.whl", hash = "sha256:c481b47f6b5845064c65a7bc78bc0860e635a9b055af0df46fdf1c58cebf8e8f"}, + {file = "coverage-7.6.4-pp39.pp310-none-any.whl", hash = "sha256:3c65d37f3a9ebb703e710befdc489a38683a5b152242664b973a7b7b22348a4e"}, + {file = "coverage-7.6.4.tar.gz", hash = "sha256:29fc0f17b1d3fea332f8001d4558f8214af7f1d87a345f3a133c901d60347c73"}, ] [package.dependencies] @@ -747,14 +757,14 @@ files = [ test = ["pytest (>=6)"] [[package]] -name = "fastapi-slim" -version = "0.115.4" +name = "fastapi" +version = "0.115.6" description = "FastAPI framework, high performance, easy to learn, fast to code, ready for production" optional = false python-versions = ">=3.8" files = [ - {file = "fastapi_slim-0.115.4-py3-none-any.whl", hash = "sha256:8947515618c21665590a1673a0bfe4c721db4267999c149d5301c3c0f7b3d9ce"}, - {file = "fastapi_slim-0.115.4.tar.gz", hash = "sha256:6d37987e4d1f6adefb8c7119c9b804e59c9b3f1a488be5425994d52308e2f958"}, + {file = "fastapi-0.115.6-py3-none-any.whl", hash = "sha256:e9240b29e36fa8f4bb7290316988e90c381e5092e0cbe84e7818cc3713bcf305"}, + {file = "fastapi-0.115.6.tar.gz", hash = "sha256:9ec46f7addc14ea472958a96aae5b5de65f39721a46aaf5705c480d9a8b76654"}, ] [package.dependencies] @@ -946,13 +956,13 @@ tqdm = ["tqdm"] [[package]] name = "ftfy" -version = "6.3.0" +version = "6.3.1" description = "Fixes mojibake and other problems with Unicode, after the fact" optional = false python-versions = ">=3.9" files = [ - {file = "ftfy-6.3.0-py3-none-any.whl", hash = "sha256:17aca296801f44142e3ff2c16f93fbf6a87609ebb3704a9a41dd5d4903396caf"}, - {file = "ftfy-6.3.0.tar.gz", hash = "sha256:1c7d6418e72b25a7760feb150acf574b86924dbb2e95b32c0b3abbd1ba3d7ad6"}, + {file = "ftfy-6.3.1-py3-none-any.whl", hash = "sha256:7c70eb532015cd2f9adb53f101fb6c7945988d023a085d127d1573dc49dd0083"}, + {file = "ftfy-6.3.1.tar.gz", hash = "sha256:9b3c3d90f84fb267fe64d375a07b7f8912d817cf86009ae134aa03e1819506ec"}, ] [package.dependencies] @@ -1242,61 +1252,68 @@ trio = ["trio (>=0.22.0,<0.23.0)"] [[package]] name = "httptools" -version = "0.6.1" +version = "0.6.4" description = "A collection of framework independent HTTP protocol utils." optional = false python-versions = ">=3.8.0" files = [ - {file = "httptools-0.6.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d2f6c3c4cb1948d912538217838f6e9960bc4a521d7f9b323b3da579cd14532f"}, - {file = "httptools-0.6.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:00d5d4b68a717765b1fabfd9ca755bd12bf44105eeb806c03d1962acd9b8e563"}, - {file = "httptools-0.6.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:639dc4f381a870c9ec860ce5c45921db50205a37cc3334e756269736ff0aac58"}, - {file = "httptools-0.6.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e57997ac7fb7ee43140cc03664de5f268813a481dff6245e0075925adc6aa185"}, - {file = "httptools-0.6.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:0ac5a0ae3d9f4fe004318d64b8a854edd85ab76cffbf7ef5e32920faef62f142"}, - {file = "httptools-0.6.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:3f30d3ce413088a98b9db71c60a6ada2001a08945cb42dd65a9a9fe228627658"}, - {file = "httptools-0.6.1-cp310-cp310-win_amd64.whl", hash = "sha256:1ed99a373e327f0107cb513b61820102ee4f3675656a37a50083eda05dc9541b"}, - {file = "httptools-0.6.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:7a7ea483c1a4485c71cb5f38be9db078f8b0e8b4c4dc0210f531cdd2ddac1ef1"}, - {file = "httptools-0.6.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:85ed077c995e942b6f1b07583e4eb0a8d324d418954fc6af913d36db7c05a5a0"}, - {file = "httptools-0.6.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8b0bb634338334385351a1600a73e558ce619af390c2b38386206ac6a27fecfc"}, - {file = "httptools-0.6.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7d9ceb2c957320def533671fc9c715a80c47025139c8d1f3797477decbc6edd2"}, - {file = "httptools-0.6.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:4f0f8271c0a4db459f9dc807acd0eadd4839934a4b9b892f6f160e94da309837"}, - {file = "httptools-0.6.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:6a4f5ccead6d18ec072ac0b84420e95d27c1cdf5c9f1bc8fbd8daf86bd94f43d"}, - {file = "httptools-0.6.1-cp311-cp311-win_amd64.whl", hash = "sha256:5cceac09f164bcba55c0500a18fe3c47df29b62353198e4f37bbcc5d591172c3"}, - {file = "httptools-0.6.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:75c8022dca7935cba14741a42744eee13ba05db00b27a4b940f0d646bd4d56d0"}, - {file = "httptools-0.6.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:48ed8129cd9a0d62cf4d1575fcf90fb37e3ff7d5654d3a5814eb3d55f36478c2"}, - {file = "httptools-0.6.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6f58e335a1402fb5a650e271e8c2d03cfa7cea46ae124649346d17bd30d59c90"}, - {file = "httptools-0.6.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:93ad80d7176aa5788902f207a4e79885f0576134695dfb0fefc15b7a4648d503"}, - {file = "httptools-0.6.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:9bb68d3a085c2174c2477eb3ffe84ae9fb4fde8792edb7bcd09a1d8467e30a84"}, - {file = "httptools-0.6.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:b512aa728bc02354e5ac086ce76c3ce635b62f5fbc32ab7082b5e582d27867bb"}, - {file = "httptools-0.6.1-cp312-cp312-win_amd64.whl", hash = "sha256:97662ce7fb196c785344d00d638fc9ad69e18ee4bfb4000b35a52efe5adcc949"}, - {file = "httptools-0.6.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:8e216a038d2d52ea13fdd9b9c9c7459fb80d78302b257828285eca1c773b99b3"}, - {file = "httptools-0.6.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:3e802e0b2378ade99cd666b5bffb8b2a7cc8f3d28988685dc300469ea8dd86cb"}, - {file = "httptools-0.6.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4bd3e488b447046e386a30f07af05f9b38d3d368d1f7b4d8f7e10af85393db97"}, - {file = "httptools-0.6.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fe467eb086d80217b7584e61313ebadc8d187a4d95bb62031b7bab4b205c3ba3"}, - {file = "httptools-0.6.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:3c3b214ce057c54675b00108ac42bacf2ab8f85c58e3f324a4e963bbc46424f4"}, - {file = "httptools-0.6.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8ae5b97f690badd2ca27cbf668494ee1b6d34cf1c464271ef7bfa9ca6b83ffaf"}, - {file = "httptools-0.6.1-cp38-cp38-win_amd64.whl", hash = "sha256:405784577ba6540fa7d6ff49e37daf104e04f4b4ff2d1ac0469eaa6a20fde084"}, - {file = "httptools-0.6.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:95fb92dd3649f9cb139e9c56604cc2d7c7bf0fc2e7c8d7fbd58f96e35eddd2a3"}, - {file = "httptools-0.6.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:dcbab042cc3ef272adc11220517278519adf8f53fd3056d0e68f0a6f891ba94e"}, - {file = "httptools-0.6.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0cf2372e98406efb42e93bfe10f2948e467edfd792b015f1b4ecd897903d3e8d"}, - {file = "httptools-0.6.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:678fcbae74477a17d103b7cae78b74800d795d702083867ce160fc202104d0da"}, - {file = "httptools-0.6.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:e0b281cf5a125c35f7f6722b65d8542d2e57331be573e9e88bc8b0115c4a7a81"}, - {file = "httptools-0.6.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:95658c342529bba4e1d3d2b1a874db16c7cca435e8827422154c9da76ac4e13a"}, - {file = "httptools-0.6.1-cp39-cp39-win_amd64.whl", hash = "sha256:7ebaec1bf683e4bf5e9fbb49b8cc36da482033596a415b3e4ebab5a4c0d7ec5e"}, - {file = "httptools-0.6.1.tar.gz", hash = "sha256:c6e26c30455600b95d94b1b836085138e82f177351454ee841c148f93a9bad5a"}, + {file = "httptools-0.6.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:3c73ce323711a6ffb0d247dcd5a550b8babf0f757e86a52558fe5b86d6fefcc0"}, + {file = "httptools-0.6.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:345c288418f0944a6fe67be8e6afa9262b18c7626c3ef3c28adc5eabc06a68da"}, + {file = "httptools-0.6.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:deee0e3343f98ee8047e9f4c5bc7cedbf69f5734454a94c38ee829fb2d5fa3c1"}, + {file = "httptools-0.6.4-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ca80b7485c76f768a3bc83ea58373f8db7b015551117375e4918e2aa77ea9b50"}, + {file = "httptools-0.6.4-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:90d96a385fa941283ebd231464045187a31ad932ebfa541be8edf5b3c2328959"}, + {file = "httptools-0.6.4-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:59e724f8b332319e2875efd360e61ac07f33b492889284a3e05e6d13746876f4"}, + {file = "httptools-0.6.4-cp310-cp310-win_amd64.whl", hash = "sha256:c26f313951f6e26147833fc923f78f95604bbec812a43e5ee37f26dc9e5a686c"}, + {file = "httptools-0.6.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:f47f8ed67cc0ff862b84a1189831d1d33c963fb3ce1ee0c65d3b0cbe7b711069"}, + {file = "httptools-0.6.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:0614154d5454c21b6410fdf5262b4a3ddb0f53f1e1721cfd59d55f32138c578a"}, + {file = "httptools-0.6.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f8787367fbdfccae38e35abf7641dafc5310310a5987b689f4c32cc8cc3ee975"}, + {file = "httptools-0.6.4-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:40b0f7fe4fd38e6a507bdb751db0379df1e99120c65fbdc8ee6c1d044897a636"}, + {file = "httptools-0.6.4-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:40a5ec98d3f49904b9fe36827dcf1aadfef3b89e2bd05b0e35e94f97c2b14721"}, + {file = "httptools-0.6.4-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:dacdd3d10ea1b4ca9df97a0a303cbacafc04b5cd375fa98732678151643d4988"}, + {file = "httptools-0.6.4-cp311-cp311-win_amd64.whl", hash = "sha256:288cd628406cc53f9a541cfaf06041b4c71d751856bab45e3702191f931ccd17"}, + {file = "httptools-0.6.4-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:df017d6c780287d5c80601dafa31f17bddb170232d85c066604d8558683711a2"}, + {file = "httptools-0.6.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:85071a1e8c2d051b507161f6c3e26155b5c790e4e28d7f236422dbacc2a9cc44"}, + {file = "httptools-0.6.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69422b7f458c5af875922cdb5bd586cc1f1033295aa9ff63ee196a87519ac8e1"}, + {file = "httptools-0.6.4-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:16e603a3bff50db08cd578d54f07032ca1631450ceb972c2f834c2b860c28ea2"}, + {file = "httptools-0.6.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:ec4f178901fa1834d4a060320d2f3abc5c9e39766953d038f1458cb885f47e81"}, + {file = "httptools-0.6.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:f9eb89ecf8b290f2e293325c646a211ff1c2493222798bb80a530c5e7502494f"}, + {file = "httptools-0.6.4-cp312-cp312-win_amd64.whl", hash = "sha256:db78cb9ca56b59b016e64b6031eda5653be0589dba2b1b43453f6e8b405a0970"}, + {file = "httptools-0.6.4-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ade273d7e767d5fae13fa637f4d53b6e961fb7fd93c7797562663f0171c26660"}, + {file = "httptools-0.6.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:856f4bc0478ae143bad54a4242fccb1f3f86a6e1be5548fecfd4102061b3a083"}, + {file = "httptools-0.6.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:322d20ea9cdd1fa98bd6a74b77e2ec5b818abdc3d36695ab402a0de8ef2865a3"}, + {file = "httptools-0.6.4-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4d87b29bd4486c0093fc64dea80231f7c7f7eb4dc70ae394d70a495ab8436071"}, + {file = "httptools-0.6.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:342dd6946aa6bda4b8f18c734576106b8a31f2fe31492881a9a160ec84ff4bd5"}, + {file = "httptools-0.6.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4b36913ba52008249223042dca46e69967985fb4051951f94357ea681e1f5dc0"}, + {file = "httptools-0.6.4-cp313-cp313-win_amd64.whl", hash = "sha256:28908df1b9bb8187393d5b5db91435ccc9c8e891657f9cbb42a2541b44c82fc8"}, + {file = "httptools-0.6.4-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:d3f0d369e7ffbe59c4b6116a44d6a8eb4783aae027f2c0b366cf0aa964185dba"}, + {file = "httptools-0.6.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:94978a49b8f4569ad607cd4946b759d90b285e39c0d4640c6b36ca7a3ddf2efc"}, + {file = "httptools-0.6.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:40dc6a8e399e15ea525305a2ddba998b0af5caa2566bcd79dcbe8948181eeaff"}, + {file = "httptools-0.6.4-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ab9ba8dcf59de5181f6be44a77458e45a578fc99c31510b8c65b7d5acc3cf490"}, + {file = "httptools-0.6.4-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:fc411e1c0a7dcd2f902c7c48cf079947a7e65b5485dea9decb82b9105ca71a43"}, + {file = "httptools-0.6.4-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:d54efd20338ac52ba31e7da78e4a72570cf729fac82bc31ff9199bedf1dc7440"}, + {file = "httptools-0.6.4-cp38-cp38-win_amd64.whl", hash = "sha256:df959752a0c2748a65ab5387d08287abf6779ae9165916fe053e68ae1fbdc47f"}, + {file = "httptools-0.6.4-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:85797e37e8eeaa5439d33e556662cc370e474445d5fab24dcadc65a8ffb04003"}, + {file = "httptools-0.6.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:db353d22843cf1028f43c3651581e4bb49374d85692a85f95f7b9a130e1b2cab"}, + {file = "httptools-0.6.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d1ffd262a73d7c28424252381a5b854c19d9de5f56f075445d33919a637e3547"}, + {file = "httptools-0.6.4-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:703c346571fa50d2e9856a37d7cd9435a25e7fd15e236c397bf224afaa355fe9"}, + {file = "httptools-0.6.4-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:aafe0f1918ed07b67c1e838f950b1c1fabc683030477e60b335649b8020e1076"}, + {file = "httptools-0.6.4-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:0e563e54979e97b6d13f1bbc05a96109923e76b901f786a5eae36e99c01237bd"}, + {file = "httptools-0.6.4-cp39-cp39-win_amd64.whl", hash = "sha256:b799de31416ecc589ad79dd85a0b2657a8fe39327944998dea368c1d4c9e55e6"}, + {file = "httptools-0.6.4.tar.gz", hash = "sha256:4e93eee4add6493b59a5c514da98c939b244fce4a0d8879cd3f466562f4b7d5c"}, ] [package.extras] -test = ["Cython (>=0.29.24,<0.30.0)"] +test = ["Cython (>=0.29.24)"] [[package]] name = "httpx" -version = "0.27.2" +version = "0.28.1" description = "The next generation HTTP client." optional = false python-versions = ">=3.8" files = [ - {file = "httpx-0.27.2-py3-none-any.whl", hash = "sha256:7bb2708e112d8fdd7829cd4243970f0c223274051cb35ee80c03301ee29a3df0"}, - {file = "httpx-0.27.2.tar.gz", hash = "sha256:f7c2be1d2f3c3c3160d441802406b206c2b76f5947b11115e6df10c6c65e66c2"}, + {file = "httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad"}, + {file = "httpx-0.28.1.tar.gz", hash = "sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc"}, ] [package.dependencies] @@ -1304,7 +1321,6 @@ anyio = "*" certifi = "*" httpcore = "==1.*" idna = "*" -sniffio = "*" [package.extras] brotli = ["brotli", "brotlicffi"] @@ -1315,13 +1331,13 @@ zstd = ["zstandard (>=0.18.0)"] [[package]] name = "huggingface-hub" -version = "0.26.2" +version = "0.27.0" description = "Client library to download and publish models, datasets and other repos on the huggingface.co hub" optional = false python-versions = ">=3.8.0" files = [ - {file = "huggingface_hub-0.26.2-py3-none-any.whl", hash = "sha256:98c2a5a8e786c7b2cb6fdeb2740893cba4d53e312572ed3d8afafda65b128c46"}, - {file = "huggingface_hub-0.26.2.tar.gz", hash = "sha256:b100d853465d965733964d123939ba287da60a547087783ddff8a323f340332b"}, + {file = "huggingface_hub-0.27.0-py3-none-any.whl", hash = "sha256:8f2e834517f1f1ddf1ecc716f91b120d7333011b7485f665a9a412eacb1a2a81"}, + {file = "huggingface_hub-0.27.0.tar.gz", hash = "sha256:902cce1a1be5739f5589e560198a65a8edcfd3b830b1666f36e4b961f0454fac"}, ] [package.dependencies] @@ -1609,13 +1625,13 @@ test = ["pytest (>=7.4)", "pytest-cov (>=4.1)"] [[package]] name = "locust" -version = "2.32.0" +version = "2.32.4" description = "Developer-friendly load testing framework" optional = false python-versions = ">=3.9" files = [ - {file = "locust-2.32.0-py3-none-any.whl", hash = "sha256:e004514332b8631ca91382d11d224baee4ced040c5f5c8b2233800ebcbc73c0e"}, - {file = "locust-2.32.0.tar.gz", hash = "sha256:d8f7f5d9d4e801b2e7b0ee3f31109333673da744ccedf85e7da0151f2d263dd9"}, + {file = "locust-2.32.4-py3-none-any.whl", hash = "sha256:7c5b8767c0d771b5167d5d6b82878622faead74f394eb9cafe8891d89eb36b97"}, + {file = "locust-2.32.4.tar.gz", hash = "sha256:fd650cbc40842e721668a8d0f7f8224775432b40c63d0a378546b9a9f54b7559"}, ] [package.dependencies] @@ -1636,6 +1652,7 @@ requests = [ {version = ">=2.26.0", markers = "python_full_version <= \"3.11.0\""}, {version = ">=2.32.2", markers = "python_full_version > \"3.11.0\""}, ] +setuptools = ">=70.0.0" tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} typing_extensions = {version = ">=4.6.0", markers = "python_version < \"3.11\""} Werkzeug = ">=2.0.0" @@ -2050,36 +2067,32 @@ reference = ["Pillow", "google-re2"] [[package]] name = "onnxruntime" -version = "1.19.2" +version = "1.20.1" description = "ONNX Runtime is a runtime accelerator for Machine Learning models" optional = false python-versions = "*" files = [ - {file = "onnxruntime-1.19.2-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:84fa57369c06cadd3c2a538ae2a26d76d583e7c34bdecd5769d71ca5c0fc750e"}, - {file = "onnxruntime-1.19.2-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bdc471a66df0c1cdef774accef69e9f2ca168c851ab5e4f2f3341512c7ef4666"}, - {file = "onnxruntime-1.19.2-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e3a4ce906105d99ebbe817f536d50a91ed8a4d1592553f49b3c23c4be2560ae6"}, - {file = "onnxruntime-1.19.2-cp310-cp310-win32.whl", hash = "sha256:4b3d723cc154c8ddeb9f6d0a8c0d6243774c6b5930847cc83170bfe4678fafb3"}, - {file = "onnxruntime-1.19.2-cp310-cp310-win_amd64.whl", hash = "sha256:17ed7382d2c58d4b7354fb2b301ff30b9bf308a1c7eac9546449cd122d21cae5"}, - {file = "onnxruntime-1.19.2-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:d863e8acdc7232d705d49e41087e10b274c42f09e259016a46f32c34e06dc4fd"}, - {file = "onnxruntime-1.19.2-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c1dfe4f660a71b31caa81fc298a25f9612815215a47b286236e61d540350d7b6"}, - {file = "onnxruntime-1.19.2-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a36511dc07c5c964b916697e42e366fa43c48cdb3d3503578d78cef30417cb84"}, - {file = "onnxruntime-1.19.2-cp311-cp311-win32.whl", hash = "sha256:50cbb8dc69d6befad4746a69760e5b00cc3ff0a59c6c3fb27f8afa20e2cab7e7"}, - {file = "onnxruntime-1.19.2-cp311-cp311-win_amd64.whl", hash = "sha256:1c3e5d415b78337fa0b1b75291e9ea9fb2a4c1f148eb5811e7212fed02cfffa8"}, - {file = "onnxruntime-1.19.2-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:68e7051bef9cfefcbb858d2d2646536829894d72a4130c24019219442b1dd2ed"}, - {file = "onnxruntime-1.19.2-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d2d366fbcc205ce68a8a3bde2185fd15c604d9645888703785b61ef174265168"}, - {file = "onnxruntime-1.19.2-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:477b93df4db467e9cbf34051662a4b27c18e131fa1836e05974eae0d6e4cf29b"}, - {file = "onnxruntime-1.19.2-cp312-cp312-win32.whl", hash = "sha256:9a174073dc5608fad05f7cf7f320b52e8035e73d80b0a23c80f840e5a97c0147"}, - {file = "onnxruntime-1.19.2-cp312-cp312-win_amd64.whl", hash = "sha256:190103273ea4507638ffc31d66a980594b237874b65379e273125150eb044857"}, - {file = "onnxruntime-1.19.2-cp38-cp38-macosx_11_0_universal2.whl", hash = "sha256:636bc1d4cc051d40bc52e1f9da87fbb9c57d9d47164695dfb1c41646ea51ea66"}, - {file = "onnxruntime-1.19.2-cp38-cp38-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5bd8b875757ea941cbcfe01582970cc299893d1b65bd56731e326a8333f638a3"}, - {file = "onnxruntime-1.19.2-cp38-cp38-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b2046fc9560f97947bbc1acbe4c6d48585ef0f12742744307d3364b131ac5778"}, - {file = "onnxruntime-1.19.2-cp38-cp38-win32.whl", hash = "sha256:31c12840b1cde4ac1f7d27d540c44e13e34f2345cf3642762d2a3333621abb6a"}, - {file = "onnxruntime-1.19.2-cp38-cp38-win_amd64.whl", hash = "sha256:016229660adea180e9a32ce218b95f8f84860a200f0f13b50070d7d90e92956c"}, - {file = "onnxruntime-1.19.2-cp39-cp39-macosx_11_0_universal2.whl", hash = "sha256:006c8d326835c017a9e9f74c9c77ebb570a71174a1e89fe078b29a557d9c3848"}, - {file = "onnxruntime-1.19.2-cp39-cp39-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:df2a94179a42d530b936f154615b54748239c2908ee44f0d722cb4df10670f68"}, - {file = "onnxruntime-1.19.2-cp39-cp39-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fae4b4de45894b9ce7ae418c5484cbf0341db6813effec01bb2216091c52f7fb"}, - {file = "onnxruntime-1.19.2-cp39-cp39-win32.whl", hash = "sha256:dc5430f473e8706fff837ae01323be9dcfddd3ea471c900a91fa7c9b807ec5d3"}, - {file = "onnxruntime-1.19.2-cp39-cp39-win_amd64.whl", hash = "sha256:38475e29a95c5f6c62c2c603d69fc7d4c6ccbf4df602bd567b86ae1138881c49"}, + {file = "onnxruntime-1.20.1-cp310-cp310-macosx_13_0_universal2.whl", hash = "sha256:e50ba5ff7fed4f7d9253a6baf801ca2883cc08491f9d32d78a80da57256a5439"}, + {file = "onnxruntime-1.20.1-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7b2908b50101a19e99c4d4e97ebb9905561daf61829403061c1adc1b588bc0de"}, + {file = "onnxruntime-1.20.1-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d82daaec24045a2e87598b8ac2b417b1cce623244e80e663882e9fe1aae86410"}, + {file = "onnxruntime-1.20.1-cp310-cp310-win32.whl", hash = "sha256:4c4b251a725a3b8cf2aab284f7d940c26094ecd9d442f07dd81ab5470e99b83f"}, + {file = "onnxruntime-1.20.1-cp310-cp310-win_amd64.whl", hash = "sha256:d3b616bb53a77a9463707bb313637223380fc327f5064c9a782e8ec69c22e6a2"}, + {file = "onnxruntime-1.20.1-cp311-cp311-macosx_13_0_universal2.whl", hash = "sha256:06bfbf02ca9ab5f28946e0f912a562a5f005301d0c419283dc57b3ed7969bb7b"}, + {file = "onnxruntime-1.20.1-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f6243e34d74423bdd1edf0ae9596dd61023b260f546ee17d701723915f06a9f7"}, + {file = "onnxruntime-1.20.1-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5eec64c0269dcdb8d9a9a53dc4d64f87b9e0c19801d9321246a53b7eb5a7d1bc"}, + {file = "onnxruntime-1.20.1-cp311-cp311-win32.whl", hash = "sha256:a19bc6e8c70e2485a1725b3d517a2319603acc14c1f1a017dda0afe6d4665b41"}, + {file = "onnxruntime-1.20.1-cp311-cp311-win_amd64.whl", hash = "sha256:8508887eb1c5f9537a4071768723ec7c30c28eb2518a00d0adcd32c89dea3221"}, + {file = "onnxruntime-1.20.1-cp312-cp312-macosx_13_0_universal2.whl", hash = "sha256:22b0655e2bf4f2161d52706e31f517a0e54939dc393e92577df51808a7edc8c9"}, + {file = "onnxruntime-1.20.1-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f1f56e898815963d6dc4ee1c35fc6c36506466eff6d16f3cb9848cea4e8c8172"}, + {file = "onnxruntime-1.20.1-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bb71a814f66517a65628c9e4a2bb530a6edd2cd5d87ffa0af0f6f773a027d99e"}, + {file = "onnxruntime-1.20.1-cp312-cp312-win32.whl", hash = "sha256:bd386cc9ee5f686ee8a75ba74037750aca55183085bf1941da8efcfe12d5b120"}, + {file = "onnxruntime-1.20.1-cp312-cp312-win_amd64.whl", hash = "sha256:19c2d843eb074f385e8bbb753a40df780511061a63f9def1b216bf53860223fb"}, + {file = "onnxruntime-1.20.1-cp313-cp313-macosx_13_0_universal2.whl", hash = "sha256:cc01437a32d0042b606f462245c8bbae269e5442797f6213e36ce61d5abdd8cc"}, + {file = "onnxruntime-1.20.1-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:fb44b08e017a648924dbe91b82d89b0c105b1adcfe31e90d1dc06b8677ad37be"}, + {file = "onnxruntime-1.20.1-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bda6aebdf7917c1d811f21d41633df00c58aff2bef2f598f69289c1f1dabc4b3"}, + {file = "onnxruntime-1.20.1-cp313-cp313-win_amd64.whl", hash = "sha256:d30367df7e70f1d9fc5a6a68106f5961686d39b54d3221f760085524e8d38e16"}, + {file = "onnxruntime-1.20.1-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c9158465745423b2b5d97ed25aa7740c7d38d2993ee2e5c3bfacb0c4145c49d8"}, + {file = "onnxruntime-1.20.1-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0df6f2df83d61f46e842dbcde610ede27218947c33e994545a22333491e72a3b"}, ] [package.dependencies] @@ -2170,69 +2183,86 @@ numpy = [ [[package]] name = "orjson" -version = "3.10.10" +version = "3.10.12" description = "Fast, correct Python JSON library supporting dataclasses, datetimes, and numpy" optional = false python-versions = ">=3.8" files = [ - {file = "orjson-3.10.10-cp310-cp310-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:b788a579b113acf1c57e0a68e558be71d5d09aa67f62ca1f68e01117e550a998"}, - {file = "orjson-3.10.10-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:804b18e2b88022c8905bb79bd2cbe59c0cd014b9328f43da8d3b28441995cda4"}, - {file = "orjson-3.10.10-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9972572a1d042ec9ee421b6da69f7cc823da5962237563fa548ab17f152f0b9b"}, - {file = "orjson-3.10.10-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dc6993ab1c2ae7dd0711161e303f1db69062955ac2668181bfdf2dd410e65258"}, - {file = "orjson-3.10.10-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d78e4cacced5781b01d9bc0f0cd8b70b906a0e109825cb41c1b03f9c41e4ce86"}, - {file = "orjson-3.10.10-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e6eb2598df518281ba0cbc30d24c5b06124ccf7e19169e883c14e0831217a0bc"}, - {file = "orjson-3.10.10-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:23776265c5215ec532de6238a52707048401a568f0fa0d938008e92a147fe2c7"}, - {file = "orjson-3.10.10-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:8cc2a654c08755cef90b468ff17c102e2def0edd62898b2486767204a7f5cc9c"}, - {file = "orjson-3.10.10-cp310-none-win32.whl", hash = "sha256:081b3fc6a86d72efeb67c13d0ea7c030017bd95f9868b1e329a376edc456153b"}, - {file = "orjson-3.10.10-cp310-none-win_amd64.whl", hash = "sha256:ff38c5fb749347768a603be1fb8a31856458af839f31f064c5aa74aca5be9efe"}, - {file = "orjson-3.10.10-cp311-cp311-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:879e99486c0fbb256266c7c6a67ff84f46035e4f8749ac6317cc83dacd7f993a"}, - {file = "orjson-3.10.10-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:019481fa9ea5ff13b5d5d95e6fd5ab25ded0810c80b150c2c7b1cc8660b662a7"}, - {file = "orjson-3.10.10-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:0dd57eff09894938b4c86d4b871a479260f9e156fa7f12f8cad4b39ea8028bb5"}, - {file = "orjson-3.10.10-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dbde6d70cd95ab4d11ea8ac5e738e30764e510fc54d777336eec09bb93b8576c"}, - {file = "orjson-3.10.10-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3b2625cb37b8fb42e2147404e5ff7ef08712099197a9cd38895006d7053e69d6"}, - {file = "orjson-3.10.10-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dbf3c20c6a7db69df58672a0d5815647ecf78c8e62a4d9bd284e8621c1fe5ccb"}, - {file = "orjson-3.10.10-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:75c38f5647e02d423807d252ce4528bf6a95bd776af999cb1fb48867ed01d1f6"}, - {file = "orjson-3.10.10-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:23458d31fa50ec18e0ec4b0b4343730928296b11111df5f547c75913714116b2"}, - {file = "orjson-3.10.10-cp311-none-win32.whl", hash = "sha256:2787cd9dedc591c989f3facd7e3e86508eafdc9536a26ec277699c0aa63c685b"}, - {file = "orjson-3.10.10-cp311-none-win_amd64.whl", hash = "sha256:6514449d2c202a75183f807bc755167713297c69f1db57a89a1ef4a0170ee269"}, - {file = "orjson-3.10.10-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:8564f48f3620861f5ef1e080ce7cd122ee89d7d6dacf25fcae675ff63b4d6e05"}, - {file = "orjson-3.10.10-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c5bf161a32b479034098c5b81f2608f09167ad2fa1c06abd4e527ea6bf4837a9"}, - {file = "orjson-3.10.10-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:68b65c93617bcafa7f04b74ae8bc2cc214bd5cb45168a953256ff83015c6747d"}, - {file = "orjson-3.10.10-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e8e28406f97fc2ea0c6150f4c1b6e8261453318930b334abc419214c82314f85"}, - {file = "orjson-3.10.10-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e4d0d9fe174cc7a5bdce2e6c378bcdb4c49b2bf522a8f996aa586020e1b96cee"}, - {file = "orjson-3.10.10-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b3be81c42f1242cbed03cbb3973501fcaa2675a0af638f8be494eaf37143d999"}, - {file = "orjson-3.10.10-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:65f9886d3bae65be026219c0a5f32dbbe91a9e6272f56d092ab22561ad0ea33b"}, - {file = "orjson-3.10.10-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:730ed5350147db7beb23ddaf072f490329e90a1d059711d364b49fe352ec987b"}, - {file = "orjson-3.10.10-cp312-none-win32.whl", hash = "sha256:a8f4bf5f1c85bea2170800020d53a8877812892697f9c2de73d576c9307a8a5f"}, - {file = "orjson-3.10.10-cp312-none-win_amd64.whl", hash = "sha256:384cd13579a1b4cd689d218e329f459eb9ddc504fa48c5a83ef4889db7fd7a4f"}, - {file = "orjson-3.10.10-cp313-cp313-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:44bffae68c291f94ff5a9b4149fe9d1bdd4cd0ff0fb575bcea8351d48db629a1"}, - {file = "orjson-3.10.10-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e27b4c6437315df3024f0835887127dac2a0a3ff643500ec27088d2588fa5ae1"}, - {file = "orjson-3.10.10-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bca84df16d6b49325a4084fd8b2fe2229cb415e15c46c529f868c3387bb1339d"}, - {file = "orjson-3.10.10-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:c14ce70e8f39bd71f9f80423801b5d10bf93d1dceffdecd04df0f64d2c69bc01"}, - {file = "orjson-3.10.10-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:24ac62336da9bda1bd93c0491eff0613003b48d3cb5d01470842e7b52a40d5b4"}, - {file = "orjson-3.10.10-cp313-none-win32.whl", hash = "sha256:eb0a42831372ec2b05acc9ee45af77bcaccbd91257345f93780a8e654efc75db"}, - {file = "orjson-3.10.10-cp313-none-win_amd64.whl", hash = "sha256:f0c4f37f8bf3f1075c6cc8dd8a9f843689a4b618628f8812d0a71e6968b95ffd"}, - {file = "orjson-3.10.10-cp38-cp38-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:829700cc18503efc0cf502d630f612884258020d98a317679cd2054af0259568"}, - {file = "orjson-3.10.10-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e0ceb5e0e8c4f010ac787d29ae6299846935044686509e2f0f06ed441c1ca949"}, - {file = "orjson-3.10.10-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:0c25908eb86968613216f3db4d3003f1c45d78eb9046b71056ca327ff92bdbd4"}, - {file = "orjson-3.10.10-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:218cb0bc03340144b6328a9ff78f0932e642199ac184dd74b01ad691f42f93ff"}, - {file = "orjson-3.10.10-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e2277ec2cea3775640dc81ab5195bb5b2ada2fe0ea6eee4677474edc75ea6785"}, - {file = "orjson-3.10.10-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:848ea3b55ab5ccc9d7bbd420d69432628b691fba3ca8ae3148c35156cbd282aa"}, - {file = "orjson-3.10.10-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:e3e67b537ac0c835b25b5f7d40d83816abd2d3f4c0b0866ee981a045287a54f3"}, - {file = "orjson-3.10.10-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:7948cfb909353fce2135dcdbe4521a5e7e1159484e0bb024c1722f272488f2b8"}, - {file = "orjson-3.10.10-cp38-none-win32.whl", hash = "sha256:78bee66a988f1a333dc0b6257503d63553b1957889c17b2c4ed72385cd1b96ae"}, - {file = "orjson-3.10.10-cp38-none-win_amd64.whl", hash = "sha256:f1d647ca8d62afeb774340a343c7fc023efacfd3a39f70c798991063f0c681dd"}, - {file = "orjson-3.10.10-cp39-cp39-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:5a059afddbaa6dd733b5a2d76a90dbc8af790b993b1b5cb97a1176ca713b5df8"}, - {file = "orjson-3.10.10-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6f9b5c59f7e2a1a410f971c5ebc68f1995822837cd10905ee255f96074537ee6"}, - {file = "orjson-3.10.10-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d5ef198bafdef4aa9d49a4165ba53ffdc0a9e1c7b6f76178572ab33118afea25"}, - {file = "orjson-3.10.10-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:aaf29ce0bb5d3320824ec3d1508652421000ba466abd63bdd52c64bcce9eb1fa"}, - {file = "orjson-3.10.10-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dddd5516bcc93e723d029c1633ae79c4417477b4f57dad9bfeeb6bc0315e654a"}, - {file = "orjson-3.10.10-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a12f2003695b10817f0fa8b8fca982ed7f5761dcb0d93cff4f2f9f6709903fd7"}, - {file = "orjson-3.10.10-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:672f9874a8a8fb9bb1b771331d31ba27f57702c8106cdbadad8bda5d10bc1019"}, - {file = "orjson-3.10.10-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:1dcbb0ca5fafb2b378b2c74419480ab2486326974826bbf6588f4dc62137570a"}, - {file = "orjson-3.10.10-cp39-none-win32.whl", hash = "sha256:d9bbd3a4b92256875cb058c3381b782649b9a3c68a4aa9a2fff020c2f9cfc1be"}, - {file = "orjson-3.10.10-cp39-none-win_amd64.whl", hash = "sha256:766f21487a53aee8524b97ca9582d5c6541b03ab6210fbaf10142ae2f3ced2aa"}, - {file = "orjson-3.10.10.tar.gz", hash = "sha256:37949383c4df7b4337ce82ee35b6d7471e55195efa7dcb45ab8226ceadb0fe3b"}, + {file = "orjson-3.10.12-cp310-cp310-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:ece01a7ec71d9940cc654c482907a6b65df27251255097629d0dea781f255c6d"}, + {file = "orjson-3.10.12-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c34ec9aebc04f11f4b978dd6caf697a2df2dd9b47d35aa4cc606cabcb9df69d7"}, + {file = "orjson-3.10.12-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fd6ec8658da3480939c79b9e9e27e0db31dffcd4ba69c334e98c9976ac29140e"}, + {file = "orjson-3.10.12-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f17e6baf4cf01534c9de8a16c0c611f3d94925d1701bf5f4aff17003677d8ced"}, + {file = "orjson-3.10.12-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6402ebb74a14ef96f94a868569f5dccf70d791de49feb73180eb3c6fda2ade56"}, + {file = "orjson-3.10.12-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0000758ae7c7853e0a4a6063f534c61656ebff644391e1f81698c1b2d2fc8cd2"}, + {file = "orjson-3.10.12-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:888442dcee99fd1e5bd37a4abb94930915ca6af4db50e23e746cdf4d1e63db13"}, + {file = "orjson-3.10.12-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:c1f7a3ce79246aa0e92f5458d86c54f257fb5dfdc14a192651ba7ec2c00f8a05"}, + {file = "orjson-3.10.12-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:802a3935f45605c66fb4a586488a38af63cb37aaad1c1d94c982c40dcc452e85"}, + {file = "orjson-3.10.12-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:1da1ef0113a2be19bb6c557fb0ec2d79c92ebd2fed4cfb1b26bab93f021fb885"}, + {file = "orjson-3.10.12-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:7a3273e99f367f137d5b3fecb5e9f45bcdbfac2a8b2f32fbc72129bbd48789c2"}, + {file = "orjson-3.10.12-cp310-none-win32.whl", hash = "sha256:475661bf249fd7907d9b0a2a2421b4e684355a77ceef85b8352439a9163418c3"}, + {file = "orjson-3.10.12-cp310-none-win_amd64.whl", hash = "sha256:87251dc1fb2b9e5ab91ce65d8f4caf21910d99ba8fb24b49fd0c118b2362d509"}, + {file = "orjson-3.10.12-cp311-cp311-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:a734c62efa42e7df94926d70fe7d37621c783dea9f707a98cdea796964d4cf74"}, + {file = "orjson-3.10.12-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:750f8b27259d3409eda8350c2919a58b0cfcd2054ddc1bd317a643afc646ef23"}, + {file = "orjson-3.10.12-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bb52c22bfffe2857e7aa13b4622afd0dd9d16ea7cc65fd2bf318d3223b1b6252"}, + {file = "orjson-3.10.12-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:440d9a337ac8c199ff8251e100c62e9488924c92852362cd27af0e67308c16ef"}, + {file = "orjson-3.10.12-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a9e15c06491c69997dfa067369baab3bf094ecb74be9912bdc4339972323f252"}, + {file = "orjson-3.10.12-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:362d204ad4b0b8724cf370d0cd917bb2dc913c394030da748a3bb632445ce7c4"}, + {file = "orjson-3.10.12-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2b57cbb4031153db37b41622eac67329c7810e5f480fda4cfd30542186f006ae"}, + {file = "orjson-3.10.12-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:165c89b53ef03ce0d7c59ca5c82fa65fe13ddf52eeb22e859e58c237d4e33b9b"}, + {file = "orjson-3.10.12-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:5dee91b8dfd54557c1a1596eb90bcd47dbcd26b0baaed919e6861f076583e9da"}, + {file = "orjson-3.10.12-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:77a4e1cfb72de6f905bdff061172adfb3caf7a4578ebf481d8f0530879476c07"}, + {file = "orjson-3.10.12-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:038d42c7bc0606443459b8fe2d1f121db474c49067d8d14c6a075bbea8bf14dd"}, + {file = "orjson-3.10.12-cp311-none-win32.whl", hash = "sha256:03b553c02ab39bed249bedd4abe37b2118324d1674e639b33fab3d1dafdf4d79"}, + {file = "orjson-3.10.12-cp311-none-win_amd64.whl", hash = "sha256:8b8713b9e46a45b2af6b96f559bfb13b1e02006f4242c156cbadef27800a55a8"}, + {file = "orjson-3.10.12-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:53206d72eb656ca5ac7d3a7141e83c5bbd3ac30d5eccfe019409177a57634b0d"}, + {file = "orjson-3.10.12-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ac8010afc2150d417ebda810e8df08dd3f544e0dd2acab5370cfa6bcc0662f8f"}, + {file = "orjson-3.10.12-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ed459b46012ae950dd2e17150e838ab08215421487371fa79d0eced8d1461d70"}, + {file = "orjson-3.10.12-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8dcb9673f108a93c1b52bfc51b0af422c2d08d4fc710ce9c839faad25020bb69"}, + {file = "orjson-3.10.12-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:22a51ae77680c5c4652ebc63a83d5255ac7d65582891d9424b566fb3b5375ee9"}, + {file = "orjson-3.10.12-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:910fdf2ac0637b9a77d1aad65f803bac414f0b06f720073438a7bd8906298192"}, + {file = "orjson-3.10.12-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:24ce85f7100160936bc2116c09d1a8492639418633119a2224114f67f63a4559"}, + {file = "orjson-3.10.12-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8a76ba5fc8dd9c913640292df27bff80a685bed3a3c990d59aa6ce24c352f8fc"}, + {file = "orjson-3.10.12-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:ff70ef093895fd53f4055ca75f93f047e088d1430888ca1229393a7c0521100f"}, + {file = "orjson-3.10.12-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:f4244b7018b5753ecd10a6d324ec1f347da130c953a9c88432c7fbc8875d13be"}, + {file = "orjson-3.10.12-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:16135ccca03445f37921fa4b585cff9a58aa8d81ebcb27622e69bfadd220b32c"}, + {file = "orjson-3.10.12-cp312-none-win32.whl", hash = "sha256:2d879c81172d583e34153d524fcba5d4adafbab8349a7b9f16ae511c2cee8708"}, + {file = "orjson-3.10.12-cp312-none-win_amd64.whl", hash = "sha256:fc23f691fa0f5c140576b8c365bc942d577d861a9ee1142e4db468e4e17094fb"}, + {file = "orjson-3.10.12-cp313-cp313-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:47962841b2a8aa9a258b377f5188db31ba49af47d4003a32f55d6f8b19006543"}, + {file = "orjson-3.10.12-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6334730e2532e77b6054e87ca84f3072bee308a45a452ea0bffbbbc40a67e296"}, + {file = "orjson-3.10.12-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:accfe93f42713c899fdac2747e8d0d5c659592df2792888c6c5f829472e4f85e"}, + {file = "orjson-3.10.12-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a7974c490c014c48810d1dede6c754c3cc46598da758c25ca3b4001ac45b703f"}, + {file = "orjson-3.10.12-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:3f250ce7727b0b2682f834a3facff88e310f52f07a5dcfd852d99637d386e79e"}, + {file = "orjson-3.10.12-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:f31422ff9486ae484f10ffc51b5ab2a60359e92d0716fcce1b3593d7bb8a9af6"}, + {file = "orjson-3.10.12-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:5f29c5d282bb2d577c2a6bbde88d8fdcc4919c593f806aac50133f01b733846e"}, + {file = "orjson-3.10.12-cp313-none-win32.whl", hash = "sha256:f45653775f38f63dc0e6cd4f14323984c3149c05d6007b58cb154dd080ddc0dc"}, + {file = "orjson-3.10.12-cp313-none-win_amd64.whl", hash = "sha256:229994d0c376d5bdc91d92b3c9e6be2f1fbabd4cc1b59daae1443a46ee5e9825"}, + {file = "orjson-3.10.12-cp38-cp38-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:7d69af5b54617a5fac5c8e5ed0859eb798e2ce8913262eb522590239db6c6763"}, + {file = "orjson-3.10.12-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7ed119ea7d2953365724a7059231a44830eb6bbb0cfead33fcbc562f5fd8f935"}, + {file = "orjson-3.10.12-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9c5fc1238ef197e7cad5c91415f524aaa51e004be5a9b35a1b8a84ade196f73f"}, + {file = "orjson-3.10.12-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:43509843990439b05f848539d6f6198d4ac86ff01dd024b2f9a795c0daeeab60"}, + {file = "orjson-3.10.12-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f72e27a62041cfb37a3de512247ece9f240a561e6c8662276beaf4d53d406db4"}, + {file = "orjson-3.10.12-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9a904f9572092bb6742ab7c16c623f0cdccbad9eeb2d14d4aa06284867bddd31"}, + {file = "orjson-3.10.12-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:855c0833999ed5dc62f64552db26f9be767434917d8348d77bacaab84f787d7b"}, + {file = "orjson-3.10.12-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:897830244e2320f6184699f598df7fb9db9f5087d6f3f03666ae89d607e4f8ed"}, + {file = "orjson-3.10.12-cp38-cp38-musllinux_1_2_armv7l.whl", hash = "sha256:0b32652eaa4a7539f6f04abc6243619c56f8530c53bf9b023e1269df5f7816dd"}, + {file = "orjson-3.10.12-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:36b4aa31e0f6a1aeeb6f8377769ca5d125db000f05c20e54163aef1d3fe8e833"}, + {file = "orjson-3.10.12-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:5535163054d6cbf2796f93e4f0dbc800f61914c0e3c4ed8499cf6ece22b4a3da"}, + {file = "orjson-3.10.12-cp38-none-win32.whl", hash = "sha256:90a5551f6f5a5fa07010bf3d0b4ca2de21adafbbc0af6cb700b63cd767266cb9"}, + {file = "orjson-3.10.12-cp38-none-win_amd64.whl", hash = "sha256:703a2fb35a06cdd45adf5d733cf613cbc0cb3ae57643472b16bc22d325b5fb6c"}, + {file = "orjson-3.10.12-cp39-cp39-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:f29de3ef71a42a5822765def1febfb36e0859d33abf5c2ad240acad5c6a1b78d"}, + {file = "orjson-3.10.12-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:de365a42acc65d74953f05e4772c974dad6c51cfc13c3240899f534d611be967"}, + {file = "orjson-3.10.12-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:91a5a0158648a67ff0004cb0df5df7dcc55bfc9ca154d9c01597a23ad54c8d0c"}, + {file = "orjson-3.10.12-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c47ce6b8d90fe9646a25b6fb52284a14ff215c9595914af63a5933a49972ce36"}, + {file = "orjson-3.10.12-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0eee4c2c5bfb5c1b47a5db80d2ac7aaa7e938956ae88089f098aff2c0f35d5d8"}, + {file = "orjson-3.10.12-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:35d3081bbe8b86587eb5c98a73b97f13d8f9fea685cf91a579beddacc0d10566"}, + {file = "orjson-3.10.12-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:73c23a6e90383884068bc2dba83d5222c9fcc3b99a0ed2411d38150734236755"}, + {file = "orjson-3.10.12-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:5472be7dc3269b4b52acba1433dac239215366f89dc1d8d0e64029abac4e714e"}, + {file = "orjson-3.10.12-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:7319cda750fca96ae5973efb31b17d97a5c5225ae0bc79bf5bf84df9e1ec2ab6"}, + {file = "orjson-3.10.12-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:74d5ca5a255bf20b8def6a2b96b1e18ad37b4a122d59b154c458ee9494377f80"}, + {file = "orjson-3.10.12-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:ff31d22ecc5fb85ef62c7d4afe8301d10c558d00dd24274d4bbe464380d3cd69"}, + {file = "orjson-3.10.12-cp39-none-win32.whl", hash = "sha256:c22c3ea6fba91d84fcb4cda30e64aff548fcf0c44c876e681f47d61d24b12e6b"}, + {file = "orjson-3.10.12-cp39-none-win_amd64.whl", hash = "sha256:be604f60d45ace6b0b33dd990a66b4526f1a7a186ac411c942674625456ca548"}, + {file = "orjson-3.10.12.tar.gz", hash = "sha256:0a78bbda3aea0f9f079057ee1ee8a1ecf790d4f1af88dd67493c6b8ee52506ff"}, ] [[package]] @@ -2462,22 +2492,19 @@ files = [ [[package]] name = "pydantic" -version = "2.9.2" +version = "2.10.4" description = "Data validation using Python type hints" optional = false python-versions = ">=3.8" files = [ - {file = "pydantic-2.9.2-py3-none-any.whl", hash = "sha256:f048cec7b26778210e28a0459867920654d48e5e62db0958433636cde4254f12"}, - {file = "pydantic-2.9.2.tar.gz", hash = "sha256:d155cef71265d1e9807ed1c32b4c8deec042a44a50a4188b25ac67ecd81a9c0f"}, + {file = "pydantic-2.10.4-py3-none-any.whl", hash = "sha256:597e135ea68be3a37552fb524bc7d0d66dcf93d395acd93a00682f1efcb8ee3d"}, + {file = "pydantic-2.10.4.tar.gz", hash = "sha256:82f12e9723da6de4fe2ba888b5971157b3be7ad914267dea8f05f82b28254f06"}, ] [package.dependencies] annotated-types = ">=0.6.0" -pydantic-core = "2.23.4" -typing-extensions = [ - {version = ">=4.6.1", markers = "python_version < \"3.13\""}, - {version = ">=4.12.2", markers = "python_version >= \"3.13\""}, -] +pydantic-core = "2.27.2" +typing-extensions = ">=4.12.2" [package.extras] email = ["email-validator (>=2.0.0)"] @@ -2485,100 +2512,111 @@ timezone = ["tzdata"] [[package]] name = "pydantic-core" -version = "2.23.4" +version = "2.27.2" description = "Core functionality for Pydantic validation and serialization" optional = false python-versions = ">=3.8" files = [ - {file = "pydantic_core-2.23.4-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:b10bd51f823d891193d4717448fab065733958bdb6a6b351967bd349d48d5c9b"}, - {file = "pydantic_core-2.23.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:4fc714bdbfb534f94034efaa6eadd74e5b93c8fa6315565a222f7b6f42ca1166"}, - {file = "pydantic_core-2.23.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:63e46b3169866bd62849936de036f901a9356e36376079b05efa83caeaa02ceb"}, - {file = "pydantic_core-2.23.4-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ed1a53de42fbe34853ba90513cea21673481cd81ed1be739f7f2efb931b24916"}, - {file = "pydantic_core-2.23.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cfdd16ab5e59fc31b5e906d1a3f666571abc367598e3e02c83403acabc092e07"}, - {file = "pydantic_core-2.23.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:255a8ef062cbf6674450e668482456abac99a5583bbafb73f9ad469540a3a232"}, - {file = "pydantic_core-2.23.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4a7cd62e831afe623fbb7aabbb4fe583212115b3ef38a9f6b71869ba644624a2"}, - {file = "pydantic_core-2.23.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f09e2ff1f17c2b51f2bc76d1cc33da96298f0a036a137f5440ab3ec5360b624f"}, - {file = "pydantic_core-2.23.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:e38e63e6f3d1cec5a27e0afe90a085af8b6806ee208b33030e65b6516353f1a3"}, - {file = "pydantic_core-2.23.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:0dbd8dbed2085ed23b5c04afa29d8fd2771674223135dc9bc937f3c09284d071"}, - {file = "pydantic_core-2.23.4-cp310-none-win32.whl", hash = "sha256:6531b7ca5f951d663c339002e91aaebda765ec7d61b7d1e3991051906ddde119"}, - {file = "pydantic_core-2.23.4-cp310-none-win_amd64.whl", hash = "sha256:7c9129eb40958b3d4500fa2467e6a83356b3b61bfff1b414c7361d9220f9ae8f"}, - {file = "pydantic_core-2.23.4-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:77733e3892bb0a7fa797826361ce8a9184d25c8dffaec60b7ffe928153680ba8"}, - {file = "pydantic_core-2.23.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1b84d168f6c48fabd1f2027a3d1bdfe62f92cade1fb273a5d68e621da0e44e6d"}, - {file = "pydantic_core-2.23.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:df49e7a0861a8c36d089c1ed57d308623d60416dab2647a4a17fe050ba85de0e"}, - {file = "pydantic_core-2.23.4-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ff02b6d461a6de369f07ec15e465a88895f3223eb75073ffea56b84d9331f607"}, - {file = "pydantic_core-2.23.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:996a38a83508c54c78a5f41456b0103c30508fed9abcad0a59b876d7398f25fd"}, - {file = "pydantic_core-2.23.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d97683ddee4723ae8c95d1eddac7c192e8c552da0c73a925a89fa8649bf13eea"}, - {file = "pydantic_core-2.23.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:216f9b2d7713eb98cb83c80b9c794de1f6b7e3145eef40400c62e86cee5f4e1e"}, - {file = "pydantic_core-2.23.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6f783e0ec4803c787bcea93e13e9932edab72068f68ecffdf86a99fd5918878b"}, - {file = "pydantic_core-2.23.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:d0776dea117cf5272382634bd2a5c1b6eb16767c223c6a5317cd3e2a757c61a0"}, - {file = "pydantic_core-2.23.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d5f7a395a8cf1621939692dba2a6b6a830efa6b3cee787d82c7de1ad2930de64"}, - {file = "pydantic_core-2.23.4-cp311-none-win32.whl", hash = "sha256:74b9127ffea03643e998e0c5ad9bd3811d3dac8c676e47db17b0ee7c3c3bf35f"}, - {file = "pydantic_core-2.23.4-cp311-none-win_amd64.whl", hash = "sha256:98d134c954828488b153d88ba1f34e14259284f256180ce659e8d83e9c05eaa3"}, - {file = "pydantic_core-2.23.4-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:f3e0da4ebaef65158d4dfd7d3678aad692f7666877df0002b8a522cdf088f231"}, - {file = "pydantic_core-2.23.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f69a8e0b033b747bb3e36a44e7732f0c99f7edd5cea723d45bc0d6e95377ffee"}, - {file = "pydantic_core-2.23.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:723314c1d51722ab28bfcd5240d858512ffd3116449c557a1336cbe3919beb87"}, - {file = "pydantic_core-2.23.4-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bb2802e667b7051a1bebbfe93684841cc9351004e2badbd6411bf357ab8d5ac8"}, - {file = "pydantic_core-2.23.4-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d18ca8148bebe1b0a382a27a8ee60350091a6ddaf475fa05ef50dc35b5df6327"}, - {file = "pydantic_core-2.23.4-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:33e3d65a85a2a4a0dc3b092b938a4062b1a05f3a9abde65ea93b233bca0e03f2"}, - {file = "pydantic_core-2.23.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:128585782e5bfa515c590ccee4b727fb76925dd04a98864182b22e89a4e6ed36"}, - {file = "pydantic_core-2.23.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:68665f4c17edcceecc112dfed5dbe6f92261fb9d6054b47d01bf6371a6196126"}, - {file = "pydantic_core-2.23.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:20152074317d9bed6b7a95ade3b7d6054845d70584216160860425f4fbd5ee9e"}, - {file = "pydantic_core-2.23.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:9261d3ce84fa1d38ed649c3638feefeae23d32ba9182963e465d58d62203bd24"}, - {file = "pydantic_core-2.23.4-cp312-none-win32.whl", hash = "sha256:4ba762ed58e8d68657fc1281e9bb72e1c3e79cc5d464be146e260c541ec12d84"}, - {file = "pydantic_core-2.23.4-cp312-none-win_amd64.whl", hash = "sha256:97df63000f4fea395b2824da80e169731088656d1818a11b95f3b173747b6cd9"}, - {file = "pydantic_core-2.23.4-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:7530e201d10d7d14abce4fb54cfe5b94a0aefc87da539d0346a484ead376c3cc"}, - {file = "pydantic_core-2.23.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:df933278128ea1cd77772673c73954e53a1c95a4fdf41eef97c2b779271bd0bd"}, - {file = "pydantic_core-2.23.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0cb3da3fd1b6a5d0279a01877713dbda118a2a4fc6f0d821a57da2e464793f05"}, - {file = "pydantic_core-2.23.4-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:42c6dcb030aefb668a2b7009c85b27f90e51e6a3b4d5c9bc4c57631292015b0d"}, - {file = "pydantic_core-2.23.4-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:696dd8d674d6ce621ab9d45b205df149399e4bb9aa34102c970b721554828510"}, - {file = "pydantic_core-2.23.4-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2971bb5ffe72cc0f555c13e19b23c85b654dd2a8f7ab493c262071377bfce9f6"}, - {file = "pydantic_core-2.23.4-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8394d940e5d400d04cad4f75c0598665cbb81aecefaca82ca85bd28264af7f9b"}, - {file = "pydantic_core-2.23.4-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0dff76e0602ca7d4cdaacc1ac4c005e0ce0dcfe095d5b5259163a80d3a10d327"}, - {file = "pydantic_core-2.23.4-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:7d32706badfe136888bdea71c0def994644e09fff0bfe47441deaed8e96fdbc6"}, - {file = "pydantic_core-2.23.4-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:ed541d70698978a20eb63d8c5d72f2cc6d7079d9d90f6b50bad07826f1320f5f"}, - {file = "pydantic_core-2.23.4-cp313-none-win32.whl", hash = "sha256:3d5639516376dce1940ea36edf408c554475369f5da2abd45d44621cb616f769"}, - {file = "pydantic_core-2.23.4-cp313-none-win_amd64.whl", hash = "sha256:5a1504ad17ba4210df3a045132a7baeeba5a200e930f57512ee02909fc5c4cb5"}, - {file = "pydantic_core-2.23.4-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:d4488a93b071c04dc20f5cecc3631fc78b9789dd72483ba15d423b5b3689b555"}, - {file = "pydantic_core-2.23.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:81965a16b675b35e1d09dd14df53f190f9129c0202356ed44ab2728b1c905658"}, - {file = "pydantic_core-2.23.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4ffa2ebd4c8530079140dd2d7f794a9d9a73cbb8e9d59ffe24c63436efa8f271"}, - {file = "pydantic_core-2.23.4-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:61817945f2fe7d166e75fbfb28004034b48e44878177fc54d81688e7b85a3665"}, - {file = "pydantic_core-2.23.4-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:29d2c342c4bc01b88402d60189f3df065fb0dda3654744d5a165a5288a657368"}, - {file = "pydantic_core-2.23.4-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5e11661ce0fd30a6790e8bcdf263b9ec5988e95e63cf901972107efc49218b13"}, - {file = "pydantic_core-2.23.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9d18368b137c6295db49ce7218b1a9ba15c5bc254c96d7c9f9e924a9bc7825ad"}, - {file = "pydantic_core-2.23.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ec4e55f79b1c4ffb2eecd8a0cfba9955a2588497d96851f4c8f99aa4a1d39b12"}, - {file = "pydantic_core-2.23.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:374a5e5049eda9e0a44c696c7ade3ff355f06b1fe0bb945ea3cac2bc336478a2"}, - {file = "pydantic_core-2.23.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:5c364564d17da23db1106787675fc7af45f2f7b58b4173bfdd105564e132e6fb"}, - {file = "pydantic_core-2.23.4-cp38-none-win32.whl", hash = "sha256:d7a80d21d613eec45e3d41eb22f8f94ddc758a6c4720842dc74c0581f54993d6"}, - {file = "pydantic_core-2.23.4-cp38-none-win_amd64.whl", hash = "sha256:5f5ff8d839f4566a474a969508fe1c5e59c31c80d9e140566f9a37bba7b8d556"}, - {file = "pydantic_core-2.23.4-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:a4fa4fc04dff799089689f4fd502ce7d59de529fc2f40a2c8836886c03e0175a"}, - {file = "pydantic_core-2.23.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0a7df63886be5e270da67e0966cf4afbae86069501d35c8c1b3b6c168f42cb36"}, - {file = "pydantic_core-2.23.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dcedcd19a557e182628afa1d553c3895a9f825b936415d0dbd3cd0bbcfd29b4b"}, - {file = "pydantic_core-2.23.4-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5f54b118ce5de9ac21c363d9b3caa6c800341e8c47a508787e5868c6b79c9323"}, - {file = "pydantic_core-2.23.4-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:86d2f57d3e1379a9525c5ab067b27dbb8a0642fb5d454e17a9ac434f9ce523e3"}, - {file = "pydantic_core-2.23.4-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:de6d1d1b9e5101508cb37ab0d972357cac5235f5c6533d1071964c47139257df"}, - {file = "pydantic_core-2.23.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1278e0d324f6908e872730c9102b0112477a7f7cf88b308e4fc36ce1bdb6d58c"}, - {file = "pydantic_core-2.23.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9a6b5099eeec78827553827f4c6b8615978bb4b6a88e5d9b93eddf8bb6790f55"}, - {file = "pydantic_core-2.23.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:e55541f756f9b3ee346b840103f32779c695a19826a4c442b7954550a0972040"}, - {file = "pydantic_core-2.23.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a5c7ba8ffb6d6f8f2ab08743be203654bb1aaa8c9dcb09f82ddd34eadb695605"}, - {file = "pydantic_core-2.23.4-cp39-none-win32.whl", hash = "sha256:37b0fe330e4a58d3c58b24d91d1eb102aeec675a3db4c292ec3928ecd892a9a6"}, - {file = "pydantic_core-2.23.4-cp39-none-win_amd64.whl", hash = "sha256:1498bec4c05c9c787bde9125cfdcc63a41004ff167f495063191b863399b1a29"}, - {file = "pydantic_core-2.23.4-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:f455ee30a9d61d3e1a15abd5068827773d6e4dc513e795f380cdd59932c782d5"}, - {file = "pydantic_core-2.23.4-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:1e90d2e3bd2c3863d48525d297cd143fe541be8bbf6f579504b9712cb6b643ec"}, - {file = "pydantic_core-2.23.4-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2e203fdf807ac7e12ab59ca2bfcabb38c7cf0b33c41efeb00f8e5da1d86af480"}, - {file = "pydantic_core-2.23.4-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e08277a400de01bc72436a0ccd02bdf596631411f592ad985dcee21445bd0068"}, - {file = "pydantic_core-2.23.4-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f220b0eea5965dec25480b6333c788fb72ce5f9129e8759ef876a1d805d00801"}, - {file = "pydantic_core-2.23.4-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:d06b0c8da4f16d1d1e352134427cb194a0a6e19ad5db9161bf32b2113409e728"}, - {file = "pydantic_core-2.23.4-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:ba1a0996f6c2773bd83e63f18914c1de3c9dd26d55f4ac302a7efe93fb8e7433"}, - {file = "pydantic_core-2.23.4-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:9a5bce9d23aac8f0cf0836ecfc033896aa8443b501c58d0602dbfd5bd5b37753"}, - {file = "pydantic_core-2.23.4-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:78ddaaa81421a29574a682b3179d4cf9e6d405a09b99d93ddcf7e5239c742e21"}, - {file = "pydantic_core-2.23.4-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:883a91b5dd7d26492ff2f04f40fbb652de40fcc0afe07e8129e8ae779c2110eb"}, - {file = "pydantic_core-2.23.4-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:88ad334a15b32a791ea935af224b9de1bf99bcd62fabf745d5f3442199d86d59"}, - {file = "pydantic_core-2.23.4-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:233710f069d251feb12a56da21e14cca67994eab08362207785cf8c598e74577"}, - {file = "pydantic_core-2.23.4-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:19442362866a753485ba5e4be408964644dd6a09123d9416c54cd49171f50744"}, - {file = "pydantic_core-2.23.4-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:624e278a7d29b6445e4e813af92af37820fafb6dcc55c012c834f9e26f9aaaef"}, - {file = "pydantic_core-2.23.4-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:f5ef8f42bec47f21d07668a043f077d507e5bf4e668d5c6dfe6aaba89de1a5b8"}, - {file = "pydantic_core-2.23.4-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:aea443fffa9fbe3af1a9ba721a87f926fe548d32cab71d188a6ede77d0ff244e"}, - {file = "pydantic_core-2.23.4.tar.gz", hash = "sha256:2584f7cf844ac4d970fba483a717dbe10c1c1c96a969bf65d61ffe94df1b2863"}, + {file = "pydantic_core-2.27.2-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:2d367ca20b2f14095a8f4fa1210f5a7b78b8a20009ecced6b12818f455b1e9fa"}, + {file = "pydantic_core-2.27.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:491a2b73db93fab69731eaee494f320faa4e093dbed776be1a829c2eb222c34c"}, + {file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7969e133a6f183be60e9f6f56bfae753585680f3b7307a8e555a948d443cc05a"}, + {file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3de9961f2a346257caf0aa508a4da705467f53778e9ef6fe744c038119737ef5"}, + {file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e2bb4d3e5873c37bb3dd58714d4cd0b0e6238cebc4177ac8fe878f8b3aa8e74c"}, + {file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:280d219beebb0752699480fe8f1dc61ab6615c2046d76b7ab7ee38858de0a4e7"}, + {file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47956ae78b6422cbd46f772f1746799cbb862de838fd8d1fbd34a82e05b0983a"}, + {file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:14d4a5c49d2f009d62a2a7140d3064f686d17a5d1a268bc641954ba181880236"}, + {file = "pydantic_core-2.27.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:337b443af21d488716f8d0b6164de833e788aa6bd7e3a39c005febc1284f4962"}, + {file = "pydantic_core-2.27.2-cp310-cp310-musllinux_1_1_armv7l.whl", hash = "sha256:03d0f86ea3184a12f41a2d23f7ccb79cdb5a18e06993f8a45baa8dfec746f0e9"}, + {file = "pydantic_core-2.27.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:7041c36f5680c6e0f08d922aed302e98b3745d97fe1589db0a3eebf6624523af"}, + {file = "pydantic_core-2.27.2-cp310-cp310-win32.whl", hash = "sha256:50a68f3e3819077be2c98110c1f9dcb3817e93f267ba80a2c05bb4f8799e2ff4"}, + {file = "pydantic_core-2.27.2-cp310-cp310-win_amd64.whl", hash = "sha256:e0fd26b16394ead34a424eecf8a31a1f5137094cabe84a1bcb10fa6ba39d3d31"}, + {file = "pydantic_core-2.27.2-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:8e10c99ef58cfdf2a66fc15d66b16c4a04f62bca39db589ae8cba08bc55331bc"}, + {file = "pydantic_core-2.27.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:26f32e0adf166a84d0cb63be85c562ca8a6fa8de28e5f0d92250c6b7e9e2aff7"}, + {file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c19d1ea0673cd13cc2f872f6c9ab42acc4e4f492a7ca9d3795ce2b112dd7e15"}, + {file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5e68c4446fe0810e959cdff46ab0a41ce2f2c86d227d96dc3847af0ba7def306"}, + {file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d9640b0059ff4f14d1f37321b94061c6db164fbe49b334b31643e0528d100d99"}, + {file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:40d02e7d45c9f8af700f3452f329ead92da4c5f4317ca9b896de7ce7199ea459"}, + {file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1c1fd185014191700554795c99b347d64f2bb637966c4cfc16998a0ca700d048"}, + {file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d81d2068e1c1228a565af076598f9e7451712700b673de8f502f0334f281387d"}, + {file = "pydantic_core-2.27.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:1a4207639fb02ec2dbb76227d7c751a20b1a6b4bc52850568e52260cae64ca3b"}, + {file = "pydantic_core-2.27.2-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:3de3ce3c9ddc8bbd88f6e0e304dea0e66d843ec9de1b0042b0911c1663ffd474"}, + {file = "pydantic_core-2.27.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:30c5f68ded0c36466acede341551106821043e9afaad516adfb6e8fa80a4e6a6"}, + {file = "pydantic_core-2.27.2-cp311-cp311-win32.whl", hash = "sha256:c70c26d2c99f78b125a3459f8afe1aed4d9687c24fd677c6a4436bc042e50d6c"}, + {file = "pydantic_core-2.27.2-cp311-cp311-win_amd64.whl", hash = "sha256:08e125dbdc505fa69ca7d9c499639ab6407cfa909214d500897d02afb816e7cc"}, + {file = "pydantic_core-2.27.2-cp311-cp311-win_arm64.whl", hash = "sha256:26f0d68d4b235a2bae0c3fc585c585b4ecc51382db0e3ba402a22cbc440915e4"}, + {file = "pydantic_core-2.27.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:9e0c8cfefa0ef83b4da9588448b6d8d2a2bf1a53c3f1ae5fca39eb3061e2f0b0"}, + {file = "pydantic_core-2.27.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:83097677b8e3bd7eaa6775720ec8e0405f1575015a463285a92bfdfe254529ef"}, + {file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:172fce187655fece0c90d90a678424b013f8fbb0ca8b036ac266749c09438cb7"}, + {file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:519f29f5213271eeeeb3093f662ba2fd512b91c5f188f3bb7b27bc5973816934"}, + {file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:05e3a55d124407fffba0dd6b0c0cd056d10e983ceb4e5dbd10dda135c31071d6"}, + {file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9c3ed807c7b91de05e63930188f19e921d1fe90de6b4f5cd43ee7fcc3525cb8c"}, + {file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6fb4aadc0b9a0c063206846d603b92030eb6f03069151a625667f982887153e2"}, + {file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:28ccb213807e037460326424ceb8b5245acb88f32f3d2777427476e1b32c48c4"}, + {file = "pydantic_core-2.27.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:de3cd1899e2c279b140adde9357c4495ed9d47131b4a4eaff9052f23398076b3"}, + {file = "pydantic_core-2.27.2-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:220f892729375e2d736b97d0e51466252ad84c51857d4d15f5e9692f9ef12be4"}, + {file = "pydantic_core-2.27.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:a0fcd29cd6b4e74fe8ddd2c90330fd8edf2e30cb52acda47f06dd615ae72da57"}, + {file = "pydantic_core-2.27.2-cp312-cp312-win32.whl", hash = "sha256:1e2cb691ed9834cd6a8be61228471d0a503731abfb42f82458ff27be7b2186fc"}, + {file = "pydantic_core-2.27.2-cp312-cp312-win_amd64.whl", hash = "sha256:cc3f1a99a4f4f9dd1de4fe0312c114e740b5ddead65bb4102884b384c15d8bc9"}, + {file = "pydantic_core-2.27.2-cp312-cp312-win_arm64.whl", hash = "sha256:3911ac9284cd8a1792d3cb26a2da18f3ca26c6908cc434a18f730dc0db7bfa3b"}, + {file = "pydantic_core-2.27.2-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:7d14bd329640e63852364c306f4d23eb744e0f8193148d4044dd3dacdaacbd8b"}, + {file = "pydantic_core-2.27.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:82f91663004eb8ed30ff478d77c4d1179b3563df6cdb15c0817cd1cdaf34d154"}, + {file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:71b24c7d61131bb83df10cc7e687433609963a944ccf45190cfc21e0887b08c9"}, + {file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fa8e459d4954f608fa26116118bb67f56b93b209c39b008277ace29937453dc9"}, + {file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ce8918cbebc8da707ba805b7fd0b382816858728ae7fe19a942080c24e5b7cd1"}, + {file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:eda3f5c2a021bbc5d976107bb302e0131351c2ba54343f8a496dc8783d3d3a6a"}, + {file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bd8086fa684c4775c27f03f062cbb9eaa6e17f064307e86b21b9e0abc9c0f02e"}, + {file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8d9b3388db186ba0c099a6d20f0604a44eabdeef1777ddd94786cdae158729e4"}, + {file = "pydantic_core-2.27.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:7a66efda2387de898c8f38c0cf7f14fca0b51a8ef0b24bfea5849f1b3c95af27"}, + {file = "pydantic_core-2.27.2-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:18a101c168e4e092ab40dbc2503bdc0f62010e95d292b27827871dc85450d7ee"}, + {file = "pydantic_core-2.27.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:ba5dd002f88b78a4215ed2f8ddbdf85e8513382820ba15ad5ad8955ce0ca19a1"}, + {file = "pydantic_core-2.27.2-cp313-cp313-win32.whl", hash = "sha256:1ebaf1d0481914d004a573394f4be3a7616334be70261007e47c2a6fe7e50130"}, + {file = "pydantic_core-2.27.2-cp313-cp313-win_amd64.whl", hash = "sha256:953101387ecf2f5652883208769a79e48db18c6df442568a0b5ccd8c2723abee"}, + {file = "pydantic_core-2.27.2-cp313-cp313-win_arm64.whl", hash = "sha256:ac4dbfd1691affb8f48c2c13241a2e3b60ff23247cbcf981759c768b6633cf8b"}, + {file = "pydantic_core-2.27.2-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:d3e8d504bdd3f10835468f29008d72fc8359d95c9c415ce6e767203db6127506"}, + {file = "pydantic_core-2.27.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:521eb9b7f036c9b6187f0b47318ab0d7ca14bd87f776240b90b21c1f4f149320"}, + {file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:85210c4d99a0114f5a9481b44560d7d1e35e32cc5634c656bc48e590b669b145"}, + {file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d716e2e30c6f140d7560ef1538953a5cd1a87264c737643d481f2779fc247fe1"}, + {file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f66d89ba397d92f840f8654756196d93804278457b5fbede59598a1f9f90b228"}, + {file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:669e193c1c576a58f132e3158f9dfa9662969edb1a250c54d8fa52590045f046"}, + {file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9fdbe7629b996647b99c01b37f11170a57ae675375b14b8c13b8518b8320ced5"}, + {file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d262606bf386a5ba0b0af3b97f37c83d7011439e3dc1a9298f21efb292e42f1a"}, + {file = "pydantic_core-2.27.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:cabb9bcb7e0d97f74df8646f34fc76fbf793b7f6dc2438517d7a9e50eee4f14d"}, + {file = "pydantic_core-2.27.2-cp38-cp38-musllinux_1_1_armv7l.whl", hash = "sha256:d2d63f1215638d28221f664596b1ccb3944f6e25dd18cd3b86b0a4c408d5ebb9"}, + {file = "pydantic_core-2.27.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:bca101c00bff0adb45a833f8451b9105d9df18accb8743b08107d7ada14bd7da"}, + {file = "pydantic_core-2.27.2-cp38-cp38-win32.whl", hash = "sha256:f6f8e111843bbb0dee4cb6594cdc73e79b3329b526037ec242a3e49012495b3b"}, + {file = "pydantic_core-2.27.2-cp38-cp38-win_amd64.whl", hash = "sha256:fd1aea04935a508f62e0d0ef1f5ae968774a32afc306fb8545e06f5ff5cdf3ad"}, + {file = "pydantic_core-2.27.2-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:c10eb4f1659290b523af58fa7cffb452a61ad6ae5613404519aee4bfbf1df993"}, + {file = "pydantic_core-2.27.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ef592d4bad47296fb11f96cd7dc898b92e795032b4894dfb4076cfccd43a9308"}, + {file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c61709a844acc6bf0b7dce7daae75195a10aac96a596ea1b776996414791ede4"}, + {file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:42c5f762659e47fdb7b16956c71598292f60a03aa92f8b6351504359dbdba6cf"}, + {file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4c9775e339e42e79ec99c441d9730fccf07414af63eac2f0e48e08fd38a64d76"}, + {file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:57762139821c31847cfb2df63c12f725788bd9f04bc2fb392790959b8f70f118"}, + {file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0d1e85068e818c73e048fe28cfc769040bb1f475524f4745a5dc621f75ac7630"}, + {file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:097830ed52fd9e427942ff3b9bc17fab52913b2f50f2880dc4a5611446606a54"}, + {file = "pydantic_core-2.27.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:044a50963a614ecfae59bb1eaf7ea7efc4bc62f49ed594e18fa1e5d953c40e9f"}, + {file = "pydantic_core-2.27.2-cp39-cp39-musllinux_1_1_armv7l.whl", hash = "sha256:4e0b4220ba5b40d727c7f879eac379b822eee5d8fff418e9d3381ee45b3b0362"}, + {file = "pydantic_core-2.27.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5e4f4bb20d75e9325cc9696c6802657b58bc1dbbe3022f32cc2b2b632c3fbb96"}, + {file = "pydantic_core-2.27.2-cp39-cp39-win32.whl", hash = "sha256:cca63613e90d001b9f2f9a9ceb276c308bfa2a43fafb75c8031c4f66039e8c6e"}, + {file = "pydantic_core-2.27.2-cp39-cp39-win_amd64.whl", hash = "sha256:77d1bca19b0f7021b3a982e6f903dcd5b2b06076def36a652e3907f596e29f67"}, + {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:2bf14caea37e91198329b828eae1618c068dfb8ef17bb33287a7ad4b61ac314e"}, + {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:b0cb791f5b45307caae8810c2023a184c74605ec3bcbb67d13846c28ff731ff8"}, + {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:688d3fd9fcb71f41c4c015c023d12a79d1c4c0732ec9eb35d96e3388a120dcf3"}, + {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3d591580c34f4d731592f0e9fe40f9cc1b430d297eecc70b962e93c5c668f15f"}, + {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:82f986faf4e644ffc189a7f1aafc86e46ef70372bb153e7001e8afccc6e54133"}, + {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:bec317a27290e2537f922639cafd54990551725fc844249e64c523301d0822fc"}, + {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:0296abcb83a797db256b773f45773da397da75a08f5fcaef41f2044adec05f50"}, + {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:0d75070718e369e452075a6017fbf187f788e17ed67a3abd47fa934d001863d9"}, + {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:7e17b560be3c98a8e3aa66ce828bdebb9e9ac6ad5466fba92eb74c4c95cb1151"}, + {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:c33939a82924da9ed65dab5a65d427205a73181d8098e79b6b426bdf8ad4e656"}, + {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:00bad2484fa6bda1e216e7345a798bd37c68fb2d97558edd584942aa41b7d278"}, + {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c817e2b40aba42bac6f457498dacabc568c3b7a986fc9ba7c8d9d260b71485fb"}, + {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:251136cdad0cb722e93732cb45ca5299fb56e1344a833640bf93b2803f8d1bfd"}, + {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d2088237af596f0a524d3afc39ab3b036e8adb054ee57cbb1dcf8e09da5b29cc"}, + {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:d4041c0b966a84b4ae7a09832eb691a35aec90910cd2dbe7a208de59be77965b"}, + {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:8083d4e875ebe0b864ffef72a4304827015cff328a1be6e22cc850753bfb122b"}, + {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:f141ee28a0ad2123b6611b6ceff018039df17f32ada8b534e6aa039545a3efb2"}, + {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:7d0c8399fcc1848491f00e0314bd59fb34a9c008761bcb422a057670c3f65e35"}, + {file = "pydantic_core-2.27.2.tar.gz", hash = "sha256:eb026e5a4c1fee05726072337ff51d1efb6f59090b7da90d30ea58625b1ffb39"}, ] [package.dependencies] @@ -2586,13 +2624,13 @@ typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0" [[package]] name = "pydantic-settings" -version = "2.6.0" +version = "2.7.0" description = "Settings management using Pydantic" optional = false python-versions = ">=3.8" files = [ - {file = "pydantic_settings-2.6.0-py3-none-any.whl", hash = "sha256:4a819166f119b74d7f8c765196b165f95cc7487ce58ea27dec8a5a26be0970e0"}, - {file = "pydantic_settings-2.6.0.tar.gz", hash = "sha256:44a1804abffac9e6a30372bb45f6cafab945ef5af25e66b1c634c01dd39e0188"}, + {file = "pydantic_settings-2.7.0-py3-none-any.whl", hash = "sha256:e00c05d5fa6cbbb227c84bd7487c5c1065084119b750df7c8c1a554aed236eb5"}, + {file = "pydantic_settings-2.7.0.tar.gz", hash = "sha256:ac4bfd4a36831a48dbf8b2d9325425b549a0a6f18cea118436d728eb4f1c4d66"}, ] [package.dependencies] @@ -2646,13 +2684,13 @@ files = [ [[package]] name = "pytest" -version = "8.3.3" +version = "8.3.4" description = "pytest: simple powerful testing with Python" optional = false python-versions = ">=3.8" files = [ - {file = "pytest-8.3.3-py3-none-any.whl", hash = "sha256:a6853c7375b2663155079443d2e45de913a911a11d669df02a50814944db57b2"}, - {file = "pytest-8.3.3.tar.gz", hash = "sha256:70b98107bd648308a7952b06e6ca9a50bc660be218d53c257cc1fc94fda10181"}, + {file = "pytest-8.3.4-py3-none-any.whl", hash = "sha256:50e16d954148559c9a74109af1eaf0c945ba2d8f30f0a3d3335edde19788b6f6"}, + {file = "pytest-8.3.4.tar.gz", hash = "sha256:965370d062bce11e73868e0335abac31b4d3de0e82f4007408d242b4f8610761"}, ] [package.dependencies] @@ -2668,35 +2706,35 @@ dev = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "pygments [[package]] name = "pytest-asyncio" -version = "0.24.0" +version = "0.25.0" description = "Pytest support for asyncio" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" files = [ - {file = "pytest_asyncio-0.24.0-py3-none-any.whl", hash = "sha256:a811296ed596b69bf0b6f3dc40f83bcaf341b155a269052d82efa2b25ac7037b"}, - {file = "pytest_asyncio-0.24.0.tar.gz", hash = "sha256:d081d828e576d85f875399194281e92bf8a68d60d72d1a2faf2feddb6c46b276"}, + {file = "pytest_asyncio-0.25.0-py3-none-any.whl", hash = "sha256:db5432d18eac6b7e28b46dcd9b69921b55c3b1086e85febfe04e70b18d9e81b3"}, + {file = "pytest_asyncio-0.25.0.tar.gz", hash = "sha256:8c0610303c9e0442a5db8604505fc0f545456ba1528824842b37b4a626cbf609"}, ] [package.dependencies] pytest = ">=8.2,<9" [package.extras] -docs = ["sphinx (>=5.3)", "sphinx-rtd-theme (>=1.0)"] +docs = ["sphinx (>=5.3)", "sphinx-rtd-theme (>=1)"] testing = ["coverage (>=6.2)", "hypothesis (>=5.7.1)"] [[package]] name = "pytest-cov" -version = "5.0.0" +version = "6.0.0" description = "Pytest plugin for measuring coverage." optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" files = [ - {file = "pytest-cov-5.0.0.tar.gz", hash = "sha256:5837b58e9f6ebd335b0f8060eecce69b662415b16dc503883a02f45dfeb14857"}, - {file = "pytest_cov-5.0.0-py3-none-any.whl", hash = "sha256:4f0764a1219df53214206bf1feea4633c3b558a2925c8b59f144f682861ce652"}, + {file = "pytest-cov-6.0.0.tar.gz", hash = "sha256:fde0b595ca248bb8e2d76f020b465f3b107c9632e6a1d1705f17834c89dcadc0"}, + {file = "pytest_cov-6.0.0-py3-none-any.whl", hash = "sha256:eee6f1b9e61008bd34975a4d5bab25801eb31898b032dd55addc93e96fcaaa35"}, ] [package.dependencies] -coverage = {version = ">=5.2.1", extras = ["toml"]} +coverage = {version = ">=7.5", extras = ["toml"]} pytest = ">=4.6" [package.extras] @@ -2749,13 +2787,13 @@ cli = ["click (>=5.0)"] [[package]] name = "python-multipart" -version = "0.0.12" +version = "0.0.20" description = "A streaming multipart parser for Python" optional = false python-versions = ">=3.8" files = [ - {file = "python_multipart-0.0.12-py3-none-any.whl", hash = "sha256:43dcf96cf65888a9cd3423544dd0d75ac10f7aa0c3c28a175bbcd00c9ce1aebf"}, - {file = "python_multipart-0.0.12.tar.gz", hash = "sha256:045e1f98d719c1ce085ed7f7e1ef9d8ccc8c02ba02b5566d5f7521410ced58cb"}, + {file = "python_multipart-0.0.20-py3-none-any.whl", hash = "sha256:8a62d3a8335e06589fe01f2a3e178cdcc632f3fbe0d492ad9ee0ec35aab1f104"}, + {file = "python_multipart-0.0.20.tar.gz", hash = "sha256:8dd0cab45b8e23064ae09147625994d090fa46f5b0d1e13af944c331a7fa9d13"}, ] [[package]] @@ -2986,13 +3024,13 @@ use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] [[package]] name = "rich" -version = "13.9.3" +version = "13.9.4" description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" optional = false python-versions = ">=3.8.0" files = [ - {file = "rich-13.9.3-py3-none-any.whl", hash = "sha256:9836f5096eb2172c9e77df411c1b009bace4193d6a481d534fea75ebba758283"}, - {file = "rich-13.9.3.tar.gz", hash = "sha256:bc1e01b899537598cf02579d2b9f4a415104d3fc439313a7a2c165d76557a08e"}, + {file = "rich-13.9.4-py3-none-any.whl", hash = "sha256:6049d5e6ec054bf2779ab3358186963bac2ea89175919d699e378b99738c2a90"}, + {file = "rich-13.9.4.tar.gz", hash = "sha256:439594978a49a09530cff7ebc4b5c7103ef57baf48d5ea3184f21d9a2befa098"}, ] [package.dependencies] @@ -3005,29 +3043,29 @@ jupyter = ["ipywidgets (>=7.5.1,<9)"] [[package]] name = "ruff" -version = "0.7.1" +version = "0.8.3" description = "An extremely fast Python linter and code formatter, written in Rust." optional = false python-versions = ">=3.7" files = [ - {file = "ruff-0.7.1-py3-none-linux_armv6l.whl", hash = "sha256:cb1bc5ed9403daa7da05475d615739cc0212e861b7306f314379d958592aaa89"}, - {file = "ruff-0.7.1-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:27c1c52a8d199a257ff1e5582d078eab7145129aa02721815ca8fa4f9612dc35"}, - {file = "ruff-0.7.1-py3-none-macosx_11_0_arm64.whl", hash = "sha256:588a34e1ef2ea55b4ddfec26bbe76bc866e92523d8c6cdec5e8aceefeff02d99"}, - {file = "ruff-0.7.1-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:94fc32f9cdf72dc75c451e5f072758b118ab8100727168a3df58502b43a599ca"}, - {file = "ruff-0.7.1-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:985818742b833bffa543a84d1cc11b5e6871de1b4e0ac3060a59a2bae3969250"}, - {file = "ruff-0.7.1-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:32f1e8a192e261366c702c5fb2ece9f68d26625f198a25c408861c16dc2dea9c"}, - {file = "ruff-0.7.1-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:699085bf05819588551b11751eff33e9ca58b1b86a6843e1b082a7de40da1565"}, - {file = "ruff-0.7.1-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:344cc2b0814047dc8c3a8ff2cd1f3d808bb23c6658db830d25147339d9bf9ea7"}, - {file = "ruff-0.7.1-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4316bbf69d5a859cc937890c7ac7a6551252b6a01b1d2c97e8fc96e45a7c8b4a"}, - {file = "ruff-0.7.1-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:79d3af9dca4c56043e738a4d6dd1e9444b6d6c10598ac52d146e331eb155a8ad"}, - {file = "ruff-0.7.1-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:c5c121b46abde94a505175524e51891f829414e093cd8326d6e741ecfc0a9112"}, - {file = "ruff-0.7.1-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:8422104078324ea250886954e48f1373a8fe7de59283d747c3a7eca050b4e378"}, - {file = "ruff-0.7.1-py3-none-musllinux_1_2_i686.whl", hash = "sha256:56aad830af8a9db644e80098fe4984a948e2b6fc2e73891538f43bbe478461b8"}, - {file = "ruff-0.7.1-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:658304f02f68d3a83c998ad8bf91f9b4f53e93e5412b8f2388359d55869727fd"}, - {file = "ruff-0.7.1-py3-none-win32.whl", hash = "sha256:b517a2011333eb7ce2d402652ecaa0ac1a30c114fbbd55c6b8ee466a7f600ee9"}, - {file = "ruff-0.7.1-py3-none-win_amd64.whl", hash = "sha256:f38c41fcde1728736b4eb2b18850f6d1e3eedd9678c914dede554a70d5241307"}, - {file = "ruff-0.7.1-py3-none-win_arm64.whl", hash = "sha256:19aa200ec824c0f36d0c9114c8ec0087082021732979a359d6f3c390a6ff2a37"}, - {file = "ruff-0.7.1.tar.gz", hash = "sha256:9d8a41d4aa2dad1575adb98a82870cf5db5f76b2938cf2206c22c940034a36f4"}, + {file = "ruff-0.8.3-py3-none-linux_armv6l.whl", hash = "sha256:8d5d273ffffff0acd3db5bf626d4b131aa5a5ada1276126231c4174543ce20d6"}, + {file = "ruff-0.8.3-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:e4d66a21de39f15c9757d00c50c8cdd20ac84f55684ca56def7891a025d7e939"}, + {file = "ruff-0.8.3-py3-none-macosx_11_0_arm64.whl", hash = "sha256:c356e770811858bd20832af696ff6c7e884701115094f427b64b25093d6d932d"}, + {file = "ruff-0.8.3-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9c0a60a825e3e177116c84009d5ebaa90cf40dfab56e1358d1df4e29a9a14b13"}, + {file = "ruff-0.8.3-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:75fb782f4db39501210ac093c79c3de581d306624575eddd7e4e13747e61ba18"}, + {file = "ruff-0.8.3-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7f26bc76a133ecb09a38b7868737eded6941b70a6d34ef53a4027e83913b6502"}, + {file = "ruff-0.8.3-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:01b14b2f72a37390c1b13477c1c02d53184f728be2f3ffc3ace5b44e9e87b90d"}, + {file = "ruff-0.8.3-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:53babd6e63e31f4e96ec95ea0d962298f9f0d9cc5990a1bbb023a6baf2503a82"}, + {file = "ruff-0.8.3-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1ae441ce4cf925b7f363d33cd6570c51435972d697e3e58928973994e56e1452"}, + {file = "ruff-0.8.3-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d7c65bc0cadce32255e93c57d57ecc2cca23149edd52714c0c5d6fa11ec328cd"}, + {file = "ruff-0.8.3-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:5be450bb18f23f0edc5a4e5585c17a56ba88920d598f04a06bd9fd76d324cb20"}, + {file = "ruff-0.8.3-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:8faeae3827eaa77f5721f09b9472a18c749139c891dbc17f45e72d8f2ca1f8fc"}, + {file = "ruff-0.8.3-py3-none-musllinux_1_2_i686.whl", hash = "sha256:db503486e1cf074b9808403991663e4277f5c664d3fe237ee0d994d1305bb060"}, + {file = "ruff-0.8.3-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:6567be9fb62fbd7a099209257fef4ad2c3153b60579818b31a23c886ed4147ea"}, + {file = "ruff-0.8.3-py3-none-win32.whl", hash = "sha256:19048f2f878f3ee4583fc6cb23fb636e48c2635e30fb2022b3a1cd293402f964"}, + {file = "ruff-0.8.3-py3-none-win_amd64.whl", hash = "sha256:f7df94f57d7418fa7c3ffb650757e0c2b96cf2501a0b192c18e4fb5571dfada9"}, + {file = "ruff-0.8.3-py3-none-win_arm64.whl", hash = "sha256:fe2756edf68ea79707c8d68b78ca9a58ed9af22e430430491ee03e718b5e4936"}, + {file = "ruff-0.8.3.tar.gz", hash = "sha256:5e7558304353b84279042fc584a4f4cb8a07ae79b2bf3da1a7551d960b5626d3"}, ] [[package]] @@ -3265,111 +3303,26 @@ all = ["defusedxml", "fsspec", "imagecodecs (>=2023.8.12)", "lxml", "matplotlib" [[package]] name = "tokenizers" -version = "0.20.1" +version = "0.21.0" description = "" optional = false python-versions = ">=3.7" files = [ - {file = "tokenizers-0.20.1-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:439261da7c0a5c88bda97acb284d49fbdaf67e9d3b623c0bfd107512d22787a9"}, - {file = "tokenizers-0.20.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:03dae629d99068b1ea5416d50de0fea13008f04129cc79af77a2a6392792d93c"}, - {file = "tokenizers-0.20.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b61f561f329ffe4b28367798b89d60c4abf3f815d37413b6352bc6412a359867"}, - {file = "tokenizers-0.20.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ec870fce1ee5248a10be69f7a8408a234d6f2109f8ea827b4f7ecdbf08c9fd15"}, - {file = "tokenizers-0.20.1-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d388d1ea8b7447da784e32e3b86a75cce55887e3b22b31c19d0b186b1c677800"}, - {file = "tokenizers-0.20.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:299c85c1d21135bc01542237979bf25c32efa0d66595dd0069ae259b97fb2dbe"}, - {file = "tokenizers-0.20.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e96f6c14c9752bb82145636b614d5a78e9cde95edfbe0a85dad0dd5ddd6ec95c"}, - {file = "tokenizers-0.20.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc9e95ad49c932b80abfbfeaf63b155761e695ad9f8a58c52a47d962d76e310f"}, - {file = "tokenizers-0.20.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:f22dee205329a636148c325921c73cf3e412e87d31f4d9c3153b302a0200057b"}, - {file = "tokenizers-0.20.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a2ffd9a8895575ac636d44500c66dffaef133823b6b25067604fa73bbc5ec09d"}, - {file = "tokenizers-0.20.1-cp310-none-win32.whl", hash = "sha256:2847843c53f445e0f19ea842a4e48b89dd0db4e62ba6e1e47a2749d6ec11f50d"}, - {file = "tokenizers-0.20.1-cp310-none-win_amd64.whl", hash = "sha256:f9aa93eacd865f2798b9e62f7ce4533cfff4f5fbd50c02926a78e81c74e432cd"}, - {file = "tokenizers-0.20.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:4a717dcb08f2dabbf27ae4b6b20cbbb2ad7ed78ce05a829fae100ff4b3c7ff15"}, - {file = "tokenizers-0.20.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3f84dad1ff1863c648d80628b1b55353d16303431283e4efbb6ab1af56a75832"}, - {file = "tokenizers-0.20.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:929c8f3afa16a5130a81ab5079c589226273ec618949cce79b46d96e59a84f61"}, - {file = "tokenizers-0.20.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d10766473954397e2d370f215ebed1cc46dcf6fd3906a2a116aa1d6219bfedc3"}, - {file = "tokenizers-0.20.1-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9300fac73ddc7e4b0330acbdda4efaabf74929a4a61e119a32a181f534a11b47"}, - {file = "tokenizers-0.20.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0ecaf7b0e39caeb1aa6dd6e0975c405716c82c1312b55ac4f716ef563a906969"}, - {file = "tokenizers-0.20.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5170be9ec942f3d1d317817ced8d749b3e1202670865e4fd465e35d8c259de83"}, - {file = "tokenizers-0.20.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ef3f1ae08fa9aea5891cbd69df29913e11d3841798e0bfb1ff78b78e4e7ea0a4"}, - {file = "tokenizers-0.20.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ee86d4095d3542d73579e953c2e5e07d9321af2ffea6ecc097d16d538a2dea16"}, - {file = "tokenizers-0.20.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:86dcd08da163912e17b27bbaba5efdc71b4fbffb841530fdb74c5707f3c49216"}, - {file = "tokenizers-0.20.1-cp311-none-win32.whl", hash = "sha256:9af2dc4ee97d037bc6b05fa4429ddc87532c706316c5e11ce2f0596dfcfa77af"}, - {file = "tokenizers-0.20.1-cp311-none-win_amd64.whl", hash = "sha256:899152a78b095559c287b4c6d0099469573bb2055347bb8154db106651296f39"}, - {file = "tokenizers-0.20.1-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:407ab666b38e02228fa785e81f7cf79ef929f104bcccf68a64525a54a93ceac9"}, - {file = "tokenizers-0.20.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2f13a2d16032ebc8bd812eb8099b035ac65887d8f0c207261472803b9633cf3e"}, - {file = "tokenizers-0.20.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e98eee4dca22849fbb56a80acaa899eec5b72055d79637dd6aa15d5e4b8628c9"}, - {file = "tokenizers-0.20.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:47c1bcdd61e61136087459cb9e0b069ff23b5568b008265e5cbc927eae3387ce"}, - {file = "tokenizers-0.20.1-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:128c1110e950534426e2274837fc06b118ab5f2fa61c3436e60e0aada0ccfd67"}, - {file = "tokenizers-0.20.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e2e2d47a819d2954f2c1cd0ad51bb58ffac6f53a872d5d82d65d79bf76b9896d"}, - {file = "tokenizers-0.20.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bdd67a0e3503a9a7cf8bc5a4a49cdde5fa5bada09a51e4c7e1c73900297539bd"}, - {file = "tokenizers-0.20.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:689b93d2e26d04da337ac407acec8b5d081d8d135e3e5066a88edd5bdb5aff89"}, - {file = "tokenizers-0.20.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:0c6a796ddcd9a19ad13cf146997cd5895a421fe6aec8fd970d69f9117bddb45c"}, - {file = "tokenizers-0.20.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:3ea919687aa7001a8ff1ba36ac64f165c4e89035f57998fa6cedcfd877be619d"}, - {file = "tokenizers-0.20.1-cp312-none-win32.whl", hash = "sha256:6d3ac5c1f48358ffe20086bf065e843c0d0a9fce0d7f0f45d5f2f9fba3609ca5"}, - {file = "tokenizers-0.20.1-cp312-none-win_amd64.whl", hash = "sha256:b0874481aea54a178f2bccc45aa2d0c99cd3f79143a0948af6a9a21dcc49173b"}, - {file = "tokenizers-0.20.1-cp37-cp37m-macosx_10_12_x86_64.whl", hash = "sha256:96af92e833bd44760fb17f23f402e07a66339c1dcbe17d79a9b55bb0cc4f038e"}, - {file = "tokenizers-0.20.1-cp37-cp37m-macosx_11_0_arm64.whl", hash = "sha256:65f34e5b731a262dfa562820818533c38ce32a45864437f3d9c82f26c139ca7f"}, - {file = "tokenizers-0.20.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:17f98fccb5c12ab1ce1f471731a9cd86df5d4bd2cf2880c5a66b229802d96145"}, - {file = "tokenizers-0.20.1-cp37-cp37m-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b8c0fc3542cf9370bf92c932eb71bdeb33d2d4aeeb4126d9fd567b60bd04cb30"}, - {file = "tokenizers-0.20.1-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4b39356df4575d37f9b187bb623aab5abb7b62c8cb702867a1768002f814800c"}, - {file = "tokenizers-0.20.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bfdad27b0e50544f6b838895a373db6114b85112ba5c0cefadffa78d6daae563"}, - {file = "tokenizers-0.20.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:094663dd0e85ee2e573126918747bdb40044a848fde388efb5b09d57bc74c680"}, - {file = "tokenizers-0.20.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:14e4cf033a2aa207d7ac790e91adca598b679999710a632c4a494aab0fc3a1b2"}, - {file = "tokenizers-0.20.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:9310951c92c9fb91660de0c19a923c432f110dbfad1a2d429fbc44fa956bf64f"}, - {file = "tokenizers-0.20.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:05e41e302c315bd2ed86c02e917bf03a6cf7d2f652c9cee1a0eb0d0f1ca0d32c"}, - {file = "tokenizers-0.20.1-cp37-none-win32.whl", hash = "sha256:212231ab7dfcdc879baf4892ca87c726259fa7c887e1688e3f3cead384d8c305"}, - {file = "tokenizers-0.20.1-cp37-none-win_amd64.whl", hash = "sha256:896195eb9dfdc85c8c052e29947169c1fcbe75a254c4b5792cdbd451587bce85"}, - {file = "tokenizers-0.20.1-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:741fb22788482d09d68e73ece1495cfc6d9b29a06c37b3df90564a9cfa688e6d"}, - {file = "tokenizers-0.20.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:10be14ebd8082086a342d969e17fc2d6edc856c59dbdbddd25f158fa40eaf043"}, - {file = "tokenizers-0.20.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:514cf279b22fa1ae0bc08e143458c74ad3b56cd078b319464959685a35c53d5e"}, - {file = "tokenizers-0.20.1-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a647c5b7cb896d6430cf3e01b4e9a2d77f719c84cefcef825d404830c2071da2"}, - {file = "tokenizers-0.20.1-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7cdf379219e1e1dd432091058dab325a2e6235ebb23e0aec8d0508567c90cd01"}, - {file = "tokenizers-0.20.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ba72260449e16c4c2f6f3252823b059fbf2d31b32617e582003f2b18b415c39"}, - {file = "tokenizers-0.20.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:910b96ed87316e4277b23c7bcaf667ce849c7cc379a453fa179e7e09290eeb25"}, - {file = "tokenizers-0.20.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e53975a6694428a0586534cc1354b2408d4e010a3103117f617cbb550299797c"}, - {file = "tokenizers-0.20.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:07c4b7be58da142b0730cc4e5fd66bb7bf6f57f4986ddda73833cd39efef8a01"}, - {file = "tokenizers-0.20.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:b605c540753e62199bf15cf69c333e934077ef2350262af2ccada46026f83d1c"}, - {file = "tokenizers-0.20.1-cp38-none-win32.whl", hash = "sha256:88b3bc76ab4db1ab95ead623d49c95205411e26302cf9f74203e762ac7e85685"}, - {file = "tokenizers-0.20.1-cp38-none-win_amd64.whl", hash = "sha256:d412a74cf5b3f68a90c615611a5aa4478bb303d1c65961d22db45001df68afcb"}, - {file = "tokenizers-0.20.1-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:a25dcb2f41a0a6aac31999e6c96a75e9152fa0127af8ece46c2f784f23b8197a"}, - {file = "tokenizers-0.20.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a12c3cebb8c92e9c35a23ab10d3852aee522f385c28d0b4fe48c0b7527d59762"}, - {file = "tokenizers-0.20.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:02e18da58cf115b7c40de973609c35bde95856012ba42a41ee919c77935af251"}, - {file = "tokenizers-0.20.1-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f326a1ac51ae909b9760e34671c26cd0dfe15662f447302a9d5bb2d872bab8ab"}, - {file = "tokenizers-0.20.1-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0b4872647ea6f25224e2833b044b0b19084e39400e8ead3cfe751238b0802140"}, - {file = "tokenizers-0.20.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ce6238a3311bb8e4c15b12600927d35c267b92a52c881ef5717a900ca14793f7"}, - {file = "tokenizers-0.20.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:57b7a8880b208866508b06ce365dc631e7a2472a3faa24daa430d046fb56c885"}, - {file = "tokenizers-0.20.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a908c69c2897a68f412aa05ba38bfa87a02980df70f5a72fa8490479308b1f2d"}, - {file = "tokenizers-0.20.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:da1001aa46f4490099c82e2facc4fbc06a6a32bf7de3918ba798010954b775e0"}, - {file = "tokenizers-0.20.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:42c097390e2f0ed0a5c5d569e6669dd4e9fff7b31c6a5ce6e9c66a61687197de"}, - {file = "tokenizers-0.20.1-cp39-none-win32.whl", hash = "sha256:3d4d218573a3d8b121a1f8c801029d70444ffb6d8f129d4cca1c7b672ee4a24c"}, - {file = "tokenizers-0.20.1-cp39-none-win_amd64.whl", hash = "sha256:37d1e6f616c84fceefa7c6484a01df05caf1e207669121c66213cb5b2911d653"}, - {file = "tokenizers-0.20.1-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:48689da7a395df41114f516208d6550e3e905e1239cc5ad386686d9358e9cef0"}, - {file = "tokenizers-0.20.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:712f90ea33f9bd2586b4a90d697c26d56d0a22fd3c91104c5858c4b5b6489a79"}, - {file = "tokenizers-0.20.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:359eceb6a620c965988fc559cebc0a98db26713758ec4df43fb76d41486a8ed5"}, - {file = "tokenizers-0.20.1-pp310-pypy310_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0d3caf244ce89d24c87545aafc3448be15870096e796c703a0d68547187192e1"}, - {file = "tokenizers-0.20.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:03b03cf8b9a32254b1bf8a305fb95c6daf1baae0c1f93b27f2b08c9759f41dee"}, - {file = "tokenizers-0.20.1-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:218e5a3561561ea0f0ef1559c6d95b825308dbec23fb55b70b92589e7ff2e1e8"}, - {file = "tokenizers-0.20.1-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:f40df5e0294a95131cc5f0e0eb91fe86d88837abfbee46b9b3610b09860195a7"}, - {file = "tokenizers-0.20.1-pp37-pypy37_pp73-macosx_10_12_x86_64.whl", hash = "sha256:08aaa0d72bb65058e8c4b0455f61b840b156c557e2aca57627056624c3a93976"}, - {file = "tokenizers-0.20.1-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:998700177b45f70afeb206ad22c08d9e5f3a80639dae1032bf41e8cbc4dada4b"}, - {file = "tokenizers-0.20.1-pp37-pypy37_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:62f7fbd3c2c38b179556d879edae442b45f68312019c3a6013e56c3947a4e648"}, - {file = "tokenizers-0.20.1-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:31e87fca4f6bbf5cc67481b562147fe932f73d5602734de7dd18a8f2eee9c6dd"}, - {file = "tokenizers-0.20.1-pp37-pypy37_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:956f21d359ae29dd51ca5726d2c9a44ffafa041c623f5aa33749da87cfa809b9"}, - {file = "tokenizers-0.20.1-pp37-pypy37_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:1fbbaf17a393c78d8aedb6a334097c91cb4119a9ced4764ab8cfdc8d254dc9f9"}, - {file = "tokenizers-0.20.1-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:ebe63e31f9c1a970c53866d814e35ec2ec26fda03097c486f82f3891cee60830"}, - {file = "tokenizers-0.20.1-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:81970b80b8ac126910295f8aab2d7ef962009ea39e0d86d304769493f69aaa1e"}, - {file = "tokenizers-0.20.1-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:130e35e76f9337ed6c31be386e75d4925ea807055acf18ca1a9b0eec03d8fe23"}, - {file = "tokenizers-0.20.1-pp38-pypy38_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cd28a8614f5c82a54ab2463554e84ad79526c5184cf4573bbac2efbbbcead457"}, - {file = "tokenizers-0.20.1-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9041ee665d0fa7f5c4ccf0f81f5e6b7087f797f85b143c094126fc2611fec9d0"}, - {file = "tokenizers-0.20.1-pp38-pypy38_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:62eb9daea2a2c06bcd8113a5824af8ef8ee7405d3a71123ba4d52c79bb3d9f1a"}, - {file = "tokenizers-0.20.1-pp38-pypy38_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:f861889707b54a9ab1204030b65fd6c22bdd4a95205deec7994dc22a8baa2ea4"}, - {file = "tokenizers-0.20.1-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:89d5c337d74ea6e5e7dc8af124cf177be843bbb9ca6e58c01f75ea103c12c8a9"}, - {file = "tokenizers-0.20.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:0b7f515c83397e73292accdbbbedc62264e070bae9682f06061e2ddce67cacaf"}, - {file = "tokenizers-0.20.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3e0305fc1ec6b1e5052d30d9c1d5c807081a7bd0cae46a33d03117082e91908c"}, - {file = "tokenizers-0.20.1-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5dc611e6ac0fa00a41de19c3bf6391a05ea201d2d22b757d63f5491ec0e67faa"}, - {file = "tokenizers-0.20.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c5ffe0d7f7bfcfa3b2585776ecf11da2e01c317027c8573c78ebcb8985279e23"}, - {file = "tokenizers-0.20.1-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:e7edb8ec12c100d5458d15b1e47c0eb30ad606a05641f19af7563bc3d1608c14"}, - {file = "tokenizers-0.20.1-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:de291633fb9303555793cc544d4a86e858da529b7d0b752bcaf721ae1d74b2c9"}, - {file = "tokenizers-0.20.1.tar.gz", hash = "sha256:84edcc7cdeeee45ceedb65d518fffb77aec69311c9c8e30f77ad84da3025f002"}, + {file = "tokenizers-0.21.0-cp39-abi3-macosx_10_12_x86_64.whl", hash = "sha256:3c4c93eae637e7d2aaae3d376f06085164e1660f89304c0ab2b1d08a406636b2"}, + {file = "tokenizers-0.21.0-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:f53ea537c925422a2e0e92a24cce96f6bc5046bbef24a1652a5edc8ba975f62e"}, + {file = "tokenizers-0.21.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6b177fb54c4702ef611de0c069d9169f0004233890e0c4c5bd5508ae05abf193"}, + {file = "tokenizers-0.21.0-cp39-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6b43779a269f4629bebb114e19c3fca0223296ae9fea8bb9a7a6c6fb0657ff8e"}, + {file = "tokenizers-0.21.0-cp39-abi3-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9aeb255802be90acfd363626753fda0064a8df06031012fe7d52fd9a905eb00e"}, + {file = "tokenizers-0.21.0-cp39-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d8b09dbeb7a8d73ee204a70f94fc06ea0f17dcf0844f16102b9f414f0b7463ba"}, + {file = "tokenizers-0.21.0-cp39-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:400832c0904f77ce87c40f1a8a27493071282f785724ae62144324f171377273"}, + {file = "tokenizers-0.21.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e84ca973b3a96894d1707e189c14a774b701596d579ffc7e69debfc036a61a04"}, + {file = "tokenizers-0.21.0-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:eb7202d231b273c34ec67767378cd04c767e967fda12d4a9e36208a34e2f137e"}, + {file = "tokenizers-0.21.0-cp39-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:089d56db6782a73a27fd8abf3ba21779f5b85d4a9f35e3b493c7bbcbbf0d539b"}, + {file = "tokenizers-0.21.0-cp39-abi3-musllinux_1_2_i686.whl", hash = "sha256:c87ca3dc48b9b1222d984b6b7490355a6fdb411a2d810f6f05977258400ddb74"}, + {file = "tokenizers-0.21.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:4145505a973116f91bc3ac45988a92e618a6f83eb458f49ea0790df94ee243ff"}, + {file = "tokenizers-0.21.0-cp39-abi3-win32.whl", hash = "sha256:eb1702c2f27d25d9dd5b389cc1f2f51813e99f8ca30d9e25348db6585a97e24a"}, + {file = "tokenizers-0.21.0-cp39-abi3-win_amd64.whl", hash = "sha256:87841da5a25a3a5f70c102de371db120f41873b854ba65e52bccd57df5a3780c"}, + {file = "tokenizers-0.21.0.tar.gz", hash = "sha256:ee0894bf311b75b0c03079f33859ae4b2334d675d4e93f5a4132e1eae2834fe4"}, ] [package.dependencies] @@ -3440,20 +3393,20 @@ zstd = ["zstandard (>=0.18.0)"] [[package]] name = "uvicorn" -version = "0.32.0" +version = "0.34.0" description = "The lightning-fast ASGI server." optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" files = [ - {file = "uvicorn-0.32.0-py3-none-any.whl", hash = "sha256:60b8f3a5ac027dcd31448f411ced12b5ef452c646f76f02f8cc3f25d8d26fd82"}, - {file = "uvicorn-0.32.0.tar.gz", hash = "sha256:f78b36b143c16f54ccdb8190d0a26b5f1901fe5a3c777e1ab29f26391af8551e"}, + {file = "uvicorn-0.34.0-py3-none-any.whl", hash = "sha256:023dc038422502fa28a09c7a30bf2b6991512da7dcdb8fd35fe57cfc154126f4"}, + {file = "uvicorn-0.34.0.tar.gz", hash = "sha256:404051050cd7e905de2c9a7e61790943440b3416f49cb409f965d9dcd0fa73e9"}, ] [package.dependencies] click = ">=7.0" colorama = {version = ">=0.4", optional = true, markers = "sys_platform == \"win32\" and extra == \"standard\""} h11 = ">=0.8" -httptools = {version = ">=0.5.0", optional = true, markers = "extra == \"standard\""} +httptools = {version = ">=0.6.3", optional = true, markers = "extra == \"standard\""} python-dotenv = {version = ">=0.13", optional = true, markers = "extra == \"standard\""} pyyaml = {version = ">=5.1", optional = true, markers = "extra == \"standard\""} typing-extensions = {version = ">=4.0", markers = "python_version < \"3.11\""} @@ -3462,7 +3415,7 @@ watchfiles = {version = ">=0.13", optional = true, markers = "extra == \"standar websockets = {version = ">=10.4", optional = true, markers = "extra == \"standard\""} [package.extras] -standard = ["colorama (>=0.4)", "httptools (>=0.5.0)", "python-dotenv (>=0.13)", "pyyaml (>=5.1)", "uvloop (>=0.14.0,!=0.15.0,!=0.15.1)", "watchfiles (>=0.13)", "websockets (>=10.4)"] +standard = ["colorama (>=0.4)", "httptools (>=0.6.3)", "python-dotenv (>=0.13)", "pyyaml (>=5.1)", "uvloop (>=0.14.0,!=0.15.0,!=0.15.1)", "watchfiles (>=0.13)", "websockets (>=10.4)"] [[package]] name = "uvloop" @@ -3778,4 +3731,4 @@ testing = ["coverage (>=5.0.3)", "zope.event", "zope.testing"] [metadata] lock-version = "2.0" python-versions = ">=3.10,<4.0" -content-hash = "f95dddfd343a4b2f4d19ffee71ce6b2f5137e5514a60765424164259c4dc1044" +content-hash = "b690d5fbd141da3947f4f1dc029aba1b95e7faafd723166f2c4bdc47a66c095e" diff --git a/machine-learning/pyproject.toml b/machine-learning/pyproject.toml index 4a7f7d4d6ab53..785c7ba8ac539 100644 --- a/machine-learning/pyproject.toml +++ b/machine-learning/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "machine-learning" -version = "1.119.1" +version = "1.123.0" description = "" authors = ["Hau Tran "] readme = "README.md" @@ -11,7 +11,7 @@ python = ">=3.10,<4.0" insightface = ">=0.7.3,<1.0" opencv-python-headless = ">=4.7.0.72,<5.0" pillow = ">=9.5.0,<11.0" -fastapi-slim = ">=0.95.2,<1.0" +fastapi = ">=0.95.2,<1.0" uvicorn = {extras = ["standard"], version = ">=0.22.0,<1.0"} pydantic = "^2.0.0" pydantic-settings = "^2.5.2" diff --git a/mobile/.fvmrc b/mobile/.fvmrc index ee6eaac06fefc..691c22dd17679 100644 --- a/mobile/.fvmrc +++ b/mobile/.fvmrc @@ -1,3 +1,3 @@ { - "flutter": "3.24.3" + "flutter": "3.24.5" } diff --git a/mobile/analysis_options.yaml b/mobile/analysis_options.yaml index 80514f1603b0d..9327780f1dcd3 100644 --- a/mobile/analysis_options.yaml +++ b/mobile/analysis_options.yaml @@ -28,6 +28,7 @@ linter: use_build_context_synchronously: false require_trailing_commas: true unrelated_type_equality_checks: true + prefer_const_constructors: true # Additional information about this file can be found at # https://dart.dev/guides/language/analysis-options @@ -68,7 +69,7 @@ custom_lint: # acceptable exceptions for the time being (until Isar is fully replaced) - integration_test/test_utils/general_helper.dart - lib/main.dart - - lib/pages/common/album_asset_selection.page.dart + - lib/pages/album/album_asset_selection.page.dart - lib/routing/router.dart - lib/services/immich_logger.service.dart # not really a service... more a util - lib/utils/{db,migration,renderlist_generator}.dart @@ -93,7 +94,7 @@ custom_lint: - lib/models/server_info/server_{config,disk_info,features,version}.model.dart - lib/models/shared_link/shared_link.model.dart - lib/providers/asset_viewer/asset_people.provider.dart - - lib/providers/authentication.provider.dart + - lib/providers/auth.provider.dart - lib/providers/image/immich_remote_{image,thumbnail}_provider.dart - lib/providers/map/map_state.provider.dart - lib/providers/search/{search,search_filter}.provider.dart @@ -103,6 +104,8 @@ custom_lint: - lib/widgets/album/album_thumbnail_listtile.dart - lib/widgets/forms/login/login_form.dart - lib/widgets/search/search_filter/{camera_picker,location_picker,people_picker}.dart + - lib/services/auth.service.dart # on ApiException + - test/services/auth.service_test.dart # on ApiException dart_code_metrics: metrics: diff --git a/mobile/android/app/build.gradle b/mobile/android/app/build.gradle index 52750232cceba..0ec511d9f125e 100644 --- a/mobile/android/app/build.gradle +++ b/mobile/android/app/build.gradle @@ -2,7 +2,7 @@ plugins { id "com.android.application" id "kotlin-android" id "dev.flutter.flutter-gradle-plugin" - id "kotlin-kapt" + id 'com.google.devtools.ksp' } def localProperties = new Properties() @@ -28,15 +28,16 @@ if (keystorePropertiesFile.exists()) { } android { - compileSdkVersion 34 + compileSdkVersion 35 compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 + sourceCompatibility JavaVersion.VERSION_17 + targetCompatibility JavaVersion.VERSION_17 + coreLibraryDesugaringEnabled true } kotlinOptions { - jvmTarget = '1.8' + jvmTarget = '17' } sourceSets { @@ -46,7 +47,7 @@ android { defaultConfig { applicationId "app.alextran.immich" minSdkVersion 26 - targetSdkVersion 34 + targetSdkVersion 35 versionCode flutterVersionCode.toInteger() versionName flutterVersionName } @@ -74,6 +75,7 @@ android { signingConfig signingConfigs.release } } + namespace 'app.alextran.immich' } flutter { @@ -81,11 +83,11 @@ flutter { } dependencies { - def kotlin_version = '1.9.24' - def kotlin_coroutines_version = '1.8.1' - def work_version = '2.9.0' - def concurrent_version = '1.1.0' - def guava_version = '33.2.0-android' + def kotlin_version = '2.0.20' + def kotlin_coroutines_version = '1.9.0' + def work_version = '2.9.1' + def concurrent_version = '1.2.0' + def guava_version = '33.3.1-android' def glide_version = '4.16.0' implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" @@ -94,7 +96,8 @@ dependencies { implementation "androidx.concurrent:concurrent-futures:$concurrent_version" implementation "com.google.guava:guava:$guava_version" implementation "com.github.bumptech.glide:glide:$glide_version" - kapt "com.github.bumptech.glide:compiler:$glide_version" + ksp "com.github.bumptech.glide:ksp:$glide_version" + coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.1.2' } // This is uncommented in F-Droid build script diff --git a/mobile/android/app/proguard-rules.pro b/mobile/android/app/proguard-rules.pro new file mode 100644 index 0000000000000..ea6dd795b58c9 --- /dev/null +++ b/mobile/android/app/proguard-rules.pro @@ -0,0 +1,32 @@ +##---------------Begin: proguard configuration for Gson ---------- +# Gson uses generic type information stored in a class file when working with fields. Proguard +# removes such information by default, so configure it to keep all of it. +-keepattributes Signature + +# For using GSON @Expose annotation +-keepattributes *Annotation* + +# Gson specific classes +-dontwarn sun.misc.** +#-keep class com.google.gson.stream.** { *; } + +# Application classes that will be serialized/deserialized over Gson +-keep class com.google.gson.examples.android.model.** { ; } + +# Prevent proguard from stripping interface information from TypeAdapter, TypeAdapterFactory, +# JsonSerializer, JsonDeserializer instances (so they can be used in @JsonAdapter) +-keep class * extends com.google.gson.TypeAdapter +-keep class * implements com.google.gson.TypeAdapterFactory +-keep class * implements com.google.gson.JsonSerializer +-keep class * implements com.google.gson.JsonDeserializer + +# Prevent R8 from leaving Data object members always null +-keepclassmembers,allowobfuscation class * { + @com.google.gson.annotations.SerializedName ; +} + +# Retain generic signatures of TypeToken and its subclasses with R8 version 3.0 and higher. +-keep,allowobfuscation,allowshrinking class com.google.gson.reflect.TypeToken +-keep,allowobfuscation,allowshrinking class * extends com.google.gson.reflect.TypeToken + +##---------------End: proguard configuration for Gson ---------- \ No newline at end of file diff --git a/mobile/android/app/src/debug/AndroidManifest.xml b/mobile/android/app/src/debug/AndroidManifest.xml index e33c470b4d2a0..ac7c0c7e53034 100644 --- a/mobile/android/app/src/debug/AndroidManifest.xml +++ b/mobile/android/app/src/debug/AndroidManifest.xml @@ -1,6 +1,6 @@ - + - \ No newline at end of file + diff --git a/mobile/android/app/src/main/AndroidManifest.xml b/mobile/android/app/src/main/AndroidManifest.xml index 17c2830b48e26..e49cf5b8daa91 100644 --- a/mobile/android/app/src/main/AndroidManifest.xml +++ b/mobile/android/app/src/main/AndroidManifest.xml @@ -1,4 +1,4 @@ - @@ -16,6 +16,8 @@ + + diff --git a/mobile/android/app/src/profile/AndroidManifest.xml b/mobile/android/app/src/profile/AndroidManifest.xml index e33c470b4d2a0..ac7c0c7e53034 100644 --- a/mobile/android/app/src/profile/AndroidManifest.xml +++ b/mobile/android/app/src/profile/AndroidManifest.xml @@ -1,6 +1,6 @@ - + - \ No newline at end of file + diff --git a/mobile/android/build.gradle b/mobile/android/build.gradle index 87cc79281dd37..bcf3daa1c8d20 100644 --- a/mobile/android/build.gradle +++ b/mobile/android/build.gradle @@ -1,5 +1,5 @@ allprojects { - ext.kotlin_version = '1.9.24' + ext.kotlin_version = '2.0.20' repositories { google() @@ -16,8 +16,8 @@ subprojects { if (project.plugins.hasPlugin("com.android.application") || project.plugins.hasPlugin("com.android.library")) { project.android { - compileSdkVersion 34 - buildToolsVersion "34.0.0" + compileSdkVersion 35 + buildToolsVersion "35.0.0" } } } diff --git a/mobile/android/fastlane/Fastfile b/mobile/android/fastlane/Fastfile index 04400658b59da..45212a76a89c2 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" => 164, - "android.injected.version.name" => "1.119.1", + "android.injected.version.code" => 172, + "android.injected.version.name" => "1.123.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.properties b/mobile/android/gradle.properties index 4d3226abc21bb..78c37cc2a3bb2 100644 --- a/mobile/android/gradle.properties +++ b/mobile/android/gradle.properties @@ -1,3 +1,5 @@ -org.gradle.jvmargs=-Xmx1536M +org.gradle.jvmargs=-Xmx4096M android.useAndroidX=true -android.enableJetifier=true \ No newline at end of file +android.enableJetifier=true +android.nonTransitiveRClass=false +android.nonFinalResIds=false \ No newline at end of file diff --git a/mobile/android/gradle/wrapper/gradle-wrapper.properties b/mobile/android/gradle/wrapper/gradle-wrapper.properties index 6357330c9e8fd..dedd5d1e69e69 100644 --- a/mobile/android/gradle/wrapper/gradle-wrapper.properties +++ b/mobile/android/gradle/wrapper/gradle-wrapper.properties @@ -1,7 +1,7 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-all.zip +networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.4-all.zip -distributionSha256Sum=fe696c020f241a5f69c30f763c5a7f38eec54b490db19cd2b0962dda420d7d12 \ No newline at end of file diff --git a/mobile/android/settings.gradle b/mobile/android/settings.gradle index e809a0abaa38f..74f8904a10960 100644 --- a/mobile/android/settings.gradle +++ b/mobile/android/settings.gradle @@ -18,9 +18,9 @@ pluginManagement { plugins { id "dev.flutter.flutter-plugin-loader" version "1.0.0" - id "com.android.application" version "7.4.2" apply false - id "org.jetbrains.kotlin.android" version "1.9.0" apply false - id "org.jetbrains.kotlin.kapt" version "1.9.0" apply false + id "com.android.application" version '8.7.2' apply false + id "org.jetbrains.kotlin.android" version "2.0.20" apply false + id 'com.google.devtools.ksp' version '2.0.20-1.0.24' apply false } include ":app" diff --git a/mobile/assets/i18n/ar-JO.json b/mobile/assets/i18n/ar-JO.json index cbf05ca49cfcf..ec65d9ac9e330 100644 --- a/mobile/assets/i18n/ar-JO.json +++ b/mobile/assets/i18n/ar-JO.json @@ -7,6 +7,7 @@ "action_common_select": "Select", "action_common_update": "تحديث", "add_a_name": "Add a name", + "add_endpoint": "Add endpoint", "add_to_album_bottom_sheet_added": "تمت الاضافة{album}", "add_to_album_bottom_sheet_already_exists": "موجودة مسبقا {album}", "advanced_settings_log_level_title": "Log level: {}", @@ -65,7 +66,12 @@ "assets_restored_successfully": "{} asset(s) restored successfully", "assets_trashed": "{} asset(s) trashed", "assets_trashed_from_server": "{} asset(s) trashed from the Immich server", + "asset_viewer_settings_subtitle": "Manage your gallery viewer settings", "asset_viewer_settings_title": "عارض الأصول", + "automatic_endpoint_switching_subtitle": "Connect locally over designated Wi-Fi when available and use alternative connections elsewhere", + "automatic_endpoint_switching_title": "Automatic URL switching", + "background_location_permission": "Background location permission", + "background_location_permission_content": "In order to switch networks when running in the background, Immich must *always* have precise location access so the app can read the Wi-Fi network's name", "backup_album_selection_page_albums_device": "Albums on device ({})", "backup_album_selection_page_albums_tap": "انقر للتضمين، وانقر نقرًا مزدوجًا للاستثناء", "backup_album_selection_page_assets_scatter": "يمكن أن تنتشر الأصول عبر ألبومات متعددة. وبالتالي، يمكن تضمين الألبومات أو استبعادها أثناء عملية النسخ الاحتياطي.", @@ -131,6 +137,7 @@ "backup_manual_success": "نجاح", "backup_manual_title": "حالة التحميل", "backup_options_page_title": "خيارات النسخ الاحتياطي", + "backup_setting_subtitle": "Manage background and foreground upload settings", "cache_settings_album_thumbnails": "Library page thumbnails ({} assets)", "cache_settings_clear_cache_button": "مسح ذاكرة التخزين المؤقت", "cache_settings_clear_cache_button_title": "يقوم بمسح ذاكرة التخزين المؤقت للتطبيق.سيؤثر هذا بشكل كبير على أداء التطبيق حتى إعادة بناء ذاكرة التخزين المؤقت.", @@ -149,11 +156,16 @@ "cache_settings_tile_subtitle": "التحكم في سلوك التخزين المحلي", "cache_settings_tile_title": "التخزين المحلي", "cache_settings_title": "إعدادات التخزين المؤقت", + "cancel": "Cancel", + "change_display_order": "Change display order", "change_password_form_confirm_password": "تأكيد كلمة المرور", "change_password_form_description": "مرحبًا ،هذه هي المرة الأولى التي تقوم فيها بالتسجيل في النظام أو تم تقديم طلب لتغيير كلمة المرور الخاصة بك.الرجاء إدخال كلمة المرور الجديدة أدناه", "change_password_form_new_password": "كلمة المرور الجديدة", "change_password_form_password_mismatch": "كلمة المرور غير مطابقة", "change_password_form_reenter_new_password": "أعد إدخال كلمة مرور جديدة", + "check_corrupt_asset_backup": "Check for corrupt asset backups", + "check_corrupt_asset_backup_button": "Perform check", + "check_corrupt_asset_backup_description": "Run this check only over Wi-Fi and once all assets have been backed-up. The procedure might take a few minutes.", "client_cert_dialog_msg_confirm": "OK", "client_cert_enter_password": "Enter Password", "client_cert_import": "Import", @@ -199,6 +211,7 @@ "crop": "Crop", "curated_location_page_title": "أماكن", "curated_object_page_title": "أشياء", + "current_server_address": "Current server address", "daily_title_text_date": "E ، MMM DD", "daily_title_text_date_year": "E ، MMM DD ، yyyy", "date_format": "E ، Lll D ، Y • H: MM A", @@ -235,6 +248,8 @@ "edit_date_time_dialog_timezone": "وحدة زمنية", "edit_image_title": "Edit", "edit_location_dialog_title": "موقع", + "enter_wifi_name": "Enter WiFi name", + "error_change_sort_album": "Failed to change album sort order", "error_saving_image": "Error: {}", "exif_bottom_sheet_description": "اضف وصفا...", "exif_bottom_sheet_details": "تفاصيل", @@ -246,11 +261,15 @@ "experimental_settings_new_asset_list_title": "تمكين شبكة الصور التجريبية", "experimental_settings_subtitle": "استخدام على مسؤوليتك الخاصة!", "experimental_settings_title": "تجريبي", + "external_network": "External network", + "external_network_sheet_info": "When not on the preferred WiFi network, the app will connect to the server through the first of the below URLs it can reach, starting from top to bottom", "favorites": "Favorites", "favorites_page_no_favorites": "لم يتم العثور على الأصول المفضلة", "favorites_page_title": "المفضلة", "filename_search": "File name or extension", "filter": "Filter", + "get_wifiname_error": "Could not get Wi-Fi name. Make sure you have granted the necessary permissions and are connected to a Wi-Fi network", + "grant_permission": "Grant permission", "haptic_feedback_switch": "تمكين ردود الفعل اللمسية", "haptic_feedback_title": "ردود فعل لمسية", "header_settings_add_header_tip": "Add Header", @@ -296,6 +315,10 @@ "library_page_sort_most_oldest_photo": "أقدم صورة", "library_page_sort_most_recent_photo": "أحدث الصور", "library_page_sort_title": "عنوان الألبوم", + "local_network": "Local network", + "local_network_sheet_info": "The app will connect to the server through this URL when using the specified Wi-Fi network", + "location_permission": "Location permission", + "location_permission_content": "In order to use the auto-switching feature, Immich needs precise location permission so it can read the current WiFi network's name", "location_picker_choose_on_map": "اختر على الخريطة", "location_picker_latitude": "خط العرض", "location_picker_latitude_error": "أدخل خط عرض صالح", @@ -365,6 +388,8 @@ "multiselect_grid_edit_date_time_err_read_only": "لا يمكن تعديل تاريخ الأصول (المواد) للقراءة فقط، سوف يتخطى", "multiselect_grid_edit_gps_err_read_only": "لا يمكن تعديل موقع الأصول (المواد) للقراءة فقط، سوف يتخطى", "my_albums": "My albums", + "networking_settings": "Networking", + "networking_subtitle": "Manage the server endpoint settings", "no_assets_to_show": "لا توجد أصول لعرضها", "no_name": "No name", "notification_permission_dialog_cancel": "يلغي", @@ -398,6 +423,7 @@ "permission_onboarding_permission_limited": "إذن محدود. للسماح بالنسخ الاحتياطي للتطبيق وإدارة مجموعة المعرض بالكامل، امنح أذونات الصور والفيديو في الإعدادات.", "permission_onboarding_request": "يتطلب التطبيق إذنًا لعرض الصور ومقاطع الفيديو الخاصة بك", "places": "Places", + "preferences_settings_subtitle": "Manage the app's preferences", "preferences_settings_title": "التفضيلات", "profile_drawer_app_logs": "السجلات", "profile_drawer_client_out_of_date_major": "تطبيق الهاتف المحمول قديم.يرجى التحديث إلى أحدث إصدار رئيسي.", @@ -412,6 +438,7 @@ "profile_drawer_trash": "نفايات", "recently_added": "Recently added", "recently_added_page_title": "أضيف مؤخرا", + "save": "Save", "save_to_gallery": "Save to gallery", "scaffold_body_error_occurred": "حدث خطأ", "search_albums": "Search albums", @@ -457,6 +484,7 @@ "search_page_places": "أماكن", "search_page_recently_added": "أضيف مؤخرا", "search_page_screenshots": "لقطات الشاشة", + "search_page_search_photos_videos": "Search for your photos and videos", "search_page_selfies": " صور ذاتيه", "search_page_things": "أشياء", "search_page_videos": "أشرطة فيديو", @@ -469,6 +497,7 @@ "select_additional_user_for_sharing_page_suggestions": "اقتراحات", "select_user_for_sharing_page_err_album": "فشل في إنشاء ألبوم", "select_user_for_sharing_page_share_suggestions": "اقتراحات", + "server_endpoint": "Server Endpoint", "server_info_box_app_version": "نسخة التطبيق", "server_info_box_latest_release": "احدث اصدار", "server_info_box_server_url": "عنوان URL الخادم", @@ -480,6 +509,7 @@ "setting_image_viewer_preview_title": "تحميل صورة معاينة", "setting_image_viewer_title": "الصور", "setting_languages_apply": "تغيير الإعدادات", + "setting_languages_subtitle": "Change the app's language", "setting_languages_title": "اللغات", "setting_notifications_notify_failures_grace_period": "Notify background backup failures: {}", "setting_notifications_notify_hours": "{} hours", @@ -612,6 +642,8 @@ "upload_dialog_info": "هل تريد النسخ الاحتياطي للأصول (الأصول) المحددة إلى الخادم؟", "upload_dialog_ok": "رفع", "upload_dialog_title": "تحميل الأصول", + "use_current_connection": "use current connection", + "validate_endpoint_error": "Please enter a valid URL", "version_announcement_overlay_ack": "يُقرّ", "version_announcement_overlay_release_notes": "ملاحظات الإصدار", "version_announcement_overlay_text_1": "مرحبًا يا صديقي ، هناك إصدار جديد", @@ -621,5 +653,7 @@ "videos": "Videos", "viewer_remove_from_stack": "حذف من الكومه أو المجموعة", "viewer_stack_use_as_main_asset": "استخدم كأصل رئيسي", - "viewer_unstack": "فك الكومه" + "viewer_unstack": "فك الكومه", + "wifi_name": "WiFi Name", + "your_wifi_name": "Your WiFi name" } \ No newline at end of file diff --git a/mobile/assets/i18n/cs-CZ.json b/mobile/assets/i18n/cs-CZ.json index 6a2c70a2a91a3..1c2eda1de5148 100644 --- a/mobile/assets/i18n/cs-CZ.json +++ b/mobile/assets/i18n/cs-CZ.json @@ -7,6 +7,7 @@ "action_common_select": "Vybrat", "action_common_update": "Aktualizovat", "add_a_name": "Přidat název", + "add_endpoint": "Přidat koncový bod", "add_to_album_bottom_sheet_added": "Přidáno do {album}", "add_to_album_bottom_sheet_already_exists": "Je již v {album}", "advanced_settings_log_level_title": "Úroveň protokolování: {}", @@ -44,9 +45,9 @@ "app_bar_signout_dialog_content": "Určitě se chcete odhlásit?", "app_bar_signout_dialog_ok": "Ano", "app_bar_signout_dialog_title": "Odhlásit se", - "archived": "Archivované", + "archived": "Archiv", "archive_page_no_archived_assets": "Nebyla nalezena žádná archivovaná média", - "archive_page_title": "Archív ({})", + "archive_page_title": "Archiv ({})", "asset_action_delete_err_read_only": "Nelze odstranit položky pouze pro čtení, přeskakuji", "asset_action_share_err_offline": "Nelze načíst offline položky, přeskakuji", "asset_list_group_by_sub_title": "Seskupit podle", @@ -65,7 +66,12 @@ "assets_restored_successfully": "{} položek úspěšně obnoveno", "assets_trashed": "{} položek vyhozeno do koše", "assets_trashed_from_server": "{} položek vyhozeno do koše na Immich serveru", + "asset_viewer_settings_subtitle": "Správa nastavení prohlížeče galerie", "asset_viewer_settings_title": "Prohlížeč", + "automatic_endpoint_switching_subtitle": "Připojit se místně přes určenou Wi-Fi, pokud je k dispozici, a používat alternativní připojení jinde", + "automatic_endpoint_switching_title": "Automatické přepínání URL", + "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ě", "backup_album_selection_page_albums_device": "Alba v zařízení ({})", "backup_album_selection_page_albums_tap": "Klepnutím na položku ji zahrnete, opětovným klepnutím ji vyloučíte", "backup_album_selection_page_assets_scatter": "Položky mohou být roztroušeny ve více albech. To umožňuje zahrnout nebo vyloučit alba během procesu zálohování.", @@ -131,6 +137,7 @@ "backup_manual_success": "Úspěch", "backup_manual_title": "Stav nahrávání", "backup_options_page_title": "Nastavení záloh", + "backup_setting_subtitle": "Správa nastavení zálohování na pozadí a na popředí", "cache_settings_album_thumbnails": "Náhledy stránek knihovny (položek {})", "cache_settings_clear_cache_button": "Vymazat vyrovnávací paměť", "cache_settings_clear_cache_button_title": "Vymaže vyrovnávací paměť aplikace. To výrazně ovlivní výkon aplikace, dokud se vyrovnávací paměť neobnoví.", @@ -149,11 +156,16 @@ "cache_settings_tile_subtitle": "Ovládání chování místního úložiště", "cache_settings_tile_title": "Místní úložiště", "cache_settings_title": "Nastavení vyrovnávací paměti", + "cancel": "Zrušit", + "change_display_order": "Změnit pořadí zobrazení", "change_password_form_confirm_password": "Potvrďte heslo", "change_password_form_description": "Dobrý den, {name}\n\nje to buď poprvé, co se přihlašujete do systému, nebo byl vytvořen požadavek na změnu hesla. Níže zadejte nové heslo.", "change_password_form_new_password": "Nové heslo", "change_password_form_password_mismatch": "Hesla se neshodují", "change_password_form_reenter_new_password": "Znovu zadejte nové heslo", + "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.", "client_cert_dialog_msg_confirm": "OK", "client_cert_enter_password": "Zadejte heslo", "client_cert_import": "Importovat", @@ -172,7 +184,7 @@ "control_bottom_app_bar_add_to_album": "Přidat do alba", "control_bottom_app_bar_album_info": "{} položek", "control_bottom_app_bar_album_info_shared": "{} položky – sdílené", - "control_bottom_app_bar_archive": "Archív", + "control_bottom_app_bar_archive": "Archivovat", "control_bottom_app_bar_create_new_album": "Vytvořit nové album", "control_bottom_app_bar_delete": "Smazat", "control_bottom_app_bar_delete_from_immich": "Smazat ze serveru Immich", @@ -199,6 +211,7 @@ "crop": "Oříznout", "curated_location_page_title": "Místa", "curated_object_page_title": "Věci", + "current_server_address": "Aktuální adresa serveru", "daily_title_text_date": "EEEE, d. MMMM", "daily_title_text_date_year": "EEEE, d. MMMM y", "date_format": "EEEE, d. MMMM y • H:mm", @@ -235,6 +248,8 @@ "edit_date_time_dialog_timezone": "Časové pásmo", "edit_image_title": "Upravit", "edit_location_dialog_title": "Poloha", + "enter_wifi_name": "Zadejte název WiFi", + "error_change_sort_album": "Nepodařilo se změnit pořadí alba", "error_saving_image": "Chyba: {}", "exif_bottom_sheet_description": "Přidat popis...", "exif_bottom_sheet_details": "PODROBNOSTI", @@ -246,11 +261,15 @@ "experimental_settings_new_asset_list_title": "Povolení experimentální mřížky fotografií", "experimental_settings_subtitle": "Používejte na vlastní riziko!", "experimental_settings_title": "Experimentální", + "external_network": "Externí síť", + "external_network_sheet_info": "Pokud nejste v preferované síti WiFi, aplikace se připojí k serveru prostřednictvím první z níže uvedených adres URL, které může dosáhnout, počínaje shora dolů", "favorites": "Oblíbené", "favorites_page_no_favorites": "Nebyla nalezena žádná oblíbená média", "favorites_page_title": "Oblíbené", "filename_search": "Název nebo přípona souboru", "filter": "Filtr", + "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", + "grant_permission": "Udělit oprávnění", "haptic_feedback_switch": "Povolit dotykovou zpětnou vazbu", "haptic_feedback_title": "Dotyková zpětná vazba", "header_settings_add_header_tip": "Přidat hlavičku", @@ -285,7 +304,7 @@ "invalid_date_format": "Chybný formát data", "library": "Knihovna", "library_page_albums": "Alba", - "library_page_archive": "Archív", + "library_page_archive": "Archivovat", "library_page_device_albums": "Alba v zařízení", "library_page_favorites": "Oblíbené", "library_page_new_album": "Nové album", @@ -296,6 +315,10 @@ "library_page_sort_most_oldest_photo": "Nejstarší fotografie", "library_page_sort_most_recent_photo": "Nejnovější fotografie", "library_page_sort_title": "Podle názvu alba", + "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", + "location_permission_content": "Aby bylo možné používat funkci automatického přepínání, potřebuje Immich oprávnění k přesné poloze, aby mohl přečíst název aktuální WiFi sítě", "location_picker_choose_on_map": "Vyberte na mapě", "location_picker_latitude": "Zeměpisná šířka", "location_picker_latitude_error": "Zadejte platnou zeměpisnou šířku", @@ -365,6 +388,8 @@ "multiselect_grid_edit_date_time_err_read_only": "Nelze upravit datum položek pouze pro čtení, přeskakuji", "multiselect_grid_edit_gps_err_read_only": "Nelze upravit polohu položek pouze pro čtení, přeskakuji", "my_albums": "Moje alba", + "networking_settings": "Síť", + "networking_subtitle": "Správa nastavení koncového bodu serveru", "no_assets_to_show": "Žádné položky k zobrazení", "no_name": "Bez jména", "notification_permission_dialog_cancel": "Zrušit", @@ -398,6 +423,7 @@ "permission_onboarding_permission_limited": "Přístup omezen. Chcete-li používat Immich k zálohování a správě celé vaší kolekce galerií, povolte v nastavení přístup k fotkám a videím.", "permission_onboarding_request": "Immich potřebuje přístup k zobrazení vašich fotek a videí.", "places": "Místa", + "preferences_settings_subtitle": "Správa předvoleb aplikace", "preferences_settings_title": "Předvolby", "profile_drawer_app_logs": "Logy", "profile_drawer_client_out_of_date_major": "Mobilní aplikace je zastaralá. Aktualizujte ji na nejnovější hlavní verzi.", @@ -412,6 +438,7 @@ "profile_drawer_trash": "Vyhodit", "recently_added": "Nedávno přidané", "recently_added_page_title": "Nedávno přidané", + "save": "Uložit", "save_to_gallery": "Uložit do galerie", "scaffold_body_error_occurred": "Došlo k chybě", "search_albums": "Vyhledávejte alba", @@ -457,6 +484,7 @@ "search_page_places": "Místa", "search_page_recently_added": "Nedávno přidané", "search_page_screenshots": "Snímky obrazovky", + "search_page_search_photos_videos": "Vyhledávejte svoje fotky a videa", "search_page_selfies": "Autoportréty", "search_page_things": "Věci", "search_page_videos": "Videa", @@ -469,6 +497,7 @@ "select_additional_user_for_sharing_page_suggestions": "Návrhy", "select_user_for_sharing_page_err_album": "Nepodařilo se vytvořit album", "select_user_for_sharing_page_share_suggestions": "Návrhy", + "server_endpoint": "Koncový bod serveru", "server_info_box_app_version": "Verze aplikace", "server_info_box_latest_release": "Nejnovější verze", "server_info_box_server_url": "URL serveru", @@ -480,6 +509,7 @@ "setting_image_viewer_preview_title": "Načíst náhled obrázku", "setting_image_viewer_title": "Obrázky", "setting_languages_apply": "Použít", + "setting_languages_subtitle": "Změna jazyka aplikace", "setting_languages_title": "Jazyk", "setting_notifications_notify_failures_grace_period": "Oznámení o selhání zálohování na pozadí: {}", "setting_notifications_notify_hours": "{} hodin", @@ -612,6 +642,8 @@ "upload_dialog_info": "Chcete zálohovat vybrané položky na server?", "upload_dialog_ok": "Nahrát", "upload_dialog_title": "Nahrát položku", + "use_current_connection": "použít aktuální připojení", + "validate_endpoint_error": "Zadejte platné URL", "version_announcement_overlay_ack": "Potvrdit", "version_announcement_overlay_release_notes": "poznámky k vydání", "version_announcement_overlay_text_1": "Ahoj, k dispozici je nová verze", @@ -621,5 +653,7 @@ "videos": "Videa", "viewer_remove_from_stack": "Odstranit ze zásobníku", "viewer_stack_use_as_main_asset": "Použít jako hlavní položku", - "viewer_unstack": "Rozbalit zásobník" + "viewer_unstack": "Rozbalit zásobník", + "wifi_name": "Název WiFi", + "your_wifi_name": "Váš název WiFi" } \ No newline at end of file diff --git a/mobile/assets/i18n/da-DK.json b/mobile/assets/i18n/da-DK.json index aa39ed54bca0a..ce2f284e519a8 100644 --- a/mobile/assets/i18n/da-DK.json +++ b/mobile/assets/i18n/da-DK.json @@ -6,7 +6,8 @@ "action_common_save": "Save", "action_common_select": "Select", "action_common_update": "Opdater", - "add_a_name": "Add a name", + "add_a_name": "Tilføj navn", + "add_endpoint": "Add endpoint", "add_to_album_bottom_sheet_added": "Tilføjet til {album}", "add_to_album_bottom_sheet_already_exists": "Allerede i {album}", "advanced_settings_log_level_title": "Logniveau: {}", @@ -22,7 +23,7 @@ "advanced_settings_troubleshooting_title": "Fejlsøgning", "album_info_card_backup_album_excluded": "EKSKLUDERET", "album_info_card_backup_album_included": "INKLUDERET", - "albums": "Albums", + "albums": "Albummer", "album_thumbnail_card_item": "1 genstand", "album_thumbnail_card_items": "{} genstande", "album_thumbnail_card_shared": ". Delt", @@ -38,13 +39,13 @@ "album_viewer_appbar_share_remove": "Fjern fra album", "album_viewer_appbar_share_to": "Del til", "album_viewer_page_share_add_users": "Tilføj brugere", - "all": "All", + "all": "Alt", "all_people_page_title": "Personer", "all_videos_page_title": "Videoer", "app_bar_signout_dialog_content": "Er du sikker på, du vil logge ud?", "app_bar_signout_dialog_ok": "Ja", "app_bar_signout_dialog_title": "Log ud", - "archived": "Archived", + "archived": "Arkiveret", "archive_page_no_archived_assets": "Ingen arkiverede elementer blev fundet", "archive_page_title": "Arkivér ({})", "asset_action_delete_err_read_only": "Kan ikke slette kun læselige elementer. Springer over", @@ -65,7 +66,12 @@ "assets_restored_successfully": "{} element(er) blev gendannet succesfuldt", "assets_trashed": "{} element(er) blev smidt i papirkurven", "assets_trashed_from_server": "{} element(er) blev smidt i serverens papirkurv", + "asset_viewer_settings_subtitle": "Manage your gallery viewer settings", "asset_viewer_settings_title": "Billedviser", + "automatic_endpoint_switching_subtitle": "Connect locally over designated Wi-Fi when available and use alternative connections elsewhere", + "automatic_endpoint_switching_title": "Automatic URL switching", + "background_location_permission": "Background location permission", + "background_location_permission_content": "In order to switch networks when running in the background, Immich must *always* have precise location access so the app can read the Wi-Fi network's name", "backup_album_selection_page_albums_device": "Albummer på enhed ({})", "backup_album_selection_page_albums_tap": "Tryk en gang for at inkludere, tryk to gange for at ekskludere", "backup_album_selection_page_assets_scatter": "Elementer kan være spredt på tværs af flere albummer. Albummer kan således inkluderes eller udelukkes under sikkerhedskopieringsprocessen.", @@ -131,6 +137,7 @@ "backup_manual_success": "Succes", "backup_manual_title": "Uploadstatus", "backup_options_page_title": "Backupindstillinger", + "backup_setting_subtitle": "Manage background and foreground upload settings", "cache_settings_album_thumbnails": "Biblioteksminiaturebilleder ({} elementer)", "cache_settings_clear_cache_button": "Fjern cache", "cache_settings_clear_cache_button_title": "Fjern appens cache. Dette vil i stor grad påvirke appens ydeevne indtil cachen er genopbygget.", @@ -149,11 +156,16 @@ "cache_settings_tile_subtitle": "Kontroller den lokale lagerplads", "cache_settings_tile_title": "Lokal lagerplads", "cache_settings_title": "Cache-indstillinger", + "cancel": "Cancel", + "change_display_order": "Change display order", "change_password_form_confirm_password": "Bekræft kodeord", "change_password_form_description": "Hej {name},\n\nDette er enten første gang du logger ind eller også er der lavet en anmodning om at ændre dit kodeord. Indtast venligst et nyt kodeord nedenfor.", "change_password_form_new_password": "Nyt kodeord", "change_password_form_password_mismatch": "Kodeord er ikke ens", "change_password_form_reenter_new_password": "Gentag nyt kodeord", + "check_corrupt_asset_backup": "Check for corrupt asset backups", + "check_corrupt_asset_backup_button": "Perform check", + "check_corrupt_asset_backup_description": "Run this check only over Wi-Fi and once all assets have been backed-up. The procedure might take a few minutes.", "client_cert_dialog_msg_confirm": "OK", "client_cert_enter_password": "Enter Password", "client_cert_import": "Import", @@ -189,9 +201,9 @@ "control_bottom_app_bar_unarchive": "Afakivér", "control_bottom_app_bar_unfavorite": "Fjern favorit", "control_bottom_app_bar_upload": "Upload", - "create_album": "Create album", + "create_album": "Opret album", "create_album_page_untitled": "Uden titel", - "create_new": "CREATE NEW", + "create_new": "OPRET NY", "create_shared_album_page_create": "Opret", "create_shared_album_page_share": "Del", "create_shared_album_page_share_add_assets": "TILFØJ ELEMENT", @@ -199,6 +211,7 @@ "crop": "Beskær", "curated_location_page_title": "Steder", "curated_object_page_title": "Ting", + "current_server_address": "Current server address", "daily_title_text_date": "E, dd MMM", "daily_title_text_date_year": "E, dd MMM, yyyy", "date_format": "E d. LLL y • hh:mm", @@ -216,25 +229,27 @@ "delete_shared_link_dialog_title": "Slet delt link", "description_input_hint_text": "Tilføj en beskrivelse...", "description_input_submit_error": "Fejl med at opdatere beskrivelsen. Tjek loggen for flere detaljer", - "download_canceled": "Download canceled", - "download_complete": "Download complete", - "download_enqueue": "Download enqueued", + "download_canceled": "Download annulleret", + "download_complete": "Download fuldført", + "download_enqueue": "Donload sat i kø", "download_error": "Fejl med download", - "download_failed": "Download failed", - "download_filename": "file: {}", - "download_finished": "Download finished", - "downloading": "Downloading...", - "downloading_media": "Downloading media", - "download_notfound": "Download not found", - "download_paused": "Download paused", + "download_failed": "Download mislykkes", + "download_filename": "fil: {}", + "download_finished": "Download afsluttet", + "downloading": "Downloader...", + "downloading_media": "Download medier", + "download_notfound": "Download ikke fundet", + "download_paused": "Download pauset", "download_started": "Download startet", "download_sucess": "Download færdig", "download_sucess_android": "Mediet er blevet downloadet til DCIM/Immich", - "download_waiting_to_retry": "Waiting to retry", + "download_waiting_to_retry": "Afventer at prøve igen", "edit_date_time_dialog_date_time": "Dato og klokkeslæt", "edit_date_time_dialog_timezone": "Tidszone", "edit_image_title": "Rediger", "edit_location_dialog_title": "Placering", + "enter_wifi_name": "Enter WiFi name", + "error_change_sort_album": "Failed to change album sort order", "error_saving_image": "Fejl: {}", "exif_bottom_sheet_description": "Tilføj beskrivelse...", "exif_bottom_sheet_details": "DETALJER", @@ -246,11 +261,15 @@ "experimental_settings_new_asset_list_title": "Aktiver eksperimentelt fotogitter", "experimental_settings_subtitle": "Brug på eget ansvar!", "experimental_settings_title": "Eksperimentelle", - "favorites": "Favorites", + "external_network": "External network", + "external_network_sheet_info": "When not on the preferred WiFi network, the app will connect to the server through the first of the below URLs it can reach, starting from top to bottom", + "favorites": "Favoritter", "favorites_page_no_favorites": "Ingen favoritter blev fundet", "favorites_page_title": "Favoritter", "filename_search": "File name or extension", "filter": "Filter", + "get_wifiname_error": "Could not get Wi-Fi name. Make sure you have granted the necessary permissions and are connected to a Wi-Fi network", + "grant_permission": "Grant permission", "haptic_feedback_switch": "Slå haptisk feedback til", "haptic_feedback_title": "Haptisk feedback", "header_settings_add_header_tip": "Add Header", @@ -274,8 +293,8 @@ "home_page_first_time_notice": "Hvis det er din første gang i appen, bedes du vælge en sikkerhedskopi af albummer så tidlinjen kan blive fyldt med billeder og videoer fra albummerne.", "home_page_share_err_local": "Kan ikke dele lokale elementer via link, springer over", "home_page_upload_err_limit": "Det er kun muligt at lave sikkerhedskopi af 30 elementer ad gangen. Springer over", - "ignore_icloud_photos": "Ignore iCloud photos", - "ignore_icloud_photos_description": "Photos that are stored on iCloud will not be uploaded to the Immich server", + "ignore_icloud_photos": "Ignorer iCloud-billeder", + "ignore_icloud_photos_description": "Billeder der er gemt på iCloud vil ikke blive uploadet til Immich-serveren", "image_saved_successfully": "Billede gemt", "image_viewer_page_state_provider_download_error": "Fejl ved download", "image_viewer_page_state_provider_download_started": "Download startet", @@ -283,7 +302,7 @@ "image_viewer_page_state_provider_share_error": "Delingsfejl", "invalid_date": "Invalid date", "invalid_date_format": "Invalid date format", - "library": "Library", + "library": "Bibliotek", "library_page_albums": "Albummer", "library_page_archive": "Arkiv", "library_page_device_albums": "Albummer på enhed", @@ -296,6 +315,10 @@ "library_page_sort_most_oldest_photo": "Ældste billede", "library_page_sort_most_recent_photo": "Seneste billede", "library_page_sort_title": "Albumtitel", + "local_network": "Local network", + "local_network_sheet_info": "The app will connect to the server through this URL when using the specified Wi-Fi network", + "location_permission": "Location permission", + "location_permission_content": "In order to use the auto-switching feature, Immich needs precise location permission so it can read the current WiFi network's name", "location_picker_choose_on_map": "Vælg på kort", "location_picker_latitude": "Breddegrad", "location_picker_latitude_error": "Indtast en gyldig breddegrad", @@ -364,7 +387,9 @@ "motion_photos_page_title": "Bevægelsesbilleder", "multiselect_grid_edit_date_time_err_read_only": "Kan ikke redigere datoen på kun læselige elementer. Springer over", "multiselect_grid_edit_gps_err_read_only": "Kan ikke redigere lokation af kun læselige elementer. Springer over", - "my_albums": "My albums", + "my_albums": "Mine albummer", + "networking_settings": "Networking", + "networking_subtitle": "Manage the server endpoint settings", "no_assets_to_show": "Ingen elementer at vise", "no_name": "Intet navn", "notification_permission_dialog_cancel": "Annuller", @@ -373,7 +398,7 @@ "notification_permission_list_tile_content": "Tillad at bruge notifikationer.", "notification_permission_list_tile_enable_button": "Slå notifikationer til", "notification_permission_list_tile_title": "Notifikationstilladelser", - "on_this_device": "On this device", + "on_this_device": "På denne enhed", "partner_list_user_photos": "{user}s billeder", "partner_list_view_all": "Se alle", "partner_page_add_partner": "Tilføj partner", @@ -385,8 +410,8 @@ "partner_page_stop_sharing_content": "{} vil ikke længere have adgang til dine billeder.", "partner_page_stop_sharing_title": "Stop med at dele dine billeder?", "partner_page_title": "Partner", - "partners": "Partners", - "people": "People", + "partners": "Partnere", + "people": "Personer", "permission_onboarding_back": "Tilbage", "permission_onboarding_continue_anyway": "Fortsæt alligevel", "permission_onboarding_get_started": "Kom i gang", @@ -397,7 +422,8 @@ "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.", - "places": "Places", + "places": "Placeringer", + "preferences_settings_subtitle": "Manage the app's preferences", "preferences_settings_title": "Præferencer", "profile_drawer_app_logs": "Log", "profile_drawer_client_out_of_date_major": "Mobilapp er forældet. Opdater venligst til den nyeste større version", @@ -410,11 +436,12 @@ "profile_drawer_settings": "Indstillinger", "profile_drawer_sign_out": "Log ud", "profile_drawer_trash": "Papirkurv", - "recently_added": "Recently added", + "recently_added": "Senest tilføjet", "recently_added_page_title": "Nyligt tilføjet", + "save": "Save", "save_to_gallery": "Gem til galleri", "scaffold_body_error_occurred": "Der opstod en fejl", - "search_albums": "Search albums", + "search_albums": "Søg i albummer", "search_bar_hint": "Søg i dine billeder", "search_filter_apply": "Tilføj filter", "search_filter_camera": "Kamera", @@ -457,6 +484,7 @@ "search_page_places": "Steder", "search_page_recently_added": "Nyligt tilføjet", "search_page_screenshots": "Skærmbilleder", + "search_page_search_photos_videos": "Search for your photos and videos", "search_page_selfies": "Selfier", "search_page_things": "Ting", "search_page_videos": "Videoer", @@ -469,6 +497,7 @@ "select_additional_user_for_sharing_page_suggestions": "Anbefalinger", "select_user_for_sharing_page_err_album": "Fejlede i at oprette et nyt album", "select_user_for_sharing_page_share_suggestions": "Anbefalinger", + "server_endpoint": "Server Endpoint", "server_info_box_app_version": "Applikationsversion", "server_info_box_latest_release": "Seneste version", "server_info_box_server_url": "Server URL", @@ -480,6 +509,7 @@ "setting_image_viewer_preview_title": "Indlæs forhåndsvisning af billedet", "setting_image_viewer_title": "Images", "setting_languages_apply": "Anvend", + "setting_languages_subtitle": "Change the app's language", "setting_languages_title": "Sprog", "setting_notifications_notify_failures_grace_period": "Giv besked om fejl med sikkerhedskopiering i baggrunden: {}", "setting_notifications_notify_hours": "{} timer", @@ -560,9 +590,9 @@ "shared_link_info_chip_upload": "Upload", "shared_link_manage_links": "Håndter delte links", "shared_link_public_album": "Offentligt album", - "shared_links": "Shared links", + "shared_links": "Delte links", "share_done": "Færdig", - "shared_with_me": "Shared with me", + "shared_with_me": "Delt med mig", "share_invite": "Inviter til album", "sharing_page_album": "Delt albums", "sharing_page_description": "Opret delte albummer for at dele billeder og video med personer på dit netværk.", @@ -594,7 +624,7 @@ "theme_setting_three_stage_loading_subtitle": "Tre-trins indlæsning kan øge ydeevnen, men kan ligeledes føre til højere netværksbelastning", "theme_setting_three_stage_loading_title": "Slå tre-trins indlæsning til", "translated_text_options": "Handlinger", - "trash": "Trash", + "trash": "Papirkurv", "trash_emptied": "Tømte papirkurven", "trash_page_delete": "Slet", "trash_page_delete_all": "Slet alt", @@ -612,14 +642,18 @@ "upload_dialog_info": "Vil du sikkerhedskopiere de(t) valgte element(er) til serveren?", "upload_dialog_ok": "Upload", "upload_dialog_title": "Upload element", + "use_current_connection": "use current connection", + "validate_endpoint_error": "Please enter a valid URL", "version_announcement_overlay_ack": "Accepter", "version_announcement_overlay_release_notes": "udgivelsesnoterne", "version_announcement_overlay_text_1": "Hej ven, der er en ny version af", "version_announcement_overlay_text_2": ". Besøg venligst ", "version_announcement_overlay_text_3": " for at sikre dig, at din dockercompose- og .env-fil er opdateret, så der undgås fejlkonfiguration, specielt hvis du bruger WatchTower eller lignede.", "version_announcement_overlay_title": "Ny serverversion er tilgængelig \uD83C\uDF89", - "videos": "Videos", + "videos": "Videoer", "viewer_remove_from_stack": "Fjern fra stak", "viewer_stack_use_as_main_asset": "Brug som hovedelement", - "viewer_unstack": "Fjern fra stak" + "viewer_unstack": "Fjern fra stak", + "wifi_name": "WiFi Name", + "your_wifi_name": "Your WiFi name" } \ No newline at end of file diff --git a/mobile/assets/i18n/de-DE.json b/mobile/assets/i18n/de-DE.json index b3452889fdecb..20c4baa5c0177 100644 --- a/mobile/assets/i18n/de-DE.json +++ b/mobile/assets/i18n/de-DE.json @@ -6,7 +6,8 @@ "action_common_save": "Speichern", "action_common_select": "Auswählen ", "action_common_update": "Aktualisieren", - "add_a_name": "Einen Namen hinzufügen", + "add_a_name": "Name hinzufügen", + "add_endpoint": "Endpunkt hinzufügen", "add_to_album_bottom_sheet_added": "Zu {album} hinzugefügt", "add_to_album_bottom_sheet_already_exists": "Bereits in {album}", "advanced_settings_log_level_title": "Log-Level: {}", @@ -65,7 +66,12 @@ "assets_restored_successfully": "{} Datei/en erfolgreich wiederhergestellt", "assets_trashed": "{} Datei/en gelöscht", "assets_trashed_from_server": "{} Datei/en vom Immich-Server gelöscht", + "asset_viewer_settings_subtitle": "Verwaltung der Einstellungen für den Galerie-Viewer", "asset_viewer_settings_title": "Fotoanzeige", + "automatic_endpoint_switching_subtitle": "Verbinden Sie sich lokal über ein bestimmtes WLAN, wenn es verfügbar ist, und verwenden Sie andere Verbindungsmöglichkeiten anderswo.", + "automatic_endpoint_switching_title": "Automatische URL-Umschaltung", + "background_location_permission": "Hintergrund Standortfreigabe", + "background_location_permission_content": "Um im Hintergrund zwischen den Netzwerken wechseln zu können, muss Immich *immer* Zugriff auf den genauen Standort haben, damit die App den Namen des WLAN-Netzwerks ermitteln kann", "backup_album_selection_page_albums_device": "Alben auf dem Gerät ({})", "backup_album_selection_page_albums_tap": "Einmalig das Album antippen um es zu sichern, doppelt antippen um es nicht mehr zu sichern.", "backup_album_selection_page_assets_scatter": "Elemente (Fotos / Videos) können sich über mehrere Alben verteilen. Daher können diese vor der Sicherung eingeschlossen oder ausgeschlossen werden.", @@ -131,6 +137,7 @@ "backup_manual_success": "Erfolgreich", "backup_manual_title": "Sicherungsstatus", "backup_options_page_title": "Sicherungsoptionen", + "backup_setting_subtitle": "Verwaltung der Upload-Einstellungen im Hintergrund und im Vordergrund", "cache_settings_album_thumbnails": "Vorschaubilder der Bibliothek ({} Elemente)", "cache_settings_clear_cache_button": "Zwischenspeicher löschen", "cache_settings_clear_cache_button_title": "Löscht den Zwischenspeicher der App. Dies wird die Leistungsfähigkeit der App deutlich einschränken, bis der Zwischenspeicher wieder aufgebaut wurde.", @@ -149,11 +156,16 @@ "cache_settings_tile_subtitle": "Lokalen Speicher verwalten", "cache_settings_tile_title": "Lokaler Speicher", "cache_settings_title": "Zwischenspeicher Einstellungen", + "cancel": "Abbrechen", + "change_display_order": "Change display order", "change_password_form_confirm_password": "Passwort bestätigen", "change_password_form_description": "Hallo {name}\n\nDas ist entweder das erste Mal dass du dich einloggst oder es wurde eine Anfrage zur Änderung deines Passwortes gestellt. Bitte gib das neue Passwort ein.", "change_password_form_new_password": "Neues Passwort", "change_password_form_password_mismatch": "Passwörter stimmen nicht überein", "change_password_form_reenter_new_password": "Passwort erneut eingeben", + "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.", "client_cert_dialog_msg_confirm": "OK", "client_cert_enter_password": "Passwort eingeben", "client_cert_import": "Importieren", @@ -199,6 +211,7 @@ "crop": "Zuschneiden", "curated_location_page_title": "Orte", "curated_object_page_title": "Dinge", + "current_server_address": "Aktuelle Server-Adresse", "daily_title_text_date": "E, dd MMM", "daily_title_text_date_year": "E, dd MMM, yyyy", "date_format": "E d. LLL y • hh:mm", @@ -235,6 +248,8 @@ "edit_date_time_dialog_timezone": "Zeitzone", "edit_image_title": "Bearbeiten", "edit_location_dialog_title": "Ort bearbeiten", + "enter_wifi_name": "WLAN-Name eingeben", + "error_change_sort_album": "Failed to change album sort order", "error_saving_image": "Fehler: {}", "exif_bottom_sheet_description": "Beschreibung hinzufügen...", "exif_bottom_sheet_details": "DETAILS", @@ -246,11 +261,15 @@ "experimental_settings_new_asset_list_title": "Experimentelles Fotogitter aktivieren", "experimental_settings_subtitle": "Benutzung auf eigene Gefahr!", "experimental_settings_title": "Experimentell", + "external_network": "Externes Netzwerk", + "external_network_sheet_info": "Wenn sich die App nicht im bevorzugten WLAN-Netzwerk befindet, verbindet sie sich mit dem Server über die erste der folgenden URLs, die sie erreichen kann (von oben nach unten)", "favorites": "Favoriten", "favorites_page_no_favorites": "Keine favorisierten Inhalte gefunden", "favorites_page_title": "Favoriten", "filename_search": "Dateiname oder Dateityp", "filter": "Filter", + "get_wifiname_error": "WLAN-Name konnte nicht ermittelt werden. Vergewissere dich, dass die erforderlichen Berechtigungen erteilt wurden und du mit einem WLAN-Netzwerk verbunden bist.\n", + "grant_permission": "Erlaubnis gewähren", "haptic_feedback_switch": "Haptisches Feedback aktivieren", "haptic_feedback_title": "Haptisches Feedback", "header_settings_add_header_tip": "Header hinzufügen", @@ -296,6 +315,10 @@ "library_page_sort_most_oldest_photo": "Ältestes Foto", "library_page_sort_most_recent_photo": "Neuestes Foto", "library_page_sort_title": "Titel des Albums", + "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", + "location_permission_content": "Um die automatische Umschaltfunktion nutzen zu können, benötigt Immich eine genaue Standortberechtigung, damit es den Namen des aktuellen WLAN-Netzwerks ermitteln kann", "location_picker_choose_on_map": "Auf der Karte auswählen", "location_picker_latitude": "Breitengrad", "location_picker_latitude_error": "Gültigen Breitengrad eingeben", @@ -365,6 +388,8 @@ "multiselect_grid_edit_date_time_err_read_only": "Das Datum und die Uhrzeit von schreibgeschützten Inhalten kann nicht verändert werden, überspringen...", "multiselect_grid_edit_gps_err_read_only": "Der Aufnahmeort von schreibgeschützten Inhalten kann nicht verändert werden, überspringen...", "my_albums": "Meine Alben", + "networking_settings": "Netzwerk", + "networking_subtitle": "Verwaltung von Server-Endpunkt-Einstellungen", "no_assets_to_show": "Keine Vorschau vorhanden", "no_name": "Kein Name", "notification_permission_dialog_cancel": "Abbrechen", @@ -398,6 +423,7 @@ "permission_onboarding_permission_limited": "Berechtigungen unzureichend. Um Immich das Sichern von ganzen Sammlungen zu ermöglichen, muss der Zugriff auf alle Fotos und Videos in den Einstellungen erlaubt werden.", "permission_onboarding_request": "Immich benötigt Berechtigung um auf deine Fotos und Videos zuzugreifen.", "places": "Orte", + "preferences_settings_subtitle": "App-Einstellungen verwalten", "preferences_settings_title": "Voreinstellungen", "profile_drawer_app_logs": "Logs", "profile_drawer_client_out_of_date_major": "Mobile-App ist veraltet. Bitte aktualisiere auf die neueste Major-Version.", @@ -412,9 +438,10 @@ "profile_drawer_trash": "Papierkorb", "recently_added": "Kürzlich hinzugefügt", "recently_added_page_title": "Zuletzt hinzugefügt", + "save": "Speichern", "save_to_gallery": "In Galerie speichern", "scaffold_body_error_occurred": "Ein Fehler ist aufgetreten", - "search_albums": "Suche Alben", + "search_albums": "nach Album suchen", "search_bar_hint": "Durchsuche deine Fotos", "search_filter_apply": "Filter anwenden", "search_filter_camera": "Kamera", @@ -457,6 +484,7 @@ "search_page_places": "Orte", "search_page_recently_added": "Zuletzt hinzugefügt", "search_page_screenshots": "Bildschirmfotos", + "search_page_search_photos_videos": "Nach deinen Fotos und Videos suchen", "search_page_selfies": "Selfies", "search_page_things": "Gegenstände und Tiere", "search_page_videos": "Videos", @@ -469,6 +497,7 @@ "select_additional_user_for_sharing_page_suggestions": "Vorschläge", "select_user_for_sharing_page_err_album": "Album konnte nicht erstellt werden", "select_user_for_sharing_page_share_suggestions": "Empfehlungen", + "server_endpoint": "Server-Endpunkt", "server_info_box_app_version": "App-Version", "server_info_box_latest_release": "Neueste Version", "server_info_box_server_url": "Server-URL", @@ -480,6 +509,7 @@ "setting_image_viewer_preview_title": "Vorschaubild laden", "setting_image_viewer_title": "Bilder", "setting_languages_apply": "Anwenden", + "setting_languages_subtitle": "App-Sprache ändern", "setting_languages_title": "Sprachen", "setting_notifications_notify_failures_grace_period": "Benachrichtigung bei Fehler/n in der Hintergrundsicherung: {}", "setting_notifications_notify_hours": "{} Stunden", @@ -612,6 +642,8 @@ "upload_dialog_info": "Willst du die ausgewählten Elemente auf dem Server sichern?", "upload_dialog_ok": "Hochladen", "upload_dialog_title": "Element hochladen", + "use_current_connection": "aktuelle Verbindung verwenden", + "validate_endpoint_error": "Bitte gib eine gültige URL ein", "version_announcement_overlay_ack": "Ich habe verstanden", "version_announcement_overlay_release_notes": "Änderungsprotokoll", "version_announcement_overlay_text_1": "Hallo mein Freund! Es gibt eine neue Version von", @@ -621,5 +653,7 @@ "videos": "Videos", "viewer_remove_from_stack": "Aus Stapel entfernen", "viewer_stack_use_as_main_asset": "An Stapelanfang", - "viewer_unstack": "Stapel aufheben" + "viewer_unstack": "Stapel aufheben", + "wifi_name": "WLAN-Name", + "your_wifi_name": "Dein WLAN-Name" } \ No newline at end of file diff --git a/mobile/assets/i18n/el-GR.json b/mobile/assets/i18n/el-GR.json index 5d8d077fab29f..47e945c1a9334 100644 --- a/mobile/assets/i18n/el-GR.json +++ b/mobile/assets/i18n/el-GR.json @@ -1,19 +1,20 @@ { - "action_common_back": "Back", + "action_common_back": "Πίσω", "action_common_cancel": "Ακύρωση", - "action_common_clear": "Clear", - "action_common_confirm": "Confirm", - "action_common_save": "Save", - "action_common_select": "Select", + "action_common_clear": "Εκκαθάριση", + "action_common_confirm": "Επιβεβαίωση", + "action_common_save": "Αποθήκευση", + "action_common_select": "Επιλογή", "action_common_update": "Ενημέρωση", - "add_a_name": "Add a name", + "add_a_name": "Πρόσθεση ονόματος", + "add_endpoint": "Add endpoint", "add_to_album_bottom_sheet_added": "Προστέθηκε στο {album}", "add_to_album_bottom_sheet_already_exists": "Ήδη στο {album}", "advanced_settings_log_level_title": "Επίπεδο καταγραφής: {}", "advanced_settings_prefer_remote_subtitle": "Μερικές συσκευές αργούν πολύ να φορτώσουν μικρογραφίες από αρχεία στη συσκευή. Ενεργοποιήστε αυτήν τη ρύθμιση για να φορτώνονται αντί αυτού απομακρυσμένες εικόνες.", "advanced_settings_prefer_remote_title": "Προτίμηση απομακρυσμένων εικόνων.", - "advanced_settings_proxy_headers_subtitle": "Define proxy headers Immich should send with each network request", - "advanced_settings_proxy_headers_title": "Proxy Headers", + "advanced_settings_proxy_headers_subtitle": "Καθορισμός κεφαλίδων διακομιστή μεσολάβησης που το Immich πρέπει να στέλνει με κάθε αίτημα δικτύου", + "advanced_settings_proxy_headers_title": "Κεφαλίδες διακομιστή μεσολάβησης", "advanced_settings_self_signed_ssl_subtitle": "Παρακάμπτει τον έλεγχο πιστοποιητικού SSL του διακομιστή. Απαραίτητο για αυτο-υπογεγραμμένα πιστοποιητικά.", "advanced_settings_self_signed_ssl_title": "Να επιτρέπονται αυτο-υπογεγραμμένα πιστοποιητικά SSL", "advanced_settings_tile_subtitle": "Ρυθμίσεις προχωρημένου χρήστη", @@ -22,13 +23,13 @@ "advanced_settings_troubleshooting_title": "Αντιμετώπιση προβλημάτων", "album_info_card_backup_album_excluded": "ΕΞΑΙΡΟΥΜΕΝΟ", "album_info_card_backup_album_included": "ΣΥΜΠΕΡΙΛΑΜΒΑΝΟΜΕΝΟ", - "albums": "Albums", + "albums": "Άλμπουμ", "album_thumbnail_card_item": "1 αντικείμενο", "album_thumbnail_card_items": "{} αντικείμενα", "album_thumbnail_card_shared": "· Κοινόχρηστο", "album_thumbnail_owned": "Δικό μου", "album_thumbnail_shared_by": "Κοινοποιημένο από {}", - "album_viewer_appbar_delete_confirm": "Are you sure you want to delete this album from your account?", + "album_viewer_appbar_delete_confirm": "Είστε βέβαιοι ότι θέλετε να διαγράψετε αυτό το άλμπουμ από τον λογαριασμό σας;", "album_viewer_appbar_share_delete": "Διαγραφή άλμπουμ", "album_viewer_appbar_share_err_delete": "Αποτυχία διαγραφής άλμπουμ", "album_viewer_appbar_share_err_leave": "Αποτυχία αποχώρησης από άλμπουμ", @@ -38,34 +39,39 @@ "album_viewer_appbar_share_remove": "Αφαίρεση από άλμπουμ", "album_viewer_appbar_share_to": "Κοινοποίηση σε", "album_viewer_page_share_add_users": "Προσθήκη χρηστών", - "all": "All", + "all": "Όλα", "all_people_page_title": "Άτομα", "all_videos_page_title": "Βίντεο", "app_bar_signout_dialog_content": "Είστε βέβαιοι ότι θέλετε να αποσυνδεθείτε;", "app_bar_signout_dialog_ok": "Ναι", "app_bar_signout_dialog_title": "Αποσύνδεση", - "archived": "Archived", + "archived": "Αρχείο", "archive_page_no_archived_assets": "Δε βρέθηκαν αρχειοθετημένα στοιχεία", - "archive_page_title": "Αρχειοθέτηση ({})", - "asset_action_delete_err_read_only": "Cannot delete read only asset(s), skipping", - "asset_action_share_err_offline": "Cannot fetch offline asset(s), skipping", - "asset_list_group_by_sub_title": "Group by", + "archive_page_title": "Αρχείο ({})", + "asset_action_delete_err_read_only": "Δεν είναι δυνατή η διαγραφή στοιχείων μόνο για ανάγνωση, παραλείπεται", + "asset_action_share_err_offline": "Δεν είναι δυνατή η ανάκτηση στοιχείων εκτός σύνδεσης, παραλείπεται", + "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": "Μήνας", "asset_list_layout_settings_group_by_month_day": "Μήνας + ημέρα", - "asset_list_layout_sub_title": "Layout", + "asset_list_layout_sub_title": "Διάταξη", "asset_list_settings_subtitle": "Ρυθμίσεις διάταξης πλέγματος φωτογραφιών", "asset_list_settings_title": "Πλέγμα φωτογραφιών", - "asset_restored_successfully": "Asset restored successfully", - "assets_deleted_permanently": "{} asset(s) deleted permanently", - "assets_deleted_permanently_from_server": "{} asset(s) deleted permanently from the Immich server", - "assets_removed_permanently_from_device": "{} asset(s) removed permanently from your device", - "assets_restored_successfully": "{} asset(s) restored successfully", - "assets_trashed": "{} asset(s) trashed", - "assets_trashed_from_server": "{} asset(s) trashed from the Immich server", - "asset_viewer_settings_title": "Asset Viewer", + "asset_restored_successfully": "Το στοιχείο αποκαταστάθηκε με επιτυχία", + "assets_deleted_permanently": "{} στοιχείο(α) διαγράφηκαν οριστικά", + "assets_deleted_permanently_from_server": "{} στοιχείο(α) διαγράφηκαν οριστικά από τον διακομιστή Immich", + "assets_removed_permanently_from_device": "{} στοιχεία καταργήθηκαν οριστικά από τη συσκευή σας", + "assets_restored_successfully": "{} στοιχεία αποκαταστάθηκαν με επιτυχία", + "assets_trashed": "{} στοιχεία μεταφέρθηκαν στον κάδο απορριμμάτων", + "assets_trashed_from_server": "{} στοιχεία μεταφέρθηκαν στον κάδο απορριμμάτων από τον διακομιστή Immich", + "asset_viewer_settings_subtitle": "Manage your gallery viewer settings", + "asset_viewer_settings_title": "Προβολή Στοιχείων", + "automatic_endpoint_switching_subtitle": "Connect locally over designated Wi-Fi when available and use alternative connections elsewhere", + "automatic_endpoint_switching_title": "Automatic URL switching", + "background_location_permission": "Background location permission", + "background_location_permission_content": "In order to switch networks when running in the background, Immich must *always* have precise location access so the app can read the Wi-Fi network's name", "backup_album_selection_page_albums_device": "Άλμπουμ στη συσκευή ({})", "backup_album_selection_page_albums_tap": "Πάτημα για συμπερίληψη, διπλό πάτημα για εξαίρεση", "backup_album_selection_page_assets_scatter": "Τα στοιχεία μπορεί να διασκορπιστούν σε πολλά άλμπουμ. Έτσι, τα άλμπουμ μπορούν να περιληφθούν ή να εξαιρεθούν κατά τη διαδικασία δημιουργίας αντιγράφων ασφαλείας.", @@ -103,7 +109,7 @@ "backup_controller_page_cancel": "Ακύρωση", "backup_controller_page_created": "Δημιουργήθηκε στις: {}", "backup_controller_page_desc_backup": "Ενεργοποιήστε την δημιουργία αντιγράφων ασφαλείας στο προσκήνιο για αυτόματη μεταφόρτωση νέων στοιχείων στον διακομιστή όταν ανοίγετε την εφαρμογή.", - "backup_controller_page_excluded": "Εξαιρεμένα:", + "backup_controller_page_excluded": "Εξαιρούμενα:", "backup_controller_page_failed": "Αποτυχημένα ({})", "backup_controller_page_filename": "Όνομα αρχείου: {} [{}]", "backup_controller_page_id": "ID: {}", @@ -130,7 +136,8 @@ "backup_manual_in_progress": "Μεταφόρτωση σε εξέλιξη. Δοκιμάστε αργότερα", "backup_manual_success": "Επιτυχία", "backup_manual_title": "Κατάσταση μεταφόρτωσης", - "backup_options_page_title": "Backup options", + "backup_options_page_title": "Επιλογές αντιγράφων ασφαλείας", + "backup_setting_subtitle": "Manage background and foreground upload settings", "cache_settings_album_thumbnails": "Μικρογραφίες σελίδας βιβλιοθήκης ({} στοιχεία)", "cache_settings_clear_cache_button": "Εκκαθάριση προσωρινής μνήμης", "cache_settings_clear_cache_button_title": "Καθαρίζει τη προσωρινή μνήμη της εφαρμογής. Αυτό θα επηρεάσει σημαντικά την απόδοση της εφαρμογής μέχρι να αναδημιουργηθεί η προσωρινή μνήμη.", @@ -144,41 +151,46 @@ "cache_settings_statistics_shared": "Μικρογραφίες κοινοποιημένου άλμπουμ", "cache_settings_statistics_thumbnail": "Μικρογραφίες", "cache_settings_statistics_title": "Χρήση προσωρινής μνήμης", - "cache_settings_subtitle": "Χειριστείτε τη συμπεριφορά της προσωρινής μνήμης της εφαρμογής Immich για κινητά τηλέφωνα", + "cache_settings_subtitle": "Διαχείρηση συμπεριφοράς της προσωρινής μνήμης", "cache_settings_thumbnail_size": "Μέγεθος προσωρινής μνήμης μικρογραφιών ({} στοιχεία)", "cache_settings_tile_subtitle": "Χειριστείτε τη συμπεριφορά της τοπικής αποθήκευσης", "cache_settings_tile_title": "Τοπική Αποθήκευση", "cache_settings_title": "Ρυθμίσεις Προσωρινής Μνήμης", + "cancel": "Cancel", + "change_display_order": "Change display order", "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": "Επανεισαγωγή Νέου Κωδικού", - "client_cert_dialog_msg_confirm": "OK", - "client_cert_enter_password": "Enter Password", - "client_cert_import": "Import", - "client_cert_import_success_msg": "Client certificate is imported", - "client_cert_invalid_msg": "Invalid certificate file or wrong password", - "client_cert_remove": "Remove", - "client_cert_remove_msg": "Client certificate is removed", - "client_cert_subtitle": "Supports PKCS12 (.p12, .pfx) format only. Certificate Import/Remove is available only before login", - "client_cert_title": "SSL Client Certificate", + "check_corrupt_asset_backup": "Check for corrupt asset backups", + "check_corrupt_asset_backup_button": "Perform check", + "check_corrupt_asset_backup_description": "Run this check only over Wi-Fi and once all assets have been backed-up. The procedure might take a few minutes.", + "client_cert_dialog_msg_confirm": "ΟΚ", + "client_cert_enter_password": "Εισαγάγετε κωδικό πρόσβασης", + "client_cert_import": "Εισαγωγή", + "client_cert_import_success_msg": "Το πιστοποιητικό πελάτη εισάγεται", + "client_cert_invalid_msg": "Μη έγκυρο αρχείο πιστοποιητικού ή λάθος κωδικός πρόσβασης", + "client_cert_remove": "Αφαίρεση", + "client_cert_remove_msg": "Το πιστοποιητικό πελάτη καταργήθηκε", + "client_cert_subtitle": "Υποστηρίζει μόνο τη μορφή PKCS12 (.p12, .pfx). Η Εισαγωγή/Αφαίρεση πιστοποιητικού είναι διαθέσιμη μόνο πριν από τη σύνδεση", + "client_cert_title": "Πιστοποιητικό πελάτη SSL", "common_add_to_album": "Προσθήκη στο άλμπουμ", "common_change_password": "Αλλαγή Κωδικού", "common_create_new_album": "Δημιουργία νέου άλμπουμ", "common_server_error": "Ελέγξτε τη σύνδεσή σας, βεβαιωθείτε ότι ο διακομιστής είναι προσβάσιμος και ότι οι εκδόσεις της εφαρμογής/διακομιστή είναι συμβατές.", "common_shared": "Κοινόχρηστο", - "contextual_search": "Sunrise on the beach", + "contextual_search": "Ανατολή στην παραλία", "control_bottom_app_bar_add_to_album": "Προσθήκη στο άλμπουμ", "control_bottom_app_bar_album_info": "{} αντικείμενα", "control_bottom_app_bar_album_info_shared": "{} αντικείμενα · Κοινόχρηστα", - "control_bottom_app_bar_archive": "Αρχειοθέτηση", + "control_bottom_app_bar_archive": "Αρχείο", "control_bottom_app_bar_create_new_album": "Δημιουργία νέου άλμπουμ", "control_bottom_app_bar_delete": "Διαγραφή", "control_bottom_app_bar_delete_from_immich": "Διαγραφή από το Immich", "control_bottom_app_bar_delete_from_local": "Διαγραφή από τη συσκευή", - "control_bottom_app_bar_download": "Download", - "control_bottom_app_bar_edit": "Edit", + "control_bottom_app_bar_download": "Λήψη", + "control_bottom_app_bar_edit": "Επεξεργασία", "control_bottom_app_bar_edit_location": "Επεξεργασία Τοποθεσίας", "control_bottom_app_bar_edit_time": "Επεξεργασία Ημερομηνίας & Ώρας", "control_bottom_app_bar_favorite": "Προσθήκη στα αγαπημένα", @@ -189,16 +201,17 @@ "control_bottom_app_bar_unarchive": "Αναίρεση αρχειοθέτησης", "control_bottom_app_bar_unfavorite": "Κατάργηση από τα αγαπημένα", "control_bottom_app_bar_upload": "Μεταφόρτωση", - "create_album": "Create album", + "create_album": "Δημιουργία άλμπουμ", "create_album_page_untitled": "Χωρίς τίτλο", - "create_new": "CREATE NEW", + "create_new": "ΔΗΜΙΟΥΡΓΙΑ ΝΕΟΥ", "create_shared_album_page_create": "Δημιουργία", "create_shared_album_page_share": "Κοινοποίηση", "create_shared_album_page_share_add_assets": "ΠΡΟΣΘΗΚΗ ΣΤΟΙΧΕΙΩΝ", "create_shared_album_page_share_select_photos": "Επιλέξτε Φωτογραφίες", - "crop": "Crop", + "crop": "Αποκοπή", "curated_location_page_title": "Τοποθεσίες", "curated_object_page_title": "Πράγματα", + "current_server_address": "Current server address", "daily_title_text_date": "Ε, MMM dd", "daily_title_text_date_year": "Ε, MMM dd, yyyy", "date_format": "Ε, LLL d, y • h:mm a", @@ -208,174 +221,186 @@ "delete_dialog_alert_remote": "Αυτά τα αντικείμενα θα διαγραφούν οριστικά από τον διακομιστή Immich", "delete_dialog_cancel": "Ακύρωση", "delete_dialog_ok": "Διαγραφή", - "delete_dialog_ok_force": "Delete Anyway", + "delete_dialog_ok_force": "Διαγραφή όπως και να έχει", "delete_dialog_title": "Οριστική Διαγραφή", - "delete_local_dialog_ok_backed_up_only": "Delete Backed Up Only", - "delete_local_dialog_ok_force": "Delete Anyway", + "delete_local_dialog_ok_backed_up_only": "Διαγραφή μόνο των αντιγράφων ασφαλείας", + "delete_local_dialog_ok_force": "Διαγραφή όπως και να έχει", "delete_shared_link_dialog_content": "Σίγουρα θέλετε να διαγράψετε αυτόν τον κοινοποιημένο σύνδεσμο;", "delete_shared_link_dialog_title": "Διαγραφή Κοινοποιημένου Συνδέσμου", "description_input_hint_text": "Προσθήκη περιγραφής...", "description_input_submit_error": "Σφάλμα κατά την ενημέρωση της περιγραφής, ελέγξτε το αρχείο καταγραφής για περισσότερες λεπτομέρειες", - "download_canceled": "Download canceled", - "download_complete": "Download complete", - "download_enqueue": "Download enqueued", - "download_error": "Download Error", - "download_failed": "Download failed", - "download_filename": "file: {}", - "download_finished": "Download finished", - "downloading": "Downloading...", - "downloading_media": "Downloading media", - "download_notfound": "Download not found", - "download_paused": "Download paused", - "download_started": "Download started", - "download_sucess": "Download success", - "download_sucess_android": "The media has been downloaded to DCIM/Immich", - "download_waiting_to_retry": "Waiting to retry", + "download_canceled": "Η λήψη ακυρώθηκε", + "download_complete": "Η λήψη ολοκληρώθηκε", + "download_enqueue": "Η λήψη τέθηκε σε ουρά", + "download_error": "Σφάλμα λήψης", + "download_failed": "Η λήψη απέτυχε", + "download_filename": "αρχείο: {}", + "download_finished": "Η λήψη ολοκληρώθηκε", + "downloading": "Λήψη...", + "downloading_media": "Λήψη πολυμέσων", + "download_notfound": "Το αρχείο δεν βρέθηκε", + "download_paused": "Η λήψη διακόπηκε", + "download_started": "Η λήψη ξεκίνησε", + "download_sucess": "Επιτυχία λήψης", + "download_sucess_android": "Το μέσο έχει ληφθεί στο DCIM/Immich", + "download_waiting_to_retry": "Αναμονή για επανάληψη", "edit_date_time_dialog_date_time": "Ημερομηνία και Ώρα", "edit_date_time_dialog_timezone": "Ζώνη ώρας", - "edit_image_title": "Edit", + "edit_image_title": "Επεξεργασία", "edit_location_dialog_title": "Τοποθεσία", - "error_saving_image": "Error: {}", + "enter_wifi_name": "Enter WiFi name", + "error_change_sort_album": "Failed to change album sort order", + "error_saving_image": "Σφάλμα: {}", "exif_bottom_sheet_description": "Προσθήκη Περιγραφής...", "exif_bottom_sheet_details": "ΛΕΠΤΟΜΕΡΕΙΕΣ", "exif_bottom_sheet_location": "ΤΟΠΟΘΕΣΙΑ", "exif_bottom_sheet_location_add": "Προσθήκη τοποθεσίας", - "exif_bottom_sheet_people": "PEOPLE", - "exif_bottom_sheet_person_add_person": "Add name", + "exif_bottom_sheet_people": "ΑΝΘΡΩΠΟΙ", + "exif_bottom_sheet_person_add_person": "Προσθήκη ονόματος", "experimental_settings_new_asset_list_subtitle": "Σε εξέλιξη", "experimental_settings_new_asset_list_title": "Ενεργοποίηση πειραματικού πλέγματος φωτογραφιών", "experimental_settings_subtitle": "Χρησιμοποιείτε με δική σας ευθύνη!", "experimental_settings_title": "Πειραματικό", - "favorites": "Favorites", + "external_network": "External network", + "external_network_sheet_info": "When not on the preferred WiFi network, the app will connect to the server through the first of the below URLs it can reach, starting from top to bottom", + "favorites": "Αγαπημένα", "favorites_page_no_favorites": "Δεν βρέθηκαν αγαπημένα στοιχεία", "favorites_page_title": "Αγαπημένα", - "filename_search": "File name or extension", - "filter": "Filter", - "haptic_feedback_switch": "Enable haptic feedback", - "haptic_feedback_title": "Haptic Feedback", - "header_settings_add_header_tip": "Add Header", - "header_settings_field_validator_msg": "Value cannot be empty", - "header_settings_header_name_input": "Header name", - "header_settings_header_value_input": "Header value", - "header_settings_page_title": "Proxy Headers", - "headers_settings_tile_subtitle": "Define proxy headers the app should send with each network request", - "headers_settings_tile_title": "Custom proxy headers", + "filename_search": "Όνομα αρχείου ή επέκταση", + "filter": "Φίλτρο", + "get_wifiname_error": "Could not get Wi-Fi name. Make sure you have granted the necessary permissions and are connected to a Wi-Fi network", + "grant_permission": "Grant permission", + "haptic_feedback_switch": "Ενεργοποίηση απτικής ανάδρασης", + "haptic_feedback_title": "Απτική Ανάδραση", + "header_settings_add_header_tip": "Προσθήκη Κεφαλίδας", + "header_settings_field_validator_msg": "Η τιμή δεν μπορεί να είναι κενή", + "header_settings_header_name_input": "Όνομα κεφαλίδας", + "header_settings_header_value_input": "Τιμή κεφαλίδας", + "header_settings_page_title": "Κεφαλίδες διακομιστή μεσολάβησης", + "headers_settings_tile_subtitle": "Καθορίστε τις κεφαλίδες διακομιστή μεσολάβησης που θα πρέπει να στέλνει η εφαρμογή με κάθε αίτημα δικτύου", + "headers_settings_tile_title": "Προσαρμοσμένες κεφαλίδες διακομιστή μεσολάβησης", "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": "Can not add partner assets to an album yet, skipping", - "home_page_archive_err_local": "Can not archive local assets yet, skipping", - "home_page_archive_err_partner": "Can not archive partner assets, skipping", - "home_page_building_timeline": "Building the timeline", - "home_page_delete_err_partner": "Can not delete partner assets, skipping", - "home_page_delete_remote_err_local": "Local assets in delete remote selection, skipping", - "home_page_favorite_err_local": "Can not favorite local assets yet, skipping", - "home_page_favorite_err_partner": "Can not favorite partner assets yet, skipping", - "home_page_first_time_notice": "If this is your first time using the app, please make sure to choose a backup album(s) so that the timeline can populate photos and videos in the album(s).", - "home_page_share_err_local": "Can not share local assets via link, skipping", - "home_page_upload_err_limit": "Can only upload a maximum of 30 assets at a time, skipping", - "ignore_icloud_photos": "Ignore iCloud photos", - "ignore_icloud_photos_description": "Photos that are stored on iCloud will not be uploaded to the Immich server", - "image_saved_successfully": "Image saved", - "image_viewer_page_state_provider_download_error": "Download Error", - "image_viewer_page_state_provider_download_started": "Download Started", - "image_viewer_page_state_provider_download_success": "Download Success", - "image_viewer_page_state_provider_share_error": "Share Error", - "invalid_date": "Invalid date", - "invalid_date_format": "Invalid date format", - "library": "Library", - "library_page_albums": "Albums", - "library_page_archive": "Archive", - "library_page_device_albums": "Albums on Device", - "library_page_favorites": "Favorites", - "library_page_new_album": "New album", - "library_page_sharing": "Sharing", - "library_page_sort_asset_count": "Number of assets", - "library_page_sort_created": "Created date", - "library_page_sort_last_modified": "Last modified", - "library_page_sort_most_oldest_photo": "Oldest photo", - "library_page_sort_most_recent_photo": "Most recent photo", - "library_page_sort_title": "Album title", - "location_picker_choose_on_map": "Choose on map", - "location_picker_latitude": "Latitude", - "location_picker_latitude_error": "Enter a valid latitude", - "location_picker_latitude_hint": "Enter your latitude here", - "location_picker_longitude": "Longitude", - "location_picker_longitude_error": "Enter a valid longitude", - "location_picker_longitude_hint": "Enter your longitude here", + "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_share_err_local": "Δεν είναι δυνατή η κοινή χρήση τοπικών στοιχείων μέσω συνδέσμου, παραλείπεται", + "home_page_upload_err_limit": "Μπορείτε να ανεβάσετε μόνο 30 στοιχεία κάθε φορά, παραλείπεται", + "ignore_icloud_photos": "Αγνοήστε τις φωτογραφίες iCloud", + "ignore_icloud_photos_description": "Οι φωτογραφίες που είναι αποθηκευμένες στο iCloud δεν θα μεταφορτωθούν στον διακομιστή Immich", + "image_saved_successfully": "Η εικόνα αποθηκεύτηκε", + "image_viewer_page_state_provider_download_error": "Σφάλμα Λήψης", + "image_viewer_page_state_provider_download_started": "Ξεκίνησε Λήψη", + "image_viewer_page_state_provider_download_success": "Επιτυχία Λήψης", + "image_viewer_page_state_provider_share_error": "Σφάλμα Κοινής Χρήσης", + "invalid_date": "Μη έγκυρη ημερομηνία", + "invalid_date_format": "Μη έγκυρη μορφή ημερομηνίας", + "library": "Βιβλιοθήκη", + "library_page_albums": "Άλμπουμ", + "library_page_archive": "Αρχείο", + "library_page_device_albums": "Άλμπουμ στη Συσκευή", + "library_page_favorites": "Αγαπημένα", + "library_page_new_album": "Νέο άλμπουμ", + "library_page_sharing": "Κοινή Χρήση", + "library_page_sort_asset_count": "Αριθμός στοιχείων", + "library_page_sort_created": "Ημερομηνία δημιουργίας", + "library_page_sort_last_modified": "Τελευταία τροποποίηση", + "library_page_sort_most_oldest_photo": "Πιο παλιά φωτογραφία", + "library_page_sort_most_recent_photo": "Πιο πρόσφατη φωτογραφία", + "library_page_sort_title": "Τίτλος άλμπουμ", + "local_network": "Local network", + "local_network_sheet_info": "The app will connect to the server through this URL when using the specified Wi-Fi network", + "location_permission": "Location permission", + "location_permission_content": "In order to use the auto-switching feature, Immich needs precise location permission so it can read the current WiFi network's name", + "location_picker_choose_on_map": "Επιλέξτε στο χάρτη", + "location_picker_latitude": "Γεωγραφικό πλάτος", + "location_picker_latitude_error": "Εισαγάγετε ένα έγκυρο γεωγραφικό πλάτος", + "location_picker_latitude_hint": "Εισαγάγετε το γεωγραφικό πλάτος σας εδώ", + "location_picker_longitude": "Γεωγραφικό μήκος", + "location_picker_longitude_error": "Εισαγάγετε ένα έγκυρο γεωγραφικό μήκος", + "location_picker_longitude_hint": "Εισαγάγετε εδώ το γεωγραφικό σας μήκος", "login_disabled": "Η σύνδεση έχει απενεργοποιηθεί", - "login_form_api_exception": "API exception. Please check the server URL and try again.", - "login_form_back_button_text": "Back", - "login_form_button_text": "Login", - "login_form_email_hint": "youremail@email.com", - "login_form_endpoint_hint": "http://your-server-ip:port/api", - "login_form_endpoint_url": "Server Endpoint URL", - "login_form_err_http": "Please specify http:// or https://", - "login_form_err_invalid_email": "Invalid Email", - "login_form_err_invalid_url": "Invalid URL", - "login_form_err_leading_whitespace": "Leading whitespace", - "login_form_err_trailing_whitespace": "Trailing whitespace", - "login_form_failed_get_oauth_server_config": "Error logging using OAuth, check server URL", - "login_form_failed_get_oauth_server_disable": "OAuth feature is not available on this server", - "login_form_failed_login": "Error logging you in, check server URL, email and password", - "login_form_handshake_exception": "There was an Handshake Exception with the server. Enable self-signed certificate support in the settings if you are using a self-signed certificate.", + "login_form_api_exception": "Εξαίρεση API. Ελέγξτε τη διεύθυνση URL του διακομιστή και δοκιμάστε ξανά.", + "login_form_back_button_text": "Πίσω", + "login_form_button_text": "Σύνδεση", + "login_form_email_hint": "to-email-sou@email.com", + "login_form_endpoint_hint": "http://ip-tou-server-sou:porta/api", + "login_form_endpoint_url": "URL τελικού σημείου διακομιστή", + "login_form_err_http": "Προσδιορίστε http:// ή https://", + "login_form_err_invalid_email": "Μη έγκυρο 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 του διακομιστή, το email και τον κωδικό πρόσβασης", + "login_form_handshake_exception": "Υπήρξε σφάλμα χειραψίας με τον διακομιστή. Ενεργοποιήστε την υποστήριξη αυτο-υπογεγραμμένου πιστοποιητικού στις ρυθμίσεις εάν χρησιμοποιείτε αυτο-υπογεγραμμένο πιστοποιητικό.", "login_form_label_email": "Email", - "login_form_label_password": "Password", - "login_form_next_button": "Next", - "login_form_password_hint": "password", - "login_form_save_login": "Stay logged in", - "login_form_server_empty": "Enter a server URL.", - "login_form_server_error": "Could not connect to server.", - "login_password_changed_error": "There was an error updating your password", - "login_password_changed_success": "Password updated successfully", - "map_assets_in_bound": "{} photo", - "map_assets_in_bounds": "{} photos", - "map_cannot_get_user_location": "Cannot get user's location", - "map_location_dialog_cancel": "Cancel", - "map_location_dialog_yes": "Yes", - "map_location_picker_page_use_location": "Use this location", - "map_location_service_disabled_content": "Location service needs to be enabled to display assets from your current location. Do you want to enable it now?", - "map_location_service_disabled_title": "Location Service disabled", - "map_no_assets_in_bounds": "No photos in this area", - "map_no_location_permission_content": "Location permission is needed to display assets from your current location. Do you want to allow it now?", - "map_no_location_permission_title": "Location Permission denied", - "map_settings_dark_mode": "Dark mode", - "map_settings_date_range_option_all": "All", - "map_settings_date_range_option_day": "Past 24 hours", - "map_settings_date_range_option_days": "Past {} days", - "map_settings_date_range_option_year": "Past year", - "map_settings_date_range_option_years": "Past {} years", - "map_settings_dialog_cancel": "Cancel", - "map_settings_dialog_save": "Save", - "map_settings_dialog_title": "Map Settings", - "map_settings_include_show_archived": "Include Archived", - "map_settings_include_show_partners": "Include Partners", - "map_settings_only_relative_range": "Date range", - "map_settings_only_show_favorites": "Show Favorite Only", - "map_settings_theme_settings": "Map Theme", - "map_zoom_to_see_photos": "Zoom out to see photos", - "memories_all_caught_up": "All caught up", - "memories_check_back_tomorrow": "Check back tomorrow for more memories", - "memories_start_over": "Start Over", - "memories_swipe_to_close": "Swipe up to close", - "memories_year_ago": "A year ago", - "memories_years_ago": "{} years ago", - "monthly_title_text_date_format": "MMMM y", - "motion_photos_page_title": "Motion Photos", - "multiselect_grid_edit_date_time_err_read_only": "Cannot edit date of read only asset(s), skipping", - "multiselect_grid_edit_gps_err_read_only": "Cannot edit location of read only asset(s), skipping", - "my_albums": "My albums", - "no_assets_to_show": "No assets to show", - "no_name": "No name", - "notification_permission_dialog_cancel": "Cancel", - "notification_permission_dialog_content": "To enable notifications, go to Settings and select allow.", - "notification_permission_dialog_settings": "Settings", - "notification_permission_list_tile_content": "Grant permission to enable notifications.", - "notification_permission_list_tile_enable_button": "Enable Notifications", - "notification_permission_list_tile_title": "Notification Permission", - "on_this_device": "On this device", - "partner_list_user_photos": "{user}'s photos", - "partner_list_view_all": "View all", + "login_form_label_password": "Κωδικός Πρόσβασης", + "login_form_next_button": "Επόμενος", + "login_form_password_hint": "κωδικός πρόσβασης", + "login_form_save_login": "Μείνετε συνδεδεμένοι", + "login_form_server_empty": "Εισαγάγετε μια διεύθυνση URL διακομιστή.", + "login_form_server_error": "Δεν ήταν δυνατή η σύνδεση με τον διακομιστή.", + "login_password_changed_error": "Παρουσιάστηκε σφάλμα κατά την ενημέρωση του κωδικού πρόσβασής σας", + "login_password_changed_success": "Ο κωδικός πρόσβασης ενημερώθηκε με επιτυχία", + "map_assets_in_bound": "{} φωτογραφία", + "map_assets_in_bounds": "{} φωτογραφίες", + "map_cannot_get_user_location": "Δεν είναι δυνατή η λήψη της τοποθεσίας του χρήστη", + "map_location_dialog_cancel": "Ακύρωση", + "map_location_dialog_yes": "Ναι", + "map_location_picker_page_use_location": "Χρησιμοποιήστε αυτήν την τοποθεσία", + "map_location_service_disabled_content": "Η υπηρεσία τοποθεσίας πρέπει να είναι ενεργοποιημένη για την εμφάνιση στοιχείων από την τρέχουσα τοποθεσία σας. Θέλετε να το ενεργοποιήσετε τώρα;", + "map_location_service_disabled_title": "Η υπηρεσία τοποθεσίας απενεργοποιήθηκε", + "map_no_assets_in_bounds": "Δεν υπάρχουν φωτογραφίες σε αυτήν την περιοχή", + "map_no_location_permission_content": "Απαιτείται άδεια τοποθεσίας για την εμφάνιση στοιχείων από την τρέχουσα τοποθεσία σας. Θέλετε να το επιτρέψετε τώρα;", + "map_no_location_permission_title": "Η άδεια τοποθεσίας απορρίφθηκε", + "map_settings_dark_mode": "Σκοτεινή λειτουργία", + "map_settings_date_range_option_all": "Όλοι", + "map_settings_date_range_option_day": "Προηγούμενες 24 ώρες", + "map_settings_date_range_option_days": "Προηγούμενες {} ημέρες", + "map_settings_date_range_option_year": "Προηγούμενο έτος", + "map_settings_date_range_option_years": "Προηγούμενα {} έτη", + "map_settings_dialog_cancel": "Ακύρωση", + "map_settings_dialog_save": "Αποθήκευση", + "map_settings_dialog_title": "Ρυθμίσεις Χάρτη", + "map_settings_include_show_archived": "Συμπεριλάβετε Αρχειοθετημένα", + "map_settings_include_show_partners": "Συμπεριλάβετε Συντρόφους", + "map_settings_only_relative_range": "Εύρος ημερομηνιών", + "map_settings_only_show_favorites": "Εμφάνιση μόνο αγαπημένων", + "map_settings_theme_settings": "Θέμα χάρτη", + "map_zoom_to_see_photos": "Σμικρύνετε για να δείτε φωτογραφίες", + "memories_all_caught_up": "Συγχρονισμένα", + "memories_check_back_tomorrow": "Ελέγξτε ξανά αύριο για περισσότερες αναμνήσεις", + "memories_start_over": "Ξεκινήστε από την αρχή", + "memories_swipe_to_close": "Σύρετε προς τα πάνω για να κλείσετε", + "memories_year_ago": "Πριν ένα χρόνο", + "memories_years_ago": "Πριν από {} χρόνια", + "monthly_title_text_date_format": "ΜΜΜΜ y", + "motion_photos_page_title": "Κινούμενες Φωτογραφίες", + "multiselect_grid_edit_date_time_err_read_only": "Δεν είναι δυνατή η επεξεργασία της ημερομηνίας των στοιχείων μόνο για ανάγνωση, παραλείπεται", + "multiselect_grid_edit_gps_err_read_only": "Δεν είναι δυνατή η επεξεργασία της τοποθεσίας των στοιχείων μόνο για ανάγνωση, παραλείπεται", + "my_albums": "Τα άλμπουμ μου", + "networking_settings": "Networking", + "networking_subtitle": "Manage the server endpoint settings", + "no_assets_to_show": "Δεν υπάρχουν στοιχεία προς εμφάνιση", + "no_name": "Κανένα όνομα", + "notification_permission_dialog_cancel": "Ακύρωση", + "notification_permission_dialog_content": "Για να ενεργοποιήσετε τις ειδοποιήσεις, μεταβείτε στις Ρυθμίσεις και επιλέξτε να επιτρέπεται.", + "notification_permission_dialog_settings": "Ρυθμίσεις", + "notification_permission_list_tile_content": "Παραχωρήστε άδεια για ενεργοποίηση ειδοποιήσεων.", + "notification_permission_list_tile_enable_button": "Ενεργοποίηση Ειδοποιήσεων", + "notification_permission_list_tile_title": "Άδεια Ειδοποίησης", + "on_this_device": "Σε αυτή τη συσκευή", + "partner_list_user_photos": "Φωτογραφίες του/της {user}", + "partner_list_view_all": "Προβολή όλων", "partner_page_add_partner": "Προσθήκη συντρόφου", "partner_page_empty_message": "Οι φωτογραφίες σας δεν διαμοιράζονται ακόμα με κανέναν.", "partner_page_no_more_users": "Δεν υπάρχουν άλλοι χρήστες για προσθήκη", @@ -385,241 +410,250 @@ "partner_page_stop_sharing_content": "Ο/Η {} δεν θα μπορεί πλέον να δει τις φωτογραφίες σας.", "partner_page_stop_sharing_title": "Θέλετε να σταματήσετε να μοιράζεστε τις φωτογραφίες σας;", "partner_page_title": "Σύντροφος", - "partners": "Partners", - "people": "People", + "partners": "Σύντροφοι", + "people": "Ανθρωποι", "permission_onboarding_back": "Πίσω", - "permission_onboarding_continue_anyway": "Continue anyway", - "permission_onboarding_get_started": "Get started", - "permission_onboarding_go_to_settings": "Go to settings", - "permission_onboarding_grant_permission": "Grant permission", - "permission_onboarding_log_out": "Log out", - "permission_onboarding_permission_denied": "Permission denied. To use Immich, grant photo and video permissions in Settings.", - "permission_onboarding_permission_granted": "Permission granted! You are all set.", - "permission_onboarding_permission_limited": "Permission limited. To let Immich backup and manage your entire gallery collection, grant photo and video permissions in Settings.", - "permission_onboarding_request": "Immich requires permission to view your photos and videos.", - "places": "Places", - "preferences_settings_title": "Preferences", - "profile_drawer_app_logs": "Logs", - "profile_drawer_client_out_of_date_major": "Mobile App is out of date. Please update to the latest major version.", - "profile_drawer_client_out_of_date_minor": "Mobile App is out of date. Please update to the latest minor version.", - "profile_drawer_client_server_up_to_date": "Client and Server are up-to-date", - "profile_drawer_documentation": "Documentation", + "permission_onboarding_continue_anyway": "Συνέχεια", + "permission_onboarding_get_started": "Ξεκινήστε", + "permission_onboarding_go_to_settings": "Μεταβείτε στις ρυθμίσεις", + "permission_onboarding_grant_permission": "Χορήγηση άδειας", + "permission_onboarding_log_out": "Αποσυνδεθείτε", + "permission_onboarding_permission_denied": "Η άδεια απορρίφθηκε. Για να χρησιμοποιήσετε το Immich, παραχωρήστε δικαιώματα φωτογραφίας και βίντεο στις Ρυθμίσεις.", + "permission_onboarding_permission_granted": "Δόθηκε άδεια! Είστε έτοιμοι.", + "permission_onboarding_permission_limited": "Περιορισμένη άδεια. Για να επιτρέψετε στο Immich να δημιουργεί αντίγραφα ασφαλείας και να διαχειρίζεται ολόκληρη τη συλλογή σας, παραχωρήστε άδειες φωτογραφιών και βίντεο στις Ρυθμίσεις.", + "permission_onboarding_request": "Το Immich απαιτεί άδεια πρόσβασεις στις φωτογραφίες και τα βίντεό σας.", + "places": "Μέρη", + "preferences_settings_subtitle": "Manage the app's preferences", + "preferences_settings_title": "Προτιμήσεις", + "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_documentation": "Οδηγίες Χρήσης", "profile_drawer_github": "GitHub", - "profile_drawer_server_out_of_date_major": "Server is out of date. Please update to the latest major version.", - "profile_drawer_server_out_of_date_minor": "Server is out of date. Please update to the latest minor version.", - "profile_drawer_settings": "Settings", - "profile_drawer_sign_out": "Sign Out", - "profile_drawer_trash": "Trash", - "recently_added": "Recently added", - "recently_added_page_title": "Recently Added", - "save_to_gallery": "Save to gallery", - "scaffold_body_error_occurred": "Error occurred", - "search_albums": "Search albums", - "search_bar_hint": "Search your photos", - "search_filter_apply": "Apply filter", - "search_filter_camera": "Camera", - "search_filter_camera_make": "Make", - "search_filter_camera_model": "Model", - "search_filter_camera_title": "Select camera type", - "search_filter_date": "Date", - "search_filter_date_interval": "{start} to {end}", - "search_filter_date_title": "Select a date range", - "search_filter_display_option_archive": "Archive", - "search_filter_display_option_favorite": "Favorite", - "search_filter_display_option_not_in_album": "Not in album", - "search_filter_display_options": "Display Options", - "search_filter_display_options_title": "Display options", - "search_filter_location": "Location", - "search_filter_location_city": "City", - "search_filter_location_country": "Country", - "search_filter_location_state": "State", - "search_filter_location_title": "Select location", - "search_filter_media_type": "Media Type", - "search_filter_media_type_all": "All", - "search_filter_media_type_image": "Image", - "search_filter_media_type_title": "Select media type", - "search_filter_media_type_video": "Video", - "search_filter_people": "People", - "search_filter_people_title": "Select people", - "search_page_categories": "Categories", - "search_page_favorites": "Favorites", - "search_page_motion_photos": "Motion Photos", - "search_page_no_objects": "No Objects Info Available", - "search_page_no_places": "No Places Info Available", + "profile_drawer_server_out_of_date_major": "Παρακαλώ ενημερώστε τον διακομιστή στην πιο πρόσφατη κύρια έκδοση.", + "profile_drawer_server_out_of_date_minor": "Παρακαλώ ενημερώστε τον διακομιστή στην πιο πρόσφατη δευτερεύουσα έκδοση.", + "profile_drawer_settings": "Ρυθμίσεις", + "profile_drawer_sign_out": "Αποσύνδεση", + "profile_drawer_trash": "Σκουπίδια", + "recently_added": "Προστέθηκαν πρόσφατα", + "recently_added_page_title": "Προστέθηκαν Πρόσφατα", + "save": "Save", + "save_to_gallery": "Αποθήκευση στη συλλογή", + "scaffold_body_error_occurred": "Παρουσιάστηκε σφάλμα", + "search_albums": "Αναζήτηση άλμπουμ", + "search_bar_hint": "Αναζητήστε τις φωτογραφίες σας", + "search_filter_apply": "Εφαρμογή φίλτρου", + "search_filter_camera": "Κάμερα", + "search_filter_camera_make": "Μάρκα", + "search_filter_camera_model": "Μοντέλο", + "search_filter_camera_title": "Επιλέξτε τύπο κάμερας", + "search_filter_date": "Ημερομηνία", + "search_filter_date_interval": "{start} έως {end}", + "search_filter_date_title": "Επιλέξτε εύρος ημερομηνιών", + "search_filter_display_option_archive": "Αρχείο", + "search_filter_display_option_favorite": "Αγαπημένο", + "search_filter_display_option_not_in_album": "Όχι στο άλμπουμ", + "search_filter_display_options": "Επιλογές εμφάνισης", + "search_filter_display_options_title": "Επιλογές εμφάνισης", + "search_filter_location": "Τοποθεσία", + "search_filter_location_city": "Πόλη", + "search_filter_location_country": "Χώρα", + "search_filter_location_state": "Πολιτεία", + "search_filter_location_title": "Επιλέξτε τοποθεσία", + "search_filter_media_type": "Τύπος Μέσου", + "search_filter_media_type_all": "Όλα", + "search_filter_media_type_image": "Εικόνα", + "search_filter_media_type_title": "Επιλέξτε τύπο μέσου", + "search_filter_media_type_video": "Βίντεο", + "search_filter_people": "Ανθρωποι", + "search_filter_people_title": "Επιλέξτε άτομα", + "search_page_categories": "Κατηγορίες", + "search_page_favorites": "Αγαπημένα", + "search_page_motion_photos": "Κινούμενες Φωτογραφίες", + "search_page_no_objects": "Μη διαθέσιμες πληροφορίες αντικειμένων", + "search_page_no_places": "Μη διαθέσιμες πληροφορίες για μέρη", "search_page_people": "Άτομα", - "search_page_person_add_name_dialog_cancel": "Cancel", - "search_page_person_add_name_dialog_hint": "Name", - "search_page_person_add_name_dialog_save": "Save", - "search_page_person_add_name_dialog_title": "Add a name", - "search_page_person_add_name_subtitle": "Find them fast by name with search", - "search_page_person_add_name_title": "Add a name", - "search_page_person_edit_name": "Edit name", - "search_page_places": "Places", - "search_page_recently_added": "Recently added", - "search_page_screenshots": "Screenshots", - "search_page_selfies": "Selfies", - "search_page_things": "Things", - "search_page_videos": "Videos", - "search_page_view_all_button": "View all", - "search_page_your_activity": "Your activity", - "search_page_your_map": "Your Map", - "search_result_page_new_search_hint": "New Search", - "search_suggestion_list_smart_search_hint_1": "Smart search is enabled by default, to search for metadata use the syntax ", - "search_suggestion_list_smart_search_hint_2": "m:your-search-term", - "select_additional_user_for_sharing_page_suggestions": "Suggestions", - "select_user_for_sharing_page_err_album": "Failed to create album", - "select_user_for_sharing_page_share_suggestions": "Suggestions", - "server_info_box_app_version": "App Version", + "search_page_person_add_name_dialog_cancel": "Ακύρωση", + "search_page_person_add_name_dialog_hint": "Όνομα", + "search_page_person_add_name_dialog_save": "Αποθήκευση", + "search_page_person_add_name_dialog_title": "Προσθέστε όνομα", + "search_page_person_add_name_subtitle": "Βρείτε τα γρήγορα ονομαστικά με αναζήτηση", + "search_page_person_add_name_title": "Προσθέστε ένα όνομα", + "search_page_person_edit_name": "Επεξεργασία ονόματος", + "search_page_places": "Μέρη", + "search_page_recently_added": "Προστέθηκε πρόσφατα", + "search_page_screenshots": "Στιγμιότυπα οθόνης", + "search_page_search_photos_videos": "Search for your photos and videos", + "search_page_selfies": "Σέλφι", + "search_page_things": "Πράγματα", + "search_page_videos": "Βίντεο", + "search_page_view_all_button": "Προβολή όλων", + "search_page_your_activity": "Η δραστηριότητά σας", + "search_page_your_map": "Ο χάρτης σας", + "search_result_page_new_search_hint": "Νέα Αναζήτηση", + "search_suggestion_list_smart_search_hint_1": "Η έξυπνη αναζήτηση είναι ενεργοποιημένη από προεπιλογή, για αναζήτηση μεταδεδομένων χρησιμοποιήστε το συντακτικό", + "search_suggestion_list_smart_search_hint_2": "m:όρος-αναζήτησης", + "select_additional_user_for_sharing_page_suggestions": "Προτάσεις", + "select_user_for_sharing_page_err_album": "Αποτυχία δημιουργίας άλπουμ", + "select_user_for_sharing_page_share_suggestions": "Προτάσεις", + "server_endpoint": "Server Endpoint", + "server_info_box_app_version": "Έκδοση εφαρμογής", "server_info_box_latest_release": "Τελευταία Έκδοση", - "server_info_box_server_url": "Server URL", - "server_info_box_server_version": "Server Version", - "setting_image_viewer_help": "The detail viewer loads the small thumbnail first, then loads the medium-size preview (if enabled), finally loads the original (if enabled).", - "setting_image_viewer_original_subtitle": "Enable to load the original full-resolution image (large!). Disable to reduce data usage (both network and on device cache).", - "setting_image_viewer_original_title": "Load original image", - "setting_image_viewer_preview_subtitle": "Enable to load a medium-resolution image. Disable to either directly load the original or only use the thumbnail.", - "setting_image_viewer_preview_title": "Load preview image", - "setting_image_viewer_title": "Images", - "setting_languages_apply": "Apply", - "setting_languages_title": "Languages", - "setting_notifications_notify_failures_grace_period": "Notify background backup failures: {}", - "setting_notifications_notify_hours": "{} hours", - "setting_notifications_notify_immediately": "immediately", - "setting_notifications_notify_minutes": "{} minutes", - "setting_notifications_notify_never": "never", - "setting_notifications_notify_seconds": "{} seconds", - "setting_notifications_single_progress_subtitle": "Detailed upload progress information per asset", - "setting_notifications_single_progress_title": "Show background backup detail progress", - "setting_notifications_subtitle": "Adjust your notification preferences", - "setting_notifications_title": "Notifications", - "setting_notifications_total_progress_subtitle": "Overall upload progress (done/total assets)", - "setting_notifications_total_progress_title": "Show background backup total progress", - "setting_pages_app_bar_settings": "Settings", - "settings_require_restart": "Please restart Immich to apply this setting", - "setting_video_viewer_looping_subtitle": "Enable to automatically loop a video in the detail viewer.", - "setting_video_viewer_looping_title": "Looping", - "setting_video_viewer_title": "Videos", - "share_add": "Add", - "share_add_photos": "Add photos", - "share_add_title": "Add a title", - "share_assets_selected": "{} selected", - "share_create_album": "Create album", + "server_info_box_server_url": "URL διακομιστή", + "server_info_box_server_version": "Έκδοση Διακομιστή", + "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": "Change the app's language", + "setting_languages_title": "Γλώσσες", + "setting_notifications_notify_failures_grace_period": "Ειδοποίηση αποτυχιών δημιουργίας αντιγράφων ασφαλείας στο παρασκήνιο: {}", + "setting_notifications_notify_hours": "{} ώρες", + "setting_notifications_notify_immediately": "αμέσως", + "setting_notifications_notify_minutes": "{} λεπτά", + "setting_notifications_notify_never": "ποτέ", + "setting_notifications_notify_seconds": "{} δευτερόλεπτα", + "setting_notifications_single_progress_subtitle": "Λεπτομερείς πληροφορίες προόδου μεταφόρτωσης ανά στοιχείο", + "setting_notifications_single_progress_title": "Εμφάνιση προόδου λεπτομερειών δημιουργίας αντιγράφων ασφαλείας παρασκηνίου", + "setting_notifications_subtitle": "Προσαρμόστε τις προτιμήσεις ειδοποίησης", + "setting_notifications_title": "Ειδοποιήσεις", + "setting_notifications_total_progress_subtitle": "Συνολική πρόοδος μεταφόρτωσης (ολοκληρώθηκε/σύνολο στοιχείων)", + "setting_notifications_total_progress_title": "Εμφάνιση συνολικής προόδου δημιουργίας αντιγράφων ασφαλείας παρασκηνίου", + "setting_pages_app_bar_settings": "Ρυθμίσεις", + "settings_require_restart": "Επανεκκινήστε το Immich για να εφαρμόσετε αυτήν τη ρύθμιση", + "setting_video_viewer_looping_subtitle": "Ενεργοποιήστε για το αυτόματη συνεχής επανάληψη βίντεο στο πρόγραμμα προβολής λεπτομερειών.", + "setting_video_viewer_looping_title": "Συνεχής Επανάληψη", + "setting_video_viewer_title": "Βίντεο", + "share_add": "Πρόσθεση", + "share_add_photos": "Προσθήκη φωτογραφιών", + "share_add_title": "Προσθέστε έναν τίτλο", + "share_assets_selected": "{} επιλεγμένα", + "share_create_album": "Δημιουργία άλμπουμ", "shared_album_activities_input_disable": "Το σχόλιο είναι απενεργοποιημένο", - "shared_album_activities_input_hint": "Say something", - "shared_album_activity_remove_content": "Do you want to delete this activity?", - "shared_album_activity_remove_title": "Delete Activity", + "shared_album_activities_input_hint": "Πες κάτι", + "shared_album_activity_remove_content": "Θέλετε να διαγράψετε αυτήν τη δραστηριότητα;", + "shared_album_activity_remove_title": "Διαγραφή Δραστηριότητας", "shared_album_activity_setting_subtitle": "Επέτρεψε σε άλλους να απαντάνε", - "shared_album_activity_setting_title": "Comments & likes", - "shared_album_section_people_action_error": "Error leaving/removing from album", - "shared_album_section_people_action_leave": "Remove user from album", - "shared_album_section_people_action_remove_user": "Remove user from album", - "shared_album_section_people_owner_label": "Owner", - "shared_album_section_people_title": "PEOPLE", - "share_dialog_preparing": "Preparing...", - "shared_link_app_bar_title": "Shared Links", - "shared_link_clipboard_copied_massage": "Copied to clipboard", - "shared_link_clipboard_text": "Link: {}\nPassword: {}", - "shared_link_create_app_bar_title": "Create link to share", - "shared_link_create_error": "Error while creating shared link", - "shared_link_create_info": "Let anyone with the link see the selected photo(s)", - "shared_link_create_submit_button": "Create link", - "shared_link_edit_allow_download": "Allow public user to download", - "shared_link_edit_allow_upload": "Allow public user to upload", - "shared_link_edit_app_bar_title": "Edit link", - "shared_link_edit_change_expiry": "Change expiration time", - "shared_link_edit_description": "Description", - "shared_link_edit_description_hint": "Enter the share description", + "shared_album_activity_setting_title": "Σχόλια & likes", + "shared_album_section_people_action_error": "Σφάλμα αποχώρησης/κατάργησης από το άλμπουμ", + "shared_album_section_people_action_leave": "Αποχώρηση χρήστη από το άλμπουμ", + "shared_album_section_people_action_remove_user": "Κατάργηση χρήστη από το άλμπουμ", + "shared_album_section_people_owner_label": "Ιδιοκτήτης", + "shared_album_section_people_title": "ΑΝΘΡΩΠΟΙ", + "share_dialog_preparing": "Προετοιμασία...", + "shared_link_app_bar_title": "Κοινόχρηστοι Σύνδεσμοι", + "shared_link_clipboard_copied_massage": "Αντιγράφηκε στο πρόχειρο", + "shared_link_clipboard_text": "Σύνδεσμος: {}\nΚωδικός πρόσβασης: {}", + "shared_link_create_app_bar_title": "Δημιουργία συνδέσμου για κοινή χρήση", + "shared_link_create_error": "Σφάλμα κατά τη δημιουργία κοινόχρηστου συνδέσμου", + "shared_link_create_info": "Να επιτρέπεται σε οποιονδήποτε έχει τον σύνδεσμο να δει τις επιλεγμένες φωτογραφίες", + "shared_link_create_submit_button": "Δημιουργία συνδέσμου", + "shared_link_edit_allow_download": "Να επιτρέπεται η λήψη απο δημόσιο χρήστη", + "shared_link_edit_allow_upload": "Να επιτρέπεται η μεταφόρτωση απο δημόσιο χρήστη", + "shared_link_edit_app_bar_title": "Επεξεργασία συνδέσμου", + "shared_link_edit_change_expiry": "Αλλαγή χρόνου λήξης", + "shared_link_edit_description": "Περιγραφή", + "shared_link_edit_description_hint": "Εισαγάγετε την περιγραφή της κοινής χρήσης", "shared_link_edit_expire_after": "Λήξη μετά από", - "shared_link_edit_expire_after_option_day": "1 day", - "shared_link_edit_expire_after_option_days": "{} days", - "shared_link_edit_expire_after_option_hour": "1 hour", - "shared_link_edit_expire_after_option_hours": "{} hours", - "shared_link_edit_expire_after_option_minute": "1 minute", - "shared_link_edit_expire_after_option_minutes": "{} minutes", - "shared_link_edit_expire_after_option_months": "{} months", - "shared_link_edit_expire_after_option_never": "Never", - "shared_link_edit_expire_after_option_year": "{} year", - "shared_link_edit_password": "Password", - "shared_link_edit_password_hint": "Enter the share password", - "shared_link_edit_show_meta": "Show metadata", - "shared_link_edit_submit_button": "Update link", - "shared_link_empty": "You don't have any shared links", - "shared_link_error_server_url_fetch": "Cannot fetch the server url", - "shared_link_expired": "Expired", - "shared_link_expires_day": "Expires in {} day", - "shared_link_expires_days": "Expires in {} days", - "shared_link_expires_hour": "Expires in {} hour", - "shared_link_expires_hours": "Expires in {} hours", - "shared_link_expires_minute": "Expires in {} minute", - "shared_link_expires_minutes": "Expires in {} minutes", - "shared_link_expires_never": "Expires ∞", - "shared_link_expires_second": "Expires in {} second", - "shared_link_expires_seconds": "Expires in {} seconds", - "shared_link_individual_shared": "Individual shared", - "shared_link_info_chip_download": "Download", + "shared_link_edit_expire_after_option_day": "1 ημέρα", + "shared_link_edit_expire_after_option_days": "{} ημέρες", + "shared_link_edit_expire_after_option_hour": "1 ώρα", + "shared_link_edit_expire_after_option_hours": "{} ώρες", + "shared_link_edit_expire_after_option_minute": "1 λεπτό", + "shared_link_edit_expire_after_option_minutes": "{} λεπτά", + "shared_link_edit_expire_after_option_months": "{} μήνες", + "shared_link_edit_expire_after_option_never": "Ποτέ", + "shared_link_edit_expire_after_option_year": "{} έτος", + "shared_link_edit_password": "Κωδικός πρόσβασης", + "shared_link_edit_password_hint": "Εισαγάγετε τον κωδικό πρόσβασης κοινής χρήσης", + "shared_link_edit_show_meta": "Εμφάνιση μεταδεδομένων", + "shared_link_edit_submit_button": "Ενημέρωση συνδέσμου", + "shared_link_empty": "Δεν έχετε κοινόχρηστους συνδέσμους", + "shared_link_error_server_url_fetch": "Δεν είναι δυνατή η ανάκτηση του URL του διακομιστή", + "shared_link_expired": "Έληξε", + "shared_link_expires_day": "Λήγει σε {} ημέρα", + "shared_link_expires_days": "Λήγει σε {} ημέρες", + "shared_link_expires_hour": "Λήγει σε {} ώρα", + "shared_link_expires_hours": "Λήγει σε {} ώρες", + "shared_link_expires_minute": "Λήγει σε {} λεπτό", + "shared_link_expires_minutes": "Λήγει σε {} λεπτά", + "shared_link_expires_never": "Λήγει ∞", + "shared_link_expires_second": "Λήγει σε {} δευτερόλεπτο", + "shared_link_expires_seconds": "Λήγει σε {} δευτερόλεπτα", + "shared_link_individual_shared": "Μεμονωμένο κοινό", + "shared_link_info_chip_download": "Λήψη", "shared_link_info_chip_metadata": "EXIF", - "shared_link_info_chip_upload": "Upload", - "shared_link_manage_links": "Manage Shared links", - "shared_link_public_album": "Public album", - "shared_links": "Shared links", - "share_done": "Done", - "shared_with_me": "Shared with me", - "share_invite": "Invite to album", - "sharing_page_album": "Shared albums", - "sharing_page_description": "Create shared albums to share photos and videos with people in your network.", - "sharing_page_empty_list": "EMPTY LIST", - "sharing_silver_appbar_create_shared_album": "New shared album", - "sharing_silver_appbar_shared_links": "Shared links", - "sharing_silver_appbar_share_partner": "Share with partner", - "sync": "Sync", - "sync_albums": "Sync albums", - "sync_albums_manual_subtitle": "Sync all uploaded videos and photos to the selected backup albums", - "sync_upload_album_setting_subtitle": "Create and upload your photos and videos to the selected albums on Immich", - "tab_controller_nav_library": "Library", - "tab_controller_nav_photos": "Photos", - "tab_controller_nav_search": "Search", - "tab_controller_nav_sharing": "Sharing", - "theme_setting_asset_list_storage_indicator_title": "Show storage indicator on asset tiles", - "theme_setting_asset_list_tiles_per_row_title": "Number of assets per row ({})", - "theme_setting_colorful_interface_subtitle": "Apply primary color to background surfaces.", - "theme_setting_colorful_interface_title": "Colorful interface", - "theme_setting_dark_mode_switch": "Dark mode", - "theme_setting_image_viewer_quality_subtitle": "Adjust the quality of the detail image viewer", - "theme_setting_image_viewer_quality_title": "Image viewer quality", - "theme_setting_primary_color_subtitle": "Pick a color for primary actions and accents.", - "theme_setting_primary_color_title": "Primary color", - "theme_setting_system_primary_color_title": "Use system color", - "theme_setting_system_theme_switch": "Automatic (Follow system setting)", - "theme_setting_theme_subtitle": "Choose the app's theme setting", - "theme_setting_theme_title": "Theme", - "theme_setting_three_stage_loading_subtitle": "Three-stage loading might increase the loading performance but causes significantly higher network load", - "theme_setting_three_stage_loading_title": "Enable three-stage loading", - "translated_text_options": "Options", - "trash": "Trash", - "trash_emptied": "Emptied trash", - "trash_page_delete": "Delete", - "trash_page_delete_all": "Delete All", - "trash_page_empty_trash_btn": "Empty trash", - "trash_page_empty_trash_dialog_content": "Do you want to empty your trashed assets? These items will be permanently removed from Immich", - "trash_page_empty_trash_dialog_ok": "Ok", - "trash_page_info": "Trashed items will be permanently deleted after {} days", - "trash_page_no_assets": "No trashed assets", - "trash_page_restore": "Restore", - "trash_page_restore_all": "Restore All", - "trash_page_select_assets_btn": "Select assets", - "trash_page_select_btn": "Select", - "trash_page_title": "Trash ({})", + "shared_link_info_chip_upload": "Μεταφόρτωση", + "shared_link_manage_links": "Διαχείριση Κοινόχρηστων Συνδέσμων", + "shared_link_public_album": "Δημόσιο άλμπουμ", + "shared_links": "Κοινόχρηστοι σύνδεσμοι", + "share_done": "Τέλος", + "shared_with_me": "Μοιρασμένα μαζί μου", + "share_invite": "Πρόσκληση σε άλμπουμ", + "sharing_page_album": "Κοινόχρηστα άλμπουμ", + "sharing_page_description": "Δημιουργήστε κοινόχρηστα άλμπουμ για να μοιράζεστε φωτογραφίες και βίντεο με άτομα στο δίκτυό σας.", + "sharing_page_empty_list": "ΚΕΝΗ ΛΙΣΤΑ", + "sharing_silver_appbar_create_shared_album": "Νέο κοινόχρηστο άλμπουμ", + "sharing_silver_appbar_shared_links": "Κοινόχρηστοι σύνδεσμοι", + "sharing_silver_appbar_share_partner": "Μοιραστείτε με τον συνεργάτη", + "sync": "Συγχρονισμός", + "sync_albums": "Συγχρονισμός άλμπουμ", + "sync_albums_manual_subtitle": "Συγχρονίστε όλα τα μεταφορτωμένα βίντεο και φωτογραφίες με τα επιλεγμένα εφεδρικά άλμπουμ", + "sync_upload_album_setting_subtitle": "Δημιουργήστε και ανεβάστε τις φωτογραφίες και τα βίντεό σας στα επιλεγμένα άλμπουμ στο Immich", + "tab_controller_nav_library": "Βιβλιοθήκη", + "tab_controller_nav_photos": "Φωτογραφίες", + "tab_controller_nav_search": "Αναζήτηση", + "tab_controller_nav_sharing": "Κοινή Χρήση", + "theme_setting_asset_list_storage_indicator_title": "Εμφάνιση ένδειξης αποθήκευσης σε πλακίδια στοιχείων", + "theme_setting_asset_list_tiles_per_row_title": "Αριθμός στοιχείων ανά σειρά ({})", + "theme_setting_colorful_interface_subtitle": "Εφαρμόστε βασικό χρώμα σε επιφάνειες φόντου.", + "theme_setting_colorful_interface_title": "Πολύχρωμη διεπαφή", + "theme_setting_dark_mode_switch": "Σκοτεινή λειτουργία", + "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_theme_title": "Θέμα", + "theme_setting_three_stage_loading_subtitle": "Η φόρτωση τριών σταδίων μπορεί να αυξήσει την απόδοση φόρτωσης, αλλά προκαλεί σημαντικά υψηλότερο φόρτο δικτύου", + "theme_setting_three_stage_loading_title": "Ενεργοποιήστε τη φόρτωση τριών σταδίων", + "translated_text_options": "Επιλογές", + "trash": "Σκουπίδια", + "trash_emptied": "Αδειάστηκαν τα σκουπίδια", + "trash_page_delete": "Διαγραφή", + "trash_page_delete_all": "Διαγραφή όλων", + "trash_page_empty_trash_btn": "Αδειάστε τα σκουπίδια", + "trash_page_empty_trash_dialog_content": "Θέλετε να αδειάσετε τα περιουσιακά σας στοιχεία στον κάδο απορριμμάτων; Αυτά τα στοιχεία θα καταργηθούν οριστικά από το Immich", + "trash_page_empty_trash_dialog_ok": "Εντάξει", + "trash_page_info": "Τα στοιχεία που έχουν απορριφθεί θα διαγραφούν οριστικά μετά από {} ημέρες", + "trash_page_no_assets": "Δεν υπάρχουν περιουσιακά στοιχεία που έχουν απορριφθεί", + "trash_page_restore": "Επαναφορά", + "trash_page_restore_all": "Επαναφορά Όλων", + "trash_page_select_assets_btn": "Επιλέξτε στοιχεία", + "trash_page_select_btn": "Επιλογή", + "trash_page_title": "Κάδος Απορριμμάτων ({})", "upload_dialog_cancel": "Ακύρωση", "upload_dialog_info": "Θέλετε να αντιγράψετε (κάνετε backup) τα επιλεγμένo(α) στοιχείο(α) στο διακομιστή;", "upload_dialog_ok": "Ανέβασμα", "upload_dialog_title": "Ανέβασμα στοιχείου", - "version_announcement_overlay_ack": "Acknowledge", - "version_announcement_overlay_release_notes": "release notes", - "version_announcement_overlay_text_1": "Hi friend, there is a new release of", - "version_announcement_overlay_text_2": "please take your time to visit the ", - "version_announcement_overlay_text_3": " and ensure your docker-compose and .env setup is up-to-date to prevent any misconfigurations, especially if you use WatchTower or any mechanism that handles updating your server application automatically.", - "version_announcement_overlay_title": "New Server Version Available \uD83C\uDF89", - "videos": "Videos", - "viewer_remove_from_stack": "Remove from Stack", - "viewer_stack_use_as_main_asset": "Use as Main Asset", - "viewer_unstack": "Un-Stack" + "use_current_connection": "use current connection", + "validate_endpoint_error": "Please enter a valid URL", + "version_announcement_overlay_ack": "Κατάλαβα", + "version_announcement_overlay_release_notes": "σημειώσεις έκδοσης", + "version_announcement_overlay_text_1": "Γειά σας, υπάρχει μια νέα έκδοση του", + "version_announcement_overlay_text_2": "παρακαλώ αφιερώστε χρόνο να επισκεφθείτε το", + "version_announcement_overlay_text_3": " και βεβαιωθείτε ότι το docker-compose και το .env σας είναι ενημερωμένη για την αποφυγή τυχόν εσφαλμένων διαμορφώσεων, ειδικά εάν χρησιμοποιείτε το WatchTower ή οποιονδήποτε μηχανισμό που χειρίζεται την αυτόματη ενημέρωση του διακομιστή σας.", + "version_announcement_overlay_title": "Διαθέσιμη νέα έκδοση διακομιστή \uD83C\uDF89", + "videos": "Βίντεο", + "viewer_remove_from_stack": "Κατάργηση από τη Στοίβα", + "viewer_stack_use_as_main_asset": "Χρήση ως Κύριο Στοιχείο", + "viewer_unstack": "Αποστοίβαξε", + "wifi_name": "WiFi Name", + "your_wifi_name": "Your WiFi name" } \ No newline at end of file diff --git a/mobile/assets/i18n/en-US.json b/mobile/assets/i18n/en-US.json index 0075f65de0557..a7f31f8440f7e 100644 --- a/mobile/assets/i18n/en-US.json +++ b/mobile/assets/i18n/en-US.json @@ -7,6 +7,7 @@ "action_common_select": "Select", "action_common_update": "Update", "add_a_name": "Add a name", + "add_endpoint": "Add endpoint", "add_to_album_bottom_sheet_added": "Added to {album}", "add_to_album_bottom_sheet_already_exists": "Already in {album}", "advanced_settings_log_level_title": "Log level: {}", @@ -65,7 +66,12 @@ "assets_restored_successfully": "{} asset(s) restored successfully", "assets_trashed": "{} asset(s) trashed", "assets_trashed_from_server": "{} asset(s) trashed from the Immich server", + "asset_viewer_settings_subtitle": "Manage your gallery viewer settings", "asset_viewer_settings_title": "Asset Viewer", + "automatic_endpoint_switching_subtitle": "Connect locally over designated Wi-Fi when available and use alternative connections elsewhere", + "automatic_endpoint_switching_title": "Automatic URL switching", + "background_location_permission": "Background location permission", + "background_location_permission_content": "In order to switch networks when running in the background, Immich must *always* have precise location access so the app can read the Wi-Fi network's name", "backup_album_selection_page_albums_device": "Albums on device ({})", "backup_album_selection_page_albums_tap": "Tap to include, double tap to exclude", "backup_album_selection_page_assets_scatter": "Assets can scatter across multiple albums. Thus, albums can be included or excluded during the backup process.", @@ -131,6 +137,7 @@ "backup_manual_success": "Success", "backup_manual_title": "Upload status", "backup_options_page_title": "Backup options", + "backup_setting_subtitle": "Manage background and foreground upload settings", "cache_settings_album_thumbnails": "Library page thumbnails ({} assets)", "cache_settings_clear_cache_button": "Clear cache", "cache_settings_clear_cache_button_title": "Clears the app's cache. This will significantly impact the app's performance until the cache has rebuilt.", @@ -149,11 +156,16 @@ "cache_settings_tile_subtitle": "Control the local storage behaviour", "cache_settings_tile_title": "Local Storage", "cache_settings_title": "Caching Settings", + "cancel": "Cancel", + "change_display_order": "Change display order", "change_password_form_confirm_password": "Confirm Password", "change_password_form_description": "Hi {name},\n\nThis is either the first time you are signing into the system or a request has been made to change your password. Please enter the new password below.", "change_password_form_new_password": "New Password", "change_password_form_password_mismatch": "Passwords do not match", "change_password_form_reenter_new_password": "Re-enter New Password", + "check_corrupt_asset_backup": "Check for corrupt asset backups", + "check_corrupt_asset_backup_button": "Perform check", + "check_corrupt_asset_backup_description": "Run this check only over Wi-Fi and once all assets have been backed-up. The procedure might take a few minutes.", "client_cert_dialog_msg_confirm": "OK", "client_cert_enter_password": "Enter Password", "client_cert_import": "Import", @@ -199,6 +211,7 @@ "crop": "Crop", "curated_location_page_title": "Places", "curated_object_page_title": "Things", + "current_server_address": "Current server address", "daily_title_text_date": "E, MMM dd", "daily_title_text_date_year": "E, MMM dd, yyyy", "date_format": "E, LLL d, y • h:mm a", @@ -235,6 +248,8 @@ "edit_date_time_dialog_timezone": "Timezone", "edit_image_title": "Edit", "edit_location_dialog_title": "Location", + "enter_wifi_name": "Enter WiFi name", + "error_change_sort_album": "Failed to change album sort order", "error_saving_image": "Error: {}", "exif_bottom_sheet_description": "Add Description...", "exif_bottom_sheet_details": "DETAILS", @@ -246,11 +261,15 @@ "experimental_settings_new_asset_list_title": "Enable experimental photo grid", "experimental_settings_subtitle": "Use at your own risk!", "experimental_settings_title": "Experimental", + "external_network": "External network", + "external_network_sheet_info": "When not on the preferred WiFi network, the app will connect to the server through the first of the below URLs it can reach, starting from top to bottom", "favorites": "Favorites", "favorites_page_no_favorites": "No favorite assets found", "favorites_page_title": "Favorites", "filename_search": "File name or extension", "filter": "Filter", + "get_wifiname_error": "Could not get Wi-Fi name. Make sure you have granted the necessary permissions and are connected to a Wi-Fi network", + "grant_permission": "Grant permission", "haptic_feedback_switch": "Enable haptic feedback", "haptic_feedback_title": "Haptic Feedback", "header_settings_add_header_tip": "Add Header", @@ -296,6 +315,10 @@ "library_page_sort_most_oldest_photo": "Oldest photo", "library_page_sort_most_recent_photo": "Most recent photo", "library_page_sort_title": "Album title", + "local_network": "Local network", + "local_network_sheet_info": "The app will connect to the server through this URL when using the specified Wi-Fi network", + "location_permission": "Location permission", + "location_permission_content": "In order to use the auto-switching feature, Immich needs precise location permission so it can read the current WiFi network's name", "location_picker_choose_on_map": "Choose on map", "location_picker_latitude": "Latitude", "location_picker_latitude_error": "Enter a valid latitude", @@ -365,6 +388,8 @@ "multiselect_grid_edit_date_time_err_read_only": "Cannot edit date of read only asset(s), skipping", "multiselect_grid_edit_gps_err_read_only": "Cannot edit location of read only asset(s), skipping", "my_albums": "My albums", + "networking_settings": "Networking", + "networking_subtitle": "Manage the server endpoint settings", "no_assets_to_show": "No assets to show", "no_name": "No name", "notification_permission_dialog_cancel": "Cancel", @@ -398,6 +423,7 @@ "permission_onboarding_permission_limited": "Permission limited. To let Immich backup and manage your entire gallery collection, grant photo and video permissions in Settings.", "permission_onboarding_request": "Immich requires permission to view your photos and videos.", "places": "Places", + "preferences_settings_subtitle": "Manage the app's preferences", "preferences_settings_title": "Preferences", "profile_drawer_app_logs": "Logs", "profile_drawer_client_out_of_date_major": "Mobile App is out of date. Please update to the latest major version.", @@ -412,6 +438,7 @@ "profile_drawer_trash": "Trash", "recently_added": "Recently added", "recently_added_page_title": "Recently Added", + "save": "Save", "save_to_gallery": "Save to gallery", "scaffold_body_error_occurred": "Error occurred", "search_albums": "Search albums", @@ -457,6 +484,7 @@ "search_page_places": "Places", "search_page_recently_added": "Recently added", "search_page_screenshots": "Screenshots", + "search_page_search_photos_videos": "Search for your photos and videos", "search_page_selfies": "Selfies", "search_page_things": "Things", "search_page_videos": "Videos", @@ -469,6 +497,7 @@ "select_additional_user_for_sharing_page_suggestions": "Suggestions", "select_user_for_sharing_page_err_album": "Failed to create album", "select_user_for_sharing_page_share_suggestions": "Suggestions", + "server_endpoint": "Server Endpoint", "server_info_box_app_version": "App Version", "server_info_box_latest_release": "Latest Version", "server_info_box_server_url": "Server URL", @@ -480,6 +509,7 @@ "setting_image_viewer_preview_title": "Load preview image", "setting_image_viewer_title": "Images", "setting_languages_apply": "Apply", + "setting_languages_subtitle": "Change the app's language", "setting_languages_title": "Languages", "setting_notifications_notify_failures_grace_period": "Notify background backup failures: {}", "setting_notifications_notify_hours": "{} hours", @@ -612,6 +642,8 @@ "upload_dialog_info": "Do you want to backup the selected Asset(s) to the server?", "upload_dialog_ok": "Upload", "upload_dialog_title": "Upload Asset", + "use_current_connection": "use current connection", + "validate_endpoint_error": "Please enter a valid URL", "version_announcement_overlay_ack": "Acknowledge", "version_announcement_overlay_release_notes": "release notes", "version_announcement_overlay_text_1": "Hi friend, there is a new release of", @@ -621,5 +653,7 @@ "videos": "Videos", "viewer_remove_from_stack": "Remove from Stack", "viewer_stack_use_as_main_asset": "Use as Main Asset", - "viewer_unstack": "Un-Stack" + "viewer_unstack": "Un-Stack", + "wifi_name": "WiFi Name", + "your_wifi_name": "Your WiFi name" } \ No newline at end of file diff --git a/mobile/assets/i18n/es-ES.json b/mobile/assets/i18n/es-ES.json index 88db7f9068eff..d7ddb03fd2e17 100644 --- a/mobile/assets/i18n/es-ES.json +++ b/mobile/assets/i18n/es-ES.json @@ -6,13 +6,14 @@ "action_common_save": "Guardar", "action_common_select": "Seleccionar", "action_common_update": "Actualizar", - "add_a_name": "Add a name", + "add_a_name": "Añadir nombre", + "add_endpoint": "Add endpoint", "add_to_album_bottom_sheet_added": "Agregado a {album}", "add_to_album_bottom_sheet_already_exists": "Ya se encuentra en {album}", "advanced_settings_log_level_title": "Nivel de registro: {}", "advanced_settings_prefer_remote_subtitle": "Algunos dispositivos tardan mucho en cargar las miniaturas de los elementos encontrados en el dispositivo. Activa esta opción para cargar imágenes remotas en su lugar.", "advanced_settings_prefer_remote_title": "Preferir imágenes remotas", - "advanced_settings_proxy_headers_subtitle": "Define proxy headers Immich should send with each network request", + "advanced_settings_proxy_headers_subtitle": "Configura headers HTTP que Immich incluirá en cada petición de red", "advanced_settings_proxy_headers_title": "Proxy Headers", "advanced_settings_self_signed_ssl_subtitle": "Omitir verificación del certificado SSL del servidor. Requerido para certificados autofirmados", "advanced_settings_self_signed_ssl_title": "Permitir certificados autofirmados", @@ -22,7 +23,7 @@ "advanced_settings_troubleshooting_title": "Solución de problemas", "album_info_card_backup_album_excluded": "EXCLUIDOS", "album_info_card_backup_album_included": "INCLUIDOS", - "albums": "Albums", + "albums": "Álbumes", "album_thumbnail_card_item": "1 elemento", "album_thumbnail_card_items": "{} elementos", "album_thumbnail_card_shared": "Compartido", @@ -38,13 +39,13 @@ "album_viewer_appbar_share_remove": "Eliminar del álbum ", "album_viewer_appbar_share_to": "Compartir Con", "album_viewer_page_share_add_users": "Agregar usuarios", - "all": "All", + "all": "Todos", "all_people_page_title": "Personas", "all_videos_page_title": "Videos", "app_bar_signout_dialog_content": "¿Estás seguro que quieres cerrar sesión?", "app_bar_signout_dialog_ok": "Sí", "app_bar_signout_dialog_title": "Cerrar sesión", - "archived": "Archived", + "archived": "Archivado", "archive_page_no_archived_assets": "No se encontraron elementos archivados", "archive_page_title": "Archivo ({})", "asset_action_delete_err_read_only": "No se pueden borrar el archivo(s) de solo lectura, omitiendo", @@ -58,14 +59,19 @@ "asset_list_layout_sub_title": "Disposición", "asset_list_settings_subtitle": "Configuraciones del diseño de la cuadrícula de fotos", "asset_list_settings_title": "Cuadrícula de fotos", - "asset_restored_successfully": "Asset restored successfully", + "asset_restored_successfully": "Elementos restaurados exitosamente", "assets_deleted_permanently": "\n{} elementos(s) eliminado(s) permanentemente", "assets_deleted_permanently_from_server": "{} asset(s) deleted permanently from the Immich server", - "assets_removed_permanently_from_device": "{} asset(s) removed permanently from your device", - "assets_restored_successfully": "{} asset(s) restored successfully", + "assets_removed_permanently_from_device": "{} elemento(s) eliminado(s) permanentemente de su dispositivo", + "assets_restored_successfully": "{} elemento(s) restaurado(s) exitosamente", "assets_trashed": "{} elemento(s) eliminado(s)", - "assets_trashed_from_server": "{} asset(s) trashed from the Immich server", + "assets_trashed_from_server": "{} elemento(s) movido a la papelera en Immich", + "asset_viewer_settings_subtitle": "Administra las configuracioens de tu visor de fotos", "asset_viewer_settings_title": "Visor de Archivos", + "automatic_endpoint_switching_subtitle": "Connect locally over designated Wi-Fi when available and use alternative connections elsewhere", + "automatic_endpoint_switching_title": "Automatic URL switching", + "background_location_permission": "Background location permission", + "background_location_permission_content": "In order to switch networks when running in the background, Immich must *always* have precise location access so the app can read the Wi-Fi network's name", "backup_album_selection_page_albums_device": "Álbumes en el dispositivo ({})", "backup_album_selection_page_albums_tap": "Toque para incluir, doble toque para excluir", "backup_album_selection_page_assets_scatter": "Los elementos pueden dispersarse en varios álbumes. De este modo, los álbumes pueden ser incluidos o excluidos durante el proceso de copia de seguridad.", @@ -131,6 +137,7 @@ "backup_manual_success": "Éxito", "backup_manual_title": "Estado de la subida", "backup_options_page_title": "Opciones de Copia de Seguridad", + "backup_setting_subtitle": "Administra las configuraciones de respaldo en segundo y primer plano", "cache_settings_album_thumbnails": "Miniaturas de la página de la biblioteca ({} elementos)", "cache_settings_clear_cache_button": "Borrar caché", "cache_settings_clear_cache_button_title": "Borra la caché de la aplicación. Esto afectará significativamente el rendimiento de la aplicación hasta que se reconstruya la caché.", @@ -149,11 +156,16 @@ "cache_settings_tile_subtitle": "Controla el comportamiento del almacenamiento local", "cache_settings_tile_title": "Almacenamiento local", "cache_settings_title": "Configuración de la caché", + "cancel": "Cancel", + "change_display_order": "Change display order", "change_password_form_confirm_password": "Confirmar Contraseña", "change_password_form_description": "Hola {name},\n\nEsta es la primera vez que inicias sesión en el sistema o se ha solicitado cambiar tu contraseña. Por favor, introduce la nueva contraseña a continuación.", "change_password_form_new_password": "Nueva Contraseña", "change_password_form_password_mismatch": "Las contraseñas no coinciden", "change_password_form_reenter_new_password": "Vuelve a ingresar la nueva contraseña", + "check_corrupt_asset_backup": "Check for corrupt asset backups", + "check_corrupt_asset_backup_button": "Perform check", + "check_corrupt_asset_backup_description": "Run this check only over Wi-Fi and once all assets have been backed-up. The procedure might take a few minutes.", "client_cert_dialog_msg_confirm": "OK", "client_cert_enter_password": "Introduzca contraseña", "client_cert_import": "Importar", @@ -189,9 +201,9 @@ "control_bottom_app_bar_unarchive": "Desarchivar", "control_bottom_app_bar_unfavorite": "Retirar favorito", "control_bottom_app_bar_upload": "Subir", - "create_album": "Create album", + "create_album": "Crear álbum", "create_album_page_untitled": "Sin título", - "create_new": "CREATE NEW", + "create_new": "Crear nuevo", "create_shared_album_page_create": "Crear", "create_shared_album_page_share": "Compartir", "create_shared_album_page_share_add_assets": "AGREGAR ELEMENTOS", @@ -199,6 +211,7 @@ "crop": "Recortar", "curated_location_page_title": "Lugares", "curated_object_page_title": "Objetos", + "current_server_address": "Current server address", "daily_title_text_date": "E dd, MMM", "daily_title_text_date_year": "E dd de MMM, yyyy", "date_format": "E d, LLL y • h:mm a", @@ -212,29 +225,31 @@ "delete_dialog_title": "Eliminar Permanentemente", "delete_local_dialog_ok_backed_up_only": "Borrar solo las que tengan copia de seguridad", "delete_local_dialog_ok_force": "Borrar de todos modos", - "delete_shared_link_dialog_content": "Estás seguro que quieres eliminar este enlace compartido", + "delete_shared_link_dialog_content": "¿Estás seguro que quieres eliminar este enlace compartido?", "delete_shared_link_dialog_title": "Eliminar enlace compartido", "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", - "download_canceled": "Download canceled", - "download_complete": "Download complete", - "download_enqueue": "Download enqueued", + "download_canceled": "Descarga cancelada", + "download_complete": "Descarga completada", + "download_enqueue": "Descarga en cola", "download_error": "Error al descargar", - "download_failed": "Download failed", - "download_filename": "file: {}", - "download_finished": "Download finished", - "downloading": "Downloading...", - "downloading_media": "Downloading media", - "download_notfound": "Download not found", - "download_paused": "Download paused", + "download_failed": "Descarga fallida", + "download_filename": "Archivo: {}", + "download_finished": "Descarga completada", + "downloading": "Descargando...", + "downloading_media": "Descargando medios", + "download_notfound": "Descarga no encontrada", + "download_paused": "Descarga en pausa", "download_started": "Descarga iniciada", "download_sucess": "Descarga Exitosa", "download_sucess_android": "Los archivos se han descargado en DCIM/Immich", - "download_waiting_to_retry": "Waiting to retry", + "download_waiting_to_retry": "Esperando para reintentar", "edit_date_time_dialog_date_time": "Fecha y Hora", "edit_date_time_dialog_timezone": "Zona horaria", "edit_image_title": "Editar", "edit_location_dialog_title": "Ubicación", + "enter_wifi_name": "Enter WiFi name", + "error_change_sort_album": "Failed to change album sort order", "error_saving_image": "Error: {}", "exif_bottom_sheet_description": "Agregar Descripción...", "exif_bottom_sheet_details": "DETALLES", @@ -246,11 +261,15 @@ "experimental_settings_new_asset_list_title": "Habilitar cuadrícula fotográfica experimental", "experimental_settings_subtitle": "Úsalo bajo tu responsabilidad", "experimental_settings_title": "Experimental", - "favorites": "Favorites", + "external_network": "External network", + "external_network_sheet_info": "When not on the preferred WiFi network, the app will connect to the server through the first of the below URLs it can reach, starting from top to bottom", + "favorites": "Favoritos", "favorites_page_no_favorites": "No se encontraron elementos marcados como favoritos", "favorites_page_title": "Favoritos", "filename_search": "Nombre o extensión", - "filter": "Filter", + "filter": "Filtrar", + "get_wifiname_error": "Could not get Wi-Fi name. Make sure you have granted the necessary permissions and are connected to a Wi-Fi network", + "grant_permission": "Grant permission", "haptic_feedback_switch": "Activar respuesta háptica", "haptic_feedback_title": "Respuesta Háptica", "header_settings_add_header_tip": "Añadir cabecera", @@ -258,7 +277,7 @@ "header_settings_header_name_input": "Nombre de la cabecera", "header_settings_header_value_input": "Valor de la cabecera", "header_settings_page_title": "Proxy Headers", - "headers_settings_tile_subtitle": "Define proxy headers the app should send with each network request", + "headers_settings_tile_subtitle": "Configura headers HTTP que la aplicación incluirá en cada petición de red", "headers_settings_tile_title": "Cabeceras de proxy personalizadas", "home_page_add_to_album_conflicts": "{added} elementos agregados al álbum {album}.{failed} elementos ya existen en el álbum.", "home_page_add_to_album_err_local": "Aún no se pueden agregar elementos locales a álbumes, omitiendo", @@ -274,8 +293,8 @@ "home_page_first_time_notice": "Si esta es la primera vez que usas la app, por favor, asegúrate de elegir un álbum de respaldo para que la línea de tiempo pueda cargar fotos y videos en los álbumes.", "home_page_share_err_local": "No se pueden compartir elementos locales a través de un enlace, omitiendo", "home_page_upload_err_limit": "Solo se pueden subir 30 elementos simultáneamente, omitiendo", - "ignore_icloud_photos": "Ignore iCloud photos", - "ignore_icloud_photos_description": "Photos that are stored on iCloud will not be uploaded to the Immich server", + "ignore_icloud_photos": "Ignorar fotos de iCloud", + "ignore_icloud_photos_description": "Las fotos almacenadas en iCloud no se subirán a Immich", "image_saved_successfully": "Imágenes guardas", "image_viewer_page_state_provider_download_error": "Error de descarga", "image_viewer_page_state_provider_download_started": "Descarga Iniciada", @@ -283,7 +302,7 @@ "image_viewer_page_state_provider_share_error": "Error al compartir", "invalid_date": "Fecha incorrecta", "invalid_date_format": "Formato de fecha incorrecto", - "library": "Library", + "library": "Biblioteca", "library_page_albums": "Álbumes", "library_page_archive": "Archivo", "library_page_device_albums": "Álbumes en el dispositivo", @@ -296,6 +315,10 @@ "library_page_sort_most_oldest_photo": "Foto más antigua", "library_page_sort_most_recent_photo": "Foto más reciente", "library_page_sort_title": "Título del álbum", + "local_network": "Local network", + "local_network_sheet_info": "The app will connect to the server through this URL when using the specified Wi-Fi network", + "location_permission": "Location permission", + "location_permission_content": "In order to use the auto-switching feature, Immich needs precise location permission so it can read the current WiFi network's name", "location_picker_choose_on_map": "Elegir en el mapa", "location_picker_latitude": "Latitud", "location_picker_latitude_error": "Introduce una latitud válida", @@ -334,10 +357,10 @@ "map_location_dialog_cancel": "Cancelar", "map_location_dialog_yes": "Sí", "map_location_picker_page_use_location": "Usar esta ubicación", - "map_location_service_disabled_content": "Los servicios de ubicación deben estar activados para mostrar elementos de tu ubicación actual. Deseas activarlos ahora?", + "map_location_service_disabled_content": "Los servicios de ubicación deben estar activados para mostrar elementos de tu ubicación actual. ¿Deseas activarlos ahora?", "map_location_service_disabled_title": "Servicios de ubicación desactivados", "map_no_assets_in_bounds": "No hay fotos en esta zona", - "map_no_location_permission_content": "Se necesitan permisos de ubicación para mostrar elementos de tu ubicación actual. Deseas activarlos ahora?", + "map_no_location_permission_content": "Se necesitan permisos de ubicación para mostrar elementos de tu ubicación actual. ¿Deseas activarlos ahora?", "map_no_location_permission_title": "Permisos de ubicación denegados", "map_settings_dark_mode": "Modo oscuro", "map_settings_date_range_option_all": "Todo", @@ -364,7 +387,9 @@ "motion_photos_page_title": "Foto en Movimiento", "multiselect_grid_edit_date_time_err_read_only": "No se puede cambiar la fecha del archivo(s) de solo lectura, omitiendo", "multiselect_grid_edit_gps_err_read_only": "No se puede cambiar la localización de archivos de solo lectura. Saltando.", - "my_albums": "My albums", + "my_albums": "Mis álbumes", + "networking_settings": "Red", + "networking_subtitle": "Configuraciones de acceso por URL al servidor", "no_assets_to_show": "No hay elementos a mostrar", "no_name": "Sin nombre", "notification_permission_dialog_cancel": "Cancelar", @@ -373,7 +398,7 @@ "notification_permission_list_tile_content": "Concede permiso para habilitar las notificaciones.", "notification_permission_list_tile_enable_button": "Permitir notificaciones", "notification_permission_list_tile_title": "Permisos de Notificacion", - "on_this_device": "On this device", + "on_this_device": "En este dispositivo", "partner_list_user_photos": "Fotos de {user}", "partner_list_view_all": "Ver todas", "partner_page_add_partner": "Agregar compañero", @@ -385,8 +410,8 @@ "partner_page_stop_sharing_content": "{} ya no podrá acceder a tus fotos", "partner_page_stop_sharing_title": "¿Dejar de compartir tus fotos?", "partner_page_title": "Compañero", - "partners": "Partners", - "people": "People", + "partners": "Colaboradores", + "people": "Personas", "permission_onboarding_back": "Volver", "permission_onboarding_continue_anyway": "Continuar de todos modos", "permission_onboarding_get_started": "Empezar", @@ -397,7 +422,8 @@ "permission_onboarding_permission_granted": "¡Permiso concedido! Todo listo.", "permission_onboarding_permission_limited": "Permiso limitado. Para permitir que Immich haga copia de seguridad y gestione toda tu colección de galería, concede permisos de fotos y videos en Configuración.", "permission_onboarding_request": "Immich requiere permiso para ver tus fotos y videos.", - "places": "Places", + "places": "Lugares", + "preferences_settings_subtitle": "Configuraciones de la aplicación", "preferences_settings_title": "Preferencias", "profile_drawer_app_logs": "Registros", "profile_drawer_client_out_of_date_major": "La app está desactualizada. Por favor actualiza a la última versión principal.", @@ -410,17 +436,18 @@ "profile_drawer_settings": "Configuración", "profile_drawer_sign_out": "Cerrar Sesión", "profile_drawer_trash": "Papelera", - "recently_added": "Recently added", + "recently_added": "Añadidos recientemente", "recently_added_page_title": "Recién Agregadas", + "save": "Save", "save_to_gallery": "Guardado en la galería", "scaffold_body_error_occurred": "Ha ocurrido un error", - "search_albums": "Search albums", + "search_albums": "Buscar álbum", "search_bar_hint": "Busca tus fotos", "search_filter_apply": "Aplicar filtros", "search_filter_camera": "Cámara", "search_filter_camera_make": "Marca", "search_filter_camera_model": "Modelo", - "search_filter_camera_title": "Select camera type", + "search_filter_camera_title": "Elige tipo de cámara", "search_filter_date": "Fecha", "search_filter_date_interval": "{start} al {end}", "search_filter_date_title": "Selecciona un intervalo de fechas", @@ -434,10 +461,10 @@ "search_filter_location_country": "País", "search_filter_location_state": "Estado", "search_filter_location_title": "Seleccionar una ubicación", - "search_filter_media_type": "Media Type", + "search_filter_media_type": "Tipo de archivo", "search_filter_media_type_all": "Todos", "search_filter_media_type_image": "Imagen", - "search_filter_media_type_title": "Select media type", + "search_filter_media_type_title": "Selecciona el tipo de archivo", "search_filter_media_type_video": "Vídeo", "search_filter_people": "Personas", "search_filter_people_title": "Seleccionar personas", @@ -457,6 +484,7 @@ "search_page_places": "Lugares", "search_page_recently_added": "Recién agregadas", "search_page_screenshots": "Capturas de pantalla", + "search_page_search_photos_videos": "Busca tus fotos y videos", "search_page_selfies": "Selfies", "search_page_things": "Cosas", "search_page_videos": "Videos", @@ -469,6 +497,7 @@ "select_additional_user_for_sharing_page_suggestions": "Sugerencias", "select_user_for_sharing_page_err_album": "Fallo al crear el álbum", "select_user_for_sharing_page_share_suggestions": "Sugerencias", + "server_endpoint": "Server Endpoint", "server_info_box_app_version": "Versión de la Aplicación", "server_info_box_latest_release": "Ultima versión", "server_info_box_server_url": "URL del servidor", @@ -480,6 +509,7 @@ "setting_image_viewer_preview_title": "Cargar imagen de previsualización", "setting_image_viewer_title": "Imágenes", "setting_languages_apply": "Aplicar", + "setting_languages_subtitle": "Cambia el idioma de la aplicación", "setting_languages_title": "Idiomas", "setting_notifications_notify_failures_grace_period": "Notificar fallos de copia de seguridad en segundo plano: {}", "setting_notifications_notify_hours": "{} horas", @@ -505,13 +535,13 @@ "share_create_album": "Crear álbum", "shared_album_activities_input_disable": "Los comentarios están deshabilitados", "shared_album_activities_input_hint": "Comenta algo", - "shared_album_activity_remove_content": "Deseas eliminar esta actividad?", + "shared_album_activity_remove_content": "¿Deseas eliminar esta actividad?", "shared_album_activity_remove_title": "Eliminar Actividad", "shared_album_activity_setting_subtitle": "Permitir que otros respondan", "shared_album_activity_setting_title": "Comentarios y me gusta", "shared_album_section_people_action_error": "Error retirando/eliminando del album", - "shared_album_section_people_action_leave": "Eliminar usuario del album", - "shared_album_section_people_action_remove_user": "Eliminar usuario del album", + "shared_album_section_people_action_leave": "Eliminar usuario del álbum", + "shared_album_section_people_action_remove_user": "Eliminar usuario del álbum", "shared_album_section_people_owner_label": "Propietario", "shared_album_section_people_title": "PERSONAS", "share_dialog_preparing": "Preparando...", @@ -560,9 +590,9 @@ "shared_link_info_chip_upload": "Subir", "shared_link_manage_links": "Administrar enlaces compartidos", "shared_link_public_album": "Álbum público ", - "shared_links": "Shared links", + "shared_links": "Enlaces", "share_done": "Hecho", - "shared_with_me": "Shared with me", + "shared_with_me": "Compartidos conmigo", "share_invite": "Invitar al álbum", "sharing_page_album": "Álbumes compartidos", "sharing_page_description": "Crea álbumes compartidos para compartir fotos y vídeos con las personas de tu red.", @@ -572,7 +602,7 @@ "sharing_silver_appbar_share_partner": "Compartir con el compañero", "sync": "Sincronizar", "sync_albums": "Sincronizar álbumes", - "sync_albums_manual_subtitle": "Sync all uploaded videos and photos to the selected backup albums", + "sync_albums_manual_subtitle": "Sincroniza todos los videos y fotos subidos con los álbumes seleccionados a respaldar", "sync_upload_album_setting_subtitle": "Create and upload your photos and videos to the selected albums on Immich", "tab_controller_nav_library": "Biblioteca", "tab_controller_nav_photos": "Fotos", @@ -594,7 +624,7 @@ "theme_setting_three_stage_loading_subtitle": "La carga en tres etapas puede aumentar el rendimiento de carga pero provoca un consumo de red significativamente mayor", "theme_setting_three_stage_loading_title": "Activar carga en tres etapas", "translated_text_options": "Opciones", - "trash": "Trash", + "trash": "Papelera", "trash_emptied": "Papelera vaciada", "trash_page_delete": "Eliminar", "trash_page_delete_all": "Eliminar todos", @@ -609,9 +639,11 @@ "trash_page_select_btn": "Seleccionar", "trash_page_title": "Papelera ({})", "upload_dialog_cancel": "Cancelar", - "upload_dialog_info": "Quieres hacer una copia de seguridad al servidor de los elementos seleccionados?", + "upload_dialog_info": "¿Quieres hacer una copia de seguridad al servidor de los elementos seleccionados?", "upload_dialog_ok": "Subir", "upload_dialog_title": "Subir elementos", + "use_current_connection": "use current connection", + "validate_endpoint_error": "Please enter a valid URL", "version_announcement_overlay_ack": "Aceptar", "version_announcement_overlay_release_notes": "notas de versión", "version_announcement_overlay_text_1": "Hola amigo, hay una nueva versión de", @@ -621,5 +653,7 @@ "videos": "Videos", "viewer_remove_from_stack": "Quitar de la pila", "viewer_stack_use_as_main_asset": "Usar como elemento principal", - "viewer_unstack": "Desapilar" + "viewer_unstack": "Desapilar", + "wifi_name": "WiFi Name", + "your_wifi_name": "Your WiFi name" } \ No newline at end of file diff --git a/mobile/assets/i18n/es-MX.json b/mobile/assets/i18n/es-MX.json index 8c07c6a3623ed..bcd25a556aa32 100644 --- a/mobile/assets/i18n/es-MX.json +++ b/mobile/assets/i18n/es-MX.json @@ -1,18 +1,19 @@ { "action_common_back": "Back", "action_common_cancel": "Cancel", - "action_common_clear": "Clear", + "action_common_clear": "Limpiar", "action_common_confirm": "Confirm", "action_common_save": "Save", "action_common_select": "Select", "action_common_update": "Update", "add_a_name": "Add a name", + "add_endpoint": "Add endpoint", "add_to_album_bottom_sheet_added": "Agregado a {album}", "add_to_album_bottom_sheet_already_exists": "Ya se encuentra en {album}", - "advanced_settings_log_level_title": "Log level: {}", + "advanced_settings_log_level_title": "Nivel de registro: {}", "advanced_settings_prefer_remote_subtitle": "Algunos dispositivos tardan mucho en cargar las miniaturas de recursos encontrados el dispositivo. Activa esta opción para cargar imágenes remotas en su lugar.", "advanced_settings_prefer_remote_title": "Preferir imágenes remotas", - "advanced_settings_proxy_headers_subtitle": "Define proxy headers Immich should send with each network request", + "advanced_settings_proxy_headers_subtitle": "Configura headers HTTP que Immich incluirá en cada petición de red", "advanced_settings_proxy_headers_title": "Proxy Headers", "advanced_settings_self_signed_ssl_subtitle": "Omitir verificación del certificado SSL del servidor. Requerido para certificados autofirmados", "advanced_settings_self_signed_ssl_title": "Permitir certificados autofirmados", @@ -22,7 +23,7 @@ "advanced_settings_troubleshooting_title": "Solución de problemas", "album_info_card_backup_album_excluded": "EXCLUIDOS", "album_info_card_backup_album_included": "INCLUIDOS", - "albums": "Albums", + "albums": "Álbumes", "album_thumbnail_card_item": "1 elemento", "album_thumbnail_card_items": "{} elementos", "album_thumbnail_card_shared": " · Compartido", @@ -38,7 +39,7 @@ "album_viewer_appbar_share_remove": "Eliminar del álbum", "album_viewer_appbar_share_to": "Share To", "album_viewer_page_share_add_users": "Agregar usuarios", - "all": "All", + "all": "Todos", "all_people_page_title": "Personas", "all_videos_page_title": "Videos", "app_bar_signout_dialog_content": "¿Estás seguro que quieres cerrar sesión?", @@ -61,11 +62,16 @@ "asset_restored_successfully": "Asset restored successfully", "assets_deleted_permanently": "{} asset(s) deleted permanently", "assets_deleted_permanently_from_server": "{} asset(s) deleted permanently from the Immich server", - "assets_removed_permanently_from_device": "{} asset(s) removed permanently from your device", + "assets_removed_permanently_from_device": "{} elemento(s) eliminado(s) permanentemente de su dispositivo", "assets_restored_successfully": "{} asset(s) restored successfully", "assets_trashed": "{} asset(s) trashed", "assets_trashed_from_server": "{} asset(s) trashed from the Immich server", - "asset_viewer_settings_title": "Asset Viewer", + "asset_viewer_settings_subtitle": "Administra las configuracioens de tu visor de fotos", + "asset_viewer_settings_title": "Visor de fotos", + "automatic_endpoint_switching_subtitle": "Connect locally over designated Wi-Fi when available and use alternative connections elsewhere", + "automatic_endpoint_switching_title": "Automatic URL switching", + "background_location_permission": "Background location permission", + "background_location_permission_content": "In order to switch networks when running in the background, Immich must *always* have precise location access so the app can read the Wi-Fi network's name", "backup_album_selection_page_albums_device": "Álbumes en el dispositivo ({})", "backup_album_selection_page_albums_tap": "Pulsar para incluir, pulsar dos veces para excluir", "backup_album_selection_page_assets_scatter": "Los archivos pueden dispersarse en varios álbumes. De este modo, los álbumes pueden ser incluidos o excluidos durante el proceso de copia de seguridad.", @@ -131,12 +137,13 @@ "backup_manual_success": "Éxito", "backup_manual_title": "Estado de la subida", "backup_options_page_title": "Backup options", + "backup_setting_subtitle": "Administra las configuraciones de respaldo en segundo y primer plano", "cache_settings_album_thumbnails": "Miniaturas de la página de la biblioteca ({} archivos)", "cache_settings_clear_cache_button": "Borrar caché", "cache_settings_clear_cache_button_title": "Borra la caché de la aplicación. Esto afectará significativamente el rendimiento de la aplicación hasta que se reconstruya la caché.", - "cache_settings_duplicated_assets_clear_button": "CLEAR", + "cache_settings_duplicated_assets_clear_button": "LIMPIAR", "cache_settings_duplicated_assets_subtitle": "Photos and videos that are black listed by the app", - "cache_settings_duplicated_assets_title": "Duplicated Assets ({})", + "cache_settings_duplicated_assets_title": "Elementos duplicados ({})", "cache_settings_image_cache_size": "Tamaño de la caché de imágenes ({} archivos)", "cache_settings_statistics_album": "Miniaturas de la biblioteca", "cache_settings_statistics_assets": "{} archivos ({})", @@ -149,17 +156,22 @@ "cache_settings_tile_subtitle": "Controla el comportamiento del almacenamiento local", "cache_settings_tile_title": "Almacenamiento local", "cache_settings_title": "Configuración de la caché", + "cancel": "Cancel", + "change_display_order": "Change display order", "change_password_form_confirm_password": "Confirmar Contraseña", "change_password_form_description": "Hola {name},\n\nEsta es la primera vez que inicias sesión en el sistema o se ha solicitado cambiar tu contraseña. Por favor, introduce la nueva contraseña a continuación.", "change_password_form_new_password": "Nueva Contraseña", "change_password_form_password_mismatch": "Las contraseñas no coinciden", "change_password_form_reenter_new_password": "Vuelve a ingresar la nueva contraseña", + "check_corrupt_asset_backup": "Check for corrupt asset backups", + "check_corrupt_asset_backup_button": "Perform check", + "check_corrupt_asset_backup_description": "Run this check only over Wi-Fi and once all assets have been backed-up. The procedure might take a few minutes.", "client_cert_dialog_msg_confirm": "OK", "client_cert_enter_password": "Enter Password", - "client_cert_import": "Import", + "client_cert_import": "Importar", "client_cert_import_success_msg": "Client certificate is imported", "client_cert_invalid_msg": "Invalid certificate file or wrong password", - "client_cert_remove": "Remove", + "client_cert_remove": "Eliminar", "client_cert_remove_msg": "Client certificate is removed", "client_cert_subtitle": "Supports PKCS12 (.p12, .pfx) format only. Certificate Import/Remove is available only before login", "client_cert_title": "SSL Client Certificate", @@ -168,7 +180,7 @@ "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_shared": "Compartido", - "contextual_search": "Sunrise on the beach", + "contextual_search": "Amanecer en la playa", "control_bottom_app_bar_add_to_album": "Agregar al álbum", "control_bottom_app_bar_album_info": "{} elementos", "control_bottom_app_bar_album_info_shared": "{} elementos · Compartidos", @@ -199,12 +211,13 @@ "crop": "Crop", "curated_location_page_title": "Lugares", "curated_object_page_title": "Objetos", + "current_server_address": "Current server address", "daily_title_text_date": "E, dd MMM", "daily_title_text_date_year": "E, dd de MMM de yyyy", "date_format": "E d, LLL y • h:mm a", "delete_dialog_alert": "Estos elementos se eliminarán permanentemente de Immich y de tu dispositivo", "delete_dialog_alert_local": "These items will be permanently removed from your device but still be available on the Immich server", - "delete_dialog_alert_local_non_backed_up": "Some of the items aren't backed up to Immich and will be permanently removed from your device", + "delete_dialog_alert_local_non_backed_up": "Algunas de las imágenes no tienen copia de seguridad y serán borradas de forma permanente de tu dispositivo", "delete_dialog_alert_remote": "These items will be permanently deleted from the Immich server", "delete_dialog_cancel": "Cancelar", "delete_dialog_ok": "Eliminar", @@ -212,7 +225,7 @@ "delete_dialog_title": "Eliminar permanentemente", "delete_local_dialog_ok_backed_up_only": "Delete Backed Up Only", "delete_local_dialog_ok_force": "Delete Anyway", - "delete_shared_link_dialog_content": "Estás seguro que quieres eliminar este enlace compartido", + "delete_shared_link_dialog_content": "¿Estás seguro que quieres eliminar este enlace compartido?", "delete_shared_link_dialog_title": "Eliminar enlace compartido", "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", @@ -235,22 +248,28 @@ "edit_date_time_dialog_timezone": "Timezone", "edit_image_title": "Edit", "edit_location_dialog_title": "Location", + "enter_wifi_name": "Enter WiFi name", + "error_change_sort_album": "Failed to change album sort order", "error_saving_image": "Error: {}", "exif_bottom_sheet_description": "Agregar Descripción...", "exif_bottom_sheet_details": "DETALLES", "exif_bottom_sheet_location": "UBICACIÓN", "exif_bottom_sheet_location_add": "Add a location", - "exif_bottom_sheet_people": "PEOPLE", + "exif_bottom_sheet_people": "PERSONAS", "exif_bottom_sheet_person_add_person": "Add name", "experimental_settings_new_asset_list_subtitle": "Trabajo en progreso", "experimental_settings_new_asset_list_title": "Habilitar cuadrícula fotográfica experimental", "experimental_settings_subtitle": "Úsalo bajo tu responsabilidad", "experimental_settings_title": "Experimental", - "favorites": "Favorites", + "external_network": "External network", + "external_network_sheet_info": "When not on the preferred WiFi network, the app will connect to the server through the first of the below URLs it can reach, starting from top to bottom", + "favorites": "Favoritos", "favorites_page_no_favorites": "No se encontraron recursos marcados como favoritos", "favorites_page_title": "Favoritos", "filename_search": "File name or extension", "filter": "Filter", + "get_wifiname_error": "Could not get Wi-Fi name. Make sure you have granted the necessary permissions and are connected to a Wi-Fi network", + "grant_permission": "Grant permission", "haptic_feedback_switch": "Enable haptic feedback", "haptic_feedback_title": "Haptic Feedback", "header_settings_add_header_tip": "Add Header", @@ -258,8 +277,8 @@ "header_settings_header_name_input": "Header name", "header_settings_header_value_input": "Header value", "header_settings_page_title": "Proxy Headers", - "headers_settings_tile_subtitle": "Define proxy headers the app should send with each network request", - "headers_settings_tile_title": "Custom proxy headers", + "headers_settings_tile_subtitle": "Configura headers HTTP que la aplicación incluirá en cada petición de red", + "headers_settings_tile_title": "Cabeceras de proxy personalizadas", "home_page_add_to_album_conflicts": "{added} elementos agregados al álbum {album}.\n{failed} elementos ya existen en el álbum.", "home_page_add_to_album_err_local": "Aún no se pueden agregar recursos locales a álbumes, omitiendo", "home_page_add_to_album_success": "{added} elementos agregados al álbum {album}. ", @@ -283,19 +302,23 @@ "image_viewer_page_state_provider_share_error": "Error al compartir", "invalid_date": "Invalid date", "invalid_date_format": "Invalid date format", - "library": "Library", + "library": "Biblioteca", "library_page_albums": "Álbumes", "library_page_archive": "Archivo", "library_page_device_albums": "Álbumes en el dispositivo", "library_page_favorites": "Favoritos", "library_page_new_album": "Nuevo álbum", "library_page_sharing": "Compartiendo", - "library_page_sort_asset_count": "Number of assets", + "library_page_sort_asset_count": "Número de elementos", "library_page_sort_created": "Creado más recientemente", "library_page_sort_last_modified": "Última modificación", - "library_page_sort_most_oldest_photo": "Oldest photo", + "library_page_sort_most_oldest_photo": "Foto más antigua", "library_page_sort_most_recent_photo": "Foto más reciente", "library_page_sort_title": "Título del álbum", + "local_network": "Local network", + "local_network_sheet_info": "The app will connect to the server through this URL when using the specified Wi-Fi network", + "location_permission": "Location permission", + "location_permission_content": "In order to use the auto-switching feature, Immich needs precise location permission so it can read the current WiFi network's name", "location_picker_choose_on_map": "Choose on map", "location_picker_latitude": "Latitude", "location_picker_latitude_error": "Enter a valid latitude", @@ -334,10 +357,10 @@ "map_location_dialog_cancel": "Cancelar", "map_location_dialog_yes": "Sí", "map_location_picker_page_use_location": "Use this location", - "map_location_service_disabled_content": "Los servicios de localización deben estar activados para mostrar elementos de tu ubicación actual. Deseas activarlos ahora?", + "map_location_service_disabled_content": "Los servicios de localización deben estar activados para mostrar elementos de tu ubicación actual. ¿Deseas activarlos ahora?", "map_location_service_disabled_title": "Servicios de localización desactivados", "map_no_assets_in_bounds": "No hay fotos en esta zona", - "map_no_location_permission_content": "Se necesitan permisos de ubicación para mostrar elementos de tu ubicación actual. Deseas activarlos ahora?", + "map_no_location_permission_content": "Se necesitan permisos de ubicación para mostrar elementos de tu ubicación actual. ¿Deseas activarlos ahora?", "map_no_location_permission_title": "Permisos de ubicación denegados", "map_settings_dark_mode": "Modo oscuro", "map_settings_date_range_option_all": "All", @@ -358,13 +381,15 @@ "memories_check_back_tomorrow": "Check back tomorrow for more memories", "memories_start_over": "Start Over", "memories_swipe_to_close": "Swipe up to close", - "memories_year_ago": "A year ago", - "memories_years_ago": "{} years ago", + "memories_year_ago": "Hace un año", + "memories_years_ago": "Hace {} años", "monthly_title_text_date_format": "MMMM y", "motion_photos_page_title": "Foto en Movimiento", "multiselect_grid_edit_date_time_err_read_only": "Cannot edit date of read only asset(s), skipping", "multiselect_grid_edit_gps_err_read_only": "Cannot edit location of read only asset(s), skipping", - "my_albums": "My albums", + "my_albums": "Mis álbumes", + "networking_settings": "Red", + "networking_subtitle": "Configuraciones de acceso por URL al servidor", "no_assets_to_show": "No assets to show", "no_name": "No name", "notification_permission_dialog_cancel": "Cancelar", @@ -386,7 +411,7 @@ "partner_page_stop_sharing_title": "¿Dejar de compartir tus fotos?", "partner_page_title": "Compañero", "partners": "Partners", - "people": "People", + "people": "Personas", "permission_onboarding_back": "Volver", "permission_onboarding_continue_anyway": "Continuar de todos modos", "permission_onboarding_get_started": "Empezar", @@ -398,7 +423,8 @@ "permission_onboarding_permission_limited": "Permiso limitado. Para permitir que Immich haga copia de seguridad y gestione toda tu colección de galería, concede permisos de fotos y videos en Configuración.", "permission_onboarding_request": "Immich requiere permiso para ver tus fotos y videos.", "places": "Places", - "preferences_settings_title": "Preferences", + "preferences_settings_subtitle": "Configuraciones de la aplicación", + "preferences_settings_title": "Preferencias", "profile_drawer_app_logs": "Registros", "profile_drawer_client_out_of_date_major": "Mobile App is out of date. Please update to the latest major version.", "profile_drawer_client_out_of_date_minor": "Mobile App is out of date. Please update to the latest minor version.", @@ -410,18 +436,19 @@ "profile_drawer_settings": "Configuración", "profile_drawer_sign_out": "Cerrar sesión", "profile_drawer_trash": "Papelera", - "recently_added": "Recently added", + "recently_added": "Añadidos recientemente", "recently_added_page_title": "Recién Agregadas", + "save": "Save", "save_to_gallery": "Save to gallery", "scaffold_body_error_occurred": "Error occurred", - "search_albums": "Search albums", + "search_albums": "Buscar álbum", "search_bar_hint": "Busca tus fotos", "search_filter_apply": "Apply filter", - "search_filter_camera": "Camera", - "search_filter_camera_make": "Make", - "search_filter_camera_model": "Model", - "search_filter_camera_title": "Select camera type", - "search_filter_date": "Date", + "search_filter_camera": "Cámara", + "search_filter_camera_make": "Marca", + "search_filter_camera_model": "Modelo", + "search_filter_camera_title": "Elige tipo de cámara", + "search_filter_date": "Fecha", "search_filter_date_interval": "{start} to {end}", "search_filter_date_title": "Select a date range", "search_filter_display_option_archive": "Archive", @@ -429,18 +456,18 @@ "search_filter_display_option_not_in_album": "Not in album", "search_filter_display_options": "Display Options", "search_filter_display_options_title": "Display options", - "search_filter_location": "Location", + "search_filter_location": "Ubicación", "search_filter_location_city": "City", "search_filter_location_country": "Country", "search_filter_location_state": "State", "search_filter_location_title": "Select location", - "search_filter_media_type": "Media Type", + "search_filter_media_type": "Tipo de archivo", "search_filter_media_type_all": "All", "search_filter_media_type_image": "Image", - "search_filter_media_type_title": "Select media type", + "search_filter_media_type_title": "Selecciona el tipo de archivo", "search_filter_media_type_video": "Video", - "search_filter_people": "People", - "search_filter_people_title": "Select people", + "search_filter_people": "Personas", + "search_filter_people_title": "Seleccionar personas", "search_page_categories": "Categorías", "search_page_favorites": "Favoritos", "search_page_motion_photos": "Foto en Movimiento", @@ -457,6 +484,7 @@ "search_page_places": "Lugares", "search_page_recently_added": "Recién agregadas", "search_page_screenshots": "Capturas de pantalla", + "search_page_search_photos_videos": "Busca tus fotos y videos", "search_page_selfies": "Selfies", "search_page_things": "Cosas", "search_page_videos": "Videos", @@ -469,6 +497,7 @@ "select_additional_user_for_sharing_page_suggestions": "Sugerencias", "select_user_for_sharing_page_err_album": "Error al crear álbum", "select_user_for_sharing_page_share_suggestions": "Sugerencias", + "server_endpoint": "Server Endpoint", "server_info_box_app_version": "Versión de la Aplicación", "server_info_box_latest_release": "Ultima versión", "server_info_box_server_url": "URL del servidor", @@ -478,9 +507,10 @@ "setting_image_viewer_original_title": "Cargar imagen original", "setting_image_viewer_preview_subtitle": "Activar para cargar una imagen de resolución media. Deshabilitar para cargar directamente la imagen original o usar una miniatura.", "setting_image_viewer_preview_title": "Cargar imagen de previsualización", - "setting_image_viewer_title": "Images", - "setting_languages_apply": "Apply", - "setting_languages_title": "Languages", + "setting_image_viewer_title": "Imágenes", + "setting_languages_apply": "Aplicar", + "setting_languages_subtitle": "Cambia el idioma de la aplicación", + "setting_languages_title": "Idiomas", "setting_notifications_notify_failures_grace_period": "Notificar fallos de copia de seguridad en segundo plano: {}", "setting_notifications_notify_hours": "{} horas", "setting_notifications_notify_immediately": "inmediatamente", @@ -495,8 +525,8 @@ "setting_notifications_total_progress_title": "Mostrar progreso total de copia de seguridad en segundo plano", "setting_pages_app_bar_settings": "Ajustes", "settings_require_restart": "Por favor, reinicia Immich para aplicar este ajuste", - "setting_video_viewer_looping_subtitle": "Enable to automatically loop a video in the detail viewer.", - "setting_video_viewer_looping_title": "Looping", + "setting_video_viewer_looping_subtitle": "Habilitar reproducción en bucle del video en la vista detallada", + "setting_video_viewer_looping_title": "Bucle", "setting_video_viewer_title": "Videos", "share_add": "Agregar", "share_add_photos": "Agregar fotos", @@ -505,15 +535,15 @@ "share_create_album": "Crear álbum", "shared_album_activities_input_disable": "Los comentarios están deshabilitados", "shared_album_activities_input_hint": "Say something", - "shared_album_activity_remove_content": "Do you want to delete this activity?", + "shared_album_activity_remove_content": "¿Quieres eliminar esta actividad?", "shared_album_activity_remove_title": "Delete Activity", "shared_album_activity_setting_subtitle": "Let others respond", "shared_album_activity_setting_title": "Comments & likes", - "shared_album_section_people_action_error": "Error leaving/removing from album", - "shared_album_section_people_action_leave": "Remove user from album", - "shared_album_section_people_action_remove_user": "Remove user from album", - "shared_album_section_people_owner_label": "Owner", - "shared_album_section_people_title": "PEOPLE", + "shared_album_section_people_action_error": "Error retirando/eliminando del album", + "shared_album_section_people_action_leave": "Eliminar usuario del álbum", + "shared_album_section_people_action_remove_user": "Eliminar usuario del álbum", + "shared_album_section_people_owner_label": "Propietario", + "shared_album_section_people_title": "PERSONAS", "share_dialog_preparing": "Preparando...", "shared_link_app_bar_title": "Enlaces compartidos", "shared_link_clipboard_copied_massage": "Copied to clipboard", @@ -562,7 +592,7 @@ "shared_link_public_album": "Public album", "shared_links": "Shared links", "share_done": "Hecho", - "shared_with_me": "Shared with me", + "shared_with_me": "Compartidos conmigo", "share_invite": "Invitar al álbum", "sharing_page_album": "Álbumes compartidos", "sharing_page_description": "Crea álbumes compartidos para compartir fotos y videos con personas de tu red.", @@ -571,8 +601,8 @@ "sharing_silver_appbar_shared_links": "Enlaces compartidos", "sharing_silver_appbar_share_partner": "Compartir con compañero", "sync": "Sync", - "sync_albums": "Sync albums", - "sync_albums_manual_subtitle": "Sync all uploaded videos and photos to the selected backup albums", + "sync_albums": "Sincronizar álbumes", + "sync_albums_manual_subtitle": "Sincroniza todos los videos y fotos subidos con los álbumes seleccionados a respaldar", "sync_upload_album_setting_subtitle": "Create and upload your photos and videos to the selected albums on Immich", "tab_controller_nav_library": "Biblioteca", "tab_controller_nav_photos": "Fotos", @@ -599,7 +629,7 @@ "trash_page_delete": "Eliminar", "trash_page_delete_all": "Eliminar todos", "trash_page_empty_trash_btn": "Vaciar papelera", - "trash_page_empty_trash_dialog_content": "Estás seguro que quieres eliminar los elementos? Estos elementos serán eliminados de Immich permanentemente", + "trash_page_empty_trash_dialog_content": "¿Estás seguro que quieres eliminar los elementos? Estos elementos serán eliminados de Immich permanentemente", "trash_page_empty_trash_dialog_ok": "Sí", "trash_page_info": "Los archivos en la papelera serán eliminados automáticamente después de {} días", "trash_page_no_assets": "No hay elementos en la papelera", @@ -609,9 +639,11 @@ "trash_page_select_btn": "Seleccionar", "trash_page_title": "Papelera ({})", "upload_dialog_cancel": "Cancelar", - "upload_dialog_info": "Quieres hacer una copia de seguridad al servidor de los elementos seleccionados?", + "upload_dialog_info": "¿Quieres hacer una copia de seguridad al servidor de los elementos seleccionados?", "upload_dialog_ok": "Subir", "upload_dialog_title": "Subir elementos", + "use_current_connection": "use current connection", + "validate_endpoint_error": "Please enter a valid URL", "version_announcement_overlay_ack": "Aceptar", "version_announcement_overlay_release_notes": "notas de la versión", "version_announcement_overlay_text_1": "Hola, amigo, hay una nueva versión de", @@ -621,5 +653,7 @@ "videos": "Videos", "viewer_remove_from_stack": "Quitar de la pila", "viewer_stack_use_as_main_asset": "Usar como elemento principal", - "viewer_unstack": "Desapilar" + "viewer_unstack": "Desapilar", + "wifi_name": "WiFi Name", + "your_wifi_name": "Your WiFi name" } \ No newline at end of file diff --git a/mobile/assets/i18n/es-PE.json b/mobile/assets/i18n/es-PE.json index 23eaa437ff0ed..3e62730ef2df2 100644 --- a/mobile/assets/i18n/es-PE.json +++ b/mobile/assets/i18n/es-PE.json @@ -1,12 +1,13 @@ { "action_common_back": "Back", "action_common_cancel": "Cancel", - "action_common_clear": "Clear", + "action_common_clear": "Limpiar", "action_common_confirm": "Confirm", "action_common_save": "Save", "action_common_select": "Select", "action_common_update": "Update", "add_a_name": "Add a name", + "add_endpoint": "Add endpoint", "add_to_album_bottom_sheet_added": "Agregado a {album}", "add_to_album_bottom_sheet_already_exists": "Ya se encuentra en {album}", "advanced_settings_log_level_title": "Log level: {}", @@ -65,7 +66,12 @@ "assets_restored_successfully": "{} asset(s) restored successfully", "assets_trashed": "{} asset(s) trashed", "assets_trashed_from_server": "{} asset(s) trashed from the Immich server", + "asset_viewer_settings_subtitle": "Manage your gallery viewer settings", "asset_viewer_settings_title": "Asset Viewer", + "automatic_endpoint_switching_subtitle": "Connect locally over designated Wi-Fi when available and use alternative connections elsewhere", + "automatic_endpoint_switching_title": "Automatic URL switching", + "background_location_permission": "Background location permission", + "background_location_permission_content": "In order to switch networks when running in the background, Immich must *always* have precise location access so the app can read the Wi-Fi network's name", "backup_album_selection_page_albums_device": "Álbumes en el dispositivo ({})", "backup_album_selection_page_albums_tap": "Pulsar para incluir, pulsar dos veces para excluir", "backup_album_selection_page_assets_scatter": "Los archivos pueden dispersarse en varios álbumes. De este modo, los álbumes pueden ser incluidos o excluidos durante el proceso de copia de seguridad.", @@ -131,10 +137,11 @@ "backup_manual_success": "Éxito", "backup_manual_title": "Estado de la subida", "backup_options_page_title": "Backup options", + "backup_setting_subtitle": "Manage background and foreground upload settings", "cache_settings_album_thumbnails": "Miniaturas de la página de la biblioteca ({} archivos)", "cache_settings_clear_cache_button": "Borrar caché", "cache_settings_clear_cache_button_title": "Borra la caché de la aplicación. Esto afectará significativamente el rendimiento de la aplicación hasta que se reconstruya la caché.", - "cache_settings_duplicated_assets_clear_button": "CLEAR", + "cache_settings_duplicated_assets_clear_button": "LIMPIAR", "cache_settings_duplicated_assets_subtitle": "Photos and videos that are black listed by the app", "cache_settings_duplicated_assets_title": "Duplicated Assets ({})", "cache_settings_image_cache_size": "Tamaño de la caché de imágenes ({} archivos)", @@ -149,11 +156,16 @@ "cache_settings_tile_subtitle": "Controla el comportamiento del almacenamiento local", "cache_settings_tile_title": "Almacenamiento local", "cache_settings_title": "Configuración de la caché", + "cancel": "Cancel", + "change_display_order": "Change display order", "change_password_form_confirm_password": "Confirmar Contraseña", "change_password_form_description": "Hola {name},\n\nEsta es la primera vez que inicias sesión en el sistema o se ha solicitado cambiar tu contraseña. Por favor, introduce la nueva contraseña a continuación.", "change_password_form_new_password": "Nueva Contraseña", "change_password_form_password_mismatch": "Las contraseñas no coinciden", "change_password_form_reenter_new_password": "Vuelve a ingresar la nueva contraseña", + "check_corrupt_asset_backup": "Check for corrupt asset backups", + "check_corrupt_asset_backup_button": "Perform check", + "check_corrupt_asset_backup_description": "Run this check only over Wi-Fi and once all assets have been backed-up. The procedure might take a few minutes.", "client_cert_dialog_msg_confirm": "OK", "client_cert_enter_password": "Enter Password", "client_cert_import": "Import", @@ -199,6 +211,7 @@ "crop": "Crop", "curated_location_page_title": "Lugares", "curated_object_page_title": "Objetos", + "current_server_address": "Current server address", "daily_title_text_date": "E, dd MMM", "daily_title_text_date_year": "E, dd de MMM de yyyy", "date_format": "E d, LLL y • h:mm a", @@ -212,7 +225,7 @@ "delete_dialog_title": "Eliminar permanentemente", "delete_local_dialog_ok_backed_up_only": "Delete Backed Up Only", "delete_local_dialog_ok_force": "Delete Anyway", - "delete_shared_link_dialog_content": "Estás seguro que quieres eliminar este enlace compartido", + "delete_shared_link_dialog_content": "¿Estás seguro que quieres eliminar este enlace compartido?", "delete_shared_link_dialog_title": "Eliminar enlace compartido", "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", @@ -235,6 +248,8 @@ "edit_date_time_dialog_timezone": "Timezone", "edit_image_title": "Edit", "edit_location_dialog_title": "Location", + "enter_wifi_name": "Enter WiFi name", + "error_change_sort_album": "Failed to change album sort order", "error_saving_image": "Error: {}", "exif_bottom_sheet_description": "Agregar Descripción...", "exif_bottom_sheet_details": "DETALLES", @@ -246,11 +261,15 @@ "experimental_settings_new_asset_list_title": "Habilitar cuadrícula fotográfica experimental", "experimental_settings_subtitle": "Úsalo bajo tu responsabilidad", "experimental_settings_title": "Experimental", + "external_network": "External network", + "external_network_sheet_info": "When not on the preferred WiFi network, the app will connect to the server through the first of the below URLs it can reach, starting from top to bottom", "favorites": "Favorites", "favorites_page_no_favorites": "No se encontraron recursos marcados como favoritos", "favorites_page_title": "Favoritos", "filename_search": "File name or extension", "filter": "Filter", + "get_wifiname_error": "Could not get Wi-Fi name. Make sure you have granted the necessary permissions and are connected to a Wi-Fi network", + "grant_permission": "Grant permission", "haptic_feedback_switch": "Enable haptic feedback", "haptic_feedback_title": "Haptic Feedback", "header_settings_add_header_tip": "Add Header", @@ -296,6 +315,10 @@ "library_page_sort_most_oldest_photo": "Oldest photo", "library_page_sort_most_recent_photo": "Foto más reciente", "library_page_sort_title": "Título del álbum", + "local_network": "Local network", + "local_network_sheet_info": "The app will connect to the server through this URL when using the specified Wi-Fi network", + "location_permission": "Location permission", + "location_permission_content": "In order to use the auto-switching feature, Immich needs precise location permission so it can read the current WiFi network's name", "location_picker_choose_on_map": "Choose on map", "location_picker_latitude": "Latitude", "location_picker_latitude_error": "Enter a valid latitude", @@ -334,10 +357,10 @@ "map_location_dialog_cancel": "Cancelar", "map_location_dialog_yes": "Sí", "map_location_picker_page_use_location": "Use this location", - "map_location_service_disabled_content": "Los servicios de localización deben estar activados para mostrar elementos de tu ubicación actual. Deseas activarlos ahora?", + "map_location_service_disabled_content": "Los servicios de localización deben estar activados para mostrar elementos de tu ubicación actual. ¿Deseas activarlos ahora?", "map_location_service_disabled_title": "Servicios de localización desactivados", "map_no_assets_in_bounds": "No hay fotos en esta zona", - "map_no_location_permission_content": "Se necesitan permisos de ubicación para mostrar elementos de tu ubicación actual. Deseas activarlos ahora?", + "map_no_location_permission_content": "Se necesitan permisos de ubicación para mostrar elementos de tu ubicación actual. ¿Deseas activarlos ahora?", "map_no_location_permission_title": "Permisos de ubicación denegados", "map_settings_dark_mode": "Modo oscuro", "map_settings_date_range_option_all": "All", @@ -365,6 +388,8 @@ "multiselect_grid_edit_date_time_err_read_only": "Cannot edit date of read only asset(s), skipping", "multiselect_grid_edit_gps_err_read_only": "Cannot edit location of read only asset(s), skipping", "my_albums": "My albums", + "networking_settings": "Networking", + "networking_subtitle": "Manage the server endpoint settings", "no_assets_to_show": "No assets to show", "no_name": "No name", "notification_permission_dialog_cancel": "Cancelar", @@ -398,6 +423,7 @@ "permission_onboarding_permission_limited": "Permiso limitado. Para permitir que Immich haga copia de seguridad y gestione toda tu colección de galería, concede permisos de fotos y videos en Configuración.", "permission_onboarding_request": "Immich requiere permiso para ver tus fotos y videos.", "places": "Places", + "preferences_settings_subtitle": "Manage the app's preferences", "preferences_settings_title": "Preferences", "profile_drawer_app_logs": "Registros", "profile_drawer_client_out_of_date_major": "Mobile App is out of date. Please update to the latest major version.", @@ -412,6 +438,7 @@ "profile_drawer_trash": "Papelera", "recently_added": "Recently added", "recently_added_page_title": "Recién Agregadas", + "save": "Save", "save_to_gallery": "Save to gallery", "scaffold_body_error_occurred": "Error occurred", "search_albums": "Search albums", @@ -457,6 +484,7 @@ "search_page_places": "Lugares", "search_page_recently_added": "Recién agregadas", "search_page_screenshots": "Capturas de pantalla", + "search_page_search_photos_videos": "Search for your photos and videos", "search_page_selfies": "Selfies", "search_page_things": "Cosas", "search_page_videos": "Videos", @@ -469,6 +497,7 @@ "select_additional_user_for_sharing_page_suggestions": "Sugerencias", "select_user_for_sharing_page_err_album": "Error al crear álbum", "select_user_for_sharing_page_share_suggestions": "Sugerencias", + "server_endpoint": "Server Endpoint", "server_info_box_app_version": "Versión de la Aplicación", "server_info_box_latest_release": "Ultima versión", "server_info_box_server_url": "URL del servidor", @@ -480,6 +509,7 @@ "setting_image_viewer_preview_title": "Cargar imagen de previsualización", "setting_image_viewer_title": "Images", "setting_languages_apply": "Apply", + "setting_languages_subtitle": "Change the app's language", "setting_languages_title": "Languages", "setting_notifications_notify_failures_grace_period": "Notificar fallos de copia de seguridad en segundo plano: {}", "setting_notifications_notify_hours": "{} horas", @@ -505,7 +535,7 @@ "share_create_album": "Crear álbum", "shared_album_activities_input_disable": "Los comentarios están deshabilitados", "shared_album_activities_input_hint": "Comenta algo", - "shared_album_activity_remove_content": "Deseas eliminar esta actividad?", + "shared_album_activity_remove_content": "¿Deseas eliminar esta actividad?", "shared_album_activity_remove_title": "Eliminar Actividad", "shared_album_activity_setting_subtitle": "Permitir que otros respondan", "shared_album_activity_setting_title": "Comentarios y me gusta", @@ -599,7 +629,7 @@ "trash_page_delete": "Eliminar", "trash_page_delete_all": "Eliminar todos", "trash_page_empty_trash_btn": "Vaciar papelera", - "trash_page_empty_trash_dialog_content": "Estás seguro que quieres eliminar los elementos? Estos elementos serán eliminados de Immich permanentemente", + "trash_page_empty_trash_dialog_content": "¿Estás seguro que quieres eliminar los elementos? Estos elementos serán eliminados de Immich permanentemente", "trash_page_empty_trash_dialog_ok": "Sí", "trash_page_info": "Los archivos en la papelera serán eliminados automáticamente después de {} días", "trash_page_no_assets": "No hay elementos en la papelera", @@ -609,9 +639,11 @@ "trash_page_select_btn": "Seleccionar", "trash_page_title": "Papelera ({})", "upload_dialog_cancel": "Cancelar", - "upload_dialog_info": "Quieres hacer una copia de seguridad al servidor de los elementos seleccionados?", + "upload_dialog_info": "¿Quieres hacer una copia de seguridad al servidor de los elementos seleccionados?", "upload_dialog_ok": "Subir", "upload_dialog_title": "Subir elementos", + "use_current_connection": "use current connection", + "validate_endpoint_error": "Please enter a valid URL", "version_announcement_overlay_ack": "Aceptar", "version_announcement_overlay_release_notes": "notas de la versión", "version_announcement_overlay_text_1": "Hola, amigo, hay una nueva versión de", @@ -621,5 +653,7 @@ "videos": "Videos", "viewer_remove_from_stack": "Quitar de la pila", "viewer_stack_use_as_main_asset": "Usar como elemento principal", - "viewer_unstack": "Desapilar" + "viewer_unstack": "Desapilar", + "wifi_name": "WiFi Name", + "your_wifi_name": "Your WiFi name" } \ No newline at end of file diff --git a/mobile/assets/i18n/es-US.json b/mobile/assets/i18n/es-US.json index 61c84d0054cdc..489232eb505b6 100644 --- a/mobile/assets/i18n/es-US.json +++ b/mobile/assets/i18n/es-US.json @@ -1,18 +1,19 @@ { "action_common_back": "Back", "action_common_cancel": "Cancel", - "action_common_clear": "Clear", + "action_common_clear": "Limpiar", "action_common_confirm": "Confirm", "action_common_save": "Save", "action_common_select": "Select", "action_common_update": "Update", "add_a_name": "Add a name", + "add_endpoint": "Add endpoint", "add_to_album_bottom_sheet_added": "Agregado a {album}", "add_to_album_bottom_sheet_already_exists": "Ya se encuentra en {album}", - "advanced_settings_log_level_title": "Log level: {}", + "advanced_settings_log_level_title": "Nivel de registro: {}", "advanced_settings_prefer_remote_subtitle": "Algunos dispositivos tardan mucho en cargar las miniaturas de recursos encontrados en el dispositivo. Activa esta opción para cargar imágenes remotas en su lugar.", "advanced_settings_prefer_remote_title": "Preferir imágenes remotas", - "advanced_settings_proxy_headers_subtitle": "Define proxy headers Immich should send with each network request", + "advanced_settings_proxy_headers_subtitle": "Configura headers HTTP que Immich incluirá en cada petición de red", "advanced_settings_proxy_headers_title": "Proxy Headers", "advanced_settings_self_signed_ssl_subtitle": "Omite la verificación del certificado SSL para la URL del servidor. Requerido para certificados autofirmados.", "advanced_settings_self_signed_ssl_title": "Permitir certificados SSL autofirmados", @@ -22,7 +23,7 @@ "advanced_settings_troubleshooting_title": "Solución de problemas", "album_info_card_backup_album_excluded": "EXCLUIDOS", "album_info_card_backup_album_included": "INCLUIDOS", - "albums": "Albums", + "albums": "Álbumes", "album_thumbnail_card_item": "1 elemento", "album_thumbnail_card_items": "{} elementos", "album_thumbnail_card_shared": " · Compartido", @@ -38,7 +39,7 @@ "album_viewer_appbar_share_remove": "Remover del álbum", "album_viewer_appbar_share_to": "Compartir con", "album_viewer_page_share_add_users": "Agregar usuarios", - "all": "All", + "all": "Todos", "all_people_page_title": "Personas", "all_videos_page_title": "Videos", "app_bar_signout_dialog_content": "¿Estás seguro de que quieres cerrar sesión?", @@ -61,11 +62,16 @@ "asset_restored_successfully": "Asset restored successfully", "assets_deleted_permanently": "{} asset(s) deleted permanently", "assets_deleted_permanently_from_server": "{} asset(s) deleted permanently from the Immich server", - "assets_removed_permanently_from_device": "{} asset(s) removed permanently from your device", + "assets_removed_permanently_from_device": "{} elemento(s) eliminado(s) permanentemente de su dispositivo", "assets_restored_successfully": "{} asset(s) restored successfully", "assets_trashed": "{} asset(s) trashed", "assets_trashed_from_server": "{} asset(s) trashed from the Immich server", - "asset_viewer_settings_title": "Asset Viewer", + "asset_viewer_settings_subtitle": "Administra las configuracioens de tu visor de fotos", + "asset_viewer_settings_title": "Visor de fotos", + "automatic_endpoint_switching_subtitle": "Connect locally over designated Wi-Fi when available and use alternative connections elsewhere", + "automatic_endpoint_switching_title": "Automatic URL switching", + "background_location_permission": "Background location permission", + "background_location_permission_content": "In order to switch networks when running in the background, Immich must *always* have precise location access so the app can read the Wi-Fi network's name", "backup_album_selection_page_albums_device": "Álbumes en el dispositivo ({})", "backup_album_selection_page_albums_tap": "Pulsar para incluir, pulsar dos veces para excluir", "backup_album_selection_page_assets_scatter": "Los archivos pueden dispersarse en varios álbumes. De este modo, los álbumes pueden ser incluidos o excluidos durante el proceso de copia de seguridad.", @@ -131,12 +137,13 @@ "backup_manual_success": "Exitoso", "backup_manual_title": "Estado de subida", "backup_options_page_title": "Backup options", + "backup_setting_subtitle": "Administra las configuraciones de respaldo en segundo y primer plano", "cache_settings_album_thumbnails": "Miniaturas de la página de la biblioteca ({} recursos)", "cache_settings_clear_cache_button": "Borrar caché", "cache_settings_clear_cache_button_title": "Borra la caché de la aplicación. Esto afectará significativamente el rendimiento de la aplicación hasta que se reconstruya la caché.", - "cache_settings_duplicated_assets_clear_button": "CLEAR", + "cache_settings_duplicated_assets_clear_button": "LIMPIAR", "cache_settings_duplicated_assets_subtitle": "Photos and videos that are black listed by the app", - "cache_settings_duplicated_assets_title": "Duplicated Assets ({})", + "cache_settings_duplicated_assets_title": "Elementos duplicados ({})", "cache_settings_image_cache_size": "Tamaño de la caché de imágenes ({} recursos)", "cache_settings_statistics_album": "Miniaturas de la biblioteca", "cache_settings_statistics_assets": "{} recursos ({})", @@ -149,17 +156,22 @@ "cache_settings_tile_subtitle": "Controla el comportamiento del almacenamiento local", "cache_settings_tile_title": "Almacenamiento local", "cache_settings_title": "Configuración de la caché", + "cancel": "Cancel", + "change_display_order": "Change display order", "change_password_form_confirm_password": "Confirmar Contraseña", "change_password_form_description": "Hola {name},\n\nÉsta es la primera vez que inicias sesión en el sistema o se ha solicitado cambiar tu contraseña. Por favor, introduce la nueva contraseña a continuación.", "change_password_form_new_password": "Nueva Contraseña", "change_password_form_password_mismatch": "Las contraseñas no coinciden", "change_password_form_reenter_new_password": "Vuelve a ingresar la nueva contraseña", + "check_corrupt_asset_backup": "Check for corrupt asset backups", + "check_corrupt_asset_backup_button": "Perform check", + "check_corrupt_asset_backup_description": "Run this check only over Wi-Fi and once all assets have been backed-up. The procedure might take a few minutes.", "client_cert_dialog_msg_confirm": "OK", "client_cert_enter_password": "Enter Password", - "client_cert_import": "Import", + "client_cert_import": "Importar", "client_cert_import_success_msg": "Client certificate is imported", "client_cert_invalid_msg": "Invalid certificate file or wrong password", - "client_cert_remove": "Remove", + "client_cert_remove": "Eliminar", "client_cert_remove_msg": "Client certificate is removed", "client_cert_subtitle": "Supports PKCS12 (.p12, .pfx) format only. Certificate Import/Remove is available only before login", "client_cert_title": "SSL Client Certificate", @@ -168,7 +180,7 @@ "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_shared": "Compartido", - "contextual_search": "Sunrise on the beach", + "contextual_search": "Amanecer en la playa", "control_bottom_app_bar_add_to_album": "Agregar al álbum", "control_bottom_app_bar_album_info": "{} elementos", "control_bottom_app_bar_album_info_shared": "{} elementos · Compartido", @@ -199,12 +211,13 @@ "crop": "Crop", "curated_location_page_title": "Lugares", "curated_object_page_title": "Objetos", + "current_server_address": "Current server address", "daily_title_text_date": "E, dd MMM", "daily_title_text_date_year": "E, dd de MMM, yyyy", "date_format": "E d, LLL y • h:mm a", "delete_dialog_alert": "Estos elementos se eliminarán permanentemente de Immich y de tu dispositivo", "delete_dialog_alert_local": "These items will be permanently removed from your device but still be available on the Immich server", - "delete_dialog_alert_local_non_backed_up": "Some of the items aren't backed up to Immich and will be permanently removed from your device", + "delete_dialog_alert_local_non_backed_up": "Algunas de las imágenes no tienen copia de seguridad y serán borradas de forma permanente de tu dispositivo", "delete_dialog_alert_remote": "These items will be permanently deleted from the Immich server", "delete_dialog_cancel": "Cancelar", "delete_dialog_ok": "Eliminar", @@ -235,22 +248,28 @@ "edit_date_time_dialog_timezone": "Timezone", "edit_image_title": "Edit", "edit_location_dialog_title": "Location", + "enter_wifi_name": "Enter WiFi name", + "error_change_sort_album": "Failed to change album sort order", "error_saving_image": "Error: {}", "exif_bottom_sheet_description": "Agregar Descripción...", "exif_bottom_sheet_details": "DETALLES", "exif_bottom_sheet_location": "UBICACIÓN", "exif_bottom_sheet_location_add": "Add a location", - "exif_bottom_sheet_people": "PEOPLE", + "exif_bottom_sheet_people": "PERSONAS", "exif_bottom_sheet_person_add_person": "Add name", "experimental_settings_new_asset_list_subtitle": "Trabajo en progreso", "experimental_settings_new_asset_list_title": "Habilitar cuadrícula fotográfica experimental", "experimental_settings_subtitle": "¡Úsalo bajo tu propio riesgo!", "experimental_settings_title": "Experimental", - "favorites": "Favorites", + "external_network": "External network", + "external_network_sheet_info": "When not on the preferred WiFi network, the app will connect to the server through the first of the below URLs it can reach, starting from top to bottom", + "favorites": "Favoritos", "favorites_page_no_favorites": "No se encontraron recursos marcados como favoritos", "favorites_page_title": "Favoritos", "filename_search": "File name or extension", "filter": "Filter", + "get_wifiname_error": "Could not get Wi-Fi name. Make sure you have granted the necessary permissions and are connected to a Wi-Fi network", + "grant_permission": "Grant permission", "haptic_feedback_switch": "Enable haptic feedback", "haptic_feedback_title": "Haptic Feedback", "header_settings_add_header_tip": "Add Header", @@ -258,8 +277,8 @@ "header_settings_header_name_input": "Header name", "header_settings_header_value_input": "Header value", "header_settings_page_title": "Proxy Headers", - "headers_settings_tile_subtitle": "Define proxy headers the app should send with each network request", - "headers_settings_tile_title": "Custom proxy headers", + "headers_settings_tile_subtitle": "Configura headers HTTP que la aplicación incluirá en cada petición de red", + "headers_settings_tile_title": "Cabeceras de proxy personalizadas", "home_page_add_to_album_conflicts": "{added} recursos agregados al álbum {album}.\n{failed} recursos ya existen en el álbum.", "home_page_add_to_album_err_local": "Aún no se pueden agregar recursos locales a álbumes, omitiendo", "home_page_add_to_album_success": "{added} recursos agregados al álbum {album}.", @@ -283,19 +302,23 @@ "image_viewer_page_state_provider_share_error": "Error al compartir", "invalid_date": "Invalid date", "invalid_date_format": "Invalid date format", - "library": "Library", + "library": "Biblioteca", "library_page_albums": "Álbumes", "library_page_archive": "Archivo", "library_page_device_albums": "Álbumes en el dispositivo", "library_page_favorites": "Favoritos", "library_page_new_album": "Nuevo álbum", "library_page_sharing": "Compartiendo", - "library_page_sort_asset_count": "Number of assets", + "library_page_sort_asset_count": "Número de recursos", "library_page_sort_created": "Creado más recientemente", "library_page_sort_last_modified": "Modificado más recientemente", - "library_page_sort_most_oldest_photo": "Oldest photo", + "library_page_sort_most_oldest_photo": "Foto más antigua", "library_page_sort_most_recent_photo": "Foto más reciente", "library_page_sort_title": "Título del álbum", + "local_network": "Local network", + "local_network_sheet_info": "The app will connect to the server through this URL when using the specified Wi-Fi network", + "location_permission": "Location permission", + "location_permission_content": "In order to use the auto-switching feature, Immich needs precise location permission so it can read the current WiFi network's name", "location_picker_choose_on_map": "Choose on map", "location_picker_latitude": "Latitude", "location_picker_latitude_error": "Enter a valid latitude", @@ -358,13 +381,15 @@ "memories_check_back_tomorrow": "Check back tomorrow for more memories", "memories_start_over": "Start Over", "memories_swipe_to_close": "Swipe up to close", - "memories_year_ago": "A year ago", - "memories_years_ago": "{} years ago", + "memories_year_ago": "Hace un año", + "memories_years_ago": "Hace {} años", "monthly_title_text_date_format": "MMMM y", "motion_photos_page_title": "Fotos en movimiento", "multiselect_grid_edit_date_time_err_read_only": "Cannot edit date of read only asset(s), skipping", "multiselect_grid_edit_gps_err_read_only": "Cannot edit location of read only asset(s), skipping", - "my_albums": "My albums", + "my_albums": "Mis álbumes", + "networking_settings": "Networking", + "networking_subtitle": "Configuraciones de acceso por URL al servidor", "no_assets_to_show": "No assets to show", "no_name": "No name", "notification_permission_dialog_cancel": "Cancelar", @@ -386,7 +411,7 @@ "partner_page_stop_sharing_title": "¿Dejar de compartir tus fotos?", "partner_page_title": "Compañero", "partners": "Partners", - "people": "People", + "people": "Personas", "permission_onboarding_back": "Volver", "permission_onboarding_continue_anyway": "Continuar de todos modos", "permission_onboarding_get_started": "Empezar", @@ -398,7 +423,8 @@ "permission_onboarding_permission_limited": "Permiso limitado. Para permitir que Immich haga copia de seguridad y gestione toda tu colección de galería, concede permisos de fotos y videos en Configuración.", "permission_onboarding_request": "Immich requiere permiso para ver tus fotos y videos.", "places": "Places", - "preferences_settings_title": "Preferences", + "preferences_settings_subtitle": "Configuraciones de la aplicación", + "preferences_settings_title": "Preferencias", "profile_drawer_app_logs": "Registros", "profile_drawer_client_out_of_date_major": "Mobile App is out of date. Please update to the latest major version.", "profile_drawer_client_out_of_date_minor": "Mobile App is out of date. Please update to the latest minor version.", @@ -410,18 +436,19 @@ "profile_drawer_settings": "Configuración", "profile_drawer_sign_out": "Cerrar sesión", "profile_drawer_trash": "Papelera", - "recently_added": "Recently added", + "recently_added": "Añadidos recientemente", "recently_added_page_title": "Recién Agregados", + "save": "Save", "save_to_gallery": "Save to gallery", "scaffold_body_error_occurred": "Error occurred", - "search_albums": "Search albums", + "search_albums": "Buscar álbum", "search_bar_hint": "Busca tus fotos", "search_filter_apply": "Apply filter", - "search_filter_camera": "Camera", - "search_filter_camera_make": "Make", - "search_filter_camera_model": "Model", - "search_filter_camera_title": "Select camera type", - "search_filter_date": "Date", + "search_filter_camera": "Cámara", + "search_filter_camera_make": "Marca", + "search_filter_camera_model": "Modelo", + "search_filter_camera_title": "Elige tipo de cámara", + "search_filter_date": "Fecha", "search_filter_date_interval": "{start} to {end}", "search_filter_date_title": "Select a date range", "search_filter_display_option_archive": "Archive", @@ -429,18 +456,18 @@ "search_filter_display_option_not_in_album": "Not in album", "search_filter_display_options": "Display Options", "search_filter_display_options_title": "Display options", - "search_filter_location": "Location", + "search_filter_location": "Ubicación", "search_filter_location_city": "City", "search_filter_location_country": "Country", "search_filter_location_state": "State", "search_filter_location_title": "Select location", - "search_filter_media_type": "Media Type", + "search_filter_media_type": "Tipo de archivo", "search_filter_media_type_all": "All", "search_filter_media_type_image": "Image", - "search_filter_media_type_title": "Select media type", + "search_filter_media_type_title": "Selecciona el tipo de archivo", "search_filter_media_type_video": "Video", - "search_filter_people": "People", - "search_filter_people_title": "Select people", + "search_filter_people": "Personas", + "search_filter_people_title": "Seleccionar personas", "search_page_categories": "Categorías", "search_page_favorites": "Favoritos", "search_page_motion_photos": "Fotos en .ovimiento", @@ -457,6 +484,7 @@ "search_page_places": "Lugares", "search_page_recently_added": "Recién agregados", "search_page_screenshots": "Capturas de pantalla", + "search_page_search_photos_videos": "Busca tus fotos y videos", "search_page_selfies": "Selfies", "search_page_things": "Cosas", "search_page_videos": "Videos", @@ -469,6 +497,7 @@ "select_additional_user_for_sharing_page_suggestions": "Sugerencias", "select_user_for_sharing_page_err_album": "Error al crear álbum", "select_user_for_sharing_page_share_suggestions": "Sugerencias", + "server_endpoint": "Server Endpoint", "server_info_box_app_version": "Versión de la Aplicación", "server_info_box_latest_release": "Ultima versión", "server_info_box_server_url": "URL del Servidor", @@ -478,9 +507,10 @@ "setting_image_viewer_original_title": "Cargar imagen original", "setting_image_viewer_preview_subtitle": "Activar para cargar una imagen de resolución media. Deshabilitar para cargar directamente la imagen original o usar una miniatura.", "setting_image_viewer_preview_title": "Cargar imagen de previsualización", - "setting_image_viewer_title": "Images", - "setting_languages_apply": "Apply", - "setting_languages_title": "Languages", + "setting_image_viewer_title": "Imágenes", + "setting_languages_apply": "Aplicar", + "setting_languages_subtitle": "Cambia el idioma de la aplicación", + "setting_languages_title": "Idiomas", "setting_notifications_notify_failures_grace_period": "Notificar fallos de copia de seguridad en segundo plano: {}", "setting_notifications_notify_hours": "{} horas", "setting_notifications_notify_immediately": "inmediatamente", @@ -495,8 +525,8 @@ "setting_notifications_total_progress_title": "Mostrar progreso total de copia de seguridad en segundo plano", "setting_pages_app_bar_settings": "Configuración", "settings_require_restart": "Por favor, reinicia Immich para aplicar este ajuste", - "setting_video_viewer_looping_subtitle": "Enable to automatically loop a video in the detail viewer.", - "setting_video_viewer_looping_title": "Looping", + "setting_video_viewer_looping_subtitle": "Habilitar reproducción en bucle del video en la vista detallada", + "setting_video_viewer_looping_title": "Bucle", "setting_video_viewer_title": "Videos", "share_add": "Agregar", "share_add_photos": "Agregar fotos", @@ -509,11 +539,11 @@ "shared_album_activity_remove_title": "Eliminar actividad", "shared_album_activity_setting_subtitle": "Permitir que otros respondan", "shared_album_activity_setting_title": "Comentarios y me gusta", - "shared_album_section_people_action_error": "Error leaving/removing from album", - "shared_album_section_people_action_leave": "Remove user from album", - "shared_album_section_people_action_remove_user": "Remove user from album", - "shared_album_section_people_owner_label": "Owner", - "shared_album_section_people_title": "PEOPLE", + "shared_album_section_people_action_error": "Error retirando/eliminando del album", + "shared_album_section_people_action_leave": "Eliminar usuario del álbum", + "shared_album_section_people_action_remove_user": "Eliminar usuario del álbum", + "shared_album_section_people_owner_label": "Propietario", + "shared_album_section_people_title": "PERSONAS", "share_dialog_preparing": "Preparando...", "shared_link_app_bar_title": "Enlaces compartidos", "shared_link_clipboard_copied_massage": "Copied to clipboard", @@ -562,7 +592,7 @@ "shared_link_public_album": "Public album", "shared_links": "Shared links", "share_done": "Hecho", - "shared_with_me": "Shared with me", + "shared_with_me": "Compartidos conmigo", "share_invite": "Invitar al álbum", "sharing_page_album": "Álbumes compartidos", "sharing_page_description": "Crea álbumes compartidos para compartir fotos y videos con personas de tu red.", @@ -571,8 +601,8 @@ "sharing_silver_appbar_shared_links": "Enlaces compartidos", "sharing_silver_appbar_share_partner": "Compartir con compañero", "sync": "Sync", - "sync_albums": "Sync albums", - "sync_albums_manual_subtitle": "Sync all uploaded videos and photos to the selected backup albums", + "sync_albums": "Sincronizar álbumes", + "sync_albums_manual_subtitle": "Sincroniza todos los videos y fotos subidos con los álbumes seleccionados a respaldar", "sync_upload_album_setting_subtitle": "Create and upload your photos and videos to the selected albums on Immich", "tab_controller_nav_library": "Biblioteca", "tab_controller_nav_photos": "Fotos", @@ -612,6 +642,8 @@ "upload_dialog_info": "¿Quieres respaldar los recursos seleccionados en el servidor?", "upload_dialog_ok": "Subir", "upload_dialog_title": "Subir recurso", + "use_current_connection": "use current connection", + "validate_endpoint_error": "Please enter a valid URL", "version_announcement_overlay_ack": "Aceptar", "version_announcement_overlay_release_notes": "notas de la versión", "version_announcement_overlay_text_1": "Hola, amigo, hay una nueva versión de", @@ -621,5 +653,7 @@ "videos": "Videos", "viewer_remove_from_stack": "Eliminar de la pila", "viewer_stack_use_as_main_asset": "Utilizar como recurso principal", - "viewer_unstack": "Desapilar" + "viewer_unstack": "Desapilar", + "wifi_name": "WiFi Name", + "your_wifi_name": "Your WiFi name" } \ No newline at end of file diff --git a/mobile/assets/i18n/fi-FI.json b/mobile/assets/i18n/fi-FI.json index 4f10b4c78b550..8c5b1d74fea01 100644 --- a/mobile/assets/i18n/fi-FI.json +++ b/mobile/assets/i18n/fi-FI.json @@ -7,6 +7,7 @@ "action_common_select": "Select", "action_common_update": "Päivitä", "add_a_name": "Add a name", + "add_endpoint": "Add endpoint", "add_to_album_bottom_sheet_added": "Lisätty albumiin {album}", "add_to_album_bottom_sheet_already_exists": "Kohde on jo albumissa {album}", "advanced_settings_log_level_title": "Lokitaso: {}", @@ -65,7 +66,12 @@ "assets_restored_successfully": "{} asset(s) restored successfully", "assets_trashed": "{} asset(s) trashed", "assets_trashed_from_server": "{} asset(s) trashed from the Immich server", + "asset_viewer_settings_subtitle": "Manage your gallery viewer settings", "asset_viewer_settings_title": "Katselin", + "automatic_endpoint_switching_subtitle": "Connect locally over designated Wi-Fi when available and use alternative connections elsewhere", + "automatic_endpoint_switching_title": "Automatic URL switching", + "background_location_permission": "Background location permission", + "background_location_permission_content": "In order to switch networks when running in the background, Immich must *always* have precise location access so the app can read the Wi-Fi network's name", "backup_album_selection_page_albums_device": "Laitteen albumit ({})", "backup_album_selection_page_albums_tap": "Napauta sisällyttääksesi, kaksoisnapauta jättääksesi pois", "backup_album_selection_page_assets_scatter": "Kohteet voivat olla hajaantuneina useisiin albumeihin. Albumeita voidaan sisällyttää varmuuskopiointiin tai jättää siitä pois.", @@ -131,6 +137,7 @@ "backup_manual_success": "Onnistui", "backup_manual_title": "Lähetyksen tila", "backup_options_page_title": "Varmuuskopioinnin asetukset", + "backup_setting_subtitle": "Manage background and foreground upload settings", "cache_settings_album_thumbnails": "Kirjastosivun esikatselukuvat ({} kohdetta)", "cache_settings_clear_cache_button": "Tyhjennä välimuisti", "cache_settings_clear_cache_button_title": "Tyhjennä sovelluksen välimuisti. Tämä vaikuttaa merkittävästi sovelluksen suorituskykyyn, kunnes välimuisti on rakennettu uudelleen.", @@ -149,11 +156,16 @@ "cache_settings_tile_subtitle": "Hallitse paikallista tallenustilaa", "cache_settings_tile_title": "Paikallinen tallennustila", "cache_settings_title": "Välimuistin asetukset", + "cancel": "Cancel", + "change_display_order": "Change display order", "change_password_form_confirm_password": "Vahvista salasana", "change_password_form_description": "Hei {name},\n\nTämä on joko ensimmäinen kirjautumisesi järjestelmään tai salasanan vaihtaminen vaihtaminen on pakotettu. Ole hyvä ja syötä uusi salasana alle.", "change_password_form_new_password": "Uusi salasana", "change_password_form_password_mismatch": "Salasanat eivät täsmää", "change_password_form_reenter_new_password": "Uusi salasana uudelleen", + "check_corrupt_asset_backup": "Check for corrupt asset backups", + "check_corrupt_asset_backup_button": "Perform check", + "check_corrupt_asset_backup_description": "Run this check only over Wi-Fi and once all assets have been backed-up. The procedure might take a few minutes.", "client_cert_dialog_msg_confirm": "OK", "client_cert_enter_password": "Enter Password", "client_cert_import": "Import", @@ -199,6 +211,7 @@ "crop": "Crop", "curated_location_page_title": "Paikat", "curated_object_page_title": "Asiat", + "current_server_address": "Current server address", "daily_title_text_date": "E, MMM dd", "daily_title_text_date_year": "E, MMM dd, yyyy", "date_format": "E, LLL d, y • h:mm a", @@ -235,6 +248,8 @@ "edit_date_time_dialog_timezone": "Aikavyöhyke", "edit_image_title": "Edit", "edit_location_dialog_title": "Sijainti", + "enter_wifi_name": "Enter WiFi name", + "error_change_sort_album": "Failed to change album sort order", "error_saving_image": "Error: {}", "exif_bottom_sheet_description": "Lisää kuvaus…", "exif_bottom_sheet_details": "TIEDOT", @@ -246,11 +261,15 @@ "experimental_settings_new_asset_list_title": "Ota käyttöön kokeellinen kuvaruudukko", "experimental_settings_subtitle": "Käyttö omalla vastuulla!", "experimental_settings_title": "Kokeellinen", + "external_network": "External network", + "external_network_sheet_info": "When not on the preferred WiFi network, the app will connect to the server through the first of the below URLs it can reach, starting from top to bottom", "favorites": "Favorites", "favorites_page_no_favorites": "Suosikkikohteita ei löytynyt", "favorites_page_title": "Suosikit", "filename_search": "File name or extension", "filter": "Filter", + "get_wifiname_error": "Could not get Wi-Fi name. Make sure you have granted the necessary permissions and are connected to a Wi-Fi network", + "grant_permission": "Grant permission", "haptic_feedback_switch": "Ota haptinen palaute käyttöön", "haptic_feedback_title": "Haptinen palaute", "header_settings_add_header_tip": "Add Header", @@ -296,6 +315,10 @@ "library_page_sort_most_oldest_photo": "Vanhin kuva", "library_page_sort_most_recent_photo": "Viimeisin kuva", "library_page_sort_title": "Albumin otsikko", + "local_network": "Local network", + "local_network_sheet_info": "The app will connect to the server through this URL when using the specified Wi-Fi network", + "location_permission": "Location permission", + "location_permission_content": "In order to use the auto-switching feature, Immich needs precise location permission so it can read the current WiFi network's name", "location_picker_choose_on_map": "Valitse kartalta", "location_picker_latitude": "Leveysaste", "location_picker_latitude_error": "Lisää kelvollinen leveysaste", @@ -365,6 +388,8 @@ "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", "my_albums": "My albums", + "networking_settings": "Networking", + "networking_subtitle": "Manage the server endpoint settings", "no_assets_to_show": "Ei näytettäviä kohteita", "no_name": "No name", "notification_permission_dialog_cancel": "Peruuta", @@ -398,6 +423,7 @@ "permission_onboarding_permission_limited": "Rajoitettu käyttöoikeus. Salliaksesi Immichin varmuuskopioida ja hallita koko kuvakirjastoasi, myönnä oikeus kuviin ja videoihin asetuksista.", "permission_onboarding_request": "Immich vaatii käyttöoikeuden kuvien ja videoiden käyttämiseen.", "places": "Places", + "preferences_settings_subtitle": "Manage the app's preferences", "preferences_settings_title": "Asetukset", "profile_drawer_app_logs": "Lokit", "profile_drawer_client_out_of_date_major": "Sovelluksen mobiiliversio on vanhentunut. Päivitä viimeisimpään merkittävään versioon.", @@ -412,6 +438,7 @@ "profile_drawer_trash": "Roskakori", "recently_added": "Recently added", "recently_added_page_title": "Viimeksi lisätyt", + "save": "Save", "save_to_gallery": "Save to gallery", "scaffold_body_error_occurred": "Tapahtui virhe", "search_albums": "Search albums", @@ -457,6 +484,7 @@ "search_page_places": "Paikat", "search_page_recently_added": "Viimeksi lisätyt", "search_page_screenshots": "Näyttökuvat", + "search_page_search_photos_videos": "Search for your photos and videos", "search_page_selfies": "Selfiet", "search_page_things": "Asiat", "search_page_videos": "Videot", @@ -469,6 +497,7 @@ "select_additional_user_for_sharing_page_suggestions": "Ehdotukset", "select_user_for_sharing_page_err_album": "Albumin luonti epäonnistui", "select_user_for_sharing_page_share_suggestions": "Ehdotukset", + "server_endpoint": "Server Endpoint", "server_info_box_app_version": "Sovelluksen versio", "server_info_box_latest_release": "Viimeisin versio", "server_info_box_server_url": "Palvelimen URL-osoite", @@ -480,6 +509,7 @@ "setting_image_viewer_preview_title": "Lataa esikatselukuva", "setting_image_viewer_title": "Kuvat", "setting_languages_apply": "Käytä", + "setting_languages_subtitle": "Change the app's language", "setting_languages_title": "Kieli", "setting_notifications_notify_failures_grace_period": "Ilmoita taustavarmuuskopioinnin epäonnistumisista: {}", "setting_notifications_notify_hours": "{} tunnin välein", @@ -612,6 +642,8 @@ "upload_dialog_info": "Haluatko varmuuskopioida valitut kohteet palvelimelle?", "upload_dialog_ok": "Lähetä", "upload_dialog_title": "Lähetä kohde", + "use_current_connection": "use current connection", + "validate_endpoint_error": "Please enter a valid URL", "version_announcement_overlay_ack": "Tiedostan", "version_announcement_overlay_release_notes": "julkaisutiedoissa", "version_announcement_overlay_text_1": "Hei, kaveri! Uusi palvelinversio on saatavilla sovelluksesta", @@ -621,5 +653,7 @@ "videos": "Videos", "viewer_remove_from_stack": "Poista pinosta", "viewer_stack_use_as_main_asset": "Käytä pääkohteena", - "viewer_unstack": "Pura pino" + "viewer_unstack": "Pura pino", + "wifi_name": "WiFi Name", + "your_wifi_name": "Your WiFi name" } \ No newline at end of file diff --git a/mobile/assets/i18n/fr-CA.json b/mobile/assets/i18n/fr-CA.json index 9e51cc7cbf5f6..056f3c7ae8099 100644 --- a/mobile/assets/i18n/fr-CA.json +++ b/mobile/assets/i18n/fr-CA.json @@ -7,6 +7,7 @@ "action_common_select": "Select", "action_common_update": "Update", "add_a_name": "Add a name", + "add_endpoint": "Add endpoint", "add_to_album_bottom_sheet_added": "Ajouté à {album}", "add_to_album_bottom_sheet_already_exists": "Déjà dans {album}", "advanced_settings_log_level_title": "Log level: {}", @@ -65,7 +66,12 @@ "assets_restored_successfully": "{} asset(s) restored successfully", "assets_trashed": "{} asset(s) trashed", "assets_trashed_from_server": "{} asset(s) trashed from the Immich server", + "asset_viewer_settings_subtitle": "Manage your gallery viewer settings", "asset_viewer_settings_title": "Asset Viewer", + "automatic_endpoint_switching_subtitle": "Connect locally over designated Wi-Fi when available and use alternative connections elsewhere", + "automatic_endpoint_switching_title": "Automatic URL switching", + "background_location_permission": "Background location permission", + "background_location_permission_content": "In order to switch networks when running in the background, Immich must *always* have precise location access so the app can read the Wi-Fi network's name", "backup_album_selection_page_albums_device": "Albums sur l'appareil ({})", "backup_album_selection_page_albums_tap": "Tapez pour inclure, tapez deux fois pour exclure", "backup_album_selection_page_assets_scatter": "Les éléments peuvent être répartis sur plusieurs albums. De ce fait, les albums peuvent être inclus ou exclus pendant le processus de sauvegarde.", @@ -131,6 +137,7 @@ "backup_manual_success": "Succès ", "backup_manual_title": "Statut du téléchargement ", "backup_options_page_title": "Backup options", + "backup_setting_subtitle": "Manage background and foreground upload settings", "cache_settings_album_thumbnails": "vignettes de la page bibliothèque ({} éléments)", "cache_settings_clear_cache_button": "Effacer le cache", "cache_settings_clear_cache_button_title": "Efface le cache de l'application. Cela aura un impact significatif sur les performances de l'application jusqu'à ce que le cache soit reconstruit.", @@ -149,11 +156,16 @@ "cache_settings_tile_subtitle": "Contrôler le comportement du stockage local", "cache_settings_tile_title": "Stockage local", "cache_settings_title": "Paramètres de mise en cache", + "cancel": "Cancel", + "change_display_order": "Change display order", "change_password_form_confirm_password": "Confirmez le mot de passe", "change_password_form_description": "Bonjour {name},\n\nC'est la première fois que vous vous connectez au système ou vous avez demandé de changer votre mot de passe. Veuillez saisir le nouveau mot de passe ci-dessous.", "change_password_form_new_password": "Nouveau mot de passe", "change_password_form_password_mismatch": "Les mots de passe ne correspondent pas", "change_password_form_reenter_new_password": "Saisissez à nouveau le nouveau mot de passe", + "check_corrupt_asset_backup": "Check for corrupt asset backups", + "check_corrupt_asset_backup_button": "Perform check", + "check_corrupt_asset_backup_description": "Run this check only over Wi-Fi and once all assets have been backed-up. The procedure might take a few minutes.", "client_cert_dialog_msg_confirm": "OK", "client_cert_enter_password": "Enter Password", "client_cert_import": "Import", @@ -199,6 +211,7 @@ "crop": "Crop", "curated_location_page_title": "Places", "curated_object_page_title": "Objets", + "current_server_address": "Current server address", "daily_title_text_date": "E, dd MMM", "daily_title_text_date_year": "E, dd MMM, yyyy", "date_format": "E, LLL d, y • h:mm a", @@ -235,6 +248,8 @@ "edit_date_time_dialog_timezone": "Timezone", "edit_image_title": "Edit", "edit_location_dialog_title": "Location", + "enter_wifi_name": "Enter WiFi name", + "error_change_sort_album": "Failed to change album sort order", "error_saving_image": "Error: {}", "exif_bottom_sheet_description": "Ajouter une description...", "exif_bottom_sheet_details": "DÉTAILS", @@ -246,11 +261,15 @@ "experimental_settings_new_asset_list_title": "Activer la grille de photos expérimentale", "experimental_settings_subtitle": "Utilisez à vos dépends!", "experimental_settings_title": "Expérimental", + "external_network": "External network", + "external_network_sheet_info": "When not on the preferred WiFi network, the app will connect to the server through the first of the below URLs it can reach, starting from top to bottom", "favorites": "Favorites", "favorites_page_no_favorites": "Aucun élément favori n'a été trouvé", "favorites_page_title": "Favoris", "filename_search": "File name or extension", "filter": "Filter", + "get_wifiname_error": "Could not get Wi-Fi name. Make sure you have granted the necessary permissions and are connected to a Wi-Fi network", + "grant_permission": "Grant permission", "haptic_feedback_switch": "Enable haptic feedback", "haptic_feedback_title": "Haptic Feedback", "header_settings_add_header_tip": "Add Header", @@ -296,6 +315,10 @@ "library_page_sort_most_oldest_photo": "Oldest photo", "library_page_sort_most_recent_photo": "Photo la plus récente", "library_page_sort_title": "Titre de l'album", + "local_network": "Local network", + "local_network_sheet_info": "The app will connect to the server through this URL when using the specified Wi-Fi network", + "location_permission": "Location permission", + "location_permission_content": "In order to use the auto-switching feature, Immich needs precise location permission so it can read the current WiFi network's name", "location_picker_choose_on_map": "Choose on map", "location_picker_latitude": "Latitude", "location_picker_latitude_error": "Enter a valid latitude", @@ -365,6 +388,8 @@ "multiselect_grid_edit_date_time_err_read_only": "Cannot edit date of read only asset(s), skipping", "multiselect_grid_edit_gps_err_read_only": "Cannot edit location of read only asset(s), skipping", "my_albums": "My albums", + "networking_settings": "Networking", + "networking_subtitle": "Manage the server endpoint settings", "no_assets_to_show": "No assets to show", "no_name": "No name", "notification_permission_dialog_cancel": "Annuler", @@ -398,6 +423,7 @@ "permission_onboarding_permission_limited": "Permission limitée. Pour permettre à Immich de sauvegarder et de gérer l'ensemble de votre bibliothèque, accordez l'autorisation pour les photos et vidéos dans les Paramètres.", "permission_onboarding_request": "Immich demande l'autorisation de visionner vos photos et vidéo", "places": "Places", + "preferences_settings_subtitle": "Manage the app's preferences", "preferences_settings_title": "Preferences", "profile_drawer_app_logs": "Journaux", "profile_drawer_client_out_of_date_major": "Mobile App is out of date. Please update to the latest major version.", @@ -412,6 +438,7 @@ "profile_drawer_trash": "Corbeille", "recently_added": "Recently added", "recently_added_page_title": "Récemment ajouté", + "save": "Save", "save_to_gallery": "Save to gallery", "scaffold_body_error_occurred": "Error occurred", "search_albums": "Search albums", @@ -457,6 +484,7 @@ "search_page_places": "Lieux", "search_page_recently_added": "Récemment ajouté", "search_page_screenshots": "Captures d'écran", + "search_page_search_photos_videos": "Search for your photos and videos", "search_page_selfies": "Selfies", "search_page_things": "Objets", "search_page_videos": "Vidéos", @@ -469,6 +497,7 @@ "select_additional_user_for_sharing_page_suggestions": "Suggestions", "select_user_for_sharing_page_err_album": "Échec de la création de l'album", "select_user_for_sharing_page_share_suggestions": "Suggestions", + "server_endpoint": "Server Endpoint", "server_info_box_app_version": "Version de l'application", "server_info_box_latest_release": "Dernière version", "server_info_box_server_url": "URL du serveur", @@ -480,6 +509,7 @@ "setting_image_viewer_preview_title": "Charger l'image d'aperçu", "setting_image_viewer_title": "Images", "setting_languages_apply": "Apply", + "setting_languages_subtitle": "Change the app's language", "setting_languages_title": "Languages", "setting_notifications_notify_failures_grace_period": "Notifier les échecs de la sauvegarde en arrière-plan: {}", "setting_notifications_notify_hours": "{} heures", @@ -612,6 +642,8 @@ "upload_dialog_info": "Voulez-vous sauvegarder la sélection vers le serveur?", "upload_dialog_ok": "Télécharger ", "upload_dialog_title": "Télécharger cet élément ", + "use_current_connection": "use current connection", + "validate_endpoint_error": "Please enter a valid URL", "version_announcement_overlay_ack": "Confirmer", "version_announcement_overlay_release_notes": "notes de mise à jour", "version_announcement_overlay_text_1": "Bonjour, une nouvelle version de", @@ -621,5 +653,7 @@ "videos": "Videos", "viewer_remove_from_stack": "Retirer de la pile", "viewer_stack_use_as_main_asset": "Utiliser comme élément principal", - "viewer_unstack": "Désempiler" + "viewer_unstack": "Désempiler", + "wifi_name": "WiFi Name", + "your_wifi_name": "Your WiFi name" } \ No newline at end of file diff --git a/mobile/assets/i18n/fr-FR.json b/mobile/assets/i18n/fr-FR.json index 2293d9ca304bb..bc46840f5fc71 100644 --- a/mobile/assets/i18n/fr-FR.json +++ b/mobile/assets/i18n/fr-FR.json @@ -6,10 +6,11 @@ "action_common_save": "Sauvegarder", "action_common_select": "Sélectionner", "action_common_update": "Mise à jour", - "add_a_name": "Add a name", + "add_a_name": "Ajouter un nom", + "add_endpoint": "Ajouter une adresse", "add_to_album_bottom_sheet_added": "Ajouté à {album}", "add_to_album_bottom_sheet_already_exists": "Déjà dans {album}", - "advanced_settings_log_level_title": "Log level: {}", + "advanced_settings_log_level_title": "Niveau de log : {}", "advanced_settings_prefer_remote_subtitle": "Certains appareils sont terriblement lents à charger des miniatures à partir de ressources présentes sur l'appareil. Activez ce paramètre pour charger des images distantes à la place.", "advanced_settings_prefer_remote_title": "Préférer les images distantes", "advanced_settings_proxy_headers_subtitle": "Ajoutez des en-têtes personnalisés à chaque requête réseau", @@ -38,15 +39,15 @@ "album_viewer_appbar_share_remove": "Retirer de l'album", "album_viewer_appbar_share_to": "Partager à", "album_viewer_page_share_add_users": "Ajouter des utilisateurs", - "all": "All", + "all": "Tous", "all_people_page_title": "Personnes", "all_videos_page_title": "Vidéos", "app_bar_signout_dialog_content": "Êtes-vous sûr de vouloir vous déconnecter ?", "app_bar_signout_dialog_ok": "Oui", "app_bar_signout_dialog_title": "Se déconnecter", - "archived": "Archived", + "archived": "Archives", "archive_page_no_archived_assets": "Aucun élément archivé n'a été trouvé", - "archive_page_title": "Archive ({})", + "archive_page_title": "Archives ({})", "asset_action_delete_err_read_only": "Impossible de supprimer le(s) élément(s) en lecture seule.", "asset_action_share_err_offline": "Impossible de récupérer le(s) élément(s) hors ligne.", "asset_list_group_by_sub_title": "Regrouper par", @@ -63,9 +64,14 @@ "assets_deleted_permanently_from_server": "{} élément(s) supprimé(s) définitivement du serveur Immich", "assets_removed_permanently_from_device": "\"{} élément(s) supprimé(s) définitivement de votre appareil", "assets_restored_successfully": "Élément restauré avec succès", - "assets_trashed": "{} élément(s) déplacé(s) vers la corbeill", + "assets_trashed": "{} élément(s) déplacé(s) vers la corbeille", "assets_trashed_from_server": "{} élément(s) déplacé(s) vers la corbeille du serveur Immich", - "asset_viewer_settings_title": "Visualisateur d'éléments", + "asset_viewer_settings_subtitle": "Modifier les paramètres du visualiseur photos", + "asset_viewer_settings_title": "Visualiseur d'éléments", + "automatic_endpoint_switching_subtitle": "Se connecter localement lorsque connecté au WI-FI spécifié mais utiliser une adresse alternative lorsque connecté à un autre réseau", + "automatic_endpoint_switching_title": "Changement automatique d'adresse", + "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é", "backup_album_selection_page_albums_device": "Albums sur l'appareil ({})", "backup_album_selection_page_albums_tap": "Tapez pour inclure, tapez deux fois pour exclure", "backup_album_selection_page_assets_scatter": "Les éléments peuvent être répartis sur plusieurs albums. De ce fait, les albums peuvent être inclus ou exclus pendant le processus de sauvegarde.", @@ -90,14 +96,14 @@ "backup_controller_page_background_battery_info_title": "Optimisation de la batterie", "backup_controller_page_background_charging": "Seulement pendant la charge", "backup_controller_page_background_configure_error": "Échec de la configuration du service d'arrière-plan", - "backup_controller_page_background_delay": "Retarder la sauvegarde des nouveaux éléments d'actif : {}", + "backup_controller_page_background_delay": "Retarder la sauvegarde des nouveaux éléments : {}", "backup_controller_page_background_description": "Activez le service d'arrière-plan pour sauvegarder automatiquement tous les nouveaux éléments sans avoir à ouvrir l'application.", "backup_controller_page_background_is_off": "La sauvegarde automatique en arrière-plan est désactivée", "backup_controller_page_background_is_on": "La sauvegarde automatique en arrière-plan est activée", "backup_controller_page_background_turn_off": "Désactiver le service d'arrière-plan", "backup_controller_page_background_turn_on": "Activer le service d'arrière-plan", "backup_controller_page_background_wifi": "Uniquement en WiFi", - "backup_controller_page_backup": "Sauvegardé", + "backup_controller_page_backup": "Sauvegarde", "backup_controller_page_backup_selected": "Sélectionné : ", "backup_controller_page_backup_sub": "Photos et vidéos sauvegardées", "backup_controller_page_cancel": "Annuler", @@ -122,7 +128,7 @@ "backup_controller_page_total_sub": "Toutes les photos et vidéos uniques des albums sélectionnés", "backup_controller_page_turn_off": "Désactiver la sauvegarde", "backup_controller_page_turn_on": "Activer la sauvegarde", - "backup_controller_page_uploading_file_info": "Transfert des informations du fichier", + "backup_controller_page_uploading_file_info": "Transfert du fichier", "backup_err_only_album": "Impossible de retirer le seul album", "backup_info_card_assets": "éléments", "backup_manual_cancelled": "Annulé", @@ -131,6 +137,7 @@ "backup_manual_success": "Succès ", "backup_manual_title": "Statut du téléchargement ", "backup_options_page_title": "Options de sauvegarde", + "backup_setting_subtitle": "Ajuster les paramètres de sauvegarde", "cache_settings_album_thumbnails": "Miniatures de la page bibliothèque ({} éléments)", "cache_settings_clear_cache_button": "Effacer le cache", "cache_settings_clear_cache_button_title": "Efface le cache de l'application. Cela aura un impact significatif sur les performances de l'application jusqu'à ce que le cache soit reconstruit.", @@ -149,14 +156,19 @@ "cache_settings_tile_subtitle": "Contrôler le comportement du stockage local", "cache_settings_tile_title": "Stockage local", "cache_settings_title": "Paramètres de mise en cache", + "cancel": "Annuler", + "change_display_order": "Change display order", "change_password_form_confirm_password": "Confirmez le mot de passe", "change_password_form_description": "Bonjour {name},\n\nC'est la première fois que vous vous connectez au système ou vous avez demandé à changer votre mot de passe. Veuillez saisir le nouveau mot de passe ci-dessous.", "change_password_form_new_password": "Nouveau mot de passe", "change_password_form_password_mismatch": "Les mots de passe ne correspondent pas", "change_password_form_reenter_new_password": "Saisissez à nouveau le nouveau mot de passe", + "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.", "client_cert_dialog_msg_confirm": "Ok", "client_cert_enter_password": "Entrer mot de passe", - "client_cert_import": "Imorted", + "client_cert_import": "Importer", "client_cert_import_success_msg": "Certificat importé", "client_cert_invalid_msg": "Fichier de certificat invalide ou mot de passe incorrect", "client_cert_remove": "Supprimer", @@ -172,7 +184,7 @@ "control_bottom_app_bar_add_to_album": "Ajouter à l'album", "control_bottom_app_bar_album_info": "{} éléments", "control_bottom_app_bar_album_info_shared": "{} éléments - Partagés", - "control_bottom_app_bar_archive": "Archive", + "control_bottom_app_bar_archive": "Archiver", "control_bottom_app_bar_create_new_album": "Créer un nouvel album", "control_bottom_app_bar_delete": "Supprimer", "control_bottom_app_bar_delete_from_immich": "Supprimer de Immich", @@ -189,16 +201,17 @@ "control_bottom_app_bar_unarchive": "Désarchiver", "control_bottom_app_bar_unfavorite": "Enlever des favoris", "control_bottom_app_bar_upload": "Téléverser", - "create_album": "Create album", + "create_album": "Créer l'album", "create_album_page_untitled": "Sans titre", - "create_new": "CREATE NEW", + "create_new": "NOUVEAU", "create_shared_album_page_create": "Créer", "create_shared_album_page_share": "Partager", "create_shared_album_page_share_add_assets": "AJOUTER DES ÉLÉMENTS", "create_shared_album_page_share_select_photos": "Sélectionner les photos", - "crop": "Crop", + "crop": "Recadrer", "curated_location_page_title": "Lieux", "curated_object_page_title": "Objets", + "current_server_address": "Adresse actuelle du serveur ", "daily_title_text_date": "E, dd MMM", "daily_title_text_date_year": "E, dd MMM, yyyy", "date_format": "E, LLL d, y • h:mm a", @@ -216,41 +229,47 @@ "delete_shared_link_dialog_title": "Supprimer le lien partagé", "description_input_hint_text": "Ajouter une description…", "description_input_submit_error": "Erreur de mise à jour de la description, vérifier le journal pour plus de détails", - "download_canceled": "Download canceled", - "download_complete": "Download complete", - "download_enqueue": "Download enqueued", - "download_error": "Download Error", - "download_failed": "Download failed", - "download_filename": "file: {}", - "download_finished": "Download finished", - "downloading": "Downloading...", - "downloading_media": "Downloading media", - "download_notfound": "Download not found", - "download_paused": "Download paused", - "download_started": "Download started", - "download_sucess": "Download success", - "download_sucess_android": "The media has been downloaded to DCIM/Immich", - "download_waiting_to_retry": "Waiting to retry", + "download_canceled": "Téléchargement annulé", + "download_complete": "Téléchargement terminé", + "download_enqueue": "Téléchargement en attente", + "download_error": "Erreur de téléchargement", + "download_failed": "Téléchargement échoué", + "download_filename": "fichier : {}", + "download_finished": "Téléchargement terminé", + "downloading": "Téléchargement...", + "downloading_media": "Téléchargement du média", + "download_notfound": "Téléchargement non trouvé", + "download_paused": "Téléchargement en pause", + "download_started": "Téléchargement commencé", + "download_sucess": "Téléchargement réussi", + "download_sucess_android": "Le média a été téléchargé dans DCIM/Immich", + "download_waiting_to_retry": "Téléchargement en attente du prochain essai", "edit_date_time_dialog_date_time": "Date et heure", "edit_date_time_dialog_timezone": "Fuseau horaire", - "edit_image_title": "Edit", + "edit_image_title": "Modifier", "edit_location_dialog_title": "Localisation", - "error_saving_image": "Error: {}", + "enter_wifi_name": "Entrez le nom du réseau ", + "error_change_sort_album": "Failed to change album sort order", + "error_saving_image": "Erreur : {}", "exif_bottom_sheet_description": "Ajouter une description…", "exif_bottom_sheet_details": "DÉTAILS", "exif_bottom_sheet_location": "LOCALISATION", - "exif_bottom_sheet_location_add": "Add a location", + "exif_bottom_sheet_location_add": "Ajouter un lieu", "exif_bottom_sheet_people": "PERSONNES", "exif_bottom_sheet_person_add_person": "Ajouter un nom", "experimental_settings_new_asset_list_subtitle": "En cours de développement", "experimental_settings_new_asset_list_title": "Activer la grille de photos expérimentale", "experimental_settings_subtitle": "Utilisez à vos dépends !", "experimental_settings_title": "Expérimental", - "favorites": "Favorites", + "external_network": "Réseau externe", + "external_network_sheet_info": "Quand vous n'êtes pas connecté à votre réseau préféré, l'application va tenter de se connecter aux adresses ci-dessous, en commencant par le haut", + "favorites": "Favoris", "favorites_page_no_favorites": "Aucun élément favori n'a été trouvé", "favorites_page_title": "Favoris", "filename_search": "Nom de fichier ou extension", - "filter": "Filter", + "filter": "Filtres", + "get_wifiname_error": "Impossible d'obtenir le nom du réseau Wi-Fi. Assurez-vous d'avoir donné les permissions nécessaires à l'application et que vous êtes connecté à un réseau Wi-Fi.", + "grant_permission": "Accorder les permissions ", "haptic_feedback_switch": "Activer le retour haptique", "haptic_feedback_title": "Retour haptique", "header_settings_add_header_tip": "Ajouter un en-tête", @@ -274,28 +293,32 @@ "home_page_first_time_notice": "Si c'est la première fois que vous utilisez l'application, veillez à choisir un ou plusieurs albums de sauvegarde afin que la chronologie puisse alimenter les photos et les vidéos de cet ou ces albums.", "home_page_share_err_local": "Impossible de partager par lien les médias locaux, cette opération est donc ignorée.", "home_page_upload_err_limit": "Limite de téléchargement de 30 éléments en même temps, demande ignorée", - "ignore_icloud_photos": "Ignore iCloud photos", - "ignore_icloud_photos_description": "Photos that are stored on iCloud will not be uploaded to the Immich server", - "image_saved_successfully": "Image saved", + "ignore_icloud_photos": "Ignorer les photos iCloud", + "ignore_icloud_photos_description": "Les photos stockées sur iCloud ne sont pas enregistrées sur Immich", + "image_saved_successfully": "Image enregistré", "image_viewer_page_state_provider_download_error": "Erreur de téléchargement", "image_viewer_page_state_provider_download_started": "Téléchargement démarré", "image_viewer_page_state_provider_download_success": "Téléchargement réussi", "image_viewer_page_state_provider_share_error": "Erreur de partage", "invalid_date": "Date invalide", "invalid_date_format": "Format de date invalide", - "library": "Library", + "library": "Bibliothèque", "library_page_albums": "Albums", "library_page_archive": "Archive", "library_page_device_albums": "Albums sur l'appareil", "library_page_favorites": "Favoris", "library_page_new_album": "Nouvel album", "library_page_sharing": "Partage", - "library_page_sort_asset_count": "Number of assets", + "library_page_sort_asset_count": "Nombre d'éléments", "library_page_sort_created": "Créations les plus récentes", "library_page_sort_last_modified": "Dernière modification", "library_page_sort_most_oldest_photo": "Photo la plus ancienne", "library_page_sort_most_recent_photo": "Photo la plus récente", "library_page_sort_title": "Titre de l'album", + "local_network": "Réseau local", + "local_network_sheet_info": "L'application va connecter au serveur via cette URL quand l'appareil est connecté au réseau Wi-Fi spécifié", + "location_permission": "Autorisation de localisation ", + "location_permission_content": "Afin de pouvoir changer d'adresse automatiquement, Immich doit avoir accès à la localisation précise, afin d'accéder au le nom du réseau Wi-Fi utilisé", "location_picker_choose_on_map": "Sélectionner sur la carte", "location_picker_latitude": "Latitude", "location_picker_latitude_error": "Saisir une latitude correcte", @@ -364,8 +387,10 @@ "motion_photos_page_title": "Photos avec mouvement", "multiselect_grid_edit_date_time_err_read_only": "Impossible de modifier la date d'un élément d'actif en lecture seule.", "multiselect_grid_edit_gps_err_read_only": "Impossible de modifier l'emplacement d'un élément en lecture seule.", - "my_albums": "My albums", - "no_assets_to_show": "Aucuns éléments à afficher", + "my_albums": "Mes albums", + "networking_settings": "Réseau ", + "networking_subtitle": "Gérer les adresses du serveur", + "no_assets_to_show": "Aucun élément à afficher", "no_name": "Sans nom", "notification_permission_dialog_cancel": "Annuler", "notification_permission_dialog_content": "Pour activer les notifications, allez dans Paramètres et sélectionnez Autoriser.", @@ -373,7 +398,7 @@ "notification_permission_list_tile_content": "Accordez la permission d'activer les notifications.", "notification_permission_list_tile_enable_button": "Activer les notifications", "notification_permission_list_tile_title": "Permission de notification", - "on_this_device": "On this device", + "on_this_device": "Sur cet appareil", "partner_list_user_photos": "Photos de {user}", "partner_list_view_all": "Voir tous", "partner_page_add_partner": "Ajouter un partenaire", @@ -385,8 +410,8 @@ "partner_page_stop_sharing_content": "{} ne pourra plus accéder à vos photos.", "partner_page_stop_sharing_title": "Arrêter de partager vos photos ?", "partner_page_title": "Partenaire", - "partners": "Partners", - "people": "People", + "partners": "Partenaires", + "people": "Personnes", "permission_onboarding_back": "Retour", "permission_onboarding_continue_anyway": "Continuer quand même", "permission_onboarding_get_started": "Commencer", @@ -397,7 +422,8 @@ "permission_onboarding_permission_granted": "Permission accordée ! Vous êtes prêts.", "permission_onboarding_permission_limited": "Permission limitée. Pour permettre à Immich de sauvegarder et de gérer l'ensemble de votre bibliothèque, accordez l'autorisation pour les photos et vidéos dans les Paramètres.", "permission_onboarding_request": "Immich demande l'autorisation de visionner vos photos et vidéo", - "places": "Places", + "places": "Lieux", + "preferences_settings_subtitle": "Gérer les préférences de l'application", "preferences_settings_title": "Préférences", "profile_drawer_app_logs": "Journaux", "profile_drawer_client_out_of_date_major": "L'application mobile est obsolète. Veuillez effectuer la mise à jour vers la dernière version majeure.", @@ -410,21 +436,22 @@ "profile_drawer_settings": "Paramètres", "profile_drawer_sign_out": "Se déconnecter", "profile_drawer_trash": "Corbeille", - "recently_added": "Recently added", + "recently_added": "Récemment ajouté", "recently_added_page_title": "Récemment ajouté", - "save_to_gallery": "Save to gallery", + "save": "Enregistrer ", + "save_to_gallery": "Enregistrer", "scaffold_body_error_occurred": "Une erreur s'est produite", - "search_albums": "Search albums", + "search_albums": "Rechercher des albums", "search_bar_hint": "Rechercher vos photos", "search_filter_apply": "Appliquer le filtre", "search_filter_camera": "Appareil", "search_filter_camera_make": "Fabricant", - "search_filter_camera_model": "Modéle", + "search_filter_camera_model": "Modèle", "search_filter_camera_title": "Sélectionner le type d'appareil", "search_filter_date": "Date", "search_filter_date_interval": "{start} à {end}", "search_filter_date_title": "Sélectionner une période", - "search_filter_display_option_archive": "Archive", + "search_filter_display_option_archive": "Archivé", "search_filter_display_option_favorite": "Favoris", "search_filter_display_option_not_in_album": "Pas dans un album", "search_filter_display_options": "Options d'affichage", @@ -457,6 +484,7 @@ "search_page_places": "Lieux", "search_page_recently_added": "Récemment ajouté", "search_page_screenshots": "Captures d'écran", + "search_page_search_photos_videos": "Rechercher dans vos photos et vidéos", "search_page_selfies": "Selfies", "search_page_things": "Objets", "search_page_videos": "Vidéos", @@ -469,6 +497,7 @@ "select_additional_user_for_sharing_page_suggestions": "Suggestions", "select_user_for_sharing_page_err_album": "Échec de la création de l'album", "select_user_for_sharing_page_share_suggestions": "Suggestions", + "server_endpoint": "Adresse du serveur", "server_info_box_app_version": "Version de l'application", "server_info_box_latest_release": "Dernière version", "server_info_box_server_url": "URL du serveur", @@ -480,6 +509,7 @@ "setting_image_viewer_preview_title": "Charger l'image d'aperçu", "setting_image_viewer_title": "Images", "setting_languages_apply": "Appliquer", + "setting_languages_subtitle": "Changer la langue de l'application", "setting_languages_title": "Langues", "setting_notifications_notify_failures_grace_period": "Notifier les échecs de la sauvegarde en arrière-plan : {}", "setting_notifications_notify_hours": "{} heures", @@ -560,9 +590,9 @@ "shared_link_info_chip_upload": "Chargement", "shared_link_manage_links": "Gérer les liens partagés", "shared_link_public_album": "Album public", - "shared_links": "Shared links", + "shared_links": "Liens partagés", "share_done": "Fait", - "shared_with_me": "Shared with me", + "shared_with_me": "Partagé avec moi", "share_invite": "Inviter à l'album", "sharing_page_album": "Albums partagés", "sharing_page_description": "Créez des albums partagés pour partager des photos et des vidéos avec les personnes de votre réseau.", @@ -570,10 +600,10 @@ "sharing_silver_appbar_create_shared_album": "Créer un album partagé", "sharing_silver_appbar_shared_links": "Liens partagés", "sharing_silver_appbar_share_partner": "Partager avec un partenaire", - "sync": "Sync", - "sync_albums": "Sync albums", - "sync_albums_manual_subtitle": "Sync all uploaded videos and photos to the selected backup albums", - "sync_upload_album_setting_subtitle": "Create and upload your photos and videos to the selected albums on Immich", + "sync": "Synchroniser", + "sync_albums": "Synchroniser dans des albums", + "sync_albums_manual_subtitle": "Synchroniser toutes les vidéos et photos sauvegardées dans les albums sélectionnés", + "sync_upload_album_setting_subtitle": "Créer et sauvegarde vos photos et vidéos dans les albums sélectionnés sur Immich", "tab_controller_nav_library": "Bibliothèque", "tab_controller_nav_photos": "Photos", "tab_controller_nav_search": "Recherche", @@ -594,7 +624,7 @@ "theme_setting_three_stage_loading_subtitle": "Le chargement en trois étapes peut améliorer les performances de chargement, mais entraîne une augmentation significative de la charge du réseau.", "theme_setting_three_stage_loading_title": "Activer le chargement en trois étapes", "translated_text_options": "Options", - "trash": "Trash", + "trash": "Corbeille", "trash_emptied": "Corbeille vidée", "trash_page_delete": "Supprimer", "trash_page_delete_all": "Tout supprimer", @@ -612,14 +642,18 @@ "upload_dialog_info": "Voulez-vous sauvegarder la sélection vers le serveur ?", "upload_dialog_ok": "Télécharger ", "upload_dialog_title": "Télécharger cet élément ", + "use_current_connection": "Utiliser le réseau actuel ", + "validate_endpoint_error": "Merci d'entrer un lien valide", "version_announcement_overlay_ack": "Confirmer", "version_announcement_overlay_release_notes": "notes de mise à jour", "version_announcement_overlay_text_1": "Bonjour, une nouvelle version de", "version_announcement_overlay_text_2": "veuillez prendre le temps de visiter le ", "version_announcement_overlay_text_3": " et assurez-vous que votre configuration docker-compose et .env est à jour pour éviter toute erreur de configuration, en particulier si vous utilisez WatchTower ou tout autre mécanisme qui gère la mise à jour automatique de votre application serveur.", "version_announcement_overlay_title": "Nouvelle version serveur disponible \uD83C\uDF89", - "videos": "Videos", + "videos": "Vidéos", "viewer_remove_from_stack": "Retirer de la pile", "viewer_stack_use_as_main_asset": "Utiliser comme élément principal", - "viewer_unstack": "Désempiler" + "viewer_unstack": "Désempiler", + "wifi_name": "Nom du réseau ", + "your_wifi_name": "Nom du réseau Wi-Fi " } \ No newline at end of file diff --git a/mobile/assets/i18n/he-IL.json b/mobile/assets/i18n/he-IL.json index a7b14d2b74dd9..a77e5eb796c8b 100644 --- a/mobile/assets/i18n/he-IL.json +++ b/mobile/assets/i18n/he-IL.json @@ -6,7 +6,8 @@ "action_common_save": "שמור", "action_common_select": "בחר", "action_common_update": "עדכון", - "add_a_name": "Add a name", + "add_a_name": "הוסף שם", + "add_endpoint": "הוסף נקודת קצה", "add_to_album_bottom_sheet_added": "נוסף ל {album}", "add_to_album_bottom_sheet_already_exists": "כבר ב {album}", "advanced_settings_log_level_title": "רמת תיעוד אירועים: {}", @@ -22,7 +23,7 @@ "advanced_settings_troubleshooting_title": "פתרון בעיות", "album_info_card_backup_album_excluded": "הוחרגו", "album_info_card_backup_album_included": "נכללו", - "albums": "Albums", + "albums": "אלבומים", "album_thumbnail_card_item": "פריט 1", "album_thumbnail_card_items": "{} פריטים", "album_thumbnail_card_shared": " · משותף", @@ -38,13 +39,13 @@ "album_viewer_appbar_share_remove": "הסרה מאלבום", "album_viewer_appbar_share_to": "שתף עם", "album_viewer_page_share_add_users": "הוסף משתמשים", - "all": "All", + "all": "הכל", "all_people_page_title": "אנשים", "all_videos_page_title": "סרטונים", "app_bar_signout_dialog_content": "האם את/ה בטוח/ה שברצונך להתנתק?", "app_bar_signout_dialog_ok": "כן", "app_bar_signout_dialog_title": "התנתק", - "archived": "Archived", + "archived": "בארכיון", "archive_page_no_archived_assets": "לא נמצאו נכסים בארכיון", "archive_page_title": "ארכיון ({})", "asset_action_delete_err_read_only": "לא ניתן למחוק נכס(ים) לקריאה בלבד, מדלג", @@ -65,7 +66,12 @@ "assets_restored_successfully": "{} נכס(ים) שוחזרו בהצלחה", "assets_trashed": "{} נכס(ים) הועברו לאשפה", "assets_trashed_from_server": "{} נכס(ים) הועברו לאשפה משרת ה-Immich", + "asset_viewer_settings_subtitle": "ניהול הגדרות מציג הגלריה שלך", "asset_viewer_settings_title": "מציג הנכסים", + "automatic_endpoint_switching_subtitle": "התחבר מקומית דרך אינטרנט אלחוטי ייעודי כאשר זמין והשתמש בחיבורים חלופיים במקומות אחרים", + "automatic_endpoint_switching_title": "החלפת כתובת אוטומטית", + "background_location_permission": "הרשאת מיקום ברקע", + "background_location_permission_content": "כדי להחליף רשתות בעת ריצה ברקע, היישום צריך *תמיד* גישה למיקום מדויק על מנת לקרוא את השם של רשת האינטרנט האלחוטי", "backup_album_selection_page_albums_device": "אלבומים במכשיר ({})", "backup_album_selection_page_albums_tap": "הקש כדי לכלול, הקש פעמיים כדי להחריג", "backup_album_selection_page_assets_scatter": "נכסים יכולים להתפזר על פני אלבומים מרובים. לפיכך, ניתן לכלול או להחריג אלבומים במהלך תהליך הגיבוי", @@ -131,6 +137,7 @@ "backup_manual_success": "הצלחה", "backup_manual_title": "מצב העלאה", "backup_options_page_title": "אפשרויות גיבוי", + "backup_setting_subtitle": "ניהול הגדרות העלאת רקע וחזית", "cache_settings_album_thumbnails": "תמונות ממוזערות של דף ספרייה ({} נכסים)", "cache_settings_clear_cache_button": "ניקוי מטמון", "cache_settings_clear_cache_button_title": "מנקה את המטמון של היישום. זה ישפיע באופן משמעותי על הביצועים של היישום עד שהמטמון נבנה מחדש", @@ -149,11 +156,16 @@ "cache_settings_tile_subtitle": "שלוט בהתנהגות האחסון המקומי", "cache_settings_tile_title": "אחסון מקומי", "cache_settings_title": "הגדרות שמירת מטמון", + "cancel": "ביטול", + "change_display_order": "Change display order", "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": "הכנס שוב סיסמה חדשה", + "check_corrupt_asset_backup": "בדוק גיבויים פגומים של נכסים", + "check_corrupt_asset_backup_button": "בצע בדיקה", + "check_corrupt_asset_backup_description": "הרץ בדיקה זו רק על Wi-Fi ולאחר שכל הנכסים גובו. ההליך עשוי לקחת כמה דקות.", "client_cert_dialog_msg_confirm": "בסדר", "client_cert_enter_password": "הזן סיסמה", "client_cert_import": "ייבוא", @@ -189,9 +201,9 @@ "control_bottom_app_bar_unarchive": "הוצא מארכיון", "control_bottom_app_bar_unfavorite": "הסר ממועדפים", "control_bottom_app_bar_upload": "העלאה", - "create_album": "Create album", + "create_album": "צור אלבום", "create_album_page_untitled": "ללא כותרת", - "create_new": "CREATE NEW", + "create_new": "צור חדש", "create_shared_album_page_create": "יצירה", "create_shared_album_page_share": "שתף", "create_shared_album_page_share_add_assets": "הוסף נכסים", @@ -199,6 +211,7 @@ "crop": "חתוך", "curated_location_page_title": "מקומות", "curated_object_page_title": "דברים", + "current_server_address": "כתובת שרת נוכחית", "daily_title_text_date": "E, MMM dd", "daily_title_text_date_year": "E, MMM dd, yyyy", "date_format": "E, LLL d, y • h:mm a", @@ -235,6 +248,8 @@ "edit_date_time_dialog_timezone": "אזור זמן", "edit_image_title": "ערוך", "edit_location_dialog_title": "מיקום", + "enter_wifi_name": "הזן שם אינטרנט אלחוטי", + "error_change_sort_album": "Failed to change album sort order", "error_saving_image": "שגיאה: {}", "exif_bottom_sheet_description": "הוסף תיאור...", "exif_bottom_sheet_details": "פרטים", @@ -246,11 +261,15 @@ "experimental_settings_new_asset_list_title": "אפשר רשת תמונות ניסיונית", "experimental_settings_subtitle": "השימוש הוא על אחריותך בלבד!", "experimental_settings_title": "נסיוני", - "favorites": "Favorites", + "external_network": "רשת חיצונית", + "external_network_sheet_info": "כאשר לא על רשת האינטרנט האלחוטי המועדפת, היישום יתחבר לשרת דרך הכתובת הראשונה שניתן להשיג מהכתובות שלהלן, החל מלמעלה למטה", + "favorites": "מועדפים", "favorites_page_no_favorites": "לא נמצאו נכסים מועדפים", "favorites_page_title": "מועדפים", "filename_search": "שם קובץ או סיומת", - "filter": "Filter", + "filter": "סנן", + "get_wifiname_error": "לא היה ניתן לקבל את שם האינטרנט האלחוטי שלך. יש לודא שהענקת את ההרשאות הדרושות ושאת/ה מחובר/ת לרשת אינטרנט אלחוטי", + "grant_permission": "להעניק הרשאה", "haptic_feedback_switch": "אפשר משוב ברטט", "haptic_feedback_title": "משוב ברטט", "header_settings_add_header_tip": "הוסף כותרת", @@ -274,8 +293,8 @@ "home_page_first_time_notice": "אם זאת הפעם הראשונה שאת/ה משתמש/ת ביישום, נא להקפיד לבחור אלבומ(ים) לגיבוי כך שציר הזמן יוכל לאכלס תמונות וסרטונים באלבומ(ים)", "home_page_share_err_local": "לא ניתן לשתף נכסים מקומיים על ידי קישור, מדלג", "home_page_upload_err_limit": "ניתן להעלות רק מקסימום של 30 נכסים בכל פעם, מדלג", - "ignore_icloud_photos": "Ignore iCloud photos", - "ignore_icloud_photos_description": "Photos that are stored on iCloud will not be uploaded to the Immich server", + "ignore_icloud_photos": "התעלם מתמונות iCloud", + "ignore_icloud_photos_description": "תמונות שמאוחסנות ב-iCloud לא יועלו לשרת ה-Immich", "image_saved_successfully": "תמונה נשמרה", "image_viewer_page_state_provider_download_error": "שגיאת הורדה", "image_viewer_page_state_provider_download_started": "ההורדה החלה", @@ -283,7 +302,7 @@ "image_viewer_page_state_provider_share_error": "שיתוף שגיאה", "invalid_date": "תאריך לא תקין", "invalid_date_format": "פורמט תאריך לא תקין", - "library": "Library", + "library": "ספרייה", "library_page_albums": "אלבומים", "library_page_archive": "ארכיון", "library_page_device_albums": "אלבומים במכשיר", @@ -296,6 +315,10 @@ "library_page_sort_most_oldest_photo": "תמונה הכי ישנה", "library_page_sort_most_recent_photo": "תמונה אחרונה ביותר", "library_page_sort_title": "כותרת אלבום", + "local_network": "רשת מקומית", + "local_network_sheet_info": "היישום יתחבר לשרת דרך הכתובת הזאת כאשר משתמשים ברשת האינטרנט האלחוטי שמצוינת", + "location_permission": "הרשאת מיקום", + "location_permission_content": "כדי להשתמש בתכונת ההחלפה האוטומטית, היישום צריך הרשאה למיקום מדויק על מנת לקרוא את השם של רשת האינטרנט האלחוטי", "location_picker_choose_on_map": "בחר על מפה", "location_picker_latitude": "קו רוחב", "location_picker_latitude_error": "הזן קו רוחב חוקי", @@ -364,7 +387,9 @@ "motion_photos_page_title": "תמונות עם תנועה", "multiselect_grid_edit_date_time_err_read_only": "לא ניתן לערוך תאריך של נכס(ים) לקריאה בלבד, מדלג", "multiselect_grid_edit_gps_err_read_only": "לא ניתן לערוך מיקום של נכס(ים) לקריאה בלבד, מדלג", - "my_albums": "My albums", + "my_albums": "האלבומים שלי", + "networking_settings": "רשת", + "networking_subtitle": "ניהול הגדרות נקודת קצה שרת", "no_assets_to_show": "אין נכסים להציג", "no_name": "ללא שם", "notification_permission_dialog_cancel": "ביטול", @@ -373,7 +398,7 @@ "notification_permission_list_tile_content": "הענק הרשאה כדי לאפשר התראות", "notification_permission_list_tile_enable_button": "אפשר התראות", "notification_permission_list_tile_title": "הרשאת התראה", - "on_this_device": "On this device", + "on_this_device": "במכשיר הזה", "partner_list_user_photos": "תמונות של {user}", "partner_list_view_all": "הצג הכל", "partner_page_add_partner": "הוספת שותף", @@ -385,8 +410,8 @@ "partner_page_stop_sharing_content": "{} לא יוכל יותר לגשת לתמונות שלך", "partner_page_stop_sharing_title": "להפסיק לשתף את התמונות שלך?", "partner_page_title": "שותף", - "partners": "Partners", - "people": "People", + "partners": "שותפים", + "people": "אנשים", "permission_onboarding_back": "חזרה", "permission_onboarding_continue_anyway": "המשך בכל זאת", "permission_onboarding_get_started": "להתחיל", @@ -397,7 +422,8 @@ "permission_onboarding_permission_granted": "ההרשאה ניתנה! את/ה מוכנ/ה", "permission_onboarding_permission_limited": "הרשאה מוגבלת. כדי לתת ליישום לגבות ולנהל את כל אוסף הגלריה שלך, הענק הרשאה לתמונות וסרטונים בהגדרות", "permission_onboarding_request": "היישום דורש הרשאה כדי לראות את התמונות והסרטונים שלך", - "places": "Places", + "places": "מקומות", + "preferences_settings_subtitle": "ניהול העדפות יישום", "preferences_settings_title": "העדפות", "profile_drawer_app_logs": "יומן", "profile_drawer_client_out_of_date_major": "האפליקציה לנייד היא מיושנת. נא לעדכן לגרסה הראשית האחרונה", @@ -410,11 +436,12 @@ "profile_drawer_settings": "הגדרות", "profile_drawer_sign_out": "יציאה", "profile_drawer_trash": "אשפה", - "recently_added": "Recently added", + "recently_added": "נוסף לאחרונה", "recently_added_page_title": "נוסף לאחרונה", + "save": "שמירה", "save_to_gallery": "שמור לגלריה", "scaffold_body_error_occurred": "אירעה שגיאה", - "search_albums": "Search albums", + "search_albums": "חפש/י אלבומים", "search_bar_hint": "חפש/י בתמונות שלך", "search_filter_apply": "החל סינון", "search_filter_camera": "מצלמה", @@ -457,6 +484,7 @@ "search_page_places": "מקומות", "search_page_recently_added": "נוסף לאחרונה", "search_page_screenshots": "צילומי מסך", + "search_page_search_photos_videos": "חפש את התמונות והסרטונים שלך", "search_page_selfies": "צילומי סלפי", "search_page_things": "דברים", "search_page_videos": "סרטונים", @@ -469,6 +497,7 @@ "select_additional_user_for_sharing_page_suggestions": "הצעות", "select_user_for_sharing_page_err_album": "יצירת אלבום נכשלה", "select_user_for_sharing_page_share_suggestions": "הצעות", + "server_endpoint": "נקודת קצה שרת", "server_info_box_app_version": "גרסת יישום", "server_info_box_latest_release": "גרסה עדכנית ביותר", "server_info_box_server_url": "כתובת שרת", @@ -480,6 +509,7 @@ "setting_image_viewer_preview_title": "טען תמונת תצוגה מקדימה", "setting_image_viewer_title": "תמונות", "setting_languages_apply": "החל", + "setting_languages_subtitle": "שינוי שפת היישום", "setting_languages_title": "שפות", "setting_notifications_notify_failures_grace_period": "הודע על כשלים בגיבוי ברקע: {}", "setting_notifications_notify_hours": "{} שעות", @@ -560,9 +590,9 @@ "shared_link_info_chip_upload": "העלאה", "shared_link_manage_links": "ניהול קישורים משותפים", "shared_link_public_album": "אלבום ציבורי", - "shared_links": "Shared links", + "shared_links": "קישורים משותפים", "share_done": "סיום", - "shared_with_me": "Shared with me", + "shared_with_me": "משותף איתי", "share_invite": "הזמן לאלבום", "sharing_page_album": "אלבומים משותפים", "sharing_page_description": "צור אלבומים משותפים כדי לשתף תמונות וסרטונים עם אנשים ברשת שלך", @@ -594,7 +624,7 @@ "theme_setting_three_stage_loading_subtitle": "טעינה בשלושה שלבים עשויה לשפר את ביצועי הטעינה אבל גורמת באופן משמעותי לעומס רשת גבוה יותר", "theme_setting_three_stage_loading_title": "אפשר טעינה בשלושה שלבים", "translated_text_options": "אפשרויות", - "trash": "Trash", + "trash": "אשפה", "trash_emptied": "האשפה רוקנה", "trash_page_delete": "מחק", "trash_page_delete_all": "מחק הכל", @@ -612,14 +642,18 @@ "upload_dialog_info": "האם ברצונך לגבות את הנכס(ים) שנבחרו לשרת?", "upload_dialog_ok": "העלאה", "upload_dialog_title": "העלאת נכס", + "use_current_connection": "השתמש בחיבור נוכחי", + "validate_endpoint_error": "נא להזין כתובת תקנית", "version_announcement_overlay_ack": "אשר", "version_announcement_overlay_release_notes": "הערות פרסום", "version_announcement_overlay_text_1": "הי חבר/ה, יש מהדורה חדשה של", "version_announcement_overlay_text_2": "אנא קח/י את הזמן שלך לבקר ב ", "version_announcement_overlay_text_3": " ולוודא שמבנה ה docker-compose וה env. שלך עדכני כדי למנוע תצורות שגויות, במיוחד אם את/ה משתמש/ת ב WatchTower או בכל מנגנון שמטפל בעדכון יישום השרת שלך באופן אוטומטי", "version_announcement_overlay_title": "גרסת שרת חדשה זמינה \uD83C\uDF89", - "videos": "Videos", + "videos": "סרטונים", "viewer_remove_from_stack": "הסר מערימה", "viewer_stack_use_as_main_asset": "השתמש כנכס ראשי", - "viewer_unstack": "ביטול ערימה" + "viewer_unstack": "ביטול ערימה", + "wifi_name": "שם אינטרנט אלחוטי", + "your_wifi_name": "שם אינטרנט אלחוטי שלך" } \ No newline at end of file diff --git a/mobile/assets/i18n/hi-IN.json b/mobile/assets/i18n/hi-IN.json index 104dae2ebd95e..af4b6b37d92fa 100644 --- a/mobile/assets/i18n/hi-IN.json +++ b/mobile/assets/i18n/hi-IN.json @@ -3,10 +3,11 @@ "action_common_cancel": "Cancel", "action_common_clear": "Clear", "action_common_confirm": "Confirm", - "action_common_save": "Save", - "action_common_select": "Select", + "action_common_save": "सहेजें", + "action_common_select": "चुनें", "action_common_update": "Update", - "add_a_name": "Add a name", + "add_a_name": "नाम जोड़ें", + "add_endpoint": "Add endpoint", "add_to_album_bottom_sheet_added": "Added to {album}", "add_to_album_bottom_sheet_already_exists": "Already in {album}", "advanced_settings_log_level_title": "Log level: {}", @@ -22,7 +23,7 @@ "advanced_settings_troubleshooting_title": "Troubleshooting", "album_info_card_backup_album_excluded": "EXCLUDED", "album_info_card_backup_album_included": "INCLUDED", - "albums": "Albums", + "albums": "एल्बम", "album_thumbnail_card_item": "1 item", "album_thumbnail_card_items": "{} items", "album_thumbnail_card_shared": " · Shared", @@ -38,13 +39,13 @@ "album_viewer_appbar_share_remove": "Remove from album", "album_viewer_appbar_share_to": "साझा करें", "album_viewer_page_share_add_users": "Add users", - "all": "All", + "all": "सभी", "all_people_page_title": "People", "all_videos_page_title": "Videos", "app_bar_signout_dialog_content": "क्या आप सुनिश्चित हैं कि आप लॉग आउट करना चाहते हैं?", "app_bar_signout_dialog_ok": "हाँ", "app_bar_signout_dialog_title": "लॉग आउट", - "archived": "Archived", + "archived": "संग्रहित", "archive_page_no_archived_assets": "No archived assets found", "archive_page_title": "Archive ({})", "asset_action_delete_err_read_only": "Cannot delete read only asset(s), skipping", @@ -58,14 +59,19 @@ "asset_list_layout_sub_title": "Layout", "asset_list_settings_subtitle": "Photo grid layout settings", "asset_list_settings_title": "Photo Grid", - "asset_restored_successfully": "Asset restored successfully", - "assets_deleted_permanently": "{} asset(s) deleted permanently", - "assets_deleted_permanently_from_server": "{} asset(s) deleted permanently from the Immich server", - "assets_removed_permanently_from_device": "{} asset(s) removed permanently from your device", - "assets_restored_successfully": "{} asset(s) restored successfully", - "assets_trashed": "{} asset(s) trashed", - "assets_trashed_from_server": "{} asset(s) trashed from the Immich server", + "asset_restored_successfully": "संपत्ति(याँ) सफलतापूर्वक पुनर्स्थापित की गईं", + "assets_deleted_permanently": "{} संपत्ति(याँ) स्थायी रूप से हटा दी गईं", + "assets_deleted_permanently_from_server": "{} संपत्ति(याँ) इमिच सर्वर से स्थायी रूप से हटा दी गईं", + "assets_removed_permanently_from_device": "{} संपत्ति(याँ) आपके डिवाइस से स्थायी रूप से हटा दी गईं", + "assets_restored_successfully": "{} संपत्ति(याँ) सफलतापूर्वक पुनर्स्थापित की गईं", + "assets_trashed": "{} संपत्ति(याँ) कचरे में डाली गईं", + "assets_trashed_from_server": "{} संपत्ति(याँ) इमिच सर्वर से कचरे में डाली गईं", + "asset_viewer_settings_subtitle": "Manage your gallery viewer settings", "asset_viewer_settings_title": "Asset Viewer", + "automatic_endpoint_switching_subtitle": "Connect locally over designated Wi-Fi when available and use alternative connections elsewhere", + "automatic_endpoint_switching_title": "Automatic URL switching", + "background_location_permission": "Background location permission", + "background_location_permission_content": "In order to switch networks when running in the background, Immich must *always* have precise location access so the app can read the Wi-Fi network's name", "backup_album_selection_page_albums_device": "Albums on device ({})", "backup_album_selection_page_albums_tap": "Tap to include, double tap to exclude", "backup_album_selection_page_assets_scatter": "Assets can scatter across multiple albums. Thus, albums can be included or excluded during the backup process.", @@ -131,6 +137,7 @@ "backup_manual_success": "Success", "backup_manual_title": "Upload status", "backup_options_page_title": "Backup options", + "backup_setting_subtitle": "Manage background and foreground upload settings", "cache_settings_album_thumbnails": "Library page thumbnails ({} assets)", "cache_settings_clear_cache_button": "Clear cache", "cache_settings_clear_cache_button_title": "Clears the app's cache. This will significantly impact the app's performance until the cache has rebuilt.", @@ -149,11 +156,16 @@ "cache_settings_tile_subtitle": "स्थानीय संग्रहण के व्यवहार को नियंत्रित करें", "cache_settings_tile_title": "स्थानीय संग्रहण", "cache_settings_title": "Caching Settings", + "cancel": "Cancel", + "change_display_order": "Change display order", "change_password_form_confirm_password": "Confirm Password", "change_password_form_description": "Hi {name},\n\nThis is either the first time you are signing into the system or a request has been made to change your password. Please enter the new password below.", "change_password_form_new_password": "New Password", "change_password_form_password_mismatch": "Passwords do not match", "change_password_form_reenter_new_password": "Re-enter New Password", + "check_corrupt_asset_backup": "Check for corrupt asset backups", + "check_corrupt_asset_backup_button": "Perform check", + "check_corrupt_asset_backup_description": "Run this check only over Wi-Fi and once all assets have been backed-up. The procedure might take a few minutes.", "client_cert_dialog_msg_confirm": "OK", "client_cert_enter_password": "Enter Password", "client_cert_import": "Import", @@ -168,7 +180,7 @@ "common_create_new_album": "Create new album", "common_server_error": "Please check your network connection, make sure the server is reachable and app/server versions are compatible.", "common_shared": "Shared", - "contextual_search": "Sunrise on the beach", + "contextual_search": "समुद्र तट पर सूर्योदय", "control_bottom_app_bar_add_to_album": "Add to album", "control_bottom_app_bar_album_info": "{} items", "control_bottom_app_bar_album_info_shared": "{} items · Shared", @@ -177,8 +189,8 @@ "control_bottom_app_bar_delete": "Delete", "control_bottom_app_bar_delete_from_immich": "Delete from Immich", "control_bottom_app_bar_delete_from_local": "Delete from device", - "control_bottom_app_bar_download": "Download", - "control_bottom_app_bar_edit": "Edit", + "control_bottom_app_bar_download": "डाउनलोड", + "control_bottom_app_bar_edit": "संपादित करें", "control_bottom_app_bar_edit_location": "Edit Location", "control_bottom_app_bar_edit_time": "Edit Date & Time", "control_bottom_app_bar_favorite": "Favorite", @@ -189,16 +201,17 @@ "control_bottom_app_bar_unarchive": "Unarchive", "control_bottom_app_bar_unfavorite": "Unfavorite", "control_bottom_app_bar_upload": "Upload", - "create_album": "Create album", + "create_album": "एल्बम बनाएँ", "create_album_page_untitled": "Untitled", - "create_new": "CREATE NEW", + "create_new": "नया बनाएं", "create_shared_album_page_create": "Create", "create_shared_album_page_share": "Share", "create_shared_album_page_share_add_assets": "ADD ASSETS", "create_shared_album_page_share_select_photos": "Select Photos", - "crop": "Crop", + "crop": "छाँटें", "curated_location_page_title": "Places", "curated_object_page_title": "Things", + "current_server_address": "Current server address", "daily_title_text_date": "E, MMM dd", "daily_title_text_date_year": "E, MMM dd, yyyy", "date_format": "E, LLL d, y • h:mm a", @@ -216,26 +229,28 @@ "delete_shared_link_dialog_title": "साझा किए गए लिंक को हटाएं", "description_input_hint_text": "Add description...", "description_input_submit_error": "Error updating description, check the log for more details", - "download_canceled": "Download canceled", - "download_complete": "Download complete", - "download_enqueue": "Download enqueued", - "download_error": "Download Error", - "download_failed": "Download failed", - "download_filename": "file: {}", - "download_finished": "Download finished", - "downloading": "Downloading...", - "downloading_media": "Downloading media", - "download_notfound": "Download not found", - "download_paused": "Download paused", - "download_started": "Download started", - "download_sucess": "Download success", - "download_sucess_android": "The media has been downloaded to DCIM/Immich", - "download_waiting_to_retry": "Waiting to retry", + "download_canceled": "डाउनलोड रद्द कर दिया गया", + "download_complete": "डाउनलोड पूरा", + "download_enqueue": "डाउनलोड कतार में है", + "download_error": "डाउनलोड त्रुटि", + "download_failed": "डाउनलोड विफल", + "download_filename": "फ़ाइल: {}", + "download_finished": "डाउनलोड समाप्त", + "downloading": "डाउनलोड हो रहा है...", + "downloading_media": "मीडिया डाउनलोड हो रहा है", + "download_notfound": "डाउनलोड नहीं मिला", + "download_paused": "डाउनलोड स्थगित", + "download_started": "डाउनलोड प्रारंभ हुआ", + "download_sucess": "डाउनलोड सफल", + "download_sucess_android": "मीडिया DCIM/Immich में डाउनलोड हो गया है", + "download_waiting_to_retry": "पुनः प्रयास करने का इंतजार कर रहा है", "edit_date_time_dialog_date_time": "Date and Time", "edit_date_time_dialog_timezone": "Timezone", - "edit_image_title": "Edit", + "edit_image_title": "संपादित करें", "edit_location_dialog_title": "Location", - "error_saving_image": "Error: {}", + "enter_wifi_name": "Enter WiFi name", + "error_change_sort_album": "Failed to change album sort order", + "error_saving_image": "त्रुटि: {}", "exif_bottom_sheet_description": "Add Description...", "exif_bottom_sheet_details": "DETAILS", "exif_bottom_sheet_location": "LOCATION", @@ -246,11 +261,15 @@ "experimental_settings_new_asset_list_title": "Enable experimental photo grid", "experimental_settings_subtitle": "Use at your own risk!", "experimental_settings_title": "Experimental", - "favorites": "Favorites", + "external_network": "External network", + "external_network_sheet_info": "When not on the preferred WiFi network, the app will connect to the server through the first of the below URLs it can reach, starting from top to bottom", + "favorites": "पसंदीदा", "favorites_page_no_favorites": "No favorite assets found", "favorites_page_title": "Favorites", - "filename_search": "File name or extension", - "filter": "Filter", + "filename_search": "फ़ाइल नाम या एक्सटेंशन", + "filter": "फ़िल्टर", + "get_wifiname_error": "Could not get Wi-Fi name. Make sure you have granted the necessary permissions and are connected to a Wi-Fi network", + "grant_permission": "Grant permission", "haptic_feedback_switch": "Enable haptic feedback", "haptic_feedback_title": "Haptic Feedback", "header_settings_add_header_tip": "Add Header", @@ -274,16 +293,16 @@ "home_page_first_time_notice": "If this is your first time using the app, please make sure to choose a backup album(s) so that the timeline can populate photos and videos in the album(s).", "home_page_share_err_local": "लोकल एसेट्स को लिंक के जरिए शेयर नहीं कर सकते, स्किप कर रहे हैं", "home_page_upload_err_limit": "Can only upload a maximum of 30 assets at a time, skipping", - "ignore_icloud_photos": "Ignore iCloud photos", - "ignore_icloud_photos_description": "Photos that are stored on iCloud will not be uploaded to the Immich server", - "image_saved_successfully": "Image saved", + "ignore_icloud_photos": "आइक्लाउड फ़ोटो को अनदेखा करें", + "ignore_icloud_photos_description": "आइक्लाउड पर स्टोर की गई फ़ोटोज़ इमिच सर्वर पर अपलोड नहीं की जाएंगी", + "image_saved_successfully": "इमेज सहेज दी गई", "image_viewer_page_state_provider_download_error": "Download Error", "image_viewer_page_state_provider_download_started": "Download Started", "image_viewer_page_state_provider_download_success": "Download Success", "image_viewer_page_state_provider_share_error": "Share Error", - "invalid_date": "Invalid date", - "invalid_date_format": "Invalid date format", - "library": "Library", + "invalid_date": "अमान्य तारीख़", + "invalid_date_format": "अमान्य तारीख़ प्रारूप", + "library": "गैलरी", "library_page_albums": "Albums", "library_page_archive": "Archive", "library_page_device_albums": "Albums on Device", @@ -296,6 +315,10 @@ "library_page_sort_most_oldest_photo": "Oldest photo", "library_page_sort_most_recent_photo": "Most recent photo", "library_page_sort_title": "Album title", + "local_network": "Local network", + "local_network_sheet_info": "The app will connect to the server through this URL when using the specified Wi-Fi network", + "location_permission": "Location permission", + "location_permission_content": "In order to use the auto-switching feature, Immich needs precise location permission so it can read the current WiFi network's name", "location_picker_choose_on_map": "Choose on map", "location_picker_latitude": "Latitude", "location_picker_latitude_error": "Enter a valid latitude", @@ -364,16 +387,18 @@ "motion_photos_page_title": "Motion Photos", "multiselect_grid_edit_date_time_err_read_only": "Cannot edit date of read only asset(s), skipping", "multiselect_grid_edit_gps_err_read_only": "Cannot edit location of read only asset(s), skipping", - "my_albums": "My albums", + "my_albums": "मेरे एल्बम", + "networking_settings": "Networking", + "networking_subtitle": "Manage the server endpoint settings", "no_assets_to_show": "No assets to show", - "no_name": "No name", + "no_name": "कोई नाम नहीं", "notification_permission_dialog_cancel": "Cancel", "notification_permission_dialog_content": "To enable notifications, go to Settings and select allow.", "notification_permission_dialog_settings": "Settings", "notification_permission_list_tile_content": "Grant permission to enable notifications.", "notification_permission_list_tile_enable_button": "Enable Notifications", "notification_permission_list_tile_title": "Notification Permission", - "on_this_device": "On this device", + "on_this_device": "इस डिवाइस पर", "partner_list_user_photos": "{user}'s photos", "partner_list_view_all": "View all", "partner_page_add_partner": "Add partner", @@ -385,8 +410,8 @@ "partner_page_stop_sharing_content": "{} will no longer be able to access your photos.", "partner_page_stop_sharing_title": "Stop sharing your photos?", "partner_page_title": "Partner", - "partners": "Partners", - "people": "People", + "partners": "साझेदार", + "people": "लोग", "permission_onboarding_back": "वापस", "permission_onboarding_continue_anyway": "Continue anyway", "permission_onboarding_get_started": "Get started", @@ -397,7 +422,8 @@ "permission_onboarding_permission_granted": "Permission granted! You are all set.", "permission_onboarding_permission_limited": "Permission limited. To let Immich backup and manage your entire gallery collection, grant photo and video permissions in Settings.", "permission_onboarding_request": "Immich requires permission to view your photos and videos.", - "places": "Places", + "places": "स्थान", + "preferences_settings_subtitle": "Manage the app's preferences", "preferences_settings_title": "Preferences", "profile_drawer_app_logs": "Logs", "profile_drawer_client_out_of_date_major": "Mobile App is out of date. Please update to the latest major version.", @@ -410,37 +436,38 @@ "profile_drawer_settings": "Settings", "profile_drawer_sign_out": "Sign Out", "profile_drawer_trash": "Trash", - "recently_added": "Recently added", + "recently_added": "हाल ही में जोड़ा गया", "recently_added_page_title": "Recently Added", - "save_to_gallery": "Save to gallery", + "save": "Save", + "save_to_gallery": "गैलरी में सहेजें", "scaffold_body_error_occurred": "Error occurred", - "search_albums": "Search albums", + "search_albums": "एल्बम खोजें", "search_bar_hint": "Search your photos", "search_filter_apply": "Apply filter", - "search_filter_camera": "Camera", + "search_filter_camera": "कैमरा", "search_filter_camera_make": "Make", "search_filter_camera_model": "Model", - "search_filter_camera_title": "Select camera type", - "search_filter_date": "Date", - "search_filter_date_interval": "{start} to {end}", - "search_filter_date_title": "Select a date range", + "search_filter_camera_title": "कैमरा प्रकार चुनें", + "search_filter_date": "तारीख़", + "search_filter_date_interval": "{start} से {end} तक", + "search_filter_date_title": "तारीख़ की सीमा चुनें", "search_filter_display_option_archive": "Archive", "search_filter_display_option_favorite": "Favorite", "search_filter_display_option_not_in_album": "Not in album", - "search_filter_display_options": "Display Options", - "search_filter_display_options_title": "Display options", - "search_filter_location": "Location", + "search_filter_display_options": "प्रदर्शन विकल्प", + "search_filter_display_options_title": "प्रदर्शन विकल्प", + "search_filter_location": "स्थान", "search_filter_location_city": "City", "search_filter_location_country": "Country", "search_filter_location_state": "State", - "search_filter_location_title": "Select location", - "search_filter_media_type": "Media Type", + "search_filter_location_title": "स्थान चुनें", + "search_filter_media_type": "मीडिया प्रकार", "search_filter_media_type_all": "All", "search_filter_media_type_image": "Image", - "search_filter_media_type_title": "Select media type", + "search_filter_media_type_title": "मीडिया प्रकार चुनें", "search_filter_media_type_video": "Video", - "search_filter_people": "People", - "search_filter_people_title": "Select people", + "search_filter_people": "लोग", + "search_filter_people_title": "लोगों का चयन करें", "search_page_categories": "Categories", "search_page_favorites": "Favorites", "search_page_motion_photos": "Motion Photos", @@ -457,6 +484,7 @@ "search_page_places": "Places", "search_page_recently_added": "Recently added", "search_page_screenshots": "Screenshots", + "search_page_search_photos_videos": "Search for your photos and videos", "search_page_selfies": "Selfies", "search_page_things": "Things", "search_page_videos": "Videos", @@ -469,6 +497,7 @@ "select_additional_user_for_sharing_page_suggestions": "Suggestions", "select_user_for_sharing_page_err_album": "Failed to create album", "select_user_for_sharing_page_share_suggestions": "Suggestions", + "server_endpoint": "Server Endpoint", "server_info_box_app_version": "App Version", "server_info_box_latest_release": "लेटेस्ट वर्ज़न", "server_info_box_server_url": "सर्वर URL", @@ -480,6 +509,7 @@ "setting_image_viewer_preview_title": "Load preview image", "setting_image_viewer_title": "Images", "setting_languages_apply": "Apply", + "setting_languages_subtitle": "Change the app's language", "setting_languages_title": "Languages", "setting_notifications_notify_failures_grace_period": "Notify background backup failures: {}", "setting_notifications_notify_hours": "{} hours", @@ -560,9 +590,9 @@ "shared_link_info_chip_upload": "Upload", "shared_link_manage_links": "साझा किए गए लिंक का प्रबंधन करें", "shared_link_public_album": "Public album", - "shared_links": "Shared links", + "shared_links": "साझा किए गए लिंक", "share_done": "Done", - "shared_with_me": "Shared with me", + "shared_with_me": "मेरे साथ साझा किया गया", "share_invite": "Invite to album", "sharing_page_album": "Shared albums", "sharing_page_description": "Create shared albums to share photos and videos with people in your network.", @@ -570,32 +600,32 @@ "sharing_silver_appbar_create_shared_album": "New shared album", "sharing_silver_appbar_shared_links": "Shared links", "sharing_silver_appbar_share_partner": "Share with partner", - "sync": "Sync", - "sync_albums": "Sync albums", - "sync_albums_manual_subtitle": "Sync all uploaded videos and photos to the selected backup albums", - "sync_upload_album_setting_subtitle": "Create and upload your photos and videos to the selected albums on Immich", + "sync": "सिंक करें", + "sync_albums": "एल्बम्स सिंक करें", + "sync_albums_manual_subtitle": "चुने हुए बैकअप एल्बम्स में सभी अपलोड की गई वीडियो और फ़ोटो सिंक करें", + "sync_upload_album_setting_subtitle": "अपनी फ़ोटो और वीडियो बनाएँ और उन्हें इमिच पर चुने हुए एल्बम्स में अपलोड करें", "tab_controller_nav_library": "Library", "tab_controller_nav_photos": "Photos", "tab_controller_nav_search": "Search", "tab_controller_nav_sharing": "Sharing", "theme_setting_asset_list_storage_indicator_title": "Show storage indicator on asset tiles", "theme_setting_asset_list_tiles_per_row_title": "Number of assets per row ({})", - "theme_setting_colorful_interface_subtitle": "Apply primary color to background surfaces.", - "theme_setting_colorful_interface_title": "Colorful interface", + "theme_setting_colorful_interface_subtitle": "प्राथमिक रंग को पृष्ठभूमि सतहों पर लागू करें", + "theme_setting_colorful_interface_title": "रंगीन इंटरफ़ेस", "theme_setting_dark_mode_switch": "Dark mode", "theme_setting_image_viewer_quality_subtitle": "Adjust the quality of the detail image viewer", "theme_setting_image_viewer_quality_title": "Image viewer quality", - "theme_setting_primary_color_subtitle": "Pick a color for primary actions and accents.", - "theme_setting_primary_color_title": "Primary color", - "theme_setting_system_primary_color_title": "Use system color", + "theme_setting_primary_color_subtitle": "प्राथमिक क्रियाओं और उच्चारणों के लिए एक रंग चुनें", + "theme_setting_primary_color_title": "प्राथमिक रंग", + "theme_setting_system_primary_color_title": "सिस्टम रंग का उपयोग करें", "theme_setting_system_theme_switch": "Automatic (Follow system setting)", "theme_setting_theme_subtitle": "Choose the app's theme setting", "theme_setting_theme_title": "Theme", "theme_setting_three_stage_loading_subtitle": "Three-stage loading might increase the loading performance but causes significantly higher network load", "theme_setting_three_stage_loading_title": "Enable three-stage loading", "translated_text_options": "Options", - "trash": "Trash", - "trash_emptied": "Emptied trash", + "trash": "कचरा", + "trash_emptied": "कचरा खाली कर दिया", "trash_page_delete": "Delete", "trash_page_delete_all": "Delete All", "trash_page_empty_trash_btn": "कूड़ेदान खाली करें", @@ -612,14 +642,18 @@ "upload_dialog_info": "Do you want to backup the selected Asset(s) to the server?", "upload_dialog_ok": "Upload", "upload_dialog_title": "Upload Asset", + "use_current_connection": "use current connection", + "validate_endpoint_error": "Please enter a valid URL", "version_announcement_overlay_ack": "Acknowledge", "version_announcement_overlay_release_notes": "release notes", "version_announcement_overlay_text_1": "Hi friend, there is a new release of", "version_announcement_overlay_text_2": "please take your time to visit the ", "version_announcement_overlay_text_3": " and ensure your docker-compose and .env setup is up-to-date to prevent any misconfigurations, especially if you use WatchTower or any mechanism that handles updating your server application automatically.", "version_announcement_overlay_title": "New Server Version Available \uD83C\uDF89", - "videos": "Videos", + "videos": "वीडियो", "viewer_remove_from_stack": "स्टैक से हटाएं", "viewer_stack_use_as_main_asset": "मुख्य संपत्ति के रूप में उपयोग करें", - "viewer_unstack": "स्टैक रद्द करें" + "viewer_unstack": "स्टैक रद्द करें", + "wifi_name": "WiFi Name", + "your_wifi_name": "Your WiFi name" } \ No newline at end of file diff --git a/mobile/assets/i18n/hu-HU.json b/mobile/assets/i18n/hu-HU.json index e28535f9b15f1..ee17a2d17449b 100644 --- a/mobile/assets/i18n/hu-HU.json +++ b/mobile/assets/i18n/hu-HU.json @@ -1,19 +1,20 @@ { "action_common_back": "Vissza", "action_common_cancel": "Mégsem", - "action_common_clear": "Kitöröl", + "action_common_clear": "Alaphelyzetbe állít", "action_common_confirm": "Jóváhagy", - "action_common_save": "Save", - "action_common_select": "Select", + "action_common_save": "Mentés", + "action_common_select": "Kiválaszt", "action_common_update": "Frissít", - "add_a_name": "Add a name", + "add_a_name": "Név hozzáadása", + "add_endpoint": "Add endpoint", "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", "advanced_settings_log_level_title": "Naplózás szintje: {}", - "advanced_settings_prefer_remote_subtitle": "Néhány eszköz fájdalmasan lassan tölti be az eszközön lévő bélyegképeket. Ezzel a beállítással inkább a távoli képeket töltjük be helyette.", + "advanced_settings_prefer_remote_subtitle": "Néhány eszköz fájdalmasan lassan tölti be az eszközön lévő bélyegképeket. Ez a beállítás inkább a távoli képeket tölti be helyettük.", "advanced_settings_prefer_remote_title": "Távoli képek előnyben részesítése", - "advanced_settings_proxy_headers_subtitle": "Define proxy headers Immich should send with each network request", - "advanced_settings_proxy_headers_title": "Proxy Headers", + "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_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_tile_subtitle": "Haladó felhasználói beállítások", @@ -22,7 +23,7 @@ "advanced_settings_troubleshooting_title": "Hibaelhárítás", "album_info_card_backup_album_excluded": "KIHAGYVA", "album_info_card_backup_album_included": "BELEÉRTVE", - "albums": "Albums", + "albums": "Albumok", "album_thumbnail_card_item": "1 elem", "album_thumbnail_card_items": "{} elem", "album_thumbnail_card_shared": "· Megosztott", @@ -30,56 +31,61 @@ "album_thumbnail_shared_by": "Megosztotta: {}", "album_viewer_appbar_delete_confirm": "Biztos, hogy törölni szeretnéd ezt az albumot?", "album_viewer_appbar_share_delete": "Album törlése", - "album_viewer_appbar_share_err_delete": "Nem sikerült törölni az albumot", + "album_viewer_appbar_share_err_delete": "Az album törlése sikertelen", "album_viewer_appbar_share_err_leave": "Nem sikerült kilépni az albumból", "album_viewer_appbar_share_err_remove": "Néhány elemet nem sikerült törölni az albumból", - "album_viewer_appbar_share_err_title": "Nem sikerült átnevezni az albumot", + "album_viewer_appbar_share_err_title": "Az album átnevezése sikertelen", "album_viewer_appbar_share_leave": "Kilépés az albumból", "album_viewer_appbar_share_remove": "Eltávolítás az albumból", "album_viewer_appbar_share_to": "Megosztás Ide", "album_viewer_page_share_add_users": "Felhasználók hozzáadása", - "all": "All", + "all": "Összes", "all_people_page_title": "Emberek", "all_videos_page_title": "Videók", "app_bar_signout_dialog_content": "Biztos, hogy ki szeretnél jelentkezni?", "app_bar_signout_dialog_ok": "Igen", "app_bar_signout_dialog_title": "Kijelentkezés", - "archived": "Archived", + "archived": "Archivált", "archive_page_no_archived_assets": "Nem található archivált elem", "archive_page_title": "Archívum ({})", "asset_action_delete_err_read_only": "Csak-olvasható elem(ek)et nem lehet törölni, így ezeket átugorjuk", - "asset_action_share_err_offline": "Nem sikerült betölteni a kapcsolat nélküli elem(ek)et, így ezeket kihagyjuk", + "asset_action_share_err_offline": "Nem lehet betölteni a kapcsolat nélküli elem(ek)et, így ezeket kihagyjuk", "asset_list_group_by_sub_title": "Csoportosítás", "asset_list_layout_settings_dynamic_layout_title": "Dinamikus elrendezés", - "asset_list_layout_settings_group_automatically": "Automatikus", + "asset_list_layout_settings_group_automatically": "Automatikusan", "asset_list_layout_settings_group_by": "Elemek csoportosítása", - "asset_list_layout_settings_group_by_month": "hónapok szerint", - "asset_list_layout_settings_group_by_month_day": "hónap és nap szerint", + "asset_list_layout_settings_group_by_month": "Hónapok szerint", + "asset_list_layout_settings_group_by_month_day": "Hónapok és napok szerint", "asset_list_layout_sub_title": "Elrendezés", "asset_list_settings_subtitle": "Fotórács elrendezése", "asset_list_settings_title": "Fotórács", - "asset_restored_successfully": "Asset restored successfully", - "assets_deleted_permanently": "{} asset(s) deleted permanently", - "assets_deleted_permanently_from_server": "{} asset(s) deleted permanently from the Immich server", - "assets_removed_permanently_from_device": "{} asset(s) removed permanently from your device", - "assets_restored_successfully": "{} asset(s) restored successfully", - "assets_trashed": "{} asset(s) trashed", - "assets_trashed_from_server": "{} asset(s) trashed from the Immich server", + "asset_restored_successfully": "Elem sikeresen helyreállítva", + "assets_deleted_permanently": "{} elem véglegesen törölve", + "assets_deleted_permanently_from_server": "{} elem véglegesen törölve az Immich szerverről", + "assets_removed_permanently_from_device": "{} elem véglegesen törölve az eszközödről", + "assets_restored_successfully": "{} elem sikeresen helyreállítva", + "assets_trashed": "{} elem lomtárba helyezve", + "assets_trashed_from_server": "{} elem lomtárba helyezve az Immich szerveren", + "asset_viewer_settings_subtitle": "Manage your gallery viewer settings", "asset_viewer_settings_title": "Elem Megjelenítő", + "automatic_endpoint_switching_subtitle": "Connect locally over designated Wi-Fi when available and use alternative connections elsewhere", + "automatic_endpoint_switching_title": "Automatic URL switching", + "background_location_permission": "Background location permission", + "background_location_permission_content": "In order to switch networks when running in the background, Immich must *always* have precise location access so the app can read the Wi-Fi network's name", "backup_album_selection_page_albums_device": "Ezen az eszközön lévő albumok ({})", - "backup_album_selection_page_albums_tap": "Koppincs a hozzáadáshoz, duplán koppincs az eltávolításhoz", + "backup_album_selection_page_albums_tap": "Koppints a hozzáadáshoz, duplán koppints az eltávolításhoz", "backup_album_selection_page_assets_scatter": "Egy elem több albumban is lehet. Ezért a mentéshez albumokat lehet hozzáadni vagy azokat a mentésből kihagyni.", "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_all": "Összes", - "backup_background_service_backup_failed_message": "Hiba a mentés közben. Újrapróbálkozás...", - "backup_background_service_connection_failed_message": "Hiba a szerverhez való csatlakozás közben. Újrapróbálkozás...", + "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...", "backup_background_service_current_upload_notification": "Feltöltés {}", - "backup_background_service_default_notification": "Új elemek keresése...", - "backup_background_service_error_title": "Hiba mentés közben", + "backup_background_service_default_notification": "Új elemek ellenőrzése...", + "backup_background_service_error_title": "Hiba a mentés közben", "backup_background_service_in_progress_notification": "Elemek mentése folyamatban…", - "backup_background_service_upload_failure_notification": "Hiba a feltöltés közben {}", + "backup_background_service_upload_failure_notification": "A feltöltés sikertelen {}", "backup_controller_page_albums": "Albumok Mentése", "backup_controller_page_background_app_refresh_disabled_content": "Engedélyezd a háttérben történő frissítést a Beállítások > Általános > Háttérben Frissítés menüpontban.", "backup_controller_page_background_app_refresh_disabled_title": "Háttérben frissítés kikapcsolva", @@ -89,7 +95,7 @@ "backup_controller_page_background_battery_info_ok": "OK", "backup_controller_page_background_battery_info_title": "Akkumulátor optimalizálás", "backup_controller_page_background_charging": "Csak töltés közben", - "backup_controller_page_background_configure_error": "Nem sikerült beállítani a háttér szolgáltatást", + "backup_controller_page_background_configure_error": "A háttérszolgáltatás beállítása sikertelen", "backup_controller_page_background_delay": "Új elemek mentésének késleltetése: {}", "backup_controller_page_background_description": "Kapcsold be a háttérfolyamatot, hogy automatikusan mentsen elemeket az applikáció megnyitása nélkül", "backup_controller_page_background_is_off": "Automatikus mentés a háttérben ki van kapcsolva", @@ -102,7 +108,7 @@ "backup_controller_page_backup_sub": "Mentett fotók és videók", "backup_controller_page_cancel": "Mégsem", "backup_controller_page_created": "Létrehozva: {}", - "backup_controller_page_desc_backup": "Ha engedélyezed az előtérben mentést, akkor az új elemek automatikusan feltöltődnek a szerverre, amikor megyitod az alkalmazást.", + "backup_controller_page_desc_backup": "Ha bekapcsolod az előtérben mentést, akkor az új elemek automatikusan feltöltődnek a szerverre, amikor megyitod az alkalmazást.", "backup_controller_page_excluded": "Kivéve:", "backup_controller_page_failed": "Sikertelen ({})", "backup_controller_page_filename": "Fájlnév: {}[{}]", @@ -131,6 +137,7 @@ "backup_manual_success": "Sikeres", "backup_manual_title": "Feltöltés állapota", "backup_options_page_title": "Biztonági mentés beállításai", + "backup_setting_subtitle": "Manage background and foreground upload settings", "cache_settings_album_thumbnails": "Képtár oldalankénti bélyegképei ({} elem)", "cache_settings_clear_cache_button": "Gyorsítótár kiürítése", "cache_settings_clear_cache_button_title": "Kiüríti az alkalmazás gyorsítótárát. Ez jelentősen kihat az alkalmazás teljesítményére, amíg a gyorsítótár újra nem épül.", @@ -149,36 +156,41 @@ "cache_settings_tile_subtitle": "Helyi tárhely viselkedésének beállítása", "cache_settings_tile_title": "Helyi Tárhely", "cache_settings_title": "Gyorsítótár Beállítások", + "cancel": "Cancel", + "change_display_order": "Change display order", "change_password_form_confirm_password": "Jelszó Megerősítése", "change_password_form_description": "Szia {name}!\n\nMost jelentkezel be először a rendszerbe vagy más okból szükséges a jelszavad meváltoztatása. Kérjük, add meg új jelszavad.", "change_password_form_new_password": "Új Jelszó", "change_password_form_password_mismatch": "A beírt jelszavak nem egyeznek", - "change_password_form_reenter_new_password": "Jelszó (még egyszer)", + "change_password_form_reenter_new_password": "Jelszó (Még Egyszer)", + "check_corrupt_asset_backup": "Check for corrupt asset backups", + "check_corrupt_asset_backup_button": "Perform check", + "check_corrupt_asset_backup_description": "Run this check only over Wi-Fi and once all assets have been backed-up. The procedure might take a few minutes.", "client_cert_dialog_msg_confirm": "OK", - "client_cert_enter_password": "Enter Password", - "client_cert_import": "Import", - "client_cert_import_success_msg": "Client certificate is imported", - "client_cert_invalid_msg": "Invalid certificate file or wrong password", - "client_cert_remove": "Remove", - "client_cert_remove_msg": "Client certificate is removed", - "client_cert_subtitle": "Supports PKCS12 (.p12, .pfx) format only. Certificate Import/Remove is available only before login", - "client_cert_title": "SSL Client Certificate", + "client_cert_enter_password": "Jelszó Megadása", + "client_cert_import": "Importálás", + "client_cert_import_success_msg": "Kliens tanúsítvány importálva", + "client_cert_invalid_msg": "Érvénytelen tanúsítvány fájl vagy hibás jelszó", + "client_cert_remove": "Eltávolítás", + "client_cert_remove_msg": "Kliens tanúsítvány eltávolítva", + "client_cert_subtitle": "Csak a PKCS12 (.p12, .pfx) formátum támogatott. Tanúsítvány Importálása/Eltávolítása csak a bejelentkezés előtt lehetséges", + "client_cert_title": "SSL Kliens Tanúsítvány", "common_add_to_album": "Albumhoz ad", "common_change_password": "Jelszócsere", "common_create_new_album": "Új album létrehozása", "common_server_error": "Kérjük, ellenőrizd a hálózati kapcsolatot, gondoskodj róla, hogy a szerver elérhető legyen, valamint az alkalmazás és a szerver kompatibilis verziójú legyen.", - "common_shared": "Megosztva", - "contextual_search": "Sunrise on the beach", + "common_shared": "Megosztott", + "contextual_search": "Napfelkelte a tengerparton", "control_bottom_app_bar_add_to_album": "Albumhoz ad", "control_bottom_app_bar_album_info": "{} elem", "control_bottom_app_bar_album_info_shared": "{} elemek · Megosztva", - "control_bottom_app_bar_archive": "Archivál", + "control_bottom_app_bar_archive": "Archiválás", "control_bottom_app_bar_create_new_album": "Új album létrehozása", "control_bottom_app_bar_delete": "Törlés", "control_bottom_app_bar_delete_from_immich": "Törlés az Immich-ből", "control_bottom_app_bar_delete_from_local": "Törlés az eszközről", - "control_bottom_app_bar_download": "Download", - "control_bottom_app_bar_edit": "Edit", + "control_bottom_app_bar_download": "Letöltés", + "control_bottom_app_bar_edit": "Szerkesztés", "control_bottom_app_bar_edit_location": "Hely Módosítása", "control_bottom_app_bar_edit_time": "Dátum és Idő Módosítása", "control_bottom_app_bar_favorite": "Kedvenc", @@ -189,16 +201,17 @@ "control_bottom_app_bar_unarchive": "Nem Archivált", "control_bottom_app_bar_unfavorite": "Nem Kedvenc", "control_bottom_app_bar_upload": "Feltöltés", - "create_album": "Create album", + "create_album": "Album létrehozása", "create_album_page_untitled": "Névtelen", - "create_new": "CREATE NEW", + "create_new": "ÚJ LÉTREHOZÁSA", "create_shared_album_page_create": "Létrehoz", "create_shared_album_page_share": "Megosztás", "create_shared_album_page_share_add_assets": "ELEMEK HOZZÁADÁSA", "create_shared_album_page_share_select_photos": "Fotók választása", - "crop": "Crop", + "crop": "Kivágás", "curated_location_page_title": "Helyek", "curated_object_page_title": "Dolgok", + "current_server_address": "Current server address", "daily_title_text_date": "MMM dd (E)", "daily_title_text_date_year": "yyyy MMM dd (E)", "date_format": "y LLL d (E) • HH:mm", @@ -216,26 +229,28 @@ "delete_shared_link_dialog_title": "Megosztott Link Törlése", "description_input_hint_text": "Leírás hozzáadása...", "description_input_submit_error": "Nem sikerült frissíteni a leírást. További információért kérjük, nézd meg az eseménynaplót", - "download_canceled": "Download canceled", - "download_complete": "Download complete", - "download_enqueue": "Download enqueued", - "download_error": "Download Error", - "download_failed": "Download failed", - "download_filename": "file: {}", - "download_finished": "Download finished", - "downloading": "Downloading...", - "downloading_media": "Downloading media", - "download_notfound": "Download not found", - "download_paused": "Download paused", - "download_started": "Download started", - "download_sucess": "Download success", - "download_sucess_android": "The media has been downloaded to DCIM/Immich", - "download_waiting_to_retry": "Waiting to retry", + "download_canceled": "Letöltés megszakítva", + "download_complete": "Letöltés kész", + "download_enqueue": "Letöltés sorba állítva", + "download_error": "Letöltési Hiba", + "download_failed": "Sikertelen letöltés", + "download_filename": "fájl: {}", + "download_finished": "Letöltés kész", + "downloading": "Letöltés...", + "downloading_media": "Média letöltése", + "download_notfound": "Letöltés nem található", + "download_paused": "Letöltés szüneteltetve", + "download_started": "Letöltés megkezdve", + "download_sucess": "Sikeres letöltés", + "download_sucess_android": "Média letöltve a DCIM/Immich mappába\n", + "download_waiting_to_retry": "Várakozás", "edit_date_time_dialog_date_time": "Dátum és Idő", "edit_date_time_dialog_timezone": "Időzóna", - "edit_image_title": "Edit", + "edit_image_title": "Szerkesztés", "edit_location_dialog_title": "Hely", - "error_saving_image": "Error: {}", + "enter_wifi_name": "Enter WiFi name", + "error_change_sort_album": "Failed to change album sort order", + "error_saving_image": "Hiba: {}", "exif_bottom_sheet_description": "Leírás Hozzáadása...", "exif_bottom_sheet_details": "RÉSZLETEK", "exif_bottom_sheet_location": "HELY", @@ -246,20 +261,24 @@ "experimental_settings_new_asset_list_title": "Kisérleti képrács engedélyezése", "experimental_settings_subtitle": "Csak saját felelősségre használd!", "experimental_settings_title": "Kísérleti", - "favorites": "Favorites", + "external_network": "External network", + "external_network_sheet_info": "When not on the preferred WiFi network, the app will connect to the server through the first of the below URLs it can reach, starting from top to bottom", + "favorites": "Kedvencek", "favorites_page_no_favorites": "Nem található kedvencnek jelölt elem", "favorites_page_title": "Kedvencek", - "filename_search": "File name or extension", - "filter": "Filter", + "filename_search": "Fájlnév vagy kiterjesztés", + "filter": "Szűrő", + "get_wifiname_error": "Could not get Wi-Fi name. Make sure you have granted the necessary permissions and are connected to a Wi-Fi network", + "grant_permission": "Grant permission", "haptic_feedback_switch": "Rezgéses visszajelzés engedélyezése", "haptic_feedback_title": "Rezgéses Visszajelzés", - "header_settings_add_header_tip": "Add Header", - "header_settings_field_validator_msg": "Value cannot be empty", - "header_settings_header_name_input": "Header name", - "header_settings_header_value_input": "Header value", - "header_settings_page_title": "Proxy Headers", - "headers_settings_tile_subtitle": "Define proxy headers the app should send with each network request", - "headers_settings_tile_title": "Custom proxy headers", + "header_settings_add_header_tip": "Fejléc Hozzáadása", + "header_settings_field_validator_msg": "Az érték nem lehet üres", + "header_settings_header_name_input": "Fejléc neve", + "header_settings_header_value_input": "Fejléc értéke", + "header_settings_page_title": "Proxy Fejlécek", + "headers_settings_tile_subtitle": "Add meg azokat a proxy fejléceket, amiket az app elküldjön minden hálózati kérésnél", + "headers_settings_tile_title": "Egyéni proxy fejlécek", "home_page_add_to_album_conflicts": "{added} elem hozzáadva a(z) \"{album}\" albumhoz. {failed} elem már eleve az albumban volt.", "home_page_add_to_album_err_local": "Helyi elemeket még nem lehet albumba tenni. Kihagyjuk.", "home_page_add_to_album_success": "{added} elem hozzáadva a(z) \"{album}\" albumhoz.", @@ -272,30 +291,34 @@ "home_page_favorite_err_local": "Helyi elemeket még nem lehet a kedvencek közé tenni, úgyhogy ezeket kihagyjuk", "home_page_favorite_err_partner": "Partner elemeit még nem lehet a kedvencek közé tenni, úgyhogy ezeket kihagyjuk", "home_page_first_time_notice": "Ha most használod először az alkalmazást, akkor ahhoz, hogy megjelenjenek a fotók és a videók az idővonaladon, állítsd be, hogy melyik albumaidról készüljön biztonsági mentés.", - "home_page_share_err_local": "Helyi elemekről nem lehet megosztási linket készíteni, úgyhogy kihagyjuk", + "home_page_share_err_local": "Helyi elemekről nem lehet megosztott linket készíteni, úgyhogy kihagyjuk", "home_page_upload_err_limit": "Csak 30 elemet tudsz egyszerre feltölteni, úgyhogy kihagyjuk", - "ignore_icloud_photos": "Ignore iCloud photos", - "ignore_icloud_photos_description": "Photos that are stored on iCloud will not be uploaded to the Immich server", - "image_saved_successfully": "Image saved", + "ignore_icloud_photos": "iCloud fotók figyelmen kívül hagyása", + "ignore_icloud_photos_description": "Az iCloud-ban tárolt fotók nem lesznek feltöltve az Immich szerverre", + "image_saved_successfully": "Kép elmentve", "image_viewer_page_state_provider_download_error": "Letöltési Hiba", "image_viewer_page_state_provider_download_started": "Letöltés Megkezdődött", "image_viewer_page_state_provider_download_success": "Letöltés Sikeres", - "image_viewer_page_state_provider_share_error": "Megosztási Hiba", - "invalid_date": "Invalid date", - "invalid_date_format": "Invalid date format", - "library": "Library", + "image_viewer_page_state_provider_share_error": "Megosztás Hiba", + "invalid_date": "Érvénytelen dátum", + "invalid_date_format": "Érvénytelen dátumformátum", + "library": "Képtár", "library_page_albums": "Albumok", "library_page_archive": "Archívum", "library_page_device_albums": "Albumok az Eszközön", "library_page_favorites": "Kedvencek", "library_page_new_album": "Új album", "library_page_sharing": "Megosztás", - "library_page_sort_asset_count": "Eszközök száma", + "library_page_sort_asset_count": "Elemek száma", "library_page_sort_created": "Létrehozás ideje", "library_page_sort_last_modified": "Utolsó módosítás ideje", "library_page_sort_most_oldest_photo": "Legrégebbi fotó", "library_page_sort_most_recent_photo": "Legújabb fotó", "library_page_sort_title": "Album címe", + "local_network": "Local network", + "local_network_sheet_info": "The app will connect to the server through this URL when using the specified Wi-Fi network", + "location_permission": "Location permission", + "location_permission_content": "In order to use the auto-switching feature, Immich needs precise location permission so it can read the current WiFi network's name", "location_picker_choose_on_map": "Válassz a térképen", "location_picker_latitude": "Szélességi kör", "location_picker_latitude_error": "Érvényes szélességi kört írj be", @@ -310,14 +333,14 @@ "login_form_email_hint": "email@cimed.hu", "login_form_endpoint_hint": "http(s)://szerver-címe:port/api", "login_form_endpoint_url": "Szerver címe", - "login_form_err_http": "Kérjük, adj meg egy http:// vagy https:// címet", + "login_form_err_http": "Kérjük, hogy egy http:// vagy https:// címet adj meg", "login_form_err_invalid_email": "Érvénytelen email cím", "login_form_err_invalid_url": "Érvénytelen cím", "login_form_err_leading_whitespace": "Az első karakter szóköz", "login_form_err_trailing_whitespace": "Az utolsó karakter szóköz", "login_form_failed_get_oauth_server_config": "Nem sikerült az OAuth bejelentkezés. Ellenőrizd a szerver címét.", "login_form_failed_get_oauth_server_disable": "OAuth bejelentkezés nem elérhető ezen a szerveren", - "login_form_failed_login": "Hiba bejelentkezés közben, ellenőrizd a címet, email-t és a jelszót", + "login_form_failed_login": "Hiba a bejelentkezés közben, ellenőrizd a szerver címét, az emailt és a jelszót", "login_form_handshake_exception": "SSL Kézfogási Hiba törént. Engedélyezd az önaláírt tanúsítvényokat a beállításokban, hogy ha önaláírt tanúsítványt használsz.", "login_form_label_email": "Email", "login_form_label_password": "Jelszó", @@ -339,7 +362,7 @@ "map_no_assets_in_bounds": "Nincsenek fotók a környéken", "map_no_location_permission_content": "A helymeghatározást engedélyezni kell a jelenlegi helyednél lévő elemek megjelenítéséhez. Szeretnéd most engedélyezni?", "map_no_location_permission_title": "Helymeghatározás letiltva", - "map_settings_dark_mode": "Sötét mód", + "map_settings_dark_mode": "Sötét téma", "map_settings_date_range_option_all": "Összes", "map_settings_date_range_option_day": "Elmúlt 24 óra", "map_settings_date_range_option_days": "Elmúlt {} nap", @@ -353,56 +376,59 @@ "map_settings_only_relative_range": "Dátum intervallum", "map_settings_only_show_favorites": "Csak Kedvencek Mutatása", "map_settings_theme_settings": "Térkép Témája", - "map_zoom_to_see_photos": "Kicsinyíts, hogy láss fényképeket", + "map_zoom_to_see_photos": "Kicsinyítsd, hogy láss fényképeket", "memories_all_caught_up": "Naprakész vagy", "memories_check_back_tomorrow": "Nézz vissza holnap újabb emlékekért", "memories_start_over": "Újrakezdés", "memories_swipe_to_close": "Bezáráshoz söpörd ki felfelé", - "memories_year_ago": "A year ago", - "memories_years_ago": "{} years ago", + "memories_year_ago": "Egy éve", + "memories_years_ago": "{} éve", "monthly_title_text_date_format": "y MMMM", - "motion_photos_page_title": "Mozgó Fotók", + "motion_photos_page_title": "Mozgóképek", "multiselect_grid_edit_date_time_err_read_only": "Csak-olvasható elem(ek) dátuma nem módosítható, ezért kihagyjuk", - "multiselect_grid_edit_gps_err_read_only": "Csak-olvasható elem(ek) helyszíne nem módosítható, ezért kihagyjuk", - "my_albums": "My albums", + "multiselect_grid_edit_gps_err_read_only": "Csak-olvasható elem(ek) helye nem módosítható, ezért kihagyjuk", + "my_albums": "Saját albumaim", + "networking_settings": "Networking", + "networking_subtitle": "Manage the server endpoint settings", "no_assets_to_show": "Nincs megjeleníthető elem", - "no_name": "No name", + "no_name": "Névtelen", "notification_permission_dialog_cancel": "Mégsem", "notification_permission_dialog_content": "Az értesítések bekapcsolásához a Beállítások menüben válaszd ki az Engedélyezés-t.", "notification_permission_dialog_settings": "Beállítások", - "notification_permission_list_tile_content": "Értesítések engedélyezése", + "notification_permission_list_tile_content": "Értesítések engedélyezése.", "notification_permission_list_tile_enable_button": "Értesítések Bekapcsolása", "notification_permission_list_tile_title": "Engedély az Értesítésekhez", - "on_this_device": "On this device", + "on_this_device": "Ezen az eszközön", "partner_list_user_photos": "{user} fényképei", "partner_list_view_all": "Összes mutatása", "partner_page_add_partner": "Partner hozzáadása", "partner_page_empty_message": "Még senkivel nem osztottad meg a fényképeidet.", - "partner_page_no_more_users": "Nincs hozzáadható felhasználó", - "partner_page_partner_add_failed": "Nem sikerült hozzáadni a felhasználót", + "partner_page_no_more_users": "Nincs több hozzáadható felhasználó", + "partner_page_partner_add_failed": "Partner hozzáadása sikertelen", "partner_page_select_partner": "Partner kiválasztása", "partner_page_shared_to_title": "Megosztva: ", "partner_page_stop_sharing_content": "{} nem fog többé hozzáférni a fotóidhoz.", "partner_page_stop_sharing_title": "Fotók megosztásának megszűntetése?", "partner_page_title": "Partner", - "partners": "Partners", - "people": "People", + "partners": "Partnerek", + "people": "Emberek", "permission_onboarding_back": "Vissza", "permission_onboarding_continue_anyway": "Folytatás mindenképp", - "permission_onboarding_get_started": "Kezdjük el", + "permission_onboarding_get_started": "Vágjunk bele", "permission_onboarding_go_to_settings": "Beállítások megnyitása", - "permission_onboarding_grant_permission": "Engedélyezés", + "permission_onboarding_grant_permission": "Engedély meadása", "permission_onboarding_log_out": "Kijelentkezés", "permission_onboarding_permission_denied": "Hozzáférés megtagadva. Az Immich használatához engedélyezni kell a fotó és videó hozzáférést a Beállításokban.", "permission_onboarding_permission_granted": "Hozzáférés engedélyezve! Minden készen áll.", "permission_onboarding_permission_limited": "Korlátozott hozzáférés. Ha szeretnéd, hogy az Immich a teljes galéria gyűjteményedet mentse és kezelje, akkor a Beállításokban engedélyezd a fotó és videó jogosultságokat.", - "permission_onboarding_request": "Engedélyezni kell, hogy az Immich hozzáférjen a képekhez és videókhoz", - "places": "Places", + "permission_onboarding_request": "Engedélyezni kell, hogy az Immich hozzáférjen a képeidhez és videóidhoz", + "places": "Helyek", + "preferences_settings_subtitle": "Manage the app's preferences", "preferences_settings_title": "Beállítások", "profile_drawer_app_logs": "Naplók", "profile_drawer_client_out_of_date_major": "A mobilalkalmazás elavult. Kérjük, frissítsd a legfrisebb főverzióra.", "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": "Kliens és a szerver is naprakész", + "profile_drawer_client_server_up_to_date": "A Kliens és a Szerver is naprakész", "profile_drawer_documentation": "Dokumentáció", "profile_drawer_github": "GitHub", "profile_drawer_server_out_of_date_major": "A szerver elavult. Kérjük, frissítsd a legfrisebb főverzióra.", @@ -410,42 +436,43 @@ "profile_drawer_settings": "Beállítások", "profile_drawer_sign_out": "Kijelentkezés", "profile_drawer_trash": "Lomtár", - "recently_added": "Recently added", + "recently_added": "Nemrég hozzáadott", "recently_added_page_title": "Nemrég Hozzáadott", - "save_to_gallery": "Save to gallery", + "save": "Save", + "save_to_gallery": "Mentés a galériába", "scaffold_body_error_occurred": "Hiba történt", - "search_albums": "Search albums", + "search_albums": "Albumok keresése", "search_bar_hint": "Fotók keresése", "search_filter_apply": "Szűrő alkalmazása", - "search_filter_camera": "Camera", + "search_filter_camera": "Kamera", "search_filter_camera_make": "Gyártó", "search_filter_camera_model": "Modell", - "search_filter_camera_title": "Select camera type", - "search_filter_date": "Date", - "search_filter_date_interval": "{start} to {end}", - "search_filter_date_title": "Select a date range", + "search_filter_camera_title": "Válaszd ki a kamera típusát", + "search_filter_date": "Dátum", + "search_filter_date_interval": "{start} - {end}", + "search_filter_date_title": "Válassz dátum intervallumot", "search_filter_display_option_archive": "Archivált", "search_filter_display_option_favorite": "Kedvenc", "search_filter_display_option_not_in_album": "Nincs albumban", - "search_filter_display_options": "Display Options", - "search_filter_display_options_title": "Display options", - "search_filter_location": "Location", - "search_filter_location_city": "Város", + "search_filter_display_options": "Megjelenítési Beállítások", + "search_filter_display_options_title": "Megjelenítési beállítások", + "search_filter_location": "Hely", + "search_filter_location_city": "Település", "search_filter_location_country": "Ország", - "search_filter_location_state": "Állam", - "search_filter_location_title": "Select location", - "search_filter_media_type": "Media Type", + "search_filter_location_state": "Megye/Állam", + "search_filter_location_title": "Válassz helyet", + "search_filter_media_type": "Média Típus", "search_filter_media_type_all": "Összes", "search_filter_media_type_image": "Kép", - "search_filter_media_type_title": "Select media type", + "search_filter_media_type_title": "Válassz média típust", "search_filter_media_type_video": "Videó", - "search_filter_people": "People", - "search_filter_people_title": "Select people", + "search_filter_people": "Emberek", + "search_filter_people_title": "Válassz embereket", "search_page_categories": "Kategóriák", "search_page_favorites": "Kedvencek", - "search_page_motion_photos": "Mozgó Fotók", + "search_page_motion_photos": "Mozgóképek", "search_page_no_objects": "Nincs Információ a Tárgyakról", - "search_page_no_places": "Nincs Információ a Helyszínekről", + "search_page_no_places": "Nincs Információ a Helyekről", "search_page_people": "Emberek", "search_page_person_add_name_dialog_cancel": "Mégsem", "search_page_person_add_name_dialog_hint": "Név", @@ -457,18 +484,20 @@ "search_page_places": "Helyek", "search_page_recently_added": "Nemrég hozzáadott", "search_page_screenshots": "Képernyőképek", + "search_page_search_photos_videos": "Search for your photos and videos", "search_page_selfies": "Szelfik", "search_page_things": "Dolgok", "search_page_videos": "Videók", "search_page_view_all_button": "Összes mutatása", - "search_page_your_activity": "Tevékenységek", - "search_page_your_map": "Térkép", - "search_result_page_new_search_hint": "Új keresés", - "search_suggestion_list_smart_search_hint_1": "Az intelligens keresés alapértelmezetten be van kapcsolva, metaadatokat így kereshetsz", + "search_page_your_activity": "Tevékenységeid", + "search_page_your_map": "Térképed", + "search_result_page_new_search_hint": "Új Keresés", + "search_suggestion_list_smart_search_hint_1": "Az intelligens keresés alapértelmezetten be van kapcsolva, metaadatokat így kereshetsz:", "search_suggestion_list_smart_search_hint_2": "m:keresési-kifejezés", "select_additional_user_for_sharing_page_suggestions": "Javaslatok", - "select_user_for_sharing_page_err_album": "Nem sikerült létrehozni az albumot", + "select_user_for_sharing_page_err_album": "Az album létrehozása sikertelen", "select_user_for_sharing_page_share_suggestions": "Javaslatok", + "server_endpoint": "Server Endpoint", "server_info_box_app_version": "Alkalmazás Verzió", "server_info_box_latest_release": "Legfrissebb Verzió", "server_info_box_server_url": "Szerver Címe", @@ -480,6 +509,7 @@ "setting_image_viewer_preview_title": "Előnézet betöltése", "setting_image_viewer_title": "Képek", "setting_languages_apply": "Alkalmaz", + "setting_languages_subtitle": "Change the app's language", "setting_languages_title": "Nyelvek", "setting_notifications_notify_failures_grace_period": "Értesítés a háttérben történő mentés hibáiról: {}", "setting_notifications_notify_hours": "{} óra", @@ -507,7 +537,7 @@ "shared_album_activities_input_hint": "Szólj hozzá", "shared_album_activity_remove_content": "Törölni szeretnéd ezt a tevékenységet?", "shared_album_activity_remove_title": "Tevékenység Törlése", - "shared_album_activity_setting_subtitle": "Engedd, hogy mások reagáljanak", + "shared_album_activity_setting_subtitle": "Mások is reagálhatnak", "shared_album_activity_setting_title": "Hozzászólások és lájkok", "shared_album_section_people_action_error": "Hiba az albummal kapcsolatos kilépés/eltávolítás közben", "shared_album_section_people_action_leave": "Felhasználó eltávolítása az albumból", @@ -518,8 +548,8 @@ "shared_link_app_bar_title": "Megosztott Linkek", "shared_link_clipboard_copied_massage": "Vágólapra másolva", "shared_link_clipboard_text": "Link: {}\nJelszó: {}", - "shared_link_create_app_bar_title": "Megosztási link létrehozása", - "shared_link_create_error": "Hiba a megosztási link létrehozásakor", + "shared_link_create_app_bar_title": "Megosztott link létrehozása", + "shared_link_create_error": "Hiba a megosztott link létrehozásakor", "shared_link_create_info": "A linket használva bárki megnézheti a kiválasztott kép(ek)et", "shared_link_create_submit_button": "Link létrehozása", "shared_link_edit_allow_download": "Letöltés engedélyezése", @@ -539,11 +569,11 @@ "shared_link_edit_expire_after_option_never": "Soha", "shared_link_edit_expire_after_option_year": "{} év", "shared_link_edit_password": "Jelszó", - "shared_link_edit_password_hint": "Add meg a megosztási jelszót", + "shared_link_edit_password_hint": "Add meg a megosztáshoz tartozó jelszót", "shared_link_edit_show_meta": "Metaadatok mutatása", "shared_link_edit_submit_button": "Link frissítése", - "shared_link_empty": "Nincsenek megosztási linkek", - "shared_link_error_server_url_fetch": "A szerver címét nem sikerült betölteni", + "shared_link_empty": "Nincsenek megosztott linkek", + "shared_link_error_server_url_fetch": "A szerver címét nem lehet betölteni", "shared_link_expired": "Lejárt", "shared_link_expires_day": "{} nap múlva lejár", "shared_link_expires_days": "{} nap múlva lejár", @@ -558,53 +588,53 @@ "shared_link_info_chip_download": "Letöltés", "shared_link_info_chip_metadata": "EXIF", "shared_link_info_chip_upload": "Feltöltés", - "shared_link_manage_links": "Megosztási linkek kezelése", + "shared_link_manage_links": "Megosztott linkek kezelése", "shared_link_public_album": "Nyilvános album", - "shared_links": "Shared links", + "shared_links": "Megosztott linkek", "share_done": "Kész", - "shared_with_me": "Shared with me", + "shared_with_me": "Velem megosztva", "share_invite": "Meghívás az albumba", "sharing_page_album": "Megosztott albumok", - "sharing_page_description": "Megosztott albumok létrehozásával fényképeket és videókat oszthatsz meg a hálózatodban lévő emberekkel.", + "sharing_page_description": "Megosztott albumok létrehozásával fényképeket és videókat oszthatsz meg az ismerőseiddel.", "sharing_page_empty_list": "ÜRES LISTA", "sharing_silver_appbar_create_shared_album": "Új megosztott album", - "sharing_silver_appbar_shared_links": "Megosztási linkek", + "sharing_silver_appbar_shared_links": "Megosztott linkek", "sharing_silver_appbar_share_partner": "Megosztás partnerrel", - "sync": "Sync", - "sync_albums": "Sync albums", - "sync_albums_manual_subtitle": "Sync all uploaded videos and photos to the selected backup albums", - "sync_upload_album_setting_subtitle": "Create and upload your photos and videos to the selected albums on Immich", + "sync": "Szinkronizálás", + "sync_albums": "Albumok szinkronizálása", + "sync_albums_manual_subtitle": "Összes fotó és videó létrehozása és szinkronizálása a kiválasztott Immich albumokba", + "sync_upload_album_setting_subtitle": "Fotók és videók létrehozása és szinkronizálása a kiválasztott Immich albumba", "tab_controller_nav_library": "Képtár", "tab_controller_nav_photos": "Képek", "tab_controller_nav_search": "Keresés", "tab_controller_nav_sharing": "Megosztás", "theme_setting_asset_list_storage_indicator_title": "Tárhely ikon mutatása az elemeken", "theme_setting_asset_list_tiles_per_row_title": "Elemek száma soronként ({})", - "theme_setting_colorful_interface_subtitle": "Apply primary color to background surfaces.", - "theme_setting_colorful_interface_title": "Colorful interface", - "theme_setting_dark_mode_switch": "Sötét mód", + "theme_setting_colorful_interface_subtitle": "Alapértelmezett szín használata a háttérben lévő felületekhez", + "theme_setting_colorful_interface_title": "Színes felhasználói felület", + "theme_setting_dark_mode_switch": "Sötét téma", "theme_setting_image_viewer_quality_subtitle": "Részletes képmegjelenítő minőségének beállítása", "theme_setting_image_viewer_quality_title": "Képmegjelenítő minősége", - "theme_setting_primary_color_subtitle": "Pick a color for primary actions and accents.", - "theme_setting_primary_color_title": "Primary color", - "theme_setting_system_primary_color_title": "Use system color", + "theme_setting_primary_color_subtitle": "Válassz egy színt az alapértelmezett műveletekhez és kiemelésekhez", + "theme_setting_primary_color_title": "Alapértelmezett szín", + "theme_setting_system_primary_color_title": "Rendszerszínek használata", "theme_setting_system_theme_switch": "Automatikus (követi a rendszer témáját)", "theme_setting_theme_subtitle": "Alkalmazás témájának választása", "theme_setting_theme_title": "Téma", "theme_setting_three_stage_loading_subtitle": "A háromlépcsős betöltés javíthatja a betöltési teljesítményt, de jelentősen növeli a hálózati forgalmat", "theme_setting_three_stage_loading_title": "Háromlépcsős betöltés engedélyezése", "translated_text_options": "Beállítások", - "trash": "Trash", - "trash_emptied": "Emptied trash", + "trash": "Lomtár", + "trash_emptied": "Lomtár kiürítve", "trash_page_delete": "Töröl", "trash_page_delete_all": "Mindet Töröl", - "trash_page_empty_trash_btn": "Lomtár Ürítése", + "trash_page_empty_trash_btn": "Lomtár ürítése", "trash_page_empty_trash_dialog_content": "Ki szeretnéd üríteni a lomtárban lévő elemeket? Ezeket véglegesen eltávolítjuk az Immich-ből", "trash_page_empty_trash_dialog_ok": "Ok", "trash_page_info": "A Lomátrba helyezett elemek {} nap után véglegesen törlődnek", - "trash_page_no_assets": "Nincsen semmi a Lomtárban", + "trash_page_no_assets": "A Lomtár üres", "trash_page_restore": "Visszaállít", - "trash_page_restore_all": "Mindet Visszaállítja", + "trash_page_restore_all": "Mindet Visszaállít", "trash_page_select_assets_btn": "Elemek kiválasztása", "trash_page_select_btn": "Kiválaszt", "trash_page_title": "Lomtár ({})", @@ -612,14 +642,18 @@ "upload_dialog_info": "Szeretnél mentést készíteni a kiválasztott elem(ek)ről a szerverre?", "upload_dialog_ok": "Feltöltés", "upload_dialog_title": "Elem Feltöltése", + "use_current_connection": "use current connection", + "validate_endpoint_error": "Please enter a valid URL", "version_announcement_overlay_ack": "Megértettem", - "version_announcement_overlay_release_notes": "a változtatások listáját elolvasd", - "version_announcement_overlay_text_1": "Szia, egy új verzió érhető el", - "version_announcement_overlay_text_2": "kérlek szánj időt arra, hogy ", - "version_announcement_overlay_text_3": "és gyöződj meg róla, hogy a docker-compose és .env beállításai naprakészek és pontosak, különösen akkor, ha watchtower-t vagy bármi olyan megoldást használsz, ami automatikusan frissíti a szervert.", - "version_announcement_overlay_title": "Új Szerververzió Érhető El \uD83C\uDF89", - "videos": "Videos", + "version_announcement_overlay_release_notes": "kiadási megjegyzések áttekintésére", + "version_announcement_overlay_text_1": "Szia barátom, ennek az alkalmazásnak van egy új verziója: ", + "version_announcement_overlay_text_2": "Kérjük, szánj időt a", + "version_announcement_overlay_text_3": ", és győződj meg róla, hogy a docker-compose.yml és az .env beállításaid naprakészek, hogy elkerüld a hibás konfigurációkat, különösen, ha a WatchTower-t vagy bármilyen automatikus frissítési megoldást használsz.", + "version_announcement_overlay_title": "Elérhető Új Szerververzió \uD83C\uDF89", + "videos": "Videók", "viewer_remove_from_stack": "Eltávolít a Csoportból", "viewer_stack_use_as_main_asset": "Fő Elemnek Beállít", - "viewer_unstack": "Csoport Megszűntetése" + "viewer_unstack": "Csoport Megszűntetése", + "wifi_name": "WiFi Name", + "your_wifi_name": "Your WiFi name" } \ No newline at end of file diff --git a/mobile/assets/i18n/it-IT.json b/mobile/assets/i18n/it-IT.json index 3d5c2805f0820..4be66e3b03041 100644 --- a/mobile/assets/i18n/it-IT.json +++ b/mobile/assets/i18n/it-IT.json @@ -7,6 +7,7 @@ "action_common_select": "Select", "action_common_update": "Aggiorna", "add_a_name": "Add a name", + "add_endpoint": "Add endpoint", "add_to_album_bottom_sheet_added": "Aggiunto in {album}", "add_to_album_bottom_sheet_already_exists": "Già presente in {album}", "advanced_settings_log_level_title": "Livello log: {}", @@ -65,7 +66,12 @@ "assets_restored_successfully": "{} asset(s) restored successfully", "assets_trashed": "{} asset(s) trashed", "assets_trashed_from_server": "{} asset(s) trashed from the Immich server", + "asset_viewer_settings_subtitle": "Manage your gallery viewer settings", "asset_viewer_settings_title": "Visualizzazione risorse", + "automatic_endpoint_switching_subtitle": "Connect locally over designated Wi-Fi when available and use alternative connections elsewhere", + "automatic_endpoint_switching_title": "Automatic URL switching", + "background_location_permission": "Background location permission", + "background_location_permission_content": "In order to switch networks when running in the background, Immich must *always* have precise location access so the app can read the Wi-Fi network's name", "backup_album_selection_page_albums_device": "Album sul dispositivo ({})", "backup_album_selection_page_albums_tap": "Tap per includere, doppio tap per escludere.", "backup_album_selection_page_assets_scatter": "Visto che le risorse possono trovarsi in più album, questi possono essere inclusi o esclusi dal backup.", @@ -131,6 +137,7 @@ "backup_manual_success": "Successo", "backup_manual_title": "Stato del caricamento", "backup_options_page_title": "Opzioni di Backup", + "backup_setting_subtitle": "Manage background and foreground upload settings", "cache_settings_album_thumbnails": "Anteprime pagine librerie ({} risorse)", "cache_settings_clear_cache_button": "Pulisci cache", "cache_settings_clear_cache_button_title": "Pulisce la cache dell'app. Questo impatterà significativamente le prestazioni dell''app fino a quando la cache non sarà rigenerata.", @@ -149,11 +156,16 @@ "cache_settings_tile_subtitle": "Controlla il comportamento dello storage locale", "cache_settings_tile_title": "Archiviazione locale", "cache_settings_title": "Impostazioni della Cache", + "cancel": "Cancel", + "change_display_order": "Change display order", "change_password_form_confirm_password": "Conferma Password", "change_password_form_description": "Ciao {name},\n\nQuesto è la prima volta che accedi al sistema oppure è stato fatto una richiesta di cambiare la password. Per favore inserisca la nuova password qui sotto", "change_password_form_new_password": "Nuova Password", "change_password_form_password_mismatch": "Le password non coincidono", "change_password_form_reenter_new_password": "Inserisci ancora la nuova password ", + "check_corrupt_asset_backup": "Check for corrupt asset backups", + "check_corrupt_asset_backup_button": "Perform check", + "check_corrupt_asset_backup_description": "Run this check only over Wi-Fi and once all assets have been backed-up. The procedure might take a few minutes.", "client_cert_dialog_msg_confirm": "OK", "client_cert_enter_password": "Enter Password", "client_cert_import": "Import", @@ -199,6 +211,7 @@ "crop": "Crop", "curated_location_page_title": "Location", "curated_object_page_title": "Oggetti", + "current_server_address": "Current server address", "daily_title_text_date": "E, dd MMM", "daily_title_text_date_year": "E, dd MMM, yyyy", "date_format": "E, d LLL, y • hh:mm", @@ -235,6 +248,8 @@ "edit_date_time_dialog_timezone": "Fuso orario", "edit_image_title": "Edit", "edit_location_dialog_title": "Posizione", + "enter_wifi_name": "Enter WiFi name", + "error_change_sort_album": "Failed to change album sort order", "error_saving_image": "Error: {}", "exif_bottom_sheet_description": "Aggiungi una descrizione...", "exif_bottom_sheet_details": "DETTAGLI", @@ -246,11 +261,15 @@ "experimental_settings_new_asset_list_title": "Attiva griglia foto sperimentale", "experimental_settings_subtitle": "Usalo a tuo rischio!", "experimental_settings_title": "Sperimentale", + "external_network": "External network", + "external_network_sheet_info": "When not on the preferred WiFi network, the app will connect to the server through the first of the below URLs it can reach, starting from top to bottom", "favorites": "Favorites", "favorites_page_no_favorites": "Nessun preferito", "favorites_page_title": "Preferiti", "filename_search": "File name or extension", "filter": "Filter", + "get_wifiname_error": "Could not get Wi-Fi name. Make sure you have granted the necessary permissions and are connected to a Wi-Fi network", + "grant_permission": "Grant permission", "haptic_feedback_switch": "Abilita feedback aptico", "haptic_feedback_title": "Feedback aptico", "header_settings_add_header_tip": "Add Header", @@ -296,6 +315,10 @@ "library_page_sort_most_oldest_photo": "Foto più vecchia", "library_page_sort_most_recent_photo": "Più recente", "library_page_sort_title": "Titolo album", + "local_network": "Local network", + "local_network_sheet_info": "The app will connect to the server through this URL when using the specified Wi-Fi network", + "location_permission": "Location permission", + "location_permission_content": "In order to use the auto-switching feature, Immich needs precise location permission so it can read the current WiFi network's name", "location_picker_choose_on_map": "Scegli una mappa", "location_picker_latitude": "Latitudine", "location_picker_latitude_error": "Inserisci una latitudine valida", @@ -365,6 +388,8 @@ "multiselect_grid_edit_date_time_err_read_only": "Non puoi modificare la data di risorse in sola lettura, azione ignorata", "multiselect_grid_edit_gps_err_read_only": "Non puoi modificare la posizione di risorse in sola lettura, azione ignorata", "my_albums": "My albums", + "networking_settings": "Networking", + "networking_subtitle": "Manage the server endpoint settings", "no_assets_to_show": "Nessuna risorsa da mostrare", "no_name": "No name", "notification_permission_dialog_cancel": "Annulla", @@ -398,6 +423,7 @@ "permission_onboarding_permission_limited": "Permessi limitati. Per consentire a Immich di gestire e fare i backup di tutta la galleria, concedi i permessi Foto e Video dalle Impostazioni.", "permission_onboarding_request": "Immich richiede i permessi per vedere le tue foto e video", "places": "Places", + "preferences_settings_subtitle": "Manage the app's preferences", "preferences_settings_title": "Preferenze", "profile_drawer_app_logs": "Logs", "profile_drawer_client_out_of_date_major": "L'applicazione non è aggiornata. Per favore aggiorna all'ultima versione principale.", @@ -412,6 +438,7 @@ "profile_drawer_trash": "Cestino", "recently_added": "Recently added", "recently_added_page_title": "Aggiunti di recente", + "save": "Save", "save_to_gallery": "Save to gallery", "scaffold_body_error_occurred": "Si è verificato un errore.", "search_albums": "Search albums", @@ -457,6 +484,7 @@ "search_page_places": "Luoghi", "search_page_recently_added": "Aggiunte di recente", "search_page_screenshots": "Screenshot", + "search_page_search_photos_videos": "Search for your photos and videos", "search_page_selfies": "Selfie", "search_page_things": "Oggetti", "search_page_videos": "Video", @@ -469,6 +497,7 @@ "select_additional_user_for_sharing_page_suggestions": "Suggerimenti ", "select_user_for_sharing_page_err_album": "Impossibile nel creare l'album ", "select_user_for_sharing_page_share_suggestions": "Suggerimenti", + "server_endpoint": "Server Endpoint", "server_info_box_app_version": "Versione App", "server_info_box_latest_release": "Ultima Versione", "server_info_box_server_url": "Server URL", @@ -480,6 +509,7 @@ "setting_image_viewer_preview_title": "Carica immagine di anteprima", "setting_image_viewer_title": "Images", "setting_languages_apply": "Applica", + "setting_languages_subtitle": "Change the app's language", "setting_languages_title": "Lingue", "setting_notifications_notify_failures_grace_period": "Notifica caricamenti falliti in background: {}", "setting_notifications_notify_hours": "{} ore", @@ -612,6 +642,8 @@ "upload_dialog_info": "Vuoi fare il backup sul server delle risorse selezionate?", "upload_dialog_ok": "Carica", "upload_dialog_title": "Carica file", + "use_current_connection": "use current connection", + "validate_endpoint_error": "Please enter a valid URL", "version_announcement_overlay_ack": "Presa visione", "version_announcement_overlay_release_notes": "note di rilascio", "version_announcement_overlay_text_1": "Ciao, c'è una nuova versione di", @@ -621,5 +653,7 @@ "videos": "Videos", "viewer_remove_from_stack": "Rimuovi dalla pila", "viewer_stack_use_as_main_asset": "Usa come risorsa principale", - "viewer_unstack": "Rimuovi dal gruppo" + "viewer_unstack": "Rimuovi dal gruppo", + "wifi_name": "WiFi Name", + "your_wifi_name": "Your WiFi name" } \ No newline at end of file diff --git a/mobile/assets/i18n/ja-JP.json b/mobile/assets/i18n/ja-JP.json index e5fed5705d69a..aa034f069961d 100644 --- a/mobile/assets/i18n/ja-JP.json +++ b/mobile/assets/i18n/ja-JP.json @@ -6,7 +6,8 @@ "action_common_save": "保存", "action_common_select": "選択", "action_common_update": "更新", - "add_a_name": "Add a name", + "add_a_name": "名前を追加", + "add_endpoint": "エンドポイントを追加してください", "add_to_album_bottom_sheet_added": "{album}に追加", "add_to_album_bottom_sheet_already_exists": "{album}に追加済み", "advanced_settings_log_level_title": "ログレベル: {}", @@ -22,7 +23,7 @@ "advanced_settings_troubleshooting_title": "トラブルシューティング", "album_info_card_backup_album_excluded": "除外中", "album_info_card_backup_album_included": "選択中", - "albums": "Albums", + "albums": "アルバム", "album_thumbnail_card_item": "1枚", "album_thumbnail_card_items": "{}枚", "album_thumbnail_card_shared": "共有済み", @@ -38,13 +39,13 @@ "album_viewer_appbar_share_remove": "アルバムから削除", "album_viewer_appbar_share_to": "次の方々と共有します", "album_viewer_page_share_add_users": "ユーザーを追加", - "all": "All", + "all": "全て", "all_people_page_title": "人物", "all_videos_page_title": "ビデオ", "app_bar_signout_dialog_content": " サインアウトしますか?", "app_bar_signout_dialog_ok": "はい", "app_bar_signout_dialog_title": " サインアウト", - "archived": "Archived", + "archived": "アーカイブ済み", "archive_page_no_archived_assets": "アーカイブ済みの写真またはビデオがありません", "archive_page_title": "アーカイブ({})", "asset_action_delete_err_read_only": "読み取り専用の項目は削除できません。スキップします", @@ -65,7 +66,12 @@ "assets_restored_successfully": "{}項目を復元しました", "assets_trashed": "{}項目をゴミ箱に移動しました", "assets_trashed_from_server": "サーバー上の{}項目をゴミ箱に移動しました", + "asset_viewer_settings_subtitle": "ギャラリービューアーに関する設定", "asset_viewer_settings_title": "アセットビューアー", + "automatic_endpoint_switching_subtitle": "指定されたWi-Fiに接続時のみローカル接続を行い、他のネットワーク下では通常通りの接続を行います", + "automatic_endpoint_switching_title": "自動URL切り替え", + "background_location_permission": "バックグラウンド位置情報アクセス", + "background_location_permission_content": "正常にWi-Fiの名前(SSID)を獲得するにはアプリが常に詳細な位置情報にアクセスできる必要があります", "backup_album_selection_page_albums_device": "端末上のアルバム数: {} ", "backup_album_selection_page_albums_tap": "タップで選択、ダブルタップで除外", "backup_album_selection_page_assets_scatter": "アルバムを選択・除外してバックアップする写真を選ぶ (同じ写真が複数のアルバムに登録されていることがあるため)", @@ -131,6 +137,7 @@ "backup_manual_success": "成功", "backup_manual_title": "アップロード状況", "backup_options_page_title": "バックアップオプション", + "backup_setting_subtitle": "アップロードに関する設定", "cache_settings_album_thumbnails": "ライブラリのサムネイル ({}枚)", "cache_settings_clear_cache_button": "キャッシュをクリア", "cache_settings_clear_cache_button_title": "キャッシュを削除 (キャッシュが再生成されるまで、アプリのパフォーマンスが著しく低下します)", @@ -149,11 +156,16 @@ "cache_settings_tile_subtitle": "ローカルストレージの挙動を確認する", "cache_settings_tile_title": "ローカルストレージ", "cache_settings_title": "キャッシュの設定", + "cancel": "キャンセル", + "change_display_order": "Change display order", "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": "再度パスワードを入力してください", + "check_corrupt_asset_backup": "破損されている項目を探す", + "check_corrupt_asset_backup_button": "チェックを行う", + "check_corrupt_asset_backup_description": "写真や動画などが全てアップロードし終えてからWi-Fiに接続時のみチェックを行なってください。作業が完了するには数分かかる場合があります", "client_cert_dialog_msg_confirm": "了解", "client_cert_enter_password": "パスワードを入力", "client_cert_import": "インポート", @@ -189,9 +201,9 @@ "control_bottom_app_bar_unarchive": "アーカイブを解除", "control_bottom_app_bar_unfavorite": "お気に入りから外す", "control_bottom_app_bar_upload": "アップロード", - "create_album": "Create album", + "create_album": "アルバム作成", "create_album_page_untitled": "タイトルなし", - "create_new": "CREATE NEW", + "create_new": "新規作成", "create_shared_album_page_create": "作成", "create_shared_album_page_share": "共有", "create_shared_album_page_share_add_assets": "写真を追加", @@ -199,6 +211,7 @@ "crop": "クロップ", "curated_location_page_title": "撮影場所", "curated_object_page_title": "被写体", + "current_server_address": "現在のサーバーURL", "daily_title_text_date": "MM DD, EE", "daily_title_text_date_year": "yyyy MM DD, EE", "date_format": "MM DD, EE • hh:mm", @@ -235,6 +248,8 @@ "edit_date_time_dialog_timezone": "タイムゾーン", "edit_image_title": "編集", "edit_location_dialog_title": "位置情報", + "enter_wifi_name": "Wi-Fiの名前(SSID)を入力", + "error_change_sort_album": "Failed to change album sort order", "error_saving_image": "エラー: {}", "exif_bottom_sheet_description": "説明を追加", "exif_bottom_sheet_details": "詳細", @@ -246,11 +261,15 @@ "experimental_settings_new_asset_list_title": "試験的なグリッドを有効化", "experimental_settings_subtitle": "試験的機能につき自己責任で!", "experimental_settings_title": "試験的機能", - "favorites": "Favorites", + "external_network": "外部のネットワーク", + "external_network_sheet_info": "指定されたWi-Fiに繋がっていない時アプリはサーバーへの接続を指定されたURLで行います。優先順位は上から下です", + "favorites": "お気に入り", "favorites_page_no_favorites": "お気に入り登録された写真またはビデオがありません", "favorites_page_title": "お気に入り", "filename_search": "ファイル名、又は拡張子", - "filter": "Filter", + "filter": "フィルター", + "get_wifiname_error": "Wi-Fiの名前(SSID)が入手できませんでした。Wi-Fiに繋がってるのと必要な権限を許可したか確認してください", + "grant_permission": "許可する", "haptic_feedback_switch": "ハプティックフィードバック", "haptic_feedback_title": "ハプティックフィードバックを有効にする", "header_settings_add_header_tip": "ヘッダを追加", @@ -274,8 +293,8 @@ "home_page_first_time_notice": "はじめてアプリを使う場合、タイムラインに写真を表示するためにアルバムを選択してください", "home_page_share_err_local": "ローカルのみの項目をリンクで共有はできません。スキップします", "home_page_upload_err_limit": "1回でアップロードできる写真の数は30枚です。スキップします", - "ignore_icloud_photos": "Ignore iCloud photos", - "ignore_icloud_photos_description": "Photos that are stored on iCloud will not be uploaded to the Immich server", + "ignore_icloud_photos": "iCloud上の写真をスキップ", + "ignore_icloud_photos_description": "iCloudに保存済みの項目をImmichサーバー上にアップロードしません", "image_saved_successfully": "画像が保存されました", "image_viewer_page_state_provider_download_error": "ダウンロード失敗", "image_viewer_page_state_provider_download_started": "ダウンロードが始まります", @@ -283,7 +302,7 @@ "image_viewer_page_state_provider_share_error": "共有エラー", "invalid_date": "日付が無効です", "invalid_date_format": "日付のフォーマットが無効です", - "library": "Library", + "library": "ライブラリ", "library_page_albums": "アルバム", "library_page_archive": "アーカイブ", "library_page_device_albums": "デバイス上のアルバム", @@ -296,6 +315,10 @@ "library_page_sort_most_oldest_photo": "一番古い項目", "library_page_sort_most_recent_photo": "最近の項目", "library_page_sort_title": "アルバム名", + "local_network": "ローカルネットワーク", + "local_network_sheet_info": "アプリは指定されたWi-Fiに繋がっている時サーバーへの接続を下記のURLで行います", + "location_permission": "位置情報権限", + "location_permission_content": "自動URL切り替えを使用するにはWi-Fiの名前(SSID)を取得する必要があり、正常に機能するにはアプリが常に詳細な位置情報にアクセスできる必要があります", "location_picker_choose_on_map": "マップを選択", "location_picker_latitude": "緯度", "location_picker_latitude_error": "有効な緯度を入力してください", @@ -364,7 +387,9 @@ "motion_photos_page_title": "モーションフォト", "multiselect_grid_edit_date_time_err_read_only": "読み取り専用の項目の日付を変更できません", "multiselect_grid_edit_gps_err_read_only": "読み取り専用の項目の位置情報を変更できません", - "my_albums": "My albums", + "my_albums": "自分のアルバム", + "networking_settings": "ネットワーク", + "networking_subtitle": "サーバーエンドポイントに関する設定", "no_assets_to_show": "表示する項目がありません", "no_name": "名前がありません", "notification_permission_dialog_cancel": "キャンセル", @@ -373,7 +398,7 @@ "notification_permission_list_tile_content": "通知の許可 をオンにしてください", "notification_permission_list_tile_enable_button": "通知をオンにする", "notification_permission_list_tile_title": "通知の許可", - "on_this_device": "On this device", + "on_this_device": "デバイス上の項目", "partner_list_user_photos": "{user}さんの写真", "partner_list_view_all": "すべて見る", "partner_page_add_partner": "パートナーを追加", @@ -385,8 +410,8 @@ "partner_page_stop_sharing_content": "{}は写真へアクセスできなくなります", "partner_page_stop_sharing_title": "写真の共有を無効化しますか?", "partner_page_title": "パートナー", - "partners": "Partners", - "people": "People", + "partners": "パートナー", + "people": "人物", "permission_onboarding_back": "戻る", "permission_onboarding_continue_anyway": "無視して続行", "permission_onboarding_get_started": "はじめる", @@ -397,7 +422,8 @@ "permission_onboarding_permission_granted": "写真へのアクセスが許可されました", "permission_onboarding_permission_limited": "写真へのアクセスが制限されています。Immichが写真のバックアップと管理を行うには、システム設定から写真と動画のアクセス権限を変更してください。", "permission_onboarding_request": "Immichは写真へのアクセス許可が必要です", - "places": "Places", + "places": "場所", + "preferences_settings_subtitle": "アプリに関する設定", "preferences_settings_title": "設定", "profile_drawer_app_logs": "ログ", "profile_drawer_client_out_of_date_major": "アプリが更新されてません。最新のバージョンに更新してください", @@ -410,11 +436,12 @@ "profile_drawer_settings": "設定", "profile_drawer_sign_out": "サインアウト", "profile_drawer_trash": "ゴミ箱", - "recently_added": "Recently added", + "recently_added": "最近追加された項目", "recently_added_page_title": "最近", + "save": "保存", "save_to_gallery": "ギャラリーに保存", "scaffold_body_error_occurred": "エラーが発生しました", - "search_albums": "Search albums", + "search_albums": "アルバムを探す", "search_bar_hint": "写真を検索", "search_filter_apply": "フィルターを適用する", "search_filter_camera": "カメラ", @@ -457,6 +484,7 @@ "search_page_places": "撮影地", "search_page_recently_added": "最近追加", "search_page_screenshots": "スクリーンショット", + "search_page_search_photos_videos": "Search for your photos and videos", "search_page_selfies": "自撮り", "search_page_things": "被写体", "search_page_videos": "ビデオ", @@ -469,6 +497,7 @@ "select_additional_user_for_sharing_page_suggestions": "ユーザーリスト", "select_user_for_sharing_page_err_album": "アルバム作成に失敗", "select_user_for_sharing_page_share_suggestions": "ユーザ一覧", + "server_endpoint": "サーバーエンドポイント", "server_info_box_app_version": "アプリのバージョン", "server_info_box_latest_release": "最新バージョン", "server_info_box_server_url": " サーバーのURL", @@ -480,6 +509,7 @@ "setting_image_viewer_preview_title": "プレビューを読み込む", "setting_image_viewer_title": "画像", "setting_languages_apply": "適用する", + "setting_languages_subtitle": "アプリの言語を変更する", "setting_languages_title": "言語", "setting_notifications_notify_failures_grace_period": "バックアップ失敗の通知: {}", "setting_notifications_notify_hours": "{}時間後", @@ -560,9 +590,9 @@ "shared_link_info_chip_upload": "アップロード", "shared_link_manage_links": "共有済みのリンクを管理", "shared_link_public_album": "公開アルバム", - "shared_links": "Shared links", + "shared_links": "共有済みリンク", "share_done": "完了", - "shared_with_me": "Shared with me", + "shared_with_me": "自分と共有中", "share_invite": "アルバムに招待", "sharing_page_album": "共有アルバム", "sharing_page_description": "共有アルバムを作成して同じネットワークにいる人たちに写真を共有", @@ -594,7 +624,7 @@ "theme_setting_three_stage_loading_subtitle": "三段階読み込みを有効にすると、パフォーマンスが改善する可能性がありますが、ネットワーク負荷が著しく増加します。", "theme_setting_three_stage_loading_title": "三段階読み込みをオンにする", "translated_text_options": "オプション", - "trash": "Trash", + "trash": "ゴミ箱", "trash_emptied": "ゴミ箱を空にしました", "trash_page_delete": "削除", "trash_page_delete_all": "すべて削除", @@ -612,14 +642,18 @@ "upload_dialog_info": "選択した項目のバックアップをしますか?", "upload_dialog_ok": "アップロード", "upload_dialog_title": "アップロード", + "use_current_connection": "現在の接続情報を使用", + "validate_endpoint_error": "有効なURLを入力してください", "version_announcement_overlay_ack": "了解", "version_announcement_overlay_release_notes": "更新情報", "version_announcement_overlay_text_1": "新しい", "version_announcement_overlay_text_2": "のバージョンが公開中です。", "version_announcement_overlay_text_3": "を確認してください。docker-composeや.envファイルが最新の状態に更新済みか、特にWatchTowerなどのツールを使ってDockerイメージを自動アップデートされてる方は確認してください。", "version_announcement_overlay_title": "サーバーの最新版が公開中\uD83C\uDF89", - "videos": "Videos", + "videos": "動画", "viewer_remove_from_stack": "スタックから外す", "viewer_stack_use_as_main_asset": "メインの画像として使用する", - "viewer_unstack": "スタックを解除" + "viewer_unstack": "スタックを解除", + "wifi_name": "Wi-Fiの名前(SSID)", + "your_wifi_name": "Wi-Fiの名前(SSID)" } \ No newline at end of file diff --git a/mobile/assets/i18n/ko-KR.json b/mobile/assets/i18n/ko-KR.json index 090925e724949..788368b131343 100644 --- a/mobile/assets/i18n/ko-KR.json +++ b/mobile/assets/i18n/ko-KR.json @@ -7,6 +7,7 @@ "action_common_select": "선택", "action_common_update": "업데이트", "add_a_name": "이름 추가", + "add_endpoint": "Add endpoint", "add_to_album_bottom_sheet_added": "{album}에 추가되었습니다.", "add_to_album_bottom_sheet_already_exists": "{album}에 이미 존재하는 항목입니다.", "advanced_settings_log_level_title": "로그 레벨: {}", @@ -30,10 +31,10 @@ "album_thumbnail_shared_by": "{}님이 공유함", "album_viewer_appbar_delete_confirm": "이 앨범을 삭제하시겠습니까?", "album_viewer_appbar_share_delete": "앨범 삭제", - "album_viewer_appbar_share_err_delete": "앨범을 삭제하지 못했습니다.", - "album_viewer_appbar_share_err_leave": "앨범에서 나가지 못했습니다.", + "album_viewer_appbar_share_err_delete": "앨범 삭제에 실패했습니다.", + "album_viewer_appbar_share_err_leave": "앨범 나가기에 실패했습니다.", "album_viewer_appbar_share_err_remove": "앨범에서 항목을 제거하지 못했습니다.", - "album_viewer_appbar_share_err_title": "앨범명을 변경하지 못했습니다.", + "album_viewer_appbar_share_err_title": "앨범명 변경에 실패했습니다.", "album_viewer_appbar_share_leave": "앨범 나가기", "album_viewer_appbar_share_remove": "앨범에서 제거", "album_viewer_appbar_share_to": "공유 대상", @@ -44,7 +45,7 @@ "app_bar_signout_dialog_content": "정말 로그아웃하시겠습니까?", "app_bar_signout_dialog_ok": "네", "app_bar_signout_dialog_title": "로그아웃", - "archived": "아카이브", + "archived": "보관함", "archive_page_no_archived_assets": "보관된 항목 없음", "archive_page_title": "보관함 ({})", "asset_action_delete_err_read_only": "읽기 전용 항목은 삭제할 수 없습니다. 건너뜁니다.", @@ -65,7 +66,12 @@ "assets_restored_successfully": "항목 {}개를 복원했습니다.", "assets_trashed": "휴지통으로 항목 {}개가 이동되었습니다.", "assets_trashed_from_server": "휴지통으로 Immich 항목 {}개가 이동되었습니다.", + "asset_viewer_settings_subtitle": "Manage your gallery viewer settings", "asset_viewer_settings_title": "보기 옵션", + "automatic_endpoint_switching_subtitle": "Connect locally over designated Wi-Fi when available and use alternative connections elsewhere", + "automatic_endpoint_switching_title": "Automatic URL switching", + "background_location_permission": "Background location permission", + "background_location_permission_content": "In order to switch networks when running in the background, Immich must *always* have precise location access so the app can read the Wi-Fi network's name", "backup_album_selection_page_albums_device": "기기의 앨범 ({})", "backup_album_selection_page_albums_tap": "한 번 눌러 선택, 두 번 눌러 제외하세요.", "backup_album_selection_page_assets_scatter": "각 항목은 여러 앨범에 포함될 수 있으며, 백업 진행 중에도 대상 앨범을 포함하거나 제외할 수 있습니다.", @@ -131,6 +137,7 @@ "backup_manual_success": "성공", "backup_manual_title": "업로드 상태", "backup_options_page_title": "백업 옵션", + "backup_setting_subtitle": "Manage background and foreground upload settings", "cache_settings_album_thumbnails": "라이브러리 섬네일 ({})", "cache_settings_clear_cache_button": "캐시 지우기", "cache_settings_clear_cache_button_title": "앱 캐시를 지웁니다. 이 작업은 캐시가 다시 생성될 때까지 앱 성능에 상당한 영향을 미칠 수 있습니다.", @@ -149,11 +156,16 @@ "cache_settings_tile_subtitle": "로컬 스토리지 동작 제어", "cache_settings_tile_title": "로컬 스토리지", "cache_settings_title": "캐시 설정", + "cancel": "Cancel", + "change_display_order": "Change display order", "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": "새 비밀번호 확인", + "check_corrupt_asset_backup": "Check for corrupt asset backups", + "check_corrupt_asset_backup_button": "Perform check", + "check_corrupt_asset_backup_description": "Run this check only over Wi-Fi and once all assets have been backed-up. The procedure might take a few minutes.", "client_cert_dialog_msg_confirm": "확인", "client_cert_enter_password": "비밀번호 입력", "client_cert_import": "가져오기", @@ -199,6 +211,7 @@ "crop": "자르기", "curated_location_page_title": "장소", "curated_object_page_title": "사물", + "current_server_address": "Current server address", "daily_title_text_date": "M월 d일 EEEE", "daily_title_text_date_year": "yyyy년 M월 d일 EEEE", "date_format": "yyyy년 M월 d일 EEEE • a h:mm", @@ -216,25 +229,27 @@ "delete_shared_link_dialog_title": "공유 링크 삭제", "description_input_hint_text": "설명 추가...", "description_input_submit_error": "설명을 변경하는 중 문제가 발생했습니다. 자세한 내용은 로그를 참조하세요.", - "download_canceled": "다운로드가 취소되었습니다", - "download_complete": "다은로드가 완료되었습니다", + "download_canceled": "다운로드가 취소되었습니다.", + "download_complete": "다은로드가 완료되었습니다.", "download_enqueue": "대기열에 다운로드", - "download_error": "다운로드 중 문제가 발생했습니다", - "download_failed": "다운로드에 실패하였습니다", + "download_error": "다운로드 중 문제가 발생했습니다.", + "download_failed": "다운로드에 실패하였습니다.", "download_filename": "파일: {}", - "download_finished": "다운로드가 완료되었습니다", + "download_finished": "다운로드가 완료되었습니다.", "downloading": "다운로드 중...", "downloading_media": "미디어 다운로드 중", "download_notfound": "다운로드할 수 없음", "download_paused": "다운로드 일시 중지됨", - "download_started": "다운로드가 시작되었습니다", - "download_sucess": "다운로드가 완료되었습니다", - "download_sucess_android": "미디어가 DCIM/Immich에 저장되었습니다", + "download_started": "다운로드가 시작되었습니다.", + "download_sucess": "다운로드가 완료되었습니다.", + "download_sucess_android": "미디어가 DCIM/Immich에 저장되었습니다.", "download_waiting_to_retry": "재시도 대기 중", "edit_date_time_dialog_date_time": "날짜 및 시간", "edit_date_time_dialog_timezone": "시간대", "edit_image_title": "편집", "edit_location_dialog_title": "위치", + "enter_wifi_name": "Enter WiFi name", + "error_change_sort_album": "Failed to change album sort order", "error_saving_image": "오류: {}", "exif_bottom_sheet_description": "설명 추가...", "exif_bottom_sheet_details": "상세 정보", @@ -246,11 +261,15 @@ "experimental_settings_new_asset_list_title": "새 사진 배열 사용 (실험적)", "experimental_settings_subtitle": "본인 책임 하에 사용하세요!", "experimental_settings_title": "실험적", + "external_network": "External network", + "external_network_sheet_info": "When not on the preferred WiFi network, the app will connect to the server through the first of the below URLs it can reach, starting from top to bottom", "favorites": "즐겨찾기", "favorites_page_no_favorites": "즐겨찾기된 항목 없음", "favorites_page_title": "즐겨찾기", "filename_search": "파일 이름 또는 확장자", "filter": "필터", + "get_wifiname_error": "Could not get Wi-Fi name. Make sure you have granted the necessary permissions and are connected to a Wi-Fi network", + "grant_permission": "Grant permission", "haptic_feedback_switch": "햅틱 피드백 활성화", "haptic_feedback_title": "햅틱 피드백", "header_settings_add_header_tip": "헤더 추가", @@ -276,7 +295,7 @@ "home_page_upload_err_limit": "한 번에 최대 30개의 항목만 업로드할 수 있습니다.", "ignore_icloud_photos": "iCloud 사진 제외", "ignore_icloud_photos_description": "iCloud에 저장된 사진은 Immich 서버에 업로드되지 않습니다.", - "image_saved_successfully": "이미지가 저장되었습니다", + "image_saved_successfully": "이미지가 저장되었습니다.", "image_viewer_page_state_provider_download_error": "다운로드 오류", "image_viewer_page_state_provider_download_started": "다운로드가 시작되었습니다.", "image_viewer_page_state_provider_download_success": "다운로드 완료", @@ -296,6 +315,10 @@ "library_page_sort_most_oldest_photo": "오래된 순", "library_page_sort_most_recent_photo": "최신순", "library_page_sort_title": "앨범 제목", + "local_network": "Local network", + "local_network_sheet_info": "The app will connect to the server through this URL when using the specified Wi-Fi network", + "location_permission": "Location permission", + "location_permission_content": "In order to use the auto-switching feature, Immich needs precise location permission so it can read the current WiFi network's name", "location_picker_choose_on_map": "지도에서 선택", "location_picker_latitude": "위도", "location_picker_latitude_error": "유효한 위도를 입력하세요.", @@ -313,8 +336,8 @@ "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_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, 이메일 및 비밀번호를 확인하세요.", @@ -365,6 +388,8 @@ "multiselect_grid_edit_date_time_err_read_only": "읽기 전용 항목의 날짜는 변경할 수 없습니다. 건너뜁니다.", "multiselect_grid_edit_gps_err_read_only": "읽기 전용 항목의 위치는 변경할 수 없습니다. 건너뜁니다.", "my_albums": "내 앨범", + "networking_settings": "Networking", + "networking_subtitle": "Manage the server endpoint settings", "no_assets_to_show": "표시할 항목 없음", "no_name": "이름 없음", "notification_permission_dialog_cancel": "취소", @@ -398,6 +423,7 @@ "permission_onboarding_permission_limited": "권한이 없습니다. Immich가 전체 갤러리 컬렉션을 백업하고 관리할 수 있도록 하려면 설정에서 사진 및 동영상 권한을 부여하세요.", "permission_onboarding_request": "사진 및 동영상 권한이 필요합니다.", "places": "장소", + "preferences_settings_subtitle": "Manage the app's preferences", "preferences_settings_title": "설정", "profile_drawer_app_logs": "로그", "profile_drawer_client_out_of_date_major": "모바일 앱이 최신 버전이 아닙니다. 최신 버전으로 업데이트하세요.", @@ -412,6 +438,7 @@ "profile_drawer_trash": "휴지통", "recently_added": "최근 추가", "recently_added_page_title": "최근 추가", + "save": "Save", "save_to_gallery": "갤러리에 저장", "scaffold_body_error_occurred": "문제가 발생했습니다.", "search_albums": "앨범 검색", @@ -457,6 +484,7 @@ "search_page_places": "장소", "search_page_recently_added": "최근 추가", "search_page_screenshots": "스크린샷", + "search_page_search_photos_videos": "Search for your photos and videos", "search_page_selfies": "셀피", "search_page_things": "사물", "search_page_videos": "동영상", @@ -469,6 +497,7 @@ "select_additional_user_for_sharing_page_suggestions": "추천", "select_user_for_sharing_page_err_album": "앨범을 생성하지 못했습니다.", "select_user_for_sharing_page_share_suggestions": "제안", + "server_endpoint": "Server Endpoint", "server_info_box_app_version": "앱 버전", "server_info_box_latest_release": "최신 버전", "server_info_box_server_url": "서버 URL", @@ -480,6 +509,7 @@ "setting_image_viewer_preview_title": "미리 보기 이미지 불러오기", "setting_image_viewer_title": "이미지", "setting_languages_apply": "적용", + "setting_languages_subtitle": "Change the app's language", "setting_languages_title": "언어", "setting_notifications_notify_failures_grace_period": "백그라운드 백업 실패 알림: {}", "setting_notifications_notify_hours": "{}시간 후", @@ -500,7 +530,7 @@ "setting_video_viewer_title": "동영상", "share_add": "추가", "share_add_photos": "사진 추가", - "share_add_title": "앨범명 추가", + "share_add_title": "제목 추가", "share_assets_selected": "{}개 항목 선택됨", "share_create_album": "앨범 생성", "shared_album_activities_input_disable": "댓글이 비활성화되었습니다", @@ -594,7 +624,7 @@ "theme_setting_three_stage_loading_subtitle": "이 기능은 앱의 로드 성능을 향상시킬 수 있지만 더 많은 데이터를 사용합니다.", "theme_setting_three_stage_loading_title": "3단계 로드 활성화", "translated_text_options": "옵션", - "trash": "쓰레기통", + "trash": "휴지통", "trash_emptied": "휴지통을 비웠습니다.", "trash_page_delete": "삭제", "trash_page_delete_all": "모두 삭제", @@ -612,6 +642,8 @@ "upload_dialog_info": "선택한 항목을 서버에 백업하시겠습니까?", "upload_dialog_ok": "업로드", "upload_dialog_title": "항목 업로드", + "use_current_connection": "use current connection", + "validate_endpoint_error": "Please enter a valid URL", "version_announcement_overlay_ack": "확인", "version_announcement_overlay_release_notes": "릴리스 노트", "version_announcement_overlay_text_1": "안녕하세요,", @@ -621,5 +653,7 @@ "videos": "동영상", "viewer_remove_from_stack": "스택에서 제거", "viewer_stack_use_as_main_asset": "대표 사진으로 설정", - "viewer_unstack": "스택 해제" + "viewer_unstack": "스택 해제", + "wifi_name": "WiFi Name", + "your_wifi_name": "Your WiFi name" } \ No newline at end of file diff --git a/mobile/assets/i18n/lt-LT.json b/mobile/assets/i18n/lt-LT.json index 0075f65de0557..a7f31f8440f7e 100644 --- a/mobile/assets/i18n/lt-LT.json +++ b/mobile/assets/i18n/lt-LT.json @@ -7,6 +7,7 @@ "action_common_select": "Select", "action_common_update": "Update", "add_a_name": "Add a name", + "add_endpoint": "Add endpoint", "add_to_album_bottom_sheet_added": "Added to {album}", "add_to_album_bottom_sheet_already_exists": "Already in {album}", "advanced_settings_log_level_title": "Log level: {}", @@ -65,7 +66,12 @@ "assets_restored_successfully": "{} asset(s) restored successfully", "assets_trashed": "{} asset(s) trashed", "assets_trashed_from_server": "{} asset(s) trashed from the Immich server", + "asset_viewer_settings_subtitle": "Manage your gallery viewer settings", "asset_viewer_settings_title": "Asset Viewer", + "automatic_endpoint_switching_subtitle": "Connect locally over designated Wi-Fi when available and use alternative connections elsewhere", + "automatic_endpoint_switching_title": "Automatic URL switching", + "background_location_permission": "Background location permission", + "background_location_permission_content": "In order to switch networks when running in the background, Immich must *always* have precise location access so the app can read the Wi-Fi network's name", "backup_album_selection_page_albums_device": "Albums on device ({})", "backup_album_selection_page_albums_tap": "Tap to include, double tap to exclude", "backup_album_selection_page_assets_scatter": "Assets can scatter across multiple albums. Thus, albums can be included or excluded during the backup process.", @@ -131,6 +137,7 @@ "backup_manual_success": "Success", "backup_manual_title": "Upload status", "backup_options_page_title": "Backup options", + "backup_setting_subtitle": "Manage background and foreground upload settings", "cache_settings_album_thumbnails": "Library page thumbnails ({} assets)", "cache_settings_clear_cache_button": "Clear cache", "cache_settings_clear_cache_button_title": "Clears the app's cache. This will significantly impact the app's performance until the cache has rebuilt.", @@ -149,11 +156,16 @@ "cache_settings_tile_subtitle": "Control the local storage behaviour", "cache_settings_tile_title": "Local Storage", "cache_settings_title": "Caching Settings", + "cancel": "Cancel", + "change_display_order": "Change display order", "change_password_form_confirm_password": "Confirm Password", "change_password_form_description": "Hi {name},\n\nThis is either the first time you are signing into the system or a request has been made to change your password. Please enter the new password below.", "change_password_form_new_password": "New Password", "change_password_form_password_mismatch": "Passwords do not match", "change_password_form_reenter_new_password": "Re-enter New Password", + "check_corrupt_asset_backup": "Check for corrupt asset backups", + "check_corrupt_asset_backup_button": "Perform check", + "check_corrupt_asset_backup_description": "Run this check only over Wi-Fi and once all assets have been backed-up. The procedure might take a few minutes.", "client_cert_dialog_msg_confirm": "OK", "client_cert_enter_password": "Enter Password", "client_cert_import": "Import", @@ -199,6 +211,7 @@ "crop": "Crop", "curated_location_page_title": "Places", "curated_object_page_title": "Things", + "current_server_address": "Current server address", "daily_title_text_date": "E, MMM dd", "daily_title_text_date_year": "E, MMM dd, yyyy", "date_format": "E, LLL d, y • h:mm a", @@ -235,6 +248,8 @@ "edit_date_time_dialog_timezone": "Timezone", "edit_image_title": "Edit", "edit_location_dialog_title": "Location", + "enter_wifi_name": "Enter WiFi name", + "error_change_sort_album": "Failed to change album sort order", "error_saving_image": "Error: {}", "exif_bottom_sheet_description": "Add Description...", "exif_bottom_sheet_details": "DETAILS", @@ -246,11 +261,15 @@ "experimental_settings_new_asset_list_title": "Enable experimental photo grid", "experimental_settings_subtitle": "Use at your own risk!", "experimental_settings_title": "Experimental", + "external_network": "External network", + "external_network_sheet_info": "When not on the preferred WiFi network, the app will connect to the server through the first of the below URLs it can reach, starting from top to bottom", "favorites": "Favorites", "favorites_page_no_favorites": "No favorite assets found", "favorites_page_title": "Favorites", "filename_search": "File name or extension", "filter": "Filter", + "get_wifiname_error": "Could not get Wi-Fi name. Make sure you have granted the necessary permissions and are connected to a Wi-Fi network", + "grant_permission": "Grant permission", "haptic_feedback_switch": "Enable haptic feedback", "haptic_feedback_title": "Haptic Feedback", "header_settings_add_header_tip": "Add Header", @@ -296,6 +315,10 @@ "library_page_sort_most_oldest_photo": "Oldest photo", "library_page_sort_most_recent_photo": "Most recent photo", "library_page_sort_title": "Album title", + "local_network": "Local network", + "local_network_sheet_info": "The app will connect to the server through this URL when using the specified Wi-Fi network", + "location_permission": "Location permission", + "location_permission_content": "In order to use the auto-switching feature, Immich needs precise location permission so it can read the current WiFi network's name", "location_picker_choose_on_map": "Choose on map", "location_picker_latitude": "Latitude", "location_picker_latitude_error": "Enter a valid latitude", @@ -365,6 +388,8 @@ "multiselect_grid_edit_date_time_err_read_only": "Cannot edit date of read only asset(s), skipping", "multiselect_grid_edit_gps_err_read_only": "Cannot edit location of read only asset(s), skipping", "my_albums": "My albums", + "networking_settings": "Networking", + "networking_subtitle": "Manage the server endpoint settings", "no_assets_to_show": "No assets to show", "no_name": "No name", "notification_permission_dialog_cancel": "Cancel", @@ -398,6 +423,7 @@ "permission_onboarding_permission_limited": "Permission limited. To let Immich backup and manage your entire gallery collection, grant photo and video permissions in Settings.", "permission_onboarding_request": "Immich requires permission to view your photos and videos.", "places": "Places", + "preferences_settings_subtitle": "Manage the app's preferences", "preferences_settings_title": "Preferences", "profile_drawer_app_logs": "Logs", "profile_drawer_client_out_of_date_major": "Mobile App is out of date. Please update to the latest major version.", @@ -412,6 +438,7 @@ "profile_drawer_trash": "Trash", "recently_added": "Recently added", "recently_added_page_title": "Recently Added", + "save": "Save", "save_to_gallery": "Save to gallery", "scaffold_body_error_occurred": "Error occurred", "search_albums": "Search albums", @@ -457,6 +484,7 @@ "search_page_places": "Places", "search_page_recently_added": "Recently added", "search_page_screenshots": "Screenshots", + "search_page_search_photos_videos": "Search for your photos and videos", "search_page_selfies": "Selfies", "search_page_things": "Things", "search_page_videos": "Videos", @@ -469,6 +497,7 @@ "select_additional_user_for_sharing_page_suggestions": "Suggestions", "select_user_for_sharing_page_err_album": "Failed to create album", "select_user_for_sharing_page_share_suggestions": "Suggestions", + "server_endpoint": "Server Endpoint", "server_info_box_app_version": "App Version", "server_info_box_latest_release": "Latest Version", "server_info_box_server_url": "Server URL", @@ -480,6 +509,7 @@ "setting_image_viewer_preview_title": "Load preview image", "setting_image_viewer_title": "Images", "setting_languages_apply": "Apply", + "setting_languages_subtitle": "Change the app's language", "setting_languages_title": "Languages", "setting_notifications_notify_failures_grace_period": "Notify background backup failures: {}", "setting_notifications_notify_hours": "{} hours", @@ -612,6 +642,8 @@ "upload_dialog_info": "Do you want to backup the selected Asset(s) to the server?", "upload_dialog_ok": "Upload", "upload_dialog_title": "Upload Asset", + "use_current_connection": "use current connection", + "validate_endpoint_error": "Please enter a valid URL", "version_announcement_overlay_ack": "Acknowledge", "version_announcement_overlay_release_notes": "release notes", "version_announcement_overlay_text_1": "Hi friend, there is a new release of", @@ -621,5 +653,7 @@ "videos": "Videos", "viewer_remove_from_stack": "Remove from Stack", "viewer_stack_use_as_main_asset": "Use as Main Asset", - "viewer_unstack": "Un-Stack" + "viewer_unstack": "Un-Stack", + "wifi_name": "WiFi Name", + "your_wifi_name": "Your WiFi name" } \ No newline at end of file diff --git a/mobile/assets/i18n/lv-LV.json b/mobile/assets/i18n/lv-LV.json index b49e2f5af75c3..fb9eaac8bfc9c 100644 --- a/mobile/assets/i18n/lv-LV.json +++ b/mobile/assets/i18n/lv-LV.json @@ -7,6 +7,7 @@ "action_common_select": "Select", "action_common_update": "Atjaunināt", "add_a_name": "Add a name", + "add_endpoint": "Add endpoint", "add_to_album_bottom_sheet_added": "Pievienots {album}", "add_to_album_bottom_sheet_already_exists": "Jau pievienots {album}", "advanced_settings_log_level_title": "Žurnalēšanas līmenis: {}", @@ -65,7 +66,12 @@ "assets_restored_successfully": "{} asset(s) restored successfully", "assets_trashed": "{} asset(s) trashed", "assets_trashed_from_server": "{} asset(s) trashed from the Immich server", + "asset_viewer_settings_subtitle": "Manage your gallery viewer settings", "asset_viewer_settings_title": "Aktīvu Skatītājs", + "automatic_endpoint_switching_subtitle": "Connect locally over designated Wi-Fi when available and use alternative connections elsewhere", + "automatic_endpoint_switching_title": "Automatic URL switching", + "background_location_permission": "Background location permission", + "background_location_permission_content": "In order to switch networks when running in the background, Immich must *always* have precise location access so the app can read the Wi-Fi network's name", "backup_album_selection_page_albums_device": "Albumi ierīcē ({})", "backup_album_selection_page_albums_tap": "Pieskarieties, lai iekļautu, veiciet dubultskārienu, lai izslēgtu", "backup_album_selection_page_assets_scatter": "Aktīvi var būt izmētāti pa vairākiem albumiem. Tādējādi dublēšanas procesā albumus var iekļaut vai neiekļaut.", @@ -131,6 +137,7 @@ "backup_manual_success": "Veiksmīgi", "backup_manual_title": "Augšupielādes statuss", "backup_options_page_title": "Dublēšanas iestatījumi", + "backup_setting_subtitle": "Manage background and foreground upload settings", "cache_settings_album_thumbnails": "Bibliotēkas lapu sīktēli ({} aktīvi)", "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.", @@ -149,11 +156,16 @@ "cache_settings_tile_subtitle": "Kontrolēt lokālās krātuves uzvedību", "cache_settings_tile_title": "Lokālā Krātuve", "cache_settings_title": "Kešdarbes iestatījumi", + "cancel": "Cancel", + "change_display_order": "Change display order", "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", + "check_corrupt_asset_backup": "Check for corrupt asset backups", + "check_corrupt_asset_backup_button": "Perform check", + "check_corrupt_asset_backup_description": "Run this check only over Wi-Fi and once all assets have been backed-up. The procedure might take a few minutes.", "client_cert_dialog_msg_confirm": "OK", "client_cert_enter_password": "Enter Password", "client_cert_import": "Import", @@ -199,6 +211,7 @@ "crop": "Crop", "curated_location_page_title": "Vietas", "curated_object_page_title": "Lietas", + "current_server_address": "Current server address", "daily_title_text_date": "E, MMM dd", "daily_title_text_date_year": "E, MMM dd, gggg", "date_format": "E, LLL d, g • h:mm a", @@ -235,6 +248,8 @@ "edit_date_time_dialog_timezone": "Laika zona", "edit_image_title": "Edit", "edit_location_dialog_title": "Atrašanās vieta", + "enter_wifi_name": "Enter WiFi name", + "error_change_sort_album": "Failed to change album sort order", "error_saving_image": "Error: {}", "exif_bottom_sheet_description": "Pievienot Aprakstu...", "exif_bottom_sheet_details": "INFORMĀCIJA", @@ -246,11 +261,15 @@ "experimental_settings_new_asset_list_title": "Iespējot eksperimentālo fotorežģi", "experimental_settings_subtitle": "Izmanto uzņemoties risku!", "experimental_settings_title": "Eksperimentāls", + "external_network": "External network", + "external_network_sheet_info": "When not on the preferred WiFi network, the app will connect to the server through the first of the below URLs it can reach, starting from top to bottom", "favorites": "Favorites", "favorites_page_no_favorites": "Nav atrasti iecienītākie aktīvi", "favorites_page_title": "Izlase", "filename_search": "File name or extension", "filter": "Filter", + "get_wifiname_error": "Could not get Wi-Fi name. Make sure you have granted the necessary permissions and are connected to a Wi-Fi network", + "grant_permission": "Grant permission", "haptic_feedback_switch": "Iestatīt haptisku reakciju", "haptic_feedback_title": "Haptiska Reakcija", "header_settings_add_header_tip": "Add Header", @@ -296,6 +315,10 @@ "library_page_sort_most_oldest_photo": "Vecākais fotoattēls", "library_page_sort_most_recent_photo": "Jaunākais fotoattēls", "library_page_sort_title": "Albuma virsraksts", + "local_network": "Local network", + "local_network_sheet_info": "The app will connect to the server through this URL when using the specified Wi-Fi network", + "location_permission": "Location permission", + "location_permission_content": "In order to use the auto-switching feature, Immich needs precise location permission so it can read the current WiFi network's name", "location_picker_choose_on_map": "Izvēlēties uz kartes", "location_picker_latitude": "Ģeogrāfiskais platums", "location_picker_latitude_error": "Ievadiet korektu ģeogrāfisko platumu", @@ -365,6 +388,8 @@ "multiselect_grid_edit_date_time_err_read_only": "Nevar rediģēt read only aktīva(-u) datumu, notiek izlaišana", "multiselect_grid_edit_gps_err_read_only": "Nevar rediģēt atrašanās vietu read only aktīva(-u) datumu, notiek izlaišana", "my_albums": "My albums", + "networking_settings": "Networking", + "networking_subtitle": "Manage the server endpoint settings", "no_assets_to_show": "Nav uzrādāmo aktīvu", "no_name": "No name", "notification_permission_dialog_cancel": "Atcelt", @@ -398,6 +423,7 @@ "permission_onboarding_permission_limited": "Atļauja ierobežota. Lai atļautu Immich dublēšanu un varētu pārvaldīt visu galeriju kolekciju, sadaļā Iestatījumi piešķiriet fotoattēlu un video atļaujas.", "permission_onboarding_request": "Immich nepieciešama atļauja skatīt jūsu fotoattēlus un videoklipus.", "places": "Places", + "preferences_settings_subtitle": "Manage the app's preferences", "preferences_settings_title": "Iestatījumi", "profile_drawer_app_logs": "Žurnāli", "profile_drawer_client_out_of_date_major": "Mobilā Aplikācija ir novecojusi. Lūdzu atjaunojiet to uz jaunāko lielo versiju", @@ -412,6 +438,7 @@ "profile_drawer_trash": "Atkritne", "recently_added": "Recently added", "recently_added_page_title": "Nesen Pievienotais", + "save": "Save", "save_to_gallery": "Save to gallery", "scaffold_body_error_occurred": "Radās kļūda", "search_albums": "Search albums", @@ -457,6 +484,7 @@ "search_page_places": "Vietas", "search_page_recently_added": "Nesen Pievienotais", "search_page_screenshots": "Ekrānuzņēmumi", + "search_page_search_photos_videos": "Search for your photos and videos", "search_page_selfies": "Selfiji", "search_page_things": "Lietas", "search_page_videos": "Videoklipi", @@ -469,6 +497,7 @@ "select_additional_user_for_sharing_page_suggestions": "Ieteikumi", "select_user_for_sharing_page_err_album": "Neizdevās izveidot albumu", "select_user_for_sharing_page_share_suggestions": "Ieteikumi", + "server_endpoint": "Server Endpoint", "server_info_box_app_version": "Aplikācijas Versija", "server_info_box_latest_release": "Jaunākā Versija", "server_info_box_server_url": "Servera URL", @@ -480,6 +509,7 @@ "setting_image_viewer_preview_title": "Ielādēt priekšskatījuma attēlu", "setting_image_viewer_title": "Attēli", "setting_languages_apply": "Lietot", + "setting_languages_subtitle": "Change the app's language", "setting_languages_title": "Valodas", "setting_notifications_notify_failures_grace_period": "Paziņot par fona dublēšanas kļūmēm: {}", "setting_notifications_notify_hours": "{} stundas", @@ -612,6 +642,8 @@ "upload_dialog_info": "Vai vēlaties veikt izvēlētā(-o) aktīva(-u) dublējumu uz servera?", "upload_dialog_ok": "Augšupielādēt", "upload_dialog_title": "Augšupielādēt Aktīvu", + "use_current_connection": "use current connection", + "validate_endpoint_error": "Please enter a valid URL", "version_announcement_overlay_ack": "Atzīt", "version_announcement_overlay_release_notes": "informācija par laidienu", "version_announcement_overlay_text_1": "Sveiks draugs, ir jauns izlaidums no", @@ -621,5 +653,7 @@ "videos": "Videos", "viewer_remove_from_stack": "Noņemt no Steka", "viewer_stack_use_as_main_asset": "Izmantot kā Galveno Aktīvu", - "viewer_unstack": "At-Stekot" + "viewer_unstack": "At-Stekot", + "wifi_name": "WiFi Name", + "your_wifi_name": "Your WiFi name" } \ No newline at end of file diff --git a/mobile/assets/i18n/mn-MN.json b/mobile/assets/i18n/mn-MN.json index 66392ed47a60d..a2128380e0b77 100644 --- a/mobile/assets/i18n/mn-MN.json +++ b/mobile/assets/i18n/mn-MN.json @@ -7,6 +7,7 @@ "action_common_select": "Select", "action_common_update": "Update", "add_a_name": "Add a name", + "add_endpoint": "Add endpoint", "add_to_album_bottom_sheet_added": "Added to {album}", "add_to_album_bottom_sheet_already_exists": "Already in {album}", "advanced_settings_log_level_title": "Log level: {}", @@ -65,7 +66,12 @@ "assets_restored_successfully": "{} asset(s) restored successfully", "assets_trashed": "{} asset(s) trashed", "assets_trashed_from_server": "{} asset(s) trashed from the Immich server", + "asset_viewer_settings_subtitle": "Manage your gallery viewer settings", "asset_viewer_settings_title": "Asset Viewer", + "automatic_endpoint_switching_subtitle": "Connect locally over designated Wi-Fi when available and use alternative connections elsewhere", + "automatic_endpoint_switching_title": "Automatic URL switching", + "background_location_permission": "Background location permission", + "background_location_permission_content": "In order to switch networks when running in the background, Immich must *always* have precise location access so the app can read the Wi-Fi network's name", "backup_album_selection_page_albums_device": "Albums on device ({})", "backup_album_selection_page_albums_tap": "Tap to include, double tap to exclude", "backup_album_selection_page_assets_scatter": "Assets can scatter across multiple albums. Thus, albums can be included or excluded during the backup process.", @@ -131,6 +137,7 @@ "backup_manual_success": "Success", "backup_manual_title": "Upload status", "backup_options_page_title": "Backup options", + "backup_setting_subtitle": "Manage background and foreground upload settings", "cache_settings_album_thumbnails": "Library page thumbnails ({} assets)", "cache_settings_clear_cache_button": "Clear cache", "cache_settings_clear_cache_button_title": "Clears the app's cache. This will significantly impact the app's performance until the cache has rebuilt.", @@ -149,11 +156,16 @@ "cache_settings_tile_subtitle": "Control the local storage behaviour", "cache_settings_tile_title": "Local Storage", "cache_settings_title": "Caching Settings", + "cancel": "Cancel", + "change_display_order": "Change display order", "change_password_form_confirm_password": "Confirm Password", "change_password_form_description": "Hi {name},\n\nThis is either the first time you are signing into the system or a request has been made to change your password. Please enter the new password below.", "change_password_form_new_password": "New Password", "change_password_form_password_mismatch": "Passwords do not match", "change_password_form_reenter_new_password": "Re-enter New Password", + "check_corrupt_asset_backup": "Check for corrupt asset backups", + "check_corrupt_asset_backup_button": "Perform check", + "check_corrupt_asset_backup_description": "Run this check only over Wi-Fi and once all assets have been backed-up. The procedure might take a few minutes.", "client_cert_dialog_msg_confirm": "OK", "client_cert_enter_password": "Enter Password", "client_cert_import": "Import", @@ -199,6 +211,7 @@ "crop": "Crop", "curated_location_page_title": "Places", "curated_object_page_title": "Things", + "current_server_address": "Current server address", "daily_title_text_date": "E, MMM dd", "daily_title_text_date_year": "E, MMM dd, yyyy", "date_format": "E, LLL d, y • h:mm a", @@ -235,6 +248,8 @@ "edit_date_time_dialog_timezone": "Timezone", "edit_image_title": "Edit", "edit_location_dialog_title": "Location", + "enter_wifi_name": "Enter WiFi name", + "error_change_sort_album": "Failed to change album sort order", "error_saving_image": "Error: {}", "exif_bottom_sheet_description": "Add Description...", "exif_bottom_sheet_details": "DETAILS", @@ -246,11 +261,15 @@ "experimental_settings_new_asset_list_title": "Enable experimental photo grid", "experimental_settings_subtitle": "Use at your own risk!", "experimental_settings_title": "Experimental", + "external_network": "External network", + "external_network_sheet_info": "When not on the preferred WiFi network, the app will connect to the server through the first of the below URLs it can reach, starting from top to bottom", "favorites": "Favorites", "favorites_page_no_favorites": "No favorite assets found", "favorites_page_title": "Favorites", "filename_search": "File name or extension", "filter": "Filter", + "get_wifiname_error": "Could not get Wi-Fi name. Make sure you have granted the necessary permissions and are connected to a Wi-Fi network", + "grant_permission": "Grant permission", "haptic_feedback_switch": "Enable haptic feedback", "haptic_feedback_title": "Haptic Feedback", "header_settings_add_header_tip": "Add Header", @@ -296,6 +315,10 @@ "library_page_sort_most_oldest_photo": "Oldest photo", "library_page_sort_most_recent_photo": "Most recent photo", "library_page_sort_title": "Album title", + "local_network": "Local network", + "local_network_sheet_info": "The app will connect to the server through this URL when using the specified Wi-Fi network", + "location_permission": "Location permission", + "location_permission_content": "In order to use the auto-switching feature, Immich needs precise location permission so it can read the current WiFi network's name", "location_picker_choose_on_map": "Choose on map", "location_picker_latitude": "Latitude", "location_picker_latitude_error": "Enter a valid latitude", @@ -365,6 +388,8 @@ "multiselect_grid_edit_date_time_err_read_only": "Cannot edit date of read only asset(s), skipping", "multiselect_grid_edit_gps_err_read_only": "Cannot edit location of read only asset(s), skipping", "my_albums": "My albums", + "networking_settings": "Networking", + "networking_subtitle": "Manage the server endpoint settings", "no_assets_to_show": "No assets to show", "no_name": "No name", "notification_permission_dialog_cancel": "Цуцлах", @@ -398,6 +423,7 @@ "permission_onboarding_permission_limited": "Permission limited. To let Immich backup and manage your entire gallery collection, grant photo and video permissions in Settings.", "permission_onboarding_request": "Immich requires permission to view your photos and videos.", "places": "Places", + "preferences_settings_subtitle": "Manage the app's preferences", "preferences_settings_title": "Preferences", "profile_drawer_app_logs": "Logs", "profile_drawer_client_out_of_date_major": "Mobile App is out of date. Please update to the latest major version.", @@ -412,6 +438,7 @@ "profile_drawer_trash": "Trash", "recently_added": "Recently added", "recently_added_page_title": "Recently Added", + "save": "Save", "save_to_gallery": "Save to gallery", "scaffold_body_error_occurred": "Error occurred", "search_albums": "Search albums", @@ -457,6 +484,7 @@ "search_page_places": "Places", "search_page_recently_added": "Recently added", "search_page_screenshots": "Screenshots", + "search_page_search_photos_videos": "Search for your photos and videos", "search_page_selfies": "Selfies", "search_page_things": "Things", "search_page_videos": "Videos", @@ -469,6 +497,7 @@ "select_additional_user_for_sharing_page_suggestions": "Suggestions", "select_user_for_sharing_page_err_album": "Failed to create album", "select_user_for_sharing_page_share_suggestions": "Suggestions", + "server_endpoint": "Server Endpoint", "server_info_box_app_version": "App Version", "server_info_box_latest_release": "Latest Version", "server_info_box_server_url": "Server URL", @@ -480,6 +509,7 @@ "setting_image_viewer_preview_title": "Load preview image", "setting_image_viewer_title": "Images", "setting_languages_apply": "Apply", + "setting_languages_subtitle": "Change the app's language", "setting_languages_title": "Languages", "setting_notifications_notify_failures_grace_period": "Notify background backup failures: {}", "setting_notifications_notify_hours": "{} hours", @@ -612,6 +642,8 @@ "upload_dialog_info": "Do you want to backup the selected Asset(s) to the server?", "upload_dialog_ok": "Upload", "upload_dialog_title": "Upload Asset", + "use_current_connection": "use current connection", + "validate_endpoint_error": "Please enter a valid URL", "version_announcement_overlay_ack": "Acknowledge", "version_announcement_overlay_release_notes": "release notes", "version_announcement_overlay_text_1": "Hi friend, there is a new release of", @@ -621,5 +653,7 @@ "videos": "Videos", "viewer_remove_from_stack": "Remove from Stack", "viewer_stack_use_as_main_asset": "Use as Main Asset", - "viewer_unstack": "Un-Stack" + "viewer_unstack": "Un-Stack", + "wifi_name": "WiFi Name", + "your_wifi_name": "Your WiFi name" } \ No newline at end of file diff --git a/mobile/assets/i18n/nb-NO.json b/mobile/assets/i18n/nb-NO.json index 8bc8402fd3f31..8dce0381e8893 100644 --- a/mobile/assets/i18n/nb-NO.json +++ b/mobile/assets/i18n/nb-NO.json @@ -6,7 +6,8 @@ "action_common_save": "Lagre", "action_common_select": "Velg", "action_common_update": "Oppdater", - "add_a_name": "Add a name", + "add_a_name": "Legg til navn", + "add_endpoint": "API endepunkt", "add_to_album_bottom_sheet_added": "Lagt til i {album}", "add_to_album_bottom_sheet_already_exists": "Allerede i {album}", "advanced_settings_log_level_title": "Loggnivå: {}", @@ -22,7 +23,7 @@ "advanced_settings_troubleshooting_title": "Feilsøking", "album_info_card_backup_album_excluded": "EKSKLUDERT", "album_info_card_backup_album_included": "INKLUDERT", - "albums": "Albums", + "albums": "Albumer", "album_thumbnail_card_item": "1 objekt", "album_thumbnail_card_items": "{} objekter", "album_thumbnail_card_shared": " · Delt", @@ -38,13 +39,13 @@ "album_viewer_appbar_share_remove": "Fjern fra album", "album_viewer_appbar_share_to": "Del til", "album_viewer_page_share_add_users": "Legg til brukere", - "all": "All", + "all": "Alt", "all_people_page_title": "Folk", "all_videos_page_title": "Videoer", "app_bar_signout_dialog_content": "Er du sikker på at du vil logge ut?", "app_bar_signout_dialog_ok": "Ja", "app_bar_signout_dialog_title": "Logg ut", - "archived": "Archived", + "archived": "Arkivert", "archive_page_no_archived_assets": "Ingen arkiverte objekter funnet", "archive_page_title": "Arkiv ({})", "asset_action_delete_err_read_only": "Kan ikke slette objekt(er) med kun lese-rettighet, hopper over", @@ -65,7 +66,12 @@ "assets_restored_successfully": "{} objekt(er) gjenopprettet", "assets_trashed": "{} objekt(er) slettet", "assets_trashed_from_server": "{} objekt(er) slettet fra Immich serveren", + "asset_viewer_settings_subtitle": "Endre dine visningsinnstillinger for galleriet", "asset_viewer_settings_title": "Objektviser", + "automatic_endpoint_switching_subtitle": "Koble til lokalt over angitt Wi-Fi når det er tilgjengelig, og bruk alternative tilkoblinger andre steder", + "automatic_endpoint_switching_title": "Automatisk URL bytte", + "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", "backup_album_selection_page_albums_device": "Album på enhet ({})", "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.", @@ -131,6 +137,7 @@ "backup_manual_success": "Vellykket", "backup_manual_title": "Opplastingsstatus", "backup_options_page_title": "Backupinnstillinger", + "backup_setting_subtitle": "Administrer opplastingsinnstillinger for bakgrunn og forgrunn", "cache_settings_album_thumbnails": "Bibliotekminiatyrbilder ({} objekter)", "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.", @@ -149,11 +156,16 @@ "cache_settings_tile_subtitle": "Kontroller lokal lagring", "cache_settings_tile_title": "Lokal lagring", "cache_settings_title": "Bufringsinnstillinger", + "cancel": "Avbryt", + "change_display_order": "Change display order", "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", + "check_corrupt_asset_backup": "Sjekk etter korrupte backupobjekter", + "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.\nDenne sjekken kan ta noen minutter.", "client_cert_dialog_msg_confirm": "OK", "client_cert_enter_password": "Skriv inn passord", "client_cert_import": "Importer", @@ -189,9 +201,9 @@ "control_bottom_app_bar_unarchive": "Fjern fra arkiv", "control_bottom_app_bar_unfavorite": "Fjern favoritt", "control_bottom_app_bar_upload": "Last opp", - "create_album": "Create album", + "create_album": "Opprett album", "create_album_page_untitled": "Uten navn", - "create_new": "CREATE NEW", + "create_new": "LAG NY", "create_shared_album_page_create": "Opprett", "create_shared_album_page_share": "Del", "create_shared_album_page_share_add_assets": "LEGG TIL OBJEKTER", @@ -199,6 +211,7 @@ "crop": "Beskjær", "curated_location_page_title": "Plasseringer", "curated_object_page_title": "Ting", + "current_server_address": "Nåværende serveradresse", "daily_title_text_date": "E, MMM dd", "daily_title_text_date_year": "E, MMM dd, yyyy", "date_format": "E, LLL d, y • h:mm a", @@ -235,6 +248,8 @@ "edit_date_time_dialog_timezone": "Tidssone", "edit_image_title": "Endre", "edit_location_dialog_title": "Lokasjon", + "enter_wifi_name": "Skriv inn Wi-Fi navn", + "error_change_sort_album": "Failed to change album sort order", "error_saving_image": "Feil: {}", "exif_bottom_sheet_description": "Legg til beskrivelse ...", "exif_bottom_sheet_details": "DETALJER", @@ -246,11 +261,15 @@ "experimental_settings_new_asset_list_title": "Aktiver eksperimentell rutenettsvisning", "experimental_settings_subtitle": "Bruk på egen risiko!", "experimental_settings_title": "Eksperimentelt", - "favorites": "Favorites", + "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", + "favorites": "Favoritter", "favorites_page_no_favorites": "Ingen favorittobjekter funnet", "favorites_page_title": "Favoritter", "filename_search": "Filnavn eller filtype", "filter": "Filter", + "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", + "grant_permission": "Gi tillatelse", "haptic_feedback_switch": "Aktivert haptisk tilbakemelding", "haptic_feedback_title": "Haptisk tilbakemelding", "header_settings_add_header_tip": "Legg til header", @@ -274,8 +293,8 @@ "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_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", - "ignore_icloud_photos": "Ignore iCloud photos", - "ignore_icloud_photos_description": "Photos that are stored on iCloud will not be uploaded to the Immich server", + "ignore_icloud_photos": "Ignorer iCloud bilder", + "ignore_icloud_photos_description": "Bilder som er lagret på iCloud vil ikke lastes opp til Immich", "image_saved_successfully": "Bilde lagret", "image_viewer_page_state_provider_download_error": "Nedlasting feilet", "image_viewer_page_state_provider_download_started": "Nedlasting startet", @@ -283,7 +302,7 @@ "image_viewer_page_state_provider_share_error": "Delingsfeil", "invalid_date": "Ugyldig dato", "invalid_date_format": "Ugyldig datoformat", - "library": "Library", + "library": "Bibliotek", "library_page_albums": "Albumer", "library_page_archive": "Arkiv", "library_page_device_albums": "Albumer på enheten", @@ -296,6 +315,10 @@ "library_page_sort_most_oldest_photo": "Eldste bilde", "library_page_sort_most_recent_photo": "Siste bilde", "library_page_sort_title": "Albumtittel", + "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", + "location_permission_content": "For å bruke funksjonen for automatisk veksling trenger Immich nøyaktig plasseringstillatelse slik at den kan lese navnet på det gjeldende Wi-Fi-nettverket", "location_picker_choose_on_map": "Velg på kart", "location_picker_latitude": "Breddegrad", "location_picker_latitude_error": "Skriv inn en gyldig bredddegrad", @@ -364,7 +387,9 @@ "motion_photos_page_title": "Bevegelige bilder", "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", - "my_albums": "My albums", + "my_albums": "Mine albumer", + "networking_settings": "Nettverk", + "networking_subtitle": "Administrer serverendepunktinnstillingene", "no_assets_to_show": "Ingen objekter å vise", "no_name": "Ingen navn", "notification_permission_dialog_cancel": "Avbryt", @@ -373,7 +398,7 @@ "notification_permission_list_tile_content": "Gi tilgang for å aktivere notifikasjoner", "notification_permission_list_tile_enable_button": "Aktiver notifikasjoner", "notification_permission_list_tile_title": "Notifikasjonstilgang", - "on_this_device": "On this device", + "on_this_device": "På denne enheten", "partner_list_user_photos": "{user}'s bilder", "partner_list_view_all": "Vis alle", "partner_page_add_partner": "Legg til partner", @@ -385,8 +410,8 @@ "partner_page_stop_sharing_content": "{} vil ikke lenger ha tilgang til dine bilder.", "partner_page_stop_sharing_title": "Stopp deling av bildene dine?", "partner_page_title": "Partner", - "partners": "Partners", - "people": "People", + "partners": "Partnere", + "people": "Mennesker", "permission_onboarding_back": "Tilbake", "permission_onboarding_continue_anyway": "Fortsett uansett", "permission_onboarding_get_started": "Kom i gang", @@ -397,7 +422,8 @@ "permission_onboarding_permission_granted": "Tilgang gitt! Du er i gang.", "permission_onboarding_permission_limited": "Begrenset tilgang. For å la Immich sikkerhetskopiere og håndtere galleriet, tillatt bilde- og video-tilgang i Innstillinger.", "permission_onboarding_request": "Immich trenger tilgang til å se dine bilder og videoer", - "places": "Places", + "places": "Steder", + "preferences_settings_subtitle": "Administrer appens preferanser", "preferences_settings_title": "Innstillinger", "profile_drawer_app_logs": "Logg", "profile_drawer_client_out_of_date_major": "Mobilapp er utdatert. Vennligst oppdater til nyeste versjon.", @@ -410,11 +436,12 @@ "profile_drawer_settings": "Innstillinger", "profile_drawer_sign_out": "Logg ut", "profile_drawer_trash": "Søppelbøtte", - "recently_added": "Recently added", + "recently_added": "Nylig lagt til", "recently_added_page_title": "Nylig lagt til", + "save": "Lagre", "save_to_gallery": "Lagre til galleriet", "scaffold_body_error_occurred": "Feil oppstått", - "search_albums": "Search albums", + "search_albums": "Søk i albumer", "search_bar_hint": "Søk i dine bilder", "search_filter_apply": "Aktiver filter", "search_filter_camera": "Kamera", @@ -457,6 +484,7 @@ "search_page_places": "Steder", "search_page_recently_added": "Nylig lagt til", "search_page_screenshots": "Skjermbilder", + "search_page_search_photos_videos": "Søk etter dine bilder og videoer", "search_page_selfies": "Selfier", "search_page_things": "Ting", "search_page_videos": "Videoer", @@ -469,6 +497,7 @@ "select_additional_user_for_sharing_page_suggestions": "Forslag", "select_user_for_sharing_page_err_album": "Feilet ved oppretting av album", "select_user_for_sharing_page_share_suggestions": "Forslag", + "server_endpoint": "Server endepunkt", "server_info_box_app_version": "App-versjon", "server_info_box_latest_release": "Siste versjon", "server_info_box_server_url": "Server-adresse", @@ -480,6 +509,7 @@ "setting_image_viewer_preview_title": "Last forhåndsvisningsbilde", "setting_image_viewer_title": "Bilder", "setting_languages_apply": "Bekreft", + "setting_languages_subtitle": "Endre app-språk", "setting_languages_title": "Språk", "setting_notifications_notify_failures_grace_period": "Varsle om sikkerhetskopieringsfeil i bakgrunnen: {}", "setting_notifications_notify_hours": "{} timer", @@ -560,9 +590,9 @@ "shared_link_info_chip_upload": "Last opp", "shared_link_manage_links": "Håndter delte linker", "shared_link_public_album": "Offentlig album", - "shared_links": "Shared links", + "shared_links": "Delte linker", "share_done": "Ferdig", - "shared_with_me": "Shared with me", + "shared_with_me": "Delt med meg", "share_invite": "Inviter til album", "sharing_page_album": "Delte album", "sharing_page_description": "Lag delte albumer for å dele bilder og videoer med folk i nettverket ditt.", @@ -594,7 +624,7 @@ "theme_setting_three_stage_loading_subtitle": "Tre-trinns innlasting kan øke lasteytelsen, men forårsaker betydelig høyere nettverksbelastning", "theme_setting_three_stage_loading_title": "Aktiver tre-trinns innlasting", "translated_text_options": "Valg", - "trash": "Trash", + "trash": "Søppel", "trash_emptied": "Søppelbøtte tømt", "trash_page_delete": "Slett", "trash_page_delete_all": "Slett alt", @@ -612,14 +642,18 @@ "upload_dialog_info": "Vil du utføre backup av valgte objekt(er) til serveren?", "upload_dialog_ok": "Last opp", "upload_dialog_title": "Last opp objekt", + "use_current_connection": "bruk nåværende tilkobling", + "validate_endpoint_error": "Skriv inn en gyldig URL", "version_announcement_overlay_ack": "Bekreft", "version_announcement_overlay_release_notes": "endringsloggen", "version_announcement_overlay_text_1": "Hei, det er en ny versjon av", "version_announcement_overlay_text_2": "vennligst ta deg tid til å besøke ", "version_announcement_overlay_text_3": " og verifiser at docker-compose og .env-oppsettet ditt er oppdatert for å forhindre en eventuell feilkonfigurasjon, spesielt hvis du benytter WatchTower eller en annen tjeneste som håndterer oppdatering av server-applikasjonen automatisk.", "version_announcement_overlay_title": "Ny serverversjon tilgjengelig", - "videos": "Videos", + "videos": "Videoer", "viewer_remove_from_stack": "Fjern fra stabling", "viewer_stack_use_as_main_asset": "Bruk som hovedobjekt", - "viewer_unstack": "avstable" + "viewer_unstack": "avstable", + "wifi_name": "Wi-Fi navn", + "your_wifi_name": "Ditt Wi-Fi navn" } \ No newline at end of file diff --git a/mobile/assets/i18n/nl-NL.json b/mobile/assets/i18n/nl-NL.json index 2bf277da1294b..ae7afef89eaee 100644 --- a/mobile/assets/i18n/nl-NL.json +++ b/mobile/assets/i18n/nl-NL.json @@ -7,6 +7,7 @@ "action_common_select": "Selecteren", "action_common_update": "Bijwerken", "add_a_name": "Naam toevoegen", + "add_endpoint": "Server toevoegen", "add_to_album_bottom_sheet_added": "Toegevoegd aan {album}", "add_to_album_bottom_sheet_already_exists": "Staat al in {album}", "advanced_settings_log_level_title": "Log niveau: {}", @@ -65,7 +66,12 @@ "assets_restored_successfully": "{} asset(s) succesvol hersteld", "assets_trashed": "{} asset(s) naar de prullenbak verplaatst", "assets_trashed_from_server": "{} asset(s) naar de prullenbak verplaatst op de Immich server", + "asset_viewer_settings_subtitle": "Beheer je instellingen voor gallerijweergave", "asset_viewer_settings_title": "Foto weergave", + "automatic_endpoint_switching_subtitle": "Verbind lokaal bij het opgegeven wifi-netwerk en gebruik anders de externe url", + "automatic_endpoint_switching_title": "Automatische serverwissel", + "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", "backup_album_selection_page_albums_device": "Albums op apparaat ({})", "backup_album_selection_page_albums_tap": "Tik om in te voegen, dubbel tik om uit te sluiten", "backup_album_selection_page_assets_scatter": "Assets kunnen over verschillende albums verdeeld zijn, dus albums kunnen inbegrepen of uitgesloten zijn van het backup proces.", @@ -131,6 +137,7 @@ "backup_manual_success": "Succes", "backup_manual_title": "Uploadstatus", "backup_options_page_title": "Back-up instellingen", + "backup_setting_subtitle": "Beheer achtergrond en voorgrond uploadinstellingen", "cache_settings_album_thumbnails": "Thumbnails bibliotheekpagina ({} assets)", "cache_settings_clear_cache_button": "Cache wissen", "cache_settings_clear_cache_button_title": "Wist de cache van de app. Dit zal de presentaties van de app aanzienlijk beïnvloeden totdat de cache opnieuw is opgebouwd.", @@ -149,11 +156,16 @@ "cache_settings_tile_subtitle": "Beheer het gedrag van lokale opslag", "cache_settings_tile_title": "Lokale opslag", "cache_settings_title": "Cache-instellingen", + "cancel": "Annuleren", + "change_display_order": "Weergavevolgorde wijzigen", "change_password_form_confirm_password": "Bevestig wachtwoord", "change_password_form_description": "Hallo {name},\n\nDit is ofwel de eerste keer dat je inlogt, of er is een verzoek gedaan om je wachtwoord te wijzigen. Vul hieronder een nieuw wachtwoord in.", "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", + "check_corrupt_asset_backup": "Controleer op corrupte back-ups van assets", + "check_corrupt_asset_backup_button": "Controle uitvoeren", + "check_corrupt_asset_backup_description": "Voer deze controle alleen uit via wifi en nadat alle assets zijn geback-upt. De procedure kan een paar minuten duren.", "client_cert_dialog_msg_confirm": "Ok", "client_cert_enter_password": "Voer wachtwoord in", "client_cert_import": "Importeren", @@ -199,6 +211,7 @@ "crop": "Bijsnijden", "curated_location_page_title": "Plaatsen", "curated_object_page_title": "Dingen", + "current_server_address": "Huidige serveradres", "daily_title_text_date": "E dd MMM", "daily_title_text_date_year": "E dd MMM yyyy", "date_format": "E d LLL y • H:mm", @@ -235,6 +248,8 @@ "edit_date_time_dialog_timezone": "Tijdzone", "edit_image_title": "Bewerken", "edit_location_dialog_title": "Locatie", + "enter_wifi_name": "Voer de WiFi naam in", + "error_change_sort_album": "Sorteervolgorde van album wijzigen mislukt", "error_saving_image": "Fout: {}", "exif_bottom_sheet_description": "Beschrijving toevoegen...", "exif_bottom_sheet_details": "DETAILS", @@ -246,11 +261,15 @@ "experimental_settings_new_asset_list_title": "Experimenteel fotoraster inschakelen", "experimental_settings_subtitle": "Gebruik op eigen risico!", "experimental_settings_title": "Experimenteel", + "external_network": "Extern netwerk", + "external_network_sheet_info": "Als je niet verbonden bent met het opgegeven wifi-netwerk, maakt de app verbinding met de server via de eerst bereikbare URL in de onderstaande lijst, van boven naar beneden", "favorites": "Favorieten", "favorites_page_no_favorites": "Geen favoriete assets gevonden", "favorites_page_title": "Favorieten", "filename_search": "Bestandsnaam of extensie", "filter": "Filter", + "get_wifiname_error": "Kon de Wi-Fi naam niet ophalen. Zorg ervoor dat je de benodigde machtigingen hebt verleend en verbonden bent met een Wi-Fi-netwerk", + "grant_permission": "Geef toestemming", "haptic_feedback_switch": "Aanraaktrillingen inschakelen", "haptic_feedback_title": "Aanraaktrillingen", "header_settings_add_header_tip": "Header toevoegen", @@ -296,6 +315,10 @@ "library_page_sort_most_oldest_photo": "Oudste foto", "library_page_sort_most_recent_photo": "Meest recente foto", "library_page_sort_title": "Albumtitel", + "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": "Locatie toestemming", + "location_permission_content": "Om de functie voor automatische serverwissel te gebruiken, heeft Immich toegang tot de exacte locatie nodig om de naam van het huidige wifi-netwerk te kunnen bepalen.", "location_picker_choose_on_map": "Kies op kaart", "location_picker_latitude": "Breedtegraad", "location_picker_latitude_error": "Voer een geldige breedtegraad in", @@ -365,6 +388,8 @@ "multiselect_grid_edit_date_time_err_read_only": "Kan datum van alleen-lezen asset(s) niet wijzigen, overslaan", "multiselect_grid_edit_gps_err_read_only": "Kan locatie van alleen-lezen asset(s) niet wijzigen, overslaan", "my_albums": "Mijn albums", + "networking_settings": "Netwerk", + "networking_subtitle": "Beheer de instellingen voor de server URL", "no_assets_to_show": "Geen foto's om te laten zien", "no_name": "Geen naam", "notification_permission_dialog_cancel": "Annuleren", @@ -398,6 +423,7 @@ "permission_onboarding_permission_limited": "Beperkte toestemming. Geef toestemming tot foto's en video's in Instellingen om Immich een back-up te laten maken van je galerij en deze te beheren.", "permission_onboarding_request": "Immich heeft toestemming nodig om je foto's en video's te bekijken.", "places": "Plaatsen", + "preferences_settings_subtitle": "Beheer de voorkeuren van de app", "preferences_settings_title": "Voorkeuren", "profile_drawer_app_logs": "Logboek", "profile_drawer_client_out_of_date_major": "Mobiele app is verouderd. Werk bij naar de nieuwste hoofdversie.", @@ -412,6 +438,7 @@ "profile_drawer_trash": "Prullenbak", "recently_added": "Onlangs toegevoegd", "recently_added_page_title": "Recent toegevoegd", + "save": "Opslaan", "save_to_gallery": "Opslaan in galerij", "scaffold_body_error_occurred": "Fout opgetreden", "search_albums": "Albums zoeken", @@ -457,6 +484,7 @@ "search_page_places": "Plaatsen", "search_page_recently_added": "Recent toegevoegd", "search_page_screenshots": "Screenshots", + "search_page_search_photos_videos": "Zoek naar je foto's en video's", "search_page_selfies": "Selfies", "search_page_things": "Dingen", "search_page_videos": "Video's", @@ -469,6 +497,7 @@ "select_additional_user_for_sharing_page_suggestions": "Suggesties", "select_user_for_sharing_page_err_album": "Album aanmaken mislukt", "select_user_for_sharing_page_share_suggestions": "Suggesties", + "server_endpoint": "Server url", "server_info_box_app_version": "Appversie", "server_info_box_latest_release": "Laatste Versie", "server_info_box_server_url": "Server URL", @@ -480,6 +509,7 @@ "setting_image_viewer_preview_title": "Voorbeeldafbeelding laden", "setting_image_viewer_title": "Afbeeldingen", "setting_languages_apply": "Toepassen", + "setting_languages_subtitle": "Wijzig de taal van de app", "setting_languages_title": "Taal", "setting_notifications_notify_failures_grace_period": "Fouten van de achtergrond back-up melden: {}", "setting_notifications_notify_hours": "{} uur", @@ -612,6 +642,8 @@ "upload_dialog_info": "Wil je een backup maken van de geselecteerde asset(s) op de server?", "upload_dialog_ok": "Uploaden", "upload_dialog_title": "Asset uploaden", + "use_current_connection": "gebruik huidige verbinding", + "validate_endpoint_error": "Vul een geldige URL in", "version_announcement_overlay_ack": "Bevestig", "version_announcement_overlay_release_notes": "releaseopmerkingen", "version_announcement_overlay_text_1": "Hoi, er is een nieuwe versie beschikbaar van", @@ -621,5 +653,7 @@ "videos": "Video's", "viewer_remove_from_stack": "Verwijder van Stapel", "viewer_stack_use_as_main_asset": "Gebruik als Hoofd Asset", - "viewer_unstack": "Ontstapel" + "viewer_unstack": "Ontstapel", + "wifi_name": "WiFi naam", + "your_wifi_name": "Je WiFi naam" } \ No newline at end of file diff --git a/mobile/assets/i18n/pl-PL.json b/mobile/assets/i18n/pl-PL.json index 3a6ba9f3b45f0..d2a15c2c5a1e4 100644 --- a/mobile/assets/i18n/pl-PL.json +++ b/mobile/assets/i18n/pl-PL.json @@ -6,7 +6,8 @@ "action_common_save": "Zapisz", "action_common_select": "Wybierz", "action_common_update": "Aktualizuj", - "add_a_name": "Add a name", + "add_a_name": "Dodaj nazwę", + "add_endpoint": "Dodaj punkt końcowy", "add_to_album_bottom_sheet_added": "Dodano do {album}", "add_to_album_bottom_sheet_already_exists": "Już w {album}", "advanced_settings_log_level_title": "Poziom dziennika: {}", @@ -22,7 +23,7 @@ "advanced_settings_troubleshooting_title": "Rozwiązywanie problemów", "album_info_card_backup_album_excluded": "WYKLUCZONE", "album_info_card_backup_album_included": "WŁĄCZONE", - "albums": "Albums", + "albums": "Albumy", "album_thumbnail_card_item": "1 pozycja", "album_thumbnail_card_items": "{} pozycje", "album_thumbnail_card_shared": "Udostępniony", @@ -38,13 +39,13 @@ "album_viewer_appbar_share_remove": "Usuń z albumu", "album_viewer_appbar_share_to": "Udostępnij", "album_viewer_page_share_add_users": "Dodaj użytkowników", - "all": "All", + "all": "Wszystko", "all_people_page_title": "Ludzie", "all_videos_page_title": "Filmy", "app_bar_signout_dialog_content": "Czy na pewno chcesz się wylogować?", "app_bar_signout_dialog_ok": "Tak", "app_bar_signout_dialog_title": "Wyloguj się", - "archived": "Archived", + "archived": "Zarchiwizowane", "archive_page_no_archived_assets": "Nie znaleziono zarchiwizowanych zasobów", "archive_page_title": "Archiwum ({})", "asset_action_delete_err_read_only": "Nie można usunąć zasobów tylko do odczytu, pomijam", @@ -65,7 +66,12 @@ "assets_restored_successfully": " {} zasoby pomyślnie przywrócono", "assets_trashed": "{} zasoby zostały usunięte", "assets_trashed_from_server": "{} zasoby usunięte z serwera Immich", + "asset_viewer_settings_subtitle": "Zarządzaj ustawieniami przeglądarki galerii", "asset_viewer_settings_title": "Przeglądarka zasobów", + "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", + "automatic_endpoint_switching_title": "Automatyczne przełączanie adresów URL", + "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", "backup_album_selection_page_albums_device": "Albumy na urządzeniu ({})", "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.", @@ -131,6 +137,7 @@ "backup_manual_success": "Sukces", "backup_manual_title": "Stan przesyłania", "backup_options_page_title": "Opcje kopi zapasowej", + "backup_setting_subtitle": "Zarządzaj ustawieniami przesyłania w tle i na pierwszym planie", "cache_settings_album_thumbnails": "Miniatury stron bibliotek ({} zasobów)", "cache_settings_clear_cache_button": "Wyczyść Cache", "cache_settings_clear_cache_button_title": "Czyści pamięć podręczną aplikacji. Wpłynie to znacząco na wydajność aplikacji, dopóki pamięć podręczna nie zostanie odbudowana.", @@ -149,11 +156,16 @@ "cache_settings_tile_subtitle": "Kontroluj zachowanie lokalnego magazynu", "cache_settings_tile_title": "Lokalny magazyn", "cache_settings_title": "Ustawienia Buforowania", + "cancel": "Anuluj", + "change_display_order": "Change display order", "change_password_form_confirm_password": "Potwierdź Hasło", "change_password_form_description": "Cześć {name},\n\nPierwszy raz logujesz się do systemu, albo złożono prośbę o zmianę hasła. Wpisz poniżej nowe hasło.", "change_password_form_new_password": "Nowe Hasło", "change_password_form_password_mismatch": "Hasła nie są zgodne", "change_password_form_reenter_new_password": "Wprowadź ponownie Nowe Hasło", + "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.", "client_cert_dialog_msg_confirm": "OK", "client_cert_enter_password": "Wprowadź hasło", "client_cert_import": "Importuj", @@ -183,15 +195,15 @@ "control_bottom_app_bar_edit_time": "Edytuj datę i godzinę", "control_bottom_app_bar_favorite": "Ulubione", "control_bottom_app_bar_share": "Udostępnij", - "control_bottom_app_bar_share_to": "Udostępnij", + "control_bottom_app_bar_share_to": "Wyślij", "control_bottom_app_bar_stack": "Stos", "control_bottom_app_bar_trash_from_immich": "Przenieść do kosza", "control_bottom_app_bar_unarchive": "Cofnij archiwizację", "control_bottom_app_bar_unfavorite": "Nieulubione", "control_bottom_app_bar_upload": "Prześlij", - "create_album": "Create album", + "create_album": "Utwórz album", "create_album_page_untitled": "Bez tytułu", - "create_new": "CREATE NEW", + "create_new": "UTWÓRZ NOWY", "create_shared_album_page_create": "Utwórz album", "create_shared_album_page_share": "Udostępnij", "create_shared_album_page_share_add_assets": "DODAJ ZASOBY", @@ -199,6 +211,7 @@ "crop": "Przytnij", "curated_location_page_title": "Miejsca", "curated_object_page_title": "Rzeczy", + "current_server_address": "Aktualny adres serwera", "daily_title_text_date": "E, MMM dd", "daily_title_text_date_year": "E, MMM dd, yyyy", "date_format": "E, LLL d, y • h:mm a", @@ -216,25 +229,27 @@ "delete_shared_link_dialog_title": "Usuń udostępniony link", "description_input_hint_text": "Dodaj opis...", "description_input_submit_error": "Błąd aktualizacji opisu, sprawdź dziennik, aby uzyskać więcej szczegółów", - "download_canceled": "Download canceled", - "download_complete": "Download complete", - "download_enqueue": "Download enqueued", + "download_canceled": "Pobieranie anulowane", + "download_complete": "Pobieranie zakończone", + "download_enqueue": "Pobieranie w kolejce", "download_error": "Błąd pobierania", - "download_failed": "Download failed", - "download_filename": "file: {}", - "download_finished": "Download finished", - "downloading": "Downloading...", - "downloading_media": "Downloading media", - "download_notfound": "Download not found", - "download_paused": "Download paused", + "download_failed": "Pobieranie nieudane", + "download_filename": "plik: {}", + "download_finished": "Pobieranie zakończone", + "downloading": "Pobieranie...", + "downloading_media": "Pobieranie multimediów", + "download_notfound": "Nie znaleziono pliku do pobrania", + "download_paused": "Pobieranie wstrzymane", "download_started": "Pobieranie rozpoczęte", "download_sucess": "Udane pobieranie", "download_sucess_android": "Media zostały pobrane do DCIM/Immich", - "download_waiting_to_retry": "Waiting to retry", + "download_waiting_to_retry": "Oczekiwanie na ponowną próbę", "edit_date_time_dialog_date_time": "Data i godzina", "edit_date_time_dialog_timezone": "Strefa czasowa", "edit_image_title": "Edytuj", "edit_location_dialog_title": "Lokalizacja", + "enter_wifi_name": "Wprowadź nazwę Wi-Fi", + "error_change_sort_album": "Failed to change album sort order", "error_saving_image": "Błąd: {}", "exif_bottom_sheet_description": "Dodaj Opis...", "exif_bottom_sheet_details": "SZCZEGÓŁY", @@ -246,13 +261,17 @@ "experimental_settings_new_asset_list_title": "Włącz eksperymentalną układ zdjęć", "experimental_settings_subtitle": "Używaj na własne ryzyko!", "experimental_settings_title": "Eksperymentalny", - "favorites": "Favorites", + "external_network": "Sieć zewnętrzna", + "external_network_sheet_info": "Jeśli nie korzystasz z preferowanej sieci Wi-Fi, aplikacja połączy się z serwerem za pośrednictwem pierwszego z poniższych adresów URL, do którego może dotrzeć, zaczynając od góry do dołu", + "favorites": "Ulubione", "favorites_page_no_favorites": "Nie znaleziono ulubionych zasobów", "favorites_page_title": "Ulubione", "filename_search": "Nazwa pliku lub rozszerzenie", - "filter": "Filter", - "haptic_feedback_switch": "Enable haptic feedback", - "haptic_feedback_title": "Haptic Feedback", + "filter": "Filtr", + "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", + "grant_permission": "Udziel pozwolenia", + "haptic_feedback_switch": "Włącz technologię haptyczną", + "haptic_feedback_title": "Technologia haptyczna", "header_settings_add_header_tip": "Dodaj nagłówek", "header_settings_field_validator_msg": "Wartość nie może być pusta", "header_settings_header_name_input": "Nazwa nagłówka", @@ -274,8 +293,8 @@ "home_page_first_time_notice": "Jeśli korzystasz z aplikacji po raz pierwszy, pamiętaj o wybraniu albumów zapasowych, aby oś czasu mogła zapełnić zdjęcia i filmy w albumach.", "home_page_share_err_local": "Nie można udostępniać zasobów lokalnych za pośrednictwem linku, pomijajam", "home_page_upload_err_limit": "Można przesłać maksymalnie 30 zasobów jednocześnie, pomijanie", - "ignore_icloud_photos": "Ignore iCloud photos", - "ignore_icloud_photos_description": "Photos that are stored on iCloud will not be uploaded to the Immich server", + "ignore_icloud_photos": "Ignoruj ​​zdjęcia w iCloud", + "ignore_icloud_photos_description": "Zdjęcia przechowywane w usłudze iCloud nie zostaną przesłane na serwer Immich", "image_saved_successfully": "Obraz zapisany", "image_viewer_page_state_provider_download_error": "Błąd pobierania", "image_viewer_page_state_provider_download_started": "Pobieranie rozpoczęte", @@ -283,7 +302,7 @@ "image_viewer_page_state_provider_share_error": "Udostępnij błąd", "invalid_date": "Nieprawidłowa data", "invalid_date_format": "Nieprawidłowy format daty", - "library": "Library", + "library": "Biblioteka", "library_page_albums": "Albumy", "library_page_archive": "Archiwum", "library_page_device_albums": "Albumy na Urządzeniu", @@ -296,6 +315,10 @@ "library_page_sort_most_oldest_photo": "Najstarsze zdjęcie", "library_page_sort_most_recent_photo": "Najnowsze zdjęcie", "library_page_sort_title": "Tytuł albumu", + "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ę", + "location_permission_content": "Aby móc korzystać z funkcji automatycznego przełączania, Immich potrzebuje precyzyjnego pozwolenia na lokalizację, aby móc odczytać nazwę bieżącej sieci WiFi", "location_picker_choose_on_map": "Wybierz na mapie", "location_picker_latitude": "Szerokość geograficzna", "location_picker_latitude_error": "Wprowadź prawidłową szerokość geograficzną", @@ -364,7 +387,9 @@ "motion_photos_page_title": "Zdjęcia ruchome", "multiselect_grid_edit_date_time_err_read_only": "Nie można edytować daty zasobów tylko do odczytu, pomijanie", "multiselect_grid_edit_gps_err_read_only": "Nie można edytować lokalizacji zasobów tylko do odczytu, pomijanie", - "my_albums": "My albums", + "my_albums": "Moje albumy", + "networking_settings": "Sieć", + "networking_subtitle": "Zarządzaj ustawieniami serwera końcowego ", "no_assets_to_show": "Brak zasobów do pokazania", "no_name": "Bez nazwy", "notification_permission_dialog_cancel": "Anuluj", @@ -373,7 +398,7 @@ "notification_permission_list_tile_content": "Przyznaj uprawnienia, aby włączyć powiadomienia.", "notification_permission_list_tile_enable_button": "Włącz Powiadomienia", "notification_permission_list_tile_title": "Pozwolenie na powiadomienia", - "on_this_device": "On this device", + "on_this_device": "Na tym urządzeniu", "partner_list_user_photos": "{user} zdjęcia", "partner_list_view_all": "Pokaż wszystkie", "partner_page_add_partner": "Dodaj partnera", @@ -385,8 +410,8 @@ "partner_page_stop_sharing_content": "{} nie będziesz już mieć dostępu do swoich zdjęć.", "partner_page_stop_sharing_title": "Przestać udostępniać swoje zdjęcia?", "partner_page_title": "Partner", - "partners": "Partners", - "people": "People", + "partners": "Partnerzy", + "people": "Ludzie", "permission_onboarding_back": "Cofnij", "permission_onboarding_continue_anyway": "Kontynuuj mimo to", "permission_onboarding_get_started": "Rozpocznij", @@ -397,7 +422,8 @@ "permission_onboarding_permission_granted": "Pozwolenie udzielone! Wszystko gotowe.", "permission_onboarding_permission_limited": "Pozwolenie ograniczone. Aby umożliwić Immichowi tworzenie kopii zapasowych całej kolekcji galerii i zarządzanie nią, przyznaj uprawnienia do zdjęć i filmów w Ustawieniach.", "permission_onboarding_request": "Immich potrzebuje pozwolenia na przeglądanie Twoich zdjęć i filmów.", - "places": "Places", + "places": "Miejsca", + "preferences_settings_subtitle": "Zarządzaj preferencjami aplikacji", "preferences_settings_title": "Ustawienia", "profile_drawer_app_logs": "Logi", "profile_drawer_client_out_of_date_major": "Aplikacja mobilna jest nieaktualna. Zaktualizuj do najnowszej wersji głównej.", @@ -410,11 +436,12 @@ "profile_drawer_settings": "Ustawienia", "profile_drawer_sign_out": "Wyloguj się", "profile_drawer_trash": "Kosz", - "recently_added": "Recently added", + "recently_added": "Ostatnio dodane", "recently_added_page_title": "Ostatnio Dodane", + "save": "Zapisz", "save_to_gallery": "Zapisz w galerii", "scaffold_body_error_occurred": "Wystąpił błąd", - "search_albums": "Search albums", + "search_albums": "Przeszukaj albumy", "search_bar_hint": "Szukaj swoich zdjęć", "search_filter_apply": "Zastosuj filtr", "search_filter_camera": "Kamera", @@ -457,6 +484,7 @@ "search_page_places": "Miejsca", "search_page_recently_added": "Ostatnio dodane", "search_page_screenshots": "Zrzuty ekranu", + "search_page_search_photos_videos": "Wyszukaj swoje zdjęcia i filmy", "search_page_selfies": "Selfi", "search_page_things": "Rzeczy", "search_page_videos": "Filmy", @@ -469,6 +497,7 @@ "select_additional_user_for_sharing_page_suggestions": "Propozycje", "select_user_for_sharing_page_err_album": "Nie udało się utworzyć albumu", "select_user_for_sharing_page_share_suggestions": "Propozycje", + "server_endpoint": "Serwer końcowy", "server_info_box_app_version": "Wersja Aplikacji", "server_info_box_latest_release": "Ostatnia wersja", "server_info_box_server_url": "Adres URL", @@ -480,6 +509,7 @@ "setting_image_viewer_preview_title": "Załaduj obraz podglądu", "setting_image_viewer_title": "Zdjęcia", "setting_languages_apply": "Zastosuj", + "setting_languages_subtitle": "Zmień język aplikacji", "setting_languages_title": "Języki", "setting_notifications_notify_failures_grace_period": "Powiadomienie o awariach kopii zapasowych w tle: {}", "setting_notifications_notify_hours": "{} godzin", @@ -560,9 +590,9 @@ "shared_link_info_chip_upload": "Wgraj", "shared_link_manage_links": "Zarządzaj udostępnionymi linkami", "shared_link_public_album": "Album publiczny", - "shared_links": "Shared links", + "shared_links": "Udostępnione linki", "share_done": "Zrobione", - "shared_with_me": "Shared with me", + "shared_with_me": "Udostępniono mi", "share_invite": "Zaproś do albumu", "sharing_page_album": "Udostępnione albumy", "sharing_page_description": "Twórz wspóldzielone albumy, aby udostępniać zdjęcia i filmy osobom w sieci.", @@ -594,7 +624,7 @@ "theme_setting_three_stage_loading_subtitle": "Trójstopniowe ładowanie może zwiększyć wydajność ładowania, ale powoduje znacznie większe obciążenie sieci", "theme_setting_three_stage_loading_title": "Włączenie trójstopniowego ładowania", "translated_text_options": "Opcje", - "trash": "Trash", + "trash": "Kosz", "trash_emptied": "Opróżnione śmieci", "trash_page_delete": "Usuń", "trash_page_delete_all": "Usuń wszystko", @@ -612,14 +642,18 @@ "upload_dialog_info": "Czy chcesz wykonać kopię zapasową wybranych zasobów na serwerze?", "upload_dialog_ok": "Prześlij", "upload_dialog_title": "Prześlij Zasób", + "use_current_connection": "użyj bieżącego połączenia", + "validate_endpoint_error": "Proszę wprowadzić prawidłowy adres URL", "version_announcement_overlay_ack": "Potwierdzam", "version_announcement_overlay_release_notes": "informacje o wydaniu", "version_announcement_overlay_text_1": "Cześć przyjacielu, jest nowe wydanie", "version_announcement_overlay_text_2": "prosimy o poświęcenie czasu na odwiedzenie ", "version_announcement_overlay_text_3": " i upewnij się, że twoja konfiguracja docker-compose i .env jest aktualna, aby zapobiec błędnym konfiguracjom, zwłaszcza jeśli używasz WatchTower lub dowolnego mechanizmu, który obsługuje automatyczną aktualizację aplikacji serwera.", "version_announcement_overlay_title": "Nowa wersja serwera dostępna \uD83C\uDF89", - "videos": "Videos", + "videos": "Filmy", "viewer_remove_from_stack": "Usuń ze stosu", "viewer_stack_use_as_main_asset": "Użyj jako głównego zasobu", - "viewer_unstack": "Usuń stos" + "viewer_unstack": "Usuń stos", + "wifi_name": "Nazwa Wi-Fi", + "your_wifi_name": "Twoja nazwa Wi-Fi" } \ No newline at end of file diff --git a/mobile/assets/i18n/pt-PT.json b/mobile/assets/i18n/pt-PT.json index 1adae1b1ec536..2411edb2f5247 100644 --- a/mobile/assets/i18n/pt-PT.json +++ b/mobile/assets/i18n/pt-PT.json @@ -6,7 +6,8 @@ "action_common_save": "Salvar", "action_common_select": "Selecionar", "action_common_update": "Atualizar", - "add_a_name": "Add a name", + "add_a_name": "Adicionar nome", + "add_endpoint": "Add endpoint", "add_to_album_bottom_sheet_added": "Adicionado a {album}", "add_to_album_bottom_sheet_already_exists": "Já existe em {album}", "advanced_settings_log_level_title": "Nível de log: {}", @@ -22,7 +23,7 @@ "advanced_settings_troubleshooting_title": "Resolução de problemas", "album_info_card_backup_album_excluded": "EXCLUÍDO", "album_info_card_backup_album_included": "INCLUÍDO", - "albums": "Albums", + "albums": "Álbuns", "album_thumbnail_card_item": "1 arquivo", "album_thumbnail_card_items": "{} arquivos", "album_thumbnail_card_shared": " · Compartilhado", @@ -38,13 +39,13 @@ "album_viewer_appbar_share_remove": "Remover do álbum", "album_viewer_appbar_share_to": "Compartilhar com", "album_viewer_page_share_add_users": "Adicionar usuários", - "all": "All", + "all": "Todos", "all_people_page_title": "Pessoas", "all_videos_page_title": "Vídeos", "app_bar_signout_dialog_content": "Tem certeza que deseja sair?", "app_bar_signout_dialog_ok": "Sim", "app_bar_signout_dialog_title": "Sair", - "archived": "Archived", + "archived": "Arquivado", "archive_page_no_archived_assets": "Nenhum arquivo encontrado", "archive_page_title": "Arquivado ({})", "asset_action_delete_err_read_only": "Não é possível excluir arquivo só leitura, ignorando", @@ -65,7 +66,12 @@ "assets_restored_successfully": "{} arquivo(s) restaurados com sucesso", "assets_trashed": "{} arquivo(s) enviados para a lixeira", "assets_trashed_from_server": "{} arquivo(s) do servidor foram enviados para a lixeira", + "asset_viewer_settings_subtitle": "Manage your gallery viewer settings", "asset_viewer_settings_title": "Visualizador", + "automatic_endpoint_switching_subtitle": "Connect locally over designated Wi-Fi when available and use alternative connections elsewhere", + "automatic_endpoint_switching_title": "Automatic URL switching", + "background_location_permission": "Background location permission", + "background_location_permission_content": "In order to switch networks when running in the background, Immich must *always* have precise location access so the app can read the Wi-Fi network's name", "backup_album_selection_page_albums_device": "Álbuns no dispositivo ({})", "backup_album_selection_page_albums_tap": "Toque para incluir, duplo toque para excluir", "backup_album_selection_page_assets_scatter": "Os arquivos podem estar espalhados em vários álbuns. Assim, os álbuns podem ser incluídos ou excluídos durante o processo de backup.", @@ -131,6 +137,7 @@ "backup_manual_success": "Sucesso", "backup_manual_title": "Estado do envio", "backup_options_page_title": "Opções de backup", + "backup_setting_subtitle": "Manage background and foreground upload settings", "cache_settings_album_thumbnails": "Miniaturas da página da biblioteca ({} arquivos)", "cache_settings_clear_cache_button": "Limpar cache", "cache_settings_clear_cache_button_title": "Limpa o cache do aplicativo. Isso afetará significativamente o desempenho do aplicativo até que o cache seja reconstruído.", @@ -149,11 +156,16 @@ "cache_settings_tile_subtitle": "Controlar o comportamento do armazenamento local", "cache_settings_tile_title": "Armazenamento local", "cache_settings_title": "Configurações de cache", + "cancel": "Cancel", + "change_display_order": "Change display order", "change_password_form_confirm_password": "Confirme a senha", "change_password_form_description": "Esta é a primeira vez que você está acessando o sistema ou foi feita uma solicitação para alterar sua senha. Por favor, insira a nova senha abaixo.", "change_password_form_new_password": "Nova senha", "change_password_form_password_mismatch": "As senhas não estão iguais", "change_password_form_reenter_new_password": "Confirme a nova senha", + "check_corrupt_asset_backup": "Check for corrupt asset backups", + "check_corrupt_asset_backup_button": "Perform check", + "check_corrupt_asset_backup_description": "Run this check only over Wi-Fi and once all assets have been backed-up. The procedure might take a few minutes.", "client_cert_dialog_msg_confirm": "OK", "client_cert_enter_password": "Digite a senha", "client_cert_import": "Importar", @@ -189,9 +201,9 @@ "control_bottom_app_bar_unarchive": "Desarquivar", "control_bottom_app_bar_unfavorite": "Remover favorito", "control_bottom_app_bar_upload": "Enviar", - "create_album": "Create album", + "create_album": "Criar Álbum", "create_album_page_untitled": "Sem título", - "create_new": "CREATE NEW", + "create_new": "CRIAR NOVO", "create_shared_album_page_create": "Criar", "create_shared_album_page_share": "Compartilhar", "create_shared_album_page_share_add_assets": "ADICIONAR ARQUIVOS", @@ -199,9 +211,10 @@ "crop": "Cortar", "curated_location_page_title": "Locais", "curated_object_page_title": "Objetos", - "daily_title_text_date": "E, MMM dd", - "daily_title_text_date_year": "E, MMM dd, yyyy", - "date_format": "E, LLL d, y • h:mm a", + "current_server_address": "Current server address", + "daily_title_text_date": "E, dd MMM", + "daily_title_text_date_year": "E, dd MMM, yyyy", + "date_format": "E, d LLL, y • h:mm a", "delete_dialog_alert": "Esses arquivos serão permanentemente apagados do Immich e de seu dispositivo", "delete_dialog_alert_local": "Estes arquivos serão permanentemente excluídos do seu dispositivo, mas continuarão disponíveis no servidor Immich", "delete_dialog_alert_local_non_backed_up": "Não há backup de alguns dos arquivos no servidor e eles serão excluídos permanentemente do seu dispositivo", @@ -235,6 +248,8 @@ "edit_date_time_dialog_timezone": "Fuso horário", "edit_image_title": "Editar", "edit_location_dialog_title": "Localização", + "enter_wifi_name": "Enter WiFi name", + "error_change_sort_album": "Failed to change album sort order", "error_saving_image": "Erro: {}", "exif_bottom_sheet_description": "Adicionar Descrição...", "exif_bottom_sheet_details": "DETALHES", @@ -246,11 +261,15 @@ "experimental_settings_new_asset_list_title": "Ativar visualização de grade experimental", "experimental_settings_subtitle": "Use por sua conta e risco!", "experimental_settings_title": "Experimental", - "favorites": "Favorites", + "external_network": "External network", + "external_network_sheet_info": "When not on the preferred WiFi network, the app will connect to the server through the first of the below URLs it can reach, starting from top to bottom", + "favorites": "Favoritos", "favorites_page_no_favorites": "Nenhum favorito encontrado", "favorites_page_title": "Favoritos", "filename_search": "Nome do arquivo ou extensão", - "filter": "Filter", + "filter": "Filtro", + "get_wifiname_error": "Could not get Wi-Fi name. Make sure you have granted the necessary permissions and are connected to a Wi-Fi network", + "grant_permission": "Grant permission", "haptic_feedback_switch": "Habilitar vibração", "haptic_feedback_title": "Vibração", "header_settings_add_header_tip": "Adicionar cabeçalho", @@ -274,8 +293,8 @@ "home_page_first_time_notice": "Se é a primeira vez que utiliza o aplicativo, certifique-se de marcar um ou mais álbuns do dispositivo para backup, assim a linha do tempo será preenchida com as fotos e vídeos.", "home_page_share_err_local": "Não é possível compartilhar arquivos locais com um link, ignorando", "home_page_upload_err_limit": "Só é possível enviar 30 arquivos por vez, ignorando", - "ignore_icloud_photos": "Ignore iCloud photos", - "ignore_icloud_photos_description": "Photos that are stored on iCloud will not be uploaded to the Immich server", + "ignore_icloud_photos": "ignorar fotos no iCloud", + "ignore_icloud_photos_description": "Fotos que estão armazenadas no iCloud não serão carregadas para o servidor do Immich", "image_saved_successfully": "Imagem salva", "image_viewer_page_state_provider_download_error": "Erro ao baixar", "image_viewer_page_state_provider_download_started": "Baixando arquivo", @@ -283,7 +302,7 @@ "image_viewer_page_state_provider_share_error": "Erro ao compartilhar", "invalid_date": "Data inválida", "invalid_date_format": "Formato de data inválido", - "library": "Library", + "library": "Biblioteca", "library_page_albums": "Álbuns", "library_page_archive": "Arquivado", "library_page_device_albums": "Álbuns no dispositivo", @@ -296,6 +315,10 @@ "library_page_sort_most_oldest_photo": "Foto mais antiga", "library_page_sort_most_recent_photo": "Foto mais recente", "library_page_sort_title": "Título do álbum", + "local_network": "Local network", + "local_network_sheet_info": "The app will connect to the server through this URL when using the specified Wi-Fi network", + "location_permission": "Location permission", + "location_permission_content": "In order to use the auto-switching feature, Immich needs precise location permission so it can read the current WiFi network's name", "location_picker_choose_on_map": "Escolha no mapa", "location_picker_latitude": "Latitude", "location_picker_latitude_error": "Digite uma latitude válida", @@ -364,7 +387,9 @@ "motion_photos_page_title": "Fotos com movimento", "multiselect_grid_edit_date_time_err_read_only": "Não é possível editar a data de arquivo só leitura, ignorando", "multiselect_grid_edit_gps_err_read_only": "Não é possível editar a localização de arquivo só leitura, ignorando", - "my_albums": "My albums", + "my_albums": "Meus álbuns", + "networking_settings": "Networking", + "networking_subtitle": "Manage the server endpoint settings", "no_assets_to_show": "Não há arquivos para exibir", "no_name": "Sem nome", "notification_permission_dialog_cancel": "Cancelar", @@ -373,7 +398,7 @@ "notification_permission_list_tile_content": "Dar permissões para ativar notificações", "notification_permission_list_tile_enable_button": "Ativar notificações", "notification_permission_list_tile_title": "Permissão de notificações", - "on_this_device": "On this device", + "on_this_device": "Neste dispositivo", "partner_list_user_photos": "Fotos de {user}", "partner_list_view_all": "Ver tudo", "partner_page_add_partner": "Adicionar parceiro", @@ -385,8 +410,8 @@ "partner_page_stop_sharing_content": "{} não poderá mais acessar as suas fotos.", "partner_page_stop_sharing_title": "Parar de compartilhar as suas fotos?", "partner_page_title": "Parceiro", - "partners": "Partners", - "people": "People", + "partners": "Parceiros", + "people": "Pessoas", "permission_onboarding_back": "Voltar", "permission_onboarding_continue_anyway": "Continuar mesmo assim", "permission_onboarding_get_started": "Começar", @@ -397,7 +422,8 @@ "permission_onboarding_permission_granted": "Permissão concedida! Está tudo pronto.", "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.", - "places": "Places", + "places": "Lugares", + "preferences_settings_subtitle": "Manage the app's preferences", "preferences_settings_title": "Preferências", "profile_drawer_app_logs": "Logs", "profile_drawer_client_out_of_date_major": "O aplicativo está desatualizado. Por favor, atualize para a versão mais recente.", @@ -410,11 +436,12 @@ "profile_drawer_settings": "Configurações", "profile_drawer_sign_out": "Sair", "profile_drawer_trash": "Lixeira", - "recently_added": "Recently added", + "recently_added": "Adicionados Recentemente", "recently_added_page_title": "Adicionado recentemente", + "save": "Save", "save_to_gallery": "Salvar na galeria", "scaffold_body_error_occurred": "Ocorreu um erro", - "search_albums": "Search albums", + "search_albums": "Pesquisar Álbuns", "search_bar_hint": "Pesquisar em suas fotos", "search_filter_apply": "Aplicar filtro", "search_filter_camera": "Câmera", @@ -457,6 +484,7 @@ "search_page_places": "Locais", "search_page_recently_added": "Adicionado recentemente", "search_page_screenshots": "Capturas de tela", + "search_page_search_photos_videos": "Search for your photos and videos", "search_page_selfies": "Selfies", "search_page_things": "Objetos", "search_page_videos": "Vídeos", @@ -469,6 +497,7 @@ "select_additional_user_for_sharing_page_suggestions": "Sugestões", "select_user_for_sharing_page_err_album": "Falha ao criar o álbum", "select_user_for_sharing_page_share_suggestions": "Sugestões", + "server_endpoint": "Server Endpoint", "server_info_box_app_version": "Versão do app", "server_info_box_latest_release": "Versão mais recente", "server_info_box_server_url": "URL do servidor", @@ -480,6 +509,7 @@ "setting_image_viewer_preview_title": "Carregar imagem de pré-visualização", "setting_image_viewer_title": "Imagens", "setting_languages_apply": "Aplicar", + "setting_languages_subtitle": "Change the app's language", "setting_languages_title": "Idioma", "setting_notifications_notify_failures_grace_period": "Notifique falhas de backup em segundo plano: {}", "setting_notifications_notify_hours": "{} horas", @@ -560,9 +590,9 @@ "shared_link_info_chip_upload": "Enviar", "shared_link_manage_links": "Gerenciar links compartilhados", "shared_link_public_album": "Álbum público", - "shared_links": "Shared links", + "shared_links": "Links compartilhados", "share_done": "Feito", - "shared_with_me": "Shared with me", + "shared_with_me": "Compartilhado comigo", "share_invite": "Convidar para o álbum", "sharing_page_album": "Álbuns compartilhados", "sharing_page_description": "Crie álbuns compartilhados para compartilhar fotos e vídeos com pessoas da sua rede.", @@ -594,7 +624,7 @@ "theme_setting_three_stage_loading_subtitle": "O carregamento em três estágios pode aumentar o desempenho do carregamento, mas causa uma carga de rede significativamente maior", "theme_setting_three_stage_loading_title": "Habilitar carregamento em três estágios", "translated_text_options": "Opções", - "trash": "Trash", + "trash": "Lixo", "trash_emptied": "Lixeira esvaziada", "trash_page_delete": "Excluir", "trash_page_delete_all": "Excluir tudo", @@ -612,14 +642,18 @@ "upload_dialog_info": "Deseja fazer o backup dos arquivos selecionados no servidor?", "upload_dialog_ok": "Enviar", "upload_dialog_title": "Enviar arquivo", + "use_current_connection": "use current connection", + "validate_endpoint_error": "Please enter a valid URL", "version_announcement_overlay_ack": "Entendi", "version_announcement_overlay_release_notes": "notas da versão", "version_announcement_overlay_text_1": "Olá, há um novo lançamento de", "version_announcement_overlay_text_2": "por favor, Verifique com calma as ", "version_announcement_overlay_text_3": "e certifique-se de que a configuração do docker-compose e do arquivo .env estejam atualizadas para evitar configurações incorretas, especialmente se utiliza o WatchTower ou qualquer outro mecanismo que faça atualização automática do servidor.", "version_announcement_overlay_title": "Nova versão do servidor disponível \uD83C\uDF89", - "videos": "Videos", + "videos": "Vídeos", "viewer_remove_from_stack": "Remover da pilha", "viewer_stack_use_as_main_asset": "Usar como foto principal", - "viewer_unstack": "Desempilhar" + "viewer_unstack": "Desempilhar", + "wifi_name": "WiFi Name", + "your_wifi_name": "Your WiFi name" } \ No newline at end of file diff --git a/mobile/assets/i18n/ro-RO.json b/mobile/assets/i18n/ro-RO.json index 255940263320e..571956e4d812a 100644 --- a/mobile/assets/i18n/ro-RO.json +++ b/mobile/assets/i18n/ro-RO.json @@ -7,6 +7,7 @@ "action_common_select": "Select", "action_common_update": "Actualizează", "add_a_name": "Add a name", + "add_endpoint": "Add endpoint", "add_to_album_bottom_sheet_added": "Adăugat în {album}", "add_to_album_bottom_sheet_already_exists": "Deja în {album}", "advanced_settings_log_level_title": "Nivel log: {}", @@ -65,7 +66,12 @@ "assets_restored_successfully": "{} asset(s) restored successfully", "assets_trashed": "{} asset(s) trashed", "assets_trashed_from_server": "{} asset(s) trashed from the Immich server", + "asset_viewer_settings_subtitle": "Manage your gallery viewer settings", "asset_viewer_settings_title": "Asset Viewer", + "automatic_endpoint_switching_subtitle": "Connect locally over designated Wi-Fi when available and use alternative connections elsewhere", + "automatic_endpoint_switching_title": "Automatic URL switching", + "background_location_permission": "Background location permission", + "background_location_permission_content": "In order to switch networks when running in the background, Immich must *always* have precise location access so the app can read the Wi-Fi network's name", "backup_album_selection_page_albums_device": "Albume în dispozitiv ({})", "backup_album_selection_page_albums_tap": "Apasă odata pentru a include, de două ori pentru a exclude", "backup_album_selection_page_assets_scatter": "Resursele pot fi împrăștiate în mai multe albume. Prin urmare, albumele pot fi incluse sau excluse în timpul procesului de backup.", @@ -131,6 +137,7 @@ "backup_manual_success": "Succes", "backup_manual_title": "Status încărcare", "backup_options_page_title": "Backup options", + "backup_setting_subtitle": "Manage background and foreground upload settings", "cache_settings_album_thumbnails": "Miniaturi pagină galerie ({} resurse)", "cache_settings_clear_cache_button": "Șterge cache", "cache_settings_clear_cache_button_title": "Șterge memoria cache a aplicatiei. Performanța aplicației va fi semnificativ afectată până când va fi reconstruită.", @@ -149,11 +156,16 @@ "cache_settings_tile_subtitle": "Controlează modul stocării locale", "cache_settings_tile_title": "Stocare locală", "cache_settings_title": "Setări pentru memoria cache", + "cancel": "Cancel", + "change_display_order": "Change display order", "change_password_form_confirm_password": "Confirmă parola", "change_password_form_description": "Salut {name},\n\nAceasta este fie prima dată când te conectazi la sistem, fie s-a făcut o cerere pentru schimbarea parolei. Te rugăm să introduci noua parolă mai jos.", "change_password_form_new_password": "Parolă nouă", "change_password_form_password_mismatch": "Parolele nu se potrivesc", "change_password_form_reenter_new_password": "Reintrodu noua parolă", + "check_corrupt_asset_backup": "Check for corrupt asset backups", + "check_corrupt_asset_backup_button": "Perform check", + "check_corrupt_asset_backup_description": "Run this check only over Wi-Fi and once all assets have been backed-up. The procedure might take a few minutes.", "client_cert_dialog_msg_confirm": "OK", "client_cert_enter_password": "Enter Password", "client_cert_import": "Import", @@ -199,6 +211,7 @@ "crop": "Crop", "curated_location_page_title": "Locuri", "curated_object_page_title": "Obiecte", + "current_server_address": "Current server address", "daily_title_text_date": "E, MMM dd", "daily_title_text_date_year": "E, MMM dd, yyyy", "date_format": "E, LLL d, y • h:mm a", @@ -235,6 +248,8 @@ "edit_date_time_dialog_timezone": "Fus orar", "edit_image_title": "Edit", "edit_location_dialog_title": "Locație", + "enter_wifi_name": "Enter WiFi name", + "error_change_sort_album": "Failed to change album sort order", "error_saving_image": "Error: {}", "exif_bottom_sheet_description": "Adaugă Descriere...", "exif_bottom_sheet_details": "DETALII", @@ -246,11 +261,15 @@ "experimental_settings_new_asset_list_title": "Activează grila experimentală de fotografii.", "experimental_settings_subtitle": "Folosește pe propria răspundere!", "experimental_settings_title": "Experimental", + "external_network": "External network", + "external_network_sheet_info": "When not on the preferred WiFi network, the app will connect to the server through the first of the below URLs it can reach, starting from top to bottom", "favorites": "Favorites", "favorites_page_no_favorites": "Nu au fost găsite resurse favorite", "favorites_page_title": "Favorite", "filename_search": "File name or extension", "filter": "Filter", + "get_wifiname_error": "Could not get Wi-Fi name. Make sure you have granted the necessary permissions and are connected to a Wi-Fi network", + "grant_permission": "Grant permission", "haptic_feedback_switch": "Enable haptic feedback", "haptic_feedback_title": "Haptic Feedback", "header_settings_add_header_tip": "Add Header", @@ -296,6 +315,10 @@ "library_page_sort_most_oldest_photo": "Cea mai veche fotografie", "library_page_sort_most_recent_photo": "Cea mai recentă fotografie", "library_page_sort_title": "Titlu album", + "local_network": "Local network", + "local_network_sheet_info": "The app will connect to the server through this URL when using the specified Wi-Fi network", + "location_permission": "Location permission", + "location_permission_content": "In order to use the auto-switching feature, Immich needs precise location permission so it can read the current WiFi network's name", "location_picker_choose_on_map": "Alege pe hartă", "location_picker_latitude": "Latitudine", "location_picker_latitude_error": "Introdu o latitudine validă", @@ -365,6 +388,8 @@ "multiselect_grid_edit_date_time_err_read_only": "Nu se poate edita data fișierului(lor) cu permisiuni doar pentru citire, omitere", "multiselect_grid_edit_gps_err_read_only": "Nu se poate edita locația fișierului(lor) cu permisiuni doar pentru citire, omitere", "my_albums": "My albums", + "networking_settings": "Networking", + "networking_subtitle": "Manage the server endpoint settings", "no_assets_to_show": "No assets to show", "no_name": "No name", "notification_permission_dialog_cancel": "Anulează", @@ -398,6 +423,7 @@ "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.", "places": "Places", + "preferences_settings_subtitle": "Manage the app's preferences", "preferences_settings_title": "Preferences", "profile_drawer_app_logs": "Log-uri", "profile_drawer_client_out_of_date_major": "Aplicația nu folosește ultima versiune. Te rugăm să actulizezi la ultima versiune majoră.", @@ -412,6 +438,7 @@ "profile_drawer_trash": "Coș", "recently_added": "Recently added", "recently_added_page_title": "Adăugate recent", + "save": "Save", "save_to_gallery": "Save to gallery", "scaffold_body_error_occurred": "A apărut o eroare", "search_albums": "Search albums", @@ -457,6 +484,7 @@ "search_page_places": "Locuri", "search_page_recently_added": "Adăugate recent", "search_page_screenshots": "Capturi de ecran", + "search_page_search_photos_videos": "Search for your photos and videos", "search_page_selfies": "Selfie-uri", "search_page_things": "Obiecte", "search_page_videos": "Videoclipuri", @@ -469,6 +497,7 @@ "select_additional_user_for_sharing_page_suggestions": "Sugestii", "select_user_for_sharing_page_err_album": "Creare album eșuată", "select_user_for_sharing_page_share_suggestions": "Sugestii", + "server_endpoint": "Server Endpoint", "server_info_box_app_version": "Versiune Aplicatie", "server_info_box_latest_release": "Ultima versiune", "server_info_box_server_url": "URL-ul server-ului", @@ -480,6 +509,7 @@ "setting_image_viewer_preview_title": "Încarcă imaginea de previzualizare", "setting_image_viewer_title": "Images", "setting_languages_apply": "Apply", + "setting_languages_subtitle": "Change the app's language", "setting_languages_title": "Languages", "setting_notifications_notify_failures_grace_period": "Notificare eșuări backup în fundal: {}", "setting_notifications_notify_hours": "{} ore", @@ -612,6 +642,8 @@ "upload_dialog_info": "Vrei să backup resursele selectate pe server?", "upload_dialog_ok": "Incarcă", "upload_dialog_title": "Încarcă resursă", + "use_current_connection": "use current connection", + "validate_endpoint_error": "Please enter a valid URL", "version_announcement_overlay_ack": "Confirm", "version_announcement_overlay_release_notes": "informații update", "version_announcement_overlay_text_1": "Salut, există un update nou pentru", @@ -621,5 +653,7 @@ "videos": "Videos", "viewer_remove_from_stack": "Șterge din grup", "viewer_stack_use_as_main_asset": "Folosește ca resursă principală", - "viewer_unstack": "Anulează grup" + "viewer_unstack": "Anulează grup", + "wifi_name": "WiFi Name", + "your_wifi_name": "Your WiFi name" } \ No newline at end of file diff --git a/mobile/assets/i18n/ru-RU.json b/mobile/assets/i18n/ru-RU.json index 80e0611d3f7e0..92d24b6a413cb 100644 --- a/mobile/assets/i18n/ru-RU.json +++ b/mobile/assets/i18n/ru-RU.json @@ -6,45 +6,46 @@ "action_common_save": "Сохранить", "action_common_select": "Выбрать", "action_common_update": "Обновить", - "add_a_name": "Add a name", + "add_a_name": "Добавить имя", + "add_endpoint": "Add endpoint", "add_to_album_bottom_sheet_added": "Добавлено в {album}", "add_to_album_bottom_sheet_already_exists": "Уже в {album}", - "advanced_settings_log_level_title": "Log level: {}", - "advanced_settings_prefer_remote_subtitle": "Некоторые устройства очень медленно загружают предпросмотр объектов, находящихся на устройстве. Активируйте эту настройку, чтобы вместо них загружались изображения с сервера.", + "advanced_settings_log_level_title": "Уровень логирования:", + "advanced_settings_prefer_remote_subtitle": "Некоторые устройства очень медленно загружают локальные изображения. Активируйте эту настройку, чтобы изображения всегда загружались с сервера.", "advanced_settings_prefer_remote_title": "Предпочитать фото на сервере", "advanced_settings_proxy_headers_subtitle": "Определите заголовки прокси-сервера, которые Immich должен отправлять с каждым сетевым запросом.", - "advanced_settings_proxy_headers_title": "Прокси-заголовки", - "advanced_settings_self_signed_ssl_subtitle": "Пропускает проверку SSL-сертификата сервера. Требуется для самоподписанных сертификатов.", + "advanced_settings_proxy_headers_title": "Заголовки прокси", + "advanced_settings_self_signed_ssl_subtitle": "Пропускать проверку SSL-сертификата сервера. Требуется для самоподписанных сертификатов.", "advanced_settings_self_signed_ssl_title": "Разрешить самоподписанные SSL-сертификаты", - "advanced_settings_tile_subtitle": "Расширенные настройки пользователя", + "advanced_settings_tile_subtitle": "Расширенные настройки", "advanced_settings_tile_title": "Расширенные", "advanced_settings_troubleshooting_subtitle": "Включить расширенные возможности для решения проблем", "advanced_settings_troubleshooting_title": "Решение проблем", "album_info_card_backup_album_excluded": "ИСКЛЮЧЕН", "album_info_card_backup_album_included": "ВКЛЮЧЕН", - "albums": "Albums", - "album_thumbnail_card_item": "1 объект", - "album_thumbnail_card_items": "{} объектов", + "albums": "Альбомы", + "album_thumbnail_card_item": "1 элемент", + "album_thumbnail_card_items": "{} элементов", "album_thumbnail_card_shared": "· Общий", "album_thumbnail_owned": "Автор", "album_thumbnail_shared_by": "Поделился {}", - "album_viewer_appbar_delete_confirm": "Вы уверены, что хотите удалить этот альбом из своей учетной записи?", + "album_viewer_appbar_delete_confirm": "Вы уверены, что хотите удалить альбом из своей учетной записи?", "album_viewer_appbar_share_delete": "Удалить альбом", - "album_viewer_appbar_share_err_delete": "Невозможно удалить альбом", - "album_viewer_appbar_share_err_leave": "Невозможно покинуть альбом", + "album_viewer_appbar_share_err_delete": "Не удалось удалить альбом", + "album_viewer_appbar_share_err_leave": "Не удалось покинуть альбом", "album_viewer_appbar_share_err_remove": "Возникли проблемы с удалением объектов из альбома", - "album_viewer_appbar_share_err_title": "Ошибка переименования альбома", + "album_viewer_appbar_share_err_title": "Не удалось переименовать альбом", "album_viewer_appbar_share_leave": "Покинуть альбом", "album_viewer_appbar_share_remove": "Удалить из альбома", "album_viewer_appbar_share_to": "Поделиться", "album_viewer_page_share_add_users": "Добавить пользователей", - "all": "All", + "all": "Все", "all_people_page_title": "Люди", "all_videos_page_title": "Видео", - "app_bar_signout_dialog_content": "Вы уверены, что хотите выйти из системы?", + "app_bar_signout_dialog_content": "Вы уверены, что хотите выйти?", "app_bar_signout_dialog_ok": "Да", - "app_bar_signout_dialog_title": "Выйти из системы", - "archived": "Archived", + "app_bar_signout_dialog_title": "Выйти", + "archived": "Архив", "archive_page_no_archived_assets": "В архиве сейчас пусто", "archive_page_title": "Архив ({})", "asset_action_delete_err_read_only": "Невозможно удалить объект(ы) только для чтения, пропуск...", @@ -52,11 +53,11 @@ "asset_list_group_by_sub_title": "Группировать по", "asset_list_layout_settings_dynamic_layout_title": "Динамическое расположение", "asset_list_layout_settings_group_automatically": "Автоматически", - "asset_list_layout_settings_group_by": "Группировать объекты по:", + "asset_list_layout_settings_group_by": "Группировать объекты по", "asset_list_layout_settings_group_by_month": "Месяцу", "asset_list_layout_settings_group_by_month_day": "Месяцу и дню", "asset_list_layout_sub_title": "Разметка", - "asset_list_settings_subtitle": "Настройка макета сетки фотографий", + "asset_list_settings_subtitle": "Настройка сетки фотографий", "asset_list_settings_title": "Сетка фотографий", "asset_restored_successfully": "Объект успешно восстановлен", "assets_deleted_permanently": "{} объект(ы) удален(ы) навсегда", @@ -65,11 +66,16 @@ "assets_restored_successfully": "{} объект(ы) успешно восстановлен(ы)", "assets_trashed": "{} объект(ы) помещен(ы) в корзину", "assets_trashed_from_server": "{} объект(ы) помещен(ы) в корзину на сервере Immich", - "asset_viewer_settings_title": "Просмотрщик изображений", - "backup_album_selection_page_albums_device": "Альбомов на устройстве ({})", + "asset_viewer_settings_subtitle": "Manage your gallery viewer settings", + "asset_viewer_settings_title": "Просмотр изображений", + "automatic_endpoint_switching_subtitle": "Connect locally over designated Wi-Fi when available and use alternative connections elsewhere", + "automatic_endpoint_switching_title": "Automatic URL switching", + "background_location_permission": "Background location permission", + "background_location_permission_content": "In order to switch networks when running in the background, Immich must *always* have precise location access so the app can read the Wi-Fi network's name", + "backup_album_selection_page_albums_device": "Альбомы на устройстве ({})", "backup_album_selection_page_albums_tap": "Нажмите, чтобы включить,\nнажмите дважды, чтобы исключить", - "backup_album_selection_page_assets_scatter": "Объекты могут быть разбросаны по нескольким альбомам. Таким образом, альбомы могут быть включены или исключены из процесса резервного копирования.", - "backup_album_selection_page_select_albums": "Выбрать альбомы", + "backup_album_selection_page_assets_scatter": "Ваши изображения и видео могут находиться в разных альбомах. Вы можете выбрать, какие альбомы включить, а какие исключить из резервного копирования.", + "backup_album_selection_page_select_albums": "Выбор альбомов", "backup_album_selection_page_selection_info": "Информация о выборе", "backup_album_selection_page_total_assets": "Всего уникальных объектов", "backup_all": "Все", @@ -81,11 +87,11 @@ "backup_background_service_in_progress_notification": "Резервное копирование ваших объектов…", "backup_background_service_upload_failure_notification": "Ошибка загрузки {}", "backup_controller_page_albums": "Резервное копирование альбомов", - "backup_controller_page_background_app_refresh_disabled_content": "Включите фоновое обновление приложений в меню Настройки > Общие > Фоновое обновление приложений, чтобы использовать фоновое резервное копирование.", + "backup_controller_page_background_app_refresh_disabled_content": "Включите фоновое обновление приложения в Настройки > Общие > Фоновое обновление приложений, чтобы использовать фоновое резервное копирование.", "backup_controller_page_background_app_refresh_disabled_title": "Фоновое обновление отключено", "backup_controller_page_background_app_refresh_enable_button_text": "Перейти в настройки", - "backup_controller_page_background_battery_info_link": "Показать как", - "backup_controller_page_background_battery_info_message": "Для наилучшего фонового резервного копирования отключите любые настройки оптимизации батареи, ограничивающие фоновую активность для Immich.\n\nПоскольку это зависит от устройства, найдите необходимую информацию для производителя вашего устройства.", + "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": "Только во время зарядки", @@ -102,7 +108,7 @@ "backup_controller_page_backup_sub": "Загруженные фото и видео", "backup_controller_page_cancel": "Отмена", "backup_controller_page_created": "Создано: {}", - "backup_controller_page_desc_backup": "Включите резервное копирование в активном режиме, чтобы автоматически загружать новые объекты на сервер при открытии приложения.", + "backup_controller_page_desc_backup": "Включите резервное копирование в активном режиме, чтобы автоматически загружать новые объекты при открытии приложения.", "backup_controller_page_excluded": "Исключены:", "backup_controller_page_failed": "Неудачных ({})", "backup_controller_page_filename": "Имя файла: {} [{}]", @@ -110,7 +116,7 @@ "backup_controller_page_info": "Информация о резервном копировании", "backup_controller_page_none_selected": "Ничего не выбрано", "backup_controller_page_remainder": "Осталось", - "backup_controller_page_remainder_sub": "Оставшиеся фото и видео для резервного копирования из выбранного", + "backup_controller_page_remainder_sub": "Фото и видео для загрузки", "backup_controller_page_select": "Выбор", "backup_controller_page_server_storage": "Хранилище на сервере", "backup_controller_page_start_backup": "Начать резервное копирование", @@ -120,20 +126,21 @@ "backup_controller_page_to_backup": "Альбомы для резервного копирования", "backup_controller_page_total": "Всего", "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_info_card_assets": "объектов", "backup_manual_cancelled": "Отменено", "backup_manual_failed": "Неудачно", - "backup_manual_in_progress": "Загрузка уже в процессе, попробуйте позже", + "backup_manual_in_progress": "Загрузка в процессе. Попробуйте позже", "backup_manual_success": "Успешно", "backup_manual_title": "Статус загрузки", "backup_options_page_title": "Резервное копирование", + "backup_setting_subtitle": "Manage background and foreground upload settings", "cache_settings_album_thumbnails": "Миниатюры страниц библиотеки ({} объектов)", "cache_settings_clear_cache_button": "Очистить кэш", - "cache_settings_clear_cache_button_title": "Очищает кэш приложения. Это значительно повлияет на производительность приложения, до тех пор, пока кэш не будет перестроен заново.", + "cache_settings_clear_cache_button_title": "Очищает кэш приложения. Это негативно повлияет на производительность, пока кэш не будет создан заново.", "cache_settings_duplicated_assets_clear_button": "ОЧИСТИТЬ", "cache_settings_duplicated_assets_subtitle": "Фото и видео, занесенные приложением в черный список", "cache_settings_duplicated_assets_title": "Дублирующиеся объекты ({})", @@ -144,16 +151,21 @@ "cache_settings_statistics_shared": "Миниатюры общих альбомов", "cache_settings_statistics_thumbnail": "Миниатюры", "cache_settings_statistics_title": "Размер кэша", - "cache_settings_subtitle": "Управление кэшированием мобильного приложения Immich", - "cache_settings_thumbnail_size": "Размер кэша эскизов ({} объектов)", - "cache_settings_tile_subtitle": "Управление поведением локального хранилища", + "cache_settings_subtitle": "Управление кэшированием мобильного приложения", + "cache_settings_thumbnail_size": "Размер кэша миниатюр ({} объектов)", + "cache_settings_tile_subtitle": "Управление локальным хранилищем", "cache_settings_tile_title": "Локальное хранилище", "cache_settings_title": "Настройки кэширования", + "cancel": "Cancel", + "change_display_order": "Change display order", "change_password_form_confirm_password": "Подтвердите пароль", - "change_password_form_description": "Привет {name},\n\nЭто либо ваш первый вход в систему, либо был сделан запрос на смену пароля. Пожалуйста, введите новый пароль ниже.", + "change_password_form_description": "Привет, {name}!\n\nЛибо ваш первый вход в систему, либо вы запросили смену пароля. Пожалуйста, введите новый пароль ниже.", "change_password_form_new_password": "Новый пароль", "change_password_form_password_mismatch": "Пароли не совпадают", "change_password_form_reenter_new_password": "Повторно введите новый пароль", + "check_corrupt_asset_backup": "Check for corrupt asset backups", + "check_corrupt_asset_backup_button": "Perform check", + "check_corrupt_asset_backup_description": "Run this check only over Wi-Fi and once all assets have been backed-up. The procedure might take a few minutes.", "client_cert_dialog_msg_confirm": "OK", "client_cert_enter_password": "Введите пароль", "client_cert_import": "Импорт", @@ -161,7 +173,7 @@ "client_cert_invalid_msg": "Неверный файл сертификата или неверный пароль", "client_cert_remove": "Удалить", "client_cert_remove_msg": "Клиентский сертификат удален", - "client_cert_subtitle": "Поддерживается только формат PKCS12 (.p12, .pfx). Импорт/удаление сертификата доступно только перед входом в систему.", + "client_cert_subtitle": "Поддерживается только формат PKCS12 (.p12, .pfx). Импорт/удаление сертификата доступно только перед входом в систему", "client_cert_title": "Клиентский SSL-сертификат ", "common_add_to_album": "Добавить в альбом", "common_change_password": "Изменить пароль", @@ -170,41 +182,42 @@ "common_shared": "Общие", "contextual_search": "Восход солнца на пляже", "control_bottom_app_bar_add_to_album": "Добавить в альбом", - "control_bottom_app_bar_album_info": "{} файлов", - "control_bottom_app_bar_album_info_shared": "{} файлов · Общий", + "control_bottom_app_bar_album_info": "{} элементов", + "control_bottom_app_bar_album_info_shared": "{} элементов · Общий", "control_bottom_app_bar_archive": "Архив", - "control_bottom_app_bar_create_new_album": "Создать новый альбом", + "control_bottom_app_bar_create_new_album": "Создать альбом", "control_bottom_app_bar_delete": "Удалить", "control_bottom_app_bar_delete_from_immich": "Удалить из Immich\n", "control_bottom_app_bar_delete_from_local": "Удалить с устройства", "control_bottom_app_bar_download": "Скачать", - "control_bottom_app_bar_edit": "Редактировать", - "control_bottom_app_bar_edit_location": "Редактировать местоположение", - "control_bottom_app_bar_edit_time": "Редактировать дату и время", + "control_bottom_app_bar_edit": "Изменить", + "control_bottom_app_bar_edit_location": "Изменить место", + "control_bottom_app_bar_edit_time": "Изменить дату", "control_bottom_app_bar_favorite": "В избранное", "control_bottom_app_bar_share": "Поделиться", "control_bottom_app_bar_share_to": "Поделиться", "control_bottom_app_bar_stack": "Стек", - "control_bottom_app_bar_trash_from_immich": "Переместить в корзину", + "control_bottom_app_bar_trash_from_immich": "В корзину", "control_bottom_app_bar_unarchive": "Восстановить", "control_bottom_app_bar_unfavorite": "Удалить из избранного", "control_bottom_app_bar_upload": "Загрузить", - "create_album": "Create album", + "create_album": "Создать альбом", "create_album_page_untitled": "Без названия", - "create_new": "CREATE NEW", + "create_new": "СОЗДАТЬ НОВЫЙ", "create_shared_album_page_create": "Создать", "create_shared_album_page_share": "Поделиться", "create_shared_album_page_share_add_assets": "ДОБАВИТЬ ОБЪЕКТЫ", - "create_shared_album_page_share_select_photos": "Выберите фотографии", - "crop": "Кадрировать", + "create_shared_album_page_share_select_photos": "Выбрать фотографии", + "crop": "Обрезать", "curated_location_page_title": "Места", "curated_object_page_title": "Предметы", + "current_server_address": "Current server address", "daily_title_text_date": "E, MMM dd", "daily_title_text_date_year": "E, MMM dd, yyyy", "date_format": "E, LLL d, y • h:mm a", - "delete_dialog_alert": "Эти элементы будут безвозвратно удалены с сервера Immich, а также с вашего устройства", - "delete_dialog_alert_local": "Эти объекты будут безвозвратно удалены с Вашего устройства, но по-прежнему будут доступны на сервере Immich", - "delete_dialog_alert_local_non_backed_up": "Резервные копии некоторых объектов не были загружены в Immich и будут безвозвратно удалены с Вашего устройства", + "delete_dialog_alert": "Эти элементы будут безвозвратно удалены с сервера, а также с вашего устройства", + "delete_dialog_alert_local": "Эти объекты будут безвозвратно удалены с вашего устройства, но по-прежнему будут доступны на сервере Immich", + "delete_dialog_alert_local_non_backed_up": "Резервные копии некоторых объектов не были загружены в Immich и будут безвозвратно удалены с вашего устройства", "delete_dialog_alert_remote": "Эти объекты будут безвозвратно удалены с сервера Immich", "delete_dialog_cancel": "Отменить", "delete_dialog_ok": "Удалить", @@ -212,8 +225,8 @@ "delete_dialog_title": "Удалить навсегда", "delete_local_dialog_ok_backed_up_only": "Удалить только резервные копии", "delete_local_dialog_ok_force": "Все равно удалить", - "delete_shared_link_dialog_content": "Вы уверены, что хотите удалить эту общую ссылку?", - "delete_shared_link_dialog_title": "Удалить общую ссылку", + "delete_shared_link_dialog_content": "Вы уверены, что хотите удалить публичную ссылку?", + "delete_shared_link_dialog_title": "Удалить публичную ссылку", "description_input_hint_text": "Добавить описание...", "description_input_submit_error": "Не удалось обновить описание, проверьте логи, чтобы узнать причину", "download_canceled": "Загрузка отменена", @@ -225,7 +238,7 @@ "download_finished": "Загрузка окончена", "downloading": "Загрузка...", "downloading_media": "Загрузка медиа", - "download_notfound": "Загрузка не обнаружена", + "download_notfound": "Загрузка не найдена", "download_paused": "Загрузка приостановлена", "download_started": "Загрузка началась", "download_sucess": "Успешная загрузка", @@ -235,22 +248,28 @@ "edit_date_time_dialog_timezone": "Часовой пояс", "edit_image_title": "Редактировать", "edit_location_dialog_title": "Местоположение", + "enter_wifi_name": "Enter WiFi name", + "error_change_sort_album": "Failed to change album sort order", "error_saving_image": "Ошибка: {}", "exif_bottom_sheet_description": "Добавить описание...", "exif_bottom_sheet_details": "ПОДРОБНОСТИ", - "exif_bottom_sheet_location": "Местоположение", - "exif_bottom_sheet_location_add": "Добавить местоположение", + "exif_bottom_sheet_location": "МЕСТО", + "exif_bottom_sheet_location_add": "Добавить место", "exif_bottom_sheet_people": "ЛЮДИ", "exif_bottom_sheet_person_add_person": "Добавить имя", - "experimental_settings_new_asset_list_subtitle": "Ведутся работы", + "experimental_settings_new_asset_list_subtitle": "В разработке", "experimental_settings_new_asset_list_title": "Включить экспериментальную сетку фотографий", "experimental_settings_subtitle": "Используйте на свой страх и риск!", "experimental_settings_title": "Экспериментальные функции", - "favorites": "Favorites", + "external_network": "External network", + "external_network_sheet_info": "When not on the preferred WiFi network, the app will connect to the server through the first of the below URLs it can reach, starting from top to bottom", + "favorites": "Избранное", "favorites_page_no_favorites": "В избранном сейчас пусто", "favorites_page_title": "Избранное", "filename_search": "Имя или расширение файла", "filter": "Фильтр", + "get_wifiname_error": "Could not get Wi-Fi name. Make sure you have granted the necessary permissions and are connected to a Wi-Fi network", + "grant_permission": "Grant permission", "haptic_feedback_switch": "Включить тактильную отдачу", "haptic_feedback_title": "Тактильная отдача", "header_settings_add_header_tip": "Добавить заголовок", @@ -258,24 +277,24 @@ "header_settings_header_name_input": "Имя заголовка", "header_settings_header_value_input": "Значение заголовка", "header_settings_page_title": "Прокси-заголовки", - "headers_settings_tile_subtitle": "Определите заголовки прокси, которые приложение должно отправлять с каждым сетевым запросом.", + "headers_settings_tile_subtitle": "Определите заголовки прокси, которые приложение должно отправлять с каждым сетевым запросом", "headers_settings_tile_title": "Пользовательские заголовки прокси", - "home_page_add_to_album_conflicts": "Добавлено {added} объектов в альбом {album}. Объекты {failed} уже есть в альбоме.", - "home_page_add_to_album_err_local": "Пока нельзя добавлять локальные объекты в альбомы, пропускаем", - "home_page_add_to_album_success": "Добавлено {added} объектов в альбом {album}.", - "home_page_album_err_partner": "Пока не удается добавить объекты партнера в альбом, пропуск...", - "home_page_archive_err_local": "Пока невозможно добавить локальные объекты в архив, пропускаем", - "home_page_archive_err_partner": "Невозможно архивировать объекты партнера, пропуск...", + "home_page_add_to_album_conflicts": "Добавлено {added} медиа в альбом {album}. {failed} медиа уже в альбоме.", + "home_page_add_to_album_err_local": "Пока нельзя добавлять локальные объекты в альбомы, пропуск", + "home_page_add_to_album_success": "Добавлено {added} медиа в альбом {album}.", + "home_page_album_err_partner": "Пока нельзя добавить медиа партнера в альбом, пропуск", + "home_page_archive_err_local": "Пока нельзя добавить локальные файлы в архив, пропуск", + "home_page_archive_err_partner": "Невозможно архивировать медиа партнера, пропуск", "home_page_building_timeline": "Построение хронологии", - "home_page_delete_err_partner": "Невозможно удалить объекты партнера, пропуск...", - "home_page_delete_remote_err_local": "Локальные объект(ы) уже в процессе удаления с сервера, пропуск...", - "home_page_favorite_err_local": "Пока не удается добавить в избранное локальные объекты, пропуск...", - "home_page_favorite_err_partner": "Пока не удается добавить в избранное объекты партнера, пропуск...", - "home_page_first_time_notice": "Если вы используете приложение впервые, убедитесь, что вы выбрали резервный(е) альбом(ы), чтобы временная шкала могла заполнить фотографии и видео в альбоме(ах).", - "home_page_share_err_local": "Невозможно поделиться локальными данными по ссылке, пропуск...", - "home_page_upload_err_limit": "Вы можете выгрузить максимум 30 файлов за раз", - "ignore_icloud_photos": "Ignore iCloud photos", - "ignore_icloud_photos_description": "Photos that are stored on iCloud will not be uploaded to the Immich server", + "home_page_delete_err_partner": "Невозможно удалить медиа партнера, пропуск", + "home_page_delete_remote_err_local": "Невозможно удалить локальные файлы с сервера, пропуск", + "home_page_favorite_err_local": "Пока нельзя добавить в избранное локальные файлы, пропуск", + "home_page_favorite_err_partner": "Пока нельзя добавить в избранное медиа партнера, пропуск", + "home_page_first_time_notice": "Если вы используете приложение впервые, выберите альбомы для резервного копирования или загрузите их вручную, чтобы заполнить ими временную шкалу.", + "home_page_share_err_local": "Нельзя поделиться локальными файлами по ссылке, пропуск", + "home_page_upload_err_limit": "Вы можете загрузить максимум 30 файлов за раз, пропуск", + "ignore_icloud_photos": "Пропускать файлы из iCloud", + "ignore_icloud_photos_description": "Не загружать файлы в Immich, если они хранятся в iCloud", "image_saved_successfully": "Изображение сохранено", "image_viewer_page_state_provider_download_error": "Ошибка загрузки", "image_viewer_page_state_provider_download_started": "Загрузка началась", @@ -283,7 +302,7 @@ "image_viewer_page_state_provider_share_error": "Ошибка общего доступа", "invalid_date": "Неверная дата", "invalid_date_format": "Неверный формат даты", - "library": "Library", + "library": "Библиотека", "library_page_albums": "Альбомы", "library_page_archive": "Архив", "library_page_device_albums": "Альбомы на устройстве", @@ -293,39 +312,43 @@ "library_page_sort_asset_count": "Количество объектов", "library_page_sort_created": "Недавно созданные", "library_page_sort_last_modified": "Последнее изменение", - "library_page_sort_most_oldest_photo": "Самые старые фото", - "library_page_sort_most_recent_photo": "Самые последние фото", + "library_page_sort_most_oldest_photo": "Старые фото", + "library_page_sort_most_recent_photo": "Последние фото", "library_page_sort_title": "Название альбома", + "local_network": "Local network", + "local_network_sheet_info": "The app will connect to the server through this URL when using the specified Wi-Fi network", + "location_permission": "Location permission", + "location_permission_content": "In order to use the auto-switching feature, Immich needs precise location permission so it can read the current WiFi network's name", "location_picker_choose_on_map": "Выбрать на карте", "location_picker_latitude": "Широта", "location_picker_latitude_error": "Укажите правильную широту", - "location_picker_latitude_hint": "Укажите широту", + "location_picker_latitude_hint": "Введите широту", "location_picker_longitude": "Долгота", "location_picker_longitude_error": "Укажите правильную долготу", - "location_picker_longitude_hint": "Укажите долготу", + "location_picker_longitude_hint": "Введите долготу", "login_disabled": "Вход отключен", - "login_form_api_exception": "Ошибка при попытке взаимодействия с сервером. Проверьте URL-адрес до него и попробуйте еще раз.", + "login_form_api_exception": "Ошибка подключения к серверу. Проверьте URL-адрес и попробуйте еще раз.", "login_form_back_button_text": "Назад", "login_form_button_text": "Войти", "login_form_email_hint": "youremail@email.com", "login_form_endpoint_hint": "http://your-server-ip:port/api", "login_form_endpoint_url": "URL-aдрес сервера", - "login_form_err_http": "Пожалуйста, укажите http:// или https://", - "login_form_err_invalid_email": "Неверный адрес Email", - "login_form_err_invalid_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_failed_get_oauth_server_disable": "Авторизация через OAuth недоступна на этом сервере", + "login_form_failed_login": "Ошибка при входе, проверьте URL-адрес сервера, адрес электронной почты и пароль", + "login_form_handshake_exception": "Ошибка проверки сертификата. Если вы используете самоподписанный сертификат, включите поддержку самоподписанных сертификатов в настройках.", "login_form_label_email": "Email", "login_form_label_password": "Пароль", "login_form_next_button": "Далее", "login_form_password_hint": "пароль", "login_form_save_login": "Оставаться в системе", - "login_form_server_empty": "Введите URL-адрес вашего сервера.", - "login_form_server_error": "Нет соединения с сервером.", + "login_form_server_empty": "Введите URL-адрес сервера.", + "login_form_server_error": "Не удалось установить соединение с сервером.", "login_password_changed_error": "Произошла ошибка при обновлении пароля", "login_password_changed_success": "Пароль успешно обновлен", "map_assets_in_bound": "{} фото", @@ -334,38 +357,40 @@ "map_location_dialog_cancel": "Отмена", "map_location_dialog_yes": "Да", "map_location_picker_page_use_location": "Это местоположение", - "map_location_service_disabled_content": "Для отображения объектов в данном месте необходимо включить службу определения местоположения. Хотите включить ее сейчас?", + "map_location_service_disabled_content": "Для отображения объектов в текущем месте необходимо включить службу определения местоположения. Включить?", "map_location_service_disabled_title": "Служба определения местоположения отключена", "map_no_assets_in_bounds": "Нет фотографий в этой области", - "map_no_location_permission_content": "Для отображения объектов из текущего местоположения необходимо разрешение на определение местоположения. Хотите ли вы разрешить его сейчас?", + "map_no_location_permission_content": "Для отображения объектов в текущем месте необходимо разрешение на определение местоположения. Предоставить разрешение?", "map_no_location_permission_title": "Доступ к местоположению отклонен", "map_settings_dark_mode": "Темный режим", "map_settings_date_range_option_all": "Все", - "map_settings_date_range_option_day": "Прошлые 24 часа", - "map_settings_date_range_option_days": "Прошлые {} дней", - "map_settings_date_range_option_year": "Прошлый год", - "map_settings_date_range_option_years": "Прошлые {} года", + "map_settings_date_range_option_day": "24 часа", + "map_settings_date_range_option_days": "{} дней", + "map_settings_date_range_option_year": "Год", + "map_settings_date_range_option_years": "{} года", "map_settings_dialog_cancel": "Отмена", "map_settings_dialog_save": "Сохранить", "map_settings_dialog_title": "Настройки карты", - "map_settings_include_show_archived": "Отображать архив", - "map_settings_include_show_partners": "Отображать снимки партнера", + "map_settings_include_show_archived": "Отображать архивированное", + "map_settings_include_show_partners": "Отображать медиа партнера", "map_settings_only_relative_range": "Период времени", "map_settings_only_show_favorites": "Показать только избранное", - "map_settings_theme_settings": "Тема карты", + "map_settings_theme_settings": "Цвет карты", "map_zoom_to_see_photos": "Уменьшение масштаба для просмотра фотографий", "memories_all_caught_up": "Это всё на сегодня", "memories_check_back_tomorrow": "Загляните завтра, чтобы увидеть больше воспоминаний", "memories_start_over": "Начать заново", "memories_swipe_to_close": "Смахните вверх, чтобы закрыть", "memories_year_ago": "Год назад", - "memories_years_ago": "{} лет назад", + "memories_years_ago": "Лет назад: {}", "monthly_title_text_date_format": "MMMM y", "motion_photos_page_title": "Динамические фото", - "multiselect_grid_edit_date_time_err_read_only": "Невозможно редактировать дату объектов только для чтения, пропуск...", - "multiselect_grid_edit_gps_err_read_only": "Невозможно редактировать местоположение объектов только для чтения, пропуск...", - "my_albums": "My albums", - "no_assets_to_show": "Объекты отсутствуют", + "multiselect_grid_edit_date_time_err_read_only": "Невозможно изменить дату файлов только для чтения, пропуск", + "multiselect_grid_edit_gps_err_read_only": "Невозможно изменить местоположение файлов только для чтения, пропуск", + "my_albums": "Мои альбомы", + "networking_settings": "Networking", + "networking_subtitle": "Manage the server endpoint settings", + "no_assets_to_show": "Медиа отсутствуют", "no_name": "Без имени", "notification_permission_dialog_cancel": "Отмена", "notification_permission_dialog_content": "Чтобы включить уведомления, перейдите в «Настройки» и выберите «Разрешить».", @@ -373,48 +398,50 @@ "notification_permission_list_tile_content": "Предоставьте разрешение на включение уведомлений", "notification_permission_list_tile_enable_button": "Включить уведомления", "notification_permission_list_tile_title": "Разрешение на уведомление", - "on_this_device": "On this device", + "on_this_device": "На этом устройстве", "partner_list_user_photos": "Фотографии {user}", "partner_list_view_all": "Посмотреть все", "partner_page_add_partner": "Добавить партнёра", - "partner_page_empty_message": "У вашего партнёра еще пока нет доступа к вашим фото", + "partner_page_empty_message": "У вашего партнёра еще нет доступа к вашим фото", "partner_page_no_more_users": "Выбраны все доступные пользователи", "partner_page_partner_add_failed": "Не удалось добавить партнёра", "partner_page_select_partner": "Выбрать партнёра", "partner_page_shared_to_title": "Поделиться с...", "partner_page_stop_sharing_content": "{} больше не сможет получить доступ к вашим фотографиям", - "partner_page_stop_sharing_title": "Закрыть доступ партнёра к вашим фото?", + "partner_page_stop_sharing_title": "Закрыть доступ к вашим фото?", "partner_page_title": "Партнёр", - "partners": "Partners", - "people": "People", + "partners": "Партнёры", + "people": "Люди", "permission_onboarding_back": "Назад", "permission_onboarding_continue_anyway": "Все равно продолжить", "permission_onboarding_get_started": "Давайте начнём", "permission_onboarding_go_to_settings": "Перейти в настройки", "permission_onboarding_grant_permission": "Предоставить разрешение", "permission_onboarding_log_out": "Выйти", - "permission_onboarding_permission_denied": "Не удалось получить доступ.", + "permission_onboarding_permission_denied": "Не удалось получить доступ. Чтобы использовать приложение, разрешите доступ к \"Фото и видео\" в настройках.", "permission_onboarding_permission_granted": "Доступ получен! Всё готово.", - "permission_onboarding_permission_limited": "Доступ к файлам ограничен. Чтобы Immich мог создавать резервные копии и управлять вашей галереей, пожалуйста, предоставьте приложению разрешение на доступ к \"Фото и видео\" в Настройках.", - "permission_onboarding_request": "Immich просит вас предоставить разрешение на доступ к вашим фото и видео", - "places": "Places", + "permission_onboarding_permission_limited": "Доступ к файлам ограничен. Чтобы Immich мог создавать резервные копии и управлять вашей галереей, пожалуйста, предоставьте приложению разрешение на доступ к \"Фото и видео\" в настройках.", + "permission_onboarding_request": "Приложению необходимо разрешение на доступ к вашим фото и видео", + "places": "Места", + "preferences_settings_subtitle": "Manage the app's preferences", "preferences_settings_title": "Параметры", "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_documentation": "Документация", "profile_drawer_github": "GitHub", - "profile_drawer_server_out_of_date_major": "Серверная версия устарела. Пожалуйста, обновитесь до последней основной версии.", - "profile_drawer_server_out_of_date_minor": "Серверная версия устарела. Пожалуйста, обновитесь до последней вспомогательной версии.", + "profile_drawer_server_out_of_date_major": "Версия сервера устарела. Пожалуйста, обновите его.", + "profile_drawer_server_out_of_date_minor": "Версия сервера устарела. Пожалуйста, обновите его.", "profile_drawer_settings": "Настройки", "profile_drawer_sign_out": "Выйти", "profile_drawer_trash": "Корзина", - "recently_added": "Recently added", + "recently_added": "Недавно добавленные", "recently_added_page_title": "Недавно добавленные", + "save": "Save", "save_to_gallery": "Сохранить в галерею", "scaffold_body_error_occurred": "Возникла ошибка", - "search_albums": "Search albums", + "search_albums": "Поиск альбома", "search_bar_hint": "Поиск фотографий", "search_filter_apply": "Применить фильтр", "search_filter_camera": "Камера", @@ -422,22 +449,22 @@ "search_filter_camera_model": "Модель", "search_filter_camera_title": "Выберите тип камеры", "search_filter_date": "Дата", - "search_filter_date_interval": "{start} до {end}", - "search_filter_date_title": "Выберите диапазон дат", + "search_filter_date_interval": "{start} — {end}", + "search_filter_date_title": "Выберите промежуток", "search_filter_display_option_archive": "Архив", "search_filter_display_option_favorite": "Избранное", "search_filter_display_option_not_in_album": "Не в альбоме", "search_filter_display_options": "Настройки отображения", "search_filter_display_options_title": "Настройки отображения", - "search_filter_location": "Местоположение", + "search_filter_location": "Место", "search_filter_location_city": "Город", "search_filter_location_country": "Страна", "search_filter_location_state": "Регион", - "search_filter_location_title": "Выберите местонахождение", - "search_filter_media_type": "Тип носителя", + "search_filter_location_title": "Выберите место", + "search_filter_media_type": "Тип файла", "search_filter_media_type_all": "Все", "search_filter_media_type_image": "Изображения", - "search_filter_media_type_title": "Выберите тип носителя", + "search_filter_media_type_title": "Выберите тип медиа", "search_filter_media_type_video": "Видео", "search_filter_people": "Люди", "search_filter_people_title": "Выберите людей", @@ -451,12 +478,13 @@ "search_page_person_add_name_dialog_hint": "Имя", "search_page_person_add_name_dialog_save": "Сохранить", "search_page_person_add_name_dialog_title": "Добавить имя", - "search_page_person_add_name_subtitle": "Быстро найдите их по имени с помощью поиска", + "search_page_person_add_name_subtitle": "Быстро находите их по имени с помощью поиска", "search_page_person_add_name_title": "Добавить имя", "search_page_person_edit_name": "Редактировать имя", "search_page_places": "Места", "search_page_recently_added": "Недавно добавленные", "search_page_screenshots": "Снимки экрана", + "search_page_search_photos_videos": "Search for your photos and videos", "search_page_selfies": "Селфи", "search_page_things": "Предметы", "search_page_videos": "Видео", @@ -469,24 +497,26 @@ "select_additional_user_for_sharing_page_suggestions": "Предложения", "select_user_for_sharing_page_err_album": "Не удалось создать альбом", "select_user_for_sharing_page_share_suggestions": "Предложения", + "server_endpoint": "Server Endpoint", "server_info_box_app_version": "Версия приложения", "server_info_box_latest_release": "Последняя версия", "server_info_box_server_url": "URL сервера", "server_info_box_server_version": "Версия сервера", - "setting_image_viewer_help": "Полноэкранный просмотрщик сначала загружает изображение для предпросмотра в низком разрешении, затем загружает изображение в уменьшенном разрешении относительно оригинала (если включено) и в конце концов загружает оригинал (если включено).", + "setting_image_viewer_help": "При просмотре изображения сперва загружается миниатюра, затем \nуменьшенное изображение среднего качества (если включено), а затем оригинал (если включено).", "setting_image_viewer_original_subtitle": "Включите для загрузки исходного изображения в полном разрешении (большое!).\nОтключите, чтобы уменьшить объем данных (как сети, так и кэша устройства).", "setting_image_viewer_original_title": "Загружать исходное изображение", - "setting_image_viewer_preview_subtitle": "Включите для загрузки изображения среднего разрешения.\nОтключите, чтобы загружать оригинал напрямую или использовать только миниатюру.", - "setting_image_viewer_preview_title": "Загружать изображение для предварительного просмотра", + "setting_image_viewer_preview_subtitle": "Включите для загрузки изображения среднего разрешения.\nОтключите, чтобы загружать только оригинал или миниатюру.", + "setting_image_viewer_preview_title": "Загружать уменьшенное изображение", "setting_image_viewer_title": "Изображения", "setting_languages_apply": "Применить", + "setting_languages_subtitle": "Change the app's language", "setting_languages_title": "Язык", "setting_notifications_notify_failures_grace_period": "Уведомлять об ошибках фонового резервного копирования: {}", - "setting_notifications_notify_hours": "{} часов", + "setting_notifications_notify_hours": "{} ч.", "setting_notifications_notify_immediately": "немедленно", - "setting_notifications_notify_minutes": "{} минут", + "setting_notifications_notify_minutes": "{} мин.", "setting_notifications_notify_never": "никогда", - "setting_notifications_notify_seconds": "{} секунд", + "setting_notifications_notify_seconds": "{} сек.", "setting_notifications_single_progress_subtitle": "Подробная информация о ходе загрузки для каждого объекта", "setting_notifications_single_progress_title": "Показать ход выполнения фонового резервного копирования", "setting_notifications_subtitle": "Настройка параметров уведомлений", @@ -503,10 +533,10 @@ "share_add_title": "Добавить название", "share_assets_selected": "{} выбрано", "share_create_album": "Создать альбом", - "shared_album_activities_input_disable": "Комментирование отключено", + "shared_album_activities_input_disable": "Комментарии отключены", "shared_album_activities_input_hint": "Скажите что-нибудь", - "shared_album_activity_remove_content": "Хотите ли Вы удалить это сообщение?", - "shared_album_activity_remove_title": "Удалить сообщение", + "shared_album_activity_remove_content": "Удалить сообщение?", + "shared_album_activity_remove_title": "Удалить", "shared_album_activity_setting_subtitle": "Разрешить другим отвечать", "shared_album_activity_setting_title": "Комментарии и лайки", "shared_album_section_people_action_error": "Ошибка при выходе/удалении из альбома", @@ -515,19 +545,19 @@ "shared_album_section_people_owner_label": "Владелец", "shared_album_section_people_title": "ЛЮДИ", "share_dialog_preparing": "Подготовка...", - "shared_link_app_bar_title": "Общие ссылки", + "shared_link_app_bar_title": "Публичные ссылки", "shared_link_clipboard_copied_massage": "Скопировано в буфер обмена", "shared_link_clipboard_text": "Ссылка: {}\nПароль: {}", - "shared_link_create_app_bar_title": "Создать ссылку общего доступа", - "shared_link_create_error": "Ошибка при создании общей ссылки", + "shared_link_create_app_bar_title": "Создать ссылку для общего доступа", + "shared_link_create_error": "Ошибка при создании публичной ссылки", "shared_link_create_info": "Разрешить всем, у кого есть ссылка, просматривать выбранные фото", "shared_link_create_submit_button": "Создать ссылку", - "shared_link_edit_allow_download": "Разрешить публичному пользователю скачивать файлы", - "shared_link_edit_allow_upload": "Разрешить публичному пользователю загружать файлы", + "shared_link_edit_allow_download": "Разрешить всем скачивать файлы", + "shared_link_edit_allow_upload": "Разрешить всем загружать файлы", "shared_link_edit_app_bar_title": "Редактировать ссылку", - "shared_link_edit_change_expiry": "Изменить срок действия доступа", + "shared_link_edit_change_expiry": "Изменить срок действия", "shared_link_edit_description": "Описание", - "shared_link_edit_description_hint": "Введите описание для общего доступа", + "shared_link_edit_description_hint": "Введите описание публичного доступа", "shared_link_edit_expire_after": "Истекает через", "shared_link_edit_expire_after_option_day": "1 день", "shared_link_edit_expire_after_option_days": "{} дней", @@ -539,10 +569,10 @@ "shared_link_edit_expire_after_option_never": "Никогда", "shared_link_edit_expire_after_option_year": "{} лет", "shared_link_edit_password": "Пароль", - "shared_link_edit_password_hint": "Введите пароль для общего доступа", + "shared_link_edit_password_hint": "Введите пароль для публичного доступа", "shared_link_edit_show_meta": "Показывать метаданные", "shared_link_edit_submit_button": "Обновить ссылку", - "shared_link_empty": "У вас нет общих ссылок", + "shared_link_empty": "У вас нет публичных ссылок", "shared_link_error_server_url_fetch": "Невозможно запросить URL с сервера", "shared_link_expired": "Срок действия истек", "shared_link_expires_day": "Истекает через {} день", @@ -551,24 +581,24 @@ "shared_link_expires_hours": "Истекает через {} часов", "shared_link_expires_minute": "Истекает через {} минуту", "shared_link_expires_minutes": "Истекает через {} минут", - "shared_link_expires_never": "Истекает ∞", + "shared_link_expires_never": "Вечная ссылка", "shared_link_expires_second": "Истекает через {} секунду", "shared_link_expires_seconds": "Истекает через {} секунд", "shared_link_individual_shared": "Индивидуальный общий доступ", "shared_link_info_chip_download": "Скачать", "shared_link_info_chip_metadata": "EXIF", "shared_link_info_chip_upload": "Загрузить", - "shared_link_manage_links": "Управление общими ссылками", + "shared_link_manage_links": "Управление публичными ссылками", "shared_link_public_album": "Публичный альбом", - "shared_links": "Shared links", + "shared_links": "Публичные ссылки", "share_done": "Готово", - "shared_with_me": "Shared with me", + "shared_with_me": "Доступные мне", "share_invite": "Пригласить в альбом", "sharing_page_album": "Общие альбомы", "sharing_page_description": "Создавайте общие альбомы, чтобы делиться фотографиями и видео с людьми в вашей сети.", "sharing_page_empty_list": "ПУСТОЙ СПИСОК", "sharing_silver_appbar_create_shared_album": "Создать общий альбом", - "sharing_silver_appbar_shared_links": "Общие ссылки", + "sharing_silver_appbar_shared_links": "Публичные ссылки", "sharing_silver_appbar_share_partner": "Поделиться с партнёром", "sync": "Синхронизировать", "sync_albums": "Синхронизировать альбомы", @@ -580,29 +610,29 @@ "tab_controller_nav_sharing": "Общие", "theme_setting_asset_list_storage_indicator_title": "Показать индикатор хранилища на плитках объектов", "theme_setting_asset_list_tiles_per_row_title": "Количество объектов в строке ({})", - "theme_setting_colorful_interface_subtitle": "Применить основной цвет на поверхность фона.", - "theme_setting_colorful_interface_title": "Красочный интерфейс", + "theme_setting_colorful_interface_subtitle": "Добавить оттенок к фону", + "theme_setting_colorful_interface_title": "Цвет фона", "theme_setting_dark_mode_switch": "Тёмная тема", - "theme_setting_image_viewer_quality_subtitle": "Настройка качества просмотра полноэкранных изображения", + "theme_setting_image_viewer_quality_subtitle": "Настройка качества просмотра изображения", "theme_setting_image_viewer_quality_title": "Качество просмотра изображений", - "theme_setting_primary_color_subtitle": "Выберите цвет для основных действий и акцентов.", + "theme_setting_primary_color_subtitle": "Основной цвет приложения.", "theme_setting_primary_color_title": "Основной цвет", "theme_setting_system_primary_color_title": "Использовать системный цвет", "theme_setting_system_theme_switch": "Автоматически (как в системе)", "theme_setting_theme_subtitle": "Настройка темы приложения", "theme_setting_theme_title": "Тема", - "theme_setting_three_stage_loading_subtitle": "Трехэтапная загрузка может повысить производительность загрузки, но вызывает значительно более высокую нагрузку на сеть", + "theme_setting_three_stage_loading_subtitle": "Трехэтапная загрузка может повысить производительность, но значительно нагружает сеть", "theme_setting_three_stage_loading_title": "Включить трехэтапную загрузку", "translated_text_options": "Опции", - "trash": "Trash", + "trash": "Корзина", "trash_emptied": "Корзина очищена", "trash_page_delete": "Удалить", "trash_page_delete_all": "Удалить все", "trash_page_empty_trash_btn": "Очистить корзину", - "trash_page_empty_trash_dialog_content": "Вы хотите очистить свою корзину? Эти объекты будут навсегда удалены из Immich.", + "trash_page_empty_trash_dialog_content": "Очистить корзину? Эти файлы будут навсегда удалены из Immich.", "trash_page_empty_trash_dialog_ok": "ОК", - "trash_page_info": "Удаленные элементы будут окончательно удалены через {} дней", - "trash_page_no_assets": "Удаленные объекты отсутствуют", + "trash_page_info": "Элементы в корзине будут окончательно удалены через {} дней", + "trash_page_no_assets": "Корзина пуста", "trash_page_restore": "Восстановить", "trash_page_restore_all": "Восстановить все", "trash_page_select_assets_btn": "Выбранные объекты", @@ -612,14 +642,18 @@ "upload_dialog_info": "Хотите создать резервную копию выбранных объектов на сервере?", "upload_dialog_ok": "Загрузить", "upload_dialog_title": "Загрузить объект", - "version_announcement_overlay_ack": "Подтверждение", + "use_current_connection": "use current connection", + "validate_endpoint_error": "Please enter a valid URL", + "version_announcement_overlay_ack": "Понятно", "version_announcement_overlay_release_notes": "примечания к выпуску", - "version_announcement_overlay_text_1": "Привет друг, вышел новый релиз", - "version_announcement_overlay_text_2": "пожалуйста, найдите время, чтобы посетить", - "version_announcement_overlay_text_3": " и убедитесь, что ваши настройки docker-compose и .env обновлены, чтобы предотвратить любые неправильные настройки, особенно если вы используете WatchTower или любой другой механизм, который обрабатывает обновление вашего серверного приложения автоматически.", + "version_announcement_overlay_text_1": "Привет, друг! Вышла новая версия", + "version_announcement_overlay_text_2": "пожалуйста, посетите", + "version_announcement_overlay_text_3": " и убедитесь, что ваши настройки docker-compose и .env обновлены, особенно если вы используете WatchTower или любой другой механизм, который автоматически обновляет сервер.", "version_announcement_overlay_title": "Доступна новая версия сервера \uD83C\uDF89", - "videos": "Videos", + "videos": "Видео", "viewer_remove_from_stack": "Удалить из стека", "viewer_stack_use_as_main_asset": "Использовать в качестве основного объекта", - "viewer_unstack": "Разобрать стек" + "viewer_unstack": "Разобрать стек", + "wifi_name": "WiFi Name", + "your_wifi_name": "Your WiFi name" } \ No newline at end of file diff --git a/mobile/assets/i18n/sk-SK.json b/mobile/assets/i18n/sk-SK.json index eb4e304f2d161..14d0e04524e67 100644 --- a/mobile/assets/i18n/sk-SK.json +++ b/mobile/assets/i18n/sk-SK.json @@ -7,6 +7,7 @@ "action_common_select": "Select", "action_common_update": "Aktualizovať", "add_a_name": "Add a name", + "add_endpoint": "Add endpoint", "add_to_album_bottom_sheet_added": "Pridané do {album}", "add_to_album_bottom_sheet_already_exists": "Už v {album}", "advanced_settings_log_level_title": "Úroveň logovania: {}", @@ -65,7 +66,12 @@ "assets_restored_successfully": "{} asset(s) restored successfully", "assets_trashed": "{} asset(s) trashed", "assets_trashed_from_server": "{} asset(s) trashed from the Immich server", + "asset_viewer_settings_subtitle": "Manage your gallery viewer settings", "asset_viewer_settings_title": "Zobrazovač položiek", + "automatic_endpoint_switching_subtitle": "Connect locally over designated Wi-Fi when available and use alternative connections elsewhere", + "automatic_endpoint_switching_title": "Automatic URL switching", + "background_location_permission": "Background location permission", + "background_location_permission_content": "In order to switch networks when running in the background, Immich must *always* have precise location access so the app can read the Wi-Fi network's name", "backup_album_selection_page_albums_device": "Albumy v zariadení ({})", "backup_album_selection_page_albums_tap": "Ťuknutím na položku ju zahrniete, dvojitým ťuknutím ju vylúčite", "backup_album_selection_page_assets_scatter": "Súbory môžu byť roztrúsené vo viacerých albumoch. To umožňuje zahrnúť alebo vylúčiť albumy počas procesu zálohovania.", @@ -131,6 +137,7 @@ "backup_manual_success": "Úspech", "backup_manual_title": "Stav nahrávania", "backup_options_page_title": "Možnosti zálohovania", + "backup_setting_subtitle": "Manage background and foreground upload settings", "cache_settings_album_thumbnails": "Náhľady stránok knižnice (položiek {})", "cache_settings_clear_cache_button": "Vymazať vyrovnávaciu pamäť", "cache_settings_clear_cache_button_title": "Vymaže vyrovnávaciu pamäť aplikácie. To výrazne ovplyvní výkon aplikácie, kým sa vyrovnávacia pamäť neobnoví.", @@ -149,11 +156,16 @@ "cache_settings_tile_subtitle": "Ovládanie správania lokálneho úložiska", "cache_settings_tile_title": "Lokálne úložisko", "cache_settings_title": "Nastavenia vyrovnávacej pamäte", + "cancel": "Cancel", + "change_display_order": "Change display order", "change_password_form_confirm_password": "Potvrďte heslo", "change_password_form_description": "Dobrý deň, {name},\n\nBuď sa do systému prihlasujete prvýkrát, alebo bola podaná žiadosť o zmenu hesla. Prosím, zadajte nové heslo nižšie.", "change_password_form_new_password": "Nové heslo", "change_password_form_password_mismatch": "Heslá sa nezhodujú", "change_password_form_reenter_new_password": "Znova zadajte nové heslo", + "check_corrupt_asset_backup": "Check for corrupt asset backups", + "check_corrupt_asset_backup_button": "Perform check", + "check_corrupt_asset_backup_description": "Run this check only over Wi-Fi and once all assets have been backed-up. The procedure might take a few minutes.", "client_cert_dialog_msg_confirm": "OK", "client_cert_enter_password": "Enter Password", "client_cert_import": "Import", @@ -199,6 +211,7 @@ "crop": "Crop", "curated_location_page_title": "Miesta", "curated_object_page_title": "Veci", + "current_server_address": "Current server address", "daily_title_text_date": "EEEE, d. MMMM", "daily_title_text_date_year": "EEEE, d. MMMM y", "date_format": "EEEE, d. MMMM y • H:mm", @@ -235,6 +248,8 @@ "edit_date_time_dialog_timezone": "Časové pásmo", "edit_image_title": "Edit", "edit_location_dialog_title": "Poloha", + "enter_wifi_name": "Enter WiFi name", + "error_change_sort_album": "Failed to change album sort order", "error_saving_image": "Error: {}", "exif_bottom_sheet_description": "Pridať popis...", "exif_bottom_sheet_details": "PODROBNOSTI", @@ -246,11 +261,15 @@ "experimental_settings_new_asset_list_title": "Povolenie experimentálnej mriežky fotografií", "experimental_settings_subtitle": "Používajte na vlastné riziko!", "experimental_settings_title": "Experimentálne", + "external_network": "External network", + "external_network_sheet_info": "When not on the preferred WiFi network, the app will connect to the server through the first of the below URLs it can reach, starting from top to bottom", "favorites": "Favorites", "favorites_page_no_favorites": "Žiadne obľúbené médiá", "favorites_page_title": "Obľúbené", "filename_search": "File name or extension", "filter": "Filter", + "get_wifiname_error": "Could not get Wi-Fi name. Make sure you have granted the necessary permissions and are connected to a Wi-Fi network", + "grant_permission": "Grant permission", "haptic_feedback_switch": "Povoliť hmatovú odozvu", "haptic_feedback_title": "Hmatová odozva", "header_settings_add_header_tip": "Add Header", @@ -296,6 +315,10 @@ "library_page_sort_most_oldest_photo": "Najstaršia fotka", "library_page_sort_most_recent_photo": "Najnovšia fotka", "library_page_sort_title": "Podľa názvu albumu", + "local_network": "Local network", + "local_network_sheet_info": "The app will connect to the server through this URL when using the specified Wi-Fi network", + "location_permission": "Location permission", + "location_permission_content": "In order to use the auto-switching feature, Immich needs precise location permission so it can read the current WiFi network's name", "location_picker_choose_on_map": "Zvoľte mapu", "location_picker_latitude": "Zemepisná dĺžka", "location_picker_latitude_error": "Zadajte platnú zemepisnú dĺžku", @@ -365,6 +388,8 @@ "multiselect_grid_edit_date_time_err_read_only": "Nemožno upraviť dátum položky len na čítanie, preskakujem", "multiselect_grid_edit_gps_err_read_only": "Nemožno upraviť polohu položky len na čítanie, preskakujem", "my_albums": "My albums", + "networking_settings": "Networking", + "networking_subtitle": "Manage the server endpoint settings", "no_assets_to_show": "Žiadne položky", "no_name": "No name", "notification_permission_dialog_cancel": "Zrušiť", @@ -398,6 +423,7 @@ "permission_onboarding_permission_limited": "Povolenie obmedzené. Ak chcete, aby Immich zálohoval a spravoval celú vašu zbierku galérie, udeľte v Nastaveniach povolenia na fotografie a videá.", "permission_onboarding_request": "Immich vyžaduje povolenie na prezeranie vašich fotografií a videí.", "places": "Places", + "preferences_settings_subtitle": "Manage the app's preferences", "preferences_settings_title": "Preferencie", "profile_drawer_app_logs": "Logy", "profile_drawer_client_out_of_date_major": "Mobilná aplikácia je zastaralá. Prosím aktualizujte na najnovšiu verziu.", @@ -412,6 +438,7 @@ "profile_drawer_trash": "Kôš", "recently_added": "Recently added", "recently_added_page_title": "Nedávno pridané", + "save": "Save", "save_to_gallery": "Save to gallery", "scaffold_body_error_occurred": "Vyskytla sa chyba", "search_albums": "Search albums", @@ -457,6 +484,7 @@ "search_page_places": "Miesta", "search_page_recently_added": "Nedávno pridané", "search_page_screenshots": "Snímky obrazovky", + "search_page_search_photos_videos": "Search for your photos and videos", "search_page_selfies": "Selfies", "search_page_things": "Veci", "search_page_videos": "Videá", @@ -469,6 +497,7 @@ "select_additional_user_for_sharing_page_suggestions": "Návrhy", "select_user_for_sharing_page_err_album": "Nepodarilo sa vytvoriť album", "select_user_for_sharing_page_share_suggestions": "Návrhy", + "server_endpoint": "Server Endpoint", "server_info_box_app_version": "Verzia aplikácie", "server_info_box_latest_release": "Najnovšia verzia", "server_info_box_server_url": "URL Serveru", @@ -480,6 +509,7 @@ "setting_image_viewer_preview_title": "Načítať náhľad obrázka", "setting_image_viewer_title": "Obrázky", "setting_languages_apply": "Použiť", + "setting_languages_subtitle": "Change the app's language", "setting_languages_title": "Jazyky", "setting_notifications_notify_failures_grace_period": "Oznámenie o zlyhaní zálohovania na pozadí: {}", "setting_notifications_notify_hours": "{} hodín", @@ -612,6 +642,8 @@ "upload_dialog_info": "Chcete zálohovať zvolené médiá na server?", "upload_dialog_ok": "Nahrať", "upload_dialog_title": "Nahrať médiá", + "use_current_connection": "use current connection", + "validate_endpoint_error": "Please enter a valid URL", "version_announcement_overlay_ack": "Potvrdiť", "version_announcement_overlay_release_notes": "poznámky k vydaniu", "version_announcement_overlay_text_1": "Ahoj, je tu nová verzia", @@ -621,5 +653,7 @@ "videos": "Videos", "viewer_remove_from_stack": "Odstrániť zo zoskupenia", "viewer_stack_use_as_main_asset": "Použiť ako hlavnú fotku", - "viewer_unstack": "Odskupiť" + "viewer_unstack": "Odskupiť", + "wifi_name": "WiFi Name", + "your_wifi_name": "Your WiFi name" } \ No newline at end of file diff --git a/mobile/assets/i18n/sl-SI.json b/mobile/assets/i18n/sl-SI.json index 1d7ef33a4ef42..54b4dd5f71ca8 100644 --- a/mobile/assets/i18n/sl-SI.json +++ b/mobile/assets/i18n/sl-SI.json @@ -3,10 +3,11 @@ "action_common_cancel": "Prekliči", "action_common_clear": "Počisti", "action_common_confirm": "Potrdi", - "action_common_save": "Save", - "action_common_select": "Select", + "action_common_save": "Shrani", + "action_common_select": "Izberi", "action_common_update": "Posodobi", - "add_a_name": "Add a name", + "add_a_name": "Dodaj ime", + "add_endpoint": "Dodaj končno točko", "add_to_album_bottom_sheet_added": "Dodano v {album}", "add_to_album_bottom_sheet_already_exists": "Že v {albumu}", "advanced_settings_log_level_title": "Nivo dnevnika: {}", @@ -22,7 +23,7 @@ "advanced_settings_troubleshooting_title": "Odpravljanje težav", "album_info_card_backup_album_excluded": "IZKLJUČENO", "album_info_card_backup_album_included": "VKLJUČENO", - "albums": "Albums", + "albums": "Albumi", "album_thumbnail_card_item": "1 element", "album_thumbnail_card_items": "{} elementov", "album_thumbnail_card_shared": "· V skupni rabi", @@ -38,13 +39,13 @@ "album_viewer_appbar_share_remove": "Odstrani iz albuma", "album_viewer_appbar_share_to": "Deli z", "album_viewer_page_share_add_users": "Dodaj uporabnike", - "all": "All", + "all": "Vse", "all_people_page_title": "Ljudje", "all_videos_page_title": "Videoposnetki", "app_bar_signout_dialog_content": "Ste prepričani, da se želite odjaviti?", "app_bar_signout_dialog_ok": "Da", "app_bar_signout_dialog_title": "Odjava", - "archived": "Archived", + "archived": "Arhivirano", "archive_page_no_archived_assets": "Ni arhiviranih sredstev", "archive_page_title": "Arhiv ({})\n", "asset_action_delete_err_read_only": "Sredstev samo za branje ni mogoče izbrisati, preskočim\n", @@ -58,14 +59,19 @@ "asset_list_layout_sub_title": "Postavitev", "asset_list_settings_subtitle": "Nastavitve postavitve mreže fotografij", "asset_list_settings_title": "Mreža fotografij", - "asset_restored_successfully": "Asset restored successfully", - "assets_deleted_permanently": "{} asset(s) deleted permanently", - "assets_deleted_permanently_from_server": "{} asset(s) deleted permanently from the Immich server", - "assets_removed_permanently_from_device": "{} asset(s) removed permanently from your device", - "assets_restored_successfully": "{} asset(s) restored successfully", - "assets_trashed": "{} asset(s) trashed", - "assets_trashed_from_server": "{} asset(s) trashed from the Immich server", + "asset_restored_successfully": "Sredstvo uspešno obnovljeno", + "assets_deleted_permanently": "Št. za vedno izbrisanih sredstev: {}", + "assets_deleted_permanently_from_server": "Št. za vedno izbrisanih sredstev iz srežnika Immich: {}", + "assets_removed_permanently_from_device": "Št. za vedno izbrisanih sredstev iz vaše naprave: {}", + "assets_restored_successfully": "Št. uspešno obnovljenih sredstev: {}", + "assets_trashed": "Št. sredstev premaknjenih v smetnjak: {}", + "assets_trashed_from_server": "Št sredstev izbrisanih iz strežnika Immich: {}", + "asset_viewer_settings_subtitle": "Upravljaj nastavitve pregledovalnika galerije", "asset_viewer_settings_title": "Pregledovalnik sredstev", + "automatic_endpoint_switching_subtitle": "Povežite se lokalno prek določenega omrežja Wi-Fi, ko je na voljo, in uporabite druge povezave drugje", + "automatic_endpoint_switching_title": "Samodejno preklapljanje URL-jev", + "background_location_permission": "Dovoljenje za iskanje lokacije v ozadju", + "background_location_permission_content": "Ko deluje v ozadju mora imeti Immich za zamenjavo omrežij, *vedno* dostop do natančne lokacije, da lahko aplikacija prebere ime omrežja Wi-Fi", "backup_album_selection_page_albums_device": "Albumi v napravi ({})", "backup_album_selection_page_albums_tap": "Tapnite za vključitev, dvakrat tapnite za izključitev", "backup_album_selection_page_assets_scatter": "Sredstva so lahko razpršena po več albumih. Tako je mogoče med postopkom varnostnega kopiranja albume vključiti ali izključiti.", @@ -131,6 +137,7 @@ "backup_manual_success": "Uspeh", "backup_manual_title": "Status nalaganja", "backup_options_page_title": "Možnosti varnostne kopije", + "backup_setting_subtitle": "Upravljaj nastavitve nalaganja v ozadju in ospredju", "cache_settings_album_thumbnails": "Sličice strani knjižnice ({} sredstev)", "cache_settings_clear_cache_button": "Počisti predpomnilnik", "cache_settings_clear_cache_button_title": "Počisti predpomnilnik aplikacije. To bo znatno vplivalo na delovanje aplikacije, dokler se predpomnilnik ne obnovi.", @@ -149,26 +156,31 @@ "cache_settings_tile_subtitle": "Nadzoruj vedenje lokalnega shranjevanja", "cache_settings_tile_title": "Lokalna shramba", "cache_settings_title": "Nastavitve predpomnjenja", + "cancel": "Prekliči", + "change_display_order": "Spremeni vrstni red prikaza", "change_password_form_confirm_password": "Potrdi geslo", "change_password_form_description": "Pozdravljeni {name},\n\nTo je bodisi prvič, da se vpisujete v sistem ali pa je bila podana zahteva za spremembo vašega gesla. Spodaj vnesite novo geslo.", "change_password_form_new_password": "Novo geslo", "change_password_form_password_mismatch": "Gesli se ne ujemata", "change_password_form_reenter_new_password": "Znova vnesi novo geslo", - "client_cert_dialog_msg_confirm": "OK", - "client_cert_enter_password": "Enter Password", - "client_cert_import": "Import", - "client_cert_import_success_msg": "Client certificate is imported", - "client_cert_invalid_msg": "Invalid certificate file or wrong password", - "client_cert_remove": "Remove", - "client_cert_remove_msg": "Client certificate is removed", - "client_cert_subtitle": "Supports PKCS12 (.p12, .pfx) format only. Certificate Import/Remove is available only before login", - "client_cert_title": "SSL Client Certificate", + "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.", + "client_cert_dialog_msg_confirm": "V redu", + "client_cert_enter_password": "Vnesi geslo", + "client_cert_import": "Uvozi", + "client_cert_import_success_msg": "Potrdilo odjemalca je uvoženo", + "client_cert_invalid_msg": "Neveljavna datoteka potrdila ali napačno geslo", + "client_cert_remove": "Odstrani", + "client_cert_remove_msg": "Potrdilo odjemalca je odstranjeno", + "client_cert_subtitle": "Podpira samo format PKCS12 (.p12, .pfx). Uvoz/odstranitev potrdila je na voljo samo pred prijavo", + "client_cert_title": "Potrdilo odjemalca SSL", "common_add_to_album": "Dodaj v album", "common_change_password": "Zamenjaj geslo", "common_create_new_album": "Ustvari nov album", "common_server_error": "Preverite omrežno povezavo, preverite, ali je strežnik dosegljiv in ali sta različici aplikacije/strežnika združljivi.", "common_shared": "V skupni rabi", - "contextual_search": "Sunrise on the beach", + "contextual_search": "Sončni vzhod na plaži", "control_bottom_app_bar_add_to_album": "Dodaj v album", "control_bottom_app_bar_album_info": "{} elementov", "control_bottom_app_bar_album_info_shared": "{} elementov · V skupni rabi", @@ -177,8 +189,8 @@ "control_bottom_app_bar_delete": "Izbriši", "control_bottom_app_bar_delete_from_immich": "Izbriši iz Immicha", "control_bottom_app_bar_delete_from_local": "Izbriši iz naprave", - "control_bottom_app_bar_download": "Download", - "control_bottom_app_bar_edit": "Edit", + "control_bottom_app_bar_download": "Prenos", + "control_bottom_app_bar_edit": "Uredi", "control_bottom_app_bar_edit_location": "Uredi lokacijo", "control_bottom_app_bar_edit_time": "Uredi datum in uro", "control_bottom_app_bar_favorite": "Priljubljen", @@ -189,16 +201,17 @@ "control_bottom_app_bar_unarchive": "Odstrani iz arhiva", "control_bottom_app_bar_unfavorite": "Odstrani iz priljubljeno", "control_bottom_app_bar_upload": "Naloži", - "create_album": "Create album", + "create_album": "Ustvari album", "create_album_page_untitled": "Brez naslova", - "create_new": "CREATE NEW", + "create_new": "USTVARI NOVEGA", "create_shared_album_page_create": "Ustvari", "create_shared_album_page_share": "Deli", "create_shared_album_page_share_add_assets": "DODAJ SREDSTVO", "create_shared_album_page_share_select_photos": "Izberi fotografije", - "crop": "Crop", + "crop": "Obrezovanje", "curated_location_page_title": "Lokacije", "curated_object_page_title": "Stvari", + "current_server_address": "Trenutni naslov strežnika", "daily_title_text_date": "E, MMM dd", "daily_title_text_date_year": "E, MMM dd, yyyy", "date_format": "E, LLL d, y • h:mm a", @@ -216,26 +229,28 @@ "delete_shared_link_dialog_title": "Izbriši povezavo skupne rabe", "description_input_hint_text": "Dodaj opis ...", "description_input_submit_error": "Napaka pri posodabljanju opisa, preverite dnevnik za več podrobnosti", - "download_canceled": "Download canceled", - "download_complete": "Download complete", - "download_enqueue": "Download enqueued", - "download_error": "Download Error", - "download_failed": "Download failed", - "download_filename": "file: {}", - "download_finished": "Download finished", - "downloading": "Downloading...", - "downloading_media": "Downloading media", - "download_notfound": "Download not found", - "download_paused": "Download paused", - "download_started": "Download started", - "download_sucess": "Download success", - "download_sucess_android": "The media has been downloaded to DCIM/Immich", - "download_waiting_to_retry": "Waiting to retry", + "download_canceled": "Prenos preklican", + "download_complete": "Prenos končan", + "download_enqueue": "Prenos v čakalni vrsti", + "download_error": "Napaka pri prenosu", + "download_failed": "Prenos ni uspel", + "download_filename": "datoteka: {}", + "download_finished": "Prenos zaključen", + "downloading": "Prenašam...", + "downloading_media": "Prenašanje medijev", + "download_notfound": "Prenosa ni bilo mogoče najti", + "download_paused": "Prenos zaustavljen", + "download_started": "Prenos se je začel", + "download_sucess": "Prenos uspešen", + "download_sucess_android": "Medij je bil prenesen v DCIM/Immich", + "download_waiting_to_retry": "Čakam na ponovni poskus", "edit_date_time_dialog_date_time": "Datum in ura", "edit_date_time_dialog_timezone": "Časovni pas", - "edit_image_title": "Edit", + "edit_image_title": "Urejanje", "edit_location_dialog_title": "Lokacija", - "error_saving_image": "Error: {}", + "enter_wifi_name": "Vnesi WiFi ime", + "error_change_sort_album": "Vrstnega reda albuma ni bilo mogoče spremeniti", + "error_saving_image": "Napaka: {}", "exif_bottom_sheet_description": "Dodaj opis..", "exif_bottom_sheet_details": "PODROBNOSTI", "exif_bottom_sheet_location": "LOKACIJA", @@ -246,11 +261,15 @@ "experimental_settings_new_asset_list_title": "Omogoči eksperimentalno mrežo fotografij", "experimental_settings_subtitle": "Uporabljajte na lastno odgovornost!", "experimental_settings_title": "Eksperimentalno", - "favorites": "Favorites", + "external_network": "Zunanje omrežje", + "external_network_sheet_info": "Ko aplikacija ni v želenem omrežju WiFi, se bo povezala s strežnikom prek prvega od spodnjih URL-jev, ki jih lahko doseže, začenši od zgoraj navzdol", + "favorites": "Priljubljene", "favorites_page_no_favorites": "Ni priljubljenih sredstev", "favorites_page_title": "Priljubljene", - "filename_search": "File name or extension", + "filename_search": "Ime ali končnica datoteke", "filter": "Filter", + "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", + "grant_permission": "Podeli dovoljenje", "haptic_feedback_switch": "Uporabi haptičen odziv", "haptic_feedback_title": "Haptičen odziv", "header_settings_add_header_tip": "Dodaj glavo", @@ -274,16 +293,16 @@ "home_page_first_time_notice": "Če aplikacijo uporabljate prvič, se prepričajte, da ste izbrali rezervne albume, tako da lahko časovna premica zapolni fotografije in videoposnetke v albumih.", "home_page_share_err_local": "Lokalnih sredstev ni mogoče deliti prek povezave, preskakujem", "home_page_upload_err_limit": "Hkrati lahko naložite največ 30 sredstev, preskakujem", - "ignore_icloud_photos": "Ignore iCloud photos", - "ignore_icloud_photos_description": "Photos that are stored on iCloud will not be uploaded to the Immich server", - "image_saved_successfully": "Image saved", + "ignore_icloud_photos": "Ignoriraj fotografije iCloud", + "ignore_icloud_photos_description": "Fotografije, shranjene v iCloud, ne bodo naložene na strežnik Immich", + "image_saved_successfully": "Slika shranjena", "image_viewer_page_state_provider_download_error": "Napaka pri prenosu", "image_viewer_page_state_provider_download_started": "Prenos se je začel", "image_viewer_page_state_provider_download_success": "Prenos je uspel", "image_viewer_page_state_provider_share_error": "Napaka skupne rabe", - "invalid_date": "Invalid date", - "invalid_date_format": "Invalid date format", - "library": "Library", + "invalid_date": "Neveljaven datum", + "invalid_date_format": "Neveljavna oblika datuma", + "library": "Knjižnica", "library_page_albums": "Albumi", "library_page_archive": "Arhiv", "library_page_device_albums": "Albumi v napravi", @@ -296,6 +315,10 @@ "library_page_sort_most_oldest_photo": "Najstarejša fotografija", "library_page_sort_most_recent_photo": "Najnovejša fotografija", "library_page_sort_title": "Naslov albuma", + "local_network": "Lokalno omrežje", + "local_network_sheet_info": "Aplikacija se bo povezala s strežnikom prek tega URL-ja, ko bo uporabljala navedeno omrežje Wi-Fi", + "location_permission": "Dovoljenje za lokacijo", + "location_permission_content": "Za uporabo funkcije samodejnega preklapljanja potrebuje Immich dovoljenje za natančno lokacijo, da lahko prebere ime trenutnega omrežja WiFi", "location_picker_choose_on_map": "Izberi na zemljevidu", "location_picker_latitude": "Zemljepisna širina", "location_picker_latitude_error": "Vnesi veljavno zemljepisno širino", @@ -364,16 +387,18 @@ "motion_photos_page_title": "Fotografije v gibanju", "multiselect_grid_edit_date_time_err_read_only": "Ni mogoče urediti datuma sredstev samo za branje, preskočim", "multiselect_grid_edit_gps_err_read_only": "Ni mogoče urediti lokacije sredstev samo za branje, preskočim", - "my_albums": "My albums", + "my_albums": "Moji albumi", + "networking_settings": "Omrežje", + "networking_subtitle": "Upravljaj nastavitve končne točke strežnika", "no_assets_to_show": "Ni sredstev za prikaz", - "no_name": "No name", + "no_name": "Brez imena", "notification_permission_dialog_cancel": "Prekliči", "notification_permission_dialog_content": "Če želite omogočiti obvestila, pojdite v Nastavitve in izberite Dovoli.", "notification_permission_dialog_settings": "Nastavitve", "notification_permission_list_tile_content": "Izdaj dovoljenje za omogočanje obvestil.", "notification_permission_list_tile_enable_button": "Omogoči obvestila", "notification_permission_list_tile_title": "Dovoljenje za obvestila", - "on_this_device": "On this device", + "on_this_device": "Na tej napravi", "partner_list_user_photos": "{user}ovih fotografij", "partner_list_view_all": "Poglej vse", "partner_page_add_partner": "Dodaj partnerja", @@ -385,8 +410,8 @@ "partner_page_stop_sharing_content": "{} ne bo imel več dostopa do vaših fotografij.", "partner_page_stop_sharing_title": "Želite prenehati deliti svoje fotografije?", "partner_page_title": "Partner", - "partners": "Partners", - "people": "People", + "partners": "Partnerji", + "people": "Ljudje", "permission_onboarding_back": "Sredstev partnerja ni mogoče izbrisati, preskakujem", "permission_onboarding_continue_anyway": "Vseeno nadaljuj", "permission_onboarding_get_started": "Začnimo", @@ -397,7 +422,8 @@ "permission_onboarding_permission_granted": "Dovoljenje je izdano! Vse je pripravljeno.", "permission_onboarding_permission_limited": "Dovoljenje je omejeno. Če želite Immichu dovoliti varnostno kopiranje in upravljanje vaše celotne zbirke galerij, v nastavitvah podelite dovoljenja za fotografije in videoposnetke.", "permission_onboarding_request": "Immich potrebuje dovoljenje za ogled vaših fotografij in videoposnetkov.", - "places": "Places", + "places": "Kraji", + "preferences_settings_subtitle": "Upravljaj nastavitve aplikacije", "preferences_settings_title": "Nastavitve", "profile_drawer_app_logs": "Dnevniki", "profile_drawer_client_out_of_date_major": "Mobilna aplikacija je zastarela. Posodobite na najnovejšo glavno različico.", @@ -410,37 +436,38 @@ "profile_drawer_settings": "Nastavitve", "profile_drawer_sign_out": "Odjava", "profile_drawer_trash": "Smetnjak", - "recently_added": "Recently added", + "recently_added": "Nedavno dodano", "recently_added_page_title": "Nedavno dodano", - "save_to_gallery": "Save to gallery", + "save": "Shrani", + "save_to_gallery": "Shrani v galerijo", "scaffold_body_error_occurred": "Prišlo je do napake", - "search_albums": "Search albums", + "search_albums": "Iskanje albumov", "search_bar_hint": "Poišči svoje fotografije", "search_filter_apply": "Uporabi filter", - "search_filter_camera": "Camera", + "search_filter_camera": "Fotoaparat", "search_filter_camera_make": "Izdelava", "search_filter_camera_model": "Model", - "search_filter_camera_title": "Select camera type", - "search_filter_date": "Date", - "search_filter_date_interval": "{start} to {end}", - "search_filter_date_title": "Select a date range", + "search_filter_camera_title": "Izberi vrsto fotoaparata", + "search_filter_date": "Datum", + "search_filter_date_interval": "{start} do {end}", + "search_filter_date_title": "Izberi časovno obdobje", "search_filter_display_option_archive": "Arhiv", "search_filter_display_option_favorite": "Priljubljen", "search_filter_display_option_not_in_album": "Ni v albumu", - "search_filter_display_options": "Display Options", - "search_filter_display_options_title": "Display options", - "search_filter_location": "Location", + "search_filter_display_options": "Možnosti zaslona", + "search_filter_display_options_title": "Možnosti prikaza", + "search_filter_location": "Lokacija", "search_filter_location_city": "Mesto", "search_filter_location_country": "Država", "search_filter_location_state": "Dežela", - "search_filter_location_title": "Select location", - "search_filter_media_type": "Media Type", + "search_filter_location_title": "Izberi lokacijo", + "search_filter_media_type": "Vrsta medija", "search_filter_media_type_all": "Vse", "search_filter_media_type_image": "Slika", - "search_filter_media_type_title": "Select media type", + "search_filter_media_type_title": "Izberi vrsto medija", "search_filter_media_type_video": "Video", - "search_filter_people": "People", - "search_filter_people_title": "Select people", + "search_filter_people": "Ljudje", + "search_filter_people_title": "Izberi osebe", "search_page_categories": "Kategorije", "search_page_favorites": "Priljubljene", "search_page_motion_photos": "Fotografije v gibanju", @@ -457,6 +484,7 @@ "search_page_places": "Lokacije", "search_page_recently_added": "Nedavno dodano", "search_page_screenshots": "Posnetki zaslona", + "search_page_search_photos_videos": "Poišči svoje fotografije in videoposnetke", "search_page_selfies": "Selfiji", "search_page_things": "Stvari", "search_page_videos": "Videoposnetki", @@ -469,6 +497,7 @@ "select_additional_user_for_sharing_page_suggestions": "Predlogi", "select_user_for_sharing_page_err_album": "Albuma ni bilo mogoče ustvariti", "select_user_for_sharing_page_share_suggestions": "Predlogi", + "server_endpoint": "Končna točka strežnika", "server_info_box_app_version": "Različica aplikacije", "server_info_box_latest_release": "Zadnja verzija", "server_info_box_server_url": "URL strežnika", @@ -480,6 +509,7 @@ "setting_image_viewer_preview_title": "Naloži predogled slike", "setting_image_viewer_title": "Slike", "setting_languages_apply": "Uporabi", + "setting_languages_subtitle": "Spremeni jezik aplikacije", "setting_languages_title": "Jeziki", "setting_notifications_notify_failures_grace_period": "Obvesti o napakah varnostnega kopiranja v ozadju: {}", "setting_notifications_notify_hours": "{} ur", @@ -560,9 +590,9 @@ "shared_link_info_chip_upload": "Naloži", "shared_link_manage_links": "Upravljanje povezav v skupni rabi", "shared_link_public_album": "Javni album", - "shared_links": "Shared links", + "shared_links": "Deljene povezave", "share_done": "Končano", - "shared_with_me": "Shared with me", + "shared_with_me": "Deljeno z mano", "share_invite": "Povabi v album", "sharing_page_album": "Albumi v skupni rabi", "sharing_page_description": "Ustvarite albume za skupno rabo fotografij in videoposnetkov z osebami v vašem omrežju.", @@ -570,32 +600,32 @@ "sharing_silver_appbar_create_shared_album": "Ustvari album v skupni rabi", "sharing_silver_appbar_shared_links": "Povezave skupne rabe", "sharing_silver_appbar_share_partner": "Deli z partnerjem", - "sync": "Sync", - "sync_albums": "Sync albums", - "sync_albums_manual_subtitle": "Sync all uploaded videos and photos to the selected backup albums", - "sync_upload_album_setting_subtitle": "Create and upload your photos and videos to the selected albums on Immich", + "sync": "Sinhronizacija", + "sync_albums": "Sinhronizacija albumov", + "sync_albums_manual_subtitle": "Sinhronizirajte vse naložene videoposnetke in fotografije v izbrane varnostne albume", + "sync_upload_album_setting_subtitle": "Ustvarite in naložite svoje fotografije in videoposnetke v izbrane albume na Immich", "tab_controller_nav_library": "Knjižnica", "tab_controller_nav_photos": "Slike", "tab_controller_nav_search": "Iskanje", "tab_controller_nav_sharing": "Deljeno", "theme_setting_asset_list_storage_indicator_title": "Pokaži indikator shrambe na ploščicah sredstev", "theme_setting_asset_list_tiles_per_row_title": "Število sredstev na vrstico ({})", - "theme_setting_colorful_interface_subtitle": "Apply primary color to background surfaces.", - "theme_setting_colorful_interface_title": "Colorful interface", + "theme_setting_colorful_interface_subtitle": "Nanesi primarno barvo na površine ozadja.", + "theme_setting_colorful_interface_title": "Barvit vmesnik", "theme_setting_dark_mode_switch": "Temni način", "theme_setting_image_viewer_quality_subtitle": "Prilagodite kakovost podrobnega pregledovalnika slik", "theme_setting_image_viewer_quality_title": "Kakovost pregledovalnika slik", - "theme_setting_primary_color_subtitle": "Pick a color for primary actions and accents.", - "theme_setting_primary_color_title": "Primary color", - "theme_setting_system_primary_color_title": "Use system color", + "theme_setting_primary_color_subtitle": "Izberi barvo za primarna dejanja in poudarke.", + "theme_setting_primary_color_title": "Primarna barva", + "theme_setting_system_primary_color_title": "Uporabi sistemsko barvo", "theme_setting_system_theme_switch": "Samodejno (Sledi nastavitvi sistema)", "theme_setting_theme_subtitle": "Izberi nastavitev teme aplikacije", "theme_setting_theme_title": "Tema", "theme_setting_three_stage_loading_subtitle": "Tristopenjsko nalaganje lahko poveča zmogljivost nalaganja, vendar povzroči znatno večjo obremenitev omrežja", "theme_setting_three_stage_loading_title": "Omogoči tristopenjsko nalaganje", "translated_text_options": "Možnosti", - "trash": "Trash", - "trash_emptied": "Emptied trash", + "trash": "Smetnjak", + "trash_emptied": "Smetnjak je izpraznjen", "trash_page_delete": "Izbriši", "trash_page_delete_all": "Izbriši vse", "trash_page_empty_trash_btn": "Izprazni smeti", @@ -612,14 +642,18 @@ "upload_dialog_info": "Ali želite varnostno kopirati izbrana sredstva na strežnik?", "upload_dialog_ok": "Naloži", "upload_dialog_title": "Naloži sredstvo", + "use_current_connection": "uporabi trenutno povezavo", + "validate_endpoint_error": "Vnesite veljaven URL", "version_announcement_overlay_ack": "Preverite", "version_announcement_overlay_release_notes": "opombe ob izdaji", "version_announcement_overlay_text_1": "Živjo prijatelj, na voljo je nova izdaja", "version_announcement_overlay_text_2": "vzemi si čas in obišči", "version_announcement_overlay_text_3": "in zagotovite, da sta vaša nastavitev docker-compose in .env posodobljena, da preprečite morebitne napačne konfiguracije, zlasti če uporabljate WatchTower ali kateri koli mehanizem, ki samodejno posodablja vašo strežniško aplikacijo.", "version_announcement_overlay_title": "Na voljo je nova različica strežnika \uD83C\uDF89", - "videos": "Videos", + "videos": "Videoposnetki", "viewer_remove_from_stack": "Odstrani iz sklada", "viewer_stack_use_as_main_asset": "Uporabi kot glavno sredstvo", - "viewer_unstack": "Razkladi" + "viewer_unstack": "Razkladi", + "wifi_name": "WiFi ime", + "your_wifi_name": "Vaše ime WiFi" } \ No newline at end of file diff --git a/mobile/assets/i18n/sr-Cyrl.json b/mobile/assets/i18n/sr-Cyrl.json index 0075f65de0557..a7f31f8440f7e 100644 --- a/mobile/assets/i18n/sr-Cyrl.json +++ b/mobile/assets/i18n/sr-Cyrl.json @@ -7,6 +7,7 @@ "action_common_select": "Select", "action_common_update": "Update", "add_a_name": "Add a name", + "add_endpoint": "Add endpoint", "add_to_album_bottom_sheet_added": "Added to {album}", "add_to_album_bottom_sheet_already_exists": "Already in {album}", "advanced_settings_log_level_title": "Log level: {}", @@ -65,7 +66,12 @@ "assets_restored_successfully": "{} asset(s) restored successfully", "assets_trashed": "{} asset(s) trashed", "assets_trashed_from_server": "{} asset(s) trashed from the Immich server", + "asset_viewer_settings_subtitle": "Manage your gallery viewer settings", "asset_viewer_settings_title": "Asset Viewer", + "automatic_endpoint_switching_subtitle": "Connect locally over designated Wi-Fi when available and use alternative connections elsewhere", + "automatic_endpoint_switching_title": "Automatic URL switching", + "background_location_permission": "Background location permission", + "background_location_permission_content": "In order to switch networks when running in the background, Immich must *always* have precise location access so the app can read the Wi-Fi network's name", "backup_album_selection_page_albums_device": "Albums on device ({})", "backup_album_selection_page_albums_tap": "Tap to include, double tap to exclude", "backup_album_selection_page_assets_scatter": "Assets can scatter across multiple albums. Thus, albums can be included or excluded during the backup process.", @@ -131,6 +137,7 @@ "backup_manual_success": "Success", "backup_manual_title": "Upload status", "backup_options_page_title": "Backup options", + "backup_setting_subtitle": "Manage background and foreground upload settings", "cache_settings_album_thumbnails": "Library page thumbnails ({} assets)", "cache_settings_clear_cache_button": "Clear cache", "cache_settings_clear_cache_button_title": "Clears the app's cache. This will significantly impact the app's performance until the cache has rebuilt.", @@ -149,11 +156,16 @@ "cache_settings_tile_subtitle": "Control the local storage behaviour", "cache_settings_tile_title": "Local Storage", "cache_settings_title": "Caching Settings", + "cancel": "Cancel", + "change_display_order": "Change display order", "change_password_form_confirm_password": "Confirm Password", "change_password_form_description": "Hi {name},\n\nThis is either the first time you are signing into the system or a request has been made to change your password. Please enter the new password below.", "change_password_form_new_password": "New Password", "change_password_form_password_mismatch": "Passwords do not match", "change_password_form_reenter_new_password": "Re-enter New Password", + "check_corrupt_asset_backup": "Check for corrupt asset backups", + "check_corrupt_asset_backup_button": "Perform check", + "check_corrupt_asset_backup_description": "Run this check only over Wi-Fi and once all assets have been backed-up. The procedure might take a few minutes.", "client_cert_dialog_msg_confirm": "OK", "client_cert_enter_password": "Enter Password", "client_cert_import": "Import", @@ -199,6 +211,7 @@ "crop": "Crop", "curated_location_page_title": "Places", "curated_object_page_title": "Things", + "current_server_address": "Current server address", "daily_title_text_date": "E, MMM dd", "daily_title_text_date_year": "E, MMM dd, yyyy", "date_format": "E, LLL d, y • h:mm a", @@ -235,6 +248,8 @@ "edit_date_time_dialog_timezone": "Timezone", "edit_image_title": "Edit", "edit_location_dialog_title": "Location", + "enter_wifi_name": "Enter WiFi name", + "error_change_sort_album": "Failed to change album sort order", "error_saving_image": "Error: {}", "exif_bottom_sheet_description": "Add Description...", "exif_bottom_sheet_details": "DETAILS", @@ -246,11 +261,15 @@ "experimental_settings_new_asset_list_title": "Enable experimental photo grid", "experimental_settings_subtitle": "Use at your own risk!", "experimental_settings_title": "Experimental", + "external_network": "External network", + "external_network_sheet_info": "When not on the preferred WiFi network, the app will connect to the server through the first of the below URLs it can reach, starting from top to bottom", "favorites": "Favorites", "favorites_page_no_favorites": "No favorite assets found", "favorites_page_title": "Favorites", "filename_search": "File name or extension", "filter": "Filter", + "get_wifiname_error": "Could not get Wi-Fi name. Make sure you have granted the necessary permissions and are connected to a Wi-Fi network", + "grant_permission": "Grant permission", "haptic_feedback_switch": "Enable haptic feedback", "haptic_feedback_title": "Haptic Feedback", "header_settings_add_header_tip": "Add Header", @@ -296,6 +315,10 @@ "library_page_sort_most_oldest_photo": "Oldest photo", "library_page_sort_most_recent_photo": "Most recent photo", "library_page_sort_title": "Album title", + "local_network": "Local network", + "local_network_sheet_info": "The app will connect to the server through this URL when using the specified Wi-Fi network", + "location_permission": "Location permission", + "location_permission_content": "In order to use the auto-switching feature, Immich needs precise location permission so it can read the current WiFi network's name", "location_picker_choose_on_map": "Choose on map", "location_picker_latitude": "Latitude", "location_picker_latitude_error": "Enter a valid latitude", @@ -365,6 +388,8 @@ "multiselect_grid_edit_date_time_err_read_only": "Cannot edit date of read only asset(s), skipping", "multiselect_grid_edit_gps_err_read_only": "Cannot edit location of read only asset(s), skipping", "my_albums": "My albums", + "networking_settings": "Networking", + "networking_subtitle": "Manage the server endpoint settings", "no_assets_to_show": "No assets to show", "no_name": "No name", "notification_permission_dialog_cancel": "Cancel", @@ -398,6 +423,7 @@ "permission_onboarding_permission_limited": "Permission limited. To let Immich backup and manage your entire gallery collection, grant photo and video permissions in Settings.", "permission_onboarding_request": "Immich requires permission to view your photos and videos.", "places": "Places", + "preferences_settings_subtitle": "Manage the app's preferences", "preferences_settings_title": "Preferences", "profile_drawer_app_logs": "Logs", "profile_drawer_client_out_of_date_major": "Mobile App is out of date. Please update to the latest major version.", @@ -412,6 +438,7 @@ "profile_drawer_trash": "Trash", "recently_added": "Recently added", "recently_added_page_title": "Recently Added", + "save": "Save", "save_to_gallery": "Save to gallery", "scaffold_body_error_occurred": "Error occurred", "search_albums": "Search albums", @@ -457,6 +484,7 @@ "search_page_places": "Places", "search_page_recently_added": "Recently added", "search_page_screenshots": "Screenshots", + "search_page_search_photos_videos": "Search for your photos and videos", "search_page_selfies": "Selfies", "search_page_things": "Things", "search_page_videos": "Videos", @@ -469,6 +497,7 @@ "select_additional_user_for_sharing_page_suggestions": "Suggestions", "select_user_for_sharing_page_err_album": "Failed to create album", "select_user_for_sharing_page_share_suggestions": "Suggestions", + "server_endpoint": "Server Endpoint", "server_info_box_app_version": "App Version", "server_info_box_latest_release": "Latest Version", "server_info_box_server_url": "Server URL", @@ -480,6 +509,7 @@ "setting_image_viewer_preview_title": "Load preview image", "setting_image_viewer_title": "Images", "setting_languages_apply": "Apply", + "setting_languages_subtitle": "Change the app's language", "setting_languages_title": "Languages", "setting_notifications_notify_failures_grace_period": "Notify background backup failures: {}", "setting_notifications_notify_hours": "{} hours", @@ -612,6 +642,8 @@ "upload_dialog_info": "Do you want to backup the selected Asset(s) to the server?", "upload_dialog_ok": "Upload", "upload_dialog_title": "Upload Asset", + "use_current_connection": "use current connection", + "validate_endpoint_error": "Please enter a valid URL", "version_announcement_overlay_ack": "Acknowledge", "version_announcement_overlay_release_notes": "release notes", "version_announcement_overlay_text_1": "Hi friend, there is a new release of", @@ -621,5 +653,7 @@ "videos": "Videos", "viewer_remove_from_stack": "Remove from Stack", "viewer_stack_use_as_main_asset": "Use as Main Asset", - "viewer_unstack": "Un-Stack" + "viewer_unstack": "Un-Stack", + "wifi_name": "WiFi Name", + "your_wifi_name": "Your WiFi name" } \ No newline at end of file diff --git a/mobile/assets/i18n/sr-Latn.json b/mobile/assets/i18n/sr-Latn.json index 3e11d73e08a7e..9042a277134a7 100644 --- a/mobile/assets/i18n/sr-Latn.json +++ b/mobile/assets/i18n/sr-Latn.json @@ -7,6 +7,7 @@ "action_common_select": "Select", "action_common_update": "Update", "add_a_name": "Add a name", + "add_endpoint": "Add endpoint", "add_to_album_bottom_sheet_added": "Dodato u {album}", "add_to_album_bottom_sheet_already_exists": "Već u {album}", "advanced_settings_log_level_title": "Log level: {}", @@ -65,7 +66,12 @@ "assets_restored_successfully": "{} asset(s) restored successfully", "assets_trashed": "{} asset(s) trashed", "assets_trashed_from_server": "{} asset(s) trashed from the Immich server", + "asset_viewer_settings_subtitle": "Manage your gallery viewer settings", "asset_viewer_settings_title": "Asset Viewer", + "automatic_endpoint_switching_subtitle": "Connect locally over designated Wi-Fi when available and use alternative connections elsewhere", + "automatic_endpoint_switching_title": "Automatic URL switching", + "background_location_permission": "Background location permission", + "background_location_permission_content": "In order to switch networks when running in the background, Immich must *always* have precise location access so the app can read the Wi-Fi network's name", "backup_album_selection_page_albums_device": "Albuma na uređaju ({})", "backup_album_selection_page_albums_tap": "Dodirni da uključiš, dodirni dvaput da isključiš", "backup_album_selection_page_assets_scatter": "Zapisi se mogu naći u više različitih albuma. Odatle albumi se mogu uključiti ili isključiti tokom procesa pravljenja pozadinskih kopija.", @@ -131,6 +137,7 @@ "backup_manual_success": "Success", "backup_manual_title": "Upload status", "backup_options_page_title": "Backup options", + "backup_setting_subtitle": "Manage background and foreground upload settings", "cache_settings_album_thumbnails": "Sličice na stranici biblioteke", "cache_settings_clear_cache_button": "Obriši keš memoriju", "cache_settings_clear_cache_button_title": "Ova opcija briše keš memoriju aplikacije. Ovo će bitno uticati na performanse aplikacije dok se keš memorija ne učita ponovo.", @@ -149,11 +156,16 @@ "cache_settings_tile_subtitle": "Control the local storage behaviour", "cache_settings_tile_title": "Local Storage", "cache_settings_title": "Opcije za keširanje", + "cancel": "Cancel", + "change_display_order": "Change display order", "change_password_form_confirm_password": "Ponovo unesite šifru", "change_password_form_description": "Ćao, {name}\n\nOvo je verovatno Vaše prvo pristupanje sistemu, ili je podnešen zahtev za promenu šifre. Molimo Vas, unesite novu šifru ispod", "change_password_form_new_password": "Nova šifra", "change_password_form_password_mismatch": "Šifre se ne podudaraju", "change_password_form_reenter_new_password": "Ponovo unesite novu šifru", + "check_corrupt_asset_backup": "Check for corrupt asset backups", + "check_corrupt_asset_backup_button": "Perform check", + "check_corrupt_asset_backup_description": "Run this check only over Wi-Fi and once all assets have been backed-up. The procedure might take a few minutes.", "client_cert_dialog_msg_confirm": "OK", "client_cert_enter_password": "Enter Password", "client_cert_import": "Import", @@ -199,6 +211,7 @@ "crop": "Crop", "curated_location_page_title": "Places", "curated_object_page_title": "Things", + "current_server_address": "Current server address", "daily_title_text_date": "E, MMM dd", "daily_title_text_date_year": "E, MMM dd, yyyy", "date_format": "E, LLL d, y • h:mm a", @@ -235,6 +248,8 @@ "edit_date_time_dialog_timezone": "Timezone", "edit_image_title": "Edit", "edit_location_dialog_title": "Location", + "enter_wifi_name": "Enter WiFi name", + "error_change_sort_album": "Failed to change album sort order", "error_saving_image": "Error: {}", "exif_bottom_sheet_description": "Dodaj opis...", "exif_bottom_sheet_details": "DETALJI", @@ -246,11 +261,15 @@ "experimental_settings_new_asset_list_title": "Aktiviraj eksperimentalni mrežni prikaz fotografija", "experimental_settings_subtitle": "Koristiti na sopstvenu odgovornost!", "experimental_settings_title": "Eksperimentalno", + "external_network": "External network", + "external_network_sheet_info": "When not on the preferred WiFi network, the app will connect to the server through the first of the below URLs it can reach, starting from top to bottom", "favorites": "Favorites", "favorites_page_no_favorites": "No favorite assets found", "favorites_page_title": "Omiljeno", "filename_search": "File name or extension", "filter": "Filter", + "get_wifiname_error": "Could not get Wi-Fi name. Make sure you have granted the necessary permissions and are connected to a Wi-Fi network", + "grant_permission": "Grant permission", "haptic_feedback_switch": "Enable haptic feedback", "haptic_feedback_title": "Haptic Feedback", "header_settings_add_header_tip": "Add Header", @@ -296,6 +315,10 @@ "library_page_sort_most_oldest_photo": "Oldest photo", "library_page_sort_most_recent_photo": "Most recent photo", "library_page_sort_title": "Naziv albuma", + "local_network": "Local network", + "local_network_sheet_info": "The app will connect to the server through this URL when using the specified Wi-Fi network", + "location_permission": "Location permission", + "location_permission_content": "In order to use the auto-switching feature, Immich needs precise location permission so it can read the current WiFi network's name", "location_picker_choose_on_map": "Choose on map", "location_picker_latitude": "Latitude", "location_picker_latitude_error": "Enter a valid latitude", @@ -365,6 +388,8 @@ "multiselect_grid_edit_date_time_err_read_only": "Cannot edit date of read only asset(s), skipping", "multiselect_grid_edit_gps_err_read_only": "Cannot edit location of read only asset(s), skipping", "my_albums": "My albums", + "networking_settings": "Networking", + "networking_subtitle": "Manage the server endpoint settings", "no_assets_to_show": "No assets to show", "no_name": "No name", "notification_permission_dialog_cancel": "Odustani", @@ -398,6 +423,7 @@ "permission_onboarding_permission_limited": "Permission limited. To let Immich backup and manage your entire gallery collection, grant photo and video permissions in Settings.", "permission_onboarding_request": "Immich requires permission to view your photos and videos.", "places": "Places", + "preferences_settings_subtitle": "Manage the app's preferences", "preferences_settings_title": "Preferences", "profile_drawer_app_logs": "Evidencija", "profile_drawer_client_out_of_date_major": "Mobile App is out of date. Please update to the latest major version.", @@ -412,6 +438,7 @@ "profile_drawer_trash": "Trash", "recently_added": "Recently added", "recently_added_page_title": "Recently Added", + "save": "Save", "save_to_gallery": "Save to gallery", "scaffold_body_error_occurred": "Error occurred", "search_albums": "Search albums", @@ -457,6 +484,7 @@ "search_page_places": "Mesta", "search_page_recently_added": "Recently added", "search_page_screenshots": "Screenshots", + "search_page_search_photos_videos": "Search for your photos and videos", "search_page_selfies": "Selfies", "search_page_things": "Stvari", "search_page_videos": "Videos", @@ -469,6 +497,7 @@ "select_additional_user_for_sharing_page_suggestions": "Sugsetije", "select_user_for_sharing_page_err_album": "Neuspešno kreiranje albuma", "select_user_for_sharing_page_share_suggestions": "Sugestije", + "server_endpoint": "Server Endpoint", "server_info_box_app_version": "Verzija Aplikacije", "server_info_box_latest_release": "Latest Version", "server_info_box_server_url": "Server URL", @@ -480,6 +509,7 @@ "setting_image_viewer_preview_title": "Pregledaj sliku", "setting_image_viewer_title": "Images", "setting_languages_apply": "Apply", + "setting_languages_subtitle": "Change the app's language", "setting_languages_title": "Languages", "setting_notifications_notify_failures_grace_period": "Neuspešne rezervne kopije: {}", "setting_notifications_notify_hours": "{} sati", @@ -612,6 +642,8 @@ "upload_dialog_info": "Do you want to backup the selected Asset(s) to the server?", "upload_dialog_ok": "Upload", "upload_dialog_title": "Upload Asset", + "use_current_connection": "use current connection", + "validate_endpoint_error": "Please enter a valid URL", "version_announcement_overlay_ack": "Priznati", "version_announcement_overlay_release_notes": "novine nove verzije", "version_announcement_overlay_text_1": "Ćao, nova verzija", @@ -621,5 +653,7 @@ "videos": "Videos", "viewer_remove_from_stack": "Remove from Stack", "viewer_stack_use_as_main_asset": "Use as Main Asset", - "viewer_unstack": "Un-Stack" + "viewer_unstack": "Un-Stack", + "wifi_name": "WiFi Name", + "your_wifi_name": "Your WiFi name" } \ No newline at end of file diff --git a/mobile/assets/i18n/sv-FI.json b/mobile/assets/i18n/sv-FI.json index 0075f65de0557..a7f31f8440f7e 100644 --- a/mobile/assets/i18n/sv-FI.json +++ b/mobile/assets/i18n/sv-FI.json @@ -7,6 +7,7 @@ "action_common_select": "Select", "action_common_update": "Update", "add_a_name": "Add a name", + "add_endpoint": "Add endpoint", "add_to_album_bottom_sheet_added": "Added to {album}", "add_to_album_bottom_sheet_already_exists": "Already in {album}", "advanced_settings_log_level_title": "Log level: {}", @@ -65,7 +66,12 @@ "assets_restored_successfully": "{} asset(s) restored successfully", "assets_trashed": "{} asset(s) trashed", "assets_trashed_from_server": "{} asset(s) trashed from the Immich server", + "asset_viewer_settings_subtitle": "Manage your gallery viewer settings", "asset_viewer_settings_title": "Asset Viewer", + "automatic_endpoint_switching_subtitle": "Connect locally over designated Wi-Fi when available and use alternative connections elsewhere", + "automatic_endpoint_switching_title": "Automatic URL switching", + "background_location_permission": "Background location permission", + "background_location_permission_content": "In order to switch networks when running in the background, Immich must *always* have precise location access so the app can read the Wi-Fi network's name", "backup_album_selection_page_albums_device": "Albums on device ({})", "backup_album_selection_page_albums_tap": "Tap to include, double tap to exclude", "backup_album_selection_page_assets_scatter": "Assets can scatter across multiple albums. Thus, albums can be included or excluded during the backup process.", @@ -131,6 +137,7 @@ "backup_manual_success": "Success", "backup_manual_title": "Upload status", "backup_options_page_title": "Backup options", + "backup_setting_subtitle": "Manage background and foreground upload settings", "cache_settings_album_thumbnails": "Library page thumbnails ({} assets)", "cache_settings_clear_cache_button": "Clear cache", "cache_settings_clear_cache_button_title": "Clears the app's cache. This will significantly impact the app's performance until the cache has rebuilt.", @@ -149,11 +156,16 @@ "cache_settings_tile_subtitle": "Control the local storage behaviour", "cache_settings_tile_title": "Local Storage", "cache_settings_title": "Caching Settings", + "cancel": "Cancel", + "change_display_order": "Change display order", "change_password_form_confirm_password": "Confirm Password", "change_password_form_description": "Hi {name},\n\nThis is either the first time you are signing into the system or a request has been made to change your password. Please enter the new password below.", "change_password_form_new_password": "New Password", "change_password_form_password_mismatch": "Passwords do not match", "change_password_form_reenter_new_password": "Re-enter New Password", + "check_corrupt_asset_backup": "Check for corrupt asset backups", + "check_corrupt_asset_backup_button": "Perform check", + "check_corrupt_asset_backup_description": "Run this check only over Wi-Fi and once all assets have been backed-up. The procedure might take a few minutes.", "client_cert_dialog_msg_confirm": "OK", "client_cert_enter_password": "Enter Password", "client_cert_import": "Import", @@ -199,6 +211,7 @@ "crop": "Crop", "curated_location_page_title": "Places", "curated_object_page_title": "Things", + "current_server_address": "Current server address", "daily_title_text_date": "E, MMM dd", "daily_title_text_date_year": "E, MMM dd, yyyy", "date_format": "E, LLL d, y • h:mm a", @@ -235,6 +248,8 @@ "edit_date_time_dialog_timezone": "Timezone", "edit_image_title": "Edit", "edit_location_dialog_title": "Location", + "enter_wifi_name": "Enter WiFi name", + "error_change_sort_album": "Failed to change album sort order", "error_saving_image": "Error: {}", "exif_bottom_sheet_description": "Add Description...", "exif_bottom_sheet_details": "DETAILS", @@ -246,11 +261,15 @@ "experimental_settings_new_asset_list_title": "Enable experimental photo grid", "experimental_settings_subtitle": "Use at your own risk!", "experimental_settings_title": "Experimental", + "external_network": "External network", + "external_network_sheet_info": "When not on the preferred WiFi network, the app will connect to the server through the first of the below URLs it can reach, starting from top to bottom", "favorites": "Favorites", "favorites_page_no_favorites": "No favorite assets found", "favorites_page_title": "Favorites", "filename_search": "File name or extension", "filter": "Filter", + "get_wifiname_error": "Could not get Wi-Fi name. Make sure you have granted the necessary permissions and are connected to a Wi-Fi network", + "grant_permission": "Grant permission", "haptic_feedback_switch": "Enable haptic feedback", "haptic_feedback_title": "Haptic Feedback", "header_settings_add_header_tip": "Add Header", @@ -296,6 +315,10 @@ "library_page_sort_most_oldest_photo": "Oldest photo", "library_page_sort_most_recent_photo": "Most recent photo", "library_page_sort_title": "Album title", + "local_network": "Local network", + "local_network_sheet_info": "The app will connect to the server through this URL when using the specified Wi-Fi network", + "location_permission": "Location permission", + "location_permission_content": "In order to use the auto-switching feature, Immich needs precise location permission so it can read the current WiFi network's name", "location_picker_choose_on_map": "Choose on map", "location_picker_latitude": "Latitude", "location_picker_latitude_error": "Enter a valid latitude", @@ -365,6 +388,8 @@ "multiselect_grid_edit_date_time_err_read_only": "Cannot edit date of read only asset(s), skipping", "multiselect_grid_edit_gps_err_read_only": "Cannot edit location of read only asset(s), skipping", "my_albums": "My albums", + "networking_settings": "Networking", + "networking_subtitle": "Manage the server endpoint settings", "no_assets_to_show": "No assets to show", "no_name": "No name", "notification_permission_dialog_cancel": "Cancel", @@ -398,6 +423,7 @@ "permission_onboarding_permission_limited": "Permission limited. To let Immich backup and manage your entire gallery collection, grant photo and video permissions in Settings.", "permission_onboarding_request": "Immich requires permission to view your photos and videos.", "places": "Places", + "preferences_settings_subtitle": "Manage the app's preferences", "preferences_settings_title": "Preferences", "profile_drawer_app_logs": "Logs", "profile_drawer_client_out_of_date_major": "Mobile App is out of date. Please update to the latest major version.", @@ -412,6 +438,7 @@ "profile_drawer_trash": "Trash", "recently_added": "Recently added", "recently_added_page_title": "Recently Added", + "save": "Save", "save_to_gallery": "Save to gallery", "scaffold_body_error_occurred": "Error occurred", "search_albums": "Search albums", @@ -457,6 +484,7 @@ "search_page_places": "Places", "search_page_recently_added": "Recently added", "search_page_screenshots": "Screenshots", + "search_page_search_photos_videos": "Search for your photos and videos", "search_page_selfies": "Selfies", "search_page_things": "Things", "search_page_videos": "Videos", @@ -469,6 +497,7 @@ "select_additional_user_for_sharing_page_suggestions": "Suggestions", "select_user_for_sharing_page_err_album": "Failed to create album", "select_user_for_sharing_page_share_suggestions": "Suggestions", + "server_endpoint": "Server Endpoint", "server_info_box_app_version": "App Version", "server_info_box_latest_release": "Latest Version", "server_info_box_server_url": "Server URL", @@ -480,6 +509,7 @@ "setting_image_viewer_preview_title": "Load preview image", "setting_image_viewer_title": "Images", "setting_languages_apply": "Apply", + "setting_languages_subtitle": "Change the app's language", "setting_languages_title": "Languages", "setting_notifications_notify_failures_grace_period": "Notify background backup failures: {}", "setting_notifications_notify_hours": "{} hours", @@ -612,6 +642,8 @@ "upload_dialog_info": "Do you want to backup the selected Asset(s) to the server?", "upload_dialog_ok": "Upload", "upload_dialog_title": "Upload Asset", + "use_current_connection": "use current connection", + "validate_endpoint_error": "Please enter a valid URL", "version_announcement_overlay_ack": "Acknowledge", "version_announcement_overlay_release_notes": "release notes", "version_announcement_overlay_text_1": "Hi friend, there is a new release of", @@ -621,5 +653,7 @@ "videos": "Videos", "viewer_remove_from_stack": "Remove from Stack", "viewer_stack_use_as_main_asset": "Use as Main Asset", - "viewer_unstack": "Un-Stack" + "viewer_unstack": "Un-Stack", + "wifi_name": "WiFi Name", + "your_wifi_name": "Your WiFi name" } \ No newline at end of file diff --git a/mobile/assets/i18n/sv-SE.json b/mobile/assets/i18n/sv-SE.json index 078f5780fc1af..26ecd8cbe30d6 100644 --- a/mobile/assets/i18n/sv-SE.json +++ b/mobile/assets/i18n/sv-SE.json @@ -6,7 +6,8 @@ "action_common_save": "Spara", "action_common_select": "Välj", "action_common_update": "Uppdatera", - "add_a_name": "Add a name", + "add_a_name": "Lägg till namn", + "add_endpoint": "Lägg till endpoint", "add_to_album_bottom_sheet_added": "Tillagd till {album}", "add_to_album_bottom_sheet_already_exists": "Redan i {album}", "advanced_settings_log_level_title": "Loggnivå: {}", @@ -22,7 +23,7 @@ "advanced_settings_troubleshooting_title": "Felsökning", "album_info_card_backup_album_excluded": "EXKLUDERAD", "album_info_card_backup_album_included": "INKLUDERAD", - "albums": "Albums", + "albums": "Album", "album_thumbnail_card_item": "1 objekt", "album_thumbnail_card_items": "{} objekt", "album_thumbnail_card_shared": " · Delad", @@ -38,13 +39,13 @@ "album_viewer_appbar_share_remove": "Ta bort från album", "album_viewer_appbar_share_to": "Dela Till", "album_viewer_page_share_add_users": "Lägg till användare", - "all": "All", + "all": "Alla", "all_people_page_title": "Personer", "all_videos_page_title": "Videor", "app_bar_signout_dialog_content": "Är du säker på att du vill logga ut?", "app_bar_signout_dialog_ok": "Ja", "app_bar_signout_dialog_title": "Logga ut", - "archived": "Archived", + "archived": "Arkiverade", "archive_page_no_archived_assets": "Inga arkiverade objekt hittade", "archive_page_title": "Arkiv ({})", "asset_action_delete_err_read_only": "Kan inte ta bort skrivskyddade objekt, hoppar över", @@ -65,7 +66,12 @@ "assets_restored_successfully": "{} objekt har återställts", "assets_trashed": "{} objekt raderade", "assets_trashed_from_server": "{} objekt raderade från Immich-servern", + "asset_viewer_settings_subtitle": "Hantera inställningar för gallerivisare", "asset_viewer_settings_title": "Objektvisare", + "automatic_endpoint_switching_subtitle": "Connect locally over designated Wi-Fi when available and use alternative connections elsewhere", + "automatic_endpoint_switching_title": "Automatisk URL-växling", + "background_location_permission": "Tillåtelse för bakgrundsplats", + "background_location_permission_content": "In order to switch networks when running in the background, Immich must *always* have precise location access so the app can read the Wi-Fi network's name", "backup_album_selection_page_albums_device": "Album på enhet ({})", "backup_album_selection_page_albums_tap": "Tryck en gång för att inkludera, tryck två gånger för att exkludera", "backup_album_selection_page_assets_scatter": "Objekt kan vara utspridda över flera album. Därför kan album inkluderas eller exkluderas under säkerhetskopieringsprocessen", @@ -131,6 +137,7 @@ "backup_manual_success": "Klart", "backup_manual_title": "Uppladdningsstatus", "backup_options_page_title": "Säkerhetskopieringsinställningar", + "backup_setting_subtitle": "Hantera inställningar för för- och bakgrundsuppladdning", "cache_settings_album_thumbnails": "Miniatyrbilder för bibliotek ({} bilder och videor)", "cache_settings_clear_cache_button": "Rensa cacheminnet", "cache_settings_clear_cache_button_title": "Rensar appens cacheminne. Detta kommer att avsevärt påverka appens prestanda tills cachen har byggts om.", @@ -149,11 +156,16 @@ "cache_settings_tile_subtitle": "Kontrollera beteende för lokal lagring", "cache_settings_tile_title": "Lokal Lagring", "cache_settings_title": "Cache Inställningar", + "cancel": "Avbryt", + "change_display_order": "Ändra visningsordning", "change_password_form_confirm_password": "Bekräfta lösenord", "change_password_form_description": "Hej {name},\n\nDet är antingen första gången du loggar in i systemet, eller så har det skett en förfrågan om återställning av ditt lösenord. Ange ditt nya lösenord nedan.", "change_password_form_new_password": "Nytt lösenord", "change_password_form_password_mismatch": "Lösenorden matchar inte", "change_password_form_reenter_new_password": "Ange Nytt Lösenord Igen", + "check_corrupt_asset_backup": "Check for corrupt asset backups", + "check_corrupt_asset_backup_button": "Kontrollera", + "check_corrupt_asset_backup_description": "Kör kontrollen endast över Wi-Fi och när alla resurser har säkerhetskopierats. Det kan ta några minuter.", "client_cert_dialog_msg_confirm": "OK", "client_cert_enter_password": "Ange Lösenord", "client_cert_import": "Importera", @@ -189,9 +201,9 @@ "control_bottom_app_bar_unarchive": "Avarkivera", "control_bottom_app_bar_unfavorite": "Avfavorisera", "control_bottom_app_bar_upload": "Ladda Upp", - "create_album": "Create album", + "create_album": "Skapa album", "create_album_page_untitled": "Namnlös", - "create_new": "CREATE NEW", + "create_new": "SKAPA NY", "create_shared_album_page_create": "Skapa", "create_shared_album_page_share": "Dela", "create_shared_album_page_share_add_assets": "LÄGG TILL OBJEKT", @@ -199,6 +211,7 @@ "crop": "Beskär", "curated_location_page_title": "Platser", "curated_object_page_title": "Objekt", + "current_server_address": "Aktuell server-adress", "daily_title_text_date": "E, dd MMM", "daily_title_text_date_year": "E, dd MMM, yyyy", "date_format": "E d. LLL y • hh:mm", @@ -235,6 +248,8 @@ "edit_date_time_dialog_timezone": "Tidszon", "edit_image_title": "Redigera", "edit_location_dialog_title": "Plats", + "enter_wifi_name": "Ange WiFi-namn", + "error_change_sort_album": "Kunde inte ändra sorteringsordning för album", "error_saving_image": "Fel: {}", "exif_bottom_sheet_description": "Lägg till beskrivning...", "exif_bottom_sheet_details": "DETALJER", @@ -246,11 +261,15 @@ "experimental_settings_new_asset_list_title": "Aktivera experimentellt fotorutnät", "experimental_settings_subtitle": "Använd på egen risk!", "experimental_settings_title": "Experimentellt", - "favorites": "Favorites", + "external_network": "Externt nätverk", + "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", + "favorites": "Favoriter", "favorites_page_no_favorites": "Inga favoritobjekt hittades", "favorites_page_title": "Favoriter", "filename_search": "Filnamn eller filändelse", "filter": "Filter", + "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", + "grant_permission": "Ge tillåtelse", "haptic_feedback_switch": "Aktivera haptisk feedback", "haptic_feedback_title": "Haptisk Feedback", "header_settings_add_header_tip": "Lägg Till Header", @@ -274,8 +293,8 @@ "home_page_first_time_notice": "Om det här är första gången du använder appen, välj ett eller flera backup-album så att tidslinjen kan fyllas med foton och videor från albumen.", "home_page_share_err_local": "Kan inte dela lokalt objekt via länk, hoppar över", "home_page_upload_err_limit": "Kan bara ladda upp max 30 objekt åt gången, hoppar över", - "ignore_icloud_photos": "Ignore iCloud photos", - "ignore_icloud_photos_description": "Photos that are stored on iCloud will not be uploaded to the Immich server", + "ignore_icloud_photos": "Ignorera iCloud-foton", + "ignore_icloud_photos_description": "Foton lagrade i iCloud kommer inte laddas upp till Immich-servern", "image_saved_successfully": "Bild sparad", "image_viewer_page_state_provider_download_error": "Fel Vid Nedladdning", "image_viewer_page_state_provider_download_started": "Nedladdning Påbörjad", @@ -283,7 +302,7 @@ "image_viewer_page_state_provider_share_error": "Delningsfel", "invalid_date": "Felaktigt datum", "invalid_date_format": "Felaktigt datumformat", - "library": "Library", + "library": "Bibliotek", "library_page_albums": "Album", "library_page_archive": "Arkiv", "library_page_device_albums": "Album på Enheten", @@ -296,6 +315,10 @@ "library_page_sort_most_oldest_photo": "Äldsta foto", "library_page_sort_most_recent_photo": "Senaste foto", "library_page_sort_title": "Albumtitel", + "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", + "location_permission_content": "In order to use the auto-switching feature, Immich needs precise location permission so it can read the current WiFi network's name", "location_picker_choose_on_map": "Välj på karta", "location_picker_latitude": "Latitud", "location_picker_latitude_error": "Ange en giltig latitud", @@ -364,7 +387,9 @@ "motion_photos_page_title": "Rörelsefoton", "multiselect_grid_edit_date_time_err_read_only": "Kan inte ändra datum på skrivskyddade objekt, hoppar över", "multiselect_grid_edit_gps_err_read_only": "Kan inte ändra plats på skrivskyddade objekt, hoppar över", - "my_albums": "My albums", + "my_albums": "Mina album", + "networking_settings": "Nätverk", + "networking_subtitle": "Hantera inställningar för server-endpointen", "no_assets_to_show": "Inga objekt att visa", "no_name": "Inget namn", "notification_permission_dialog_cancel": "Avbryt", @@ -373,7 +398,7 @@ "notification_permission_list_tile_content": "Tillåt rättighet för att slå på notiser.", "notification_permission_list_tile_enable_button": "Aktivera Notiser", "notification_permission_list_tile_title": "Notisrättighet", - "on_this_device": "On this device", + "on_this_device": "På enheten", "partner_list_user_photos": "{user}s foton", "partner_list_view_all": "Visa alla", "partner_page_add_partner": "Lägg till partner", @@ -385,8 +410,8 @@ "partner_page_stop_sharing_content": "{} kommer inte längre att komma åt dina foton.", "partner_page_stop_sharing_title": "Sluta dela dina foton?", "partner_page_title": "Partner", - "partners": "Partners", - "people": "People", + "partners": "Partner", + "people": "Människor", "permission_onboarding_back": "Bakåt", "permission_onboarding_continue_anyway": "Fortsätt ändå", "permission_onboarding_get_started": "Kom igång", @@ -397,7 +422,8 @@ "permission_onboarding_permission_granted": "Rättigheten beviljad! Du är klar.", "permission_onboarding_permission_limited": "Rättighet begränsad. För att låta Immich säkerhetskopiera och hantera hela ditt galleri, tillåt foto- och video-rättigheter i Inställningar.", "permission_onboarding_request": "Immich kräver tillstånd för att se dina foton och videor.", - "places": "Places", + "places": "Platser", + "preferences_settings_subtitle": "Hantera appens inställningar", "preferences_settings_title": "Inställningar", "profile_drawer_app_logs": "Loggar", "profile_drawer_client_out_of_date_major": "Mobilappen är utdaterad. Uppdatera till senaste huvudversionen.", @@ -410,11 +436,12 @@ "profile_drawer_settings": "Inställningar", "profile_drawer_sign_out": "Logga ut", "profile_drawer_trash": "Papperskorg", - "recently_added": "Recently added", + "recently_added": "Nyligen tillagda", "recently_added_page_title": "Nyligen tillagda", + "save": "Spara", "save_to_gallery": "Spara i galleri", "scaffold_body_error_occurred": "Fel uppstod", - "search_albums": "Search albums", + "search_albums": "Sök i album", "search_bar_hint": "Sök bland dina foton", "search_filter_apply": "Aktivera filter", "search_filter_camera": "Kamera", @@ -457,6 +484,7 @@ "search_page_places": "Platser", "search_page_recently_added": "Nyligen tillagda", "search_page_screenshots": "Skärmdumpar", + "search_page_search_photos_videos": "Sök efter dina foton och videor", "search_page_selfies": "Selfies", "search_page_things": "Objekt", "search_page_videos": "Videor", @@ -469,6 +497,7 @@ "select_additional_user_for_sharing_page_suggestions": "Förslag", "select_user_for_sharing_page_err_album": "Kunde inte skapa nytt album", "select_user_for_sharing_page_share_suggestions": "Förslag", + "server_endpoint": "Server-endpoint", "server_info_box_app_version": "App-version", "server_info_box_latest_release": "Senaste Version", "server_info_box_server_url": "Server-URL", @@ -480,6 +509,7 @@ "setting_image_viewer_preview_title": "Ladda förhandsgranskning av bild", "setting_image_viewer_title": "Bilder", "setting_languages_apply": "Verkställ", + "setting_languages_subtitle": "Ändra appens språk", "setting_languages_title": "Språk", "setting_notifications_notify_failures_grace_period": "Rapportera säkerhetskopieringsfel i bakgrunden: {}", "setting_notifications_notify_hours": "{} timmar", @@ -560,9 +590,9 @@ "shared_link_info_chip_upload": "Ladda upp", "shared_link_manage_links": "Hantera Delade länkar", "shared_link_public_album": "Publikt album", - "shared_links": "Shared links", + "shared_links": "Delade länkar", "share_done": "Klart", - "shared_with_me": "Shared with me", + "shared_with_me": "Delade med mig", "share_invite": "Bjuder in till album", "sharing_page_album": "Delade album", "sharing_page_description": "Skapa delade album för att dela foton och video med personer i ditt nätverk.", @@ -594,7 +624,7 @@ "theme_setting_three_stage_loading_subtitle": "Trestegsladdning kan öka prestandan, men kan också leda till signifikant högre nätverksbelastning", "theme_setting_three_stage_loading_title": "Aktivera trestegsladdning", "translated_text_options": "Val", - "trash": "Trash", + "trash": "Papperskorg", "trash_emptied": "Tömd papperskorg", "trash_page_delete": "Ta Bort", "trash_page_delete_all": "Ta Bort Alla", @@ -612,14 +642,18 @@ "upload_dialog_info": "Vill du säkerhetskopiera de valda objekten till servern?", "upload_dialog_ok": "Ladda Upp", "upload_dialog_title": "Ladda Upp Objekt", + "use_current_connection": "Använd aktuell anslutning", + "validate_endpoint_error": "Ange en giltig URL", "version_announcement_overlay_ack": "Bekräfta", "version_announcement_overlay_release_notes": "versionsinformation", "version_announcement_overlay_text_1": "Hej vännen, det finns en ny version av", "version_announcement_overlay_text_2": ". Ta gärna din tid att besöka ", "version_announcement_overlay_text_3": " för att se till att din docker-compose och .env-fil är uppdaterad för att undvika felkonfiguration, speciellt om du använder WatchTower eller liknande mekanism som automatiskt uppdaterar din container", "version_announcement_overlay_title": "Ny server-version finns tillgänglig \uD83C\uDF89", - "videos": "Videos", + "videos": "Videor", "viewer_remove_from_stack": "Ta bort från Stapeln", "viewer_stack_use_as_main_asset": "Använd som Huvudobjekt", - "viewer_unstack": "Stapla Av" + "viewer_unstack": "Stapla Av", + "wifi_name": "WiFi-namn", + "your_wifi_name": "Ditt WiFi-namn" } \ No newline at end of file diff --git a/mobile/assets/i18n/th-TH.json b/mobile/assets/i18n/th-TH.json index b6013ceed4685..d9ad20f50c81c 100644 --- a/mobile/assets/i18n/th-TH.json +++ b/mobile/assets/i18n/th-TH.json @@ -7,6 +7,7 @@ "action_common_select": "Select", "action_common_update": "อัปเดต", "add_a_name": "Add a name", + "add_endpoint": "Add endpoint", "add_to_album_bottom_sheet_added": "เพิ่มไปยัง {album}", "add_to_album_bottom_sheet_already_exists": "อยู่ใน {album} อยู่แล้ว", "advanced_settings_log_level_title": "ระดับการ Log: {}", @@ -65,7 +66,12 @@ "assets_restored_successfully": "{} asset(s) restored successfully", "assets_trashed": "{} asset(s) trashed", "assets_trashed_from_server": "{} asset(s) trashed from the Immich server", + "asset_viewer_settings_subtitle": "Manage your gallery viewer settings", "asset_viewer_settings_title": "ตัวดูทรัพยากร", + "automatic_endpoint_switching_subtitle": "Connect locally over designated Wi-Fi when available and use alternative connections elsewhere", + "automatic_endpoint_switching_title": "Automatic URL switching", + "background_location_permission": "Background location permission", + "background_location_permission_content": "In order to switch networks when running in the background, Immich must *always* have precise location access so the app can read the Wi-Fi network's name", "backup_album_selection_page_albums_device": "อัลบั้มบนเครื่อง ({})", "backup_album_selection_page_albums_tap": "กดเพื่อรวม กดสองครั้งเพื่อยกเว้น", "backup_album_selection_page_assets_scatter": "ทรัพยาการสามารถกระจายไปในหลายอัลบั้ม ดังนั้นอัลบั้มสามารถถูกรวมหรือยกเว้นในกระบวนการสำรองข้อมูล", @@ -131,6 +137,7 @@ "backup_manual_success": "สำเร็จ", "backup_manual_title": "สถานะอัพโหลด", "backup_options_page_title": "ตัวเลือกการสำรองข้อมูล", + "backup_setting_subtitle": "Manage background and foreground upload settings", "cache_settings_album_thumbnails": "รูปย่อคลังภาพ ({} ทรัพยากร)", "cache_settings_clear_cache_button": "ล้างแคช", "cache_settings_clear_cache_button_title": "ล้างแคชของแอพ จะส่งผลกระทบต่อประสิทธิภาพแอพจนกว่าแคชจะถูกสร้างใหม่", @@ -149,11 +156,16 @@ "cache_settings_tile_subtitle": "ควบคุมพฤติกรรมของที่จัดเก็บในตัวเครื่อง", "cache_settings_tile_title": "ที่จัดเก็บในตัวเครื่อง", "cache_settings_title": "ตั้งค่าแคช", + "cancel": "Cancel", + "change_display_order": "Change display order", "change_password_form_confirm_password": "ยืนยันรหัสผ่าน", "change_password_form_description": "สวัสดี {name},\n\nครั้งนี้อาจจะเป็นครั้งแรกที่คุณเข้าสู่ระบบ หรือมีคำขอเพื่อที่จะเปลี่ยนรหัสผ่านของคุI กรุณาเพิ่มรหัสผ่านใหม่ข้างล่าง", "change_password_form_new_password": "รหัสผ่านใหม่", "change_password_form_password_mismatch": "รหัสผ่านไม่ตรงกัน", "change_password_form_reenter_new_password": "กรอกรหัสผ่านใหม่", + "check_corrupt_asset_backup": "Check for corrupt asset backups", + "check_corrupt_asset_backup_button": "Perform check", + "check_corrupt_asset_backup_description": "Run this check only over Wi-Fi and once all assets have been backed-up. The procedure might take a few minutes.", "client_cert_dialog_msg_confirm": "OK", "client_cert_enter_password": "Enter Password", "client_cert_import": "Import", @@ -199,6 +211,7 @@ "crop": "Crop", "curated_location_page_title": "สถานที่", "curated_object_page_title": "สิ่งของ", + "current_server_address": "Current server address", "daily_title_text_date": "E dd MMM", "daily_title_text_date_year": "E dd MMM yyyy", "date_format": "E, LLL d, y • h:mm a", @@ -235,6 +248,8 @@ "edit_date_time_dialog_timezone": "เขดเวลา", "edit_image_title": "Edit", "edit_location_dialog_title": "ตำแหน่ง", + "enter_wifi_name": "Enter WiFi name", + "error_change_sort_album": "Failed to change album sort order", "error_saving_image": "Error: {}", "exif_bottom_sheet_description": "เพิ่มคำอธิบาย", "exif_bottom_sheet_details": "รายละเอียด", @@ -246,11 +261,15 @@ "experimental_settings_new_asset_list_title": "เปิดตารางรูปภาพที่กำลังทดลอง", "experimental_settings_subtitle": "ใช้ภายใต้ความเสี่ยงของคุณเอง!", "experimental_settings_title": "ทดลอง", + "external_network": "External network", + "external_network_sheet_info": "When not on the preferred WiFi network, the app will connect to the server through the first of the below URLs it can reach, starting from top to bottom", "favorites": "Favorites", "favorites_page_no_favorites": "ไม่พบทรัพยากรในรายการโปรด", "favorites_page_title": "รายการโปรด", "filename_search": "File name or extension", "filter": "Filter", + "get_wifiname_error": "Could not get Wi-Fi name. Make sure you have granted the necessary permissions and are connected to a Wi-Fi network", + "grant_permission": "Grant permission", "haptic_feedback_switch": "เปิดการตอบสนองแบบสัมผัส", "haptic_feedback_title": "การตอบสนองแบบสัมผัส", "header_settings_add_header_tip": "Add Header", @@ -296,6 +315,10 @@ "library_page_sort_most_oldest_photo": "รูปภาพที่เก่าที่สุด", "library_page_sort_most_recent_photo": "รูปล่าสุด", "library_page_sort_title": "ชื่ออัลบั้ม", + "local_network": "Local network", + "local_network_sheet_info": "The app will connect to the server through this URL when using the specified Wi-Fi network", + "location_permission": "Location permission", + "location_permission_content": "In order to use the auto-switching feature, Immich needs precise location permission so it can read the current WiFi network's name", "location_picker_choose_on_map": "เลือกบนแผนที่", "location_picker_latitude": "ละติจูต", "location_picker_latitude_error": "กรุณาเพิ่มละติจูตที่ถูกต้อง", @@ -365,6 +388,8 @@ "multiselect_grid_edit_date_time_err_read_only": "ไม่สามารถแก้ไขวันที่ทรัพยากรแบบอ่านอย่างเดียว กำลังข้าม", "multiselect_grid_edit_gps_err_read_only": "ไม่สามารถแก้ตำแหน่งของทรัพยากรแบบอ่านอย่างเดียว กำลังข้าม", "my_albums": "My albums", + "networking_settings": "Networking", + "networking_subtitle": "Manage the server endpoint settings", "no_assets_to_show": "ไม่มีทรัพยากรให้แสดง", "no_name": "No name", "notification_permission_dialog_cancel": "ยกเลิก", @@ -398,6 +423,7 @@ "permission_onboarding_permission_limited": "สิทธ์จำกัด เพื่อให้ Immich สำรองข้อมูลและจัดการคลังภาพได้ ตั้งค่าสิทธิเข้าถึงรูปภาพและวิดีโอ", "permission_onboarding_request": "Immich จำเป็นจะต้องได้รับสิทธิ์ดูรูปภาพและวิดีโอ", "places": "Places", + "preferences_settings_subtitle": "Manage the app's preferences", "preferences_settings_title": "การตั้งค่า", "profile_drawer_app_logs": "การบันทึก", "profile_drawer_client_out_of_date_major": "แอปพลิเคชันมีอัพเดต โปรดอัปเดตเป็นเวอร์ชันหลักล่าสุด", @@ -412,6 +438,7 @@ "profile_drawer_trash": "ขยะ", "recently_added": "Recently added", "recently_added_page_title": "เพิ่มล่าสุด", + "save": "Save", "save_to_gallery": "Save to gallery", "scaffold_body_error_occurred": "เกิดข้อผิดพลาด", "search_albums": "Search albums", @@ -457,6 +484,7 @@ "search_page_places": "สถานที่", "search_page_recently_added": "เพิ่มล่าสุด", "search_page_screenshots": "แคปหน้าจอ", + "search_page_search_photos_videos": "Search for your photos and videos", "search_page_selfies": "เซลฟี่", "search_page_things": "สิ่งของ", "search_page_videos": "วิดีโอ", @@ -469,6 +497,7 @@ "select_additional_user_for_sharing_page_suggestions": "ข้อเสนอแนะ", "select_user_for_sharing_page_err_album": "สร้างอัลบั้มล้มเหลว", "select_user_for_sharing_page_share_suggestions": "ข้อเสนอแนะ", + "server_endpoint": "Server Endpoint", "server_info_box_app_version": "เวอร์ชันแอพ", "server_info_box_latest_release": "เวอร์ชันล่าสุด", "server_info_box_server_url": "URL เซิร์ฟเวอร์", @@ -480,6 +509,7 @@ "setting_image_viewer_preview_title": "โหลดรูปภาพตัวอย่าง", "setting_image_viewer_title": "รูปภาพ", "setting_languages_apply": "บันทึก", + "setting_languages_subtitle": "Change the app's language", "setting_languages_title": "ภาษา", "setting_notifications_notify_failures_grace_period": "แจ้งการสำรองข้อมูลในเบื้องหลังล้มเหลว: {}", "setting_notifications_notify_hours": "{} ชั่วโมง", @@ -612,6 +642,8 @@ "upload_dialog_info": "คุณต้องการอัพโหลดทรัพยากรดังกล่าวบนเซิร์ฟเวอร์หรือไม่?", "upload_dialog_ok": "อัปโหลด", "upload_dialog_title": "อัปโหลดทรัพยากร", + "use_current_connection": "use current connection", + "validate_endpoint_error": "Please enter a valid URL", "version_announcement_overlay_ack": "รับทราบ", "version_announcement_overlay_release_notes": "รายงานการอัพเดท", "version_announcement_overlay_text_1": "สวัสดีเพื่อน ขณะนี้มีเวอร์ชั้นใหม่ของ", @@ -621,5 +653,7 @@ "videos": "Videos", "viewer_remove_from_stack": "เอาออกจากที่ซ้อน", "viewer_stack_use_as_main_asset": "ใช้เป็นทรัพยากรหลัก", - "viewer_unstack": "หยุดซ้อน" + "viewer_unstack": "หยุดซ้อน", + "wifi_name": "WiFi Name", + "your_wifi_name": "Your WiFi name" } \ No newline at end of file diff --git a/mobile/assets/i18n/uk-UA.json b/mobile/assets/i18n/uk-UA.json index 8bdd9aeaf2339..3c4303e6a7538 100644 --- a/mobile/assets/i18n/uk-UA.json +++ b/mobile/assets/i18n/uk-UA.json @@ -6,8 +6,9 @@ "action_common_save": "Зберегти", "action_common_select": "Вибрати", "action_common_update": "Оновити", - "add_a_name": "Add a name", - "add_to_album_bottom_sheet_added": "Додати до {album}", + "add_a_name": "Додати ім'я", + "add_endpoint": "Add endpoint", + "add_to_album_bottom_sheet_added": "Додано до {album}", "add_to_album_bottom_sheet_already_exists": "Вже є в {album}", "advanced_settings_log_level_title": "Log level: {}", "advanced_settings_prefer_remote_subtitle": "Деякі пристрої вельми повільно завантажують мініатюри із елементів на пристрої. Активуйте для завантаження віддалених мініатюр натомість.", @@ -22,7 +23,7 @@ "advanced_settings_troubleshooting_title": "Усунення несправностей", "album_info_card_backup_album_excluded": "ВИЛУЧЕНИЙ", "album_info_card_backup_album_included": "ВКЛЮЧЕНИЙ", - "albums": "Albums", + "albums": "Альбоми", "album_thumbnail_card_item": "1 елемент", "album_thumbnail_card_items": "{} елементів", "album_thumbnail_card_shared": " · Спільний", @@ -38,13 +39,13 @@ "album_viewer_appbar_share_remove": "Видалити з альбому", "album_viewer_appbar_share_to": "Поділитися", "album_viewer_page_share_add_users": "Додати користувачів", - "all": "All", + "all": "Усі", "all_people_page_title": "Люди", "all_videos_page_title": "Відео", "app_bar_signout_dialog_content": "Ви впевнені, що бажаєте вийти з аккаунта?", "app_bar_signout_dialog_ok": "Так", "app_bar_signout_dialog_title": "Вийти з аккаунта", - "archived": "Archived", + "archived": "Архів", "archive_page_no_archived_assets": "Немає архівних елементів", "archive_page_title": "Архів ({})", "asset_action_delete_err_read_only": "Неможливо видалити елемент(и) лише для читання, пропущено", @@ -65,7 +66,12 @@ "assets_restored_successfully": "{} елемент(и) успішно відновлено", "assets_trashed": "{} елемент(и) поміщено до кошика", "assets_trashed_from_server": "{} елемент(и) поміщено до кошика на сервері Immich", + "asset_viewer_settings_subtitle": "Manage your gallery viewer settings", "asset_viewer_settings_title": "Переглядач зображень", + "automatic_endpoint_switching_subtitle": "Connect locally over designated Wi-Fi when available and use alternative connections elsewhere", + "automatic_endpoint_switching_title": "Automatic URL switching", + "background_location_permission": "Background location permission", + "background_location_permission_content": "In order to switch networks when running in the background, Immich must *always* have precise location access so the app can read the Wi-Fi network's name", "backup_album_selection_page_albums_device": "Альбоми на пристрої ({})", "backup_album_selection_page_albums_tap": "Торкніться, щоб включити,\nторкніться двічі, щоб виключити", "backup_album_selection_page_assets_scatter": "Елементи можуть належати до кількох альбомів водночас. Таким чином, альбоми можуть бути включені або вилучені під час резервного копіювання.", @@ -131,6 +137,7 @@ "backup_manual_success": "Успіх", "backup_manual_title": "Стан завантаження", "backup_options_page_title": "Резервне копіювання", + "backup_setting_subtitle": "Manage background and foreground upload settings", "cache_settings_album_thumbnails": "Мініатюри сторінок бібліотеки ({} елементи)", "cache_settings_clear_cache_button": "Очистити кеш", "cache_settings_clear_cache_button_title": "Очищає кеш програми. Це суттєво знизить продуктивність програми, доки кеш не буде перебудовано.", @@ -149,11 +156,16 @@ "cache_settings_tile_subtitle": "Керування поведінкою локального сховища", "cache_settings_tile_title": "Локальне сховище", "cache_settings_title": "Налаштування кешування", + "cancel": "Cancel", + "change_display_order": "Change display order", "change_password_form_confirm_password": "Підтвердити пароль", "change_password_form_description": "Привіт {name},\n\nВи або або вперше входите у систему, або було зроблено запит на зміну вашого пароля. \nВведіть ваш новий пароль.", "change_password_form_new_password": "Новий пароль", "change_password_form_password_mismatch": "Паролі не співпадають", "change_password_form_reenter_new_password": "Повторіть новий пароль", + "check_corrupt_asset_backup": "Check for corrupt asset backups", + "check_corrupt_asset_backup_button": "Perform check", + "check_corrupt_asset_backup_description": "Run this check only over Wi-Fi and once all assets have been backed-up. The procedure might take a few minutes.", "client_cert_dialog_msg_confirm": "OK", "client_cert_enter_password": "Введіть пароль", "client_cert_import": "Імпорт", @@ -189,9 +201,9 @@ "control_bottom_app_bar_unarchive": "Розархівувати", "control_bottom_app_bar_unfavorite": "Видалити з улюблених", "control_bottom_app_bar_upload": "Завантажити", - "create_album": "Create album", + "create_album": "Створити альбом", "create_album_page_untitled": "Без назви", - "create_new": "CREATE NEW", + "create_new": "СТВОРИТИ НОВИЙ", "create_shared_album_page_create": "Створити", "create_shared_album_page_share": "Поділитися", "create_shared_album_page_share_add_assets": "ДОДАТИ ЕЛЕМЕНТИ", @@ -199,6 +211,7 @@ "crop": "Кадрувати", "curated_location_page_title": "Місця", "curated_object_page_title": "Речі", + "current_server_address": "Current server address", "daily_title_text_date": "E, MMM dd", "daily_title_text_date_year": "E, MMM dd, yyyy", "date_format": "E, LLL d, y • h:mm a", @@ -216,8 +229,8 @@ "delete_shared_link_dialog_title": "Видалити спільне посилання", "description_input_hint_text": "Додати опис...", "description_input_submit_error": "Помилка оновлення опису, перевірте логи для подробиць", - "download_canceled": "\nЗавантаження скасовано", - "download_complete": "\nЗавантаження закінчено", + "download_canceled": "Завантаження скасовано", + "download_complete": "Завантаження закінчено", "download_enqueue": "Завантаження поставлено в чергу", "download_error": "Помилка завантаження", "download_failed": "Завантаження не вдалося", @@ -226,7 +239,7 @@ "downloading": "Завантаження...", "downloading_media": "Завантаження медіа", "download_notfound": "Завантаження не виявлено", - "download_paused": "\nЗавантаження призупинено", + "download_paused": "Завантаження призупинено", "download_started": "Завантаження розпочато", "download_sucess": "Успішне завантаження", "download_sucess_android": "Медіафайли завантажено в DCIM/Immich", @@ -235,6 +248,8 @@ "edit_date_time_dialog_timezone": "Часовий пояс", "edit_image_title": "Редагувати", "edit_location_dialog_title": "Місцезнаходження", + "enter_wifi_name": "Enter WiFi name", + "error_change_sort_album": "Failed to change album sort order", "error_saving_image": "Помилка: {}", "exif_bottom_sheet_description": "Додати опис...", "exif_bottom_sheet_details": "ПОДРОБИЦІ", @@ -246,11 +261,15 @@ "experimental_settings_new_asset_list_title": "Експериментальний макет знімків", "experimental_settings_subtitle": "На власний ризик!", "experimental_settings_title": "Експериментальні", - "favorites": "Favorites", + "external_network": "External network", + "external_network_sheet_info": "When not on the preferred WiFi network, the app will connect to the server through the first of the below URLs it can reach, starting from top to bottom", + "favorites": "Вибране", "favorites_page_no_favorites": "Немає улюблених елементів", "favorites_page_title": "Улюблені", "filename_search": "Ім'я або розширення файлу", "filter": "Фільтр", + "get_wifiname_error": "Could not get Wi-Fi name. Make sure you have granted the necessary permissions and are connected to a Wi-Fi network", + "grant_permission": "Grant permission", "haptic_feedback_switch": "Увімкнути тактильну віддачу", "haptic_feedback_title": "Тактильна віддача", "header_settings_add_header_tip": "Додати заголовок", @@ -274,8 +293,8 @@ "home_page_first_time_notice": "Якщо ви вперше користуєтеся програмою, переконайтеся, що ви вибрали альбоми для резервування, щоб могти заповнювати хронологію знімків та відео в альбомах.", "home_page_share_err_local": "Неможливо поділитися локальними елементами через посилання, пропущено", "home_page_upload_err_limit": "Можна вантажити не більше 30 елементів водночас, пропущено", - "ignore_icloud_photos": "Ignore iCloud photos", - "ignore_icloud_photos_description": "Photos that are stored on iCloud will not be uploaded to the Immich server", + "ignore_icloud_photos": "Пропускати файли з iCloud", + "ignore_icloud_photos_description": "Не завантажувати файли в Immich, якщо вони зберігаються в iCloud", "image_saved_successfully": "Зображення збережено", "image_viewer_page_state_provider_download_error": "Помилка завантаження", "image_viewer_page_state_provider_download_started": "Завантаження почалося", @@ -283,7 +302,7 @@ "image_viewer_page_state_provider_share_error": "Помилка спільного доступу", "invalid_date": "Недійсна дата", "invalid_date_format": "Недійсний формат дати", - "library": "Library", + "library": "Бібліотека", "library_page_albums": "Альбоми", "library_page_archive": "Архів", "library_page_device_albums": "Альбоми на пристрої", @@ -296,6 +315,10 @@ "library_page_sort_most_oldest_photo": "Найдавніші фото", "library_page_sort_most_recent_photo": "Найновіші фото", "library_page_sort_title": "Назва альбому", + "local_network": "Local network", + "local_network_sheet_info": "The app will connect to the server through this URL when using the specified Wi-Fi network", + "location_permission": "Location permission", + "location_permission_content": "In order to use the auto-switching feature, Immich needs precise location permission so it can read the current WiFi network's name", "location_picker_choose_on_map": "Обрати на мапі", "location_picker_latitude": "Широта", "location_picker_latitude_error": "Вкажіть дійсну широту", @@ -364,7 +387,9 @@ "motion_photos_page_title": "Рухомі Знімки", "multiselect_grid_edit_date_time_err_read_only": "Неможливо редагувати дату елементів лише для читання, пропущено", "multiselect_grid_edit_gps_err_read_only": "Неможливо редагувати місцезнаходження елементів лише для читання, пропущено", - "my_albums": "My albums", + "my_albums": "Мої альбоми", + "networking_settings": "Networking", + "networking_subtitle": "Manage the server endpoint settings", "no_assets_to_show": "Елементи відсутні", "no_name": "Без імені", "notification_permission_dialog_cancel": "Скасувати", @@ -373,7 +398,7 @@ "notification_permission_list_tile_content": "Надати дозвіл для сповіщень.", "notification_permission_list_tile_enable_button": "Увімкнути Сповіщення", "notification_permission_list_tile_title": "Дозвіл на Сповіщення", - "on_this_device": "On this device", + "on_this_device": "На цьому пристрої", "partner_list_user_photos": "Фотографії {user}", "partner_list_view_all": "Переглянути усі", "partner_page_add_partner": "Додати партнера", @@ -385,8 +410,8 @@ "partner_page_stop_sharing_content": "{} втратить доступ до ваших знімків.", "partner_page_stop_sharing_title": "Припинити надання ваших знімків?", "partner_page_title": "Партнер", - "partners": "Partners", - "people": "People", + "partners": "\nПартнери", + "people": "Люди", "permission_onboarding_back": "Назад", "permission_onboarding_continue_anyway": "Все одно продовжити", "permission_onboarding_get_started": "Розпочати", @@ -397,7 +422,8 @@ "permission_onboarding_permission_granted": "Доступ надано! Все готово.", "permission_onboarding_permission_limited": "Обмежений доступ. Аби дозволити Immich резервне копіювання та керування вашою галереєю, надайте доступ до знімків та відео у Налаштуваннях", "permission_onboarding_request": "Immich потребує доступу до ваших знімків та відео.", - "places": "Places", + "places": "Місця", + "preferences_settings_subtitle": "Manage the app's preferences", "preferences_settings_title": "Параметри", "profile_drawer_app_logs": "Журнал", "profile_drawer_client_out_of_date_major": "Мобільний додаток застарів. Будь ласка, оновіть до останньої мажорної версії.", @@ -410,11 +436,12 @@ "profile_drawer_settings": "Налаштування", "profile_drawer_sign_out": "Вийти", "profile_drawer_trash": "Кошик", - "recently_added": "Recently added", + "recently_added": "Нещодавно додані", "recently_added_page_title": "Нещодавні", + "save": "Save", "save_to_gallery": "Зберегти в галерею", "scaffold_body_error_occurred": "Виникла помилка", - "search_albums": "Search albums", + "search_albums": "Пошук альбому", "search_bar_hint": "Шукати ваші знімки", "search_filter_apply": "Застосувати фільтр", "search_filter_camera": "Камера", @@ -457,6 +484,7 @@ "search_page_places": "Місця", "search_page_recently_added": "Нещодавно додані", "search_page_screenshots": "Знімки екрану", + "search_page_search_photos_videos": "Search for your photos and videos", "search_page_selfies": "Селфі", "search_page_things": "Речі", "search_page_videos": "Відео", @@ -469,6 +497,7 @@ "select_additional_user_for_sharing_page_suggestions": "Пропозиції", "select_user_for_sharing_page_err_album": "Не вдалося створити альбом", "select_user_for_sharing_page_share_suggestions": "Пропозиції", + "server_endpoint": "Server Endpoint", "server_info_box_app_version": "Версія додатка", "server_info_box_latest_release": "Остання версія", "server_info_box_server_url": "URL сервера", @@ -480,6 +509,7 @@ "setting_image_viewer_preview_title": "Завантажувати зображення попереднього перегляду", "setting_image_viewer_title": "Зображення", "setting_languages_apply": "Застосувати", + "setting_languages_subtitle": "Change the app's language", "setting_languages_title": "Мова", "setting_notifications_notify_failures_grace_period": "Повідомити про помилки фонового резервного копіювання: {}", "setting_notifications_notify_hours": "{} годин", @@ -560,9 +590,9 @@ "shared_link_info_chip_upload": "Завантажити", "shared_link_manage_links": "Керування спільними посиланнями", "shared_link_public_album": "Публічний альбом", - "shared_links": "Shared links", + "shared_links": "Публічні посилання", "share_done": "Готово", - "shared_with_me": "Shared with me", + "shared_with_me": "Доступні мені", "share_invite": "Запросити в альбом", "sharing_page_album": "Спільні альбоми", "sharing_page_description": "Створюйте спільні альбоми, щоб ділитися знімками та відео з людьми у вашій мережі.", @@ -594,7 +624,7 @@ "theme_setting_three_stage_loading_subtitle": "Триетапне завантаження може підвищити продуктивність завантаження, але спричинить значно більше навантаження на мережу", "theme_setting_three_stage_loading_title": "Увімкнути триетапне завантаження", "translated_text_options": "Налаштування", - "trash": "Trash", + "trash": "Кошик", "trash_emptied": "Кошик очищений", "trash_page_delete": "Видалити", "trash_page_delete_all": "Видалити усі", @@ -612,14 +642,18 @@ "upload_dialog_info": "Бажаєте створити резервну копію вибраних елементів на сервері?", "upload_dialog_ok": "Завантажити", "upload_dialog_title": "Завантажити Елементи", + "use_current_connection": "use current connection", + "validate_endpoint_error": "Please enter a valid URL", "version_announcement_overlay_ack": "Прийняти", "version_announcement_overlay_release_notes": "примітки до випуску", "version_announcement_overlay_text_1": "Вітаємо, є новий випуск ", "version_announcement_overlay_text_2": "знайдіть хвильку навідатися на ", "version_announcement_overlay_text_3": "і переконайтеся, що ваші налаштування docker-compose та .env оновлені, аби запобігти будь-якій неправильній конфігурації, особливо, якщо ви використовуєте WatchTower або інший механізм, для автоматичних оновлень вашої серверної частини.", "version_announcement_overlay_title": "Доступна нова версія сервера \uD83C\uDF89", - "videos": "Videos", + "videos": "Відео", "viewer_remove_from_stack": "Видалити зі стеку", "viewer_stack_use_as_main_asset": "Використовувати як основний елементи", - "viewer_unstack": "Розібрати стек" + "viewer_unstack": "Розібрати стек", + "wifi_name": "WiFi Name", + "your_wifi_name": "Your WiFi name" } \ No newline at end of file diff --git a/mobile/assets/i18n/vi-VN.json b/mobile/assets/i18n/vi-VN.json index c77f9427f1309..6990d1f266c32 100644 --- a/mobile/assets/i18n/vi-VN.json +++ b/mobile/assets/i18n/vi-VN.json @@ -7,6 +7,7 @@ "action_common_select": "Chọn", "action_common_update": "Cập nhật", "add_a_name": "Add a name", + "add_endpoint": "Add endpoint", "add_to_album_bottom_sheet_added": "Thêm vào {album}", "add_to_album_bottom_sheet_already_exists": "Đã có sẵn trong {album}", "advanced_settings_log_level_title": "Phân loại nhật ký: {}", @@ -38,7 +39,7 @@ "album_viewer_appbar_share_remove": "Xoá khỏi album", "album_viewer_appbar_share_to": "Chia sẻ với", "album_viewer_page_share_add_users": "Thêm người dùng", - "all": "All", + "all": "Tất cả", "all_people_page_title": "Mọi người", "all_videos_page_title": "Video", "app_bar_signout_dialog_content": "Bạn có muốn đăng xuất?", @@ -65,7 +66,12 @@ "assets_restored_successfully": "Đã khôi phục {} mục thành công", "assets_trashed": "Đã chuyển {} mục vào thùng rác", "assets_trashed_from_server": "Đã chuyển {} mục từ máy chủ Immich vào thùng rác", + "asset_viewer_settings_subtitle": "Manage your gallery viewer settings", "asset_viewer_settings_title": "Trình xem ảnh", + "automatic_endpoint_switching_subtitle": "Connect locally over designated Wi-Fi when available and use alternative connections elsewhere", + "automatic_endpoint_switching_title": "Automatic URL switching", + "background_location_permission": "Background location permission", + "background_location_permission_content": "In order to switch networks when running in the background, Immich must *always* have precise location access so the app can read the Wi-Fi network's name", "backup_album_selection_page_albums_device": "Album trên thiết bị ({})", "backup_album_selection_page_albums_tap": "Nhấn để chọn, nhấn đúp để bỏ qua", "backup_album_selection_page_assets_scatter": "Ảnh có thể có trong nhiều album khác nhau. Trong quá trình sao lưu, bạn có thể chọn để sao lưu tất cả các album hoặc chỉ một số album nhất định.", @@ -121,7 +127,7 @@ "backup_controller_page_total": "Tổng số", "backup_controller_page_total_sub": "Tất cả ảnh và video không trùng lập từ các album được chọn", "backup_controller_page_turn_off": "Tắt sao lưu khi ứng dụng hoạt động", - "backup_controller_page_turn_on": "Bật sao lưu khi ứng dụng hoạt động", + "backup_controller_page_turn_on": "Bật sao lưu khi mở ứng dụng", "backup_controller_page_uploading_file_info": "Thông tin tệp đang tải lên", "backup_err_only_album": "Không thể xóa album duy nhất", "backup_info_card_assets": "ảnh", @@ -131,6 +137,7 @@ "backup_manual_success": "Thành công", "backup_manual_title": "Trạng thái tải lên", "backup_options_page_title": "Tuỳ chỉnh sao lưu", + "backup_setting_subtitle": "Manage background and foreground upload settings", "cache_settings_album_thumbnails": "Trang thư viện hình thu nhỏ ({} ảnh)", "cache_settings_clear_cache_button": "Xoá bộ nhớ đệm", "cache_settings_clear_cache_button_title": "Xóa bộ nhớ đệm của ứng dụng. Điều này sẽ ảnh hưởng đến hiệu suất của ứng dụng đến khi bộ nhớ đệm được tạo lại.", @@ -149,11 +156,16 @@ "cache_settings_tile_subtitle": "Kiểm soát cách xử lý lưu trữ cục bộ", "cache_settings_tile_title": "Lưu trữ cục bộ", "cache_settings_title": "Cài đặt bộ nhớ đệm", + "cancel": "Cancel", + "change_display_order": "Change display order", "change_password_form_confirm_password": "Xác nhận mật khẩu", "change_password_form_description": "Xin chào {name},\n\nĐây là lần đầu tiên bạn đăng nhập vào hệ thống hoặc đã có yêu cầu thay đổi mật khẩu. Vui lòng nhập mật khẩu mới bên dưới.", "change_password_form_new_password": "Mật khẩu mới", "change_password_form_password_mismatch": "Mật khẩu không giống nhau", "change_password_form_reenter_new_password": "Nhập lại mật khẩu mới", + "check_corrupt_asset_backup": "Check for corrupt asset backups", + "check_corrupt_asset_backup_button": "Perform check", + "check_corrupt_asset_backup_description": "Run this check only over Wi-Fi and once all assets have been backed-up. The procedure might take a few minutes.", "client_cert_dialog_msg_confirm": "Đồng ý", "client_cert_enter_password": "Nhập mật khẩu", "client_cert_import": "Nhập", @@ -199,6 +211,7 @@ "crop": "Cắt", "curated_location_page_title": "Địa điểm", "curated_object_page_title": "Sự vật", + "current_server_address": "Current server address", "daily_title_text_date": "E, MMM dd", "daily_title_text_date_year": "E, MMM dd, yyyy", "date_format": "E, LLL d, y • h:mm a", @@ -235,6 +248,8 @@ "edit_date_time_dialog_timezone": "Múi giờ", "edit_image_title": "Sửa", "edit_location_dialog_title": "Vị trí", + "enter_wifi_name": "Enter WiFi name", + "error_change_sort_album": "Failed to change album sort order", "error_saving_image": "Lỗi: {}", "exif_bottom_sheet_description": "Thêm mô tả...", "exif_bottom_sheet_details": "CHI TIẾT", @@ -246,13 +261,17 @@ "experimental_settings_new_asset_list_title": "Bật lưới ảnh thử nghiệm", "experimental_settings_subtitle": "Sử dụng có thể rủi ro!", "experimental_settings_title": "Chưa hoàn thiện", + "external_network": "External network", + "external_network_sheet_info": "When not on the preferred WiFi network, the app will connect to the server through the first of the below URLs it can reach, starting from top to bottom", "favorites": "Favorites", "favorites_page_no_favorites": "Không tìm thấy ảnh yêu thích", "favorites_page_title": "Ảnh yêu thích", "filename_search": "Tên hoặc phần mở rộng tập tin", "filter": "Bộ lọc", - "haptic_feedback_switch": "Bật phản hồi haptic\n", - "haptic_feedback_title": "Haptic Feedback\n", + "get_wifiname_error": "Could not get Wi-Fi name. Make sure you have granted the necessary permissions and are connected to a Wi-Fi network", + "grant_permission": "Grant permission", + "haptic_feedback_switch": "Bật phản hồi haptic", + "haptic_feedback_title": "Phản hồi Hapic", "header_settings_add_header_tip": "Thêm Header", "header_settings_field_validator_msg": "Trường này không được để trống", "header_settings_header_name_input": "Tên Header", @@ -296,6 +315,10 @@ "library_page_sort_most_oldest_photo": "Ảnh cũ nhất", "library_page_sort_most_recent_photo": "Ảnh gần đây nhất", "library_page_sort_title": "Tiêu đề album", + "local_network": "Local network", + "local_network_sheet_info": "The app will connect to the server through this URL when using the specified Wi-Fi network", + "location_permission": "Location permission", + "location_permission_content": "In order to use the auto-switching feature, Immich needs precise location permission so it can read the current WiFi network's name", "location_picker_choose_on_map": "Chọn trên bản đồ", "location_picker_latitude": "Vĩ độ", "location_picker_latitude_error": "Nhập vĩ độ hợp lệ", @@ -365,6 +388,8 @@ "multiselect_grid_edit_date_time_err_read_only": "Không thể chỉnh sửa ngày của ảnh chỉ có quyền đọc, bỏ qua", "multiselect_grid_edit_gps_err_read_only": "Không thể chỉnh sửa vị trí của ảnh chỉ có quyền đọc, bỏ qua", "my_albums": "My albums", + "networking_settings": "Networking", + "networking_subtitle": "Manage the server endpoint settings", "no_assets_to_show": "Không có mục nào để hiển thị", "no_name": "Không có tên", "notification_permission_dialog_cancel": "Từ chối", @@ -398,6 +423,7 @@ "permission_onboarding_permission_limited": "Quyền truy cập vào ảnh của bạn bị hạn chế. Để Immich sao lưu và quản lý toàn bộ thư viện ảnh của bạn, hãy cấp quyền truy cập toàn bộ ảnh trong Cài đặt.", "permission_onboarding_request": "Immich cần quyền để xem ảnh và video của bạn", "places": "Places", + "preferences_settings_subtitle": "Manage the app's preferences", "preferences_settings_title": "Tuỳ chỉnh", "profile_drawer_app_logs": "Nhật ký", "profile_drawer_client_out_of_date_major": "Ứng dụng đã lỗi thời. Vui lòng cập nhật lên phiên bản chính mới nhất.", @@ -412,6 +438,7 @@ "profile_drawer_trash": "Thùng rác", "recently_added": "Recently added", "recently_added_page_title": "Mới thêm gần đây", + "save": "Save", "save_to_gallery": "Lưu vào thư viện", "scaffold_body_error_occurred": "Xảy ra lỗi", "search_albums": "Search albums", @@ -457,6 +484,7 @@ "search_page_places": "Địa điểm", "search_page_recently_added": "Mới thêm gần đây", "search_page_screenshots": "Ảnh màn hình", + "search_page_search_photos_videos": "Search for your photos and videos", "search_page_selfies": "Ảnh selfie", "search_page_things": "Sự vật", "search_page_videos": "Video", @@ -469,6 +497,7 @@ "select_additional_user_for_sharing_page_suggestions": "Gợi ý", "select_user_for_sharing_page_err_album": "Tạo album thất bại", "select_user_for_sharing_page_share_suggestions": "Gợi ý", + "server_endpoint": "Server Endpoint", "server_info_box_app_version": "Phiên bản ứng dụng", "server_info_box_latest_release": "Phiên bản mới nhất", "server_info_box_server_url": "Địa chỉ máy chủ", @@ -480,6 +509,7 @@ "setting_image_viewer_preview_title": "Tải ảnh xem trước", "setting_image_viewer_title": "Hình ảnh", "setting_languages_apply": "Áp dụng", + "setting_languages_subtitle": "Change the app's language", "setting_languages_title": "Ngôn ngữ", "setting_notifications_notify_failures_grace_period": "Thông báo sao lưu nền thất bại: {}", "setting_notifications_notify_hours": "{} giờ", @@ -612,6 +642,8 @@ "upload_dialog_info": "Bạn có muốn sao lưu những mục đã chọn tới máy chủ không?", "upload_dialog_ok": "Tải lên", "upload_dialog_title": "Tải lên ảnh", + "use_current_connection": "use current connection", + "validate_endpoint_error": "Please enter a valid URL", "version_announcement_overlay_ack": "Công nhận", "version_announcement_overlay_release_notes": "ghi chú phát hành", "version_announcement_overlay_text_1": "Chào bạn, có một bản phát hành mới của", @@ -621,5 +653,7 @@ "videos": "Videos", "viewer_remove_from_stack": "Xoá khỏi nhóm", "viewer_stack_use_as_main_asset": "Đặt làm lựa chọn hàng đầu", - "viewer_unstack": "Huỷ xếp nhóm" + "viewer_unstack": "Huỷ xếp nhóm", + "wifi_name": "WiFi Name", + "your_wifi_name": "Your WiFi name" } \ No newline at end of file diff --git a/mobile/assets/i18n/zh-CN.json b/mobile/assets/i18n/zh-CN.json index 0da7c3b2db4c3..36481f6bb68f6 100644 --- a/mobile/assets/i18n/zh-CN.json +++ b/mobile/assets/i18n/zh-CN.json @@ -7,6 +7,7 @@ "action_common_select": "选择", "action_common_update": "更新", "add_a_name": "添加姓名", + "add_endpoint": "添加服务接口", "add_to_album_bottom_sheet_added": "添加到 {album}", "add_to_album_bottom_sheet_already_exists": "已在 {album} 中", "advanced_settings_log_level_title": "日志等级:{}", @@ -65,7 +66,12 @@ "assets_restored_successfully": "已成功恢复{}个项目", "assets_trashed": "{}个回收站项目", "assets_trashed_from_server": "{}个项目已放入回收站", + "asset_viewer_settings_subtitle": "管理图库浏览器设置", "asset_viewer_settings_title": "资源查看器", + "automatic_endpoint_switching_subtitle": "在可用的情况下,通过指定的 Wi-Fi 进行本地连接,并在其它地方使用替代连接", + "automatic_endpoint_switching_title": "自动切换URL", + "background_location_permission": "后台定位权限", + "background_location_permission_content": "为了在后台运行时切换网络,Immich 必须*始终*拥有精确的位置访问权限,这样应用程序才能读取 Wi-Fi 网络的名称", "backup_album_selection_page_albums_device": "设备上的相册({})", "backup_album_selection_page_albums_tap": "单击选中,双击取消", "backup_album_selection_page_assets_scatter": "项目会分散在多个相册中。因此,可以在备份过程中包含或排除相册。", @@ -131,6 +137,7 @@ "backup_manual_success": "成功", "backup_manual_title": "上传状态", "backup_options_page_title": "备份选项", + "backup_setting_subtitle": "管理后台和前台上传设置", "cache_settings_album_thumbnails": "图库缩略图({} 项)", "cache_settings_clear_cache_button": "清除缓存", "cache_settings_clear_cache_button_title": "清除应用缓存。在重新生成缓存之前,将显著影响应用的性能。", @@ -149,11 +156,16 @@ "cache_settings_tile_subtitle": "设置本地存储行为", "cache_settings_tile_title": "本地存储", "cache_settings_title": "缓存设置", + "cancel": "取消", + "change_display_order": "Change display order", "change_password_form_confirm_password": "确认密码", "change_password_form_description": "{name} 您好,\n\n这是您首次登录系统,或被管理员要求更改密码。\n请在下方输入新密码。", "change_password_form_new_password": "新密码", "change_password_form_password_mismatch": "密码不匹配", "change_password_form_reenter_new_password": "再次输入新密码", + "check_corrupt_asset_backup": "检查备份是否损坏", + "check_corrupt_asset_backup_button": "执行检查", + "check_corrupt_asset_backup_description": "仅在连接到Wi-Fi并完成所有项目备份后执行此检查。该过程可能需要几分钟。", "client_cert_dialog_msg_confirm": "确定", "client_cert_enter_password": "输入密码", "client_cert_import": "导入", @@ -199,6 +211,7 @@ "crop": "裁剪", "curated_location_page_title": "地点", "curated_object_page_title": "事物", + "current_server_address": "当前服务器地址", "daily_title_text_date": "E, MMM dd", "daily_title_text_date_year": "E, MMM dd, yyyy", "date_format": "E, LLL d, y • h:mm a", @@ -235,6 +248,8 @@ "edit_date_time_dialog_timezone": "时区", "edit_image_title": "编辑", "edit_location_dialog_title": "位置", + "enter_wifi_name": "输入 Wi-Fi 名称", + "error_change_sort_album": "Failed to change album sort order", "error_saving_image": "错误:{}", "exif_bottom_sheet_description": "添加描述...", "exif_bottom_sheet_details": "详情", @@ -246,11 +261,15 @@ "experimental_settings_new_asset_list_title": "启用实验性照片网格", "experimental_settings_subtitle": "使用风险自负!", "experimental_settings_title": "实验性功能", + "external_network": "外部网络", + "external_network_sheet_info": "当不在首选的 Wi-Fi 网络上时,应用程序将通过下方第一个可连通的 URL 连接到服务器", "favorites": "收藏", "favorites_page_no_favorites": "未找到收藏项目", "favorites_page_title": "收藏", "filename_search": "文件名或扩展名", "filter": "筛选", + "get_wifiname_error": "无法获取 Wi-Fi 名称。确保已授予必要的权限,并已连接到 Wi-Fi 网络", + "grant_permission": "获取权限", "haptic_feedback_switch": "启用振动反馈", "haptic_feedback_title": "振动反馈", "header_settings_add_header_tip": "添加标头", @@ -296,6 +315,10 @@ "library_page_sort_most_oldest_photo": "最早的照片", "library_page_sort_most_recent_photo": "最近的项目", "library_page_sort_title": "相册标题", + "local_network": "本地网络", + "local_network_sheet_info": "使用指定的 Wi-Fi 网络时,应用程序将通过此 URL 连接到服务器", + "location_permission": "定位权限", + "location_permission_content": "为了使用自动切换功能,Immich 需要精确的定位权限,这样才能读取当前 Wi-Fi 网络的名称", "location_picker_choose_on_map": "在地图上选择", "location_picker_latitude": "纬度", "location_picker_latitude_error": "输入有效的纬度值", @@ -365,6 +388,8 @@ "multiselect_grid_edit_date_time_err_read_only": "无法编辑只读项目的日期,跳过", "multiselect_grid_edit_gps_err_read_only": "无法编辑只读项目的位置信息,跳过", "my_albums": "我的相册", + "networking_settings": "网络", + "networking_subtitle": "管理服务接口设置", "no_assets_to_show": "无项目展示", "no_name": "无姓名", "notification_permission_dialog_cancel": "取消", @@ -398,6 +423,7 @@ "permission_onboarding_permission_limited": "权限受限:要让 Immich 备份和管理您的整个图库收藏,请在“设置”中授予照片和视频权限。", "permission_onboarding_request": "Immich 需要权限才能查看您的照片和视频。", "places": "地点", + "preferences_settings_subtitle": "管理应用的偏好设置", "preferences_settings_title": "偏好设置", "profile_drawer_app_logs": "日志", "profile_drawer_client_out_of_date_major": "客户端有大版本升级,请尽快升级至最新版。", @@ -412,6 +438,7 @@ "profile_drawer_trash": "回收站", "recently_added": "近期添加", "recently_added_page_title": "最近添加", + "save": "保存", "save_to_gallery": "保存到图库", "scaffold_body_error_occurred": "发生错误", "search_albums": "搜索相册", @@ -457,6 +484,7 @@ "search_page_places": "地点", "search_page_recently_added": "最近添加", "search_page_screenshots": "屏幕截图", + "search_page_search_photos_videos": "搜索您的照片和视频", "search_page_selfies": "自拍", "search_page_things": "事物", "search_page_videos": "视频", @@ -469,6 +497,7 @@ "select_additional_user_for_sharing_page_suggestions": "建议", "select_user_for_sharing_page_err_album": "创建相册失败", "select_user_for_sharing_page_share_suggestions": "建议", + "server_endpoint": "服务接口", "server_info_box_app_version": "App 版本", "server_info_box_latest_release": "最新版本", "server_info_box_server_url": "服务器地址", @@ -480,6 +509,7 @@ "setting_image_viewer_preview_title": "加载预览图", "setting_image_viewer_title": "图片", "setting_languages_apply": "应用", + "setting_languages_subtitle": "更改应用语言", "setting_languages_title": "语言", "setting_notifications_notify_failures_grace_period": "后台备份失败通知:{}", "setting_notifications_notify_hours": "{} 小时", @@ -612,6 +642,8 @@ "upload_dialog_info": "是否要将所选项目备份到服务器?", "upload_dialog_ok": "上传", "upload_dialog_title": "上传项目", + "use_current_connection": "使用当前连接", + "validate_endpoint_error": "请输入有效的URL", "version_announcement_overlay_ack": "我知道了", "version_announcement_overlay_release_notes": "发行说明", "version_announcement_overlay_text_1": "号外号外,有新版本的", @@ -621,5 +653,7 @@ "videos": "视频", "viewer_remove_from_stack": "从堆叠中移除", "viewer_stack_use_as_main_asset": "作为主项目使用", - "viewer_unstack": "取消堆叠" + "viewer_unstack": "取消堆叠", + "wifi_name": "Wi-Fi 名称", + "your_wifi_name": "您的 Wi-Fi 名称" } \ No newline at end of file diff --git a/mobile/assets/i18n/zh-Hans.json b/mobile/assets/i18n/zh-Hans.json index 21a7fc2e4e67b..c6f361a756116 100644 --- a/mobile/assets/i18n/zh-Hans.json +++ b/mobile/assets/i18n/zh-Hans.json @@ -7,6 +7,7 @@ "action_common_select": "选择", "action_common_update": "更新", "add_a_name": "添加姓名", + "add_endpoint": "添加服务接口", "add_to_album_bottom_sheet_added": "添加到 {album}", "add_to_album_bottom_sheet_already_exists": "已在 {album} 中", "advanced_settings_log_level_title": "日志等级:{}", @@ -65,7 +66,12 @@ "assets_restored_successfully": "已成功恢复{}个项目", "assets_trashed": "{}个回收站项目", "assets_trashed_from_server": "{}个项目已放入回收站", + "asset_viewer_settings_subtitle": "管理图库浏览器设置", "asset_viewer_settings_title": "资源查看器", + "automatic_endpoint_switching_subtitle": "在可用的情况下,通过指定的 Wi-Fi 进行本地连接,并在其它地方使用替代连接", + "automatic_endpoint_switching_title": "自动切换URL", + "background_location_permission": "后台定位权限", + "background_location_permission_content": "为了在后台运行时切换网络,Immich 必须*始终*拥有精确的位置访问权限,这样应用程序才能读取 Wi-Fi 网络的名称", "backup_album_selection_page_albums_device": "设备上的相册({})", "backup_album_selection_page_albums_tap": "单击选中,双击取消", "backup_album_selection_page_assets_scatter": "项目会分散在多个相册中。因此,可以在备份过程中包含或排除相册。", @@ -131,6 +137,7 @@ "backup_manual_success": "成功", "backup_manual_title": "上传状态", "backup_options_page_title": "备份选项", + "backup_setting_subtitle": "管理后台和前台上传设置", "cache_settings_album_thumbnails": "图库缩略图({} 项)", "cache_settings_clear_cache_button": "清除缓存", "cache_settings_clear_cache_button_title": "清除应用缓存。在重新生成缓存之前,将显著影响应用的性能。", @@ -149,11 +156,16 @@ "cache_settings_tile_subtitle": "设置本地存储行为", "cache_settings_tile_title": "本地存储", "cache_settings_title": "缓存设置", + "cancel": "取消", + "change_display_order": "Change display order", "change_password_form_confirm_password": "确认密码", "change_password_form_description": "{name} 您好,\n\n这是您首次登录系统,或被管理员要求更改密码。\n请在下方输入新密码。", "change_password_form_new_password": "新密码", "change_password_form_password_mismatch": "密码不匹配", "change_password_form_reenter_new_password": "再次输入新密码", + "check_corrupt_asset_backup": "检查备份是否损坏", + "check_corrupt_asset_backup_button": "执行检查", + "check_corrupt_asset_backup_description": "仅在连接到Wi-Fi并完成所有项目备份后执行此检查。该过程可能需要几分钟。", "client_cert_dialog_msg_confirm": "确定", "client_cert_enter_password": "输入密码", "client_cert_import": "导入", @@ -199,6 +211,7 @@ "crop": "裁剪", "curated_location_page_title": "地点", "curated_object_page_title": "事物", + "current_server_address": "当前服务器地址", "daily_title_text_date": "E, MMM dd", "daily_title_text_date_year": "E, MMM dd, yyyy", "date_format": "E, LLL d, y • h:mm a", @@ -235,6 +248,8 @@ "edit_date_time_dialog_timezone": "时区", "edit_image_title": "编辑", "edit_location_dialog_title": "位置", + "enter_wifi_name": "输入 Wi-Fi 名称", + "error_change_sort_album": "Failed to change album sort order", "error_saving_image": "错误:{}", "exif_bottom_sheet_description": "添加描述...", "exif_bottom_sheet_details": "详情", @@ -246,11 +261,15 @@ "experimental_settings_new_asset_list_title": "启用实验性照片网格", "experimental_settings_subtitle": "使用风险自负!", "experimental_settings_title": "实验性功能", + "external_network": "外部网络", + "external_network_sheet_info": "当不在首选的 Wi-Fi 网络上时,应用程序将通过下方第一个可连通的 URL 连接到服务器", "favorites": "收藏", "favorites_page_no_favorites": "未找到收藏项目", "favorites_page_title": "收藏", "filename_search": "文件名或扩展名", "filter": "筛选", + "get_wifiname_error": "无法获取 Wi-Fi 名称。确保已授予必要的权限,并已连接到 Wi-Fi 网络", + "grant_permission": "获取权限", "haptic_feedback_switch": "启用振动反馈", "haptic_feedback_title": "振动反馈", "header_settings_add_header_tip": "添加标头", @@ -296,6 +315,10 @@ "library_page_sort_most_oldest_photo": "最早的照片", "library_page_sort_most_recent_photo": "最近的项目", "library_page_sort_title": "相册标题", + "local_network": "本地网络", + "local_network_sheet_info": "使用指定的 Wi-Fi 网络时,应用程序将通过此 URL 连接到服务器", + "location_permission": "定位权限", + "location_permission_content": "为了使用自动切换功能,Immich 需要精确的定位权限,这样才能读取当前 Wi-Fi 网络的名称", "location_picker_choose_on_map": "在地图上选择", "location_picker_latitude": "纬度", "location_picker_latitude_error": "输入有效的纬度值", @@ -365,6 +388,8 @@ "multiselect_grid_edit_date_time_err_read_only": "无法编辑只读项目的日期,跳过", "multiselect_grid_edit_gps_err_read_only": "无法编辑只读项目的位置信息,跳过", "my_albums": "我的相册", + "networking_settings": "网络", + "networking_subtitle": "管理服务接口设置", "no_assets_to_show": "无项目展示", "no_name": "无姓名", "notification_permission_dialog_cancel": "取消", @@ -398,6 +423,7 @@ "permission_onboarding_permission_limited": "权限受限:要让 Immich 备份和管理您的整个图库收藏,请在“设置”中授予照片和视频权限。", "permission_onboarding_request": "Immich 需要权限才能查看您的照片和视频。", "places": "地点", + "preferences_settings_subtitle": "管理应用的偏好设置", "preferences_settings_title": "偏好设置", "profile_drawer_app_logs": "日志", "profile_drawer_client_out_of_date_major": "客户端有大版本升级,请尽快升级至最新版。", @@ -412,6 +438,7 @@ "profile_drawer_trash": "回收站", "recently_added": "近期添加", "recently_added_page_title": "最近添加", + "save": "保存", "save_to_gallery": "保存到图库", "scaffold_body_error_occurred": "发生错误", "search_albums": "搜索相册", @@ -457,6 +484,7 @@ "search_page_places": "地点", "search_page_recently_added": "最近添加", "search_page_screenshots": "屏幕截图", + "search_page_search_photos_videos": "搜索您的照片和视频", "search_page_selfies": "自拍", "search_page_things": "事物", "search_page_videos": "视频", @@ -469,6 +497,7 @@ "select_additional_user_for_sharing_page_suggestions": "建议", "select_user_for_sharing_page_err_album": "创建相册失败", "select_user_for_sharing_page_share_suggestions": "建议", + "server_endpoint": "服务接口", "server_info_box_app_version": "App 版本", "server_info_box_latest_release": "最新版本", "server_info_box_server_url": "服务器地址", @@ -480,6 +509,7 @@ "setting_image_viewer_preview_title": "加载预览图", "setting_image_viewer_title": "图片", "setting_languages_apply": "应用", + "setting_languages_subtitle": "更改应用语言", "setting_languages_title": "语言", "setting_notifications_notify_failures_grace_period": "后台备份失败通知:{}", "setting_notifications_notify_hours": "{} 小时", @@ -612,6 +642,8 @@ "upload_dialog_info": "是否要将所选项目备份到服务器?", "upload_dialog_ok": "上传", "upload_dialog_title": "上传项目", + "use_current_connection": "使用当前连接", + "validate_endpoint_error": "请输入有效的URL", "version_announcement_overlay_ack": "我知道了", "version_announcement_overlay_release_notes": "发行说明", "version_announcement_overlay_text_1": "号外号外,有新版本的", @@ -621,5 +653,7 @@ "videos": "视频", "viewer_remove_from_stack": "从堆叠中移除", "viewer_stack_use_as_main_asset": "作为主项目使用", - "viewer_unstack": "取消堆叠" + "viewer_unstack": "取消堆叠", + "wifi_name": "Wi-Fi 名称", + "your_wifi_name": "您的 Wi-Fi 名称" } \ No newline at end of file diff --git a/mobile/assets/i18n/zh-TW.json b/mobile/assets/i18n/zh-TW.json index 0075f65de0557..88d1d48aec56d 100644 --- a/mobile/assets/i18n/zh-TW.json +++ b/mobile/assets/i18n/zh-TW.json @@ -1,625 +1,659 @@ { - "action_common_back": "Back", - "action_common_cancel": "Cancel", - "action_common_clear": "Clear", - "action_common_confirm": "Confirm", - "action_common_save": "Save", - "action_common_select": "Select", - "action_common_update": "Update", - "add_a_name": "Add a name", - "add_to_album_bottom_sheet_added": "Added to {album}", - "add_to_album_bottom_sheet_already_exists": "Already in {album}", - "advanced_settings_log_level_title": "Log level: {}", - "advanced_settings_prefer_remote_subtitle": "Some devices are painfully slow to load thumbnails from assets on the device. Activate this setting to load remote images instead.", - "advanced_settings_prefer_remote_title": "Prefer remote images", - "advanced_settings_proxy_headers_subtitle": "Define proxy headers Immich should send with each network request", - "advanced_settings_proxy_headers_title": "Proxy Headers", - "advanced_settings_self_signed_ssl_subtitle": "Skips SSL certificate verification for the server endpoint. Required for self-signed certificates.", - "advanced_settings_self_signed_ssl_title": "Allow self-signed SSL certificates", - "advanced_settings_tile_subtitle": "Advanced user's settings", - "advanced_settings_tile_title": "Advanced", - "advanced_settings_troubleshooting_subtitle": "Enable additional features for troubleshooting", - "advanced_settings_troubleshooting_title": "Troubleshooting", - "album_info_card_backup_album_excluded": "EXCLUDED", - "album_info_card_backup_album_included": "INCLUDED", - "albums": "Albums", - "album_thumbnail_card_item": "1 item", - "album_thumbnail_card_items": "{} items", - "album_thumbnail_card_shared": " · Shared", - "album_thumbnail_owned": "Owned", - "album_thumbnail_shared_by": "Shared by {}", - "album_viewer_appbar_delete_confirm": "Are you sure you want to delete this album from your account?", - "album_viewer_appbar_share_delete": "Delete album", - "album_viewer_appbar_share_err_delete": "Failed to delete album", - "album_viewer_appbar_share_err_leave": "Failed to leave album", - "album_viewer_appbar_share_err_remove": "There are problems in removing assets from album", - "album_viewer_appbar_share_err_title": "Failed to change album title", - "album_viewer_appbar_share_leave": "Leave album", - "album_viewer_appbar_share_remove": "Remove from album", - "album_viewer_appbar_share_to": "Share To", - "album_viewer_page_share_add_users": "Add users", - "all": "All", - "all_people_page_title": "People", - "all_videos_page_title": "Videos", - "app_bar_signout_dialog_content": "Are you sure you want to sign out?", - "app_bar_signout_dialog_ok": "Yes", - "app_bar_signout_dialog_title": "Sign out", - "archived": "Archived", - "archive_page_no_archived_assets": "No archived assets found", - "archive_page_title": "Archive ({})", - "asset_action_delete_err_read_only": "Cannot delete read only asset(s), skipping", - "asset_action_share_err_offline": "Cannot fetch offline asset(s), skipping", - "asset_list_group_by_sub_title": "Group by", - "asset_list_layout_settings_dynamic_layout_title": "Dynamic layout", - "asset_list_layout_settings_group_automatically": "Automatic", - "asset_list_layout_settings_group_by": "Group assets by", - "asset_list_layout_settings_group_by_month": "Month", - "asset_list_layout_settings_group_by_month_day": "Month + day", - "asset_list_layout_sub_title": "Layout", - "asset_list_settings_subtitle": "Photo grid layout settings", - "asset_list_settings_title": "Photo Grid", - "asset_restored_successfully": "Asset restored successfully", - "assets_deleted_permanently": "{} asset(s) deleted permanently", - "assets_deleted_permanently_from_server": "{} asset(s) deleted permanently from the Immich server", - "assets_removed_permanently_from_device": "{} asset(s) removed permanently from your device", - "assets_restored_successfully": "{} asset(s) restored successfully", - "assets_trashed": "{} asset(s) trashed", - "assets_trashed_from_server": "{} asset(s) trashed from the Immich server", - "asset_viewer_settings_title": "Asset Viewer", - "backup_album_selection_page_albums_device": "Albums on device ({})", - "backup_album_selection_page_albums_tap": "Tap to include, double tap to exclude", - "backup_album_selection_page_assets_scatter": "Assets can scatter across multiple albums. Thus, albums can be included or excluded during the backup process.", - "backup_album_selection_page_select_albums": "Select albums", - "backup_album_selection_page_selection_info": "Selection Info", - "backup_album_selection_page_total_assets": "Total unique assets", - "backup_all": "All", - "backup_background_service_backup_failed_message": "Failed to backup assets. Retrying…", - "backup_background_service_connection_failed_message": "Failed to connect to the server. Retrying…", - "backup_background_service_current_upload_notification": "Uploading {}", - "backup_background_service_default_notification": "Checking for new assets…", - "backup_background_service_error_title": "Backup error", - "backup_background_service_in_progress_notification": "Backing up your assets…", - "backup_background_service_upload_failure_notification": "Failed to upload {}", - "backup_controller_page_albums": "Backup Albums", - "backup_controller_page_background_app_refresh_disabled_content": "Enable background app refresh in Settings > General > Background App Refresh in order to use background backup.", - "backup_controller_page_background_app_refresh_disabled_title": "Background app refresh disabled", - "backup_controller_page_background_app_refresh_enable_button_text": "Go to settings", - "backup_controller_page_background_battery_info_link": "Show me how", - "backup_controller_page_background_battery_info_message": "For the best background backup experience, please disable any battery optimizations restricting background activity for Immich.\n\nSince this is device-specific, please lookup the required information for your device manufacturer.", - "backup_controller_page_background_battery_info_ok": "OK", - "backup_controller_page_background_battery_info_title": "Battery optimizations", - "backup_controller_page_background_charging": "Only while charging", - "backup_controller_page_background_configure_error": "Failed to configure the background service", - "backup_controller_page_background_delay": "Delay new assets backup: {}", - "backup_controller_page_background_description": "Turn on the background service to automatically backup any new assets without needing to open the app", - "backup_controller_page_background_is_off": "Automatic background backup is off", - "backup_controller_page_background_is_on": "Automatic background backup is on", - "backup_controller_page_background_turn_off": "Turn off background service", - "backup_controller_page_background_turn_on": "Turn on background service", - "backup_controller_page_background_wifi": "Only on WiFi", - "backup_controller_page_backup": "Backup", - "backup_controller_page_backup_selected": "Selected: ", - "backup_controller_page_backup_sub": "Backed up photos and videos", - "backup_controller_page_cancel": "Cancel", - "backup_controller_page_created": "Created on: {}", - "backup_controller_page_desc_backup": "Turn on foreground backup to automatically upload new assets to the server when opening the app.", - "backup_controller_page_excluded": "Excluded: ", - "backup_controller_page_failed": "Failed ({})", - "backup_controller_page_filename": "File name: {} [{}]", - "backup_controller_page_id": "ID: {}", - "backup_controller_page_info": "Backup Information", - "backup_controller_page_none_selected": "None selected", - "backup_controller_page_remainder": "Remainder", - "backup_controller_page_remainder_sub": "Remaining photos and videos to back up from selection", - "backup_controller_page_select": "Select", - "backup_controller_page_server_storage": "Server Storage", - "backup_controller_page_start_backup": "Start Backup", - "backup_controller_page_status_off": "Automatic foreground backup is off", - "backup_controller_page_status_on": "Automatic foreground backup is on", - "backup_controller_page_storage_format": "{} of {} used", - "backup_controller_page_to_backup": "Albums to be backed up", - "backup_controller_page_total": "Total", - "backup_controller_page_total_sub": "All unique photos and videos from selected albums", - "backup_controller_page_turn_off": "Turn off foreground backup", - "backup_controller_page_turn_on": "Turn on foreground backup", - "backup_controller_page_uploading_file_info": "Uploading file info", - "backup_err_only_album": "Cannot remove the only album", - "backup_info_card_assets": "assets", - "backup_manual_cancelled": "Cancelled", - "backup_manual_failed": "Failed", - "backup_manual_in_progress": "Upload already in progress. Try after sometime", - "backup_manual_success": "Success", - "backup_manual_title": "Upload status", - "backup_options_page_title": "Backup options", - "cache_settings_album_thumbnails": "Library page thumbnails ({} assets)", - "cache_settings_clear_cache_button": "Clear cache", - "cache_settings_clear_cache_button_title": "Clears the app's cache. This will significantly impact the app's performance until the cache has rebuilt.", - "cache_settings_duplicated_assets_clear_button": "CLEAR", - "cache_settings_duplicated_assets_subtitle": "Photos and videos that are black listed by the app", - "cache_settings_duplicated_assets_title": "Duplicated Assets ({})", - "cache_settings_image_cache_size": "Image cache size ({} assets)", - "cache_settings_statistics_album": "Library thumbnails", - "cache_settings_statistics_assets": "{} assets ({})", - "cache_settings_statistics_full": "Full images", - "cache_settings_statistics_shared": "Shared album thumbnails", - "cache_settings_statistics_thumbnail": "Thumbnails", - "cache_settings_statistics_title": "Cache usage", - "cache_settings_subtitle": "Control the caching behaviour of the Immich mobile application", - "cache_settings_thumbnail_size": "Thumbnail cache size ({} assets)", - "cache_settings_tile_subtitle": "Control the local storage behaviour", - "cache_settings_tile_title": "Local Storage", - "cache_settings_title": "Caching Settings", - "change_password_form_confirm_password": "Confirm Password", - "change_password_form_description": "Hi {name},\n\nThis is either the first time you are signing into the system or a request has been made to change your password. Please enter the new password below.", - "change_password_form_new_password": "New Password", - "change_password_form_password_mismatch": "Passwords do not match", - "change_password_form_reenter_new_password": "Re-enter New Password", - "client_cert_dialog_msg_confirm": "OK", - "client_cert_enter_password": "Enter Password", - "client_cert_import": "Import", - "client_cert_import_success_msg": "Client certificate is imported", - "client_cert_invalid_msg": "Invalid certificate file or wrong password", - "client_cert_remove": "Remove", - "client_cert_remove_msg": "Client certificate is removed", - "client_cert_subtitle": "Supports PKCS12 (.p12, .pfx) format only. Certificate Import/Remove is available only before login", - "client_cert_title": "SSL Client Certificate", - "common_add_to_album": "Add to album", - "common_change_password": "Change Password", - "common_create_new_album": "Create new album", - "common_server_error": "Please check your network connection, make sure the server is reachable and app/server versions are compatible.", - "common_shared": "Shared", - "contextual_search": "Sunrise on the beach", - "control_bottom_app_bar_add_to_album": "Add to album", - "control_bottom_app_bar_album_info": "{} items", - "control_bottom_app_bar_album_info_shared": "{} items · Shared", - "control_bottom_app_bar_archive": "Archive", - "control_bottom_app_bar_create_new_album": "Create new album", - "control_bottom_app_bar_delete": "Delete", - "control_bottom_app_bar_delete_from_immich": "Delete from Immich", - "control_bottom_app_bar_delete_from_local": "Delete from device", - "control_bottom_app_bar_download": "Download", - "control_bottom_app_bar_edit": "Edit", - "control_bottom_app_bar_edit_location": "Edit Location", - "control_bottom_app_bar_edit_time": "Edit Date & Time", - "control_bottom_app_bar_favorite": "Favorite", - "control_bottom_app_bar_share": "Share", - "control_bottom_app_bar_share_to": "Share To", - "control_bottom_app_bar_stack": "Stack", - "control_bottom_app_bar_trash_from_immich": "Move to Trash", - "control_bottom_app_bar_unarchive": "Unarchive", - "control_bottom_app_bar_unfavorite": "Unfavorite", - "control_bottom_app_bar_upload": "Upload", - "create_album": "Create album", - "create_album_page_untitled": "Untitled", - "create_new": "CREATE NEW", - "create_shared_album_page_create": "Create", - "create_shared_album_page_share": "Share", - "create_shared_album_page_share_add_assets": "ADD ASSETS", - "create_shared_album_page_share_select_photos": "Select Photos", - "crop": "Crop", - "curated_location_page_title": "Places", - "curated_object_page_title": "Things", + "action_common_back": "後退", + "action_common_cancel": "取消", + "action_common_clear": "清空", + "action_common_confirm": "確定", + "action_common_save": "儲存", + "action_common_select": "選擇", + "action_common_update": "更新", + "add_a_name": "新增姓名", + "add_endpoint": "Add endpoint", + "add_to_album_bottom_sheet_added": "新增到 {album}", + "add_to_album_bottom_sheet_already_exists": "已在 {album} 中", + "advanced_settings_log_level_title": "日誌等級: {}", + "advanced_settings_prefer_remote_subtitle": "在某些裝置上,從本地的項目載入縮圖的速度非常慢。\n啓用此選項以載入遙距項目。", + "advanced_settings_prefer_remote_title": "優先遙距項目", + "advanced_settings_proxy_headers_subtitle": "定義代理標頭,套用於Immich的每次網絡請求", + "advanced_settings_proxy_headers_title": "代理標頭", + "advanced_settings_self_signed_ssl_subtitle": "略過伺服器端點的 SSL 證書驗證(該選項適用於使用自簽名證書的伺服器)。", + "advanced_settings_self_signed_ssl_title": "允許自簽名 SSL 證書", + "advanced_settings_tile_subtitle": "進階用戶設定", + "advanced_settings_tile_title": "進階", + "advanced_settings_troubleshooting_subtitle": "啓用用於故障排除的額外功能", + "advanced_settings_troubleshooting_title": "故障排除", + "album_info_card_backup_album_excluded": "已排除", + "album_info_card_backup_album_included": "已選中", + "albums": "相簿", + "album_thumbnail_card_item": "1 項", + "album_thumbnail_card_items": "{} 項", + "album_thumbnail_card_shared": " · 已共享", + "album_thumbnail_owned": "擁有", + "album_thumbnail_shared_by": "由 {} 共享", + "album_viewer_appbar_delete_confirm": "確定要從賬戶中刪除此相簿嗎?", + "album_viewer_appbar_share_delete": "刪除相簿", + "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_remove": "從相簿中移除", + "album_viewer_appbar_share_to": "共享給", + "album_viewer_page_share_add_users": "新增用戶", + "all": "所有", + "all_people_page_title": "人物", + "all_videos_page_title": "短片", + "app_bar_signout_dialog_content": "您確定要退出嗎?", + "app_bar_signout_dialog_ok": "是", + "app_bar_signout_dialog_title": "退出登入", + "archived": "已存檔", + "archive_page_no_archived_assets": "未找到歸檔項目", + "archive_page_title": "歸檔( {} )", + "asset_action_delete_err_read_only": "無法刪除唯讀項目,略過", + "asset_action_share_err_offline": "無法獲取離線項目,略過", + "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": "月", + "asset_list_layout_settings_group_by_month_day": "月和日", + "asset_list_layout_sub_title": "佈局", + "asset_list_settings_subtitle": "照片網格佈局設定", + "asset_list_settings_title": "照片網格", + "asset_restored_successfully": "已成功恢復所有項目", + "assets_deleted_permanently": "{} 個項目已被永久刪除", + "assets_deleted_permanently_from_server": "已從伺服器中永久移除 {} 個項目", + "assets_removed_permanently_from_device": "已從裝置中永久移除 {} 個項目", + "assets_restored_successfully": "已成功恢復 {} 個項目", + "assets_trashed": "{} 個回收桶項目", + "assets_trashed_from_server": "{} 個項目已放入回收桶", + "asset_viewer_settings_subtitle": "Manage your gallery viewer settings", + "asset_viewer_settings_title": "資源查看器", + "automatic_endpoint_switching_subtitle": "Connect locally over designated Wi-Fi when available and use alternative connections elsewhere", + "automatic_endpoint_switching_title": "Automatic URL switching", + "background_location_permission": "Background location permission", + "background_location_permission_content": "In order to switch networks when running in the background, Immich must *always* have precise location access so the app can read the Wi-Fi network's name", + "backup_album_selection_page_albums_device": "裝置上的相簿( {} )", + "backup_album_selection_page_albums_tap": "單擊選中,雙擊取消", + "backup_album_selection_page_assets_scatter": "項目會分散在多個相簿中。因此,可以在備份過程中包含或排除相簿。", + "backup_album_selection_page_select_albums": "選擇相簿", + "backup_album_selection_page_selection_info": "選擇資訊", + "backup_album_selection_page_total_assets": "總計", + "backup_all": "全部", + "backup_background_service_backup_failed_message": "備份失敗,正在重試…", + "backup_background_service_connection_failed_message": "連接伺服器失敗,正在重試…", + "backup_background_service_current_upload_notification": "正在上傳 {} ", + "backup_background_service_default_notification": "正在檢查新項目…", + "backup_background_service_error_title": "備份失敗", + "backup_background_service_in_progress_notification": "正在備份…", + "backup_background_service_upload_failure_notification": "上傳失敗 {} ", + "backup_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": "延遲 {} 後備份", + "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": "僅使用 WiFi", + "backup_controller_page_backup": "備份", + "backup_controller_page_backup_selected": "已選中:", + "backup_controller_page_backup_sub": "已備份的照片和短片", + "backup_controller_page_cancel": "取消", + "backup_controller_page_created": "新增時間: {} ", + "backup_controller_page_desc_backup": "打開前台備份,以本程式運行時自動備份新項目。", + "backup_controller_page_excluded": "已排除:", + "backup_controller_page_failed": "失敗( {} )", + "backup_controller_page_filename": "文件名稱: {} [ {} ]", + "backup_controller_page_id": "ID: {} ", + "backup_controller_page_info": "備份資訊", + "backup_controller_page_none_selected": "未選擇", + "backup_controller_page_remainder": "剩餘", + "backup_controller_page_remainder_sub": "所選數據中尚未備份的數據", + "backup_controller_page_select": "選擇", + "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": " {} / {} 已使用", + "backup_controller_page_to_backup": "要備份的相簿", + "backup_controller_page_total": "總計", + "backup_controller_page_total_sub": "選中相簿中所有不重複的短片和圖片", + "backup_controller_page_turn_off": "關閉前台備份", + "backup_controller_page_turn_on": "開啓前台備份", + "backup_controller_page_uploading_file_info": "正在上傳中的文件資訊", + "backup_err_only_album": "不能移除唯一的相簿", + "backup_info_card_assets": "項", + "backup_manual_cancelled": "已取消", + "backup_manual_failed": "失敗", + "backup_manual_in_progress": "上傳正在進行中,請稍後再試", + "backup_manual_success": "成功", + "backup_manual_title": "上傳狀態", + "backup_options_page_title": "備份選項", + "backup_setting_subtitle": "Manage background and foreground upload settings", + "cache_settings_album_thumbnails": "圖庫縮圖( {} 項)", + "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": "重複項目( {} )", + "cache_settings_image_cache_size": "圖片緩存大小( {} 項)", + "cache_settings_statistics_album": "圖庫縮圖", + "cache_settings_statistics_assets": " {} 項( {} )", + "cache_settings_statistics_full": "完整圖片", + "cache_settings_statistics_shared": "共享相簿縮圖", + "cache_settings_statistics_thumbnail": "縮圖", + "cache_settings_statistics_title": "緩存使用情況", + "cache_settings_subtitle": "控制 Immich app 的緩存行為", + "cache_settings_thumbnail_size": "縮圖緩存大小( {} 項)", + "cache_settings_tile_subtitle": "設定本地存儲行為", + "cache_settings_tile_title": "本地存儲", + "cache_settings_title": "緩存設定", + "cancel": "Cancel", + "change_display_order": "Change display order", + "change_password_form_confirm_password": "確認密碼", + "change_password_form_description": "您好 {name} :\n\n這是您首次登入系統,或被管理員要求更改密碼。\n請在下方輸入新密碼。", + "change_password_form_new_password": "新密碼", + "change_password_form_password_mismatch": "密碼不一致", + "change_password_form_reenter_new_password": "再次輸入新密碼", + "check_corrupt_asset_backup": "Check for corrupt asset backups", + "check_corrupt_asset_backup_button": "Perform check", + "check_corrupt_asset_backup_description": "Run this check only over Wi-Fi and once all assets have been backed-up. The procedure might take a few minutes.", + "client_cert_dialog_msg_confirm": "確定", + "client_cert_enter_password": "輸入密碼", + "client_cert_import": "匯入", + "client_cert_import_success_msg": "已匯入客戶端證書", + "client_cert_invalid_msg": "無效的證書文件或密碼錯誤", + "client_cert_remove": "移除", + "client_cert_remove_msg": "客戶端證書已移除", + "client_cert_subtitle": "僅支持PKCS12 (.p12, .pfx)格式。僅可在登入前進行證書的匯入和移除", + "client_cert_title": "SSL客戶端證書", + "common_add_to_album": "新增到相簿", + "common_change_password": "更改密碼", + "common_create_new_album": "新增相簿", + "common_server_error": "請檢查您的網絡連接,確保伺服器可連接,且本程式與伺服器版本兼容。", + "common_shared": "共享", + "contextual_search": "海灘上的日出", + "control_bottom_app_bar_add_to_album": "新增到相簿", + "control_bottom_app_bar_album_info": " {} 項", + "control_bottom_app_bar_album_info_shared": " {} 項 · 已共享", + "control_bottom_app_bar_archive": "歸檔", + "control_bottom_app_bar_create_new_album": "新增相簿", + "control_bottom_app_bar_delete": "刪除", + "control_bottom_app_bar_delete_from_immich": "從Immich伺服器中刪除", + "control_bottom_app_bar_delete_from_local": "從移動裝置中刪除", + "control_bottom_app_bar_download": "下載", + "control_bottom_app_bar_edit": "編輯", + "control_bottom_app_bar_edit_location": "編輯位置資訊", + "control_bottom_app_bar_edit_time": "編輯日期和時間", + "control_bottom_app_bar_favorite": "收藏", + "control_bottom_app_bar_share": "共享", + "control_bottom_app_bar_share_to": "發送給", + "control_bottom_app_bar_stack": "堆疊", + "control_bottom_app_bar_trash_from_immich": "放入回收桶", + "control_bottom_app_bar_unarchive": "取消歸檔", + "control_bottom_app_bar_unfavorite": "取消收藏", + "control_bottom_app_bar_upload": "上傳", + "create_album": "新增相簿", + "create_album_page_untitled": "未命名", + "create_new": "新增", + "create_shared_album_page_create": "新增", + "create_shared_album_page_share": "共享", + "create_shared_album_page_share_add_assets": "新增項目", + "create_shared_album_page_share_select_photos": "選擇項目", + "crop": "裁剪", + "curated_location_page_title": "地點", + "curated_object_page_title": "事物", + "current_server_address": "Current server address", "daily_title_text_date": "E, MMM dd", "daily_title_text_date_year": "E, MMM dd, yyyy", "date_format": "E, LLL d, y • h:mm a", - "delete_dialog_alert": "These items will be permanently deleted from Immich and from your device", - "delete_dialog_alert_local": "These items will be permanently removed from your device but still be available on the Immich server", - "delete_dialog_alert_local_non_backed_up": "Some of the items aren't backed up to Immich and will be permanently removed from your device", - "delete_dialog_alert_remote": "These items will be permanently deleted from the Immich server", - "delete_dialog_cancel": "Cancel", - "delete_dialog_ok": "Delete", - "delete_dialog_ok_force": "Delete Anyway", - "delete_dialog_title": "Delete Permanently", - "delete_local_dialog_ok_backed_up_only": "Delete Backed Up Only", - "delete_local_dialog_ok_force": "Delete Anyway", - "delete_shared_link_dialog_content": "Are you sure you want to delete this shared link?", - "delete_shared_link_dialog_title": "Delete Shared Link", - "description_input_hint_text": "Add description...", - "description_input_submit_error": "Error updating description, check the log for more details", - "download_canceled": "Download canceled", - "download_complete": "Download complete", - "download_enqueue": "Download enqueued", - "download_error": "Download Error", - "download_failed": "Download failed", - "download_filename": "file: {}", - "download_finished": "Download finished", - "downloading": "Downloading...", - "downloading_media": "Downloading media", - "download_notfound": "Download not found", - "download_paused": "Download paused", - "download_started": "Download started", - "download_sucess": "Download success", - "download_sucess_android": "The media has been downloaded to DCIM/Immich", - "download_waiting_to_retry": "Waiting to retry", - "edit_date_time_dialog_date_time": "Date and Time", - "edit_date_time_dialog_timezone": "Timezone", - "edit_image_title": "Edit", - "edit_location_dialog_title": "Location", - "error_saving_image": "Error: {}", - "exif_bottom_sheet_description": "Add Description...", - "exif_bottom_sheet_details": "DETAILS", - "exif_bottom_sheet_location": "LOCATION", - "exif_bottom_sheet_location_add": "Add a location", - "exif_bottom_sheet_people": "PEOPLE", - "exif_bottom_sheet_person_add_person": "Add name", - "experimental_settings_new_asset_list_subtitle": "Work in progress", - "experimental_settings_new_asset_list_title": "Enable experimental photo grid", - "experimental_settings_subtitle": "Use at your own risk!", - "experimental_settings_title": "Experimental", - "favorites": "Favorites", - "favorites_page_no_favorites": "No favorite assets found", - "favorites_page_title": "Favorites", - "filename_search": "File name or extension", - "filter": "Filter", - "haptic_feedback_switch": "Enable haptic feedback", - "haptic_feedback_title": "Haptic Feedback", - "header_settings_add_header_tip": "Add Header", - "header_settings_field_validator_msg": "Value cannot be empty", - "header_settings_header_name_input": "Header name", - "header_settings_header_value_input": "Header value", - "header_settings_page_title": "Proxy Headers", - "headers_settings_tile_subtitle": "Define proxy headers the app should send with each network request", - "headers_settings_tile_title": "Custom proxy headers", - "home_page_add_to_album_conflicts": "Added {added} assets to album {album}. {failed} assets are already in the album.", - "home_page_add_to_album_err_local": "Can not add local assets to albums yet, skipping", - "home_page_add_to_album_success": "Added {added} assets to album {album}.", - "home_page_album_err_partner": "Can not add partner assets to an album yet, skipping", - "home_page_archive_err_local": "Can not archive local assets yet, skipping", - "home_page_archive_err_partner": "Can not archive partner assets, skipping", - "home_page_building_timeline": "Building the timeline", - "home_page_delete_err_partner": "Can not delete partner assets, skipping", - "home_page_delete_remote_err_local": "Local assets in delete remote selection, skipping", - "home_page_favorite_err_local": "Can not favorite local assets yet, skipping", - "home_page_favorite_err_partner": "Can not favorite partner assets yet, skipping", - "home_page_first_time_notice": "If this is your first time using the app, please make sure to choose a backup album(s) so that the timeline can populate photos and videos in the album(s).", - "home_page_share_err_local": "Can not share local assets via link, skipping", - "home_page_upload_err_limit": "Can only upload a maximum of 30 assets at a time, skipping", - "ignore_icloud_photos": "Ignore iCloud photos", - "ignore_icloud_photos_description": "Photos that are stored on iCloud will not be uploaded to the Immich server", - "image_saved_successfully": "Image saved", - "image_viewer_page_state_provider_download_error": "Download Error", - "image_viewer_page_state_provider_download_started": "Download Started", - "image_viewer_page_state_provider_download_success": "Download Success", - "image_viewer_page_state_provider_share_error": "Share Error", - "invalid_date": "Invalid date", - "invalid_date_format": "Invalid date format", - "library": "Library", - "library_page_albums": "Albums", - "library_page_archive": "Archive", - "library_page_device_albums": "Albums on Device", - "library_page_favorites": "Favorites", - "library_page_new_album": "New album", - "library_page_sharing": "Sharing", - "library_page_sort_asset_count": "Number of assets", - "library_page_sort_created": "Created date", - "library_page_sort_last_modified": "Last modified", - "library_page_sort_most_oldest_photo": "Oldest photo", - "library_page_sort_most_recent_photo": "Most recent photo", - "library_page_sort_title": "Album title", - "location_picker_choose_on_map": "Choose on map", - "location_picker_latitude": "Latitude", - "location_picker_latitude_error": "Enter a valid latitude", - "location_picker_latitude_hint": "Enter your latitude here", - "location_picker_longitude": "Longitude", - "location_picker_longitude_error": "Enter a valid longitude", - "location_picker_longitude_hint": "Enter your longitude here", - "login_disabled": "Login has been disabled", - "login_form_api_exception": "API exception. Please check the server URL and try again.", - "login_form_back_button_text": "Back", - "login_form_button_text": "Login", + "delete_dialog_alert": "這些項目將從 Immich 和您的裝置中永久刪除", + "delete_dialog_alert_local": "這些項目將從您的移動裝置中永久刪除,但仍然可以從Immich伺服器中再次獲取", + "delete_dialog_alert_local_non_backed_up": "部分項目還未備份至Immich伺服器,將從您的移動裝置中永久刪除", + "delete_dialog_alert_remote": "這些項目將從Immich伺服器中永久刪除", + "delete_dialog_cancel": "取消", + "delete_dialog_ok": "刪除", + "delete_dialog_ok_force": "確認刪除", + "delete_dialog_title": "永久刪除", + "delete_local_dialog_ok_backed_up_only": "僅刪除已備份項目", + "delete_local_dialog_ok_force": "確認刪除", + "delete_shared_link_dialog_content": "確定要刪除此共享鏈接?", + "delete_shared_link_dialog_title": "刪除共享鏈接", + "description_input_hint_text": "新增描述...", + "description_input_submit_error": "更新描述時出錯,請檢查日誌以獲取更多詳細資訊", + "download_canceled": "下載已取消", + "download_complete": "下載完成", + "download_enqueue": "已加入下載隊列", + "download_error": "下載出錯", + "download_failed": "下載失敗", + "download_filename": "文件: {} ", + "download_finished": "下載完成", + "downloading": "下載中...", + "downloading_media": "正在下載媒體", + "download_notfound": "無法找到下載", + "download_paused": "下載已暫停", + "download_started": "開始下載", + "download_sucess": "下載成功", + "download_sucess_android": "媒體已下載至 DCIM/Immich", + "download_waiting_to_retry": "等待重試", + "edit_date_time_dialog_date_time": "日期和時間", + "edit_date_time_dialog_timezone": "時區", + "edit_image_title": "編輯", + "edit_location_dialog_title": "位置", + "enter_wifi_name": "Enter WiFi name", + "error_change_sort_album": "Failed to change album sort order", + "error_saving_image": "錯誤: {} ", + "exif_bottom_sheet_description": "新增描述...", + "exif_bottom_sheet_details": "詳情", + "exif_bottom_sheet_location": "位置", + "exif_bottom_sheet_location_add": "新增位置資訊", + "exif_bottom_sheet_people": "人物", + "exif_bottom_sheet_person_add_person": "新增姓名", + "experimental_settings_new_asset_list_subtitle": "正在處理", + "experimental_settings_new_asset_list_title": "啓用實驗性照片網格", + "experimental_settings_subtitle": "使用風險自負!", + "experimental_settings_title": "實驗性功能", + "external_network": "External network", + "external_network_sheet_info": "When not on the preferred WiFi network, the app will connect to the server through the first of the below URLs it can reach, starting from top to bottom", + "favorites": "收藏", + "favorites_page_no_favorites": "未找到收藏項目", + "favorites_page_title": "收藏", + "filename_search": "文件名或副檔名", + "filter": "篩選", + "get_wifiname_error": "Could not get Wi-Fi name. Make sure you have granted the necessary permissions and are connected to a Wi-Fi network", + "grant_permission": "Grant permission", + "haptic_feedback_switch": "啓用振動反饋", + "haptic_feedback_title": "振動反饋", + "header_settings_add_header_tip": "新增標頭", + "header_settings_field_validator_msg": "設定不可為空", + "header_settings_header_name_input": "標頭名稱", + "header_settings_header_value_input": "標頭值", + "header_settings_page_title": "代理標頭", + "headers_settings_tile_subtitle": "定義代理標頭,套用於每次網絡請求", + "headers_settings_tile_title": "自定義代理標頭", + "home_page_add_to_album_conflicts": "已在相簿 {album} 中新增 {added} 項。\n其中 {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_share_err_local": "暫無法通過鏈接共享本地項目,略過", + "home_page_upload_err_limit": "一次最多只能上傳 30 個項目,略過", + "ignore_icloud_photos": "忽略iCloud照片", + "ignore_icloud_photos_description": "存儲在iCloud中的照片不會上傳至Immich伺服器", + "image_saved_successfully": "圖片已儲存", + "image_viewer_page_state_provider_download_error": "下載出現錯誤", + "image_viewer_page_state_provider_download_started": "下載啓動", + "image_viewer_page_state_provider_download_success": "下載成功", + "image_viewer_page_state_provider_share_error": "共享出錯", + "invalid_date": "無效的日期", + "invalid_date_format": "無效的日期格式", + "library": "圖庫", + "library_page_albums": "相簿", + "library_page_archive": "歸檔", + "library_page_device_albums": "裝置上的相簿", + "library_page_favorites": "收藏", + "library_page_new_album": "新增相簿", + "library_page_sharing": "共享", + "library_page_sort_asset_count": "項目數量", + "library_page_sort_created": "新增日期", + "library_page_sort_last_modified": "上次修改", + "library_page_sort_most_oldest_photo": "最早的照片", + "library_page_sort_most_recent_photo": "最近的項目", + "library_page_sort_title": "相簿標題", + "local_network": "Local network", + "local_network_sheet_info": "The app will connect to the server through this URL when using the specified Wi-Fi network", + "location_permission": "Location permission", + "location_permission_content": "In order to use the auto-switching feature, Immich needs precise location permission so it can read the current WiFi network's name", + "location_picker_choose_on_map": "在地圖上選擇", + "location_picker_latitude": "緯度", + "location_picker_latitude_error": "輸入有效的緯度值", + "location_picker_latitude_hint": "請在此處輸入您的緯度值", + "location_picker_longitude": "經度", + "location_picker_longitude_error": "輸入有效的經度值", + "location_picker_longitude_hint": "請在此處輸入您的經度值", + "login_disabled": "已禁用登入", + "login_form_api_exception": "API 異常,請檢查伺服器地址並重試。", + "login_form_back_button_text": "後退", + "login_form_button_text": "登入", "login_form_email_hint": "youremail@email.com", - "login_form_endpoint_hint": "http://your-server-ip:port/api", - "login_form_endpoint_url": "Server Endpoint URL", - "login_form_err_http": "Please specify http:// or https://", - "login_form_err_invalid_email": "Invalid Email", - "login_form_err_invalid_url": "Invalid URL", - "login_form_err_leading_whitespace": "Leading whitespace", - "login_form_err_trailing_whitespace": "Trailing whitespace", - "login_form_failed_get_oauth_server_config": "Error logging using OAuth, check server URL", - "login_form_failed_get_oauth_server_disable": "OAuth feature is not available on this server", - "login_form_failed_login": "Error logging you in, check server URL, email and password", - "login_form_handshake_exception": "There was an Handshake Exception with the server. Enable self-signed certificate support in the settings if you are using a self-signed certificate.", - "login_form_label_email": "Email", - "login_form_label_password": "Password", - "login_form_next_button": "Next", - "login_form_password_hint": "password", - "login_form_save_login": "Stay logged in", - "login_form_server_empty": "Enter a server URL.", - "login_form_server_error": "Could not connect to server.", - "login_password_changed_error": "There was an error updating your password", - "login_password_changed_success": "Password updated successfully", - "map_assets_in_bound": "{} photo", - "map_assets_in_bounds": "{} photos", - "map_cannot_get_user_location": "Cannot get user's location", - "map_location_dialog_cancel": "Cancel", - "map_location_dialog_yes": "Yes", - "map_location_picker_page_use_location": "Use this location", - "map_location_service_disabled_content": "Location service needs to be enabled to display assets from your current location. Do you want to enable it now?", - "map_location_service_disabled_title": "Location Service disabled", - "map_no_assets_in_bounds": "No photos in this area", - "map_no_location_permission_content": "Location permission is needed to display assets from your current location. Do you want to allow it now?", - "map_no_location_permission_title": "Location Permission denied", - "map_settings_dark_mode": "Dark mode", - "map_settings_date_range_option_all": "All", - "map_settings_date_range_option_day": "Past 24 hours", - "map_settings_date_range_option_days": "Past {} days", - "map_settings_date_range_option_year": "Past year", - "map_settings_date_range_option_years": "Past {} years", - "map_settings_dialog_cancel": "Cancel", - "map_settings_dialog_save": "Save", - "map_settings_dialog_title": "Map Settings", - "map_settings_include_show_archived": "Include Archived", - "map_settings_include_show_partners": "Include Partners", - "map_settings_only_relative_range": "Date range", - "map_settings_only_show_favorites": "Show Favorite Only", - "map_settings_theme_settings": "Map Theme", - "map_zoom_to_see_photos": "Zoom out to see photos", - "memories_all_caught_up": "All caught up", - "memories_check_back_tomorrow": "Check back tomorrow for more memories", - "memories_start_over": "Start Over", - "memories_swipe_to_close": "Swipe up to close", - "memories_year_ago": "A year ago", - "memories_years_ago": "{} years ago", + "login_form_endpoint_hint": "http(s)://您的伺服器地址:端口/api", + "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": "登入失敗,請檢查伺服器地址、電郵和密碼", + "login_form_handshake_exception": "與伺服器通信時出現握手異常。如果您使用的是自簽名證書,請在設定中啓用自簽名證書支持。", + "login_form_label_email": "電郵", + "login_form_label_password": "密碼", + "login_form_next_button": "下一個", + "login_form_password_hint": "密碼", + "login_form_save_login": "保持登入", + "login_form_server_empty": "輸入伺服器地址", + "login_form_server_error": "無法連接到伺服器。", + "login_password_changed_error": "密碼更新失敗", + "login_password_changed_success": "密碼更新成功", + "map_assets_in_bound": " {} 張照片", + "map_assets_in_bounds": " {} 張照片", + "map_cannot_get_user_location": "無法獲取用戶位置", + "map_location_dialog_cancel": "取消", + "map_location_dialog_yes": "確定", + "map_location_picker_page_use_location": "使用此位置", + "map_location_service_disabled_content": "需要啓用定位服務才能顯示當前位置相關的項目。要現在啓用嗎?", + "map_location_service_disabled_title": "定位服務已禁用", + "map_no_assets_in_bounds": "此區域中沒有相關項目", + "map_no_location_permission_content": "需要位置權限才能顯示與當前位置相關的項目。要現在就授予位置權限嗎?", + "map_no_location_permission_title": "位置權限被拒絕", + "map_settings_dark_mode": "深色模式", + "map_settings_date_range_option_all": "所有", + "map_settings_date_range_option_day": "過去24小時", + "map_settings_date_range_option_days": " {} 天前", + "map_settings_date_range_option_year": "1年前", + "map_settings_date_range_option_years": " {} 年前", + "map_settings_dialog_cancel": "取消", + "map_settings_dialog_save": "儲存", + "map_settings_dialog_title": "地圖設定", + "map_settings_include_show_archived": "包括已歸檔項目", + "map_settings_include_show_partners": "包含夥伴", + "map_settings_only_relative_range": "日期範圍", + "map_settings_only_show_favorites": "僅顯示收藏的項目", + "map_settings_theme_settings": "地圖主題", + "map_zoom_to_see_photos": "縮小以查看項目", + "memories_all_caught_up": "已全部看完", + "memories_check_back_tomorrow": "明天再看", + "memories_start_over": "再看一次", + "memories_swipe_to_close": "上滑關閉", + "memories_year_ago": "1年前", + "memories_years_ago": " {} 年前", "monthly_title_text_date_format": "MMMM y", - "motion_photos_page_title": "Motion Photos", - "multiselect_grid_edit_date_time_err_read_only": "Cannot edit date of read only asset(s), skipping", - "multiselect_grid_edit_gps_err_read_only": "Cannot edit location of read only asset(s), skipping", - "my_albums": "My albums", - "no_assets_to_show": "No assets to show", - "no_name": "No name", - "notification_permission_dialog_cancel": "Cancel", - "notification_permission_dialog_content": "To enable notifications, go to Settings and select allow.", - "notification_permission_dialog_settings": "Settings", - "notification_permission_list_tile_content": "Grant permission to enable notifications.", - "notification_permission_list_tile_enable_button": "Enable Notifications", - "notification_permission_list_tile_title": "Notification Permission", - "on_this_device": "On this device", - "partner_list_user_photos": "{user}'s photos", - "partner_list_view_all": "View all", - "partner_page_add_partner": "Add partner", - "partner_page_empty_message": "Your photos are not yet shared with any partner.", - "partner_page_no_more_users": "No more users to add", - "partner_page_partner_add_failed": "Failed to add partner", - "partner_page_select_partner": "Select partner", - "partner_page_shared_to_title": "Shared to", - "partner_page_stop_sharing_content": "{} will no longer be able to access your photos.", - "partner_page_stop_sharing_title": "Stop sharing your photos?", - "partner_page_title": "Partner", - "partners": "Partners", - "people": "People", - "permission_onboarding_back": "Back", - "permission_onboarding_continue_anyway": "Continue anyway", - "permission_onboarding_get_started": "Get started", - "permission_onboarding_go_to_settings": "Go to settings", - "permission_onboarding_grant_permission": "Grant permission", - "permission_onboarding_log_out": "Log out", - "permission_onboarding_permission_denied": "Permission denied. To use Immich, grant photo and video permissions in Settings.", - "permission_onboarding_permission_granted": "Permission granted! You are all set.", - "permission_onboarding_permission_limited": "Permission limited. To let Immich backup and manage your entire gallery collection, grant photo and video permissions in Settings.", - "permission_onboarding_request": "Immich requires permission to view your photos and videos.", - "places": "Places", - "preferences_settings_title": "Preferences", - "profile_drawer_app_logs": "Logs", - "profile_drawer_client_out_of_date_major": "Mobile App is out of date. Please update to the latest major version.", - "profile_drawer_client_out_of_date_minor": "Mobile App is out of date. Please update to the latest minor version.", - "profile_drawer_client_server_up_to_date": "Client and Server are up-to-date", - "profile_drawer_documentation": "Documentation", + "motion_photos_page_title": "動態照片", + "multiselect_grid_edit_date_time_err_read_only": "無法編輯唯讀項目的日期,略過", + "multiselect_grid_edit_gps_err_read_only": "無法編輯唯讀項目的位置資訊,略過", + "my_albums": "我的相簿", + "networking_settings": "Networking", + "networking_subtitle": "Manage the server endpoint settings", + "no_assets_to_show": "無項目展示", + "no_name": "無姓名", + "notification_permission_dialog_cancel": "取消", + "notification_permission_dialog_content": "要啓用通知,請前往「設定」,並選擇「允許」。", + "notification_permission_dialog_settings": "設定", + "notification_permission_list_tile_content": "授予通知權限。", + "notification_permission_list_tile_enable_button": "啓用通知", + "notification_permission_list_tile_title": "通知權限", + "on_this_device": "在此裝置", + "partner_list_user_photos": "{user} 的照片", + "partner_list_view_all": "展示全部", + "partner_page_add_partner": "新增同伴", + "partner_page_empty_message": "您的照片尚未與任何同伴共享。", + "partner_page_no_more_users": "無需新增更多用戶", + "partner_page_partner_add_failed": "新增同伴失敗", + "partner_page_select_partner": "選擇同伴", + "partner_page_shared_to_title": "共享給", + "partner_page_stop_sharing_content": " {} 將無法再存取您的照片。", + "partner_page_stop_sharing_title": "您確定要停止共享您的照片嗎?", + "partner_page_title": "同伴", + "partners": "同伴", + "people": "人物", + "permission_onboarding_back": "返回", + "permission_onboarding_continue_anyway": "仍然繼續", + "permission_onboarding_get_started": "開始使用", + "permission_onboarding_go_to_settings": "前往設定", + "permission_onboarding_grant_permission": "授予權限", + "permission_onboarding_log_out": "登出", + "permission_onboarding_permission_denied": "權限被拒:要使用 Immich,請在「設定」中授予照片和短片權限。", + "permission_onboarding_permission_granted": "已授權!一切就緒。", + "permission_onboarding_permission_limited": "權限受限:要讓 Immich 備份和管理您的整個圖庫收藏,請在「設定」中授予照片和短片權限。", + "permission_onboarding_request": "Immich 需要權限才能查看您的照片和短片。", + "places": "地點", + "preferences_settings_subtitle": "Manage the app's preferences", + "preferences_settings_title": "偏好設定", + "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_documentation": "文檔", "profile_drawer_github": "GitHub", - "profile_drawer_server_out_of_date_major": "Server is out of date. Please update to the latest major version.", - "profile_drawer_server_out_of_date_minor": "Server is out of date. Please update to the latest minor version.", - "profile_drawer_settings": "Settings", - "profile_drawer_sign_out": "Sign Out", - "profile_drawer_trash": "Trash", - "recently_added": "Recently added", - "recently_added_page_title": "Recently Added", - "save_to_gallery": "Save to gallery", - "scaffold_body_error_occurred": "Error occurred", - "search_albums": "Search albums", - "search_bar_hint": "Search your photos", - "search_filter_apply": "Apply filter", - "search_filter_camera": "Camera", - "search_filter_camera_make": "Make", - "search_filter_camera_model": "Model", - "search_filter_camera_title": "Select camera type", - "search_filter_date": "Date", - "search_filter_date_interval": "{start} to {end}", - "search_filter_date_title": "Select a date range", - "search_filter_display_option_archive": "Archive", - "search_filter_display_option_favorite": "Favorite", - "search_filter_display_option_not_in_album": "Not in album", - "search_filter_display_options": "Display Options", - "search_filter_display_options_title": "Display options", - "search_filter_location": "Location", - "search_filter_location_city": "City", - "search_filter_location_country": "Country", - "search_filter_location_state": "State", - "search_filter_location_title": "Select location", - "search_filter_media_type": "Media Type", - "search_filter_media_type_all": "All", - "search_filter_media_type_image": "Image", - "search_filter_media_type_title": "Select media type", - "search_filter_media_type_video": "Video", - "search_filter_people": "People", - "search_filter_people_title": "Select people", - "search_page_categories": "Categories", - "search_page_favorites": "Favorites", - "search_page_motion_photos": "Motion Photos", - "search_page_no_objects": "No Objects Info Available", - "search_page_no_places": "No Places Info Available", - "search_page_people": "People", - "search_page_person_add_name_dialog_cancel": "Cancel", - "search_page_person_add_name_dialog_hint": "Name", - "search_page_person_add_name_dialog_save": "Save", - "search_page_person_add_name_dialog_title": "Add a name", - "search_page_person_add_name_subtitle": "Find them fast by name with search", - "search_page_person_add_name_title": "Add a name", - "search_page_person_edit_name": "Edit name", - "search_page_places": "Places", - "search_page_recently_added": "Recently added", - "search_page_screenshots": "Screenshots", - "search_page_selfies": "Selfies", - "search_page_things": "Things", - "search_page_videos": "Videos", - "search_page_view_all_button": "View all", - "search_page_your_activity": "Your activity", - "search_page_your_map": "Your Map", - "search_result_page_new_search_hint": "New Search", - "search_suggestion_list_smart_search_hint_1": "Smart search is enabled by default, to search for metadata use the syntax ", - "search_suggestion_list_smart_search_hint_2": "m:your-search-term", - "select_additional_user_for_sharing_page_suggestions": "Suggestions", - "select_user_for_sharing_page_err_album": "Failed to create album", - "select_user_for_sharing_page_share_suggestions": "Suggestions", - "server_info_box_app_version": "App Version", - "server_info_box_latest_release": "Latest Version", - "server_info_box_server_url": "Server URL", - "server_info_box_server_version": "Server Version", - "setting_image_viewer_help": "The detail viewer loads the small thumbnail first, then loads the medium-size preview (if enabled), finally loads the original (if enabled).", - "setting_image_viewer_original_subtitle": "Enable to load the original full-resolution image (large!). Disable to reduce data usage (both network and on device cache).", - "setting_image_viewer_original_title": "Load original image", - "setting_image_viewer_preview_subtitle": "Enable to load a medium-resolution image. Disable to either directly load the original or only use the thumbnail.", - "setting_image_viewer_preview_title": "Load preview image", - "setting_image_viewer_title": "Images", - "setting_languages_apply": "Apply", - "setting_languages_title": "Languages", - "setting_notifications_notify_failures_grace_period": "Notify background backup failures: {}", - "setting_notifications_notify_hours": "{} hours", - "setting_notifications_notify_immediately": "immediately", - "setting_notifications_notify_minutes": "{} minutes", - "setting_notifications_notify_never": "never", - "setting_notifications_notify_seconds": "{} seconds", - "setting_notifications_single_progress_subtitle": "Detailed upload progress information per asset", - "setting_notifications_single_progress_title": "Show background backup detail progress", - "setting_notifications_subtitle": "Adjust your notification preferences", - "setting_notifications_title": "Notifications", - "setting_notifications_total_progress_subtitle": "Overall upload progress (done/total assets)", - "setting_notifications_total_progress_title": "Show background backup total progress", - "setting_pages_app_bar_settings": "Settings", - "settings_require_restart": "Please restart Immich to apply this setting", - "setting_video_viewer_looping_subtitle": "Enable to automatically loop a video in the detail viewer.", - "setting_video_viewer_looping_title": "Looping", - "setting_video_viewer_title": "Videos", - "share_add": "Add", - "share_add_photos": "Add photos", - "share_add_title": "Add a title", - "share_assets_selected": "{} selected", - "share_create_album": "Create album", - "shared_album_activities_input_disable": "Comment is disabled", - "shared_album_activities_input_hint": "Say something", - "shared_album_activity_remove_content": "Do you want to delete this activity?", - "shared_album_activity_remove_title": "Delete Activity", - "shared_album_activity_setting_subtitle": "Let others respond", - "shared_album_activity_setting_title": "Comments & likes", - "shared_album_section_people_action_error": "Error leaving/removing from album", - "shared_album_section_people_action_leave": "Remove user from album", - "shared_album_section_people_action_remove_user": "Remove user from album", - "shared_album_section_people_owner_label": "Owner", - "shared_album_section_people_title": "PEOPLE", - "share_dialog_preparing": "Preparing...", - "shared_link_app_bar_title": "Shared Links", - "shared_link_clipboard_copied_massage": "Copied to clipboard", - "shared_link_clipboard_text": "Link: {}\nPassword: {}", - "shared_link_create_app_bar_title": "Create link to share", - "shared_link_create_error": "Error while creating shared link", - "shared_link_create_info": "Let anyone with the link see the selected photo(s)", - "shared_link_create_submit_button": "Create link", - "shared_link_edit_allow_download": "Allow public user to download", - "shared_link_edit_allow_upload": "Allow public user to upload", - "shared_link_edit_app_bar_title": "Edit link", - "shared_link_edit_change_expiry": "Change expiration time", - "shared_link_edit_description": "Description", - "shared_link_edit_description_hint": "Enter the share description", - "shared_link_edit_expire_after": "Expire after", - "shared_link_edit_expire_after_option_day": "1 day", - "shared_link_edit_expire_after_option_days": "{} days", - "shared_link_edit_expire_after_option_hour": "1 hour", - "shared_link_edit_expire_after_option_hours": "{} hours", - "shared_link_edit_expire_after_option_minute": "1 minute", - "shared_link_edit_expire_after_option_minutes": "{} minutes", - "shared_link_edit_expire_after_option_months": "{} months", - "shared_link_edit_expire_after_option_never": "Never", - "shared_link_edit_expire_after_option_year": "{} year", - "shared_link_edit_password": "Password", - "shared_link_edit_password_hint": "Enter the share password", - "shared_link_edit_show_meta": "Show metadata", - "shared_link_edit_submit_button": "Update link", - "shared_link_empty": "You don't have any shared links", - "shared_link_error_server_url_fetch": "Cannot fetch the server url", - "shared_link_expired": "Expired", - "shared_link_expires_day": "Expires in {} day", - "shared_link_expires_days": "Expires in {} days", - "shared_link_expires_hour": "Expires in {} hour", - "shared_link_expires_hours": "Expires in {} hours", - "shared_link_expires_minute": "Expires in {} minute", - "shared_link_expires_minutes": "Expires in {} minutes", - "shared_link_expires_never": "Expires ∞", - "shared_link_expires_second": "Expires in {} second", - "shared_link_expires_seconds": "Expires in {} seconds", - "shared_link_individual_shared": "Individual shared", - "shared_link_info_chip_download": "Download", + "profile_drawer_server_out_of_date_major": "服務端有大版本升級,請盡快升級至最新版。", + "profile_drawer_server_out_of_date_minor": "服務端有小版本升級,請盡快升級至最新版。", + "profile_drawer_settings": "設定", + "profile_drawer_sign_out": "登出", + "profile_drawer_trash": "回收桶", + "recently_added": "近期新增", + "recently_added_page_title": "最近新增", + "save": "Save", + "save_to_gallery": "儲存到圖庫", + "scaffold_body_error_occurred": "發生錯誤", + "search_albums": "搜尋相簿", + "search_bar_hint": "搜尋照片", + "search_filter_apply": "套用篩選", + "search_filter_camera": "相機", + "search_filter_camera_make": "製造商", + "search_filter_camera_model": "型號", + "search_filter_camera_title": "選擇相機類型", + "search_filter_date": "日期", + "search_filter_date_interval": "從 {start} 到 {end}", + "search_filter_date_title": "選擇日期範圍", + "search_filter_display_option_archive": "歸檔", + "search_filter_display_option_favorite": "收藏", + "search_filter_display_option_not_in_album": "不在相簿中", + "search_filter_display_options": "顯示選項", + "search_filter_display_options_title": "顯示選項", + "search_filter_location": "位置", + "search_filter_location_city": "城市", + "search_filter_location_country": "國家", + "search_filter_location_state": "省", + "search_filter_location_title": "選擇位置", + "search_filter_media_type": "媒體類型", + "search_filter_media_type_all": "所有", + "search_filter_media_type_image": "照片", + "search_filter_media_type_title": "選擇媒體類型", + "search_filter_media_type_video": "短片", + "search_filter_people": "人物", + "search_filter_people_title": "選擇人物", + "search_page_categories": "類別", + "search_page_favorites": "收藏", + "search_page_motion_photos": "動態照片\n", + "search_page_no_objects": "找不到物件資訊", + "search_page_no_places": "找不到地點資訊", + "search_page_people": "人物", + "search_page_person_add_name_dialog_cancel": "取消", + "search_page_person_add_name_dialog_hint": "姓名", + "search_page_person_add_name_dialog_save": "儲存", + "search_page_person_add_name_dialog_title": "新增姓名", + "search_page_person_add_name_subtitle": "通過姓名快速查找", + "search_page_person_add_name_title": "新增姓名", + "search_page_person_edit_name": "編輯姓名", + "search_page_places": "地點", + "search_page_recently_added": "最近新增", + "search_page_screenshots": "屏幕截圖", + "search_page_search_photos_videos": "Search for your photos and videos", + "search_page_selfies": "自拍", + "search_page_things": "事物", + "search_page_videos": "短片", + "search_page_view_all_button": "查看全部", + "search_page_your_activity": "您的活動", + "search_page_your_map": "你的足跡", + "search_result_page_new_search_hint": "搜尋新的", + "search_suggestion_list_smart_search_hint_1": "默認情況下啓用智能搜尋,要搜尋中繼數據,請使用相關語法", + "search_suggestion_list_smart_search_hint_2": "m:您的搜尋關鍵詞", + "select_additional_user_for_sharing_page_suggestions": "建議", + "select_user_for_sharing_page_err_album": "新增相簿失敗", + "select_user_for_sharing_page_share_suggestions": "建議", + "server_endpoint": "Server Endpoint", + "server_info_box_app_version": "App 版本", + "server_info_box_latest_release": "最新版本", + "server_info_box_server_url": "伺服器地址", + "server_info_box_server_version": "伺服器版本", + "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": "Change the app's language", + "setting_languages_title": "語言", + "setting_notifications_notify_failures_grace_period": "背景備份失敗通知: {} ", + "setting_notifications_notify_hours": " {} 小時", + "setting_notifications_notify_immediately": "立即", + "setting_notifications_notify_minutes": " {} 分鐘", + "setting_notifications_notify_never": "從不", + "setting_notifications_notify_seconds": " {} 秒", + "setting_notifications_single_progress_subtitle": "每項的詳細上傳進度資訊", + "setting_notifications_single_progress_title": "顯示背景備份詳細進度", + "setting_notifications_subtitle": "調整通知選項", + "setting_notifications_title": "通知", + "setting_notifications_total_progress_subtitle": "總體上傳進度(已完成/總計)", + "setting_notifications_total_progress_title": "顯示背景備份總進度", + "setting_pages_app_bar_settings": "設定", + "settings_require_restart": "請重啓 Immich 以使設定生效", + "setting_video_viewer_looping_subtitle": "對播放窗口中的短片開啓循環播放。", + "setting_video_viewer_looping_title": "循環播放", + "setting_video_viewer_title": "短片", + "share_add": "新增", + "share_add_photos": "新增項目", + "share_add_title": "新增標題", + "share_assets_selected": " {} 已選擇", + "share_create_album": "新增相簿", + "shared_album_activities_input_disable": "已禁用評論", + "shared_album_activities_input_hint": "評論一下", + "shared_album_activity_remove_content": "您確定要刪除此活動嗎?", + "shared_album_activity_remove_title": "刪除活動", + "shared_album_activity_setting_subtitle": "允許他人回覆", + "shared_album_activity_setting_title": "評論與讚好", + "shared_album_section_people_action_error": "退出/刪除相簿失敗", + "shared_album_section_people_action_leave": "從相簿中刪除用戶", + "shared_album_section_people_action_remove_user": "從相簿中刪除用戶", + "shared_album_section_people_owner_label": "所有者", + "shared_album_section_people_title": "人物", + "share_dialog_preparing": "正在準備...", + "shared_link_app_bar_title": "共享鏈接", + "shared_link_clipboard_copied_massage": "複製到剪貼板", + "shared_link_clipboard_text": "鏈接: {} \n密碼: {} ", + "shared_link_create_app_bar_title": "新增共享鏈接", + "shared_link_create_error": "新增共享鏈接出錯", + "shared_link_create_info": "任何獲得鏈接的人都可看到照片", + "shared_link_create_submit_button": "新增鏈接", + "shared_link_edit_allow_download": "允許遊客下載", + "shared_link_edit_allow_upload": "允許遊客上傳", + "shared_link_edit_app_bar_title": "編輯鏈接", + "shared_link_edit_change_expiry": "修改過期時間", + "shared_link_edit_description": "描述", + "shared_link_edit_description_hint": "編輯共享描述", + "shared_link_edit_expire_after": "有效期", + "shared_link_edit_expire_after_option_day": "1天", + "shared_link_edit_expire_after_option_days": " {} 天", + "shared_link_edit_expire_after_option_hour": "1小時", + "shared_link_edit_expire_after_option_hours": " {} 小時", + "shared_link_edit_expire_after_option_minute": "1分鐘", + "shared_link_edit_expire_after_option_minutes": " {} 分鐘", + "shared_link_edit_expire_after_option_months": " {} 個月", + "shared_link_edit_expire_after_option_never": "永久", + "shared_link_edit_expire_after_option_year": " {} 年", + "shared_link_edit_password": "密碼", + "shared_link_edit_password_hint": "輸入共享密碼", + "shared_link_edit_show_meta": "顯示中繼數據", + "shared_link_edit_submit_button": "更新鏈接", + "shared_link_empty": "您還沒有新增共享鏈接", + "shared_link_error_server_url_fetch": "無法獲取伺服器地址", + "shared_link_expired": "已過期", + "shared_link_expires_day": " {} 天後過期", + "shared_link_expires_days": " {} 天後過期", + "shared_link_expires_hour": " {} 小時後過期", + "shared_link_expires_hours": " {} 小時後過期", + "shared_link_expires_minute": " {} 分鐘後過期", + "shared_link_expires_minutes": "將在 {} 分鐘後過期", + "shared_link_expires_never": "永不過期", + "shared_link_expires_second": " {} 秒後過期", + "shared_link_expires_seconds": "將在 {} 秒後過期", + "shared_link_individual_shared": "個人共享", + "shared_link_info_chip_download": "下載", "shared_link_info_chip_metadata": "EXIF", - "shared_link_info_chip_upload": "Upload", - "shared_link_manage_links": "Manage Shared links", - "shared_link_public_album": "Public album", - "shared_links": "Shared links", - "share_done": "Done", - "shared_with_me": "Shared with me", - "share_invite": "Invite to album", - "sharing_page_album": "Shared albums", - "sharing_page_description": "Create shared albums to share photos and videos with people in your network.", - "sharing_page_empty_list": "EMPTY LIST", - "sharing_silver_appbar_create_shared_album": "New shared album", - "sharing_silver_appbar_shared_links": "Shared links", - "sharing_silver_appbar_share_partner": "Share with partner", - "sync": "Sync", - "sync_albums": "Sync albums", - "sync_albums_manual_subtitle": "Sync all uploaded videos and photos to the selected backup albums", - "sync_upload_album_setting_subtitle": "Create and upload your photos and videos to the selected albums on Immich", - "tab_controller_nav_library": "Library", - "tab_controller_nav_photos": "Photos", - "tab_controller_nav_search": "Search", - "tab_controller_nav_sharing": "Sharing", - "theme_setting_asset_list_storage_indicator_title": "Show storage indicator on asset tiles", - "theme_setting_asset_list_tiles_per_row_title": "Number of assets per row ({})", - "theme_setting_colorful_interface_subtitle": "Apply primary color to background surfaces.", - "theme_setting_colorful_interface_title": "Colorful interface", - "theme_setting_dark_mode_switch": "Dark mode", - "theme_setting_image_viewer_quality_subtitle": "Adjust the quality of the detail image viewer", - "theme_setting_image_viewer_quality_title": "Image viewer quality", - "theme_setting_primary_color_subtitle": "Pick a color for primary actions and accents.", - "theme_setting_primary_color_title": "Primary color", - "theme_setting_system_primary_color_title": "Use system color", - "theme_setting_system_theme_switch": "Automatic (Follow system setting)", - "theme_setting_theme_subtitle": "Choose the app's theme setting", - "theme_setting_theme_title": "Theme", - "theme_setting_three_stage_loading_subtitle": "Three-stage loading might increase the loading performance but causes significantly higher network load", - "theme_setting_three_stage_loading_title": "Enable three-stage loading", - "translated_text_options": "Options", - "trash": "Trash", - "trash_emptied": "Emptied trash", - "trash_page_delete": "Delete", - "trash_page_delete_all": "Delete All", - "trash_page_empty_trash_btn": "Empty trash", - "trash_page_empty_trash_dialog_content": "Do you want to empty your trashed assets? These items will be permanently removed from Immich", - "trash_page_empty_trash_dialog_ok": "Ok", - "trash_page_info": "Trashed items will be permanently deleted after {} days", - "trash_page_no_assets": "No trashed assets", - "trash_page_restore": "Restore", - "trash_page_restore_all": "Restore All", - "trash_page_select_assets_btn": "Select assets", - "trash_page_select_btn": "Select", - "trash_page_title": "Trash ({})", - "upload_dialog_cancel": "Cancel", - "upload_dialog_info": "Do you want to backup the selected Asset(s) to the server?", - "upload_dialog_ok": "Upload", - "upload_dialog_title": "Upload Asset", - "version_announcement_overlay_ack": "Acknowledge", - "version_announcement_overlay_release_notes": "release notes", - "version_announcement_overlay_text_1": "Hi friend, there is a new release of", - "version_announcement_overlay_text_2": "please take your time to visit the ", - "version_announcement_overlay_text_3": " and ensure your docker-compose and .env setup is up-to-date to prevent any misconfigurations, especially if you use WatchTower or any mechanism that handles updating your server application automatically.", - "version_announcement_overlay_title": "New Server Version Available \uD83C\uDF89", - "videos": "Videos", - "viewer_remove_from_stack": "Remove from Stack", - "viewer_stack_use_as_main_asset": "Use as Main Asset", - "viewer_unstack": "Un-Stack" + "shared_link_info_chip_upload": "上載", + "shared_link_manage_links": "管理共享鏈接", + "shared_link_public_album": "公共相簿", + "shared_links": "共享鏈接", + "share_done": "完成", + "shared_with_me": "與我共享", + "share_invite": "邀請到共享相簿", + "sharing_page_album": "共享相簿", + "sharing_page_description": "新增共享相簿以與網絡中的人共享照片和短片。", + "sharing_page_empty_list": "空白清單", + "sharing_silver_appbar_create_shared_album": "新增共享相簿", + "sharing_silver_appbar_shared_links": "共享鏈接", + "sharing_silver_appbar_share_partner": "共享給同伴", + "sync": "同步", + "sync_albums": "同步相簿", + "sync_albums_manual_subtitle": "將所有上傳的短片和照片同步到選定的備份相簿", + "sync_upload_album_setting_subtitle": "新增照片和短片並上傳到 Immich 上的選定相簿中", + "tab_controller_nav_library": "圖庫", + "tab_controller_nav_photos": "照片", + "tab_controller_nav_search": "搜尋", + "tab_controller_nav_sharing": "共享", + "theme_setting_asset_list_storage_indicator_title": "在項目標題上顯示使用之儲存空間", + "theme_setting_asset_list_tiles_per_row_title": "每行展示 {} 項", + "theme_setting_colorful_interface_subtitle": "套用主色調到背景", + "theme_setting_colorful_interface_title": "彩色界面", + "theme_setting_dark_mode_switch": "深色模式", + "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_theme_title": "主題", + "theme_setting_three_stage_loading_subtitle": "三段式載入可能會提升載入性能,但可能會導致更高的網絡負載", + "theme_setting_three_stage_loading_title": "啓用三段式載入", + "translated_text_options": "選項", + "trash": "回收桶", + "trash_emptied": "已清空回收桶\n", + "trash_page_delete": "刪除", + "trash_page_delete_all": "刪除全部", + "trash_page_empty_trash_btn": "清空回收桶", + "trash_page_empty_trash_dialog_content": "是否清空回收桶?這些項目將被從Immich中永久刪除", + "trash_page_empty_trash_dialog_ok": "確定", + "trash_page_info": "回收桶中項目將在 {} 天後永久刪除", + "trash_page_no_assets": "暫無已刪除項目", + "trash_page_restore": "恢復", + "trash_page_restore_all": "恢復全部", + "trash_page_select_assets_btn": "選擇項目", + "trash_page_select_btn": "選擇", + "trash_page_title": "回收桶 ( {} )", + "upload_dialog_cancel": "取消", + "upload_dialog_info": "是否要將所選項目備份到伺服器?", + "upload_dialog_ok": "上傳", + "upload_dialog_title": "上傳項目", + "use_current_connection": "use current connection", + "validate_endpoint_error": "Please enter a valid URL", + "version_announcement_overlay_ack": "我知道了", + "version_announcement_overlay_release_notes": "發行說明", + "version_announcement_overlay_text_1": "好消息,有新版本的", + "version_announcement_overlay_text_2": "請花點時間訪問", + "version_announcement_overlay_text_3": "並檢查您的 docker-compose 和 .env 是否為最新且正確的設定,特別是您在使用 WatchTower 或者其他自動更新的程式時,您需要更加細緻的檢查。", + "version_announcement_overlay_title": "服務端有新版本啦 \uD83C\uDF89", + "videos": "短片", + "viewer_remove_from_stack": "從堆疊中移除", + "viewer_stack_use_as_main_asset": "作為主項目使用", + "viewer_unstack": "取消堆疊", + "wifi_name": "WiFi Name", + "your_wifi_name": "Your WiFi name" } \ No newline at end of file diff --git a/mobile/immich_lint/pubspec.yaml b/mobile/immich_lint/pubspec.yaml index 9d1a3c26b3ca8..5d871b03e6b46 100644 --- a/mobile/immich_lint/pubspec.yaml +++ b/mobile/immich_lint/pubspec.yaml @@ -5,7 +5,7 @@ environment: sdk: '>=3.0.0 <4.0.0' dependencies: - analyzer: ^6.8.0 + analyzer: ^7.0.0 analyzer_plugin: ^0.11.3 custom_lint_builder: ^0.6.4 glob: ^2.1.2 diff --git a/mobile/ios/Podfile b/mobile/ios/Podfile index f38ac9619ba7e..b048c0bb0c87b 100644 --- a/mobile/ios/Podfile +++ b/mobile/ios/Podfile @@ -102,6 +102,13 @@ post_install do |installer| ## dart: PermissionGroup.criticalAlerts # 'PERMISSION_CRITICAL_ALERTS=1' + + ## The 'PERMISSION_LOCATION' macro enables the `locationWhenInUse` and `locationAlways` permission. If + ## the application only requires `locationWhenInUse`, only specify the `PERMISSION_LOCATION_WHENINUSE` + ## macro. + ## + ## dart: [PermissionGroup.location, PermissionGroup.locationAlways, PermissionGroup.locationWhenInUse] + 'PERMISSION_LOCATION=1', ] end diff --git a/mobile/ios/Podfile.lock b/mobile/ios/Podfile.lock index 567406aef0df2..bc65bd4b7f919 100644 --- a/mobile/ios/Podfile.lock +++ b/mobile/ios/Podfile.lock @@ -48,7 +48,7 @@ PODS: - flutter_udid (0.0.1): - Flutter - SAMKeychain - - flutter_web_auth (0.5.0): + - flutter_web_auth (0.6.0): - Flutter - fluttertoast (0.0.2): - Flutter @@ -65,6 +65,10 @@ PODS: - maplibre_gl (0.0.1): - Flutter - MapLibre (= 5.14.0-pre3) + - native_video_player (1.0.0): + - Flutter + - network_info_plus (0.0.1): + - Flutter - package_info_plus (0.4.5): - Flutter - path_provider_foundation (0.0.1): @@ -93,9 +97,6 @@ PODS: - Toast (4.0.0) - url_launcher_ios (0.0.1): - Flutter - - video_player_avfoundation (0.0.1): - - Flutter - - FlutterMacOS - wakelock_plus (0.0.1): - Flutter @@ -115,6 +116,8 @@ DEPENDENCIES: - integration_test (from `.symlinks/plugins/integration_test/ios`) - isar_flutter_libs (from `.symlinks/plugins/isar_flutter_libs/ios`) - maplibre_gl (from `.symlinks/plugins/maplibre_gl/ios`) + - native_video_player (from `.symlinks/plugins/native_video_player/ios`) + - network_info_plus (from `.symlinks/plugins/network_info_plus/ios`) - package_info_plus (from `.symlinks/plugins/package_info_plus/ios`) - path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`) - path_provider_ios (from `.symlinks/plugins/path_provider_ios/ios`) @@ -124,7 +127,6 @@ DEPENDENCIES: - shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`) - sqflite (from `.symlinks/plugins/sqflite/darwin`) - url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`) - - video_player_avfoundation (from `.symlinks/plugins/video_player_avfoundation/darwin`) - wakelock_plus (from `.symlinks/plugins/wakelock_plus/ios`) SPEC REPOS: @@ -168,6 +170,10 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/isar_flutter_libs/ios" maplibre_gl: :path: ".symlinks/plugins/maplibre_gl/ios" + native_video_player: + :path: ".symlinks/plugins/native_video_player/ios" + network_info_plus: + :path: ".symlinks/plugins/network_info_plus/ios" package_info_plus: :path: ".symlinks/plugins/package_info_plus/ios" path_provider_foundation: @@ -186,15 +192,13 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/sqflite/darwin" url_launcher_ios: :path: ".symlinks/plugins/url_launcher_ios/ios" - video_player_avfoundation: - :path: ".symlinks/plugins/video_player_avfoundation/darwin" wakelock_plus: :path: ".symlinks/plugins/wakelock_plus/ios" SPEC CHECKSUMS: background_downloader: 9f788ffc5de45acf87d6380e91ca0841066c18cf connectivity_plus: ddd7f30999e1faaef5967c23d5b6d503d10434db - device_info_plus: 97af1d7e84681a90d0693e63169a5d50e0839a0d + device_info_plus: bf2e3232933866d73fe290f2942f2156cdd10342 DKImagePickerController: 946cec48c7873164274ecc4624d19e3da4c1ef3c DKPhotoGallery: b3834fecb755ee09a593d7c9e389d8b5d6deed60 file_picker: 09aa5ec1ab24135ccd7a1621c46c84134bfd6655 @@ -202,30 +206,31 @@ SPEC CHECKSUMS: flutter_local_notifications: 4cde75091f6327eb8517fa068a0a5950212d2086 flutter_native_splash: edf599c81f74d093a4daf8e17bd7a018854bc778 flutter_udid: a2482c67a61b9c806ef59dd82ed8d007f1b7ac04 - flutter_web_auth: c25208760459cec375a3c39f6a8759165ca0fa4d + flutter_web_auth: acc15a8fd7bba796a933c724a6dffc3d00f07c27 fluttertoast: e9a18c7be5413da53898f660530c56f35edfba9c geolocator_apple: 6cbaf322953988e009e5ecb481f07efece75c450 image_picker_ios: c560581cceedb403a6ff17f2f816d7fea1421fc1 integration_test: 252f60fa39af5e17c3aa9899d35d908a0721b573 - isar_flutter_libs: b69f437aeab9c521821c3f376198c4371fa21073 + isar_flutter_libs: fdf730ca925d05687f36d7f1d355e482529ed097 MapLibre: 620fc933c1d6029b33738c905c1490d024e5d4ef maplibre_gl: a2efec727dd340e4c65e26d2b03b584f14881fd9 - package_info_plus: 58f0028419748fad15bf008b270aaa8e54380b1c + native_video_player: d12af78a1a4a8cf09775a5177d5b392def6fd23c + network_info_plus: 6613d9d7cdeb0e6f366ed4dbe4b3c51c52d567a9 + package_info_plus: c0502532a26c7662a62a356cebe2692ec5fe4ec4 path_provider_foundation: 2b6b4c569c0fb62ec74538f866245ac84301af46 path_provider_ios: 14f3d2fd28c4fdb42f44e0f751d12861c43cee02 permission_handler_apple: 9878588469a2b0d0fc1e048d9f43605f92e6cec2 photo_manager: ff695c7a1dd5bc379974953a2b5c0a293f7c4c8a SAMKeychain: 483e1c9f32984d50ca961e26818a534283b4cd5c SDWebImage: 066c47b573f408f18caa467d71deace7c0f8280d - share_plus: 8875f4f2500512ea181eef553c3e27dba5135aad + share_plus: 8b6f8b3447e494cca5317c8c3073de39b3600d1f shared_preferences_foundation: fcdcbc04712aee1108ac7fda236f363274528f78 sqflite: 673a0e54cc04b7d6dba8d24fb8095b31c3a99eec SwiftyGif: 706c60cf65fa2bc5ee0313beece843c8eb8194d4 Toast: 91b396c56ee72a5790816f40d3a94dd357abc196 url_launcher_ios: 5334b05cef931de560670eeae103fd3e431ac3fe - video_player_avfoundation: 7c6c11d8470e1675df7397027218274b6d2360b3 wakelock_plus: 78ec7c5b202cab7761af8e2b2b3d0671be6c4ae1 -PODFILE CHECKSUM: 64c9b5291666c0ca3caabdfe9865c141ac40321d +PODFILE CHECKSUM: 2282844f7aed70427ae663932332dad1225156c8 COCOAPODS: 1.15.2 diff --git a/mobile/ios/Runner.xcodeproj/project.pbxproj b/mobile/ios/Runner.xcodeproj/project.pbxproj index e1598cb50fab1..4f4297fe536b3 100644 --- a/mobile/ios/Runner.xcodeproj/project.pbxproj +++ b/mobile/ios/Runner.xcodeproj/project.pbxproj @@ -51,6 +51,7 @@ 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; 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 = ""; }; F7101BB0391A314774615E89 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; + FA9973382CF6DF4B000EF859 /* Runner.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Runner.entitlements; sourceTree = ""; }; FAC7416727DB9F5500C668D8 /* RunnerProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = RunnerProfile.entitlements; sourceTree = ""; }; /* End PBXFileReference section */ @@ -126,6 +127,7 @@ 97C146F01CF9000F007C117D /* Runner */ = { isa = PBXGroup; children = ( + FA9973382CF6DF4B000EF859 /* Runner.entitlements */, 65DD438629917FAD0047FFA8 /* BackgroundSync */, FAC7416727DB9F5500C668D8 /* RunnerProfile.entitlements */, 97C146FA1CF9000F007C117D /* Main.storyboard */, @@ -401,7 +403,7 @@ CODE_SIGN_ENTITLEMENTS = Runner/RunnerProfile.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 181; + CURRENT_PROJECT_VERSION = 186; DEVELOPMENT_TEAM = 2F67MQ8R79; ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; @@ -410,7 +412,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.107.0; + MARKETING_VERSION = 1.121.0; PRODUCT_BUNDLE_IDENTIFIER = app.alextran.immich.profile; PRODUCT_NAME = "Immich-Profile"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -541,9 +543,10 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 181; + CURRENT_PROJECT_VERSION = 186; DEVELOPMENT_TEAM = 2F67MQ8R79; ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; @@ -552,8 +555,8 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.107.0; - PRODUCT_BUNDLE_IDENTIFIER = app.alextran.immich.debug; + MARKETING_VERSION = 1.121.0; + PRODUCT_BUNDLE_IDENTIFIER = app.alextran.immich.vdebug; PRODUCT_NAME = "Immich-Debug"; PROVISIONING_PROFILE_SPECIFIER = ""; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; @@ -569,9 +572,10 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 181; + CURRENT_PROJECT_VERSION = 186; DEVELOPMENT_TEAM = 2F67MQ8R79; ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; @@ -580,7 +584,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.107.0; + MARKETING_VERSION = 1.121.0; PRODUCT_BUNDLE_IDENTIFIER = app.alextran.immich; PRODUCT_NAME = Immich; PROVISIONING_PROFILE_SPECIFIER = ""; diff --git a/mobile/ios/Runner/AppDelegate.swift b/mobile/ios/Runner/AppDelegate.swift index 05cb061ca58b2..8f635bc61b932 100644 --- a/mobile/ios/Runner/AppDelegate.swift +++ b/mobile/ios/Runner/AppDelegate.swift @@ -1,48 +1,57 @@ -import UIKit -import shared_preferences_foundation -import Flutter import BackgroundTasks +import Flutter +import network_info_plus import path_provider_ios -import photo_manager import permission_handler_apple +import photo_manager +import shared_preferences_foundation +import UIKit @main @objc class AppDelegate: FlutterAppDelegate { - override func application( _ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? ) -> Bool { + // Required for flutter_local_notification + if #available(iOS 10.0, *) { + UNUserNotificationCenter.current().delegate = self as? UNUserNotificationCenterDelegate + } + + do { + try AVAudioSession.sharedInstance().setCategory(.playback, mode: .default) + try AVAudioSession.sharedInstance().setActive(true) + } catch { + print("Failed to set audio session category. Error: \(error)") + } - // Required for flutter_local_notification - if #available(iOS 10.0, *) { - UNUserNotificationCenter.current().delegate = self as? UNUserNotificationCenterDelegate + GeneratedPluginRegistrant.register(with: self) + BackgroundServicePlugin.registerBackgroundProcessing() + + BackgroundServicePlugin.register(with: self.registrar(forPlugin: "BackgroundServicePlugin")!) + + BackgroundServicePlugin.setPluginRegistrantCallback { registry in + if !registry.hasPlugin("org.cocoapods.path-provider-ios") { + FLTPathProviderPlugin.register(with: registry.registrar(forPlugin: "org.cocoapods.path-provider-ios")!) } - GeneratedPluginRegistrant.register(with: self) - BackgroundServicePlugin.registerBackgroundProcessing() - - BackgroundServicePlugin.register(with: self.registrar(forPlugin: "BackgroundServicePlugin")!) - - BackgroundServicePlugin.setPluginRegistrantCallback { registry in - if !registry.hasPlugin("org.cocoapods.path-provider-ios") { - FLTPathProviderPlugin.register(with: registry.registrar(forPlugin: "org.cocoapods.path-provider-ios")!) - } - - if !registry.hasPlugin("org.cocoapods.photo-manager") { - PhotoManagerPlugin.register(with: registry.registrar(forPlugin: "org.cocoapods.photo-manager")!) - } - - if !registry.hasPlugin("org.cocoapods.shared-preferences-foundation") { - SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "org.cocoapods.shared-preferences-foundation")!) - } - - if !registry.hasPlugin("org.cocoapods.permission-handler-apple") { - PermissionHandlerPlugin.register(with: registry.registrar(forPlugin: "org.cocoapods.permission-handler-apple")!) - } + if !registry.hasPlugin("org.cocoapods.photo-manager") { + PhotoManagerPlugin.register(with: registry.registrar(forPlugin: "org.cocoapods.photo-manager")!) } - - return super.application(application, didFinishLaunchingWithOptions: launchOptions) + + if !registry.hasPlugin("org.cocoapods.shared-preferences-foundation") { + SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "org.cocoapods.shared-preferences-foundation")!) + } + + if !registry.hasPlugin("org.cocoapods.permission-handler-apple") { + PermissionHandlerPlugin.register(with: registry.registrar(forPlugin: "org.cocoapods.permission-handler-apple")!) + } + + if !registry.hasPlugin("org.cocoapods.network-info-plus") { + FPPNetworkInfoPlusPlugin.register(with: registry.registrar(forPlugin: "org.cocoapods.network-info-plus")!) + } + } + + return super.application(application, didFinishLaunchingWithOptions: launchOptions) } - } diff --git a/mobile/ios/Runner/BackgroundSync/BackgroundSyncWorker.swift b/mobile/ios/Runner/BackgroundSync/BackgroundSyncWorker.swift index e391f5187e06d..88d93683086b0 100644 --- a/mobile/ios/Runner/BackgroundSync/BackgroundSyncWorker.swift +++ b/mobile/ios/Runner/BackgroundSync/BackgroundSyncWorker.swift @@ -86,7 +86,7 @@ class BackgroundSyncWorker { result(false) break default: - result(FlutterError()) + result(FlutterError()) self.complete(UIBackgroundFetchResult.failed) } } diff --git a/mobile/ios/Runner/Info.plist b/mobile/ios/Runner/Info.plist index 59a83c7e2e0b9..ea7cbfc1a0603 100644 --- a/mobile/ios/Runner/Info.plist +++ b/mobile/ios/Runner/Info.plist @@ -58,11 +58,11 @@ CFBundlePackageType APPL CFBundleShortVersionString - 1.119.0 + 1.123.0 CFBundleSignature ???? CFBundleVersion - 181 + 186 FLTEnableImpeller ITSAppUsesNonExemptEncryption @@ -82,8 +82,12 @@ NSCameraUsageDescription We need to access the camera to let you take beautiful video using this app + NSLocationAlwaysAndWhenInUseUsageDescription + We require this permission to access the local WiFi name for background upload mechanism + NSLocationUsageDescription + We require this permission to access the local WiFi name NSLocationWhenInUseUsageDescription - Enable location setting to show position of assets on map + We require this permission to access the local WiFi name NSMicrophoneUsageDescription We need to access the microphone to let you take beautiful video using this app NSPhotoLibraryAddUsageDescription diff --git a/mobile/ios/Runner/Runner.entitlements b/mobile/ios/Runner/Runner.entitlements index 0c67376ebacb4..ba21fbdaf2902 100644 --- a/mobile/ios/Runner/Runner.entitlements +++ b/mobile/ios/Runner/Runner.entitlements @@ -1,5 +1,8 @@ - + + com.apple.developer.networking.wifi-info + + diff --git a/mobile/ios/Runner/RunnerProfile.entitlements b/mobile/ios/Runner/RunnerProfile.entitlements index 903def2af5306..75e36a143e4f0 100644 --- a/mobile/ios/Runner/RunnerProfile.entitlements +++ b/mobile/ios/Runner/RunnerProfile.entitlements @@ -4,5 +4,7 @@ aps-environment development + com.apple.developer.networking.wifi-info + diff --git a/mobile/ios/fastlane/Fastfile b/mobile/ios/fastlane/Fastfile index 77dc24e006069..b22a9830154cf 100644 --- a/mobile/ios/fastlane/Fastfile +++ b/mobile/ios/fastlane/Fastfile @@ -19,7 +19,7 @@ platform :ios do desc "iOS Release" lane :release do increment_version_number( - version_number: "1.119.1" + version_number: "1.123.0" ) increment_build_number( build_number: latest_testflight_build_number + 1, diff --git a/mobile/lib/constants/colors.dart b/mobile/lib/constants/colors.dart new file mode 100644 index 0000000000000..ade878d6f6378 --- /dev/null +++ b/mobile/lib/constants/colors.dart @@ -0,0 +1,23 @@ +import 'package:flutter/material.dart'; + +enum ImmichColorPreset { + indigo, + deepPurple, + pink, + red, + orange, + yellow, + lime, + green, + cyan, + slateGray +} + +const ImmichColorPreset defaultColorPreset = ImmichColorPreset.indigo; +const String defaultColorPresetName = "indigo"; + +const Color immichBrandColorLight = Color(0xFF4150AF); +const Color immichBrandColorDark = Color(0xFFACCBFA); +const Color whiteOpacity75 = Color.fromARGB((0.75 * 255) ~/ 1, 255, 255, 255); +const Color red400 = Color(0xFFEF5350); +const Color grey200 = Color(0xFFEEEEEE); diff --git a/mobile/lib/constants/enums.dart b/mobile/lib/constants/enums.dart new file mode 100644 index 0000000000000..a9b5107426bc3 --- /dev/null +++ b/mobile/lib/constants/enums.dart @@ -0,0 +1,4 @@ +enum SortOrder { + asc, + desc, +} diff --git a/mobile/lib/constants/locales.dart b/mobile/lib/constants/locales.dart index d92ae7660e8bd..5c928c124e917 100644 --- a/mobile/lib/constants/locales.dart +++ b/mobile/lib/constants/locales.dart @@ -48,3 +48,8 @@ const Map locales = { }; const String translationsPath = 'assets/i18n'; + +const List localesNotSupportedByOverpass = [ + Locale('el', 'GR'), + Locale('sr', 'Cyrl'), +]; diff --git a/mobile/lib/entities/album.entity.dart b/mobile/lib/entities/album.entity.dart index 6331c4b9f06d0..8caff2255f073 100644 --- a/mobile/lib/entities/album.entity.dart +++ b/mobile/lib/entities/album.entity.dart @@ -1,4 +1,5 @@ import 'package:flutter/foundation.dart'; +import 'package:immich_mobile/constants/enums.dart'; import 'package:immich_mobile/entities/asset.entity.dart'; import 'package:immich_mobile/entities/user.entity.dart'; import 'package:immich_mobile/utils/datetime_comparison.dart'; @@ -23,6 +24,7 @@ class Album { this.lastModifiedAssetTimestamp, required this.shared, required this.activityEnabled, + this.sortOrder = SortOrder.desc, }); // fields stored in DB @@ -39,6 +41,8 @@ class Album { DateTime? lastModifiedAssetTimestamp; bool shared; bool activityEnabled; + @enumerated + SortOrder sortOrder; final IsarLink owner = IsarLink(); final IsarLink thumbnail = IsarLink(); final IsarLinks sharedUsers = IsarLinks(); @@ -154,6 +158,11 @@ class Album { ); a.remoteAssetCount = dto.assetCount; a.owner.value = await db.users.getById(dto.ownerId); + if (dto.order != null) { + a.sortOrder = + dto.order == AssetOrder.asc ? SortOrder.asc : SortOrder.desc; + } + if (dto.albumThumbnailAssetId != null) { a.thumbnail.value = await db.assets .where() diff --git a/mobile/lib/entities/album.entity.g.dart b/mobile/lib/entities/album.entity.g.dart index 11046ec1e0d67..327dc606caba2 100644 --- a/mobile/lib/entities/album.entity.g.dart +++ b/mobile/lib/entities/album.entity.g.dart @@ -62,8 +62,14 @@ const AlbumSchema = CollectionSchema( name: r'shared', type: IsarType.bool, ), - r'startDate': PropertySchema( + r'sortOrder': PropertySchema( id: 9, + name: r'sortOrder', + type: IsarType.byte, + enumMap: _AlbumsortOrderEnumValueMap, + ), + r'startDate': PropertySchema( + id: 10, name: r'startDate', type: IsarType.dateTime, ) @@ -131,7 +137,7 @@ const AlbumSchema = CollectionSchema( getId: _albumGetId, getLinks: _albumGetLinks, attach: _albumAttach, - version: '3.1.0+1', + version: '3.1.8', ); int _albumEstimateSize( @@ -171,7 +177,8 @@ void _albumSerialize( writer.writeString(offsets[6], object.name); writer.writeString(offsets[7], object.remoteId); writer.writeBool(offsets[8], object.shared); - writer.writeDateTime(offsets[9], object.startDate); + writer.writeByte(offsets[9], object.sortOrder.index); + writer.writeDateTime(offsets[10], object.startDate); } Album _albumDeserialize( @@ -190,7 +197,9 @@ Album _albumDeserialize( name: reader.readString(offsets[6]), remoteId: reader.readStringOrNull(offsets[7]), shared: reader.readBool(offsets[8]), - startDate: reader.readDateTimeOrNull(offsets[9]), + sortOrder: _AlbumsortOrderValueEnumMap[reader.readByteOrNull(offsets[9])] ?? + SortOrder.desc, + startDate: reader.readDateTimeOrNull(offsets[10]), ); object.id = id; return object; @@ -222,12 +231,24 @@ P _albumDeserializeProp

( case 8: return (reader.readBool(offset)) as P; case 9: + return (_AlbumsortOrderValueEnumMap[reader.readByteOrNull(offset)] ?? + SortOrder.desc) as P; + case 10: return (reader.readDateTimeOrNull(offset)) as P; default: throw IsarError('Unknown property with id $propertyId'); } } +const _AlbumsortOrderEnumValueMap = { + 'asc': 0, + 'desc': 1, +}; +const _AlbumsortOrderValueEnumMap = { + 0: SortOrder.asc, + 1: SortOrder.desc, +}; + Id _albumGetId(Album object) { return object.id; } @@ -1191,6 +1212,59 @@ extension AlbumQueryFilter on QueryBuilder { }); } + QueryBuilder sortOrderEqualTo( + SortOrder value) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'sortOrder', + value: value, + )); + }); + } + + QueryBuilder sortOrderGreaterThan( + SortOrder value, { + bool include = false, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + include: include, + property: r'sortOrder', + value: value, + )); + }); + } + + QueryBuilder sortOrderLessThan( + SortOrder value, { + bool include = false, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.lessThan( + include: include, + property: r'sortOrder', + value: value, + )); + }); + } + + QueryBuilder sortOrderBetween( + SortOrder lower, + SortOrder upper, { + bool includeLower = true, + bool includeUpper = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.between( + property: r'sortOrder', + lower: lower, + includeLower: includeLower, + upper: upper, + includeUpper: includeUpper, + )); + }); + } + QueryBuilder startDateIsNull() { return QueryBuilder.apply(this, (query) { return query.addFilterCondition(const FilterCondition.isNull( @@ -1513,6 +1587,18 @@ extension AlbumQuerySortBy on QueryBuilder { }); } + QueryBuilder sortBySortOrder() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'sortOrder', Sort.asc); + }); + } + + QueryBuilder sortBySortOrderDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'sortOrder', Sort.desc); + }); + } + QueryBuilder sortByStartDate() { return QueryBuilder.apply(this, (query) { return query.addSortBy(r'startDate', Sort.asc); @@ -1648,6 +1734,18 @@ extension AlbumQuerySortThenBy on QueryBuilder { }); } + QueryBuilder thenBySortOrder() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'sortOrder', Sort.asc); + }); + } + + QueryBuilder thenBySortOrderDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'sortOrder', Sort.desc); + }); + } + QueryBuilder thenByStartDate() { return QueryBuilder.apply(this, (query) { return query.addSortBy(r'startDate', Sort.asc); @@ -1719,6 +1817,12 @@ extension AlbumQueryWhereDistinct on QueryBuilder { }); } + QueryBuilder distinctBySortOrder() { + return QueryBuilder.apply(this, (query) { + return query.addDistinctBy(r'sortOrder'); + }); + } + QueryBuilder distinctByStartDate() { return QueryBuilder.apply(this, (query) { return query.addDistinctBy(r'startDate'); @@ -1788,6 +1892,12 @@ extension AlbumQueryProperty on QueryBuilder { }); } + QueryBuilder sortOrderProperty() { + return QueryBuilder.apply(this, (query) { + return query.addPropertyName(r'sortOrder'); + }); + } + QueryBuilder startDateProperty() { return QueryBuilder.apply(this, (query) { return query.addPropertyName(r'startDate'); diff --git a/mobile/lib/entities/android_device_asset.entity.g.dart b/mobile/lib/entities/android_device_asset.entity.g.dart index 9b1eef0ae59d7..eaa7658565f1c 100644 --- a/mobile/lib/entities/android_device_asset.entity.g.dart +++ b/mobile/lib/entities/android_device_asset.entity.g.dart @@ -49,7 +49,7 @@ const AndroidDeviceAssetSchema = CollectionSchema( getId: _androidDeviceAssetGetId, getLinks: _androidDeviceAssetGetLinks, attach: _androidDeviceAssetAttach, - version: '3.1.0+1', + version: '3.1.8', ); int _androidDeviceAssetEstimateSize( diff --git a/mobile/lib/entities/asset.entity.dart b/mobile/lib/entities/asset.entity.dart index 182c10307fdef..4bec35970a44f 100644 --- a/mobile/lib/entities/asset.entity.dart +++ b/mobile/lib/entities/asset.entity.dart @@ -1,4 +1,5 @@ import 'dart:convert'; +import 'dart:io'; import 'package:immich_mobile/entities/exif_info.entity.dart'; import 'package:immich_mobile/utils/hash.dart'; @@ -22,12 +23,8 @@ class Asset { durationInSeconds = remote.duration.toDuration()?.inSeconds ?? 0, type = remote.type.toAssetType(), fileName = remote.originalFileName, - height = isFlipped(remote) - ? remote.exifInfo?.exifImageWidth?.toInt() - : remote.exifInfo?.exifImageHeight?.toInt(), - width = isFlipped(remote) - ? remote.exifInfo?.exifImageHeight?.toInt() - : remote.exifInfo?.exifImageWidth?.toInt(), + height = remote.exifInfo?.exifImageHeight?.toInt(), + width = remote.exifInfo?.exifImageWidth?.toInt(), livePhotoVideoId = remote.livePhotoVideoId, ownerId = fastHash(remote.ownerId), exifInfo = @@ -93,6 +90,27 @@ class Asset { set local(AssetEntity? assetEntity) => _local = assetEntity; + @ignore + bool _didUpdateLocal = false; + + @ignore + Future get localAsync async { + final local = this.local; + if (local == null) { + throw Exception('Asset $fileName has no local data'); + } + + final updatedLocal = + _didUpdateLocal ? local : await local.obtainForNewProperties(); + if (updatedLocal == null) { + throw Exception('Could not fetch local data for $fileName'); + } + + this.local = updatedLocal; + _didUpdateLocal = true; + return updatedLocal; + } + Id id = Isar.autoIncrement; /// stores the raw SHA1 bytes as a base64 String @@ -150,10 +168,21 @@ class Asset { int stackCount; - /// Aspect ratio of the asset + /// Returns null if the asset has no sync access to the exif info @ignore - double? get aspectRatio => - width == null || height == null ? 0 : width! / height!; + double? get aspectRatio { + final orientatedWidth = this.orientatedWidth; + final orientatedHeight = this.orientatedHeight; + + if (orientatedWidth != null && + orientatedHeight != null && + orientatedWidth > 0 && + orientatedHeight > 0) { + return orientatedWidth.toDouble() / orientatedHeight.toDouble(); + } + + return null; + } /// `true` if this [Asset] is present on the device @ignore @@ -172,6 +201,12 @@ class Asset { @ignore bool get isImage => type == AssetType.image; + @ignore + bool get isVideo => type == AssetType.video; + + @ignore + bool get isMotionPhoto => livePhotoVideoId != null; + @ignore AssetState get storage { if (isRemote && isLocal) { @@ -192,6 +227,50 @@ class Asset { @ignore set byteHash(List hash) => checksum = base64.encode(hash); + /// Returns null if the asset has no sync access to the exif info + @ignore + @pragma('vm:prefer-inline') + bool? get isFlipped { + final exifInfo = this.exifInfo; + if (exifInfo != null) { + return exifInfo.isFlipped; + } + + if (_didUpdateLocal && Platform.isAndroid) { + final local = this.local; + if (local == null) { + throw Exception('Asset $fileName has no local data'); + } + return local.orientation == 90 || local.orientation == 270; + } + + return null; + } + + /// Returns null if the asset has no sync access to the exif info + @ignore + @pragma('vm:prefer-inline') + int? get orientatedHeight { + final isFlipped = this.isFlipped; + if (isFlipped == null) { + return null; + } + + return isFlipped ? width : height; + } + + /// Returns null if the asset has no sync access to the exif info + @ignore + @pragma('vm:prefer-inline') + int? get orientatedWidth { + final isFlipped = this.isFlipped; + if (isFlipped == null) { + return null; + } + + return isFlipped ? height : width; + } + @override bool operator ==(other) { if (other is! Asset) return false; @@ -511,21 +590,3 @@ extension AssetsHelper on IsarCollection { return where().anyOf(ids, (q, String e) => q.localIdEqualTo(e)); } } - -/// Returns `true` if this [int] is flipped 90° clockwise -bool isRotated90CW(int orientation) { - return [7, 8, -90].contains(orientation); -} - -/// Returns `true` if this [int] is flipped 270° clockwise -bool isRotated270CW(int orientation) { - return [5, 6, 90].contains(orientation); -} - -/// Returns `true` if this [Asset] is flipped 90° or 270° clockwise -bool isFlipped(AssetResponseDto response) { - final int orientation = - int.tryParse(response.exifInfo?.orientation ?? '0') ?? 0; - return orientation != 0 && - (isRotated90CW(orientation) || isRotated270CW(orientation)); -} diff --git a/mobile/lib/entities/asset.entity.g.dart b/mobile/lib/entities/asset.entity.g.dart index 23bf23604635d..07eee4825e0bd 100644 --- a/mobile/lib/entities/asset.entity.g.dart +++ b/mobile/lib/entities/asset.entity.g.dart @@ -180,7 +180,7 @@ const AssetSchema = CollectionSchema( getId: _assetGetId, getLinks: _assetGetLinks, attach: _assetAttach, - version: '3.1.0+1', + version: '3.1.8', ); int _assetEstimateSize( diff --git a/mobile/lib/entities/backup_album.entity.g.dart b/mobile/lib/entities/backup_album.entity.g.dart index 7fb6c0e03b6b2..23d00e43cadbe 100644 --- a/mobile/lib/entities/backup_album.entity.g.dart +++ b/mobile/lib/entities/backup_album.entity.g.dart @@ -45,7 +45,7 @@ const BackupAlbumSchema = CollectionSchema( getId: _backupAlbumGetId, getLinks: _backupAlbumGetLinks, attach: _backupAlbumAttach, - version: '3.1.0+1', + version: '3.1.8', ); int _backupAlbumEstimateSize( diff --git a/mobile/lib/entities/duplicated_asset.entity.g.dart b/mobile/lib/entities/duplicated_asset.entity.g.dart index 28faa05b6d0f9..8965d47c97e33 100644 --- a/mobile/lib/entities/duplicated_asset.entity.g.dart +++ b/mobile/lib/entities/duplicated_asset.entity.g.dart @@ -34,7 +34,7 @@ const DuplicatedAssetSchema = CollectionSchema( getId: _duplicatedAssetGetId, getLinks: _duplicatedAssetGetLinks, attach: _duplicatedAssetAttach, - version: '3.1.0+1', + version: '3.1.8', ); int _duplicatedAssetEstimateSize( diff --git a/mobile/lib/entities/etag.entity.g.dart b/mobile/lib/entities/etag.entity.g.dart index 5327f6041afca..afabca4aeaa4e 100644 --- a/mobile/lib/entities/etag.entity.g.dart +++ b/mobile/lib/entities/etag.entity.g.dart @@ -58,7 +58,7 @@ const ETagSchema = CollectionSchema( getId: _eTagGetId, getLinks: _eTagGetLinks, attach: _eTagAttach, - version: '3.1.0+1', + version: '3.1.8', ); int _eTagEstimateSize( diff --git a/mobile/lib/entities/exif_info.entity.dart b/mobile/lib/entities/exif_info.entity.dart index 63d06f5d2c1aa..c46f3dddc15e0 100644 --- a/mobile/lib/entities/exif_info.entity.dart +++ b/mobile/lib/entities/exif_info.entity.dart @@ -23,6 +23,7 @@ class ExifInfo { String? state; String? country; String? description; + String? orientation; @ignore bool get hasCoordinates => @@ -45,6 +46,13 @@ class ExifInfo { @ignore String get focalLength => mm != null ? mm!.toStringAsFixed(1) : ""; + @ignore + bool? _isFlipped; + + @ignore + @pragma('vm:prefer-inline') + bool get isFlipped => _isFlipped ??= _isOrientationFlipped(orientation); + @ignore double? get latitude => lat; @@ -67,7 +75,8 @@ class ExifInfo { city = dto.city, state = dto.state, country = dto.country, - description = dto.description; + description = dto.description, + orientation = dto.orientation; ExifInfo({ this.id, @@ -87,6 +96,7 @@ class ExifInfo { this.state, this.country, this.description, + this.orientation, }); ExifInfo copyWith({ @@ -107,6 +117,7 @@ class ExifInfo { String? state, String? country, String? description, + String? orientation, }) => ExifInfo( id: id ?? this.id, @@ -126,6 +137,7 @@ class ExifInfo { state: state ?? this.state, country: country ?? this.country, description: description ?? this.description, + orientation: orientation ?? this.orientation, ); @override @@ -147,7 +159,8 @@ class ExifInfo { city == other.city && state == other.state && country == other.country && - description == other.description; + description == other.description && + orientation == other.orientation; } @override @@ -169,7 +182,8 @@ class ExifInfo { city.hashCode ^ state.hashCode ^ country.hashCode ^ - description.hashCode; + description.hashCode ^ + orientation.hashCode; @override String toString() { @@ -192,10 +206,21 @@ class ExifInfo { state: $state, country: $country, description: $description, + orientation: $orientation }"""; } } +bool _isOrientationFlipped(String? orientation) { + final value = orientation != null ? int.tryParse(orientation) : null; + if (value == null) { + return false; + } + final isRotated90CW = value == 5 || value == 6 || value == 90; + final isRotated270CW = value == 7 || value == 8 || value == -90; + return isRotated90CW || isRotated270CW; +} + double? _exposureTimeToSeconds(String? s) { if (s == null) { return null; diff --git a/mobile/lib/entities/exif_info.entity.g.dart b/mobile/lib/entities/exif_info.entity.g.dart index 016f6d71260d0..0b744e5f20ae6 100644 --- a/mobile/lib/entities/exif_info.entity.g.dart +++ b/mobile/lib/entities/exif_info.entity.g.dart @@ -87,13 +87,18 @@ const ExifInfoSchema = CollectionSchema( name: r'model', type: IsarType.string, ), - r'state': PropertySchema( + r'orientation': PropertySchema( id: 14, + name: r'orientation', + type: IsarType.string, + ), + r'state': PropertySchema( + id: 15, name: r'state', type: IsarType.string, ), r'timeZone': PropertySchema( - id: 15, + id: 16, name: r'timeZone', type: IsarType.string, ) @@ -109,7 +114,7 @@ const ExifInfoSchema = CollectionSchema( getId: _exifInfoGetId, getLinks: _exifInfoGetLinks, attach: _exifInfoAttach, - version: '3.1.0+1', + version: '3.1.8', ); int _exifInfoEstimateSize( @@ -154,6 +159,12 @@ int _exifInfoEstimateSize( bytesCount += 3 + value.length * 3; } } + { + final value = object.orientation; + if (value != null) { + bytesCount += 3 + value.length * 3; + } + } { final value = object.state; if (value != null) { @@ -189,8 +200,9 @@ void _exifInfoSerialize( writer.writeString(offsets[11], object.make); writer.writeFloat(offsets[12], object.mm); writer.writeString(offsets[13], object.model); - writer.writeString(offsets[14], object.state); - writer.writeString(offsets[15], object.timeZone); + writer.writeString(offsets[14], object.orientation); + writer.writeString(offsets[15], object.state); + writer.writeString(offsets[16], object.timeZone); } ExifInfo _exifInfoDeserialize( @@ -215,8 +227,9 @@ ExifInfo _exifInfoDeserialize( make: reader.readStringOrNull(offsets[11]), mm: reader.readFloatOrNull(offsets[12]), model: reader.readStringOrNull(offsets[13]), - state: reader.readStringOrNull(offsets[14]), - timeZone: reader.readStringOrNull(offsets[15]), + orientation: reader.readStringOrNull(offsets[14]), + state: reader.readStringOrNull(offsets[15]), + timeZone: reader.readStringOrNull(offsets[16]), ); return object; } @@ -260,6 +273,8 @@ P _exifInfoDeserializeProp

( return (reader.readStringOrNull(offset)) as P; case 15: return (reader.readStringOrNull(offset)) as P; + case 16: + return (reader.readStringOrNull(offset)) as P; default: throw IsarError('Unknown property with id $propertyId'); } @@ -1909,6 +1924,155 @@ extension ExifInfoQueryFilter }); } + QueryBuilder orientationIsNull() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(const FilterCondition.isNull( + property: r'orientation', + )); + }); + } + + QueryBuilder + orientationIsNotNull() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(const FilterCondition.isNotNull( + property: r'orientation', + )); + }); + } + + QueryBuilder orientationEqualTo( + String? value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'orientation', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + orientationGreaterThan( + String? value, { + bool include = false, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + include: include, + property: r'orientation', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder orientationLessThan( + String? value, { + bool include = false, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.lessThan( + include: include, + property: r'orientation', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder orientationBetween( + String? lower, + String? upper, { + bool includeLower = true, + bool includeUpper = true, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.between( + property: r'orientation', + lower: lower, + includeLower: includeLower, + upper: upper, + includeUpper: includeUpper, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder orientationStartsWith( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.startsWith( + property: r'orientation', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder orientationEndsWith( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.endsWith( + property: r'orientation', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder orientationContains( + String value, + {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.contains( + property: r'orientation', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder orientationMatches( + String pattern, + {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.matches( + property: r'orientation', + wildcard: pattern, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder orientationIsEmpty() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'orientation', + value: '', + )); + }); + } + + QueryBuilder + orientationIsNotEmpty() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + property: r'orientation', + value: '', + )); + }); + } + QueryBuilder stateIsNull() { return QueryBuilder.apply(this, (query) { return query.addFilterCondition(const FilterCondition.isNull( @@ -2377,6 +2541,18 @@ extension ExifInfoQuerySortBy on QueryBuilder { }); } + QueryBuilder sortByOrientation() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'orientation', Sort.asc); + }); + } + + QueryBuilder sortByOrientationDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'orientation', Sort.desc); + }); + } + QueryBuilder sortByState() { return QueryBuilder.apply(this, (query) { return query.addSortBy(r'state', Sort.asc); @@ -2584,6 +2760,18 @@ extension ExifInfoQuerySortThenBy }); } + QueryBuilder thenByOrientation() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'orientation', Sort.asc); + }); + } + + QueryBuilder thenByOrientationDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'orientation', Sort.desc); + }); + } + QueryBuilder thenByState() { return QueryBuilder.apply(this, (query) { return query.addSortBy(r'state', Sort.asc); @@ -2701,6 +2889,13 @@ extension ExifInfoQueryWhereDistinct }); } + QueryBuilder distinctByOrientation( + {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addDistinctBy(r'orientation', caseSensitive: caseSensitive); + }); + } + QueryBuilder distinctByState( {bool caseSensitive = true}) { return QueryBuilder.apply(this, (query) { @@ -2809,6 +3004,12 @@ extension ExifInfoQueryProperty }); } + QueryBuilder orientationProperty() { + return QueryBuilder.apply(this, (query) { + return query.addPropertyName(r'orientation'); + }); + } + QueryBuilder stateProperty() { return QueryBuilder.apply(this, (query) { return query.addPropertyName(r'state'); diff --git a/mobile/lib/entities/ios_device_asset.entity.g.dart b/mobile/lib/entities/ios_device_asset.entity.g.dart index 6ecf9f0b73098..ffed338c916fb 100644 --- a/mobile/lib/entities/ios_device_asset.entity.g.dart +++ b/mobile/lib/entities/ios_device_asset.entity.g.dart @@ -66,7 +66,7 @@ const IOSDeviceAssetSchema = CollectionSchema( getId: _iOSDeviceAssetGetId, getLinks: _iOSDeviceAssetGetLinks, attach: _iOSDeviceAssetAttach, - version: '3.1.0+1', + version: '3.1.8', ); int _iOSDeviceAssetEstimateSize( diff --git a/mobile/lib/entities/logger_message.entity.g.dart b/mobile/lib/entities/logger_message.entity.g.dart index 50c7fcf8ed281..e292e7173a48d 100644 --- a/mobile/lib/entities/logger_message.entity.g.dart +++ b/mobile/lib/entities/logger_message.entity.g.dart @@ -60,7 +60,7 @@ const LoggerMessageSchema = CollectionSchema( getId: _loggerMessageGetId, getLinks: _loggerMessageGetLinks, attach: _loggerMessageAttach, - version: '3.1.0+1', + version: '3.1.8', ); int _loggerMessageEstimateSize( diff --git a/mobile/lib/entities/store.entity.dart b/mobile/lib/entities/store.entity.dart index 1dda2b9a12a03..316859b064d1e 100644 --- a/mobile/lib/entities/store.entity.dart +++ b/mobile/lib/entities/store.entity.dart @@ -236,6 +236,12 @@ enum StoreKey { colorfulInterface(130, type: bool), syncAlbums(131, type: bool), + + // Auto endpoint switching + autoEndpointSwitching(132, type: bool), + preferredWifiName(133, type: String), + localEndpoint(134, type: String), + externalEndpointList(135, type: String), ; const StoreKey( diff --git a/mobile/lib/entities/store.entity.g.dart b/mobile/lib/entities/store.entity.g.dart index eb8fa62f4078d..7d3210ff85a7a 100644 --- a/mobile/lib/entities/store.entity.g.dart +++ b/mobile/lib/entities/store.entity.g.dart @@ -39,7 +39,7 @@ const StoreValueSchema = CollectionSchema( getId: _storeValueGetId, getLinks: _storeValueGetLinks, attach: _storeValueAttach, - version: '3.1.0+1', + version: '3.1.8', ); int _storeValueEstimateSize( diff --git a/mobile/lib/entities/user.entity.g.dart b/mobile/lib/entities/user.entity.g.dart index a0ecc4705c738..a7aaee44bf164 100644 --- a/mobile/lib/entities/user.entity.g.dart +++ b/mobile/lib/entities/user.entity.g.dart @@ -129,7 +129,7 @@ const UserSchema = CollectionSchema( getId: _userGetId, getLinks: _userGetLinks, attach: _userAttach, - version: '3.1.0+1', + version: '3.1.8', ); int _userEstimateSize( diff --git a/mobile/lib/extensions/build_context_extensions.dart b/mobile/lib/extensions/build_context_extensions.dart index 141a1ede15095..69a9c3b34706f 100644 --- a/mobile/lib/extensions/build_context_extensions.dart +++ b/mobile/lib/extensions/build_context_extensions.dart @@ -4,6 +4,9 @@ extension ContextHelper on BuildContext { // Returns the current padding from MediaQuery EdgeInsets get padding => MediaQuery.paddingOf(this); + // Returns the current view insets from MediaQuery + EdgeInsets get viewInsets => MediaQuery.viewInsetsOf(this); + // Returns the current width from MediaQuery double get width => MediaQuery.sizeOf(this).width; @@ -13,6 +16,15 @@ extension ContextHelper on BuildContext { // Returns true if the app is running on a mobile device (!tablets) bool get isMobile => width < 550; + // Returns the current device pixel ratio from MediaQuery + double get devicePixelRatio => MediaQuery.devicePixelRatioOf(this); + + // Returns the current orientation from MediaQuery + Orientation get orientation => MediaQuery.orientationOf(this); + + // Returns the current platform brightness from MediaQuery + Brightness get platformBrightness => MediaQuery.platformBrightnessOf(this); + // Returns the current ThemeData ThemeData get themeData => Theme.of(this); @@ -31,6 +43,19 @@ extension ContextHelper on BuildContext { // Current ColorScheme used ColorScheme get colorScheme => themeData.colorScheme; + // Navigate by pushing or popping routes from the current context + NavigatorState get navigator => Navigator.of(this); + + // Showing material banners from the current context + ScaffoldMessengerState get scaffoldMessenger => ScaffoldMessenger.of(this); + // Pop-out from the current context with optional result void pop([T? result]) => Navigator.of(this).pop(result); + + // Managing focus within the widget tree from the current context + FocusScopeNode get focusScope => FocusScope.of(this); + + // Show SnackBars from the current context + void showSnackBar(SnackBar snackBar) => + ScaffoldMessenger.of(this).showSnackBar(snackBar); } diff --git a/mobile/lib/extensions/scroll_extensions.dart b/mobile/lib/extensions/scroll_extensions.dart new file mode 100644 index 0000000000000..5bbd73163a6b8 --- /dev/null +++ b/mobile/lib/extensions/scroll_extensions.dart @@ -0,0 +1,38 @@ +import 'package:flutter/cupertino.dart'; + +// https://stackoverflow.com/a/74453792 +class FastScrollPhysics extends ScrollPhysics { + const FastScrollPhysics({super.parent}); + + @override + FastScrollPhysics applyTo(ScrollPhysics? ancestor) { + return FastScrollPhysics(parent: buildParent(ancestor)); + } + + @override + SpringDescription get spring => const SpringDescription( + mass: 40, + stiffness: 100, + damping: 1, + ); +} + +class FastClampingScrollPhysics extends ClampingScrollPhysics { + const FastClampingScrollPhysics({super.parent}); + + @override + FastClampingScrollPhysics applyTo(ScrollPhysics? ancestor) { + return FastClampingScrollPhysics(parent: buildParent(ancestor)); + } + + @override + SpringDescription get spring => const SpringDescription( + // When swiping between videos on Android, the placeholder of the first opened video + // can briefly be seen and cause a flicker effect if the video begins to initialize + // before the animation finishes - probably a bug in PhotoViewGallery's animation handling + // Making the animation faster is not just stylistic, but also helps to avoid this flicker + mass: 80, + stiffness: 100, + damping: 1, + ); +} diff --git a/mobile/lib/interfaces/album_api.interface.dart b/mobile/lib/interfaces/album_api.interface.dart index 33b589841fdc3..b751ccc170793 100644 --- a/mobile/lib/interfaces/album_api.interface.dart +++ b/mobile/lib/interfaces/album_api.interface.dart @@ -1,3 +1,4 @@ +import 'package:immich_mobile/constants/enums.dart'; import 'package:immich_mobile/entities/album.entity.dart'; abstract interface class IAlbumApiRepository { @@ -17,6 +18,7 @@ abstract interface class IAlbumApiRepository { String? thumbnailAssetId, String? description, bool? activityEnabled, + SortOrder? sortOrder, }); Future delete(String albumId); diff --git a/mobile/lib/interfaces/auth.interface.dart b/mobile/lib/interfaces/auth.interface.dart new file mode 100644 index 0000000000000..57088f45695c7 --- /dev/null +++ b/mobile/lib/interfaces/auth.interface.dart @@ -0,0 +1,11 @@ +import 'package:immich_mobile/interfaces/database.interface.dart'; +import 'package:immich_mobile/models/auth/auxilary_endpoint.model.dart'; + +abstract interface class IAuthRepository implements IDatabaseRepository { + Future clearLocalData(); + String getAccessToken(); + bool getEndpointSwitchingFeature(); + String? getPreferredWifiName(); + String? getLocalEndpoint(); + List getExternalEndpointList(); +} diff --git a/mobile/lib/interfaces/auth_api.interface.dart b/mobile/lib/interfaces/auth_api.interface.dart new file mode 100644 index 0000000000000..0a4b235ff35bd --- /dev/null +++ b/mobile/lib/interfaces/auth_api.interface.dart @@ -0,0 +1,9 @@ +import 'package:immich_mobile/models/auth/login_response.model.dart'; + +abstract interface class IAuthApiRepository { + Future login(String email, String password); + + Future logout(); + + Future changePassword(String newPassword); +} diff --git a/mobile/lib/interfaces/network.interface.dart b/mobile/lib/interfaces/network.interface.dart new file mode 100644 index 0000000000000..098d67a27bc1b --- /dev/null +++ b/mobile/lib/interfaces/network.interface.dart @@ -0,0 +1,4 @@ +abstract interface class INetworkRepository { + Future getWifiName(); + Future getWifiIp(); +} diff --git a/mobile/lib/main.dart b/mobile/lib/main.dart index 48bc936a8276d..807212fc655eb 100644 --- a/mobile/lib/main.dart +++ b/mobile/lib/main.dart @@ -4,21 +4,26 @@ import 'dart:io'; import 'package:background_downloader/background_downloader.dart'; import 'package:device_info_plus/device_info_plus.dart'; import 'package:easy_localization/easy_localization.dart'; +import 'package:intl/date_symbol_data_local.dart'; +import 'package:timezone/data/latest.dart'; +import 'package:isar/isar.dart'; +import 'package:logging/logging.dart'; +import 'package:path_provider/path_provider.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_displaymode/flutter_displaymode.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/extensions/build_context_extensions.dart'; -import 'package:immich_mobile/utils/download.dart'; -import 'package:timezone/data/latest.dart'; import 'package:immich_mobile/constants/locales.dart'; -import 'package:immich_mobile/services/background.service.dart'; -import 'package:immich_mobile/entities/backup_album.entity.dart'; -import 'package:immich_mobile/entities/duplicated_asset.entity.dart'; +import 'package:immich_mobile/providers/locale_provider.dart'; +import 'package:immich_mobile/providers/theme.provider.dart'; +import 'package:immich_mobile/providers/app_life_cycle.provider.dart'; +import 'package:immich_mobile/providers/db.provider.dart'; import 'package:immich_mobile/routing/router.dart'; import 'package:immich_mobile/routing/tab_navigation_observer.dart'; -import 'package:immich_mobile/utils/cache/widgets_binding.dart'; +import 'package:immich_mobile/entities/backup_album.entity.dart'; +import 'package:immich_mobile/entities/duplicated_asset.entity.dart'; import 'package:immich_mobile/entities/album.entity.dart'; import 'package:immich_mobile/entities/android_device_asset.entity.dart'; import 'package:immich_mobile/entities/asset.entity.dart'; @@ -28,16 +33,15 @@ import 'package:immich_mobile/entities/ios_device_asset.entity.dart'; import 'package:immich_mobile/entities/logger_message.entity.dart'; import 'package:immich_mobile/entities/store.entity.dart'; import 'package:immich_mobile/entities/user.entity.dart'; -import 'package:immich_mobile/providers/app_life_cycle.provider.dart'; -import 'package:immich_mobile/providers/db.provider.dart'; +import 'package:immich_mobile/services/background.service.dart'; import 'package:immich_mobile/services/immich_logger.service.dart'; import 'package:immich_mobile/services/local_notification.service.dart'; -import 'package:immich_mobile/utils/http_ssl_cert_override.dart'; -import 'package:immich_mobile/utils/immich_app_theme.dart'; import 'package:immich_mobile/utils/migration.dart'; -import 'package:isar/isar.dart'; -import 'package:logging/logging.dart'; -import 'package:path_provider/path_provider.dart'; +import 'package:immich_mobile/utils/download.dart'; +import 'package:immich_mobile/utils/cache/widgets_binding.dart'; +import 'package:immich_mobile/utils/http_ssl_cert_override.dart'; +import 'package:immich_mobile/theme/theme_data.dart'; +import 'package:immich_mobile/theme/dynamic_theme.dart'; void main() async { ImmichWidgetsBinding(); @@ -56,6 +60,7 @@ void main() async { Future initApp() async { await EasyLocalization.ensureInitialized(); + await initializeDateFormatting(); if (kReleaseMode && Platform.isAndroid) { try { @@ -66,12 +71,12 @@ Future initApp() async { } } - await fetchSystemPalette(); + await DynamicTheme.fetchSystemPalette(); // Initialize Immich Logger Service ImmichLogger(); - var log = Logger("ImmichErrorLogger"); + final log = Logger("ImmichErrorLogger"); FlutterError.onError = (details) { FlutterError.presentError(details); @@ -189,6 +194,12 @@ class ImmichAppState extends ConsumerState await ref.read(localNotificationService).setup(); } + @override + void didChangeDependencies() { + super.didChangeDependencies(); + Intl.defaultLocale = context.locale.toLanguageTag(); + } + @override initState() { super.initState(); @@ -210,20 +221,31 @@ class ImmichAppState extends ConsumerState final router = ref.watch(appRouterProvider); final immichTheme = ref.watch(immichThemeProvider); - return MaterialApp( - localizationsDelegates: context.localizationDelegates, - supportedLocales: context.supportedLocales, - locale: context.locale, - debugShowCheckedModeBanner: true, - home: MaterialApp.router( - title: 'Immich', - debugShowCheckedModeBanner: false, - themeMode: ref.watch(immichThemeModeProvider), - darkTheme: getThemeData(colorScheme: immichTheme.dark), - theme: getThemeData(colorScheme: immichTheme.light), - routeInformationParser: router.defaultRouteParser(), - routerDelegate: router.delegate( - navigatorObservers: () => [TabNavigationObserver(ref: ref)], + return ProviderScope( + overrides: [ + localeProvider.overrideWithValue(context.locale), + ], + child: MaterialApp( + localizationsDelegates: context.localizationDelegates, + supportedLocales: context.supportedLocales, + locale: context.locale, + debugShowCheckedModeBanner: true, + home: MaterialApp.router( + title: 'Immich', + debugShowCheckedModeBanner: false, + themeMode: ref.watch(immichThemeModeProvider), + darkTheme: getThemeData( + colorScheme: immichTheme.dark, + locale: context.locale, + ), + theme: getThemeData( + colorScheme: immichTheme.light, + locale: context.locale, + ), + routeInformationParser: router.defaultRouteParser(), + routerDelegate: router.delegate( + navigatorObservers: () => [TabNavigationObserver(ref: ref)], + ), ), ), ); diff --git a/mobile/lib/models/authentication/authentication_state.model.dart b/mobile/lib/models/auth/auth_state.model.dart similarity index 74% rename from mobile/lib/models/authentication/authentication_state.model.dart rename to mobile/lib/models/auth/auth_state.model.dart index 9dcd320c8148a..fb65850f1d9eb 100644 --- a/mobile/lib/models/authentication/authentication_state.model.dart +++ b/mobile/lib/models/auth/auth_state.model.dart @@ -1,62 +1,58 @@ -class AuthenticationState { +class AuthState { final String deviceId; final String userId; final String userEmail; final bool isAuthenticated; final String name; final bool isAdmin; - final bool shouldChangePassword; final String profileImagePath; - AuthenticationState({ + + AuthState({ required this.deviceId, required this.userId, required this.userEmail, required this.isAuthenticated, required this.name, required this.isAdmin, - required this.shouldChangePassword, required this.profileImagePath, }); - AuthenticationState copyWith({ + AuthState copyWith({ String? deviceId, String? userId, String? userEmail, bool? isAuthenticated, String? name, bool? isAdmin, - bool? shouldChangePassword, String? profileImagePath, }) { - return AuthenticationState( + return AuthState( deviceId: deviceId ?? this.deviceId, userId: userId ?? this.userId, userEmail: userEmail ?? this.userEmail, isAuthenticated: isAuthenticated ?? this.isAuthenticated, name: name ?? this.name, isAdmin: isAdmin ?? this.isAdmin, - shouldChangePassword: shouldChangePassword ?? this.shouldChangePassword, profileImagePath: profileImagePath ?? this.profileImagePath, ); } @override String toString() { - return 'AuthenticationState(deviceId: $deviceId, userId: $userId, userEmail: $userEmail, isAuthenticated: $isAuthenticated, name: $name, isAdmin: $isAdmin, shouldChangePassword: $shouldChangePassword, profileImagePath: $profileImagePath)'; + return 'AuthenticationState(deviceId: $deviceId, userId: $userId, userEmail: $userEmail, isAuthenticated: $isAuthenticated, name: $name, isAdmin: $isAdmin, profileImagePath: $profileImagePath)'; } @override bool operator ==(Object other) { if (identical(this, other)) return true; - return other is AuthenticationState && + return other is AuthState && other.deviceId == deviceId && other.userId == userId && other.userEmail == userEmail && other.isAuthenticated == isAuthenticated && other.name == name && other.isAdmin == isAdmin && - other.shouldChangePassword == shouldChangePassword && other.profileImagePath == profileImagePath; } @@ -68,7 +64,6 @@ class AuthenticationState { isAuthenticated.hashCode ^ name.hashCode ^ isAdmin.hashCode ^ - shouldChangePassword.hashCode ^ profileImagePath.hashCode; } } diff --git a/mobile/lib/models/auth/auxilary_endpoint.model.dart b/mobile/lib/models/auth/auxilary_endpoint.model.dart new file mode 100644 index 0000000000000..89aba60913cc6 --- /dev/null +++ b/mobile/lib/models/auth/auxilary_endpoint.model.dart @@ -0,0 +1,105 @@ +// ignore_for_file: public_member_api_docs, sort_constructors_first +import 'dart:convert'; + +class AuxilaryEndpoint { + final String url; + final AuxCheckStatus status; + + AuxilaryEndpoint({ + required this.url, + required this.status, + }); + + AuxilaryEndpoint copyWith({ + String? url, + AuxCheckStatus? status, + }) { + return AuxilaryEndpoint( + url: url ?? this.url, + status: status ?? this.status, + ); + } + + @override + String toString() => 'AuxilaryEndpoint(url: $url, status: $status)'; + + @override + bool operator ==(covariant AuxilaryEndpoint other) { + if (identical(this, other)) return true; + + return other.url == url && other.status == status; + } + + @override + int get hashCode => url.hashCode ^ status.hashCode; + + Map toMap() { + return { + 'url': url, + 'status': status.toMap(), + }; + } + + factory AuxilaryEndpoint.fromMap(Map map) { + return AuxilaryEndpoint( + url: map['url'] as String, + status: AuxCheckStatus.fromMap(map['status'] as Map), + ); + } + + String toJson() => json.encode(toMap()); + + factory AuxilaryEndpoint.fromJson(String source) => + AuxilaryEndpoint.fromMap(json.decode(source) as Map); +} + +class AuxCheckStatus { + final String name; + AuxCheckStatus({ + required this.name, + }); + const AuxCheckStatus._(this.name); + + static const loading = AuxCheckStatus._('loading'); + static const valid = AuxCheckStatus._('valid'); + static const error = AuxCheckStatus._('error'); + static const unknown = AuxCheckStatus._('unknown'); + + @override + bool operator ==(covariant AuxCheckStatus other) { + if (identical(this, other)) return true; + + return other.name == name; + } + + @override + int get hashCode => name.hashCode; + + AuxCheckStatus copyWith({ + String? name, + }) { + return AuxCheckStatus( + name: name ?? this.name, + ); + } + + Map toMap() { + return { + 'name': name, + }; + } + + factory AuxCheckStatus.fromMap(Map map) { + return AuxCheckStatus( + name: map['name'] as String, + ); + } + + String toJson() => json.encode(toMap()); + + factory AuxCheckStatus.fromJson(String source) => + AuxCheckStatus.fromMap(json.decode(source) as Map); + + @override + String toString() => 'AuxCheckStatus(name: $name)'; +} diff --git a/mobile/lib/models/auth/login_response.model.dart b/mobile/lib/models/auth/login_response.model.dart new file mode 100644 index 0000000000000..f1398418cab04 --- /dev/null +++ b/mobile/lib/models/auth/login_response.model.dart @@ -0,0 +1,30 @@ +class LoginResponse { + final String accessToken; + + final bool isAdmin; + + final String name; + + final String profileImagePath; + + final bool shouldChangePassword; + + final String userEmail; + + final String userId; + + LoginResponse({ + required this.accessToken, + required this.isAdmin, + required this.name, + required this.profileImagePath, + required this.shouldChangePassword, + required this.userEmail, + required this.userId, + }); + + @override + String toString() { + return 'LoginResponse[accessToken=$accessToken, isAdmin=$isAdmin, name=$name, profileImagePath=$profileImagePath, shouldChangePassword=$shouldChangePassword, userEmail=$userEmail, userId=$userId]'; + } +} diff --git a/mobile/lib/models/backup/current_upload_asset.model.dart b/mobile/lib/models/backup/current_upload_asset.model.dart index 9a761c9e4a507..787f1172697a4 100644 --- a/mobile/lib/models/backup/current_upload_asset.model.dart +++ b/mobile/lib/models/backup/current_upload_asset.model.dart @@ -18,6 +18,9 @@ class CurrentUploadAsset { this.iCloudAsset, }); + @pragma('vm:prefer-inline') + bool get isIcloudAsset => iCloudAsset != null && iCloudAsset!; + CurrentUploadAsset copyWith({ String? id, DateTime? fileCreatedAt, diff --git a/mobile/lib/pages/common/album_additional_shared_user_selection.page.dart b/mobile/lib/pages/album/album_additional_shared_user_selection.page.dart similarity index 100% rename from mobile/lib/pages/common/album_additional_shared_user_selection.page.dart rename to mobile/lib/pages/album/album_additional_shared_user_selection.page.dart diff --git a/mobile/lib/pages/common/album_asset_selection.page.dart b/mobile/lib/pages/album/album_asset_selection.page.dart similarity index 100% rename from mobile/lib/pages/common/album_asset_selection.page.dart rename to mobile/lib/pages/album/album_asset_selection.page.dart diff --git a/mobile/lib/pages/album/album_control_button.dart b/mobile/lib/pages/album/album_control_button.dart new file mode 100644 index 0000000000000..b0ac3fbfa52a1 --- /dev/null +++ b/mobile/lib/pages/album/album_control_button.dart @@ -0,0 +1,53 @@ +import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter/material.dart'; +import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:immich_mobile/providers/album/current_album.provider.dart'; +import 'package:immich_mobile/providers/auth.provider.dart'; +import 'package:immich_mobile/widgets/album/album_action_filled_button.dart'; + +// ignore: must_be_immutable +class AlbumControlButton extends ConsumerWidget { + void Function() onAddPhotosPressed; + void Function() onAddUsersPressed; + + AlbumControlButton({ + super.key, + required this.onAddPhotosPressed, + required this.onAddUsersPressed, + }); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final userId = ref.watch(authProvider).userId; + final isOwner = ref.watch( + currentAlbumProvider.select((album) { + return album?.ownerId == userId; + }), + ); + + return Padding( + padding: const EdgeInsets.only(left: 16.0, top: 8, bottom: 16), + child: SizedBox( + height: 40, + child: ListView( + scrollDirection: Axis.horizontal, + children: [ + AlbumActionFilledButton( + key: const ValueKey('add_photos_button'), + iconData: Icons.add_photo_alternate_outlined, + onPressed: onAddPhotosPressed, + labelText: "share_add_photos".tr(), + ), + if (isOwner) + AlbumActionFilledButton( + key: const ValueKey('add_users_button'), + iconData: Icons.person_add_alt_rounded, + onPressed: onAddUsersPressed, + labelText: "album_viewer_page_share_add_users".tr(), + ), + ], + ), + ), + ); + } +} diff --git a/mobile/lib/pages/album/album_date_range.dart b/mobile/lib/pages/album/album_date_range.dart new file mode 100644 index 0000000000000..5f7ef40d4b176 --- /dev/null +++ b/mobile/lib/pages/album/album_date_range.dart @@ -0,0 +1,61 @@ +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'; +import 'package:immich_mobile/providers/album/current_album.provider.dart'; + +class AlbumDateRange extends ConsumerWidget { + const AlbumDateRange({super.key}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final data = ref.watch( + currentAlbumProvider.select((album) { + if (album == null || album.assets.isEmpty) { + return null; + } + + final startDate = album.startDate; + final endDate = album.endDate; + if (startDate == null || endDate == null) { + return null; + } + return (startDate, endDate, album.shared); + }), + ); + + if (data == null) { + return const SizedBox(); + } + final (startDate, endDate, shared) = data; + + return Padding( + padding: shared + ? const EdgeInsets.only( + left: 16.0, + bottom: 0.0, + ) + : const EdgeInsets.only(left: 16.0, bottom: 8.0), + child: Text( + _getDateRangeText(startDate, endDate), + style: context.textTheme.labelLarge, + ), + ); + } + + @pragma('vm:prefer-inline') + String _getDateRangeText(DateTime startDate, DateTime endDate) { + if (startDate.day == endDate.day && + startDate.month == endDate.month && + startDate.year == endDate.year) { + return DateFormat.yMMMd().format(startDate); + } + + final String startDateText = (startDate.year == endDate.year + ? DateFormat.MMMd() + : DateFormat.yMMMd()) + .format(startDate); + final String endDateText = DateFormat.yMMMd().format(endDate); + return "$startDateText - $endDateText"; + } +} diff --git a/mobile/lib/pages/common/album_options.page.dart b/mobile/lib/pages/album/album_options.page.dart similarity index 94% rename from mobile/lib/pages/common/album_options.page.dart rename to mobile/lib/pages/album/album_options.page.dart index 93e4c180fed6b..0e9bfeb2ce6db 100644 --- a/mobile/lib/pages/common/album_options.page.dart +++ b/mobile/lib/pages/album/album_options.page.dart @@ -7,25 +7,28 @@ import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/extensions/theme_extensions.dart'; import 'package:immich_mobile/providers/album/album.provider.dart'; -import 'package:immich_mobile/providers/authentication.provider.dart'; +import 'package:immich_mobile/providers/album/current_album.provider.dart'; +import 'package:immich_mobile/providers/auth.provider.dart'; import 'package:immich_mobile/utils/immich_loading_overlay.dart'; import 'package:immich_mobile/routing/router.dart'; -import 'package:immich_mobile/entities/album.entity.dart'; import 'package:immich_mobile/entities/user.entity.dart'; import 'package:immich_mobile/widgets/common/immich_toast.dart'; import 'package:immich_mobile/widgets/common/user_circle_avatar.dart'; @RoutePage() class AlbumOptionsPage extends HookConsumerWidget { - final Album album; - - const AlbumOptionsPage({super.key, required this.album}); + const AlbumOptionsPage({super.key}); @override Widget build(BuildContext context, WidgetRef ref) { + final album = ref.watch(currentAlbumProvider); + if (album == null) { + return const SizedBox(); + } + final sharedUsers = useState(album.sharedUsers.toList()); final owner = album.owner.value; - final userId = ref.watch(authenticationProvider).userId; + final userId = ref.watch(authProvider).userId; final activityEnabled = useState(album.activityEnabled); final isProcessing = useProcessingOverlay(); final isOwner = owner?.id == userId; @@ -49,7 +52,7 @@ class AlbumOptionsPage extends HookConsumerWidget { if (isSuccess) { context.navigateTo( - TabControllerRoute(children: [AlbumsRoute()]), + const TabControllerRoute(children: [AlbumsRoute()]), ); } else { showErrorMessage(); diff --git a/mobile/lib/pages/album/album_shared_user_icons.dart b/mobile/lib/pages/album/album_shared_user_icons.dart new file mode 100644 index 0000000000000..4cb9804e25bc3 --- /dev/null +++ b/mobile/lib/pages/album/album_shared_user_icons.dart @@ -0,0 +1,56 @@ +import 'package:auto_route/auto_route.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_hooks/flutter_hooks.dart'; +import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:immich_mobile/entities/user.entity.dart'; +import 'package:immich_mobile/providers/album/current_album.provider.dart'; +import 'package:immich_mobile/routing/router.dart'; +import 'package:immich_mobile/widgets/common/user_circle_avatar.dart'; + +class AlbumSharedUserIcons extends HookConsumerWidget { + const AlbumSharedUserIcons({super.key}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final sharedUsers = useRef>(const []); + sharedUsers.value = ref.watch( + currentAlbumProvider.select((album) { + if (album == null) { + return const []; + } + + if (album.sharedUsers.length == sharedUsers.value.length) { + return sharedUsers.value; + } + + return album.sharedUsers.toList(growable: false); + }), + ); + + if (sharedUsers.value.isEmpty) { + return const SizedBox(); + } + + return GestureDetector( + onTap: () => context.pushRoute(AlbumOptionsRoute()), + child: SizedBox( + height: 50, + child: ListView.builder( + padding: const EdgeInsets.only(left: 16), + scrollDirection: Axis.horizontal, + itemBuilder: ((context, index) { + return Padding( + padding: const EdgeInsets.only(right: 8.0), + child: UserCircleAvatar( + user: sharedUsers.value[index], + radius: 18, + size: 36, + ), + ); + }), + itemCount: sharedUsers.value.length, + ), + ), + ); + } +} diff --git a/mobile/lib/pages/common/album_shared_user_selection.page.dart b/mobile/lib/pages/album/album_shared_user_selection.page.dart similarity index 98% rename from mobile/lib/pages/common/album_shared_user_selection.page.dart rename to mobile/lib/pages/album/album_shared_user_selection.page.dart index 9dadef1a76f8a..ed8a45194deb1 100644 --- a/mobile/lib/pages/common/album_shared_user_selection.page.dart +++ b/mobile/lib/pages/album/album_shared_user_selection.page.dart @@ -33,7 +33,7 @@ class AlbumSharedUserSelectionPage extends HookConsumerWidget { if (newAlbum != null) { ref.watch(albumTitleProvider.notifier).clearAlbumTitle(); context.maybePop(true); - context.navigateTo(TabControllerRoute(children: [AlbumsRoute()])); + context.navigateTo(const TabControllerRoute(children: [AlbumsRoute()])); } ScaffoldMessenger( diff --git a/mobile/lib/pages/album/album_title.dart b/mobile/lib/pages/album/album_title.dart new file mode 100644 index 0000000000000..435e282523eb6 --- /dev/null +++ b/mobile/lib/pages/album/album_title.dart @@ -0,0 +1,41 @@ +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/album/current_album.provider.dart'; +import 'package:immich_mobile/widgets/album/album_viewer_editable_title.dart'; +import 'package:immich_mobile/providers/auth.provider.dart'; + +class AlbumTitle extends ConsumerWidget { + const AlbumTitle({super.key, required this.titleFocusNode}); + + final FocusNode titleFocusNode; + + @override + Widget build(BuildContext context, WidgetRef ref) { + final userId = ref.watch(authProvider).userId; + final (isOwner, isRemote, albumName) = ref.watch( + currentAlbumProvider.select((album) { + if (album == null) { + return const (false, false, ''); + } + + return (album.ownerId == userId, album.isRemote, album.name); + }), + ); + + if (isOwner && isRemote) { + return Padding( + padding: const EdgeInsets.only(left: 8, right: 8), + child: AlbumViewerEditableTitle( + albumName: albumName, + titleFocusNode: titleFocusNode, + ), + ); + } + + return Padding( + padding: const EdgeInsets.only(left: 16, right: 8), + child: Text(albumName, style: context.textTheme.headlineMedium), + ); + } +} diff --git a/mobile/lib/pages/album/album_viewer.dart b/mobile/lib/pages/album/album_viewer.dart new file mode 100644 index 0000000000000..19782c4e30ed2 --- /dev/null +++ b/mobile/lib/pages/album/album_viewer.dart @@ -0,0 +1,147 @@ +import 'dart:async'; + +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:fluttertoast/fluttertoast.dart'; +import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:immich_mobile/extensions/build_context_extensions.dart'; +import 'package:immich_mobile/models/albums/asset_selection_page_result.model.dart'; +import 'package:immich_mobile/pages/album/album_control_button.dart'; +import 'package:immich_mobile/pages/album/album_date_range.dart'; +import 'package:immich_mobile/pages/album/album_shared_user_icons.dart'; +import 'package:immich_mobile/pages/album/album_title.dart'; +import 'package:immich_mobile/providers/album/album.provider.dart'; +import 'package:immich_mobile/providers/album/current_album.provider.dart'; +import 'package:immich_mobile/utils/immich_loading_overlay.dart'; +import 'package:immich_mobile/providers/multiselect.provider.dart'; +import 'package:immich_mobile/providers/auth.provider.dart'; +import 'package:immich_mobile/widgets/album/album_viewer_appbar.dart'; +import 'package:immich_mobile/routing/router.dart'; +import 'package:immich_mobile/entities/asset.entity.dart'; +import 'package:immich_mobile/providers/asset.provider.dart'; +import 'package:immich_mobile/widgets/asset_grid/multiselect_grid.dart'; +import 'package:immich_mobile/widgets/common/immich_toast.dart'; + +class AlbumViewer extends HookConsumerWidget { + const AlbumViewer({super.key}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final album = ref.watch(currentAlbumProvider); + if (album == null) { + return const SizedBox(); + } + + final titleFocusNode = useFocusNode(); + final userId = ref.watch(authProvider).userId; + final isMultiselecting = ref.watch(multiselectProvider); + final isProcessing = useProcessingOverlay(); + + Future onRemoveFromAlbumPressed(Iterable assets) async { + final bool isSuccess = + await ref.read(albumProvider.notifier).removeAsset(album, assets); + + if (!isSuccess) { + ImmichToast.show( + context: context, + msg: "album_viewer_appbar_share_err_remove".tr(), + toastType: ToastType.error, + gravity: ToastGravity.BOTTOM, + ); + } + return isSuccess; + } + + /// Find out if the assets in album exist on the device + /// If they exist, add to selected asset state to show they are already selected. + void onAddPhotosPressed() async { + AssetSelectionPageResult? returnPayload = + await context.pushRoute( + AlbumAssetSelectionRoute( + existingAssets: album.assets, + canDeselect: false, + query: getRemoteAssetQuery(ref), + ), + ); + + if (returnPayload != null && returnPayload.selectedAssets.isNotEmpty) { + // Check if there is new assets add + isProcessing.value = true; + + await ref + .watch(albumProvider.notifier) + .addAssets(album, returnPayload.selectedAssets); + + isProcessing.value = false; + } + } + + void onAddUsersPressed() async { + List? sharedUserIds = await context.pushRoute?>( + AlbumAdditionalSharedUserSelectionRoute(album: album), + ); + + if (sharedUserIds != null) { + isProcessing.value = true; + + await ref.watch(albumProvider.notifier).addUsers(album, sharedUserIds); + + isProcessing.value = false; + } + } + + onActivitiesPressed() { + if (album.remoteId != null) { + context.pushRoute( + const ActivitiesRoute(), + ); + } + } + + return Stack( + children: [ + MultiselectGrid( + key: const ValueKey("albumViewerMultiselectGrid"), + renderListProvider: albumRenderlistProvider(album.id), + topWidget: Column( + mainAxisAlignment: MainAxisAlignment.end, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + AlbumTitle( + key: const ValueKey("albumTitle"), + titleFocusNode: titleFocusNode, + ), + const AlbumDateRange(), + const AlbumSharedUserIcons(), + if (album.isRemote) + AlbumControlButton( + key: const ValueKey("albumControlButton"), + onAddPhotosPressed: onAddPhotosPressed, + onAddUsersPressed: onAddUsersPressed, + ), + ], + ), + onRemoveFromAlbum: onRemoveFromAlbumPressed, + editEnabled: album.ownerId == userId, + ), + AnimatedPositioned( + key: const ValueKey("albumViewerAppbarPositioned"), + duration: const Duration(milliseconds: 300), + top: isMultiselecting ? -(kToolbarHeight + context.padding.top) : 0, + left: 0, + right: 0, + child: AlbumViewerAppbar( + key: const ValueKey("albumViewerAppbar"), + titleFocusNode: titleFocusNode, + userId: userId, + onAddPhotos: onAddPhotosPressed, + onAddUsers: onAddUsersPressed, + onActivities: onActivitiesPressed, + ), + ), + ], + ); + } +} diff --git a/mobile/lib/pages/album/album_viewer.page.dart b/mobile/lib/pages/album/album_viewer.page.dart new file mode 100644 index 0000000000000..491bd3bb8d570 --- /dev/null +++ b/mobile/lib/pages/album/album_viewer.page.dart @@ -0,0 +1,27 @@ +import 'package:auto_route/auto_route.dart'; +import 'package:flutter/material.dart'; +import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:immich_mobile/pages/album/album_viewer.dart'; +import 'package:immich_mobile/providers/album/album.provider.dart'; +import 'package:immich_mobile/providers/album/current_album.provider.dart'; + +@RoutePage() +class AlbumViewerPage extends HookConsumerWidget { + final int albumId; + + const AlbumViewerPage({super.key, required this.albumId}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + // Listen provider to prevent autoDispose when navigating to other routes from within the viewer page + ref.listen(currentAlbumProvider, (_, __) {}); + + ref.listen(albumWatcher(albumId), (_, albumFuture) { + albumFuture.whenData( + (value) => ref.read(currentAlbumProvider.notifier).set(value), + ); + }); + + return const Scaffold(body: AlbumViewer()); + } +} diff --git a/mobile/lib/pages/albums/albums.page.dart b/mobile/lib/pages/albums/albums.page.dart index e466149ac3ee8..6f7d99b72726b 100644 --- a/mobile/lib/pages/albums/albums.page.dart +++ b/mobile/lib/pages/albums/albums.page.dart @@ -78,7 +78,7 @@ class AlbumsPage extends HookConsumerWidget { showUploadButton: false, actions: [ IconButton( - icon: Icon( + icon: const Icon( Icons.add_rounded, size: 28, ), @@ -112,13 +112,13 @@ class AlbumsPage extends HookConsumerWidget { ], begin: Alignment.topLeft, end: Alignment.bottomRight, - transform: GradientRotation(0.5 * pi), + transform: const GradientRotation(0.5 * pi), ), ), child: TextField( autofocus: false, decoration: InputDecoration( - contentPadding: EdgeInsets.all(16), + contentPadding: const EdgeInsets.all(16), border: OutlineInputBorder( borderRadius: BorderRadius.circular(25), borderSide: BorderSide( @@ -362,13 +362,13 @@ class SortButton extends ConsumerWidget { return MenuAnchor( style: MenuStyle( - elevation: WidgetStatePropertyAll(1), + elevation: const WidgetStatePropertyAll(1), shape: WidgetStateProperty.all( RoundedRectangleBorder( borderRadius: BorderRadius.circular(24), ), ), - padding: WidgetStatePropertyAll( + padding: const WidgetStatePropertyAll( EdgeInsets.all(4), ), ), diff --git a/mobile/lib/pages/backup/backup_controller.page.dart b/mobile/lib/pages/backup/backup_controller.page.dart index d8baecf808d63..6783f7b54a178 100644 --- a/mobile/lib/pages/backup/backup_controller.page.dart +++ b/mobile/lib/pages/backup/backup_controller.page.dart @@ -1,11 +1,9 @@ -import 'dart:async'; import 'dart:io'; import 'dart:math'; 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:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/extensions/build_context_extensions.dart'; @@ -31,8 +29,6 @@ class BackupControllerPage extends HookConsumerWidget { BackUpState backupState = ref.watch(backupProvider); final hasAnyAlbum = backupState.selectedBackupAlbums.isNotEmpty; final didGetBackupInfo = useState(false); - final isScreenDarkened = useState(false); - final darkenScreenTimer = useRef(null); bool hasExclusiveAccess = backupState.backupProgress != BackUpProgressEnum.inBackground; @@ -43,25 +39,6 @@ class BackupControllerPage extends HookConsumerWidget { ? false : true; - void startScreenDarkenTimer() { - darkenScreenTimer.value = Timer(const Duration(seconds: 30), () { - isScreenDarkened.value = true; - SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersiveSticky); - }); - } - - void stopScreenDarkenTimer() { - darkenScreenTimer.value?.cancel(); - isScreenDarkened.value = false; - SystemChrome.setEnabledSystemUIMode( - SystemUiMode.manual, - overlays: [ - SystemUiOverlay.top, - SystemUiOverlay.bottom, - ], - ); - } - useEffect( () { // Update the background settings information just to make sure we @@ -77,8 +54,6 @@ class BackupControllerPage extends HookConsumerWidget { return () { WakelockPlus.disable(); - darkenScreenTimer.value?.cancel(); - isScreenDarkened.value = false; }; }, [], @@ -99,10 +74,8 @@ class BackupControllerPage extends HookConsumerWidget { useEffect( () { if (backupState.backupProgress == BackUpProgressEnum.inProgress) { - startScreenDarkenTimer(); WakelockPlus.enable(); } else { - stopScreenDarkenTimer(); WakelockPlus.disable(); } @@ -297,103 +270,77 @@ class BackupControllerPage extends HookConsumerWidget { ); } - return GestureDetector( - onTap: () { - if (isScreenDarkened.value) { - stopScreenDarkenTimer(); - } - if (backupState.backupProgress == BackUpProgressEnum.inProgress) { - startScreenDarkenTimer(); - } - }, - child: AnimatedOpacity( - opacity: isScreenDarkened.value ? 0.1 : 1.0, - duration: const Duration(seconds: 1), - child: Scaffold( - appBar: AppBar( - elevation: 0, - title: const Text( - "backup_controller_page_backup", - ).tr(), - leading: IconButton( - onPressed: () { - ref.watch(websocketProvider.notifier).listenUploadEvent(); - context.maybePop(true); - }, + return Scaffold( + appBar: AppBar( + elevation: 0, + title: const Text( + "backup_controller_page_backup", + ).tr(), + leading: IconButton( + onPressed: () { + ref.watch(websocketProvider.notifier).listenUploadEvent(); + context.maybePop(true); + }, + splashRadius: 24, + icon: const Icon( + Icons.arrow_back_ios_rounded, + ), + ), + actions: [ + Padding( + padding: const EdgeInsets.only(right: 8.0), + child: IconButton( + onPressed: () => context.pushRoute(const BackupOptionsRoute()), splashRadius: 24, icon: const Icon( - Icons.arrow_back_ios_rounded, + Icons.settings_outlined, ), ), - actions: [ - Padding( - padding: const EdgeInsets.only(right: 8.0), - child: IconButton( - onPressed: () => - context.pushRoute(const BackupOptionsRoute()), - splashRadius: 24, - icon: const Icon( - Icons.settings_outlined, - ), - ), - ), - ], ), - body: Stack( - children: [ - Padding( - padding: - const EdgeInsets.only(left: 16.0, right: 16, bottom: 32), - child: ListView( - // crossAxisAlignment: CrossAxisAlignment.start, - children: hasAnyAlbum - ? [ - buildFolderSelectionTile(), - BackupInfoCard( - title: "backup_controller_page_total".tr(), - subtitle: "backup_controller_page_total_sub".tr(), - info: ref - .watch(backupProvider) - .availableAlbums - .isEmpty - ? "..." - : "${backupState.allUniqueAssets.length}", - ), - BackupInfoCard( - title: "backup_controller_page_backup".tr(), - subtitle: "backup_controller_page_backup_sub".tr(), - info: ref - .watch(backupProvider) - .availableAlbums - .isEmpty - ? "..." - : "${backupState.selectedAlbumsBackupAssetsIds.length}", - ), - BackupInfoCard( - title: "backup_controller_page_remainder".tr(), - subtitle: - "backup_controller_page_remainder_sub".tr(), - info: ref - .watch(backupProvider) - .availableAlbums - .isEmpty - ? "..." - : "${max(0, backupState.allUniqueAssets.length - backupState.selectedAlbumsBackupAssetsIds.length)}", - ), - const Divider(), - const CurrentUploadingAssetInfoBox(), - if (!hasExclusiveAccess) buildBackgroundBackupInfo(), - buildBackupButton(), - ] - : [ - buildFolderSelectionTile(), - if (!didGetBackupInfo.value) buildLoadingIndicator(), - ], - ), - ), - ], + ], + ), + body: Stack( + children: [ + Padding( + padding: const EdgeInsets.only(left: 16.0, right: 16, bottom: 32), + child: ListView( + // crossAxisAlignment: CrossAxisAlignment.start, + children: hasAnyAlbum + ? [ + buildFolderSelectionTile(), + BackupInfoCard( + title: "backup_controller_page_total".tr(), + subtitle: "backup_controller_page_total_sub".tr(), + info: ref.watch(backupProvider).availableAlbums.isEmpty + ? "..." + : "${backupState.allUniqueAssets.length}", + ), + BackupInfoCard( + title: "backup_controller_page_backup".tr(), + subtitle: "backup_controller_page_backup_sub".tr(), + info: ref.watch(backupProvider).availableAlbums.isEmpty + ? "..." + : "${backupState.selectedAlbumsBackupAssetsIds.length}", + ), + BackupInfoCard( + title: "backup_controller_page_remainder".tr(), + subtitle: "backup_controller_page_remainder_sub".tr(), + info: ref.watch(backupProvider).availableAlbums.isEmpty + ? "..." + : "${max(0, backupState.allUniqueAssets.length - backupState.selectedAlbumsBackupAssetsIds.length)}", + ), + const Divider(), + const CurrentUploadingAssetInfoBox(), + if (!hasExclusiveAccess) buildBackgroundBackupInfo(), + buildBackupButton(), + ] + : [ + buildFolderSelectionTile(), + if (!didGetBackupInfo.value) buildLoadingIndicator(), + ], + ), ), - ), + ], ), ); } diff --git a/mobile/lib/pages/common/album_viewer.page.dart b/mobile/lib/pages/common/album_viewer.page.dart deleted file mode 100644 index b977128cfa25c..0000000000000 --- a/mobile/lib/pages/common/album_viewer.page.dart +++ /dev/null @@ -1,267 +0,0 @@ -import 'dart:async'; - -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:fluttertoast/fluttertoast.dart'; -import 'package:hooks_riverpod/hooks_riverpod.dart'; -import 'package:immich_mobile/extensions/asyncvalue_extensions.dart'; -import 'package:immich_mobile/extensions/build_context_extensions.dart'; -import 'package:immich_mobile/models/albums/asset_selection_page_result.model.dart'; -import 'package:immich_mobile/providers/album/album.provider.dart'; -import 'package:immich_mobile/providers/album/current_album.provider.dart'; -import 'package:immich_mobile/utils/immich_loading_overlay.dart'; -import 'package:immich_mobile/widgets/album/album_action_filled_button.dart'; -import 'package:immich_mobile/widgets/album/album_viewer_editable_title.dart'; -import 'package:immich_mobile/providers/multiselect.provider.dart'; -import 'package:immich_mobile/providers/authentication.provider.dart'; -import 'package:immich_mobile/widgets/album/album_viewer_appbar.dart'; -import 'package:immich_mobile/routing/router.dart'; -import 'package:immich_mobile/entities/album.entity.dart'; -import 'package:immich_mobile/entities/asset.entity.dart'; -import 'package:immich_mobile/providers/asset.provider.dart'; -import 'package:immich_mobile/widgets/asset_grid/multiselect_grid.dart'; -import 'package:immich_mobile/widgets/common/immich_toast.dart'; -import 'package:immich_mobile/widgets/common/user_circle_avatar.dart'; - -@RoutePage() -class AlbumViewerPage extends HookConsumerWidget { - final int albumId; - - const AlbumViewerPage({super.key, required this.albumId}); - - @override - Widget build(BuildContext context, WidgetRef ref) { - FocusNode titleFocusNode = useFocusNode(); - final album = ref.watch(albumWatcher(albumId)); - // Listen provider to prevent autoDispose when navigating to other routes from within the viewer page - ref.listen(currentAlbumProvider, (_, __) {}); - album.whenData( - (value) => Future.microtask( - () => ref.read(currentAlbumProvider.notifier).set(value), - ), - ); - final userId = ref.watch(authenticationProvider).userId; - final isProcessing = useProcessingOverlay(); - - Future onRemoveFromAlbumPressed(Iterable assets) async { - final a = album.valueOrNull; - final bool isSuccess = a != null && - await ref.read(albumProvider.notifier).removeAsset(a, assets); - - if (!isSuccess) { - ImmichToast.show( - context: context, - msg: "album_viewer_appbar_share_err_remove".tr(), - toastType: ToastType.error, - gravity: ToastGravity.BOTTOM, - ); - } - return isSuccess; - } - - /// Find out if the assets in album exist on the device - /// If they exist, add to selected asset state to show they are already selected. - void onAddPhotosPressed(Album albumInfo) async { - AssetSelectionPageResult? returnPayload = - await context.pushRoute( - AlbumAssetSelectionRoute( - existingAssets: albumInfo.assets, - canDeselect: false, - query: getRemoteAssetQuery(ref), - ), - ); - - if (returnPayload != null && returnPayload.selectedAssets.isNotEmpty) { - // Check if there is new assets add - isProcessing.value = true; - - await ref.watch(albumProvider.notifier).addAssets( - albumInfo, - returnPayload.selectedAssets, - ); - - isProcessing.value = false; - } - } - - void onAddUsersPressed(Album album) async { - List? sharedUserIds = await context.pushRoute?>( - AlbumAdditionalSharedUserSelectionRoute(album: album), - ); - - if (sharedUserIds != null) { - isProcessing.value = true; - - await ref.watch(albumProvider.notifier).addUsers(album, sharedUserIds); - - isProcessing.value = false; - } - } - - Widget buildControlButton(Album album) { - return Padding( - padding: const EdgeInsets.only(left: 16.0, top: 8, bottom: 16), - child: SizedBox( - height: 40, - child: ListView( - scrollDirection: Axis.horizontal, - children: [ - AlbumActionFilledButton( - iconData: Icons.add_photo_alternate_outlined, - onPressed: () => onAddPhotosPressed(album), - labelText: "share_add_photos".tr(), - ), - if (userId == album.ownerId) - AlbumActionFilledButton( - iconData: Icons.person_add_alt_rounded, - onPressed: () => onAddUsersPressed(album), - labelText: "album_viewer_page_share_add_users".tr(), - ), - ], - ), - ), - ); - } - - Widget buildTitle(Album album) { - return Padding( - padding: const EdgeInsets.only(left: 8, right: 8), - child: userId == album.ownerId && album.isRemote - ? AlbumViewerEditableTitle( - album: album, - titleFocusNode: titleFocusNode, - ) - : Padding( - padding: const EdgeInsets.only(left: 8.0), - child: Text( - album.name, - style: context.textTheme.headlineMedium, - ), - ), - ); - } - - Widget buildAlbumDateRange(Album album) { - final DateTime? startDate = album.startDate; - final DateTime? endDate = album.endDate; - - if (startDate == null || endDate == null) { - return const SizedBox(); - } - - final String dateRangeText; - if (startDate.day == endDate.day && - startDate.month == endDate.month && - startDate.year == endDate.year) { - dateRangeText = DateFormat.yMMMd().format(startDate); - } else { - final String startDateText = (startDate.year == endDate.year - ? DateFormat.MMMd() - : DateFormat.yMMMd()) - .format(startDate); - final String endDateText = DateFormat.yMMMd().format(endDate); - dateRangeText = "$startDateText - $endDateText"; - } - - return Padding( - padding: EdgeInsets.only( - left: 16.0, - bottom: album.shared ? 0.0 : 8.0, - ), - child: Text( - dateRangeText, - style: context.textTheme.labelLarge, - ), - ); - } - - Widget buildSharedUserIconsRow(Album album) { - return album.sharedUsers.isNotEmpty - ? GestureDetector( - onTap: () => context.pushRoute(AlbumOptionsRoute(album: album)), - child: SizedBox( - height: 50, - child: ListView.builder( - padding: const EdgeInsets.only(left: 16), - scrollDirection: Axis.horizontal, - itemBuilder: ((context, index) { - return Padding( - padding: const EdgeInsets.only(right: 8.0), - child: UserCircleAvatar( - user: album.sharedUsers.toList()[index], - radius: 18, - size: 36, - ), - ); - }), - itemCount: album.sharedUsers.length, - ), - ), - ) - : const SizedBox.shrink(); - } - - Widget buildHeader(Album album) { - return Column( - mainAxisAlignment: MainAxisAlignment.end, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - buildTitle(album), - if (album.assets.isNotEmpty == true) buildAlbumDateRange(album), - buildSharedUserIconsRow(album), - ], - ); - } - - onActivitiesPressed(Album album) { - if (album.remoteId != null) { - context.pushRoute( - const ActivitiesRoute(), - ); - } - } - - return Scaffold( - body: Stack( - children: [ - album.widgetWhen( - onData: (albumInfo) => MultiselectGrid( - renderListProvider: albumRenderlistProvider(albumId), - topWidget: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - buildHeader(albumInfo), - if (albumInfo.isRemote) buildControlButton(albumInfo), - ], - ), - onRemoveFromAlbum: onRemoveFromAlbumPressed, - editEnabled: albumInfo.ownerId == userId, - ), - ), - AnimatedPositioned( - duration: const Duration(milliseconds: 300), - top: ref.watch(multiselectProvider) - ? -(kToolbarHeight + MediaQuery.of(context).padding.top) - : 0, - left: 0, - right: 0, - child: album.when( - data: (data) => AlbumViewerAppbar( - titleFocusNode: titleFocusNode, - album: data, - userId: userId, - onAddPhotos: onAddPhotosPressed, - onAddUsers: onAddUsersPressed, - onActivities: onActivitiesPressed, - ), - error: (error, stackTrace) => AppBar(title: const Text("Error")), - loading: () => AppBar(), - ), - ), - ], - ), - ); - } -} diff --git a/mobile/lib/pages/common/app_log_detail.page.dart b/mobile/lib/pages/common/app_log_detail.page.dart index 1b9af6cfcfa08..dd6af817284e0 100644 --- a/mobile/lib/pages/common/app_log_detail.page.dart +++ b/mobile/lib/pages/common/app_log_detail.page.dart @@ -37,7 +37,7 @@ class AppLogDetailPage extends HookConsumerWidget { IconButton( onPressed: () { Clipboard.setData(ClipboardData(text: text)).then((_) { - ScaffoldMessenger.of(context).showSnackBar( + context.scaffoldMessenger.showSnackBar( SnackBar( content: Text( "Copied to clipboard", diff --git a/mobile/lib/pages/common/download_panel.dart b/mobile/lib/pages/common/download_panel.dart index 95cefd742af0a..4421e337e9c99 100644 --- a/mobile/lib/pages/common/download_panel.dart +++ b/mobile/lib/pages/common/download_panel.dart @@ -97,7 +97,7 @@ class DownloadTaskTile extends StatelessWidget { return SizedBox( key: const ValueKey('download_progress'), - width: MediaQuery.of(context).size.width - 32, + width: context.width - 32, child: Card( clipBehavior: Clip.antiAlias, shape: RoundedRectangleBorder( diff --git a/mobile/lib/pages/common/gallery_stacked_children.dart b/mobile/lib/pages/common/gallery_stacked_children.dart new file mode 100644 index 0000000000000..eafc3250494f9 --- /dev/null +++ b/mobile/lib/pages/common/gallery_stacked_children.dart @@ -0,0 +1,91 @@ +import 'package:flutter/material.dart'; +import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:immich_mobile/providers/asset_viewer/asset_stack.provider.dart'; +import 'package:immich_mobile/providers/asset_viewer/current_asset.provider.dart'; +import 'package:immich_mobile/providers/asset_viewer/show_controls.provider.dart'; +import 'package:immich_mobile/providers/image/immich_remote_image_provider.dart'; + +class GalleryStackedChildren extends HookConsumerWidget { + final ValueNotifier stackIndex; + + const GalleryStackedChildren(this.stackIndex, {super.key}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final asset = ref.watch(currentAssetProvider); + if (asset == null) { + return const SizedBox(); + } + + final stackId = asset.stackId; + if (stackId == null) { + return const SizedBox(); + } + + final stackElements = ref.watch(assetStackStateProvider(stackId)); + final showControls = ref.watch(showControlsProvider); + + return IgnorePointer( + ignoring: !showControls, + child: AnimatedOpacity( + duration: const Duration(milliseconds: 100), + opacity: showControls ? 1.0 : 0.0, + child: SizedBox( + height: 80, + child: ListView.builder( + shrinkWrap: true, + scrollDirection: Axis.horizontal, + itemCount: stackElements.length, + padding: const EdgeInsets.only( + left: 5, + right: 5, + bottom: 30, + ), + itemBuilder: (context, index) { + final currentAsset = stackElements.elementAt(index); + final assetId = currentAsset.remoteId; + if (assetId == null) { + return const SizedBox(); + } + + return Padding( + key: ValueKey(currentAsset.id), + padding: const EdgeInsets.only(right: 5), + child: GestureDetector( + onTap: () { + stackIndex.value = index; + ref.read(currentAssetProvider.notifier).set(currentAsset); + }, + child: Container( + width: 60, + height: 60, + decoration: index == stackIndex.value + ? 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: Image( + fit: BoxFit.cover, + image: ImmichRemoteImageProvider(assetId: assetId), + ), + ), + ), + ), + ); + }, + ), + ), + ), + ); + } +} diff --git a/mobile/lib/pages/common/gallery_viewer.page.dart b/mobile/lib/pages/common/gallery_viewer.page.dart index 57c75ca84df84..5f77f28d8e110 100644 --- a/mobile/lib/pages/common/gallery_viewer.page.dart +++ b/mobile/lib/pages/common/gallery_viewer.page.dart @@ -8,18 +8,19 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_hooks/flutter_hooks.dart' hide Store; import 'package:hooks_riverpod/hooks_riverpod.dart'; -import 'package:immich_mobile/constants/constants.dart'; import 'package:immich_mobile/entities/asset.entity.dart'; import 'package:immich_mobile/extensions/build_context_extensions.dart'; +import 'package:immich_mobile/extensions/scroll_extensions.dart'; import 'package:immich_mobile/pages/common/download_panel.dart'; -import 'package:immich_mobile/pages/common/video_viewer.page.dart'; +import 'package:immich_mobile/pages/common/native_video_viewer.page.dart'; +import 'package:immich_mobile/pages/common/gallery_stacked_children.dart'; import 'package:immich_mobile/providers/app_settings.provider.dart'; import 'package:immich_mobile/providers/asset_viewer/asset_stack.provider.dart'; import 'package:immich_mobile/providers/asset_viewer/current_asset.provider.dart'; +import 'package:immich_mobile/providers/asset_viewer/is_motion_video_playing.provider.dart'; import 'package:immich_mobile/providers/asset_viewer/show_controls.provider.dart'; import 'package:immich_mobile/providers/asset_viewer/video_player_value_provider.dart'; import 'package:immich_mobile/providers/haptic_feedback.provider.dart'; -import 'package:immich_mobile/providers/image/immich_remote_image_provider.dart'; import 'package:immich_mobile/services/app_settings.service.dart'; import 'package:immich_mobile/widgets/asset_grid/asset_grid_data_structure.dart'; import 'package:immich_mobile/widgets/asset_viewer/advanced_bottom_sheet.dart'; @@ -35,6 +36,7 @@ import 'package:immich_mobile/widgets/photo_view/src/utils/photo_view_hero_attri @RoutePage() // ignore: must_be_immutable +/// Expects [currentAssetProvider] to be set before navigating to this page class GalleryViewerPage extends HookConsumerWidget { final int initialIndex; final int heroOffset; @@ -53,79 +55,67 @@ class GalleryViewerPage extends HookConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { - final settings = ref.watch(appSettingsServiceProvider); - final loadAsset = renderList.loadAsset; final totalAssets = useState(renderList.totalAssets); - final shouldLoopVideo = useState(AppSettingsEnum.loopVideo.defaultValue); final isZoomed = useState(false); - final isPlayingVideo = useState(false); - final localPosition = useState(null); - final currentIndex = useState(initialIndex); - final currentAsset = loadAsset(currentIndex.value); - - // Update is playing motion video - ref.listen(videoPlaybackValueProvider.select((v) => v.state), (_, state) { - isPlayingVideo.value = state == VideoPlaybackState.playing; - }); - - final stackIndex = useState(-1); - final stack = showStack && currentAsset.stackCount > 0 - ? ref.watch(assetStackStateProvider(currentAsset)) - : []; - final stackElements = showStack ? [currentAsset, ...stack] : []; - // Assets from response DTOs do not have an isar id, querying which would give us the default autoIncrement id - final isFromDto = currentAsset.id == noDbId; - - Asset asset = stackIndex.value == -1 - ? currentAsset - : stackElements.elementAt(stackIndex.value); - - final isMotionPhoto = asset.livePhotoVideoId != null; - // Listen provider to prevent autoDispose when navigating to other routes from within the gallery page - ref.listen(currentAssetProvider, (_, __) {}); - useEffect( - () { - // Delay state update to after the execution of build method - Future.microtask( - () => ref.read(currentAssetProvider.notifier).set(asset), - ); - return null; - }, - [asset], - ); - - useEffect( - () { - shouldLoopVideo.value = - settings.getSetting(AppSettingsEnum.loopVideo); - return null; - }, - [], - ); + final stackIndex = useState(0); + final localPosition = useRef(null); + final currentIndex = useValueNotifier(initialIndex); + final loadAsset = renderList.loadAsset; + final isPlayingMotionVideo = ref.watch(isPlayingMotionVideoProvider); Future precacheNextImage(int index) async { + if (!context.mounted) { + return; + } + void onError(Object exception, StackTrace? stackTrace) { // swallow error silently - debugPrint('Error precaching next image: $exception, $stackTrace'); + log.severe('Error precaching next image: $exception, $stackTrace'); } try { if (index < totalAssets.value && index >= 0) { final asset = loadAsset(index); await precacheImage( - ImmichImage.imageProvider(asset: asset), + ImmichImage.imageProvider( + asset: asset, + width: context.width, + height: context.height, + ), context, onError: onError, ); } } catch (e) { // swallow error silently - debugPrint('Error precaching next image: $e'); + log.severe('Error precaching next image: $e'); context.maybePop(); } } + useEffect( + () { + if (ref.read(showControlsProvider)) { + SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge); + } else { + SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersive); + } + + // Delay this a bit so we can finish loading the page + Timer(const Duration(milliseconds: 400), () { + precacheNextImage(currentIndex.value + 1); + }); + + return null; + }, + const [], + ); + void showInfo() { + final asset = ref.read(currentAssetProvider); + if (asset == null) { + return; + } showModalBottomSheet( shape: const RoundedRectangleBorder( borderRadius: BorderRadius.all(Radius.circular(15.0)), @@ -141,7 +131,7 @@ class GalleryViewerPage extends HookConsumerWidget { heightFactor: 0.75, child: Padding( padding: EdgeInsets.only( - bottom: MediaQuery.viewInsetsOf(context).bottom, + bottom: context.viewInsets.bottom, ), child: ref .watch(appSettingsServiceProvider) @@ -183,86 +173,99 @@ class GalleryViewerPage extends HookConsumerWidget { } } - useEffect( - () { - if (ref.read(showControlsProvider)) { - SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge); - } else { - SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersive); - } - isPlayingVideo.value = false; - return null; - }, - [], - ); - - useEffect( - () { - // No need to await this - unawaited( - // Delay this a bit so we can finish loading the page - Future.delayed(const Duration(milliseconds: 400)).then( - // Precache the next image - (_) => precacheNextImage(currentIndex.value + 1), - ), - ); - return null; - }, - [], - ); - ref.listen(showControlsProvider, (_, show) { - if (show) { + if (show || Platform.isIOS) { SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge); - } else { - SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersive); + return; } + + // This prevents the bottom bar from "dropping" while the controls are being hidden + Timer(const Duration(milliseconds: 100), () { + SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersive); + }); }); - Widget buildStackedChildren() { - return ListView.builder( - shrinkWrap: true, - scrollDirection: Axis.horizontal, - itemCount: stackElements.length, - padding: const EdgeInsets.only( - left: 5, - right: 5, - bottom: 30, + PhotoViewGalleryPageOptions buildImage(BuildContext context, Asset asset) { + return PhotoViewGalleryPageOptions( + onDragStart: (_, details, __) { + localPosition.value = details.localPosition; + }, + onDragUpdate: (_, details, __) { + handleSwipeUpDown(details); + }, + onTapDown: (_, __, ___) { + ref.read(showControlsProvider.notifier).toggle(); + }, + onLongPressStart: asset.isMotionPhoto + ? (_, __, ___) { + ref.read(isPlayingMotionVideoProvider.notifier).playing = true; + } + : null, + imageProvider: ImmichImage.imageProvider(asset: asset), + heroAttributes: _getHeroAttributes(asset), + filterQuality: FilterQuality.high, + tightMode: true, + minScale: PhotoViewComputedScale.contained, + errorBuilder: (context, error, stackTrace) => ImmichImage( + asset, + fit: BoxFit.contain, ), - itemBuilder: (context, index) { - final assetId = stackElements.elementAt(index).remoteId; - return Padding( - padding: const EdgeInsets.only(right: 5), - child: GestureDetector( - onTap: () => stackIndex.value = index, - child: Container( - width: 60, - height: 60, - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(6), - border: (stackIndex.value == -1 && index == 0) || - index == stackIndex.value - ? Border.all( - color: Colors.white, - width: 2, - ) - : null, - ), - child: ClipRRect( - borderRadius: BorderRadius.circular(4), - child: Image( - fit: BoxFit.cover, - image: ImmichRemoteImageProvider(assetId: assetId!), - ), - ), + ); + } + + PhotoViewGalleryPageOptions buildVideo(BuildContext context, Asset asset) { + // This key is to prevent the video player from being re-initialized during the hero animation + final key = GlobalKey(); + return PhotoViewGalleryPageOptions.customChild( + onDragStart: (_, details, __) => + localPosition.value = details.localPosition, + onDragUpdate: (_, details, __) => handleSwipeUpDown(details), + heroAttributes: _getHeroAttributes(asset), + filterQuality: FilterQuality.high, + initialScale: 1.0, + maxScale: 1.0, + minScale: 1.0, + basePosition: Alignment.center, + child: SizedBox( + width: context.width, + height: context.height, + child: NativeVideoViewerPage( + key: key, + asset: asset, + image: Image( + key: ValueKey(asset), + image: ImmichImage.imageProvider( + asset: asset, + width: context.width, + height: context.height, ), + fit: BoxFit.contain, + height: context.height, + width: context.width, + alignment: Alignment.center, ), - ); - }, + ), + ), ); } + PhotoViewGalleryPageOptions buildAsset(BuildContext context, int index) { + var newAsset = loadAsset(index); + final stackId = newAsset.stackId; + if (stackId != null && currentIndex.value == index) { + final stackElements = + ref.read(assetStackStateProvider(newAsset.stackId!)); + if (stackIndex.value < stackElements.length) { + newAsset = stackElements.elementAt(stackIndex.value); + } + } + + if (newAsset.isImage && !isPlayingMotionVideo) { + return buildImage(context, newAsset); + } + return buildVideo(context, newAsset); + } + return PopScope( // Change immersive mode back to normal "edgeToEdge" mode onPopInvokedWithResult: (didPop, _) => @@ -272,128 +275,79 @@ class GalleryViewerPage extends HookConsumerWidget { body: Stack( children: [ PhotoViewGallery.builder( + key: ValueKey(isPlayingMotionVideo), scaleStateChangedCallback: (state) { - isZoomed.value = state != PhotoViewScaleState.initial; - ref.read(showControlsProvider.notifier).show = !isZoomed.value; + final asset = ref.read(currentAssetProvider); + if (asset == null) { + return; + } + + if (asset.isImage && !ref.read(isPlayingMotionVideoProvider)) { + isZoomed.value = state != PhotoViewScaleState.initial; + ref.read(showControlsProvider.notifier).show = + !isZoomed.value; + } }, - loadingBuilder: (context, event, index) => ClipRect( - child: Stack( - fit: StackFit.expand, - children: [ - BackdropFilter( - filter: ui.ImageFilter.blur( - sigmaX: 10, - sigmaY: 10, + gaplessPlayback: true, + loadingBuilder: (context, event, index) { + final asset = loadAsset(index); + return ClipRect( + child: Stack( + fit: StackFit.expand, + children: [ + BackdropFilter( + filter: ui.ImageFilter.blur( + sigmaX: 10, + sigmaY: 10, + ), ), - ), - ImmichThumbnail( - asset: asset, - fit: BoxFit.contain, - ), - ], - ), - ), + ImmichThumbnail( + key: ValueKey(asset), + asset: asset, + fit: BoxFit.contain, + ), + ], + ), + ); + }, pageController: controller, scrollPhysics: isZoomed.value ? const NeverScrollableScrollPhysics() // Don't allow paging while scrolled in : (Platform.isIOS - ? const ScrollPhysics() // Use bouncing physics for iOS - : const ClampingScrollPhysics() // Use heavy physics for Android + ? const FastScrollPhysics() // Use bouncing physics for iOS + : const FastClampingScrollPhysics() // Use heavy physics for Android ), itemCount: totalAssets.value, scrollDirection: Axis.horizontal, - onPageChanged: (value) async { + onPageChanged: (value) { final next = currentIndex.value < value ? value + 1 : value - 1; ref.read(hapticFeedbackProvider.notifier).selectionClick(); - currentIndex.value = value; - stackIndex.value = -1; - isPlayingVideo.value = false; - - // Wait for page change animation to finish - await Future.delayed(const Duration(milliseconds: 400)); - // Then precache the next image - unawaited(precacheNextImage(next)); - }, - builder: (context, index) { - final a = - index == currentIndex.value ? asset : loadAsset(index); + final newAsset = loadAsset(value); - final ImageProvider provider = - ImmichImage.imageProvider(asset: a); + currentIndex.value = value; + stackIndex.value = 0; - if (a.isImage && !isPlayingVideo.value) { - return PhotoViewGalleryPageOptions( - onDragStart: (_, details, __) => - localPosition.value = details.localPosition, - onDragUpdate: (_, details, __) => - handleSwipeUpDown(details), - onTapDown: (_, __, ___) { - ref.read(showControlsProvider.notifier).toggle(); - }, - onLongPressStart: (_, __, ___) { - if (asset.livePhotoVideoId != null) { - isPlayingVideo.value = true; - } - }, - imageProvider: provider, - heroAttributes: PhotoViewHeroAttributes( - tag: isFromDto - ? '${currentAsset.remoteId}-$heroOffset' - : currentAsset.id + heroOffset, - transitionOnUserGestures: true, - ), - filterQuality: FilterQuality.high, - tightMode: true, - minScale: PhotoViewComputedScale.contained, - errorBuilder: (context, error, stackTrace) => ImmichImage( - a, - fit: BoxFit.contain, - ), - ); - } else { - return PhotoViewGalleryPageOptions.customChild( - onDragStart: (_, details, __) => - localPosition.value = details.localPosition, - onDragUpdate: (_, details, __) => - handleSwipeUpDown(details), - heroAttributes: PhotoViewHeroAttributes( - tag: isFromDto - ? '${currentAsset.remoteId}-$heroOffset' - : currentAsset.id + heroOffset, - ), - filterQuality: FilterQuality.high, - maxScale: 1.0, - minScale: 1.0, - basePosition: Alignment.center, - child: VideoViewerPage( - key: ValueKey(a), - asset: a, - isMotionVideo: a.livePhotoVideoId != null, - loopVideo: shouldLoopVideo.value, - placeholder: Image( - image: provider, - fit: BoxFit.contain, - height: context.height, - width: context.width, - alignment: Alignment.center, - ), - ), - ); + ref.read(currentAssetProvider.notifier).set(newAsset); + if (newAsset.isVideo || newAsset.isMotionPhoto) { + ref.read(videoPlaybackValueProvider.notifier).reset(); } + + // Wait for page change animation to finish, then precache the next image + Timer(const Duration(milliseconds: 400), () { + precacheNextImage(next); + }); }, + builder: buildAsset, ), Positioned( top: 0, left: 0, right: 0, child: GalleryAppBar( - asset: asset, + key: const ValueKey('app-bar'), showInfo: showInfo, - isPlayingVideo: isPlayingVideo.value, - onToggleMotionVideo: () => - isPlayingVideo.value = !isPlayingVideo.value, ), ), Positioned( @@ -402,22 +356,15 @@ class GalleryViewerPage extends HookConsumerWidget { right: 0, child: Column( children: [ - Visibility( - visible: stack.isNotEmpty, - child: SizedBox( - height: 80, - child: buildStackedChildren(), - ), - ), + GalleryStackedChildren(stackIndex), BottomGalleryBar( + key: const ValueKey('bottom-bar'), renderList: renderList, totalAssets: totalAssets, controller: controller, showStack: showStack, - stackIndex: stackIndex.value, - asset: asset, + stackIndex: stackIndex, assetIndex: currentIndex, - showVideoPlayerControls: !asset.isImage && !isMotionPhoto, ), ], ), @@ -428,4 +375,14 @@ class GalleryViewerPage extends HookConsumerWidget { ), ); } + + @pragma('vm:prefer-inline') + PhotoViewHeroAttributes _getHeroAttributes(Asset asset) { + return PhotoViewHeroAttributes( + tag: asset.isInDb + ? asset.id + heroOffset + : '${asset.remoteId}-$heroOffset', + transitionOnUserGestures: true, + ); + } } diff --git a/mobile/lib/pages/common/large_leading_tile.dart b/mobile/lib/pages/common/large_leading_tile.dart index 8213ca423f268..c6bbeb2e7df24 100644 --- a/mobile/lib/pages/common/large_leading_tile.dart +++ b/mobile/lib/pages/common/large_leading_tile.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:immich_mobile/extensions/build_context_extensions.dart'; class LargeLeadingTile extends StatelessWidget { const LargeLeadingTile({ @@ -37,7 +38,7 @@ class LargeLeadingTile extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ SizedBox( - width: MediaQuery.of(context).size.width * 0.6, + width: context.width * 0.6, child: title, ), subtitle ?? const SizedBox.shrink(), diff --git a/mobile/lib/pages/common/native_video_viewer.page.dart b/mobile/lib/pages/common/native_video_viewer.page.dart new file mode 100644 index 0000000000000..9c50f49dbbac8 --- /dev/null +++ b/mobile/lib/pages/common/native_video_viewer.page.dart @@ -0,0 +1,386 @@ +import 'dart:async'; +import 'dart:io'; + +import 'package:auto_route/auto_route.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_hooks/flutter_hooks.dart' hide Store; +import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:immich_mobile/entities/asset.entity.dart'; +import 'package:immich_mobile/entities/store.entity.dart'; +import 'package:immich_mobile/providers/app_settings.provider.dart'; +import 'package:immich_mobile/providers/asset_viewer/current_asset.provider.dart'; +import 'package:immich_mobile/providers/asset_viewer/is_motion_video_playing.provider.dart'; +import 'package:immich_mobile/providers/asset_viewer/video_player_controls_provider.dart'; +import 'package:immich_mobile/providers/asset_viewer/video_player_value_provider.dart'; +import 'package:immich_mobile/services/api.service.dart'; +import 'package:immich_mobile/services/app_settings.service.dart'; +import 'package:immich_mobile/services/asset.service.dart'; +import 'package:immich_mobile/utils/debounce.dart'; +import 'package:immich_mobile/utils/hooks/interval_hook.dart'; +import 'package:immich_mobile/widgets/asset_viewer/custom_video_player_controls.dart'; +import 'package:logging/logging.dart'; +import 'package:native_video_player/native_video_player.dart'; +import 'package:wakelock_plus/wakelock_plus.dart'; + +@RoutePage() +class NativeVideoViewerPage extends HookConsumerWidget { + final Asset asset; + final bool showControls; + final Widget image; + + const NativeVideoViewerPage({ + super.key, + required this.asset, + required this.image, + this.showControls = true, + }); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final controller = useState(null); + final lastVideoPosition = useRef(-1); + final isBuffering = useRef(false); + + // When a video is opened through the timeline, `isCurrent` will immediately be true. + // When swiping from video A to video B, `isCurrent` will initially be true for video A and false for video B. + // If the swipe is completed, `isCurrent` will be true for video B after a delay. + // If the swipe is canceled, `currentAsset` will not have changed and video A will continue to play. + final currentAsset = useState(ref.read(currentAssetProvider)); + final isCurrent = currentAsset.value == asset; + + // Used to show the placeholder during hero animations for remote videos to avoid a stutter + final isVisible = useState(Platform.isIOS && asset.isLocal); + + final log = Logger('NativeVideoViewerPage'); + + Future createSource() async { + if (!context.mounted) { + return null; + } + + try { + final local = asset.local; + if (local != null && asset.livePhotoVideoId == null) { + final file = await local.file; + if (file == null) { + throw Exception('No file found for the video'); + } + + final source = await VideoSource.init( + path: file.path, + type: VideoSourceType.file, + ); + return source; + } + + // Use a network URL for the video player controller + final serverEndpoint = Store.get(StoreKey.serverEndpoint); + final String videoUrl = asset.livePhotoVideoId != null + ? '$serverEndpoint/assets/${asset.livePhotoVideoId}/video/playback' + : '$serverEndpoint/assets/${asset.remoteId}/video/playback'; + + final source = await VideoSource.init( + path: videoUrl, + type: VideoSourceType.network, + headers: ApiService.getRequestHeaders(), + ); + return source; + } catch (error) { + log.severe( + 'Error creating video source for asset ${asset.fileName}: $error', + ); + return null; + } + } + + final videoSource = useMemoized>(() => createSource()); + final aspectRatio = useState(asset.aspectRatio); + useMemoized( + () async { + if (!context.mounted || aspectRatio.value != null) { + return null; + } + + try { + aspectRatio.value = + await ref.read(assetServiceProvider).getAspectRatio(asset); + } catch (error) { + log.severe( + 'Error getting aspect ratio for asset ${asset.fileName}: $error', + ); + } + }, + ); + + void checkIfBuffering() { + if (!context.mounted) { + return; + } + + final videoPlayback = ref.read(videoPlaybackValueProvider); + if ((isBuffering.value || + videoPlayback.state == VideoPlaybackState.initializing) && + videoPlayback.state != VideoPlaybackState.buffering) { + ref.read(videoPlaybackValueProvider.notifier).value = + videoPlayback.copyWith(state: VideoPlaybackState.buffering); + } + } + + // Timer to mark videos as buffering if the position does not change + useInterval(const Duration(seconds: 5), checkIfBuffering); + + // When the position changes, seek to the position + // Debounce the seek to avoid seeking too often + // But also don't delay the seek too much to maintain visual feedback + final seekDebouncer = useDebouncer( + interval: const Duration(milliseconds: 100), + maxWaitTime: const Duration(milliseconds: 200), + ); + ref.listen(videoPlayerControlsProvider, (oldControls, newControls) async { + final playerController = controller.value; + if (playerController == null) { + return; + } + + final playbackInfo = playerController.playbackInfo; + if (playbackInfo == null) { + return; + } + + final oldSeek = (oldControls?.position ?? 0) ~/ 1; + final newSeek = newControls.position ~/ 1; + if (oldSeek != newSeek || newControls.restarted) { + seekDebouncer.run(() => playerController.seekTo(newSeek)); + } + + if (oldControls?.pause != newControls.pause || newControls.restarted) { + // Make sure the last seek is complete before pausing or playing + // Otherwise, `onPlaybackPositionChanged` can receive outdated events + if (seekDebouncer.isActive) { + await seekDebouncer.drain(); + } + + try { + if (newControls.pause) { + await playerController.pause(); + } else { + await playerController.play(); + } + } catch (error) { + log.severe('Error pausing or playing video: $error'); + } + } + }); + + void onPlaybackReady() async { + final videoController = controller.value; + if (videoController == null || !isCurrent || !context.mounted) { + return; + } + + final videoPlayback = + VideoPlaybackValue.fromNativeController(videoController); + ref.read(videoPlaybackValueProvider.notifier).value = videoPlayback; + + try { + await videoController.play(); + await videoController.setVolume(0.9); + } catch (error) { + log.severe('Error playing video: $error'); + } + } + + void onPlaybackStatusChanged() { + final videoController = controller.value; + if (videoController == null || !context.mounted) { + return; + } + + final videoPlayback = + VideoPlaybackValue.fromNativeController(videoController); + if (videoPlayback.state == VideoPlaybackState.playing) { + // Sync with the controls playing + WakelockPlus.enable(); + } else { + // Sync with the controls pause + WakelockPlus.disable(); + } + + ref.read(videoPlaybackValueProvider.notifier).status = + videoPlayback.state; + } + + void onPlaybackPositionChanged() { + // When seeking, these events sometimes move the slider to an older position + if (seekDebouncer.isActive) { + return; + } + + final videoController = controller.value; + if (videoController == null || !context.mounted) { + return; + } + + final playbackInfo = videoController.playbackInfo; + if (playbackInfo == null) { + return; + } + + ref.read(videoPlaybackValueProvider.notifier).position = + Duration(seconds: playbackInfo.position); + + // Check if the video is buffering + if (playbackInfo.status == PlaybackStatus.playing) { + isBuffering.value = lastVideoPosition.value == playbackInfo.position; + lastVideoPosition.value = playbackInfo.position; + } else { + isBuffering.value = false; + lastVideoPosition.value = -1; + } + } + + void onPlaybackEnded() { + final videoController = controller.value; + if (videoController == null || !context.mounted) { + return; + } + + if (videoController.playbackInfo?.status == PlaybackStatus.stopped && + !ref + .read(appSettingsServiceProvider) + .getSetting(AppSettingsEnum.loopVideo)) { + ref.read(isPlayingMotionVideoProvider.notifier).playing = false; + } + } + + void removeListeners(NativeVideoPlayerController controller) { + controller.onPlaybackPositionChanged + .removeListener(onPlaybackPositionChanged); + controller.onPlaybackStatusChanged + .removeListener(onPlaybackStatusChanged); + controller.onPlaybackReady.removeListener(onPlaybackReady); + controller.onPlaybackEnded.removeListener(onPlaybackEnded); + } + + void initController(NativeVideoPlayerController nc) async { + if (controller.value != null || !context.mounted) { + return; + } + ref.read(videoPlayerControlsProvider.notifier).reset(); + ref.read(videoPlaybackValueProvider.notifier).reset(); + + final source = await videoSource; + if (source == null) { + return; + } + + nc.onPlaybackPositionChanged.addListener(onPlaybackPositionChanged); + nc.onPlaybackStatusChanged.addListener(onPlaybackStatusChanged); + nc.onPlaybackReady.addListener(onPlaybackReady); + nc.onPlaybackEnded.addListener(onPlaybackEnded); + + nc.loadVideoSource(source).catchError((error) { + log.severe('Error loading video source: $error'); + }); + final loopVideo = ref + .read(appSettingsServiceProvider) + .getSetting(AppSettingsEnum.loopVideo); + nc.setLoop(loopVideo); + + controller.value = nc; + Timer(const Duration(milliseconds: 200), checkIfBuffering); + } + + ref.listen(currentAssetProvider, (_, value) { + final playerController = controller.value; + if (playerController != null && value != asset) { + removeListeners(playerController); + } + + final curAsset = currentAsset.value; + if (curAsset == asset) { + return; + } + + final imageToVideo = curAsset != null && !curAsset.isVideo; + + // No need to delay video playback when swiping from an image to a video + if (imageToVideo && Platform.isIOS) { + currentAsset.value = value; + onPlaybackReady(); + return; + } + + // Delay the video playback to avoid a stutter in the swipe animation + Timer( + Platform.isIOS + ? const Duration(milliseconds: 300) + : imageToVideo + ? const Duration(milliseconds: 200) + : const Duration(milliseconds: 400), () { + if (!context.mounted) { + return; + } + + currentAsset.value = value; + if (currentAsset.value == asset) { + onPlaybackReady(); + } + }); + }); + + useEffect( + () { + // If opening a remote video from a hero animation, delay visibility to avoid a stutter + final timer = isVisible.value + ? null + : Timer( + const Duration(milliseconds: 300), + () => isVisible.value = true, + ); + + return () { + timer?.cancel(); + final playerController = controller.value; + if (playerController == null) { + return; + } + removeListeners(playerController); + playerController.stop().catchError((error) { + log.fine('Error stopping video: $error'); + }); + + WakelockPlus.disable(); + }; + }, + const [], + ); + + return Stack( + children: [ + // This remains under the video to avoid flickering + // For motion videos, this is the image portion of the asset + Center(key: ValueKey(asset.id), child: image), + if (aspectRatio.value != null) + Visibility.maintain( + key: ValueKey(asset), + visible: isVisible.value, + child: Center( + key: ValueKey(asset), + child: AspectRatio( + key: ValueKey(asset), + aspectRatio: aspectRatio.value!, + child: isCurrent + ? NativeVideoPlayerView( + key: ValueKey(asset), + onViewReady: initController, + ) + : null, + ), + ), + ), + if (showControls) const Center(child: CustomVideoPlayerControls()), + ], + ); + } +} diff --git a/mobile/lib/pages/common/settings.page.dart b/mobile/lib/pages/common/settings.page.dart index 117b0aedc0cbc..3cbded1787d5b 100644 --- a/mobile/lib/pages/common/settings.page.dart +++ b/mobile/lib/pages/common/settings.page.dart @@ -8,36 +8,69 @@ 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/language_settings.dart'; +import 'package:immich_mobile/widgets/settings/networking_settings/networking_settings.dart'; import 'package:immich_mobile/widgets/settings/notification_setting.dart'; import 'package:immich_mobile/widgets/settings/preference_settings/preference_setting.dart'; import 'package:immich_mobile/routing/router.dart'; enum SettingSection { + advanced( + 'advanced_settings_tile_title', + Icons.build_outlined, + "advanced_settings_tile_subtitle", + ), + assetViewer( + 'asset_viewer_settings_title', + Icons.image_outlined, + "asset_viewer_settings_subtitle", + ), + backup( + 'backup_controller_page_backup', + Icons.cloud_upload_outlined, + "backup_setting_subtitle", + ), + languages( + 'setting_languages_title', + Icons.language, + "setting_languages_subtitle", + ), + networking( + 'networking_settings', + Icons.wifi, + "networking_subtitle", + ), notifications( 'setting_notifications_title', Icons.notifications_none_rounded, + "setting_notifications_subtitle", + ), + preferences( + 'preferences_settings_title', + Icons.interests_outlined, + "preferences_settings_subtitle", ), - languages('setting_languages_title', Icons.language), - preferences('preferences_settings_title', Icons.interests_outlined), - backup('backup_controller_page_backup', Icons.cloud_upload_outlined), - timeline('asset_list_settings_title', Icons.auto_awesome_mosaic_outlined), - viewer('asset_viewer_settings_title', Icons.image_outlined), - advanced('advanced_settings_tile_title', Icons.build_outlined); + timeline( + 'asset_list_settings_title', + Icons.auto_awesome_mosaic_outlined, + "asset_list_settings_subtitle", + ); final String title; + final String subtitle; final IconData icon; Widget get widget => switch (this) { - SettingSection.notifications => const NotificationSetting(), + SettingSection.advanced => const AdvancedSettings(), + SettingSection.assetViewer => const AssetViewerSettings(), + SettingSection.backup => const BackupSettings(), SettingSection.languages => const LanguageSettings(), + SettingSection.networking => const NetworkingSettings(), + SettingSection.notifications => const NotificationSetting(), SettingSection.preferences => const PreferenceSetting(), - SettingSection.backup => const BackupSettings(), SettingSection.timeline => const AssetListSettings(), - SettingSection.viewer => const AssetViewerSettings(), - SettingSection.advanced => const AdvancedSettings(), }; - const SettingSection(this.title, this.icon); + const SettingSection(this.title, this.icon, this.subtitle); } @RoutePage() @@ -46,6 +79,7 @@ class SettingsPage extends StatelessWidget { @override Widget build(BuildContext context) { + context.locale; return Scaffold( appBar: AppBar( centerTitle: false, @@ -60,22 +94,51 @@ class _MobileLayout extends StatelessWidget { @override Widget build(BuildContext context) { return ListView( + physics: const ClampingScrollPhysics(), + padding: const EdgeInsets.symmetric(vertical: 10.0), children: SettingSection.values .map( - (s) => ListTile( - contentPadding: - const EdgeInsets.symmetric(vertical: 2.0, horizontal: 16.0), - leading: Icon(s.icon), - title: Padding( - padding: const EdgeInsets.only(left: 8.0), - child: Text( - s.title, - style: const TextStyle( - fontWeight: FontWeight.bold, + (setting) => Padding( + padding: const EdgeInsets.symmetric( + horizontal: 16.0, + ), + child: Card( + elevation: 0, + clipBehavior: Clip.antiAlias, + color: context.colorScheme.surfaceContainer, + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.all(Radius.circular(16)), + ), + margin: const EdgeInsets.symmetric(vertical: 4.0), + child: ListTile( + contentPadding: const EdgeInsets.symmetric( + horizontal: 16.0, + ), + leading: Container( + decoration: BoxDecoration( + borderRadius: const BorderRadius.all(Radius.circular(16)), + color: context.isDarkTheme + ? Colors.black26 + : Colors.white.withAlpha(100), + ), + padding: const EdgeInsets.all(16.0), + child: Icon(setting.icon, color: context.primaryColor), ), - ).tr(), + title: Text( + setting.title, + style: context.textTheme.titleMedium!.copyWith( + fontWeight: FontWeight.w600, + color: context.primaryColor, + ), + ).tr(), + subtitle: Text( + setting.subtitle, + style: context.textTheme.labelLarge, + ).tr(), + onTap: () => + context.pushRoute(SettingsSubRoute(section: setting)), + ), ), - onTap: () => context.pushRoute(SettingsSubRoute(section: s)), ), ) .toList(), @@ -129,6 +192,7 @@ class SettingsSubPage extends StatelessWidget { @override Widget build(BuildContext context) { + context.locale; return Scaffold( appBar: AppBar( centerTitle: false, diff --git a/mobile/lib/pages/common/splash_screen.page.dart b/mobile/lib/pages/common/splash_screen.page.dart index d23e25372c374..6a060e19f0dcc 100644 --- a/mobile/lib/pages/common/splash_screen.page.dart +++ b/mobile/lib/pages/common/splash_screen.page.dart @@ -1,81 +1,88 @@ import 'package:auto_route/auto_route.dart'; import 'package:flutter/material.dart'; -import 'package:flutter_hooks/flutter_hooks.dart' hide Store; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/providers/backup/backup.provider.dart'; -import 'package:immich_mobile/providers/authentication.provider.dart'; +import 'package:immich_mobile/providers/auth.provider.dart'; import 'package:immich_mobile/providers/gallery_permission.provider.dart'; import 'package:immich_mobile/routing/router.dart'; import 'package:immich_mobile/entities/store.entity.dart'; -import 'package:immich_mobile/providers/api.provider.dart'; import 'package:logging/logging.dart'; @RoutePage() -class SplashScreenPage extends HookConsumerWidget { +class SplashScreenPage extends StatefulHookConsumerWidget { const SplashScreenPage({super.key}); @override - Widget build(BuildContext context, WidgetRef ref) { - final apiService = ref.watch(apiServiceProvider); + SplashScreenPageState createState() => SplashScreenPageState(); +} + +class SplashScreenPageState extends ConsumerState { + final log = Logger("SplashScreenPage"); + @override + void initState() { + super.initState(); + ref + .read(authProvider.notifier) + .setOpenApiServiceEndpoint() + .then(logConnectionInfo) + .whenComplete(() => resumeSession()); + } + + void logConnectionInfo(String? endpoint) { + if (endpoint == null) { + return; + } + + log.info("Resuming session at $endpoint"); + } + + void resumeSession() async { final serverUrl = Store.tryGet(StoreKey.serverUrl); final endpoint = Store.tryGet(StoreKey.serverEndpoint); final accessToken = Store.tryGet(StoreKey.accessToken); - final log = Logger("SplashScreenPage"); - - void performLoggingIn() async { - bool isAuthSuccess = false; - if (accessToken != null && serverUrl != null && endpoint != null) { - apiService.setEndpoint(endpoint); + bool isAuthSuccess = false; - try { - isAuthSuccess = await ref - .read(authenticationProvider.notifier) - .setSuccessLoginInfo( - accessToken: accessToken, - serverUrl: serverUrl, - ); - } catch (error, stackTrace) { - log.severe( - 'Cannot set success login info', - error, - stackTrace, - ); - } - } else { - isAuthSuccess = false; + if (accessToken != null && serverUrl != null && endpoint != null) { + try { + isAuthSuccess = await ref.read(authProvider.notifier).saveAuthInfo( + accessToken: accessToken, + ); + } catch (error, stackTrace) { log.severe( - 'Missing authentication, server, or endpoint info from the local store', + 'Cannot set success login info', + error, + stackTrace, ); } + } else { + isAuthSuccess = false; + log.severe( + 'Missing authentication, server, or endpoint info from the local store', + ); + } - if (!isAuthSuccess) { - log.severe( - 'Unable to login using offline or online methods - Logging out completely', - ); - ref.read(authenticationProvider.notifier).logout(); - context.replaceRoute(const LoginRoute()); - return; - } + if (!isAuthSuccess) { + log.severe( + 'Unable to login using offline or online methods - Logging out completely', + ); + ref.read(authProvider.notifier).logout(); + context.replaceRoute(const LoginRoute()); + return; + } - context.replaceRoute(const TabControllerRoute()); + context.replaceRoute(const TabControllerRoute()); - final hasPermission = - await ref.read(galleryPermissionNotifier.notifier).hasPermission; - if (hasPermission) { - // Resume backup (if enable) then navigate - ref.watch(backupProvider.notifier).resumeBackup(); - } + final hasPermission = + await ref.read(galleryPermissionNotifier.notifier).hasPermission; + if (hasPermission) { + // Resume backup (if enable) then navigate + ref.watch(backupProvider.notifier).resumeBackup(); } + } - useEffect( - () { - performLoggingIn(); - return null; - }, - [], - ); - + @override + Widget build(BuildContext context) { return const Scaffold( body: Center( child: Image( diff --git a/mobile/lib/pages/common/video_viewer.page.dart b/mobile/lib/pages/common/video_viewer.page.dart deleted file mode 100644 index 573f7277f2e4c..0000000000000 --- a/mobile/lib/pages/common/video_viewer.page.dart +++ /dev/null @@ -1,168 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_hooks/flutter_hooks.dart'; -import 'package:hooks_riverpod/hooks_riverpod.dart'; -import 'package:immich_mobile/entities/asset.entity.dart'; -import 'package:immich_mobile/providers/asset_viewer/show_controls.provider.dart'; -import 'package:immich_mobile/providers/asset_viewer/video_player_controller_provider.dart'; -import 'package:immich_mobile/providers/asset_viewer/video_player_controls_provider.dart'; -import 'package:immich_mobile/providers/asset_viewer/video_player_value_provider.dart'; -import 'package:immich_mobile/widgets/asset_viewer/video_player.dart'; -import 'package:immich_mobile/widgets/common/delayed_loading_indicator.dart'; -import 'package:wakelock_plus/wakelock_plus.dart'; - -class VideoViewerPage extends HookConsumerWidget { - final Asset asset; - final bool isMotionVideo; - final Widget? placeholder; - final Duration hideControlsTimer; - final bool showControls; - final bool showDownloadingIndicator; - final bool loopVideo; - - const VideoViewerPage({ - super.key, - required this.asset, - this.isMotionVideo = false, - this.placeholder, - this.showControls = true, - this.hideControlsTimer = const Duration(seconds: 5), - this.showDownloadingIndicator = true, - this.loopVideo = false, - }); - - @override - build(BuildContext context, WidgetRef ref) { - final controller = - ref.watch(videoPlayerControllerProvider(asset: asset)).value; - // The last volume of the video used when mute is toggled - final lastVolume = useState(0.5); - - // When the volume changes, set the volume - ref.listen(videoPlayerControlsProvider.select((value) => value.mute), - (_, mute) { - if (mute) { - controller?.setVolume(0.0); - } else { - controller?.setVolume(lastVolume.value); - } - }); - - // When the position changes, seek to the position - ref.listen(videoPlayerControlsProvider.select((value) => value.position), - (_, position) { - if (controller == null) { - // No seeeking if there is no video - return; - } - - // Find the position to seek to - final Duration seek = controller.value.duration * (position / 100.0); - controller.seekTo(seek); - }); - - // When the custom video controls paus or plays - ref.listen(videoPlayerControlsProvider.select((value) => value.pause), - (lastPause, pause) { - if (pause) { - controller?.pause(); - } else { - controller?.play(); - } - }); - - // Updates the [videoPlaybackValueProvider] with the current - // position and duration of the video from the Chewie [controller] - // Also sets the error if there is an error in the playback - void updateVideoPlayback() { - final videoPlayback = VideoPlaybackValue.fromController(controller); - ref.read(videoPlaybackValueProvider.notifier).value = videoPlayback; - final state = videoPlayback.state; - - // Enable the WakeLock while the video is playing - if (state == VideoPlaybackState.playing) { - // Sync with the controls playing - WakelockPlus.enable(); - } else { - // Sync with the controls pause - WakelockPlus.disable(); - } - } - - // Adds and removes the listener to the video player - useEffect( - () { - Future.microtask( - () => ref.read(videoPlayerControlsProvider.notifier).reset(), - ); - // Guard no controller - if (controller == null) { - return null; - } - - // Hide the controls - // Done in a microtask to avoid setting the state while the is building - if (!isMotionVideo) { - Future.microtask(() { - ref.read(showControlsProvider.notifier).show = false; - }); - } - - // Subscribes to listener - Future.microtask(() { - controller.addListener(updateVideoPlayback); - }); - return () { - // Removes listener when we dispose - controller.removeListener(updateVideoPlayback); - controller.pause(); - }; - }, - [controller], - ); - - final size = MediaQuery.sizeOf(context); - - return PopScope( - onPopInvokedWithResult: (didPop, _) { - ref.read(videoPlaybackValueProvider.notifier).value = - VideoPlaybackValue.uninitialized(); - }, - child: AnimatedSwitcher( - duration: const Duration(milliseconds: 400), - child: Stack( - children: [ - Visibility( - visible: controller == null, - child: Stack( - children: [ - if (placeholder != null) placeholder!, - const Positioned.fill( - child: Center( - child: DelayedLoadingIndicator( - fadeInDuration: Duration(milliseconds: 500), - ), - ), - ), - ], - ), - ), - if (controller != null) - SizedBox( - height: size.height, - width: size.width, - child: VideoPlayerViewer( - controller: controller, - isMotionVideo: isMotionVideo, - placeholder: placeholder, - hideControlsTimer: hideControlsTimer, - showControls: showControls, - showDownloadingIndicator: showDownloadingIndicator, - loopVideo: loopVideo, - ), - ), - ], - ), - ), - ); - } -} diff --git a/mobile/lib/pages/editing/crop.page.dart b/mobile/lib/pages/editing/crop.page.dart index 8bfb8c8bb9bf9..dc467f5740bd6 100644 --- a/mobile/lib/pages/editing/crop.page.dart +++ b/mobile/lib/pages/editing/crop.page.dart @@ -92,7 +92,7 @@ class CropImagePage extends HookWidget { IconButton( icon: Icon( Icons.rotate_left, - color: Theme.of(context).iconTheme.color, + color: context.themeData.iconTheme.color, ), onPressed: () { cropController.rotateLeft(); @@ -101,7 +101,7 @@ class CropImagePage extends HookWidget { IconButton( icon: Icon( Icons.rotate_right, - color: Theme.of(context).iconTheme.color, + color: context.themeData.iconTheme.color, ), onPressed: () { cropController.rotateRight(); @@ -203,7 +203,7 @@ class _AspectRatioButton extends StatelessWidget { iconData, color: aspectRatio.value == ratio ? context.primaryColor - : Theme.of(context).iconTheme.color, + : context.themeData.iconTheme.color, ), onPressed: () { cropController.crop = const Rect.fromLTRB(0.1, 0.1, 0.9, 0.9); diff --git a/mobile/lib/pages/editing/edit.page.dart b/mobile/lib/pages/editing/edit.page.dart index 650d2dc912db9..385140eb59d14 100644 --- a/mobile/lib/pages/editing/edit.page.dart +++ b/mobile/lib/pages/editing/edit.page.dart @@ -70,7 +70,7 @@ class EditImagePage extends ConsumerWidget { title: "${p.withoutExtension(asset.fileName)}_edited.jpg", ); await ref.read(albumProvider.notifier).refreshDeviceAlbums(); - Navigator.of(context).popUntil((route) => route.isFirst); + context.navigator.popUntil((route) => route.isFirst); ImmichToast.show( durationInSecond: 3, context: context, @@ -99,8 +99,7 @@ class EditImagePage extends ConsumerWidget { color: context.primaryColor, size: 24, ), - onPressed: () => - Navigator.of(context).popUntil((route) => route.isFirst), + onPressed: () => context.navigator.popUntil((route) => route.isFirst), ), actions: [ TextButton( @@ -120,8 +119,8 @@ class EditImagePage extends ConsumerWidget { body: Center( child: ConstrainedBox( constraints: BoxConstraints( - maxHeight: MediaQuery.of(context).size.height * 0.7, - maxWidth: MediaQuery.of(context).size.width * 0.9, + maxHeight: context.height * 0.7, + maxWidth: context.width * 0.9, ), child: Container( decoration: BoxDecoration( @@ -161,7 +160,7 @@ class EditImagePage extends ConsumerWidget { IconButton( icon: Icon( Icons.crop_rotate_rounded, - color: Theme.of(context).iconTheme.color, + color: context.themeData.iconTheme.color, size: 25, ), onPressed: () { @@ -179,7 +178,7 @@ class EditImagePage extends ConsumerWidget { IconButton( icon: Icon( Icons.filter, - color: Theme.of(context).iconTheme.color, + color: context.themeData.iconTheme.color, size: 25, ), onPressed: () { diff --git a/mobile/lib/pages/editing/filter.page.dart b/mobile/lib/pages/editing/filter.page.dart index da8ba74891595..f8b1f180df5f1 100644 --- a/mobile/lib/pages/editing/filter.page.dart +++ b/mobile/lib/pages/editing/filter.page.dart @@ -104,7 +104,7 @@ class FilterImagePage extends HookWidget { body: Column( children: [ SizedBox( - height: MediaQuery.of(context).size.height * 0.7, + height: context.height * 0.7, child: Center( child: ColorFiltered( colorFilter: colorFilter.value, @@ -180,7 +180,7 @@ class _FilterButton extends StatelessWidget { ), ), const SizedBox(height: 10), - Text(label, style: Theme.of(context).textTheme.bodyMedium), + Text(label, style: context.themeData.textTheme.bodyMedium), ], ); } diff --git a/mobile/lib/pages/library/library.page.dart b/mobile/lib/pages/library/library.page.dart index 48d2c685ba1e7..92fe8cec17368 100644 --- a/mobile/lib/pages/library/library.page.dart +++ b/mobile/lib/pages/library/library.page.dart @@ -23,11 +23,12 @@ class LibraryPage extends ConsumerWidget { const LibraryPage({super.key}); @override Widget build(BuildContext context, WidgetRef ref) { + context.locale; final trashEnabled = ref.watch(serverInfoProvider.select((v) => v.serverFeatures.trash)); return Scaffold( - appBar: ImmichAppBar(), + appBar: const ImmichAppBar(), body: Padding( padding: const EdgeInsets.symmetric(horizontal: 16), child: ListView( @@ -80,7 +81,7 @@ class LibraryPage extends ConsumerWidget { ], ), const SizedBox(height: 12), - QuickAccessButtons(), + const QuickAccessButtons(), const SizedBox( height: 32, ), @@ -121,8 +122,8 @@ class QuickAccessButtons extends ConsumerWidget { ListTile( shape: RoundedRectangleBorder( borderRadius: BorderRadius.only( - topLeft: Radius.circular(20), - topRight: Radius.circular(20), + topLeft: const Radius.circular(20), + topRight: const Radius.circular(20), bottomLeft: Radius.circular(partners.isEmpty ? 20 : 0), bottomRight: Radius.circular(partners.isEmpty ? 20 : 0), ), @@ -172,7 +173,7 @@ class PartnerList extends ConsumerWidget { right: 18.0, ), leading: userAvatar(context, partner, radius: 16), - title: Text( + title: const Text( "partner_list_user_photos", style: TextStyle( fontWeight: FontWeight.w500, @@ -201,7 +202,7 @@ class PeopleCollectionCard extends ConsumerWidget { builder: (context, constraints) { final isTablet = constraints.maxWidth > 600; final widthFactor = isTablet ? 0.25 : 0.5; - final size = MediaQuery.of(context).size.width * widthFactor - 20.0; + final size = context.width * widthFactor - 20.0; return GestureDetector( onTap: () => context.pushRoute(const PeopleCollectionRoute()), @@ -271,7 +272,7 @@ class LocalAlbumsCollectionCard extends HookConsumerWidget { builder: (context, constraints) { final isTablet = constraints.maxWidth > 600; final widthFactor = isTablet ? 0.25 : 0.5; - final size = MediaQuery.of(context).size.width * widthFactor - 20.0; + final size = context.width * widthFactor - 20.0; return GestureDetector( onTap: () => context.pushRoute( @@ -334,7 +335,7 @@ class PlacesCollectionCard extends StatelessWidget { builder: (context, constraints) { final isTablet = constraints.maxWidth > 600; final widthFactor = isTablet ? 0.25 : 0.5; - final size = MediaQuery.of(context).size.width * widthFactor - 20.0; + final size = context.width * widthFactor - 20.0; return GestureDetector( onTap: () => context.pushRoute(const PlacesCollectionRoute()), diff --git a/mobile/lib/pages/library/people/people_collection.page.dart b/mobile/lib/pages/library/people/people_collection.page.dart index ad78e27a41a77..6c62d70058ef6 100644 --- a/mobile/lib/pages/library/people/people_collection.page.dart +++ b/mobile/lib/pages/library/people/people_collection.page.dart @@ -32,8 +32,7 @@ class PeopleCollectionPage extends HookConsumerWidget { return LayoutBuilder( builder: (context, constraints) { final isTablet = constraints.maxWidth > 600; - final isPortrait = - MediaQuery.of(context).orientation == Orientation.portrait; + final isPortrait = context.orientation == Orientation.portrait; return Scaffold( appBar: AppBar( diff --git a/mobile/lib/pages/library/places/places_collection.page.dart b/mobile/lib/pages/library/places/places_collection.page.dart index 3e4f9f6a1da01..f42febc373d26 100644 --- a/mobile/lib/pages/library/places/places_collection.page.dart +++ b/mobile/lib/pages/library/places/places_collection.page.dart @@ -60,7 +60,7 @@ class PlacesCollectionPage extends HookConsumerWidget { ); }, error: (error, stask) => const Text('Error getting places'), - loading: () => Center(child: const CircularProgressIndicator()), + 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 7f1008c6553fe..82819c94bd229 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 @@ -279,7 +279,7 @@ class SharedLinkEditPage extends HookConsumerWidget { void copyLinkToClipboard() { Clipboard.setData(ClipboardData(text: newShareLink.value)).then((_) { - ScaffoldMessenger.of(context).showSnackBar( + context.scaffoldMessenger.showSnackBar( SnackBar( content: Text( "shared_link_clipboard_copied_massage", diff --git a/mobile/lib/pages/photos/memory.page.dart b/mobile/lib/pages/photos/memory.page.dart index 3f86f5be082c0..74a94ed6ee084 100644 --- a/mobile/lib/pages/photos/memory.page.dart +++ b/mobile/lib/pages/photos/memory.page.dart @@ -113,11 +113,15 @@ class MemoryPage extends HookConsumerWidget { } // Precache the asset + final size = MediaQuery.sizeOf(context); await precacheImage( ImmichImage.imageProvider( asset: asset, + width: size.width, + height: size.height, ), context, + size: size, ); } diff --git a/mobile/lib/pages/photos/photos.page.dart b/mobile/lib/pages/photos/photos.page.dart index 14e5724155da3..30fe1ab3f2939 100644 --- a/mobile/lib/pages/photos/photos.page.dart +++ b/mobile/lib/pages/photos/photos.page.dart @@ -110,12 +110,12 @@ class PhotosPage extends HookConsumerWidget { AnimatedPositioned( duration: const Duration(milliseconds: 300), top: ref.watch(multiselectProvider) - ? -(kToolbarHeight + MediaQuery.of(context).padding.top) + ? -(kToolbarHeight + context.padding.top) : 0, left: 0, right: 0, child: Container( - height: kToolbarHeight + MediaQuery.of(context).padding.top, + height: kToolbarHeight + context.padding.top, color: context.themeData.appBarTheme.backgroundColor, child: const ImmichAppBar(), ), diff --git a/mobile/lib/pages/search/map/map.page.dart b/mobile/lib/pages/search/map/map.page.dart index 3be7e9b3e5374..52ce13f958f24 100644 --- a/mobile/lib/pages/search/map/map.page.dart +++ b/mobile/lib/pages/search/map/map.page.dart @@ -15,6 +15,8 @@ import 'package:immich_mobile/extensions/latlngbounds_extension.dart'; import 'package:immich_mobile/extensions/maplibrecontroller_extensions.dart'; import 'package:immich_mobile/models/map/map_event.model.dart'; import 'package:immich_mobile/models/map/map_marker.model.dart'; +import 'package:immich_mobile/providers/asset_viewer/current_asset.provider.dart'; +import 'package:immich_mobile/providers/asset_viewer/show_controls.provider.dart'; import 'package:immich_mobile/providers/db.provider.dart'; import 'package:immich_mobile/providers/map/map_marker.provider.dart'; import 'package:immich_mobile/providers/map/map_state.provider.dart'; @@ -99,8 +101,11 @@ class MapPage extends HookConsumerWidget { useEffect( () { + final currentAssetLink = + ref.read(currentAssetProvider.notifier).ref.keepAlive(); + loadMarkers(); - return null; + return currentAssetLink.close; }, [], ); @@ -186,6 +191,10 @@ class MapPage extends HookConsumerWidget { GroupAssetsBy.none, ); + ref.read(currentAssetProvider.notifier).set(asset); + if (asset.isVideo) { + ref.read(showControlsProvider.notifier).show = false; + } context.pushRoute( GalleryViewerRoute( initialIndex: 0, @@ -255,7 +264,7 @@ class MapPage extends HookConsumerWidget { selectedAssets.value = selected ? selection : {}; } - return MapThemeOveride( + return MapThemeOverride( mapBuilder: (style) => context.isMobile // Single-column ? Scaffold( @@ -305,7 +314,7 @@ class MapPage extends HookConsumerWidget { ), Positioned( right: 0, - bottom: MediaQuery.paddingOf(context).bottom + 16, + bottom: context.padding.bottom + 16, child: ElevatedButton( onPressed: onZoomToLocation, style: ElevatedButton.styleFrom( diff --git a/mobile/lib/pages/search/map/map_location_picker.page.dart b/mobile/lib/pages/search/map/map_location_picker.page.dart index 2fd1e1ee9edde..487de69a1ee9e 100644 --- a/mobile/lib/pages/search/map/map_location_picker.page.dart +++ b/mobile/lib/pages/search/map/map_location_picker.page.dart @@ -58,7 +58,7 @@ class MapLocationPickerPage extends HookConsumerWidget { controller.value?.animateCamera(CameraUpdate.newLatLng(currentLatLng)); } - return MapThemeOveride( + return MapThemeOverride( mapBuilder: (style) => Builder( builder: (ctx) => Scaffold( backgroundColor: ctx.themeData.cardColor, diff --git a/mobile/lib/pages/search/search.page.dart b/mobile/lib/pages/search/search.page.dart index 83220cff15c58..01119485cfe4e 100644 --- a/mobile/lib/pages/search/search.page.dart +++ b/mobile/lib/pages/search/search.page.dart @@ -187,7 +187,7 @@ class SearchPage extends HookConsumerWidget { showFilterBottomSheet( context: context, isScrollControlled: true, - isDismissible: false, + isDismissible: true, child: FilterBottomSheetScaffold( title: 'search_filter_location_title'.tr(), onSearch: search, @@ -196,7 +196,7 @@ class SearchPage extends HookConsumerWidget { padding: const EdgeInsets.symmetric(vertical: 16.0), child: Container( padding: EdgeInsets.only( - bottom: MediaQuery.of(context).viewInsets.bottom, + bottom: context.viewInsets.bottom, ), child: Padding( padding: const EdgeInsets.symmetric(horizontal: 16.0), @@ -238,7 +238,7 @@ class SearchPage extends HookConsumerWidget { showFilterBottomSheet( context: context, isScrollControlled: true, - isDismissible: false, + isDismissible: true, child: FilterBottomSheetScaffold( title: 'search_filter_camera_title'.tr(), onSearch: search, @@ -499,8 +499,8 @@ class SearchPage extends HookConsumerWidget { controller: textSearchController, decoration: InputDecoration( contentPadding: prefilter != null - ? EdgeInsets.only(left: 24) - : EdgeInsets.all(8), + ? const EdgeInsets.only(left: 24) + : const EdgeInsets.all(8), prefixIcon: prefilter != null ? null : Icon( @@ -647,7 +647,9 @@ class SearchResultGrid extends StatelessWidget { stackEnabled: false, emptyIndicator: Padding( padding: const EdgeInsets.symmetric(horizontal: 16.0), - child: !isSearching ? SearchEmptyContent() : SizedBox.shrink(), + child: !isSearching + ? const SearchEmptyContent() + : const SizedBox.shrink(), ), ), ), @@ -661,29 +663,31 @@ class SearchEmptyContent extends StatelessWidget { @override Widget build(BuildContext context) { - return ListView( - shrinkWrap: true, - physics: NeverScrollableScrollPhysics(), - children: [ - SizedBox(height: 40), - Center( - child: Image.asset( - context.isDarkTheme - ? 'assets/polaroid-dark.png' - : 'assets/polaroid-light.png', - height: 125, + return NotificationListener( + onNotification: (_) => true, + child: ListView( + shrinkWrap: false, + children: [ + const SizedBox(height: 40), + Center( + child: Image.asset( + context.isDarkTheme + ? 'assets/polaroid-dark.png' + : 'assets/polaroid-light.png', + height: 125, + ), ), - ), - SizedBox(height: 16), - Center( - child: Text( - "Search for your photos and videos", - style: context.textTheme.labelLarge, + const SizedBox(height: 16), + Center( + child: Text( + 'search_page_search_photos_videos'.tr(), + style: context.textTheme.labelLarge, + ), ), - ), - SizedBox(height: 32), - QuickLinkList(), - ], + const SizedBox(height: 32), + const QuickLinkList(), + ], + ), ); } } @@ -723,13 +727,13 @@ class QuickLinkList extends StatelessWidget { QuickLink( title: 'videos'.tr(), icon: Icons.play_circle_outline_rounded, - onTap: () => context.pushRoute(AllVideosRoute()), + onTap: () => context.pushRoute(const AllVideosRoute()), ), QuickLink( title: 'favorites'.tr(), icon: Icons.favorite_border_rounded, isBottom: true, - onTap: () => context.pushRoute(FavoritesRoute()), + onTap: () => context.pushRoute(const FavoritesRoute()), ), ], ), diff --git a/mobile/lib/providers/album/album.provider.dart b/mobile/lib/providers/album/album.provider.dart index 53c8855c0a9cf..b3d619a81579a 100644 --- a/mobile/lib/providers/album/album.provider.dart +++ b/mobile/lib/providers/album/album.provider.dart @@ -1,6 +1,7 @@ import 'dart:async'; import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:immich_mobile/constants/enums.dart'; import 'package:immich_mobile/entities/user.entity.dart'; import 'package:immich_mobile/models/albums/album_search.model.dart'; import 'package:immich_mobile/services/album.service.dart'; @@ -106,6 +107,13 @@ class AlbumNotifier extends StateNotifier> { return _albumService.setActivityStatus(album, enabled); } + Future toggleSortOrder(Album album) { + final order = + album.sortOrder == SortOrder.asc ? SortOrder.desc : SortOrder.asc; + + return _albumService.updateSortOrder(album, order); + } + @override void dispose() { _streamSub.cancel(); @@ -135,11 +143,22 @@ final albumWatcher = final albumRenderlistProvider = StreamProvider.autoDispose.family((ref, albumId) { final album = ref.watch(albumWatcher(albumId)).value; + if (album != null) { - final query = - album.assets.filter().isTrashedEqualTo(false).sortByFileCreatedAtDesc(); - return renderListGeneratorWithGroupBy(query, GroupAssetsBy.none); + final query = album.assets.filter().isTrashedEqualTo(false); + if (album.sortOrder == SortOrder.asc) { + return renderListGeneratorWithGroupBy( + query.sortByFileCreatedAt(), + GroupAssetsBy.none, + ); + } else if (album.sortOrder == SortOrder.desc) { + return renderListGeneratorWithGroupBy( + query.sortByFileCreatedAtDesc(), + GroupAssetsBy.none, + ); + } } + return const Stream.empty(); }); diff --git a/mobile/lib/providers/album/album_sort_by_options.provider.dart b/mobile/lib/providers/album/album_sort_by_options.provider.dart index 216688ee15804..cafde372530c9 100644 --- a/mobile/lib/providers/album/album_sort_by_options.provider.dart +++ b/mobile/lib/providers/album/album_sort_by_options.provider.dart @@ -39,12 +39,21 @@ class _AlbumSortHandlers { static const AlbumSortFn mostRecent = _sortByMostRecent; static List _sortByMostRecent(List albums, bool isReverse) { final sorted = albums.sorted((a, b) { - if (a.endDate != null && b.endDate != null) { - return a.endDate!.compareTo(b.endDate!); + if (a.endDate == null && b.endDate == null) { + return 0; } - if (a.endDate == null) return 1; - if (b.endDate == null) return -1; - return 0; + + if (a.endDate == null) { + // Put nulls at the end for recent sorting + return 1; + } + + if (b.endDate == null) { + return -1; + } + + // Sort by descending recent date + return b.endDate!.compareTo(a.endDate!); }); return (isReverse ? sorted.reversed : sorted).toList(); } diff --git a/mobile/lib/providers/app_life_cycle.provider.dart b/mobile/lib/providers/app_life_cycle.provider.dart index c06a99da35b62..780e22b818d7e 100644 --- a/mobile/lib/providers/app_life_cycle.provider.dart +++ b/mobile/lib/providers/app_life_cycle.provider.dart @@ -1,3 +1,4 @@ +import 'package:flutter/foundation.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/providers/album/album.provider.dart'; import 'package:immich_mobile/services/background.service.dart'; @@ -5,7 +6,7 @@ import 'package:immich_mobile/models/backup/backup_state.model.dart'; import 'package:immich_mobile/providers/backup/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/authentication.provider.dart'; +import 'package:immich_mobile/providers/auth.provider.dart'; import 'package:immich_mobile/providers/memory.provider.dart'; import 'package:immich_mobile/providers/gallery_permission.provider.dart'; import 'package:immich_mobile/providers/notification_permission.provider.dart'; @@ -35,43 +36,60 @@ class AppLifeCycleNotifier extends StateNotifier { return state; } - void handleAppResume() { + void handleAppResume() async { state = AppLifeCycleEnum.resumed; // no need to resume because app was never really paused if (!_wasPaused) return; _wasPaused = false; - final isAuthenticated = _ref.read(authenticationProvider).isAuthenticated; + final isAuthenticated = _ref.read(authProvider).isAuthenticated; // Needs to be logged in if (isAuthenticated) { + // switch endpoint if needed + final endpoint = + await _ref.read(authProvider.notifier).setOpenApiServiceEndpoint(); + if (kDebugMode) { + debugPrint("Using server URL: $endpoint"); + } + final permission = _ref.watch(galleryPermissionNotifier); if (permission.isGranted || permission.isLimited) { - _ref.read(backupProvider.notifier).resumeBackup(); - _ref.read(backgroundServiceProvider).resumeServiceIfEnabled(); + await _ref.read(backupProvider.notifier).resumeBackup(); + await _ref.read(backgroundServiceProvider).resumeServiceIfEnabled(); } - _ref.read(serverInfoProvider.notifier).getServerVersion(); + + await _ref.read(serverInfoProvider.notifier).getServerVersion(); + switch (_ref.read(tabProvider)) { case TabEnum.home: - _ref.read(assetProvider.notifier).getAllAsset(); + await _ref.read(assetProvider.notifier).getAllAsset(); + break; case TabEnum.search: - // nothing to do + // nothing to do + break; + case TabEnum.albums: - _ref.read(albumProvider.notifier).refreshRemoteAlbums(); + await _ref.read(albumProvider.notifier).refreshRemoteAlbums(); + break; case TabEnum.library: - // nothing to do + // nothing to do + break; } } _ref.read(websocketProvider.notifier).connect(); - _ref + await _ref .read(notificationPermissionProvider.notifier) .getNotificationPermission(); - _ref.read(galleryPermissionNotifier.notifier).getGalleryPermissionStatus(); - _ref.read(iOSBackgroundSettingsProvider.notifier).refresh(); + await _ref + .read(galleryPermissionNotifier.notifier) + .getGalleryPermissionStatus(); + + await _ref.read(iOSBackgroundSettingsProvider.notifier).refresh(); _ref.invalidate(memoryFutureProvider); } @@ -85,7 +103,7 @@ class AppLifeCycleNotifier extends StateNotifier { state = AppLifeCycleEnum.paused; _wasPaused = true; - if (_ref.read(authenticationProvider).isAuthenticated) { + if (_ref.read(authProvider).isAuthenticated) { // Do not cancel backup if manual upload is in progress if (_ref.read(backupProvider.notifier).backupProgress != BackUpProgressEnum.manualInProgress) { diff --git a/mobile/lib/providers/asset.provider.dart b/mobile/lib/providers/asset.provider.dart index c7e75df79b27f..9252de01bfa72 100644 --- a/mobile/lib/providers/asset.provider.dart +++ b/mobile/lib/providers/asset.provider.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:immich_mobile/providers/locale_provider.dart'; import 'package:immich_mobile/providers/memory.provider.dart'; import 'package:immich_mobile/repositories/asset_media.repository.dart'; import 'package:immich_mobile/services/album.service.dart'; @@ -84,34 +85,48 @@ class AssetNotifier extends StateNotifier { _deleteInProgress = true; state = true; try { + // Filter the assets based on the backed-up status final assets = onlyBackedUp ? deleteAssets.where((e) => e.storage == AssetState.merged) : deleteAssets; + + if (assets.isEmpty) { + return false; // No assets to delete + } + + // Proceed with local deletion of the filtered assets final localDeleted = await _deleteLocalAssets(assets); + if (localDeleted.isNotEmpty) { - final localOnlyIds = deleteAssets + final localOnlyIds = assets .where((e) => e.storage == AssetState.local) .map((e) => e.id) .toList(); - // Update merged assets to remote only + + // Update merged assets to remote-only final mergedAssets = - deleteAssets.where((e) => e.storage == AssetState.merged).map((e) { + assets.where((e) => e.storage == AssetState.merged).map((e) { e.localId = null; return e; }).toList(); + + // Update the local database await _db.writeTxn(() async { if (mergedAssets.isNotEmpty) { - await _db.assets.putAll(mergedAssets); + await _db.assets + .putAll(mergedAssets); // Use the filtered merged assets } await _db.exifInfos.deleteAll(localOnlyIds); await _db.assets.deleteAll(localOnlyIds); }); + return true; } } finally { _deleteInProgress = false; state = false; } + return false; } @@ -314,24 +329,31 @@ final assetWatcher = return db.assets.watchObject(asset.id, fireImmediately: true); }); -final assetsProvider = StreamProvider.family((ref, userId) { - if (userId == null) return const Stream.empty(); - final query = _commonFilterAndSort( - _assets(ref).where().ownerIdEqualToAnyChecksum(userId), - ); - return renderListGenerator(query, ref); -}); +final assetsProvider = StreamProvider.family( + (ref, userId) { + if (userId == null) return const Stream.empty(); + ref.watch(localeProvider); + final query = _commonFilterAndSort( + _assets(ref).where().ownerIdEqualToAnyChecksum(userId), + ); + return renderListGenerator(query, ref); + }, + dependencies: [localeProvider], +); -final multiUserAssetsProvider = - StreamProvider.family>((ref, userIds) { - if (userIds.isEmpty) return const Stream.empty(); - final query = _commonFilterAndSort( - _assets(ref) - .where() - .anyOf(userIds, (q, u) => q.ownerIdEqualToAnyChecksum(u)), - ); - return renderListGenerator(query, ref); -}); +final multiUserAssetsProvider = StreamProvider.family>( + (ref, userIds) { + if (userIds.isEmpty) return const Stream.empty(); + ref.watch(localeProvider); + final query = _commonFilterAndSort( + _assets(ref) + .where() + .anyOf(userIds, (q, u) => q.ownerIdEqualToAnyChecksum(u)), + ); + return renderListGenerator(query, ref); + }, + dependencies: [localeProvider], +); QueryBuilder? getRemoteAssetQuery(WidgetRef ref) { final userId = ref.watch(currentUserProvider)?.isarId; diff --git a/mobile/lib/providers/asset_viewer/asset_stack.provider.dart b/mobile/lib/providers/asset_viewer/asset_stack.provider.dart index c3e4414b3935a..407aef16109e1 100644 --- a/mobile/lib/providers/asset_viewer/asset_stack.provider.dart +++ b/mobile/lib/providers/asset_viewer/asset_stack.provider.dart @@ -7,49 +7,49 @@ import 'package:riverpod_annotation/riverpod_annotation.dart'; part 'asset_stack.provider.g.dart'; class AssetStackNotifier extends StateNotifier> { - final Asset _asset; + final String _stackId; final Ref _ref; - AssetStackNotifier( - this._asset, - this._ref, - ) : super([]) { - fetchStackChildren(); + AssetStackNotifier(this._stackId, this._ref) : super([]) { + _fetchStack(_stackId); } - void fetchStackChildren() async { - if (mounted) { - state = await _ref.read(assetStackProvider(_asset).future); + void _fetchStack(String stackId) async { + if (!mounted) { + return; + } + + final stack = await _ref.read(assetStackProvider(stackId).future); + if (stack.isNotEmpty) { + state = stack; } } void removeChild(int index) { if (index < state.length) { state.removeAt(index); + state = List.from(state); } } } final assetStackStateProvider = StateNotifierProvider.autoDispose - .family, Asset>( - (ref, asset) => AssetStackNotifier(asset, ref), + .family, String>( + (ref, stackId) => AssetStackNotifier(stackId, ref), ); final assetStackProvider = - FutureProvider.autoDispose.family, Asset>((ref, asset) async { - // Guard [local asset] - if (asset.remoteId == null) { - return []; - } - - return await ref + FutureProvider.autoDispose.family, String>((ref, stackId) { + return ref .watch(dbProvider) .assets .filter() .isArchivedEqualTo(false) .isTrashedEqualTo(false) - .stackPrimaryAssetIdEqualTo(asset.remoteId) - .sortByFileCreatedAtDesc() + .stackIdEqualTo(stackId) + // orders primary asset first as its ID is null + .sortByStackPrimaryAssetId() + .thenByFileCreatedAtDesc() .findAll(); }); diff --git a/mobile/lib/providers/asset_viewer/is_motion_video_playing.provider.dart b/mobile/lib/providers/asset_viewer/is_motion_video_playing.provider.dart new file mode 100644 index 0000000000000..4af061f9548c1 --- /dev/null +++ b/mobile/lib/providers/asset_viewer/is_motion_video_playing.provider.dart @@ -0,0 +1,23 @@ +import 'package:hooks_riverpod/hooks_riverpod.dart'; + +/// Whether to display the video part of a motion photo +final isPlayingMotionVideoProvider = + StateNotifierProvider((ref) { + return IsPlayingMotionVideo(ref); +}); + +class IsPlayingMotionVideo extends StateNotifier { + IsPlayingMotionVideo(this.ref) : super(false); + + final Ref ref; + + bool get playing => state; + + set playing(bool value) { + state = value; + } + + void toggle() { + state = !state; + } +} diff --git a/mobile/lib/providers/asset_viewer/render_list_status_provider.dart b/mobile/lib/providers/asset_viewer/render_list_status_provider.dart new file mode 100644 index 0000000000000..903007031ea66 --- /dev/null +++ b/mobile/lib/providers/asset_viewer/render_list_status_provider.dart @@ -0,0 +1,20 @@ +import 'package:hooks_riverpod/hooks_riverpod.dart'; + +enum RenderListStatusEnum { complete, empty, error, loading } + +final renderListStatusProvider = + StateNotifierProvider((ref) { + return RenderListStatus(ref); +}); + +class RenderListStatus extends StateNotifier { + RenderListStatus(this.ref) : super(RenderListStatusEnum.complete); + + final Ref ref; + + RenderListStatusEnum get status => state; + + set status(RenderListStatusEnum value) { + state = value; + } +} diff --git a/mobile/lib/providers/asset_viewer/video_player_controller_provider.dart b/mobile/lib/providers/asset_viewer/video_player_controller_provider.dart deleted file mode 100644 index 969e181cbb0ad..0000000000000 --- a/mobile/lib/providers/asset_viewer/video_player_controller_provider.dart +++ /dev/null @@ -1,46 +0,0 @@ -import 'package:immich_mobile/entities/asset.entity.dart'; -import 'package:immich_mobile/entities/store.entity.dart'; -import 'package:immich_mobile/services/api.service.dart'; -import 'package:riverpod_annotation/riverpod_annotation.dart'; -import 'package:video_player/video_player.dart'; - -part 'video_player_controller_provider.g.dart'; - -@riverpod -Future videoPlayerController( - VideoPlayerControllerRef ref, { - required Asset asset, -}) async { - late VideoPlayerController controller; - if (asset.isLocal && asset.livePhotoVideoId == null) { - // Use a local file for the video player controller - final file = await asset.local!.file; - if (file == null) { - throw Exception('No file found for the video'); - } - controller = VideoPlayerController.file(file); - } else { - // Use a network URL for the video player controller - final serverEndpoint = Store.get(StoreKey.serverEndpoint); - final String videoUrl = asset.livePhotoVideoId != null - ? '$serverEndpoint/assets/${asset.livePhotoVideoId}/video/playback' - : '$serverEndpoint/assets/${asset.remoteId}/video/playback'; - - final url = Uri.parse(videoUrl); - controller = VideoPlayerController.networkUrl( - url, - httpHeaders: ApiService.getRequestHeaders(), - videoPlayerOptions: asset.livePhotoVideoId != null - ? VideoPlayerOptions(mixWithOthers: true) - : VideoPlayerOptions(mixWithOthers: false), - ); - } - - await controller.initialize(); - - ref.onDispose(() { - controller.dispose(); - }); - - return controller; -} diff --git a/mobile/lib/providers/asset_viewer/video_player_controller_provider.g.dart b/mobile/lib/providers/asset_viewer/video_player_controller_provider.g.dart deleted file mode 100644 index 00ad37648a85e..0000000000000 --- a/mobile/lib/providers/asset_viewer/video_player_controller_provider.g.dart +++ /dev/null @@ -1,164 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -part of 'video_player_controller_provider.dart'; - -// ************************************************************************** -// RiverpodGenerator -// ************************************************************************** - -String _$videoPlayerControllerHash() => - r'84b2961cc2aeaf9d03255dbf9b9484619d0c24f5'; - -/// Copied from Dart SDK -class _SystemHash { - _SystemHash._(); - - static int combine(int hash, int value) { - // ignore: parameter_assignments - hash = 0x1fffffff & (hash + value); - // ignore: parameter_assignments - hash = 0x1fffffff & (hash + ((0x0007ffff & hash) << 10)); - return hash ^ (hash >> 6); - } - - static int finish(int hash) { - // ignore: parameter_assignments - hash = 0x1fffffff & (hash + ((0x03ffffff & hash) << 3)); - // ignore: parameter_assignments - hash = hash ^ (hash >> 11); - return 0x1fffffff & (hash + ((0x00003fff & hash) << 15)); - } -} - -/// See also [videoPlayerController]. -@ProviderFor(videoPlayerController) -const videoPlayerControllerProvider = VideoPlayerControllerFamily(); - -/// See also [videoPlayerController]. -class VideoPlayerControllerFamily - extends Family> { - /// See also [videoPlayerController]. - const VideoPlayerControllerFamily(); - - /// See also [videoPlayerController]. - VideoPlayerControllerProvider call({ - required Asset asset, - }) { - return VideoPlayerControllerProvider( - asset: asset, - ); - } - - @override - VideoPlayerControllerProvider getProviderOverride( - covariant VideoPlayerControllerProvider provider, - ) { - return call( - asset: provider.asset, - ); - } - - static const Iterable? _dependencies = null; - - @override - Iterable? get dependencies => _dependencies; - - static const Iterable? _allTransitiveDependencies = null; - - @override - Iterable? get allTransitiveDependencies => - _allTransitiveDependencies; - - @override - String? get name => r'videoPlayerControllerProvider'; -} - -/// See also [videoPlayerController]. -class VideoPlayerControllerProvider - extends AutoDisposeFutureProvider { - /// See also [videoPlayerController]. - VideoPlayerControllerProvider({ - required Asset asset, - }) : this._internal( - (ref) => videoPlayerController( - ref as VideoPlayerControllerRef, - asset: asset, - ), - from: videoPlayerControllerProvider, - name: r'videoPlayerControllerProvider', - debugGetCreateSourceHash: - const bool.fromEnvironment('dart.vm.product') - ? null - : _$videoPlayerControllerHash, - dependencies: VideoPlayerControllerFamily._dependencies, - allTransitiveDependencies: - VideoPlayerControllerFamily._allTransitiveDependencies, - asset: asset, - ); - - VideoPlayerControllerProvider._internal( - super._createNotifier, { - required super.name, - required super.dependencies, - required super.allTransitiveDependencies, - required super.debugGetCreateSourceHash, - required super.from, - required this.asset, - }) : super.internal(); - - final Asset asset; - - @override - Override overrideWith( - FutureOr Function(VideoPlayerControllerRef provider) - create, - ) { - return ProviderOverride( - origin: this, - override: VideoPlayerControllerProvider._internal( - (ref) => create(ref as VideoPlayerControllerRef), - from: from, - name: null, - dependencies: null, - allTransitiveDependencies: null, - debugGetCreateSourceHash: null, - asset: asset, - ), - ); - } - - @override - AutoDisposeFutureProviderElement createElement() { - return _VideoPlayerControllerProviderElement(this); - } - - @override - bool operator ==(Object other) { - return other is VideoPlayerControllerProvider && other.asset == asset; - } - - @override - int get hashCode { - var hash = _SystemHash.combine(0, runtimeType.hashCode); - hash = _SystemHash.combine(hash, asset.hashCode); - - return _SystemHash.finish(hash); - } -} - -mixin VideoPlayerControllerRef - on AutoDisposeFutureProviderRef { - /// The parameter `asset` of this provider. - Asset get asset; -} - -class _VideoPlayerControllerProviderElement - extends AutoDisposeFutureProviderElement - with VideoPlayerControllerRef { - _VideoPlayerControllerProviderElement(super.provider); - - @override - Asset get asset => (origin as VideoPlayerControllerProvider).asset; -} -// ignore_for_file: type=lint -// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member diff --git a/mobile/lib/providers/asset_viewer/video_player_controls_provider.dart b/mobile/lib/providers/asset_viewer/video_player_controls_provider.dart index d15b26ea20994..69be91480ffc2 100644 --- a/mobile/lib/providers/asset_viewer/video_player_controls_provider.dart +++ b/mobile/lib/providers/asset_viewer/video_player_controls_provider.dart @@ -1,15 +1,16 @@ import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:immich_mobile/providers/asset_viewer/video_player_value_provider.dart'; class VideoPlaybackControls { - VideoPlaybackControls({ + const VideoPlaybackControls({ required this.position, - required this.mute, required this.pause, + this.restarted = false, }); final double position; - final bool mute; final bool pause; + final bool restarted; } final videoPlayerControlsProvider = @@ -17,15 +18,11 @@ final videoPlayerControlsProvider = return VideoPlayerControls(ref); }); +const videoPlayerControlsDefault = + VideoPlaybackControls(position: 0, pause: false); + class VideoPlayerControls extends StateNotifier { - VideoPlayerControls(this.ref) - : super( - VideoPlaybackControls( - position: 0, - pause: false, - mute: false, - ), - ); + VideoPlayerControls(this.ref) : super(videoPlayerControlsDefault); final Ref ref; @@ -36,75 +33,48 @@ class VideoPlayerControls extends StateNotifier { } void reset() { - state = VideoPlaybackControls( - position: 0, - pause: false, - mute: false, - ); + state = videoPlayerControlsDefault; } double get position => state.position; - bool get mute => state.mute; + bool get paused => state.pause; set position(double value) { - state = VideoPlaybackControls( - position: value, - mute: state.mute, - pause: state.pause, - ); - } - - set mute(bool value) { - state = VideoPlaybackControls( - position: state.position, - mute: value, - pause: state.pause, - ); - } + if (state.position == value) { + return; + } - void toggleMute() { - state = VideoPlaybackControls( - position: state.position, - mute: !state.mute, - pause: state.pause, - ); + state = VideoPlaybackControls(position: value, pause: state.pause); } void pause() { - state = VideoPlaybackControls( - position: state.position, - mute: state.mute, - pause: true, - ); + if (state.pause) { + return; + } + + state = VideoPlaybackControls(position: state.position, pause: true); } void play() { - state = VideoPlaybackControls( - position: state.position, - mute: state.mute, - pause: false, - ); + if (!state.pause) { + return; + } + + state = VideoPlaybackControls(position: state.position, pause: false); } void togglePlay() { - state = VideoPlaybackControls( - position: state.position, - mute: state.mute, - pause: !state.pause, - ); + state = + VideoPlaybackControls(position: state.position, pause: !state.pause); } void restart() { - state = VideoPlaybackControls( - position: 0, - mute: state.mute, - pause: true, - ); - - state = VideoPlaybackControls( - position: 0, - mute: state.mute, - pause: false, - ); + state = + const VideoPlaybackControls(position: 0, pause: false, restarted: true); + ref.read(videoPlaybackValueProvider.notifier).value = + ref.read(videoPlaybackValueProvider.notifier).value.copyWith( + state: VideoPlaybackState.playing, + position: Duration.zero, + ); } } diff --git a/mobile/lib/providers/asset_viewer/video_player_value_provider.dart b/mobile/lib/providers/asset_viewer/video_player_value_provider.dart index ebdf739ef03de..1a3c54e9e9293 100644 --- a/mobile/lib/providers/asset_viewer/video_player_value_provider.dart +++ b/mobile/lib/providers/asset_viewer/video_player_value_provider.dart @@ -1,5 +1,5 @@ import 'package:hooks_riverpod/hooks_riverpod.dart'; -import 'package:video_player/video_player.dart'; +import 'package:native_video_player/native_video_player.dart'; enum VideoPlaybackState { initializing, @@ -22,56 +22,66 @@ class VideoPlaybackValue { /// The volume of the video final double volume; - VideoPlaybackValue({ + const VideoPlaybackValue({ required this.position, required this.duration, required this.state, required this.volume, }); - factory VideoPlaybackValue.fromController(VideoPlayerController? controller) { - final video = controller?.value; - late VideoPlaybackState s; - if (video == null) { - s = VideoPlaybackState.initializing; - } else if (video.isCompleted) { - s = VideoPlaybackState.completed; - } else if (video.isPlaying) { - s = VideoPlaybackState.playing; - } else if (video.isBuffering) { - s = VideoPlaybackState.buffering; - } else { - s = VideoPlaybackState.paused; + factory VideoPlaybackValue.fromNativeController( + NativeVideoPlayerController controller, + ) { + final playbackInfo = controller.playbackInfo; + final videoInfo = controller.videoInfo; + + if (playbackInfo == null || videoInfo == null) { + return videoPlaybackValueDefault; } + final VideoPlaybackState status = switch (playbackInfo.status) { + PlaybackStatus.playing => VideoPlaybackState.playing, + PlaybackStatus.paused => VideoPlaybackState.paused, + PlaybackStatus.stopped => VideoPlaybackState.completed, + }; + return VideoPlaybackValue( - position: video?.position ?? Duration.zero, - duration: video?.duration ?? Duration.zero, - state: s, - volume: video?.volume ?? 0.0, + position: Duration(seconds: playbackInfo.position), + duration: Duration(seconds: videoInfo.duration), + state: status, + volume: playbackInfo.volume, ); } - factory VideoPlaybackValue.uninitialized() { + VideoPlaybackValue copyWith({ + Duration? position, + Duration? duration, + VideoPlaybackState? state, + double? volume, + }) { return VideoPlaybackValue( - position: Duration.zero, - duration: Duration.zero, - state: VideoPlaybackState.initializing, - volume: 0.0, + position: position ?? this.position, + duration: duration ?? this.duration, + state: state ?? this.state, + volume: volume ?? this.volume, ); } } +const VideoPlaybackValue videoPlaybackValueDefault = VideoPlaybackValue( + position: Duration.zero, + duration: Duration.zero, + state: VideoPlaybackState.initializing, + volume: 0.0, +); + final videoPlaybackValueProvider = StateNotifierProvider((ref) { return VideoPlaybackValueState(ref); }); class VideoPlaybackValueState extends StateNotifier { - VideoPlaybackValueState(this.ref) - : super( - VideoPlaybackValue.uninitialized(), - ); + VideoPlaybackValueState(this.ref) : super(videoPlaybackValueDefault); final Ref ref; @@ -82,6 +92,7 @@ class VideoPlaybackValueState extends StateNotifier { } set position(Duration value) { + if (state.position == value) return; state = VideoPlaybackValue( position: value, duration: state.duration, @@ -89,4 +100,18 @@ class VideoPlaybackValueState extends StateNotifier { volume: state.volume, ); } + + set status(VideoPlaybackState value) { + if (state.state == value) return; + state = VideoPlaybackValue( + position: state.position, + duration: state.duration, + state: value, + volume: state.volume, + ); + } + + void reset() { + state = videoPlaybackValueDefault; + } } diff --git a/mobile/lib/providers/auth.provider.dart b/mobile/lib/providers/auth.provider.dart new file mode 100644 index 0000000000000..a23ffd3d68a2a --- /dev/null +++ b/mobile/lib/providers/auth.provider.dart @@ -0,0 +1,205 @@ +import 'package:flutter/foundation.dart'; +import 'package:flutter_udid/flutter_udid.dart'; +import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:immich_mobile/entities/store.entity.dart'; +import 'package:immich_mobile/models/auth/login_response.model.dart'; +import 'package:immich_mobile/models/auth/auth_state.model.dart'; +import 'package:immich_mobile/entities/user.entity.dart'; +import 'package:immich_mobile/providers/api.provider.dart'; +import 'package:immich_mobile/services/api.service.dart'; +import 'package:immich_mobile/services/auth.service.dart'; +import 'package:immich_mobile/utils/hash.dart'; +import 'package:logging/logging.dart'; +import 'package:openapi/api.dart'; + +final authProvider = StateNotifierProvider((ref) { + return AuthNotifier( + ref.watch(authServiceProvider), + ref.watch(apiServiceProvider), + ); +}); + +class AuthNotifier extends StateNotifier { + final AuthService _authService; + final ApiService _apiService; + final _log = Logger("AuthenticationNotifier"); + + static const Duration _timeoutDuration = Duration(seconds: 7); + + AuthNotifier( + this._authService, + this._apiService, + ) : super( + AuthState( + deviceId: "", + userId: "", + userEmail: "", + name: '', + profileImagePath: '', + isAdmin: false, + isAuthenticated: false, + ), + ); + + Future validateServerUrl(String url) { + return _authService.validateServerUrl(url); + } + + /// Validating the url is the alternative connecting server url without + /// saving the infomation to the local database + Future validateAuxilaryServerUrl(String url) async { + try { + final validEndpoint = await _apiService.resolveEndpoint(url); + return await _authService.validateAuxilaryServerUrl(validEndpoint); + } catch (_) { + return false; + } + } + + Future login(String email, String password) async { + final response = await _authService.login(email, password); + await saveAuthInfo(accessToken: response.accessToken); + return response; + } + + Future logout() async { + try { + await _authService.logout(); + } finally { + await _cleanUp(); + } + } + + Future _cleanUp() async { + state = AuthState( + deviceId: "", + userId: "", + userEmail: "", + name: '', + profileImagePath: '', + isAdmin: false, + isAuthenticated: false, + ); + } + + void updateUserProfileImagePath(String path) { + state = state.copyWith(profileImagePath: path); + } + + Future changePassword(String newPassword) async { + try { + await _authService.changePassword(newPassword); + return true; + } catch (_) { + return false; + } + } + + Future saveAuthInfo({ + required String accessToken, + }) async { + _apiService.setAccessToken(accessToken); + + // Get the deviceid from the store if it exists, otherwise generate a new one + String deviceId = + Store.tryGet(StoreKey.deviceId) ?? await FlutterUdid.consistentUdid; + + User? user = Store.tryGet(StoreKey.currentUser); + + UserAdminResponseDto? userResponse; + UserPreferencesResponseDto? userPreferences; + try { + final responses = await Future.wait([ + _apiService.usersApi.getMyUser().timeout(_timeoutDuration), + _apiService.usersApi.getMyPreferences().timeout(_timeoutDuration), + ]); + userResponse = responses[0] as UserAdminResponseDto; + userPreferences = responses[1] as UserPreferencesResponseDto; + } on ApiException catch (error, stackTrace) { + if (error.code == 401) { + _log.severe("Unauthorized access, token likely expired. Logging out."); + return false; + } + _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", + ); + } + } + + // If the user information is successfully retrieved, update the store + // Due to the flow of the code, this will always happen on first login + if (userResponse != null) { + Store.put(StoreKey.deviceId, deviceId); + Store.put(StoreKey.deviceIdHash, fastHash(deviceId)); + Store.put( + StoreKey.currentUser, + User.fromUserDto(userResponse, userPreferences), + ); + Store.put(StoreKey.accessToken, accessToken); + + user = User.fromUserDto(userResponse, userPreferences); + } else { + _log.severe("Unable to get user information from the server."); + } + + // If the user is null, the login was not successful + // and we don't have a local copy of the user from a prior successful login + if (user == null) { + return false; + } + + state = state.copyWith( + isAuthenticated: true, + userId: user.id, + userEmail: user.email, + name: user.name, + profileImagePath: user.profileImagePath, + isAdmin: user.isAdmin, + deviceId: deviceId, + ); + + return true; + } + + Future saveWifiName(String wifiName) { + return Store.put(StoreKey.preferredWifiName, wifiName); + } + + Future saveLocalEndpoint(String url) { + return Store.put(StoreKey.localEndpoint, url); + } + + String? getSavedWifiName() { + return Store.tryGet(StoreKey.preferredWifiName); + } + + String? getSavedLocalEndpoint() { + return Store.tryGet(StoreKey.localEndpoint); + } + + /// Returns the current server endpoint (with /api) URL from the store + String? getServerEndpoint() { + return Store.tryGet(StoreKey.serverEndpoint); + } + + /// Returns the current server URL (input by the user) from the store + String? getServerUrl() { + return Store.tryGet(StoreKey.serverUrl); + } + + Future setOpenApiServiceEndpoint() { + return _authService.setOpenApiServiceEndpoint(); + } +} diff --git a/mobile/lib/providers/authentication.provider.dart b/mobile/lib/providers/authentication.provider.dart deleted file mode 100644 index 1fe7db5d46f42..0000000000000 --- a/mobile/lib/providers/authentication.provider.dart +++ /dev/null @@ -1,244 +0,0 @@ -import 'dart:io'; - -import 'package:device_info_plus/device_info_plus.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_udid/flutter_udid.dart'; -import 'package:hooks_riverpod/hooks_riverpod.dart'; -import 'package:immich_mobile/providers/album/album.provider.dart'; -import 'package:immich_mobile/entities/store.entity.dart'; -import 'package:immich_mobile/models/authentication/authentication_state.model.dart'; -import 'package:immich_mobile/entities/user.entity.dart'; -import 'package:immich_mobile/providers/api.provider.dart'; -import 'package:immich_mobile/providers/db.provider.dart'; -import 'package:immich_mobile/services/api.service.dart'; -import 'package:immich_mobile/utils/db.dart'; -import 'package:immich_mobile/utils/hash.dart'; -import 'package:isar/isar.dart'; -import 'package:logging/logging.dart'; -import 'package:openapi/api.dart'; - -class AuthenticationNotifier extends StateNotifier { - AuthenticationNotifier( - this._apiService, - this._db, - this._ref, - ) : super( - AuthenticationState( - deviceId: "", - userId: "", - userEmail: "", - name: '', - profileImagePath: '', - isAdmin: false, - shouldChangePassword: false, - isAuthenticated: false, - ), - ); - - final ApiService _apiService; - final Isar _db; - final StateNotifierProviderRef - _ref; - final _log = Logger("AuthenticationNotifier"); - - Future login( - String email, - String password, - String serverUrl, - ) async { - try { - // Resolve API server endpoint from user provided serverUrl - await _apiService.resolveAndSetEndpoint(serverUrl); - await _apiService.serverInfoApi.pingServer(); - } catch (e) { - debugPrint('Invalid Server Endpoint Url $e'); - return false; - } - - // Make sign-in request - DeviceInfoPlugin deviceInfoPlugin = DeviceInfoPlugin(); - - if (Platform.isIOS) { - var iosInfo = await deviceInfoPlugin.iosInfo; - _apiService.authenticationApi.apiClient - .addDefaultHeader('deviceModel', iosInfo.utsname.machine); - _apiService.authenticationApi.apiClient - .addDefaultHeader('deviceType', 'iOS'); - } else { - var androidInfo = await deviceInfoPlugin.androidInfo; - _apiService.authenticationApi.apiClient - .addDefaultHeader('deviceModel', androidInfo.model); - _apiService.authenticationApi.apiClient - .addDefaultHeader('deviceType', 'Android'); - } - - try { - var loginResponse = await _apiService.authenticationApi.login( - LoginCredentialDto( - email: email, - password: password, - ), - ); - - if (loginResponse == null) { - debugPrint('Login Response is null'); - return false; - } - - return setSuccessLoginInfo( - accessToken: loginResponse.accessToken, - serverUrl: serverUrl, - ); - } catch (e) { - debugPrint("Error logging in $e"); - return false; - } - } - - Future logout() async { - var log = Logger('AuthenticationNotifier'); - try { - String? userEmail = Store.tryGet(StoreKey.currentUser)?.email; - - await _apiService.authenticationApi - .logout() - .then((_) => log.info("Logout was successful for $userEmail")) - .onError( - (error, stackTrace) => - log.severe("Logout failed for $userEmail", error, stackTrace), - ); - - await Future.wait([ - clearAssetsAndAlbums(_db), - Store.delete(StoreKey.currentUser), - Store.delete(StoreKey.accessToken), - ]); - _ref.invalidate(albumProvider); - - state = state.copyWith( - deviceId: "", - userId: "", - userEmail: "", - name: '', - profileImagePath: '', - isAdmin: false, - shouldChangePassword: false, - isAuthenticated: false, - ); - } catch (e, stack) { - log.severe('Logout failed', e, stack); - } - } - - updateUserProfileImagePath(String path) { - state = state.copyWith(profileImagePath: path); - } - - Future changePassword(String newPassword) async { - try { - await _apiService.usersApi.updateMyUser( - UserUpdateMeDto( - password: newPassword, - ), - ); - - state = state.copyWith(shouldChangePassword: false); - - return true; - } catch (e) { - debugPrint("Error changing password $e"); - return false; - } - } - - Future setSuccessLoginInfo({ - required String accessToken, - required String serverUrl, - }) async { - _apiService.setAccessToken(accessToken); - - // Get the deviceid from the store if it exists, otherwise generate a new one - String deviceId = - Store.tryGet(StoreKey.deviceId) ?? await FlutterUdid.consistentUdid; - - bool shouldChangePassword = false; - User? user = Store.tryGet(StoreKey.currentUser); - - UserAdminResponseDto? userResponse; - UserPreferencesResponseDto? userPreferences; - try { - final responses = await Future.wait([ - _apiService.usersApi.getMyUser().timeout(const Duration(seconds: 7)), - _apiService.usersApi - .getMyPreferences() - .timeout(const Duration(seconds: 7)), - ]); - userResponse = responses[0] as UserAdminResponseDto; - userPreferences = responses[1] as UserPreferencesResponseDto; - } on ApiException catch (error, stackTrace) { - if (error.code == 401) { - _log.severe("Unauthorized access, token likely expired. Logging out."); - return false; - } - _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, - ); - debugPrint( - "Error getting user information from the server [CATCH ALL] $error $stackTrace", - ); - } - - // If the user information is successfully retrieved, update the store - // Due to the flow of the code, this will always happen on first login - if (userResponse != null) { - Store.put(StoreKey.deviceId, deviceId); - Store.put(StoreKey.deviceIdHash, fastHash(deviceId)); - Store.put( - StoreKey.currentUser, - User.fromUserDto(userResponse, userPreferences), - ); - Store.put(StoreKey.serverUrl, serverUrl); - Store.put(StoreKey.accessToken, accessToken); - - shouldChangePassword = userResponse.shouldChangePassword; - user = User.fromUserDto(userResponse, userPreferences); - } else { - _log.severe("Unable to get user information from the server."); - } - - // If the user is null, the login was not successful - // and we don't have a local copy of the user from a prior successful login - if (user == null) { - return false; - } - - state = state.copyWith( - isAuthenticated: true, - userId: user.id, - userEmail: user.email, - name: user.name, - profileImagePath: user.profileImagePath, - isAdmin: user.isAdmin, - shouldChangePassword: shouldChangePassword, - deviceId: deviceId, - ); - - return true; - } -} - -final authenticationProvider = - StateNotifierProvider((ref) { - return AuthenticationNotifier( - ref.watch(apiServiceProvider), - ref.watch(dbProvider), - ref, - ); -}); diff --git a/mobile/lib/providers/backup/backup.provider.dart b/mobile/lib/providers/backup/backup.provider.dart index dc6d2f7cc89cb..aab367485c206 100644 --- a/mobile/lib/providers/backup/backup.provider.dart +++ b/mobile/lib/providers/backup/backup.provider.dart @@ -22,8 +22,8 @@ import 'package:immich_mobile/repositories/backup.repository.dart'; import 'package:immich_mobile/repositories/file_media.repository.dart'; import 'package:immich_mobile/services/background.service.dart'; import 'package:immich_mobile/services/backup.service.dart'; -import 'package:immich_mobile/models/authentication/authentication_state.model.dart'; -import 'package:immich_mobile/providers/authentication.provider.dart'; +import 'package:immich_mobile/models/auth/auth_state.model.dart'; +import 'package:immich_mobile/providers/auth.provider.dart'; import 'package:immich_mobile/providers/gallery_permission.provider.dart'; import 'package:immich_mobile/models/server_info/server_disk_info.model.dart'; import 'package:immich_mobile/entities/store.entity.dart'; @@ -92,7 +92,7 @@ class BackupNotifier extends StateNotifier { final log = Logger('BackupNotifier'); final BackupService _backupService; final ServerInfoService _serverInfoService; - final AuthenticationState _authState; + final AuthState _authState; final BackgroundService _backgroundService; final GalleryPermissionNotifier _galleryPermissionNotifier; final Isar _db; @@ -765,7 +765,7 @@ final backupProvider = return BackupNotifier( ref.watch(backupServiceProvider), ref.watch(serverInfoServiceProvider), - ref.watch(authenticationProvider), + ref.watch(authProvider), ref.watch(backgroundServiceProvider), ref.watch(galleryPermissionNotifier.notifier), ref.watch(dbProvider), diff --git a/mobile/lib/providers/backup/backup_verification.provider.dart b/mobile/lib/providers/backup/backup_verification.provider.dart index 7b8e7b8c4b6d0..5881814320602 100644 --- a/mobile/lib/providers/backup/backup_verification.provider.dart +++ b/mobile/lib/providers/backup/backup_verification.provider.dart @@ -35,7 +35,7 @@ class BackupVerification extends _$BackupVerification { return; } final connection = await Connectivity().checkConnectivity(); - if (connection.contains(ConnectivityResult.wifi)) { + if (!connection.contains(ConnectivityResult.wifi)) { if (context.mounted) { ImmichToast.show( context: context, diff --git a/mobile/lib/providers/backup/backup_verification.provider.g.dart b/mobile/lib/providers/backup/backup_verification.provider.g.dart index e286f434219b5..9b5269884796c 100644 --- a/mobile/lib/providers/backup/backup_verification.provider.g.dart +++ b/mobile/lib/providers/backup/backup_verification.provider.g.dart @@ -7,7 +7,7 @@ part of 'backup_verification.provider.dart'; // ************************************************************************** String _$backupVerificationHash() => - r'021dfdf65e1903c932e4a1c14967b786dd3516fb'; + r'b204e43ab575d5fa5b2ee663297f32bcee9074f5'; /// See also [BackupVerification]. @ProviderFor(BackupVerification) diff --git a/mobile/lib/providers/image/immich_local_image_provider.dart b/mobile/lib/providers/image/immich_local_image_provider.dart index bbfaf12a4f445..36fd3334b9442 100644 --- a/mobile/lib/providers/image/immich_local_image_provider.dart +++ b/mobile/lib/providers/image/immich_local_image_provider.dart @@ -7,14 +7,21 @@ import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/painting.dart'; import 'package:immich_mobile/entities/asset.entity.dart'; +import 'package:logging/logging.dart'; import 'package:photo_manager/photo_manager.dart' show ThumbnailSize; /// The local image provider for an asset class ImmichLocalImageProvider extends ImageProvider { final Asset asset; + // only used for videos + final double width; + final double height; + final Logger log = Logger('ImmichLocalImageProvider'); ImmichLocalImageProvider({ required this.asset, + required this.width, + required this.height, }) : assert(asset.local != null, 'Only usable when asset.local is set'); /// Converts an [ImageProvider]'s settings plus an [ImageConfiguration] to a key @@ -42,38 +49,57 @@ class ImmichLocalImageProvider extends ImageProvider { // Streams in each stage of the image as we ask for it Stream _codec( - Asset key, + Asset asset, ImageDecoderCallback decode, StreamController chunkEvents, ) async* { - // Load a small thumbnail - final thumbBytes = await asset.local?.thumbnailDataWithSize( - const ThumbnailSize.square(256), - quality: 80, - ); - if (thumbBytes != null) { - final buffer = await ui.ImmutableBuffer.fromUint8List(thumbBytes); - final codec = await decode(buffer); - yield codec; - } else { - debugPrint("Loading thumb for ${asset.fileName} failed"); - } + ui.ImmutableBuffer? buffer; + try { + final local = asset.local; + if (local == null) { + throw StateError('Asset ${asset.fileName} has no local data'); + } - if (asset.isImage) { - final File? file = await asset.local?.originFile; - if (file == null) { - throw StateError("Opening file for asset ${asset.fileName} failed"); + var thumbBytes = await local + .thumbnailDataWithSize(const ThumbnailSize.square(256), quality: 80); + if (thumbBytes == null) { + throw StateError("Loading thumbnail for ${asset.fileName} failed"); } - try { - final buffer = await ui.ImmutableBuffer.fromFilePath(file.path); - final codec = await decode(buffer); - yield codec; - } catch (error) { - throw StateError("Loading asset ${asset.fileName} failed"); + buffer = await ui.ImmutableBuffer.fromUint8List(thumbBytes); + thumbBytes = null; + yield await decode(buffer); + buffer = null; + + switch (asset.type) { + case AssetType.image: + final File? file = await local.originFile; + if (file == null) { + throw StateError("Opening file for asset ${asset.fileName} failed"); + } + buffer = await ui.ImmutableBuffer.fromFilePath(file.path); + yield await decode(buffer); + buffer = null; + break; + case AssetType.video: + final size = ThumbnailSize(width.ceil(), height.ceil()); + thumbBytes = await local.thumbnailDataWithSize(size); + if (thumbBytes == null) { + throw StateError("Failed to load preview for ${asset.fileName}"); + } + buffer = await ui.ImmutableBuffer.fromUint8List(thumbBytes); + thumbBytes = null; + yield await decode(buffer); + buffer = null; + break; + default: + throw StateError('Unsupported asset type ${asset.type}'); } + } catch (error, stack) { + log.severe('Error loading local image ${asset.fileName}', error, stack); + buffer?.dispose(); + } finally { + chunkEvents.close(); } - - chunkEvents.close(); } @override diff --git a/mobile/lib/providers/locale_provider.dart b/mobile/lib/providers/locale_provider.dart new file mode 100644 index 0000000000000..5de3fa009a2d2 --- /dev/null +++ b/mobile/lib/providers/locale_provider.dart @@ -0,0 +1,4 @@ +import 'package:flutter/widgets.dart'; +import 'package:hooks_riverpod/hooks_riverpod.dart'; + +final localeProvider = Provider((_) => throw UnimplementedError()); diff --git a/mobile/lib/providers/network.provider.dart b/mobile/lib/providers/network.provider.dart new file mode 100644 index 0000000000000..5cb2fae4b1645 --- /dev/null +++ b/mobile/lib/providers/network.provider.dart @@ -0,0 +1,38 @@ +import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:immich_mobile/services/network.service.dart'; + +final networkProvider = StateNotifierProvider((ref) { + return NetworkNotifier( + ref.watch(networkServiceProvider), + ); +}); + +class NetworkNotifier extends StateNotifier { + final NetworkService _networkService; + + NetworkNotifier(this._networkService) : super(''); + + Future getWifiName() { + return _networkService.getWifiName(); + } + + Future getWifiReadPermission() { + return _networkService.getLocationWhenInUserPermission(); + } + + Future getWifiReadBackgroundPermission() { + return _networkService.getLocationAlwaysPermission(); + } + + Future requestWifiReadPermission() { + return _networkService.requestLocationWhenInUsePermission(); + } + + Future requestWifiReadBackgroundPermission() { + return _networkService.requestLocationAlwaysPermission(); + } + + Future openSettings() { + return _networkService.openSettings(); + } +} diff --git a/mobile/lib/providers/partner.provider.dart b/mobile/lib/providers/partner.provider.dart index 6ea335979f6f6..bf638ae355cea 100644 --- a/mobile/lib/providers/partner.provider.dart +++ b/mobile/lib/providers/partner.provider.dart @@ -1,5 +1,6 @@ import 'dart:async'; +import 'package:collection/collection.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/providers/album/suggested_shared_users.provider.dart'; import 'package:immich_mobile/services/partner.service.dart'; @@ -9,9 +10,19 @@ import 'package:isar/isar.dart'; class PartnerSharedWithNotifier extends StateNotifier> { PartnerSharedWithNotifier(Isar db, this._ps) : super([]) { - final query = db.users.filter().isPartnerSharedWithEqualTo(true); - query.findAll().then((partners) => state = partners); - query.watch().listen((partners) => state = partners); + Function eq = const ListEquality().equals; + final query = db.users.filter().isPartnerSharedWithEqualTo(true).sortById(); + query.findAll().then((partners) { + if (!eq(state, partners)) { + state = partners; + } + }).then((_) { + query.watch().listen((partners) { + if (!eq(state, partners)) { + state = partners; + } + }); + }); } Future updatePartner(User partner, {required bool inTimeline}) { @@ -31,9 +42,19 @@ final partnerSharedWithProvider = class PartnerSharedByNotifier extends StateNotifier> { PartnerSharedByNotifier(Isar db) : super([]) { - final query = db.users.filter().isPartnerSharedByEqualTo(true); - query.findAll().then((partners) => state = partners); - streamSub = query.watch().listen((partners) => state = partners); + Function eq = const ListEquality().equals; + final query = db.users.filter().isPartnerSharedByEqualTo(true).sortById(); + query.findAll().then((partners) { + if (!eq(state, partners)) { + state = partners; + } + }).then((_) { + streamSub = query.watch().listen((partners) { + if (!eq(state, partners)) { + state = partners; + } + }); + }); } late final StreamSubscription> streamSub; diff --git a/mobile/lib/providers/server_info.provider.dart b/mobile/lib/providers/server_info.provider.dart index 14521b06f64ca..a793acb3f66d4 100644 --- a/mobile/lib/providers/server_info.provider.dart +++ b/mobile/lib/providers/server_info.provider.dart @@ -59,7 +59,7 @@ class ServerInfoNotifier extends StateNotifier { await getServerConfig(); } - getServerVersion() async { + Future getServerVersion() async { try { final serverVersion = await _serverInfoService.getServerVersion(); diff --git a/mobile/lib/providers/theme.provider.dart b/mobile/lib/providers/theme.provider.dart new file mode 100644 index 0000000000000..73623bd026743 --- /dev/null +++ b/mobile/lib/providers/theme.provider.dart @@ -0,0 +1,74 @@ +import 'package:flutter/material.dart'; +import 'package:hooks_riverpod/hooks_riverpod.dart'; + +import 'package:immich_mobile/constants/colors.dart'; +import 'package:immich_mobile/theme/color_scheme.dart'; +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'; + +final immichThemeModeProvider = StateProvider((ref) { + final themeMode = ref + .watch(appSettingsServiceProvider) + .getSetting(AppSettingsEnum.themeMode); + + debugPrint("Current themeMode $themeMode"); + + if (themeMode == ThemeMode.light.name) { + return ThemeMode.light; + } else if (themeMode == ThemeMode.dark.name) { + return ThemeMode.dark; + } else { + return ThemeMode.system; + } +}); + +final immichThemePresetProvider = StateProvider((ref) { + final appSettingsProvider = ref.watch(appSettingsServiceProvider); + final primaryColorPreset = + appSettingsProvider.getSetting(AppSettingsEnum.primaryColor); + + debugPrint("Current theme preset $primaryColorPreset"); + + try { + return ImmichColorPreset.values + .firstWhere((e) => e.name == primaryColorPreset); + } catch (e) { + debugPrint( + "Theme preset $primaryColorPreset not found. Applying default preset.", + ); + appSettingsProvider.setSetting( + AppSettingsEnum.primaryColor, + defaultColorPresetName, + ); + return defaultColorPreset; + } +}); + +final dynamicThemeSettingProvider = StateProvider((ref) { + return ref + .watch(appSettingsServiceProvider) + .getSetting(AppSettingsEnum.dynamicTheme); +}); + +final colorfulInterfaceSettingProvider = StateProvider((ref) { + return ref + .watch(appSettingsServiceProvider) + .getSetting(AppSettingsEnum.colorfulInterface); +}); + +// Provider for current selected theme +final immichThemeProvider = StateProvider((ref) { + final primaryColorPreset = ref.read(immichThemePresetProvider); + final useSystemColor = ref.watch(dynamicThemeSettingProvider); + final useColorfulInterface = ref.watch(colorfulInterfaceSettingProvider); + final ImmichTheme? dynamicTheme = DynamicTheme.theme; + final currentTheme = (useSystemColor && dynamicTheme != null) + ? dynamicTheme + : primaryColorPreset.themeOfPreset; + + return useColorfulInterface + ? currentTheme + : decolorizeSurfaces(theme: currentTheme); +}); diff --git a/mobile/lib/providers/websocket.provider.dart b/mobile/lib/providers/websocket.provider.dart index 6216a5de641eb..6889db7b7f48f 100644 --- a/mobile/lib/providers/websocket.provider.dart +++ b/mobile/lib/providers/websocket.provider.dart @@ -4,7 +4,7 @@ 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/providers/authentication.provider.dart'; +import 'package:immich_mobile/providers/auth.provider.dart'; import 'package:immich_mobile/entities/asset.entity.dart'; import 'package:immich_mobile/models/server_info/server_version.model.dart'; import 'package:immich_mobile/entities/store.entity.dart'; @@ -103,7 +103,7 @@ class WebsocketNotifier extends StateNotifier { /// Connects websocket to server unless already connected void connect() { if (state.isConnected) return; - final authenticationState = _ref.read(authenticationProvider); + final authenticationState = _ref.read(authProvider); if (authenticationState.isAuthenticated) { try { diff --git a/mobile/lib/repositories/album_api.repository.dart b/mobile/lib/repositories/album_api.repository.dart index 5d0b56dc7882a..2438304158e1b 100644 --- a/mobile/lib/repositories/album_api.repository.dart +++ b/mobile/lib/repositories/album_api.repository.dart @@ -1,4 +1,5 @@ import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:immich_mobile/constants/enums.dart'; import 'package:immich_mobile/entities/album.entity.dart'; import 'package:immich_mobile/entities/asset.entity.dart'; import 'package:immich_mobile/entities/user.entity.dart'; @@ -56,7 +57,13 @@ class AlbumApiRepository extends ApiRepository implements IAlbumApiRepository { String? thumbnailAssetId, String? description, bool? activityEnabled, + SortOrder? sortOrder, }) async { + AssetOrder? order; + if (sortOrder != null) { + order = sortOrder == SortOrder.asc ? AssetOrder.asc : AssetOrder.desc; + } + final response = await checkNull( _api.updateAlbumInfo( albumId, @@ -65,9 +72,11 @@ class AlbumApiRepository extends ApiRepository implements IAlbumApiRepository { albumThumbnailAssetId: thumbnailAssetId, description: description, isActivityEnabled: activityEnabled, + order: order, ), ), ); + return _toAlbum(response); } @@ -152,6 +161,7 @@ class AlbumApiRepository extends ApiRepository implements IAlbumApiRepository { startDate: dto.startDate, endDate: dto.endDate, activityEnabled: dto.isActivityEnabled, + sortOrder: dto.order == AssetOrder.asc ? SortOrder.asc : SortOrder.desc, ); album.remoteAssetCount = dto.assetCount; album.owner.value = User.fromSimpleUserDto(dto.owner); diff --git a/mobile/lib/repositories/album_media.repository.dart b/mobile/lib/repositories/album_media.repository.dart index c3795f75df4e1..dac9ccd4da6fd 100644 --- a/mobile/lib/repositories/album_media.repository.dart +++ b/mobile/lib/repositories/album_media.repository.dart @@ -14,7 +14,6 @@ class AlbumMediaRepository implements IAlbumMediaRepository { final List assetPathEntities = await PhotoManager.getAssetPathList( hasAll: true, - filterOption: FilterOptionGroup(containsPathModified: true), ); return assetPathEntities.map(_toAlbum).toList(); } diff --git a/mobile/lib/repositories/asset_api.repository.dart b/mobile/lib/repositories/asset_api.repository.dart index 54d57c4dfccf6..f4fcd8a6dd6e0 100644 --- a/mobile/lib/repositories/asset_api.repository.dart +++ b/mobile/lib/repositories/asset_api.repository.dart @@ -34,7 +34,7 @@ class AssetApiRepository extends ApiRepository implements IAssetApiRepository { int currentPage = 1; while (hasNext) { final response = await checkNull( - _searchApi.searchMetadata( + _searchApi.searchAssets( MetadataSearchDto( personIds: personIds, page: currentPage, diff --git a/mobile/lib/repositories/auth.repository.dart b/mobile/lib/repositories/auth.repository.dart new file mode 100644 index 0000000000000..fa504e6ac335d --- /dev/null +++ b/mobile/lib/repositories/auth.repository.dart @@ -0,0 +1,69 @@ +import 'dart:convert'; + +import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:immich_mobile/entities/album.entity.dart'; +import 'package:immich_mobile/entities/asset.entity.dart'; +import 'package:immich_mobile/entities/etag.entity.dart'; +import 'package:immich_mobile/entities/exif_info.entity.dart'; +import 'package:immich_mobile/entities/store.entity.dart'; +import 'package:immich_mobile/entities/user.entity.dart'; +import 'package:immich_mobile/interfaces/auth.interface.dart'; +import 'package:immich_mobile/models/auth/auxilary_endpoint.model.dart'; +import 'package:immich_mobile/providers/db.provider.dart'; +import 'package:immich_mobile/repositories/database.repository.dart'; + +final authRepositoryProvider = Provider( + (ref) => AuthRepository(ref.watch(dbProvider)), +); + +class AuthRepository extends DatabaseRepository implements IAuthRepository { + AuthRepository(super.db); + + @override + Future clearLocalData() { + return db.writeTxn(() { + return Future.wait([ + db.assets.clear(), + db.exifInfos.clear(), + db.albums.clear(), + db.eTags.clear(), + db.users.clear(), + ]); + }); + } + + @override + String getAccessToken() { + return Store.get(StoreKey.accessToken); + } + + @override + bool getEndpointSwitchingFeature() { + return Store.tryGet(StoreKey.autoEndpointSwitching) ?? false; + } + + @override + String? getPreferredWifiName() { + return Store.tryGet(StoreKey.preferredWifiName); + } + + @override + String? getLocalEndpoint() { + return Store.tryGet(StoreKey.localEndpoint); + } + + @override + List getExternalEndpointList() { + final jsonString = Store.tryGet(StoreKey.externalEndpointList); + + if (jsonString == null) { + return []; + } + + final List jsonList = jsonDecode(jsonString); + final endpointList = + jsonList.map((e) => AuxilaryEndpoint.fromJson(e)).toList(); + + return endpointList; + } +} diff --git a/mobile/lib/repositories/auth_api.repository.dart b/mobile/lib/repositories/auth_api.repository.dart new file mode 100644 index 0000000000000..f3a1d52de37da --- /dev/null +++ b/mobile/lib/repositories/auth_api.repository.dart @@ -0,0 +1,58 @@ +import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:immich_mobile/interfaces/auth_api.interface.dart'; +import 'package:immich_mobile/models/auth/login_response.model.dart'; +import 'package:immich_mobile/providers/api.provider.dart'; +import 'package:immich_mobile/repositories/api.repository.dart'; +import 'package:immich_mobile/services/api.service.dart'; +import 'package:openapi/api.dart'; + +final authApiRepositoryProvider = + Provider((ref) => AuthApiRepository(ref.watch(apiServiceProvider))); + +class AuthApiRepository extends ApiRepository implements IAuthApiRepository { + final ApiService _apiService; + + AuthApiRepository(this._apiService); + + @override + Future changePassword(String newPassword) async { + await _apiService.usersApi.updateMyUser( + UserUpdateMeDto( + password: newPassword, + ), + ); + } + + @override + Future login(String email, String password) async { + final loginResponseDto = await checkNull( + _apiService.authenticationApi.login( + LoginCredentialDto( + email: email, + password: password, + ), + ), + ); + + return _mapLoginReponse(loginResponseDto); + } + + @override + Future logout() async { + await _apiService.authenticationApi + .logout() + .timeout(const Duration(seconds: 7)); + } + + _mapLoginReponse(LoginResponseDto dto) { + return LoginResponse( + accessToken: dto.accessToken, + isAdmin: dto.isAdmin, + name: dto.name, + profileImagePath: dto.profileImagePath, + shouldChangePassword: dto.shouldChangePassword, + userEmail: dto.userEmail, + userId: dto.userId, + ); + } +} diff --git a/mobile/lib/repositories/database.repository.dart b/mobile/lib/repositories/database.repository.dart index f9ee1426bbee7..3eb74621fa255 100644 --- a/mobile/lib/repositories/database.repository.dart +++ b/mobile/lib/repositories/database.repository.dart @@ -1,5 +1,4 @@ import 'dart:async'; - import 'package:immich_mobile/interfaces/database.interface.dart'; import 'package:isar/isar.dart'; diff --git a/mobile/lib/repositories/network.repository.dart b/mobile/lib/repositories/network.repository.dart new file mode 100644 index 0000000000000..54f527afb164e --- /dev/null +++ b/mobile/lib/repositories/network.repository.dart @@ -0,0 +1,37 @@ +import 'dart:io'; + +import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:immich_mobile/interfaces/network.interface.dart'; +import 'package:network_info_plus/network_info_plus.dart'; + +final networkRepositoryProvider = Provider((_) { + final networkInfo = NetworkInfo(); + + return NetworkRepository(networkInfo); +}); + +class NetworkRepository implements INetworkRepository { + final NetworkInfo _networkInfo; + + NetworkRepository(this._networkInfo); + + @override + Future getWifiName() { + if (Platform.isAndroid) { + // remove quote around the return value on Android + // https://github.com/fluttercommunity/plus_plugins/tree/main/packages/network_info_plus/network_info_plus#android + return _networkInfo.getWifiName().then((value) { + if (value != null) { + return value.replaceAll(RegExp(r'"'), ''); + } + return value; + }); + } + return _networkInfo.getWifiName(); + } + + @override + Future getWifiIp() { + return _networkInfo.getWifiIP(); + } +} diff --git a/mobile/lib/repositories/permission.repository.dart b/mobile/lib/repositories/permission.repository.dart new file mode 100644 index 0000000000000..f825c36075729 --- /dev/null +++ b/mobile/lib/repositories/permission.repository.dart @@ -0,0 +1,45 @@ +import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:permission_handler/permission_handler.dart'; + +final permissionRepositoryProvider = Provider((_) { + return PermissionRepository(); +}); + +class PermissionRepository implements IPermissionRepository { + PermissionRepository(); + + @override + Future hasLocationWhenInUsePermission() { + return Permission.locationWhenInUse.isGranted; + } + + @override + Future requestLocationWhenInUsePermission() async { + final result = await Permission.locationWhenInUse.request(); + return result.isGranted; + } + + @override + Future hasLocationAlwaysPermission() { + return Permission.locationAlways.isGranted; + } + + @override + Future requestLocationAlwaysPermission() async { + final result = await Permission.locationAlways.request(); + return result.isGranted; + } + + @override + Future openSettings() { + return openAppSettings(); + } +} + +abstract interface class IPermissionRepository { + Future hasLocationWhenInUsePermission(); + Future requestLocationWhenInUsePermission(); + Future hasLocationAlwaysPermission(); + Future requestLocationAlwaysPermission(); + Future openSettings(); +} diff --git a/mobile/lib/routing/router.dart b/mobile/lib/routing/router.dart index b001c6bdd6d33..5adfeb4061db2 100644 --- a/mobile/lib/routing/router.dart +++ b/mobile/lib/routing/router.dart @@ -14,16 +14,17 @@ import 'package:immich_mobile/pages/backup/backup_controller.page.dart'; import 'package:immich_mobile/pages/backup/backup_options.page.dart'; import 'package:immich_mobile/pages/backup/failed_backup_status.page.dart'; import 'package:immich_mobile/pages/albums/albums.page.dart'; +import 'package:immich_mobile/pages/common/native_video_viewer.page.dart'; import 'package:immich_mobile/pages/library/local_albums.page.dart'; import 'package:immich_mobile/pages/library/people/people_collection.page.dart'; import 'package:immich_mobile/pages/library/places/places_collection.page.dart'; import 'package:immich_mobile/pages/library/library.page.dart'; import 'package:immich_mobile/pages/common/activities.page.dart'; -import 'package:immich_mobile/pages/common/album_additional_shared_user_selection.page.dart'; -import 'package:immich_mobile/pages/common/album_asset_selection.page.dart'; -import 'package:immich_mobile/pages/common/album_options.page.dart'; -import 'package:immich_mobile/pages/common/album_shared_user_selection.page.dart'; -import 'package:immich_mobile/pages/common/album_viewer.page.dart'; +import 'package:immich_mobile/pages/album/album_additional_shared_user_selection.page.dart'; +import 'package:immich_mobile/pages/album/album_asset_selection.page.dart'; +import 'package:immich_mobile/pages/album/album_options.page.dart'; +import 'package:immich_mobile/pages/album/album_shared_user_selection.page.dart'; +import 'package:immich_mobile/pages/album/album_viewer.page.dart'; import 'package:immich_mobile/pages/common/app_log.page.dart'; import 'package:immich_mobile/pages/common/app_log_detail.page.dart'; import 'package:immich_mobile/pages/common/create_album.page.dart'; @@ -272,6 +273,10 @@ class AppRouter extends RootStackRouter { guards: [_authGuard, _duplicateGuard], transitionsBuilder: TransitionsBuilders.slideLeft, ), + AutoRoute( + page: NativeVideoViewerRoute.page, + guards: [_authGuard, _duplicateGuard], + ), ]; } diff --git a/mobile/lib/routing/router.gr.dart b/mobile/lib/routing/router.gr.dart index ea7d385e85626..3bd89661753f9 100644 --- a/mobile/lib/routing/router.gr.dart +++ b/mobile/lib/routing/router.gr.dart @@ -139,13 +139,11 @@ class AlbumAssetSelectionRouteArgs { class AlbumOptionsRoute extends PageRouteInfo { AlbumOptionsRoute({ Key? key, - required Album album, List? children, }) : super( AlbumOptionsRoute.name, args: AlbumOptionsRouteArgs( key: key, - album: album, ), initialChildren: children, ); @@ -158,25 +156,19 @@ class AlbumOptionsRoute extends PageRouteInfo { final args = data.argsAs(); return AlbumOptionsPage( key: args.key, - album: args.album, ); }, ); } class AlbumOptionsRouteArgs { - const AlbumOptionsRouteArgs({ - this.key, - required this.album, - }); + const AlbumOptionsRouteArgs({this.key}); final Key? key; - final Album album; - @override String toString() { - return 'AlbumOptionsRouteArgs{key: $key, album: $album}'; + return 'AlbumOptionsRouteArgs{key: $key}'; } } @@ -1079,6 +1071,64 @@ class MemoryRouteArgs { } } +/// generated route for +/// [NativeVideoViewerPage] +class NativeVideoViewerRoute extends PageRouteInfo { + NativeVideoViewerRoute({ + Key? key, + required Asset asset, + required Widget image, + bool showControls = true, + List? children, + }) : super( + NativeVideoViewerRoute.name, + args: NativeVideoViewerRouteArgs( + key: key, + asset: asset, + image: image, + showControls: showControls, + ), + initialChildren: children, + ); + + static const String name = 'NativeVideoViewerRoute'; + + static PageInfo page = PageInfo( + name, + builder: (data) { + final args = data.argsAs(); + return NativeVideoViewerPage( + key: args.key, + asset: args.asset, + image: args.image, + showControls: args.showControls, + ); + }, + ); +} + +class NativeVideoViewerRouteArgs { + const NativeVideoViewerRouteArgs({ + this.key, + required this.asset, + required this.image, + this.showControls = true, + }); + + final Key? key; + + final Asset asset; + + final Widget image; + + final bool showControls; + + @override + String toString() { + return 'NativeVideoViewerRouteArgs{key: $key, asset: $asset, image: $image, showControls: $showControls}'; + } +} + /// generated route for /// [PartnerDetailPage] class PartnerDetailRoute extends PageRouteInfo { diff --git a/mobile/lib/services/album.service.dart b/mobile/lib/services/album.service.dart index 53a65e2869aea..5f013c0e53e5e 100644 --- a/mobile/lib/services/album.service.dart +++ b/mobile/lib/services/album.service.dart @@ -5,6 +5,7 @@ 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/interfaces/album.interface.dart'; import 'package:immich_mobile/interfaces/album_api.interface.dart'; import 'package:immich_mobile/interfaces/album_media.interface.dart'; @@ -76,10 +77,16 @@ class AlbumService { final Stopwatch sw = Stopwatch()..start(); bool changes = false; try { - final List excludedIds = await _backupAlbumRepository - .getIdsBySelection(BackupSelection.exclude); - final List selectedIds = await _backupAlbumRepository - .getIdsBySelection(BackupSelection.select); + final (selectedIds, excludedIds, onDevice) = await ( + _backupAlbumRepository + .getIdsBySelection(BackupSelection.select) + .then((value) => value.toSet()), + _backupAlbumRepository + .getIdsBySelection(BackupSelection.exclude) + .then((value) => value.toSet()), + _albumMediaRepository.getAll() + ).wait; + _log.info("Found ${onDevice.length} device albums"); if (selectedIds.isEmpty) { final numLocal = await _albumRepository.count(local: true); if (numLocal > 0) { @@ -87,8 +94,6 @@ class AlbumService { } return false; } - final List onDevice = await _albumMediaRepository.getAll(); - _log.info("Found ${onDevice.length} device albums"); Set? excludedAssets; if (excludedIds.isNotEmpty) { if (Platform.isIOS) { @@ -108,22 +113,19 @@ class AlbumService { "Ignoring ${excludedIds.length} excluded albums resulting in ${onDevice.length} device albums", ); } - final hasAll = selectedIds - .map( - (id) => onDevice.firstWhereOrNull((album) => album.localId == id), - ) - .whereNotNull() - .any((a) => a.isAll); + + final allAlbum = onDevice.firstWhereOrNull((album) => album.isAll); + final hasAll = allAlbum != null && selectedIds.contains(allAlbum.localId); if (hasAll) { if (Platform.isAndroid) { // remove the virtual "Recent" album and keep and individual albums // on Android, the virtual "Recent" `lastModified` value is always null - onDevice.removeWhere((e) => e.isAll); + onDevice.removeWhere((album) => album.isAll); _log.info("'Recents' is selected, keeping all individual albums"); } } else { // keep only the explicitly selected albums - onDevice.removeWhere((e) => !selectedIds.contains(e.localId)); + onDevice.removeWhere((album) => !selectedIds.contains(album.localId)); _log.info("'Recents' is not selected, keeping only selected albums"); } changes = @@ -138,15 +140,19 @@ class AlbumService { Future> _loadExcludedAssetIds( List albums, - List excludedAlbumIds, + Set excludedAlbumIds, ) async { final Set result = HashSet(); - for (Album album in albums) { - if (excludedAlbumIds.contains(album.localId)) { - final assetIds = - await _albumMediaRepository.getAssetIds(album.localId!); - result.addAll(assetIds); - } + for (final batchAlbums in albums + .where((album) => excludedAlbumIds.contains(album.localId)) + .slices(5)) { + await batchAlbums + .map( + (album) => _albumMediaRepository + .getAssetIds(album.localId!) + .then((assetIds) => result.addAll(assetIds)), + ) + .wait; } return result; } @@ -163,11 +169,10 @@ class AlbumService { bool changes = false; try { await _userService.refreshUsers(); - final List sharedAlbum = - await _albumApiRepository.getAll(shared: true); - - final List ownedAlbum = - await _albumApiRepository.getAll(shared: null); + final (sharedAlbum, ownedAlbum) = await ( + _albumApiRepository.getAll(shared: true), + _albumApiRepository.getAll(shared: null) + ).wait; final albums = HashSet( equals: (a, b) => a.remoteId == b.remoteId, @@ -432,4 +437,17 @@ class AlbumService { ) async { return _albumRepository.search(searchTerm, filterMode); } + + Future updateSortOrder(Album album, SortOrder order) async { + try { + final updateAlbum = + await _albumApiRepository.update(album.remoteId!, sortOrder: order); + album.sortOrder = updateAlbum.sortOrder; + + return _albumRepository.update(album); + } catch (error, stackTrace) { + _log.severe("Error updating album sort order", error, stackTrace); + } + return null; + } } diff --git a/mobile/lib/services/api.service.dart b/mobile/lib/services/api.service.dart index 515023d163f1c..0f6fe8a100ef8 100644 --- a/mobile/lib/services/api.service.dart +++ b/mobile/lib/services/api.service.dart @@ -2,6 +2,7 @@ import 'dart:async'; import 'dart:convert'; import 'dart:io'; +import 'package:device_info_plus/device_info_plus.dart'; import 'package:flutter/material.dart'; import 'package:immich_mobile/entities/store.entity.dart'; import 'package:immich_mobile/utils/url_helper.dart'; @@ -66,10 +67,10 @@ class ApiService implements Authentication { } Future resolveAndSetEndpoint(String serverUrl) async { - final endpoint = await _resolveEndpoint(serverUrl); + final endpoint = await resolveEndpoint(serverUrl); setEndpoint(endpoint); - // Save in hivebox for next startup + // Save in local database for next startup Store.put(StoreKey.serverEndpoint, endpoint); return endpoint; } @@ -81,7 +82,7 @@ class ApiService implements Authentication { /// host - required /// port - optional (default: based on schema) /// path - optional - Future _resolveEndpoint(String serverUrl) async { + Future resolveEndpoint(String serverUrl) async { final url = sanitizeUrl(serverUrl); if (!await _isEndpointAvailable(serverUrl)) { @@ -103,7 +104,7 @@ class ApiService implements Authentication { try { await setEndpoint(serverUrl); - await serverInfoApi.pingServer().timeout(Duration(seconds: 5)); + await serverInfoApi.pingServer().timeout(const Duration(seconds: 5)); } on TimeoutException catch (_) { return false; } on SocketException catch (_) { @@ -148,11 +149,27 @@ class ApiService implements Authentication { return ""; } - setAccessToken(String accessToken) { + void setAccessToken(String accessToken) { _accessToken = accessToken; Store.put(StoreKey.accessToken, accessToken); } + Future setDeviceInfoHeader() async { + DeviceInfoPlugin deviceInfoPlugin = DeviceInfoPlugin(); + + if (Platform.isIOS) { + final iosInfo = await deviceInfoPlugin.iosInfo; + authenticationApi.apiClient + .addDefaultHeader('deviceModel', iosInfo.utsname.machine); + authenticationApi.apiClient.addDefaultHeader('deviceType', 'iOS'); + } else { + final androidInfo = await deviceInfoPlugin.androidInfo; + authenticationApi.apiClient + .addDefaultHeader('deviceModel', androidInfo.model); + authenticationApi.apiClient.addDefaultHeader('deviceType', 'Android'); + } + } + static Map getRequestHeaders() { var accessToken = Store.get(StoreKey.accessToken, ""); var customHeadersStr = Store.get(StoreKey.customHeaders, ""); diff --git a/mobile/lib/services/app_settings.service.dart b/mobile/lib/services/app_settings.service.dart index 8f773e1bb33a9..c3fde894d545d 100644 --- a/mobile/lib/services/app_settings.service.dart +++ b/mobile/lib/services/app_settings.service.dart @@ -1,4 +1,4 @@ -import 'package:immich_mobile/constants/immich_colors.dart'; +import 'package:immich_mobile/constants/colors.dart'; import 'package:immich_mobile/entities/store.entity.dart'; enum AppSettingsEnum { @@ -77,6 +77,7 @@ enum AppSettingsEnum { ), enableHapticFeedback(StoreKey.enableHapticFeedback, null, true), syncAlbums(StoreKey.syncAlbums, null, false), + autoEndpointSwitching(StoreKey.autoEndpointSwitching, null, 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 b2cad4dc828eb..7d27d1b27b0ea 100644 --- a/mobile/lib/services/asset.service.dart +++ b/mobile/lib/services/asset.service.dart @@ -1,4 +1,5 @@ import 'dart:async'; +import 'dart:io'; import 'package:collection/collection.dart'; import 'package:flutter/material.dart'; @@ -402,4 +403,29 @@ class AssetService { return exifInfo?.description ?? ""; } + + Future getAspectRatio(Asset asset) async { + // platform_manager always returns 0 for orientation on iOS, so only prefer it on Android + if (asset.isLocal && Platform.isAndroid) { + await asset.localAsync; + } else if (asset.isRemote) { + asset = await loadExif(asset); + } else if (asset.isLocal) { + await asset.localAsync; + } + + final aspectRatio = asset.aspectRatio; + if (aspectRatio != null) { + return aspectRatio; + } + + final width = asset.width; + final height = asset.height; + if (width != null && height != null) { + // we don't know the orientation, so assume it's normal + return width / height; + } + + return 1.0; + } } diff --git a/mobile/lib/services/auth.service.dart b/mobile/lib/services/auth.service.dart new file mode 100644 index 0000000000000..08741a15db0f6 --- /dev/null +++ b/mobile/lib/services/auth.service.dart @@ -0,0 +1,196 @@ +import 'dart:async'; +import 'dart:io'; + +import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:immich_mobile/entities/store.entity.dart'; +import 'package:immich_mobile/interfaces/auth.interface.dart'; +import 'package:immich_mobile/interfaces/auth_api.interface.dart'; +import 'package:immich_mobile/models/auth/auxilary_endpoint.model.dart'; +import 'package:immich_mobile/models/auth/login_response.model.dart'; +import 'package:immich_mobile/providers/api.provider.dart'; +import 'package:immich_mobile/repositories/auth.repository.dart'; +import 'package:immich_mobile/repositories/auth_api.repository.dart'; +import 'package:immich_mobile/services/api.service.dart'; +import 'package:immich_mobile/services/network.service.dart'; +import 'package:logging/logging.dart'; +import 'package:openapi/api.dart'; + +final authServiceProvider = Provider( + (ref) => AuthService( + ref.watch(authApiRepositoryProvider), + ref.watch(authRepositoryProvider), + ref.watch(apiServiceProvider), + ref.watch(networkServiceProvider), + ), +); + +class AuthService { + final IAuthApiRepository _authApiRepository; + final IAuthRepository _authRepository; + final ApiService _apiService; + final NetworkService _networkService; + + final _log = Logger("AuthService"); + + AuthService( + this._authApiRepository, + this._authRepository, + this._apiService, + this._networkService, + ); + + /// Validates the provided server URL by resolving and setting the endpoint. + /// Also sets the device info header and stores the valid URL. + /// + /// [url] - The server URL to be validated. + /// + /// Returns the validated and resolved server URL as a [String]. + /// + /// Throws an exception if the URL cannot be resolved or set. + Future validateServerUrl(String url) async { + final validUrl = await _apiService.resolveAndSetEndpoint(url); + await _apiService.setDeviceInfoHeader(); + Store.put(StoreKey.serverUrl, validUrl); + + return validUrl; + } + + Future validateAuxilaryServerUrl(String url) async { + final httpclient = HttpClient(); + bool isValid = false; + + try { + final uri = Uri.parse('$url/users/me'); + final request = await httpclient.getUrl(uri); + + // add auth token + any configured custom headers + final customHeaders = ApiService.getRequestHeaders(); + customHeaders.forEach((key, value) { + request.headers.add(key, value); + }); + + final response = await request.close(); + if (response.statusCode == 200) { + isValid = true; + } + } catch (error) { + _log.severe("Error validating auxilary endpoint", error); + } finally { + httpclient.close(); + } + + return isValid; + } + + Future login(String email, String password) { + return _authApiRepository.login(email, password); + } + + /// Performs user logout operation by making a server request and clearing local data. + /// + /// This method attempts to log out the user through the authentication API repository. + /// If the server request fails, the error is logged but local data is still cleared. + /// The local data cleanup is guaranteed to execute regardless of the server request outcome. + /// + /// Throws any unhandled exceptions from the API request or local data clearing operations. + Future logout() async { + try { + await _authApiRepository.logout(); + } catch (error, stackTrace) { + _log.severe("Error logging out", error, stackTrace); + } finally { + await clearLocalData().catchError((error, stackTrace) { + _log.severe("Error clearing local data", error, stackTrace); + }); + } + } + + /// Clears all local authentication-related data. + /// + /// This method performs a concurrent deletion of: + /// - Authentication repository data + /// - Current user information + /// - Access token + /// - Asset ETag + /// + /// All deletions are executed in parallel using [Future.wait]. + Future clearLocalData() { + return Future.wait([ + _authRepository.clearLocalData(), + Store.delete(StoreKey.currentUser), + Store.delete(StoreKey.accessToken), + Store.delete(StoreKey.assetETag), + Store.delete(StoreKey.autoEndpointSwitching), + Store.delete(StoreKey.preferredWifiName), + Store.delete(StoreKey.localEndpoint), + Store.delete(StoreKey.externalEndpointList), + ]); + } + + Future changePassword(String newPassword) { + try { + return _authApiRepository.changePassword(newPassword); + } catch (error, stackTrace) { + _log.severe("Error changing password", error, stackTrace); + rethrow; + } + } + + Future setOpenApiServiceEndpoint() async { + final enable = _authRepository.getEndpointSwitchingFeature(); + if (!enable) { + return null; + } + + final wifiName = await _networkService.getWifiName(); + final savedWifiName = _authRepository.getPreferredWifiName(); + String? endpoint; + + if (wifiName == savedWifiName) { + endpoint = await _setLocalConnection(); + } + + endpoint ??= await _setRemoteConnection(); + + return endpoint; + } + + Future _setLocalConnection() async { + try { + final localEndpoint = _authRepository.getLocalEndpoint(); + if (localEndpoint != null) { + await _apiService.resolveAndSetEndpoint(localEndpoint); + return localEndpoint; + } + } catch (error, stackTrace) { + _log.severe("Cannot set local endpoint", error, stackTrace); + } + + return null; + } + + Future _setRemoteConnection() async { + List endpointList; + + try { + endpointList = _authRepository.getExternalEndpointList(); + } catch (error, stackTrace) { + _log.severe("Cannot get external endpoint", error, stackTrace); + return null; + } + + for (final endpoint in endpointList) { + try { + return await _apiService.resolveAndSetEndpoint(endpoint.url); + } on ApiException catch (error) { + _log.severe("Cannot resolve endpoint", error); + continue; + } catch (_) { + _log.severe("Auxilary server is not valid"); + continue; + } + } + + return null; + } +} diff --git a/mobile/lib/services/background.service.dart b/mobile/lib/services/background.service.dart index 3959e2a6edc2b..27be2c046df79 100644 --- a/mobile/lib/services/background.service.dart +++ b/mobile/lib/services/background.service.dart @@ -6,6 +6,7 @@ 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'; @@ -17,15 +18,20 @@ import 'package:immich_mobile/repositories/album.repository.dart'; import 'package:immich_mobile/repositories/album_api.repository.dart'; import 'package:immich_mobile/repositories/asset.repository.dart'; import 'package:immich_mobile/repositories/asset_media.repository.dart'; +import 'package:immich_mobile/repositories/auth.repository.dart'; +import 'package:immich_mobile/repositories/auth_api.repository.dart'; import 'package:immich_mobile/repositories/backup.repository.dart'; import 'package:immich_mobile/repositories/album_media.repository.dart'; import 'package:immich_mobile/repositories/etag.repository.dart'; import 'package:immich_mobile/repositories/exif_info.repository.dart'; import 'package:immich_mobile/repositories/file_media.repository.dart'; +import 'package:immich_mobile/repositories/network.repository.dart'; import 'package:immich_mobile/repositories/partner_api.repository.dart'; +import 'package:immich_mobile/repositories/permission.repository.dart'; import 'package:immich_mobile/repositories/user.repository.dart'; import 'package:immich_mobile/repositories/user_api.repository.dart'; import 'package:immich_mobile/services/album.service.dart'; +import 'package:immich_mobile/services/auth.service.dart'; import 'package:immich_mobile/services/entity.service.dart'; import 'package:immich_mobile/services/hash.service.dart'; import 'package:immich_mobile/services/localization.service.dart'; @@ -36,11 +42,13 @@ import 'package:immich_mobile/services/backup.service.dart'; import 'package:immich_mobile/services/app_settings.service.dart'; import 'package:immich_mobile/entities/store.entity.dart'; import 'package:immich_mobile/services/api.service.dart'; +import 'package:immich_mobile/services/network.service.dart'; import 'package:immich_mobile/services/sync.service.dart'; import 'package:immich_mobile/services/user.service.dart'; import 'package:immich_mobile/utils/backup_progress.dart'; import 'package:immich_mobile/utils/diff.dart'; import 'package:immich_mobile/utils/http_ssl_cert_override.dart'; +import 'package:network_info_plus/network_info_plus.dart'; import 'package:path_provider_ios/path_provider_ios.dart'; import 'package:photo_manager/photo_manager.dart' show PMProgressHandler; @@ -422,6 +430,24 @@ class BackgroundService { assetMediaRepository, ); + AuthApiRepository authApiRepository = AuthApiRepository(apiService); + AuthRepository authRepository = AuthRepository(db); + NetworkRepository networkRepository = NetworkRepository(NetworkInfo()); + PermissionRepository permissionRepository = PermissionRepository(); + NetworkService networkService = + NetworkService(networkRepository, permissionRepository); + AuthService authService = AuthService( + authApiRepository, + authRepository, + apiService, + networkService, + ); + + final endpoint = await authService.setOpenApiServiceEndpoint(); + if (kDebugMode) { + debugPrint("[BG UPLOAD] Using endpoint: $endpoint"); + } + final selectedAlbums = await backupRepository.getAllBySelection(BackupSelection.select); final excludedAlbums = diff --git a/mobile/lib/services/backup.service.dart b/mobile/lib/services/backup.service.dart index a0b6bf16c2304..7bce1047e2c68 100644 --- a/mobile/lib/services/backup.service.dart +++ b/mobile/lib/services/backup.service.dart @@ -313,15 +313,12 @@ class BackupService { ); } } else { - if (asset.type == AssetType.video) { - file = await asset.local!.originFile; - } else { - file = await asset.local!.originFile + file = + await asset.local!.originFile.timeout(const Duration(seconds: 5)); + + if (asset.local!.isLivePhoto) { + livePhotoFile = await asset.local!.originFileWithSubtype .timeout(const Duration(seconds: 5)); - if (asset.local!.isLivePhoto) { - livePhotoFile = await asset.local!.originFileWithSubtype - .timeout(const Duration(seconds: 5)); - } } } diff --git a/mobile/lib/services/device.service.dart b/mobile/lib/services/device.service.dart new file mode 100644 index 0000000000000..e1676d56835f7 --- /dev/null +++ b/mobile/lib/services/device.service.dart @@ -0,0 +1,24 @@ +import 'package:flutter_udid/flutter_udid.dart'; +import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:immich_mobile/entities/store.entity.dart'; + +final deviceServiceProvider = Provider((ref) => DeviceService()); + +class DeviceService { + DeviceService(); + + createDeviceId() { + return FlutterUdid.consistentUdid; + } + + /// Returns the device ID from local storage or creates a new one if not found. + /// + /// This method first attempts to retrieve the device ID from the local store using + /// [StoreKey.deviceId]. If no device ID is found (returns null), it generates a + /// new device ID by calling [createDeviceId]. + /// + /// Returns a [String] representing the device's unique identifier. + String getDeviceId() { + return Store.tryGet(StoreKey.deviceId) ?? createDeviceId(); + } +} diff --git a/mobile/lib/services/network.service.dart b/mobile/lib/services/network.service.dart new file mode 100644 index 0000000000000..f2d2de325d05c --- /dev/null +++ b/mobile/lib/services/network.service.dart @@ -0,0 +1,47 @@ +import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:immich_mobile/interfaces/network.interface.dart'; +import 'package:immich_mobile/repositories/network.repository.dart'; +import 'package:immich_mobile/repositories/permission.repository.dart'; + +final networkServiceProvider = Provider((ref) { + return NetworkService( + ref.watch(networkRepositoryProvider), + ref.watch(permissionRepositoryProvider), + ); +}); + +class NetworkService { + final INetworkRepository _repository; + final IPermissionRepository _permissionRepository; + + NetworkService(this._repository, this._permissionRepository); + + Future getLocationWhenInUserPermission() { + return _permissionRepository.hasLocationWhenInUsePermission(); + } + + Future requestLocationWhenInUsePermission() { + return _permissionRepository.requestLocationWhenInUsePermission(); + } + + Future getLocationAlwaysPermission() { + return _permissionRepository.hasLocationAlwaysPermission(); + } + + Future requestLocationAlwaysPermission() { + return _permissionRepository.requestLocationAlwaysPermission(); + } + + Future getWifiName() async { + final canRead = await getLocationWhenInUserPermission(); + if (!canRead) { + return null; + } + + return await _repository.getWifiName(); + } + + Future openSettings() { + return _permissionRepository.openSettings(); + } +} diff --git a/mobile/lib/services/search.service.dart b/mobile/lib/services/search.service.dart index 3dd0106c09b47..14e53c3ce41af 100644 --- a/mobile/lib/services/search.service.dart +++ b/mobile/lib/services/search.service.dart @@ -77,7 +77,7 @@ class SearchService { ), ); } else { - response = await _apiService.searchApi.searchMetadata( + response = await _apiService.searchApi.searchAssets( MetadataSearchDto( originalFileName: filter.filename != null && filter.filename!.isNotEmpty diff --git a/mobile/lib/services/share.service.dart b/mobile/lib/services/share.service.dart index 40a2e0402b11e..d44d75931d09c 100644 --- a/mobile/lib/services/share.service.dart +++ b/mobile/lib/services/share.service.dart @@ -64,10 +64,13 @@ class ShareService { ); } - final box = context.findRenderObject() as RenderBox?; + final size = MediaQuery.of(context).size; Share.shareXFiles( downloadedXFiles, - sharePositionOrigin: box!.localToGlobal(Offset.zero) & box.size, + sharePositionOrigin: Rect.fromPoints( + Offset.zero, + Offset(size.width / 3, size.height), + ), ); return true; } catch (error) { diff --git a/mobile/lib/services/sync.service.dart b/mobile/lib/services/sync.service.dart index f1a6e9b0d7365..086ec097d1d37 100644 --- a/mobile/lib/services/sync.service.dart +++ b/mobile/lib/services/sync.service.dart @@ -403,6 +403,8 @@ class SyncService { album.lastModifiedAssetTimestamp = originalDto.lastModifiedAssetTimestamp; album.shared = dto.shared; album.activityEnabled = dto.activityEnabled; + album.sortOrder = dto.sortOrder; + final remoteThumbnailAssetId = dto.remoteThumbnailAssetId; if (remoteThumbnailAssetId != null && album.thumbnail.value?.remoteId != remoteThumbnailAssetId) { diff --git a/mobile/lib/services/user.service.dart b/mobile/lib/services/user.service.dart index 4c2b3cbbd00fb..13adcc4e7abf1 100644 --- a/mobile/lib/services/user.service.dart +++ b/mobile/lib/services/user.service.dart @@ -35,8 +35,9 @@ class UserService { this._syncService, ); - Future> getUsers({bool self = false}) => - _userRepository.getAll(self: self); + Future> getUsers({bool self = false}) { + return _userRepository.getAll(self: self); + } Future<({String profileImagePath})?> uploadProfileImage(XFile image) async { try { diff --git a/mobile/lib/constants/immich_colors.dart b/mobile/lib/theme/color_scheme.dart similarity index 84% rename from mobile/lib/constants/immich_colors.dart rename to mobile/lib/theme/color_scheme.dart index 6f6d1a6a31e88..c01b7cfa5a553 100644 --- a/mobile/lib/constants/immich_colors.dart +++ b/mobile/lib/theme/color_scheme.dart @@ -1,26 +1,8 @@ import 'package:flutter/material.dart'; -import 'package:immich_mobile/utils/immich_app_theme.dart'; +import 'package:immich_mobile/constants/colors.dart'; +import 'package:immich_mobile/theme/theme_data.dart'; -enum ImmichColorPreset { - indigo, - deepPurple, - pink, - red, - orange, - yellow, - lime, - green, - cyan, - slateGray -} - -const ImmichColorPreset defaultColorPreset = ImmichColorPreset.indigo; -const String defaultColorPresetName = "indigo"; - -const Color immichBrandColorLight = Color(0xFF4150AF); -const Color immichBrandColorDark = Color(0xFFACCBFA); - -final Map _themePresetsMap = { +final Map _themePresets = { ImmichColorPreset.indigo: ImmichTheme( light: ColorScheme.fromSeed( seedColor: immichBrandColorLight, @@ -107,5 +89,5 @@ final Map _themePresetsMap = { }; extension ImmichColorModeExtension on ImmichColorPreset { - ImmichTheme getTheme() => _themePresetsMap[this]!; + ImmichTheme get themeOfPreset => _themePresets[this]!; } diff --git a/mobile/lib/theme/dynamic_theme.dart b/mobile/lib/theme/dynamic_theme.dart new file mode 100644 index 0000000000000..39d6b6ee45e46 --- /dev/null +++ b/mobile/lib/theme/dynamic_theme.dart @@ -0,0 +1,38 @@ +import 'package:flutter/material.dart'; +import 'package:dynamic_color/dynamic_color.dart'; + +import 'package:immich_mobile/theme/theme_data.dart'; + +abstract final class DynamicTheme { + DynamicTheme._(); + + static ImmichTheme? _theme; + // Method to fetch dynamic system colors + static Future fetchSystemPalette() async { + try { + final corePalette = await DynamicColorPlugin.getCorePalette(); + if (corePalette != null) { + final primaryColor = corePalette.toColorScheme().primary; + debugPrint('dynamic_color: Core palette detected.'); + + // Some palettes do not generate surface container colors accurately, + // so we regenerate all colors using the primary color + _theme = ImmichTheme( + light: ColorScheme.fromSeed( + seedColor: primaryColor, + brightness: Brightness.light, + ), + dark: ColorScheme.fromSeed( + seedColor: primaryColor, + brightness: Brightness.dark, + ), + ); + } + } catch (error) { + debugPrint('dynamic_color: Failed to obtain core palette: $error'); + } + } + + static ImmichTheme? get theme => _theme; + static bool get isAvailable => _theme != null; +} diff --git a/mobile/lib/utils/immich_app_theme.dart b/mobile/lib/theme/theme_data.dart similarity index 55% rename from mobile/lib/utils/immich_app_theme.dart rename to mobile/lib/theme/theme_data.dart index c0cf60514f04d..de96e12c5d2c3 100644 --- a/mobile/lib/utils/immich_app_theme.dart +++ b/mobile/lib/theme/theme_data.dart @@ -1,192 +1,59 @@ -import 'package:dynamic_color/dynamic_color.dart'; import 'package:flutter/material.dart'; -import 'package:hooks_riverpod/hooks_riverpod.dart'; -import 'package:immich_mobile/constants/immich_colors.dart'; + +import 'package:immich_mobile/constants/locales.dart'; import 'package:immich_mobile/extensions/theme_extensions.dart'; -import 'package:immich_mobile/providers/app_settings.provider.dart'; -import 'package:immich_mobile/services/app_settings.service.dart'; class ImmichTheme { - ColorScheme light; - ColorScheme dark; + final ColorScheme light; + final ColorScheme dark; - ImmichTheme({required this.light, required this.dark}); + const ImmichTheme({required this.light, required this.dark}); } -ImmichTheme? _immichDynamicTheme; -bool get isDynamicThemeAvailable => _immichDynamicTheme != null; - -final immichThemeModeProvider = StateProvider((ref) { - var themeMode = ref - .watch(appSettingsServiceProvider) - .getSetting(AppSettingsEnum.themeMode); - - debugPrint("Current themeMode $themeMode"); - - if (themeMode == "light") { - return ThemeMode.light; - } else if (themeMode == "dark") { - return ThemeMode.dark; - } else { - return ThemeMode.system; - } -}); - -final immichThemePresetProvider = StateProvider((ref) { - var appSettingsProvider = ref.watch(appSettingsServiceProvider); - var primaryColorName = - appSettingsProvider.getSetting(AppSettingsEnum.primaryColor); - - debugPrint("Current theme preset $primaryColorName"); - - try { - return ImmichColorPreset.values - .firstWhere((e) => e.name == primaryColorName); - } catch (e) { - debugPrint( - "Theme preset $primaryColorName not found. Applying default preset.", - ); - appSettingsProvider.setSetting( - AppSettingsEnum.primaryColor, - defaultColorPresetName, - ); - return defaultColorPreset; - } -}); - -final dynamicThemeSettingProvider = StateProvider((ref) { - return ref - .watch(appSettingsServiceProvider) - .getSetting(AppSettingsEnum.dynamicTheme); -}); - -final colorfulInterfaceSettingProvider = StateProvider((ref) { - return ref - .watch(appSettingsServiceProvider) - .getSetting(AppSettingsEnum.colorfulInterface); -}); - -// Provider for current selected theme -final immichThemeProvider = StateProvider((ref) { - var primaryColor = ref.read(immichThemePresetProvider); - var useSystemColor = ref.watch(dynamicThemeSettingProvider); - var useColorfulInterface = ref.watch(colorfulInterfaceSettingProvider); - - var currentTheme = (useSystemColor && _immichDynamicTheme != null) - ? _immichDynamicTheme! - : primaryColor.getTheme(); - - return useColorfulInterface - ? currentTheme - : _decolorizeSurfaces(theme: currentTheme); -}); - -// Method to fetch dynamic system colors -Future fetchSystemPalette() async { - try { - final corePalette = await DynamicColorPlugin.getCorePalette(); - if (corePalette != null) { - final primaryColor = corePalette.toColorScheme().primary; - debugPrint('dynamic_color: Core palette detected.'); - - // Some palettes do not generate surface container colors accurately, - // so we regenerate all colors using the primary color - _immichDynamicTheme = ImmichTheme( - light: ColorScheme.fromSeed( - seedColor: primaryColor, - brightness: Brightness.light, - ), - dark: ColorScheme.fromSeed( - seedColor: primaryColor, - brightness: Brightness.dark, - ), - ); - } - } catch (e) { - debugPrint('dynamic_color: Failed to obtain core palette.'); - } -} - -// This method replaces all surface shades in ImmichTheme to a static ones -// as we are creating the colorscheme through seedColor the default surfaces are -// tinted with primary color -ImmichTheme _decolorizeSurfaces({ - required ImmichTheme theme, +ThemeData getThemeData({ + required ColorScheme colorScheme, + required Locale locale, }) { - return ImmichTheme( - light: theme.light.copyWith( - surface: const Color(0xFFf9f9f9), - onSurface: const Color(0xFF1b1b1b), - surfaceContainerLowest: const Color(0xFFffffff), - surfaceContainerLow: const Color(0xFFf3f3f3), - surfaceContainer: const Color(0xFFeeeeee), - surfaceContainerHigh: const Color(0xFFe8e8e8), - surfaceContainerHighest: const Color(0xFFe2e2e2), - surfaceDim: const Color(0xFFdadada), - surfaceBright: const Color(0xFFf9f9f9), - onSurfaceVariant: const Color(0xFF4c4546), - inverseSurface: const Color(0xFF303030), - onInverseSurface: const Color(0xFFf1f1f1), - ), - dark: theme.dark.copyWith( - surface: const Color(0xFF131313), - onSurface: const Color(0xFFE2E2E2), - surfaceContainerLowest: const Color(0xFF0E0E0E), - surfaceContainerLow: const Color(0xFF1B1B1B), - surfaceContainer: const Color(0xFF1F1F1F), - surfaceContainerHigh: const Color(0xFF242424), - surfaceContainerHighest: const Color(0xFF2E2E2E), - surfaceDim: const Color(0xFF131313), - surfaceBright: const Color(0xFF353535), - onSurfaceVariant: const Color(0xFFCfC4C5), - inverseSurface: const Color(0xFFE2E2E2), - onInverseSurface: const Color(0xFF303030), - ), - ); -} - -ThemeData getThemeData({required ColorScheme colorScheme}) { - var isDark = colorScheme.brightness == Brightness.dark; - var primaryColor = colorScheme.primary; + final isDark = colorScheme.brightness == Brightness.dark; return ThemeData( useMaterial3: true, - brightness: isDark ? Brightness.dark : Brightness.light, + brightness: colorScheme.brightness, colorScheme: colorScheme, - primaryColor: primaryColor, + primaryColor: colorScheme.primary, hintColor: colorScheme.onSurfaceSecondary, - focusColor: primaryColor, + focusColor: colorScheme.primary, scaffoldBackgroundColor: colorScheme.surface, - splashColor: primaryColor.withOpacity(0.1), - highlightColor: primaryColor.withOpacity(0.1), + splashColor: colorScheme.primary.withOpacity(0.1), + highlightColor: colorScheme.primary.withOpacity(0.1), dialogBackgroundColor: colorScheme.surfaceContainer, bottomSheetTheme: BottomSheetThemeData( backgroundColor: colorScheme.surfaceContainer, ), - fontFamily: 'Overpass', + fontFamily: _getFontFamilyFromLocale(locale), snackBarTheme: SnackBarThemeData( contentTextStyle: TextStyle( - fontFamily: 'Overpass', - color: primaryColor, + fontFamily: _getFontFamilyFromLocale(locale), + color: colorScheme.primary, fontWeight: FontWeight.bold, ), backgroundColor: colorScheme.surfaceContainerHighest, ), appBarTheme: AppBarTheme( titleTextStyle: TextStyle( - color: primaryColor, - fontFamily: 'Overpass', + color: colorScheme.primary, + fontFamily: _getFontFamilyFromLocale(locale), fontWeight: FontWeight.bold, fontSize: 18, ), backgroundColor: isDark ? colorScheme.surfaceContainer : colorScheme.surface, - foregroundColor: primaryColor, + foregroundColor: colorScheme.primary, elevation: 0, scrolledUnderElevation: 0, centerTitle: true, ), - textTheme: TextTheme( + textTheme: const TextTheme( displayLarge: TextStyle( fontSize: 26, fontWeight: FontWeight.bold, @@ -199,22 +66,22 @@ ThemeData getThemeData({required ColorScheme colorScheme}) { fontSize: 12, fontWeight: FontWeight.bold, ), - titleSmall: const TextStyle( + titleSmall: TextStyle( fontSize: 16.0, fontWeight: FontWeight.bold, ), - titleMedium: const TextStyle( + titleMedium: TextStyle( fontSize: 18.0, fontWeight: FontWeight.bold, ), - titleLarge: const TextStyle( + titleLarge: TextStyle( fontSize: 26.0, fontWeight: FontWeight.bold, ), ), elevatedButtonTheme: ElevatedButtonThemeData( style: ElevatedButton.styleFrom( - backgroundColor: primaryColor, + backgroundColor: colorScheme.primary, foregroundColor: isDark ? Colors.black87 : Colors.white, ), ), @@ -246,7 +113,7 @@ ThemeData getThemeData({required ColorScheme colorScheme}) { inputDecorationTheme: InputDecorationTheme( focusedBorder: OutlineInputBorder( borderSide: BorderSide( - color: primaryColor, + color: colorScheme.primary, ), borderRadius: const BorderRadius.all(Radius.circular(15)), ), @@ -257,7 +124,7 @@ ThemeData getThemeData({required ColorScheme colorScheme}) { borderRadius: const BorderRadius.all(Radius.circular(15)), ), labelStyle: TextStyle( - color: primaryColor, + color: colorScheme.primary, ), hintStyle: const TextStyle( fontSize: 14.0, @@ -265,20 +132,20 @@ ThemeData getThemeData({required ColorScheme colorScheme}) { ), ), textSelectionTheme: TextSelectionThemeData( - cursorColor: primaryColor, + cursorColor: colorScheme.primary, ), dropdownMenuTheme: DropdownMenuThemeData( - menuStyle: MenuStyle( + menuStyle: const MenuStyle( shape: WidgetStatePropertyAll( RoundedRectangleBorder( - borderRadius: BorderRadius.circular(15), + borderRadius: BorderRadius.all(Radius.circular(15)), ), ), ), inputDecorationTheme: InputDecorationTheme( focusedBorder: OutlineInputBorder( borderSide: BorderSide( - color: primaryColor, + color: colorScheme.primary, ), ), enabledBorder: OutlineInputBorder( @@ -288,7 +155,7 @@ ThemeData getThemeData({required ColorScheme colorScheme}) { borderRadius: const BorderRadius.all(Radius.circular(15)), ), labelStyle: TextStyle( - color: primaryColor, + color: colorScheme.primary, ), hintStyle: const TextStyle( fontSize: 14.0, @@ -298,3 +165,49 @@ ThemeData getThemeData({required ColorScheme colorScheme}) { ), ); } + +// This method replaces all surface shades in ImmichTheme to a static ones +// as we are creating the colorscheme through seedColor the default surfaces are +// tinted with primary color +ImmichTheme decolorizeSurfaces({ + required ImmichTheme theme, +}) { + return ImmichTheme( + light: theme.light.copyWith( + surface: const Color(0xFFf9f9f9), + onSurface: const Color(0xFF1b1b1b), + surfaceContainerLowest: const Color(0xFFffffff), + surfaceContainerLow: const Color(0xFFf3f3f3), + surfaceContainer: const Color(0xFFeeeeee), + surfaceContainerHigh: const Color(0xFFe8e8e8), + surfaceContainerHighest: const Color(0xFFe2e2e2), + surfaceDim: const Color(0xFFdadada), + surfaceBright: const Color(0xFFf9f9f9), + onSurfaceVariant: const Color(0xFF4c4546), + inverseSurface: const Color(0xFF303030), + onInverseSurface: const Color(0xFFf1f1f1), + ), + dark: theme.dark.copyWith( + surface: const Color(0xFF131313), + onSurface: const Color(0xFFE2E2E2), + surfaceContainerLowest: const Color(0xFF0E0E0E), + surfaceContainerLow: const Color(0xFF1B1B1B), + surfaceContainer: const Color(0xFF1F1F1F), + surfaceContainerHigh: const Color(0xFF242424), + surfaceContainerHighest: const Color(0xFF2E2E2E), + surfaceDim: const Color(0xFF131313), + surfaceBright: const Color(0xFF353535), + onSurfaceVariant: const Color(0xFFCfC4C5), + inverseSurface: const Color(0xFFE2E2E2), + onInverseSurface: const Color(0xFF303030), + ), + ); +} + +String? _getFontFamilyFromLocale(Locale locale) { + if (localesNotSupportedByOverpass.contains(locale)) { + // Let Flutter use the default font + return null; + } + return 'Overpass'; +} diff --git a/mobile/lib/utils/debounce.dart b/mobile/lib/utils/debounce.dart index ca5f8fc2beef0..78870151a6e78 100644 --- a/mobile/lib/utils/debounce.dart +++ b/mobile/lib/utils/debounce.dart @@ -3,20 +3,52 @@ import 'dart:async'; import 'package:flutter_hooks/flutter_hooks.dart'; /// Used to debounce function calls with the [interval] provided. +/// If [maxWaitTime] is provided, the first [run] call as well as the next call since [maxWaitTime] has passed will be immediately executed, even if [interval] is not satisfied. class Debouncer { - Debouncer({required this.interval}); + Debouncer({required this.interval, this.maxWaitTime}); final Duration interval; + final Duration? maxWaitTime; Timer? _timer; FutureOr Function()? _lastAction; + DateTime? _lastActionTime; + Future? _actionFuture; void run(FutureOr Function() action) { _lastAction = action; _timer?.cancel(); + + if (maxWaitTime != null && + // _actionFuture == null && // TODO: should this check be here? + (_lastActionTime == null || + DateTime.now().difference(_lastActionTime!) > maxWaitTime!)) { + _callAndRest(); + return; + } _timer = Timer(interval, _callAndRest); } + Future? drain() { + if (_timer != null && _timer!.isActive) { + _timer!.cancel(); + if (_lastAction != null) { + _callAndRest(); + } + } + return _actionFuture; + } + + @pragma('vm:prefer-inline') void _callAndRest() { - _lastAction?.call(); + _lastActionTime = DateTime.now(); + final action = _lastAction; + _lastAction = null; + + final result = action!(); + if (result is Future) { + _actionFuture = result.whenComplete(() { + _actionFuture = null; + }); + } _timer = null; } @@ -24,31 +56,48 @@ class Debouncer { _timer?.cancel(); _timer = null; _lastAction = null; + _lastActionTime = null; + _actionFuture = null; } + + bool get isActive => + _actionFuture != null || (_timer != null && _timer!.isActive); } /// Creates a [Debouncer] that will be disposed automatically. If no [interval] is provided, a /// default interval of 300ms is used to debounce the function calls Debouncer useDebouncer({ Duration interval = const Duration(milliseconds: 300), + Duration? maxWaitTime, List? keys, }) => - use(_DebouncerHook(interval: interval, keys: keys)); + use( + _DebouncerHook( + interval: interval, + maxWaitTime: maxWaitTime, + keys: keys, + ), + ); class _DebouncerHook extends Hook { const _DebouncerHook({ required this.interval, + this.maxWaitTime, super.keys, }); final Duration interval; + final Duration? maxWaitTime; @override HookState> createState() => _DebouncerHookState(); } class _DebouncerHookState extends HookState { - late final debouncer = Debouncer(interval: hook.interval); + late final debouncer = Debouncer( + interval: hook.interval, + maxWaitTime: hook.maxWaitTime, + ); @override Debouncer build(_) => debouncer; diff --git a/mobile/lib/utils/hooks/chewiew_controller_hook.dart b/mobile/lib/utils/hooks/chewiew_controller_hook.dart deleted file mode 100644 index 2868e896cf2f4..0000000000000 --- a/mobile/lib/utils/hooks/chewiew_controller_hook.dart +++ /dev/null @@ -1,161 +0,0 @@ -import 'package:chewie/chewie.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_hooks/flutter_hooks.dart'; -import 'package:video_player/video_player.dart'; - -/// Provides the initialized video player controller -/// If the asset is local, use the local file -/// Otherwise, use a video player with a URL -ChewieController useChewieController({ - required VideoPlayerController controller, - EdgeInsets controlsSafeAreaMinimum = const EdgeInsets.only( - bottom: 100, - ), - bool showOptions = true, - bool showControlsOnInitialize = false, - bool autoPlay = true, - bool allowFullScreen = false, - bool allowedScreenSleep = false, - bool showControls = true, - bool loopVideo = false, - Widget? customControls, - Widget? placeholder, - Duration hideControlsTimer = const Duration(seconds: 1), - VoidCallback? onPlaying, - VoidCallback? onPaused, - VoidCallback? onVideoEnded, -}) { - return use( - _ChewieControllerHook( - controller: controller, - placeholder: placeholder, - showOptions: showOptions, - controlsSafeAreaMinimum: controlsSafeAreaMinimum, - autoPlay: autoPlay, - allowFullScreen: allowFullScreen, - customControls: customControls, - hideControlsTimer: hideControlsTimer, - showControlsOnInitialize: showControlsOnInitialize, - showControls: showControls, - loopVideo: loopVideo, - allowedScreenSleep: allowedScreenSleep, - onPlaying: onPlaying, - onPaused: onPaused, - onVideoEnded: onVideoEnded, - ), - ); -} - -class _ChewieControllerHook extends Hook { - final VideoPlayerController controller; - final EdgeInsets controlsSafeAreaMinimum; - final bool showOptions; - final bool showControlsOnInitialize; - final bool autoPlay; - final bool allowFullScreen; - final bool allowedScreenSleep; - final bool showControls; - final bool loopVideo; - final Widget? customControls; - final Widget? placeholder; - final Duration hideControlsTimer; - final VoidCallback? onPlaying; - final VoidCallback? onPaused; - final VoidCallback? onVideoEnded; - - const _ChewieControllerHook({ - required this.controller, - this.controlsSafeAreaMinimum = const EdgeInsets.only( - bottom: 100, - ), - this.showOptions = true, - this.showControlsOnInitialize = false, - this.autoPlay = true, - this.allowFullScreen = false, - this.allowedScreenSleep = false, - this.showControls = true, - this.loopVideo = false, - this.customControls, - this.placeholder, - this.hideControlsTimer = const Duration(seconds: 3), - this.onPlaying, - this.onPaused, - this.onVideoEnded, - }); - - @override - createState() => _ChewieControllerHookState(); -} - -class _ChewieControllerHookState - extends HookState { - late ChewieController chewieController = ChewieController( - videoPlayerController: hook.controller, - controlsSafeAreaMinimum: hook.controlsSafeAreaMinimum, - showOptions: hook.showOptions, - showControlsOnInitialize: hook.showControlsOnInitialize, - autoPlay: hook.autoPlay, - allowFullScreen: hook.allowFullScreen, - allowedScreenSleep: hook.allowedScreenSleep, - showControls: hook.showControls, - looping: hook.loopVideo, - customControls: hook.customControls, - placeholder: hook.placeholder, - hideControlsTimer: hook.hideControlsTimer, - ); - - @override - void dispose() { - chewieController.dispose(); - super.dispose(); - } - - @override - ChewieController build(BuildContext context) { - return chewieController; - } - - /* - /// Initializes the chewie controller and video player controller - Future _initialize() async { - if (hook.asset.isLocal && hook.asset.livePhotoVideoId == null) { - // Use a local file for the video player controller - final file = await hook.asset.local!.file; - if (file == null) { - throw Exception('No file found for the video'); - } - videoPlayerController = VideoPlayerController.file(file); - } else { - // Use a network URL for the video player controller - final serverEndpoint = store.Store.get(store.StoreKey.serverEndpoint); - final String videoUrl = hook.asset.livePhotoVideoId != null - ? '$serverEndpoint/assets/${hook.asset.livePhotoVideoId}/video/playback' - : '$serverEndpoint/assets/${hook.asset.remoteId}/video/playback'; - - final url = Uri.parse(videoUrl); - final accessToken = store.Store.get(StoreKey.accessToken); - - videoPlayerController = VideoPlayerController.networkUrl( - url, - httpHeaders: {"x-immich-user-token": accessToken}, - ); - } - - await videoPlayerController!.initialize(); - - chewieController = ChewieController( - videoPlayerController: videoPlayerController!, - controlsSafeAreaMinimum: hook.controlsSafeAreaMinimum, - showOptions: hook.showOptions, - showControlsOnInitialize: hook.showControlsOnInitialize, - autoPlay: hook.autoPlay, - allowFullScreen: hook.allowFullScreen, - allowedScreenSleep: hook.allowedScreenSleep, - showControls: hook.showControls, - customControls: hook.customControls, - placeholder: hook.placeholder, - hideControlsTimer: hook.hideControlsTimer, - ); - } - */ -} diff --git a/mobile/lib/utils/hooks/interval_hook.dart b/mobile/lib/utils/hooks/interval_hook.dart new file mode 100644 index 0000000000000..0c346065f7210 --- /dev/null +++ b/mobile/lib/utils/hooks/interval_hook.dart @@ -0,0 +1,18 @@ +import 'dart:async'; +import 'dart:ui'; + +import 'package:flutter_hooks/flutter_hooks.dart'; + +// https://github.com/rrousselGit/flutter_hooks/issues/233#issuecomment-840416638 +void useInterval(Duration delay, VoidCallback callback) { + final savedCallback = useRef(callback); + savedCallback.value = callback; + + useEffect( + () { + final timer = Timer.periodic(delay, (_) => savedCallback.value()); + return timer.cancel; + }, + [delay], + ); +} diff --git a/mobile/lib/utils/migration.dart b/mobile/lib/utils/migration.dart index 2b02a5ff8f290..681f8a22cedd6 100644 --- a/mobile/lib/utils/migration.dart +++ b/mobile/lib/utils/migration.dart @@ -4,7 +4,7 @@ import 'package:immich_mobile/entities/store.entity.dart'; import 'package:immich_mobile/utils/db.dart'; import 'package:isar/isar.dart'; -const int targetVersion = 6; +const int targetVersion = 8; Future migrateDatabaseIfNeeded(Isar db) async { final int version = Store.get(StoreKey.version, 1); diff --git a/mobile/lib/utils/throttle.dart b/mobile/lib/utils/throttle.dart index 9a54e01fc195c..bc0dcf9e2fe2a 100644 --- a/mobile/lib/utils/throttle.dart +++ b/mobile/lib/utils/throttle.dart @@ -1,5 +1,3 @@ -import 'dart:async'; - import 'package:flutter_hooks/flutter_hooks.dart'; /// Throttles function calls with the [interval] provided. @@ -10,12 +8,15 @@ class Throttler { Throttler({required this.interval}); - void run(FutureOr Function() action) { + T? run(T Function() action) { if (_lastActionTime == null || (DateTime.now().difference(_lastActionTime!) > interval)) { - action(); + final response = action(); _lastActionTime = DateTime.now(); + return response; } + + return null; } void dispose() { diff --git a/mobile/lib/widgets/album/album_viewer_appbar.dart b/mobile/lib/widgets/album/album_viewer_appbar.dart index 89528cc4da365..7c36ebc21d4e4 100644 --- a/mobile/lib/widgets/album/album_viewer_appbar.dart +++ b/mobile/lib/widgets/album/album_viewer_appbar.dart @@ -1,22 +1,21 @@ 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:fluttertoast/fluttertoast.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/providers/activity_statistics.provider.dart'; import 'package:immich_mobile/providers/album/album.provider.dart'; import 'package:immich_mobile/providers/album/album_viewer.provider.dart'; -import 'package:immich_mobile/utils/immich_loading_overlay.dart'; +import 'package:immich_mobile/providers/album/current_album.provider.dart'; import 'package:immich_mobile/routing/router.dart'; -import 'package:immich_mobile/entities/album.entity.dart'; import 'package:immich_mobile/widgets/common/immich_toast.dart'; class AlbumViewerAppbar extends HookConsumerWidget implements PreferredSizeWidget { const AlbumViewerAppbar({ super.key, - required this.album, required this.userId, required this.titleFocusNode, this.onAddPhotos, @@ -24,34 +23,48 @@ class AlbumViewerAppbar extends HookConsumerWidget required this.onActivities, }); - final Album album; final String userId; final FocusNode titleFocusNode; - final Function(Album album)? onAddPhotos; - final Function(Album album)? onAddUsers; - final Function(Album album) onActivities; + final void Function()? onAddPhotos; + final void Function()? onAddUsers; + final void Function() onActivities; @override Widget build(BuildContext context, WidgetRef ref) { - final newAlbumTitle = ref.watch(albumViewerProvider).editTitleText; - final isEditAlbum = ref.watch(albumViewerProvider).isEditAlbum; - final isProcessing = useProcessingOverlay(); + final albumState = useState(ref.read(currentAlbumProvider)); + final album = albumState.value; + ref.listen(currentAlbumProvider, (_, newAlbum) { + final oldAlbum = albumState.value; + if (oldAlbum != null && newAlbum != null && oldAlbum.id == newAlbum.id) { + return; + } + + albumState.value = newAlbum; + }); + + if (album == null) { + return const SizedBox(); + } + + final albumViewer = ref.watch(albumViewerProvider); + final newAlbumTitle = albumViewer.editTitleText; + final isEditAlbum = albumViewer.isEditAlbum; + final comments = album.shared ? ref.watch(activityStatisticsProvider(album.remoteId!)) : 0; deleteAlbum() async { - isProcessing.value = true; + final bool success = + await ref.watch(albumProvider.notifier).deleteAlbum(album); - final bool success; if (album.shared) { - success = await ref.watch(albumProvider.notifier).deleteAlbum(album); - context.navigateTo(TabControllerRoute(children: [AlbumsRoute()])); + context.navigateTo(const TabControllerRoute(children: [AlbumsRoute()])); } else { - success = await ref.watch(albumProvider.notifier).deleteAlbum(album); context .navigateTo(const TabControllerRoute(children: [LibraryRoute()])); } + if (!success) { ImmichToast.show( context: context, @@ -60,11 +73,9 @@ class AlbumViewerAppbar extends HookConsumerWidget gravity: ToastGravity.BOTTOM, ); } - - isProcessing.value = false; } - Future showConfirmationDialog() async { + Future onDeleteAlbumPressed() { return showDialog( context: context, barrierDismissible: false, // user must tap button! @@ -102,18 +113,12 @@ class AlbumViewerAppbar extends HookConsumerWidget ); } - void onDeleteAlbumPressed() async { - showConfirmationDialog(); - } - void onLeaveAlbumPressed() async { - isProcessing.value = true; - bool isSuccess = await ref.watch(albumProvider.notifier).leaveAlbum(album); if (isSuccess) { - context.navigateTo(TabControllerRoute(children: [AlbumsRoute()])); + context.navigateTo(const TabControllerRoute(children: [AlbumsRoute()])); } else { context.pop(); ImmichToast.show( @@ -123,8 +128,6 @@ class AlbumViewerAppbar extends HookConsumerWidget gravity: ToastGravity.BOTTOM, ); } - - isProcessing.value = false; } buildBottomSheetActions() { @@ -136,7 +139,7 @@ class AlbumViewerAppbar extends HookConsumerWidget 'album_viewer_appbar_share_delete', style: TextStyle(fontWeight: FontWeight.w500), ).tr(), - onTap: () => onDeleteAlbumPressed(), + onTap: onDeleteAlbumPressed, ) : ListTile( leading: const Icon(Icons.person_remove_rounded), @@ -144,25 +147,52 @@ class AlbumViewerAppbar extends HookConsumerWidget 'album_viewer_appbar_share_leave', style: TextStyle(fontWeight: FontWeight.w500), ).tr(), - onTap: () => onLeaveAlbumPressed(), + onTap: onLeaveAlbumPressed, ), ]; // } } + void onSortOrderToggled() async { + final updatedAlbum = + await ref.read(albumProvider.notifier).toggleSortOrder(album); + + if (updatedAlbum == null) { + ImmichToast.show( + context: context, + msg: "error_change_sort_album".tr(), + toastType: ToastType.error, + gravity: ToastGravity.BOTTOM, + ); + } + + context.pop(); + } + void buildBottomSheet() { final ownerActions = [ ListTile( leading: const Icon(Icons.person_add_alt_rounded), onTap: () { context.pop(); - onAddUsers!(album); + final onAddUsers = this.onAddUsers; + if (onAddUsers != null) { + onAddUsers(); + } }, title: const Text( "album_viewer_page_share_add_users", style: TextStyle(fontWeight: FontWeight.w500), ).tr(), ), + ListTile( + leading: const Icon(Icons.swap_vert_rounded), + onTap: onSortOrderToggled, + title: const Text( + "change_display_order", + style: TextStyle(fontWeight: FontWeight.w500), + ).tr(), + ), ListTile( leading: const Icon(Icons.share_rounded), onTap: () { @@ -176,7 +206,7 @@ class AlbumViewerAppbar extends HookConsumerWidget ), ListTile( leading: const Icon(Icons.settings_rounded), - onTap: () => context.navigateTo(AlbumOptionsRoute(album: album)), + onTap: () => context.navigateTo(AlbumOptionsRoute()), title: const Text( "translated_text_options", style: TextStyle(fontWeight: FontWeight.w500), @@ -189,7 +219,10 @@ class AlbumViewerAppbar extends HookConsumerWidget leading: const Icon(Icons.add_photo_alternate_outlined), onTap: () { context.pop(); - onAddPhotos!(album); + final onAddPhotos = this.onAddPhotos; + if (onAddPhotos != null) { + onAddPhotos(); + } }, title: const Text( "share_add_photos", @@ -222,9 +255,7 @@ class AlbumViewerAppbar extends HookConsumerWidget Widget buildActivitiesButton() { return IconButton( - onPressed: () { - onActivities(album); - }, + onPressed: onActivities, icon: Row( crossAxisAlignment: CrossAxisAlignment.center, children: [ @@ -271,7 +302,7 @@ class AlbumViewerAppbar extends HookConsumerWidget ); } else { return IconButton( - onPressed: () async => await context.maybePop(), + onPressed: context.maybePop, icon: const Icon(Icons.arrow_back_ios_rounded), splashRadius: 25, ); @@ -285,12 +316,13 @@ class AlbumViewerAppbar extends HookConsumerWidget actions: [ if (album.shared && (album.activityEnabled || comments != 0)) buildActivitiesButton(), - if (album.isRemote) + if (album.isRemote) ...[ IconButton( splashRadius: 25, onPressed: buildBottomSheet, icon: const Icon(Icons.more_horiz_rounded), ), + ], ], ); } diff --git a/mobile/lib/widgets/album/album_viewer_editable_title.dart b/mobile/lib/widgets/album/album_viewer_editable_title.dart index 59e09aa05058e..7547dff932f03 100644 --- a/mobile/lib/widgets/album/album_viewer_editable_title.dart +++ b/mobile/lib/widgets/album/album_viewer_editable_title.dart @@ -4,20 +4,19 @@ import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/providers/album/album_viewer.provider.dart'; -import 'package:immich_mobile/entities/album.entity.dart'; class AlbumViewerEditableTitle extends HookConsumerWidget { - final Album album; + final String albumName; final FocusNode titleFocusNode; const AlbumViewerEditableTitle({ super.key, - required this.album, + required this.albumName, required this.titleFocusNode, }); @override Widget build(BuildContext context, WidgetRef ref) { - final titleTextEditController = useTextEditingController(text: album.name); + final titleTextEditController = useTextEditingController(text: albumName); void onFocusModeChange() { if (!titleFocusNode.hasFocus && titleTextEditController.text.isEmpty) { @@ -49,9 +48,9 @@ class AlbumViewerEditableTitle extends HookConsumerWidget { style: context.textTheme.headlineMedium, controller: titleTextEditController, onTap: () { - FocusScope.of(context).requestFocus(titleFocusNode); + context.focusScope.requestFocus(titleFocusNode); - ref.watch(albumViewerProvider.notifier).setEditTitleText(album.name); + ref.watch(albumViewerProvider.notifier).setEditTitleText(albumName); ref.watch(albumViewerProvider.notifier).enableEditAlbum(); if (titleTextEditController.text == 'Untitled') { diff --git a/mobile/lib/widgets/asset_grid/immich_asset_grid_view.dart b/mobile/lib/widgets/asset_grid/immich_asset_grid_view.dart index 38e499b5dec8e..c38e61a47356d 100644 --- a/mobile/lib/widgets/asset_grid/immich_asset_grid_view.dart +++ b/mobile/lib/widgets/asset_grid/immich_asset_grid_view.dart @@ -12,7 +12,10 @@ import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/extensions/collection_extensions.dart'; import 'package:immich_mobile/extensions/theme_extensions.dart'; +import 'package:immich_mobile/providers/asset_viewer/current_asset.provider.dart'; +import 'package:immich_mobile/providers/asset_viewer/is_motion_video_playing.provider.dart'; import 'package:immich_mobile/providers/asset_viewer/scroll_notifier.provider.dart'; +import 'package:immich_mobile/providers/asset_viewer/show_controls.provider.dart'; import 'package:immich_mobile/widgets/asset_grid/asset_drag_region.dart'; import 'package:immich_mobile/widgets/asset_grid/thumbnail_image.dart'; import 'package:immich_mobile/widgets/asset_grid/thumbnail_placeholder.dart'; @@ -89,6 +92,7 @@ class ImmichAssetGridViewState extends ConsumerState { ScrollOffsetController(); final ItemPositionsListener _itemPositionsListener = ItemPositionsListener.create(); + late final KeepAliveLink currentAssetLink; /// The timestamp when the haptic feedback was last invoked int _hapticFeedbackTS = 0; @@ -201,6 +205,13 @@ class ImmichAssetGridViewState extends ConsumerState { allAssetsSelected: _allAssetsSelected, showStack: widget.showStack, heroOffset: widget.heroOffset, + onAssetTap: (asset) { + ref.read(currentAssetProvider.notifier).set(asset); + ref.read(isPlayingMotionVideoProvider.notifier).playing = false; + if (asset.isVideo) { + ref.read(showControlsProvider.notifier).show = false; + } + }, ); } @@ -348,6 +359,7 @@ class ImmichAssetGridViewState extends ConsumerState { @override void initState() { super.initState(); + currentAssetLink = ref.read(currentAssetProvider.notifier).ref.keepAlive(); scrollToTopNotifierProvider.addListener(_scrollToTop); scrollToDateNotifierProvider.addListener(_scrollToDate); @@ -369,6 +381,7 @@ class ImmichAssetGridViewState extends ConsumerState { _itemPositionsListener.itemPositions.removeListener(_positionListener); } _itemPositionsListener.itemPositions.removeListener(_hapticsListener); + currentAssetLink.close(); super.dispose(); } @@ -595,12 +608,13 @@ class _Section extends StatelessWidget { final RenderList renderList; final bool selectionActive; final bool dynamicLayout; - final Function(List) selectAssets; - final Function(List) deselectAssets; + final void Function(List) selectAssets; + final void Function(List) deselectAssets; final bool Function(List) allAssetsSelected; final bool showStack; final int heroOffset; final bool showStorageIndicator; + final void Function(Asset) onAssetTap; const _Section({ required this.section, @@ -618,6 +632,7 @@ class _Section extends StatelessWidget { required this.showStack, required this.heroOffset, required this.showStorageIndicator, + required this.onAssetTap, }); @override @@ -683,6 +698,7 @@ class _Section extends StatelessWidget { selectionActive: selectionActive, onSelect: (asset) => selectAssets([asset]), onDeselect: (asset) => deselectAssets([asset]), + onAssetTap: onAssetTap, ), ], ); @@ -724,9 +740,9 @@ class _Title extends StatelessWidget { final String title; final List assets; final bool selectionActive; - final Function(List) selectAssets; - final Function(List) deselectAssets; - final Function(List) allAssetsSelected; + final void Function(List) selectAssets; + final void Function(List) deselectAssets; + final bool Function(List) allAssetsSelected; const _Title({ required this.title, @@ -765,8 +781,9 @@ class _AssetRow extends StatelessWidget { final bool showStorageIndicator; final int heroOffset; final bool showStack; - final Function(Asset)? onSelect; - final Function(Asset)? onDeselect; + final void Function(Asset) onAssetTap; + final void Function(Asset)? onSelect; + final void Function(Asset)? onDeselect; final bool isSelectionActive; const _AssetRow({ @@ -786,6 +803,7 @@ class _AssetRow extends StatelessWidget { required this.showStack, required this.isSelectionActive, required this.selectedAssets, + required this.onAssetTap, this.onSelect, this.onDeselect, }); @@ -838,6 +856,8 @@ class _AssetRow extends StatelessWidget { onSelect?.call(asset); } } else { + final asset = renderList.loadAsset(absoluteOffset + index); + onAssetTap(asset); context.pushRoute( GalleryViewerRoute( renderList: renderList, diff --git a/mobile/lib/widgets/asset_grid/multiselect_grid.dart b/mobile/lib/widgets/asset_grid/multiselect_grid.dart index eeecfa9b58435..6bcd6e5784140 100644 --- a/mobile/lib/widgets/asset_grid/multiselect_grid.dart +++ b/mobile/lib/widgets/asset_grid/multiselect_grid.dart @@ -203,18 +203,30 @@ class MultiselectGrid extends HookConsumerWidget { void onDeleteLocal(bool onlyBackedUp) async { processing.value = true; try { + // Select only the local assets from the selection final localIds = selection.value.where((a) => a.isLocal).toList(); + // Delete only the backed-up assets if 'onlyBackedUp' is true final isDeleted = await ref .read(assetProvider.notifier) .deleteLocalOnlyAssets(localIds, onlyBackedUp: onlyBackedUp); + if (isDeleted) { + // Show a toast with the correct number of deleted assets + final deletedCount = localIds + .where( + (e) => !onlyBackedUp || e.isRemote, + ) // Only count backed-up assets + .length; + ImmichToast.show( context: context, msg: 'assets_removed_permanently_from_device' - .tr(args: ["${localIds.length}"]), + .tr(args: ["$deletedCount"]), gravity: ToastGravity.BOTTOM, ); + + // Reset the selection selectionEnabledHook.value = false; } } finally { @@ -421,6 +433,7 @@ class MultiselectGrid extends HookConsumerWidget { ), if (selectionEnabledHook.value) ControlBottomAppBar( + key: const ValueKey("controlBottomAppBar"), onShare: onShareAssets, onFavorite: favoriteEnabled ? onFavoriteAssets : null, onArchive: archiveEnabled ? onArchiveAsset : null, diff --git a/mobile/lib/widgets/asset_grid/multiselect_grid_status_indicator.dart b/mobile/lib/widgets/asset_grid/multiselect_grid_status_indicator.dart new file mode 100644 index 0000000000000..b17029f2af04b --- /dev/null +++ b/mobile/lib/widgets/asset_grid/multiselect_grid_status_indicator.dart @@ -0,0 +1,35 @@ +import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter/material.dart'; +import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:immich_mobile/providers/asset_viewer/render_list_status_provider.dart'; +import 'package:immich_mobile/widgets/common/delayed_loading_indicator.dart'; + +class MultiselectGridStatusIndicator extends HookConsumerWidget { + const MultiselectGridStatusIndicator({ + super.key, + this.buildLoadingIndicator, + this.emptyIndicator, + }); + + final Widget Function()? buildLoadingIndicator; + final Widget? emptyIndicator; + + @override + Widget build(BuildContext context, WidgetRef ref) { + final renderListStatus = ref.watch(renderListStatusProvider); + return switch (renderListStatus) { + RenderListStatusEnum.loading => buildLoadingIndicator == null + ? const Center( + child: DelayedLoadingIndicator( + delay: Duration(milliseconds: 500), + ), + ) + : buildLoadingIndicator!(), + RenderListStatusEnum.empty => + emptyIndicator ?? Center(child: const Text("no_assets_to_show").tr()), + RenderListStatusEnum.error => + Center(child: const Text("error_loading_assets").tr()), + RenderListStatusEnum.complete => const SizedBox() + }; + } +} diff --git a/mobile/lib/widgets/asset_viewer/advanced_bottom_sheet.dart b/mobile/lib/widgets/asset_viewer/advanced_bottom_sheet.dart index c63d98fb59d2b..367519fead492 100644 --- a/mobile/lib/widgets/asset_viewer/advanced_bottom_sheet.dart +++ b/mobile/lib/widgets/asset_viewer/advanced_bottom_sheet.dart @@ -54,7 +54,7 @@ class AdvancedBottomSheet extends HookConsumerWidget { text: assetDetail.toString(), ), ).then((_) { - ScaffoldMessenger.of(context).showSnackBar( + context.scaffoldMessenger.showSnackBar( SnackBar( content: Text( "Copied to clipboard", diff --git a/mobile/lib/widgets/asset_viewer/bottom_gallery_bar.dart b/mobile/lib/widgets/asset_viewer/bottom_gallery_bar.dart index f550857b9d867..256141dc7d273 100644 --- a/mobile/lib/widgets/asset_viewer/bottom_gallery_bar.dart +++ b/mobile/lib/widgets/asset_viewer/bottom_gallery_bar.dart @@ -9,6 +9,7 @@ import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/providers/album/album.provider.dart'; import 'package:immich_mobile/providers/album/current_album.provider.dart'; import 'package:immich_mobile/providers/asset_viewer/asset_stack.provider.dart'; +import 'package:immich_mobile/providers/asset_viewer/current_asset.provider.dart'; import 'package:immich_mobile/providers/asset_viewer/download.provider.dart'; import 'package:immich_mobile/providers/asset_viewer/show_controls.provider.dart'; import 'package:immich_mobile/services/stack.service.dart'; @@ -25,12 +26,10 @@ import 'package:immich_mobile/widgets/common/immich_toast.dart'; import 'package:immich_mobile/pages/editing/edit.page.dart'; class BottomGalleryBar extends ConsumerWidget { - final Asset asset; final ValueNotifier assetIndex; final bool showStack; - final int stackIndex; + final ValueNotifier stackIndex; final ValueNotifier totalAssets; - final bool showVideoPlayerControls; final PageController controller; final RenderList renderList; @@ -38,20 +37,24 @@ class BottomGalleryBar extends ConsumerWidget { super.key, required this.showStack, required this.stackIndex, - required this.asset, required this.assetIndex, required this.controller, required this.totalAssets, - required this.showVideoPlayerControls, required this.renderList, }); @override Widget build(BuildContext context, WidgetRef ref) { + final asset = ref.watch(currentAssetProvider); + if (asset == null) { + return const SizedBox(); + } final isOwner = asset.ownerId == ref.watch(currentUserProvider)?.isarId; + final showControls = ref.watch(showControlsProvider); + final stackId = asset.stackId; - final stackItems = showStack && asset.stackCount > 0 - ? ref.watch(assetStackStateProvider(asset)) + final stackItems = showStack && stackId != null + ? ref.watch(assetStackStateProvider(stackId)) : []; bool isStackPrimaryAsset = asset.stackPrimaryAssetId == null; final navStack = AutoRouter.of(context).stackData; @@ -63,10 +66,10 @@ class BottomGalleryBar extends ConsumerWidget { final isInAlbum = ref.watch(currentAlbumProvider)?.isRemote ?? false; void removeAssetFromStack() { - if (stackIndex > 0 && showStack) { + if (stackIndex.value > 0 && showStack && stackId != null) { ref - .read(assetStackStateProvider(asset).notifier) - .removeChild(stackIndex - 1); + .read(assetStackStateProvider(stackId).notifier) + .removeChild(stackIndex.value - 1); } } @@ -134,7 +137,7 @@ class BottomGalleryBar extends ConsumerWidget { await ref .read(stackServiceProvider) - .deleteStack(asset.stackId!, [asset, ...stackItems]); + .deleteStack(asset.stackId!, stackItems); } void showStackActionItems() { @@ -187,7 +190,7 @@ class BottomGalleryBar extends ConsumerWidget { void handleEdit() async { final image = Image(image: ImmichImage.imageProvider(asset: asset)); - Navigator.of(context).push( + context.navigator.push( MaterialPageRoute( builder: (context) => EditImagePage( asset: asset, @@ -323,43 +326,55 @@ class BottomGalleryBar extends ConsumerWidget { }, ]; return IgnorePointer( - ignoring: !ref.watch(showControlsProvider), + ignoring: !showControls, child: AnimatedOpacity( duration: const Duration(milliseconds: 100), - opacity: ref.watch(showControlsProvider) ? 1.0 : 0.0, - child: Column( - children: [ - Visibility( - visible: showVideoPlayerControls, - child: const VideoControls(), + opacity: showControls ? 1.0 : 0.0, + child: DecoratedBox( + decoration: const BoxDecoration( + gradient: LinearGradient( + begin: Alignment.bottomCenter, + end: Alignment.topCenter, + colors: [Colors.black, Colors.transparent], ), - BottomNavigationBar( - backgroundColor: Colors.black.withOpacity(0.4), - unselectedIconTheme: const IconThemeData(color: Colors.white), - selectedIconTheme: const IconThemeData(color: Colors.white), - unselectedLabelStyle: const TextStyle( - color: Colors.white, - fontWeight: FontWeight.w500, - height: 2.3, - ), - selectedLabelStyle: const TextStyle( - color: Colors.white, - fontWeight: FontWeight.w500, - height: 2.3, - ), - unselectedFontSize: 14, - selectedFontSize: 14, - selectedItemColor: Colors.white, - unselectedItemColor: Colors.white, - showSelectedLabels: true, - showUnselectedLabels: true, - items: - albumActions.map((e) => e.keys.first).toList(growable: false), - onTap: (index) { - albumActions[index].values.first.call(index); - }, + ), + position: DecorationPosition.background, + child: Padding( + padding: const EdgeInsets.only(top: 40.0), + child: Column( + children: [ + if (asset.isVideo) const VideoControls(), + BottomNavigationBar( + elevation: 0.0, + backgroundColor: Colors.transparent, + unselectedIconTheme: const IconThemeData(color: Colors.white), + selectedIconTheme: const IconThemeData(color: Colors.white), + unselectedLabelStyle: const TextStyle( + color: Colors.white, + fontWeight: FontWeight.w500, + height: 2.3, + ), + selectedLabelStyle: const TextStyle( + color: Colors.white, + fontWeight: FontWeight.w500, + height: 2.3, + ), + unselectedFontSize: 14, + selectedFontSize: 14, + selectedItemColor: Colors.white, + unselectedItemColor: Colors.white, + showSelectedLabels: true, + showUnselectedLabels: true, + items: albumActions + .map((e) => e.keys.first) + .toList(growable: false), + onTap: (index) { + albumActions[index].values.first.call(index); + }, + ), + ], ), - ], + ), ), ), ); diff --git a/mobile/lib/widgets/asset_viewer/custom_video_player_controls.dart b/mobile/lib/widgets/asset_viewer/custom_video_player_controls.dart index a34fcb9baf5e0..d759b0d80b3e6 100644 --- a/mobile/lib/widgets/asset_viewer/custom_video_player_controls.dart +++ b/mobile/lib/widgets/asset_viewer/custom_video_player_controls.dart @@ -1,38 +1,48 @@ import 'package:flutter/material.dart'; -import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:immich_mobile/providers/asset_viewer/current_asset.provider.dart'; import 'package:immich_mobile/providers/asset_viewer/show_controls.provider.dart'; import 'package:immich_mobile/providers/asset_viewer/video_player_controls_provider.dart'; import 'package:immich_mobile/providers/asset_viewer/video_player_value_provider.dart'; +import 'package:immich_mobile/utils/hooks/timer_hook.dart'; import 'package:immich_mobile/widgets/asset_viewer/center_play_button.dart'; import 'package:immich_mobile/widgets/common/delayed_loading_indicator.dart'; -import 'package:immich_mobile/utils/hooks/timer_hook.dart'; class CustomVideoPlayerControls extends HookConsumerWidget { final Duration hideTimerDuration; const CustomVideoPlayerControls({ super.key, - this.hideTimerDuration = const Duration(seconds: 3), + this.hideTimerDuration = const Duration(seconds: 5), }); @override Widget build(BuildContext context, WidgetRef ref) { + final assetIsVideo = ref.watch( + currentAssetProvider.select((asset) => asset != null && asset.isVideo), + ); + final showControls = ref.watch(showControlsProvider); + final VideoPlaybackState state = + ref.watch(videoPlaybackValueProvider.select((value) => value.state)); + // A timer to hide the controls final hideTimer = useTimer( hideTimerDuration, () { + if (!context.mounted) { + return; + } final state = ref.read(videoPlaybackValueProvider).state; + // Do not hide on paused - if (state != VideoPlaybackState.paused) { + if (state != VideoPlaybackState.paused && + state != VideoPlaybackState.completed && + assetIsVideo) { ref.read(showControlsProvider.notifier).show = false; } }, ); - - final showBuffering = useState(false); - final VideoPlaybackState state = - ref.watch(videoPlaybackValueProvider).state; + final showBuffering = state == VideoPlaybackState.buffering; /// Shows the controls and starts the timer to hide them void showControlsAndStartHideTimer() { @@ -40,28 +50,15 @@ class CustomVideoPlayerControls extends HookConsumerWidget { ref.read(showControlsProvider.notifier).show = true; } - // When we mute, show the controls - ref.listen(videoPlayerControlsProvider.select((v) => v.mute), - (previous, next) { - showControlsAndStartHideTimer(); - }); - // When we change position, show or hide timer ref.listen(videoPlayerControlsProvider.select((v) => v.position), (previous, next) { showControlsAndStartHideTimer(); }); - ref.listen(videoPlaybackValueProvider.select((value) => value.state), - (_, state) { - // Show buffering - showBuffering.value = state == VideoPlaybackState.buffering; - }); - /// Toggles between playing and pausing depending on the state of the video void togglePlay() { showControlsAndStartHideTimer(); - final state = ref.read(videoPlaybackValueProvider).state; if (state == VideoPlaybackState.playing) { ref.read(videoPlayerControlsProvider.notifier).pause(); } else if (state == VideoPlaybackState.completed) { @@ -75,10 +72,10 @@ class CustomVideoPlayerControls extends HookConsumerWidget { behavior: HitTestBehavior.opaque, onTap: showControlsAndStartHideTimer, child: AbsorbPointer( - absorbing: !ref.watch(showControlsProvider), + absorbing: !showControls, child: Stack( children: [ - if (showBuffering.value) + if (showBuffering) const Center( child: DelayedLoadingIndicator( fadeInDuration: Duration(milliseconds: 400), @@ -86,18 +83,14 @@ class CustomVideoPlayerControls extends HookConsumerWidget { ) else GestureDetector( - onTap: () { - if (state != VideoPlaybackState.playing) { - togglePlay(); - } - ref.read(showControlsProvider.notifier).show = false; - }, + onTap: () => + ref.read(showControlsProvider.notifier).show = false, child: CenterPlayButton( backgroundColor: Colors.black54, iconColor: Colors.white, isFinished: state == VideoPlaybackState.completed, isPlaying: state == VideoPlaybackState.playing, - show: ref.watch(showControlsProvider), + show: assetIsVideo && showControls, onPressed: togglePlay, ), ), diff --git a/mobile/lib/widgets/asset_viewer/detail_panel/file_info.dart b/mobile/lib/widgets/asset_viewer/detail_panel/file_info.dart index 3c650bdc6a2e3..0dd3305302c41 100644 --- a/mobile/lib/widgets/asset_viewer/detail_panel/file_info.dart +++ b/mobile/lib/widgets/asset_viewer/detail_panel/file_info.dart @@ -15,9 +15,10 @@ class FileInfo extends StatelessWidget { Widget build(BuildContext context) { final textColor = context.isDarkTheme ? Colors.white : Colors.black; - String resolution = asset.width != null && asset.height != null - ? "${asset.height} x ${asset.width} " - : ""; + final height = asset.orientatedHeight ?? asset.height; + final width = asset.orientatedWidth ?? asset.width; + String resolution = + height != null && width != null ? "$height x $width " : ""; String fileSize = asset.exifInfo?.fileSize != null ? formatBytes(asset.exifInfo!.fileSize!) : ""; diff --git a/mobile/lib/widgets/asset_viewer/formatted_duration.dart b/mobile/lib/widgets/asset_viewer/formatted_duration.dart new file mode 100644 index 0000000000000..a34aab7d125d2 --- /dev/null +++ b/mobile/lib/widgets/asset_viewer/formatted_duration.dart @@ -0,0 +1,33 @@ +import 'package:flutter/material.dart'; + +@pragma('vm:prefer-inline') +String _formatDuration(Duration position) { + final seconds = position.inSeconds.remainder(60).toString().padLeft(2, "0"); + final minutes = position.inMinutes.remainder(60).toString().padLeft(2, "0"); + if (position.inHours == 0) { + return "$minutes:$seconds"; + } + final hours = position.inHours.toString().padLeft(2, '0'); + return "$hours:$minutes:$seconds"; +} + +class FormattedDuration extends StatelessWidget { + final Duration data; + const FormattedDuration(this.data, {super.key}); + + @override + Widget build(BuildContext context) { + return SizedBox( + width: data.inHours > 0 ? 70 : 60, // use a fixed width to prevent jitter + child: Text( + _formatDuration(data), + style: const TextStyle( + fontSize: 14.0, + color: Colors.white, + fontWeight: FontWeight.w500, + ), + textAlign: TextAlign.center, + ), + ); + } +} diff --git a/mobile/lib/widgets/asset_viewer/gallery_app_bar.dart b/mobile/lib/widgets/asset_viewer/gallery_app_bar.dart index f400224e0a0be..f7e2158ea981d 100644 --- a/mobile/lib/widgets/asset_viewer/gallery_app_bar.dart +++ b/mobile/lib/widgets/asset_viewer/gallery_app_bar.dart @@ -4,6 +4,7 @@ import 'package:flutter/material.dart'; import 'package:fluttertoast/fluttertoast.dart'; import 'package:hooks_riverpod/hooks_riverpod.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/widgets/album/add_to_album_bottom_sheet.dart'; import 'package:immich_mobile/providers/asset_viewer/download.provider.dart'; import 'package:immich_mobile/providers/asset_viewer/show_controls.provider.dart'; @@ -19,23 +20,19 @@ import 'package:immich_mobile/providers/user.provider.dart'; import 'package:immich_mobile/widgets/common/immich_toast.dart'; class GalleryAppBar extends ConsumerWidget { - final Asset asset; final void Function() showInfo; - final void Function() onToggleMotionVideo; - final bool isPlayingVideo; - const GalleryAppBar({ - super.key, - required this.asset, - required this.showInfo, - required this.onToggleMotionVideo, - required this.isPlayingVideo, - }); + const GalleryAppBar({super.key, required this.showInfo}); @override Widget build(BuildContext context, WidgetRef ref) { + final asset = ref.watch(currentAssetProvider); + if (asset == null) { + return const SizedBox(); + } final album = ref.watch(currentAlbumProvider); final isOwner = asset.ownerId == ref.watch(currentUserProvider)?.isarId; + final showControls = ref.watch(showControlsProvider); final isPartner = ref .watch(partnerSharedWithProvider) @@ -98,23 +95,21 @@ class GalleryAppBar extends ConsumerWidget { } return IgnorePointer( - ignoring: !ref.watch(showControlsProvider), + ignoring: !showControls, child: AnimatedOpacity( duration: const Duration(milliseconds: 100), - opacity: ref.watch(showControlsProvider) ? 1.0 : 0.0, + opacity: showControls ? 1.0 : 0.0, child: Container( color: Colors.black.withOpacity(0.4), child: TopControlAppBar( isOwner: isOwner, isPartner: isPartner, - isPlayingMotionVideo: isPlayingVideo, asset: asset, onMoreInfoPressed: showInfo, onFavorite: toggleFavorite, onRestorePressed: () => handleRestore(asset), onUploadPressed: asset.isLocal ? () => handleUpload(asset) : null, onDownloadPressed: asset.isLocal ? null : handleDownloadAsset, - onToggleMotionVideo: onToggleMotionVideo, onAddToAlbumPressed: () => addToAlbum(asset), onActivitiesPressed: handleActivities, ), diff --git a/mobile/lib/widgets/asset_viewer/motion_photo_button.dart b/mobile/lib/widgets/asset_viewer/motion_photo_button.dart new file mode 100644 index 0000000000000..f5479ab86e90d --- /dev/null +++ b/mobile/lib/widgets/asset_viewer/motion_photo_button.dart @@ -0,0 +1,22 @@ +import 'package:flutter/material.dart'; +import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:immich_mobile/constants/colors.dart'; +import 'package:immich_mobile/providers/asset_viewer/is_motion_video_playing.provider.dart'; + +class MotionPhotoButton extends ConsumerWidget { + const MotionPhotoButton({super.key}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final isPlaying = ref.watch(isPlayingMotionVideoProvider); + + return IconButton( + onPressed: () { + ref.read(isPlayingMotionVideoProvider.notifier).toggle(); + }, + icon: isPlaying + ? const Icon(Icons.motion_photos_pause_outlined, color: grey200) + : const Icon(Icons.play_circle_outline_rounded, color: grey200), + ); + } +} diff --git a/mobile/lib/widgets/asset_viewer/top_control_app_bar.dart b/mobile/lib/widgets/asset_viewer/top_control_app_bar.dart index 984b61f50cc05..2bdbb72ec03ac 100644 --- a/mobile/lib/widgets/asset_viewer/top_control_app_bar.dart +++ b/mobile/lib/widgets/asset_viewer/top_control_app_bar.dart @@ -5,6 +5,7 @@ import 'package:immich_mobile/providers/activity_statistics.provider.dart'; import 'package:immich_mobile/providers/album/current_album.provider.dart'; import 'package:immich_mobile/entities/asset.entity.dart'; import 'package:immich_mobile/providers/asset.provider.dart'; +import 'package:immich_mobile/widgets/asset_viewer/motion_photo_button.dart'; class TopControlAppBar extends HookConsumerWidget { const TopControlAppBar({ @@ -14,8 +15,6 @@ class TopControlAppBar extends HookConsumerWidget { required this.onDownloadPressed, required this.onAddToAlbumPressed, required this.onRestorePressed, - required this.onToggleMotionVideo, - required this.isPlayingMotionVideo, required this.onFavorite, required this.onUploadPressed, required this.isOwner, @@ -27,12 +26,10 @@ class TopControlAppBar extends HookConsumerWidget { final Function onMoreInfoPressed; final VoidCallback? onUploadPressed; final VoidCallback? onDownloadPressed; - final VoidCallback onToggleMotionVideo; final VoidCallback onAddToAlbumPressed; final VoidCallback onRestorePressed; final VoidCallback onActivitiesPressed; final Function(Asset) onFavorite; - final bool isPlayingMotionVideo; final bool isOwner; final bool isPartner; @@ -57,23 +54,6 @@ class TopControlAppBar extends HookConsumerWidget { ); } - Widget buildLivePhotoButton() { - return IconButton( - onPressed: () { - onToggleMotionVideo(); - }, - icon: isPlayingMotionVideo - ? Icon( - Icons.motion_photos_pause_outlined, - color: Colors.grey[200], - ) - : Icon( - Icons.play_circle_outline_rounded, - color: Colors.grey[200], - ), - ); - } - Widget buildMoreInfoButton() { return IconButton( onPressed: () { @@ -175,13 +155,11 @@ class TopControlAppBar extends HookConsumerWidget { foregroundColor: Colors.grey[100], backgroundColor: Colors.transparent, leading: buildBackButton(), - actionsIconTheme: const IconThemeData( - size: iconSize, - ), + actionsIconTheme: const IconThemeData(size: iconSize), shape: const Border(), actions: [ if (asset.isRemote && isOwner) buildFavoriteButton(a), - if (asset.livePhotoVideoId != null) buildLivePhotoButton(), + if (asset.livePhotoVideoId != null) const MotionPhotoButton(), if (asset.isLocal && !asset.isRemote) buildUploadButton(), if (asset.isRemote && !asset.isLocal && isOwner) buildDownloadButton(), if (asset.isRemote && (isOwner || isPartner) && !asset.isTrashed) diff --git a/mobile/lib/widgets/asset_viewer/video_controls.dart b/mobile/lib/widgets/asset_viewer/video_controls.dart index a5f5f18ce87c1..22aa2b17d12b8 100644 --- a/mobile/lib/widgets/asset_viewer/video_controls.dart +++ b/mobile/lib/widgets/asset_viewer/video_controls.dart @@ -1,125 +1,20 @@ -import 'dart:math'; - import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; -import 'package:immich_mobile/providers/asset_viewer/show_controls.provider.dart'; -import 'package:immich_mobile/providers/asset_viewer/video_player_controls_provider.dart'; -import 'package:immich_mobile/providers/asset_viewer/video_player_value_provider.dart'; +import 'package:immich_mobile/extensions/build_context_extensions.dart'; +import 'package:immich_mobile/widgets/asset_viewer/video_position.dart'; -/// The video controls for the [videPlayerControlsProvider] +/// The video controls for the [videoPlayerControlsProvider] class VideoControls extends ConsumerWidget { const VideoControls({super.key}); @override Widget build(BuildContext context, WidgetRef ref) { - final duration = - ref.watch(videoPlaybackValueProvider.select((v) => v.duration)); - final position = - ref.watch(videoPlaybackValueProvider.select((v) => v.position)); - - return AnimatedOpacity( - opacity: ref.watch(showControlsProvider) ? 1.0 : 0.0, - duration: const Duration(milliseconds: 100), - child: OrientationBuilder( - builder: (context, orientation) => Container( - padding: EdgeInsets.symmetric( - horizontal: orientation == Orientation.portrait ? 12.0 : 64.0, - ), - color: Colors.black.withOpacity(0.4), - child: Padding( - padding: MediaQuery.of(context).orientation == Orientation.portrait - ? const EdgeInsets.symmetric(horizontal: 12.0) - : const EdgeInsets.symmetric(horizontal: 64.0), - child: Row( - children: [ - Text( - _formatDuration(position), - style: TextStyle( - fontSize: 14.0, - color: Colors.white.withOpacity(.75), - fontWeight: FontWeight.normal, - ), - ), - Expanded( - child: Slider( - value: duration == Duration.zero - ? 0.0 - : min( - position.inMicroseconds / - duration.inMicroseconds * - 100, - 100, - ), - min: 0, - max: 100, - thumbColor: Colors.white, - activeColor: Colors.white, - inactiveColor: Colors.white.withOpacity(0.75), - onChanged: (position) { - ref.read(videoPlayerControlsProvider.notifier).position = - position; - }, - ), - ), - Text( - _formatDuration(duration), - style: TextStyle( - fontSize: 14.0, - color: Colors.white.withOpacity(.75), - fontWeight: FontWeight.normal, - ), - ), - IconButton( - icon: Icon( - ref.watch( - videoPlayerControlsProvider.select((value) => value.mute), - ) - ? Icons.volume_off - : Icons.volume_up, - ), - onPressed: () => ref - .read(videoPlayerControlsProvider.notifier) - .toggleMute(), - color: Colors.white, - ), - ], - ), - ), - ), - ), - ); - } - - String _formatDuration(Duration position) { - final ms = position.inMilliseconds; - - int seconds = ms ~/ 1000; - final int hours = seconds ~/ 3600; - seconds = seconds % 3600; - final minutes = seconds ~/ 60; - seconds = seconds % 60; - - final hoursString = hours >= 10 - ? '$hours' - : hours == 0 - ? '00' - : '0$hours'; - - final minutesString = minutes >= 10 - ? '$minutes' - : minutes == 0 - ? '00' - : '0$minutes'; - - final secondsString = seconds >= 10 - ? '$seconds' - : seconds == 0 - ? '00' - : '0$seconds'; - - final formattedTime = - '${hoursString == '00' ? '' : '$hoursString:'}$minutesString:$secondsString'; - - return formattedTime; + final isPortrait = context.orientation == Orientation.portrait; + return isPortrait + ? const VideoPosition() + : const Padding( + padding: EdgeInsets.symmetric(horizontal: 60.0), + child: VideoPosition(), + ); } } diff --git a/mobile/lib/widgets/asset_viewer/video_player.dart b/mobile/lib/widgets/asset_viewer/video_player.dart deleted file mode 100644 index ebf158b59a5fb..0000000000000 --- a/mobile/lib/widgets/asset_viewer/video_player.dart +++ /dev/null @@ -1,48 +0,0 @@ -import 'package:chewie/chewie.dart'; -import 'package:flutter/material.dart'; -import 'package:hooks_riverpod/hooks_riverpod.dart'; -import 'package:immich_mobile/utils/hooks/chewiew_controller_hook.dart'; -import 'package:immich_mobile/widgets/asset_viewer/custom_video_player_controls.dart'; -import 'package:video_player/video_player.dart'; - -class VideoPlayerViewer extends HookConsumerWidget { - final VideoPlayerController controller; - final bool isMotionVideo; - final Widget? placeholder; - final Duration hideControlsTimer; - final bool showControls; - final bool showDownloadingIndicator; - final bool loopVideo; - - const VideoPlayerViewer({ - super.key, - required this.controller, - required this.isMotionVideo, - this.placeholder, - required this.hideControlsTimer, - required this.showControls, - required this.showDownloadingIndicator, - required this.loopVideo, - }); - - @override - Widget build(BuildContext context, WidgetRef ref) { - final chewie = useChewieController( - controller: controller, - controlsSafeAreaMinimum: const EdgeInsets.only( - bottom: 100, - ), - placeholder: SizedBox.expand(child: placeholder), - customControls: CustomVideoPlayerControls( - hideTimerDuration: hideControlsTimer, - ), - showControls: showControls && !isMotionVideo, - hideControlsTimer: hideControlsTimer, - loopVideo: loopVideo, - ); - - return Chewie( - controller: chewie, - ); - } -} diff --git a/mobile/lib/widgets/asset_viewer/video_position.dart b/mobile/lib/widgets/asset_viewer/video_position.dart new file mode 100644 index 0000000000000..4d0e7aa17f755 --- /dev/null +++ b/mobile/lib/widgets/asset_viewer/video_position.dart @@ -0,0 +1,116 @@ +import 'dart:math'; + +import 'package:flutter/material.dart'; +import 'package:flutter_hooks/flutter_hooks.dart'; +import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:immich_mobile/constants/colors.dart'; +import 'package:immich_mobile/providers/asset_viewer/video_player_controls_provider.dart'; +import 'package:immich_mobile/providers/asset_viewer/video_player_value_provider.dart'; +import 'package:immich_mobile/widgets/asset_viewer/formatted_duration.dart'; + +class VideoPosition extends HookConsumerWidget { + const VideoPosition({super.key}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final (position, duration) = ref.watch( + videoPlaybackValueProvider.select((v) => (v.position, v.duration)), + ); + final wasPlaying = useRef(true); + return duration == Duration.zero + ? const _VideoPositionPlaceholder() + : Column( + children: [ + Padding( + // align with slider's inherent padding + padding: const EdgeInsets.symmetric(horizontal: 12.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + FormattedDuration(position), + FormattedDuration(duration), + ], + ), + ), + Row( + children: [ + Expanded( + child: Slider( + value: min( + position.inMicroseconds / duration.inMicroseconds * 100, + 100, + ), + min: 0, + max: 100, + thumbColor: Colors.white, + activeColor: Colors.white, + inactiveColor: whiteOpacity75, + onChangeStart: (value) { + final state = + ref.read(videoPlaybackValueProvider).state; + wasPlaying.value = state != VideoPlaybackState.paused; + ref.read(videoPlayerControlsProvider.notifier).pause(); + }, + onChangeEnd: (value) { + if (wasPlaying.value) { + ref.read(videoPlayerControlsProvider.notifier).play(); + } + }, + onChanged: (value) { + final inSeconds = + (duration * (value / 100.0)).inSeconds; + final position = inSeconds.toDouble(); + ref + .read(videoPlayerControlsProvider.notifier) + .position = position; + // This immediately updates the slider position without waiting for the video to update + ref.read(videoPlaybackValueProvider.notifier).position = + Duration(seconds: inSeconds); + }, + ), + ), + ], + ), + ], + ); + } +} + +class _VideoPositionPlaceholder extends StatelessWidget { + const _VideoPositionPlaceholder(); + + static void _onChangedDummy(_) {} + + @override + Widget build(BuildContext context) { + return const Column( + children: [ + Padding( + padding: EdgeInsets.symmetric(horizontal: 12.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + FormattedDuration(Duration.zero), + FormattedDuration(Duration.zero), + ], + ), + ), + Row( + children: [ + Expanded( + child: Slider( + value: 0.0, + min: 0, + max: 100, + thumbColor: Colors.white, + activeColor: Colors.white, + inactiveColor: whiteOpacity75, + onChanged: _onChangedDummy, + ), + ), + ], + ), + ], + ); + } +} diff --git a/mobile/lib/widgets/backup/asset_info_table.dart b/mobile/lib/widgets/backup/asset_info_table.dart new file mode 100644 index 0000000000000..bbcbbe375f0ff --- /dev/null +++ b/mobile/lib/widgets/backup/asset_info_table.dart @@ -0,0 +1,102 @@ +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'; +import 'package:immich_mobile/extensions/theme_extensions.dart'; +import 'package:immich_mobile/models/backup/backup_state.model.dart'; +import 'package:immich_mobile/models/backup/current_upload_asset.model.dart'; +import 'package:immich_mobile/providers/backup/backup.provider.dart'; +import 'package:immich_mobile/providers/backup/manual_upload.provider.dart'; + +class BackupAssetInfoTable extends ConsumerWidget { + const BackupAssetInfoTable({super.key}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final isManualUpload = ref.watch( + backupProvider.select( + (value) => value.backupProgress == BackUpProgressEnum.manualInProgress, + ), + ); + + final asset = isManualUpload + ? ref.watch( + manualUploadProvider.select((value) => value.currentUploadAsset), + ) + : ref.watch(backupProvider.select((value) => value.currentUploadAsset)); + + return Padding( + padding: const EdgeInsets.only(top: 8.0), + child: Table( + border: TableBorder.all( + color: context.colorScheme.outlineVariant, + width: 1, + ), + children: [ + TableRow( + children: [ + TableCell( + verticalAlignment: TableCellVerticalAlignment.middle, + child: Padding( + padding: const EdgeInsets.all(6.0), + child: Text( + 'backup_controller_page_filename', + style: TextStyle( + color: context.colorScheme.onSurfaceSecondary, + fontWeight: FontWeight.bold, + fontSize: 10.0, + ), + ).tr( + args: [asset.fileName, asset.fileType.toLowerCase()], + ), + ), + ), + ], + ), + TableRow( + children: [ + TableCell( + verticalAlignment: TableCellVerticalAlignment.middle, + child: Padding( + padding: const EdgeInsets.all(6.0), + child: Text( + "backup_controller_page_created", + style: TextStyle( + color: context.colorScheme.onSurfaceSecondary, + fontWeight: FontWeight.bold, + fontSize: 10.0, + ), + ).tr( + args: [_getAssetCreationDate(asset)], + ), + ), + ), + ], + ), + TableRow( + children: [ + TableCell( + child: Padding( + padding: const EdgeInsets.all(6.0), + child: Text( + "backup_controller_page_id", + style: TextStyle( + color: context.colorScheme.onSurfaceSecondary, + fontWeight: FontWeight.bold, + fontSize: 10.0, + ), + ).tr(args: [asset.id]), + ), + ), + ], + ), + ], + ), + ); + } + + @pragma('vm:prefer-inline') + String _getAssetCreationDate(CurrentUploadAsset asset) { + return DateFormat.yMMMMd().format(asset.fileCreatedAt.toLocal()); + } +} diff --git a/mobile/lib/widgets/backup/current_backup_asset_info_box.dart b/mobile/lib/widgets/backup/current_backup_asset_info_box.dart index f2f84e271f155..b6d0edb2004ff 100644 --- a/mobile/lib/widgets/backup/current_backup_asset_info_box.dart +++ b/mobile/lib/widgets/backup/current_backup_asset_info_box.dart @@ -1,296 +1,43 @@ import 'dart:io'; -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'; -import 'package:immich_mobile/entities/asset.entity.dart'; import 'package:immich_mobile/extensions/build_context_extensions.dart'; -import 'package:immich_mobile/extensions/theme_extensions.dart'; -import 'package:immich_mobile/models/backup/backup_state.model.dart'; -import 'package:immich_mobile/providers/backup/backup.provider.dart'; -import 'package:immich_mobile/providers/backup/error_backup_list.provider.dart'; -import 'package:immich_mobile/providers/backup/manual_upload.provider.dart'; -import 'package:immich_mobile/repositories/asset_media.repository.dart'; -import 'package:immich_mobile/routing/router.dart'; -import 'package:immich_mobile/widgets/common/immich_thumbnail.dart'; +import 'package:immich_mobile/widgets/backup/asset_info_table.dart'; +import 'package:immich_mobile/widgets/backup/error_chip.dart'; +import 'package:immich_mobile/widgets/backup/icloud_download_progress_bar.dart'; +import 'package:immich_mobile/widgets/backup/upload_progress_bar.dart'; +import 'package:immich_mobile/widgets/backup/upload_stats.dart'; -class CurrentUploadingAssetInfoBox extends HookConsumerWidget { +class CurrentUploadingAssetInfoBox extends StatelessWidget { const CurrentUploadingAssetInfoBox({super.key}); - @override - Widget build(BuildContext context, WidgetRef ref) { - var isManualUpload = ref.watch(backupProvider).backupProgress == - BackUpProgressEnum.manualInProgress; - var asset = !isManualUpload - ? ref.watch(backupProvider).currentUploadAsset - : ref.watch(manualUploadProvider).currentUploadAsset; - var uploadProgress = !isManualUpload - ? ref.watch(backupProvider).progressInPercentage - : ref.watch(manualUploadProvider).progressInPercentage; - var uploadFileProgress = !isManualUpload - ? ref.watch(backupProvider).progressInFileSize - : ref.watch(manualUploadProvider).progressInFileSize; - var uploadFileSpeed = !isManualUpload - ? ref.watch(backupProvider).progressInFileSpeed - : ref.watch(manualUploadProvider).progressInFileSpeed; - var iCloudDownloadProgress = - ref.watch(backupProvider).iCloudDownloadProgress; - final isShowThumbnail = useState(false); - - String formatUploadFileSpeed(double uploadFileSpeed) { - if (uploadFileSpeed < 1024) { - return '${uploadFileSpeed.toStringAsFixed(2)} B/s'; - } else if (uploadFileSpeed < 1024 * 1024) { - return '${(uploadFileSpeed / 1024).toStringAsFixed(2)} KB/s'; - } else if (uploadFileSpeed < 1024 * 1024 * 1024) { - return '${(uploadFileSpeed / (1024 * 1024)).toStringAsFixed(2)} MB/s'; - } else { - return '${(uploadFileSpeed / (1024 * 1024 * 1024)).toStringAsFixed(2)} GB/s'; - } - } - - String getAssetCreationDate() { - return DateFormat.yMMMMd().format( - DateTime.parse( - asset.fileCreatedAt.toString(), - ).toLocal(), - ); - } - - Widget buildErrorChip() { - return ActionChip( - avatar: Icon( - Icons.info, - color: Colors.red[400], - ), - elevation: 1, - visualDensity: VisualDensity.compact, - label: Text( - "backup_controller_page_failed", - style: TextStyle( - color: Colors.red[400], - fontWeight: FontWeight.bold, - fontSize: 11, - ), - ).tr( - args: [ref.watch(errorBackupListProvider).length.toString()], - ), - backgroundColor: Colors.white, - onPressed: () => context.pushRoute(const FailedBackupStatusRoute()), - ); - } - Widget buildAssetInfoTable() { - return Table( - border: TableBorder.all( - color: context.colorScheme.outlineVariant, - width: 1, - ), + @override + Widget build(BuildContext context) { + return ListTile( + isThreeLine: true, + leading: Icon( + Icons.image_outlined, + color: context.primaryColor, + size: 30, + ), + title: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - TableRow( - children: [ - TableCell( - verticalAlignment: TableCellVerticalAlignment.middle, - child: Padding( - padding: const EdgeInsets.all(6.0), - child: Text( - 'backup_controller_page_filename', - style: TextStyle( - color: context.colorScheme.onSurfaceSecondary, - fontWeight: FontWeight.bold, - fontSize: 10.0, - ), - ).tr( - args: [asset.fileName, asset.fileType.toLowerCase()], - ), - ), - ), - ], - ), - TableRow( - children: [ - TableCell( - verticalAlignment: TableCellVerticalAlignment.middle, - child: Padding( - padding: const EdgeInsets.all(6.0), - child: Text( - "backup_controller_page_created", - style: TextStyle( - color: context.colorScheme.onSurfaceSecondary, - fontWeight: FontWeight.bold, - fontSize: 10.0, - ), - ).tr( - args: [getAssetCreationDate()], - ), - ), - ), - ], - ), - TableRow( - children: [ - TableCell( - child: Padding( - padding: const EdgeInsets.all(6.0), - child: Text( - "backup_controller_page_id", - style: TextStyle( - color: context.colorScheme.onSurfaceSecondary, - fontWeight: FontWeight.bold, - fontSize: 10.0, - ), - ).tr(args: [asset.id]), - ), - ), - ], - ), + Text( + "backup_controller_page_uploading_file_info", + style: context.textTheme.titleSmall, + ).tr(), + const BackupErrorChip(), + ], + ), + subtitle: Column( + children: [ + if (Platform.isIOS) const IcloudDownloadProgressBar(), + const BackupUploadProgressBar(), + const BackupUploadStats(), + const BackupAssetInfoTable(), ], - ); - } - - buildiCloudDownloadProgerssBar() { - if (asset.iCloudAsset != null && asset.iCloudAsset!) { - return Padding( - padding: const EdgeInsets.only(top: 8.0), - child: Row( - children: [ - SizedBox( - width: 110, - child: Text( - "iCloud Download", - style: context.textTheme.labelSmall, - ), - ), - Expanded( - child: LinearProgressIndicator( - minHeight: 10.0, - value: uploadProgress / 100.0, - borderRadius: const BorderRadius.all(Radius.circular(10.0)), - ), - ), - Text( - " ${iCloudDownloadProgress.toStringAsFixed(0)}%", - style: const TextStyle(fontSize: 12), - ), - ], - ), - ); - } - - return const SizedBox(); - } - - buildUploadProgressBar() { - return Padding( - padding: const EdgeInsets.only(top: 8.0), - child: Row( - children: [ - if (asset.iCloudAsset != null && asset.iCloudAsset!) - SizedBox( - width: 110, - child: Text( - "Immich Upload", - style: context.textTheme.labelSmall, - ), - ), - Expanded( - child: LinearProgressIndicator( - minHeight: 10.0, - value: uploadProgress / 100.0, - borderRadius: const BorderRadius.all(Radius.circular(10.0)), - ), - ), - Text( - " ${uploadProgress.toStringAsFixed(0)}%", - style: const TextStyle(fontSize: 12, fontFamily: "OverpassMono"), - ), - ], - ), - ); - } - - buildUploadStats() { - return Padding( - padding: const EdgeInsets.only(top: 2.0, bottom: 2.0), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - uploadFileProgress, - style: const TextStyle(fontSize: 10, fontFamily: "OverpassMono"), - ), - Text( - formatUploadFileSpeed(uploadFileSpeed), - style: const TextStyle(fontSize: 10, fontFamily: "OverpassMono"), - ), - ], - ), - ); - } - - return FutureBuilder( - future: ref.read(assetMediaRepositoryProvider).get(asset.id), - builder: (context, thumbnail) => ListTile( - isThreeLine: true, - leading: AnimatedCrossFade( - alignment: Alignment.centerLeft, - firstChild: GestureDetector( - onTap: () => isShowThumbnail.value = false, - child: thumbnail.hasData - ? ClipRRect( - borderRadius: BorderRadius.circular(5), - child: ImmichThumbnail( - asset: thumbnail.data, - width: 50, - height: 50, - ), - ) - : const SizedBox( - width: 50, - height: 50, - child: Padding( - padding: EdgeInsets.all(8.0), - child: CircularProgressIndicator.adaptive( - strokeWidth: 1, - ), - ), - ), - ), - secondChild: GestureDetector( - onTap: () => isShowThumbnail.value = true, - child: Icon( - Icons.image_outlined, - color: context.primaryColor, - size: 30, - ), - ), - crossFadeState: isShowThumbnail.value - ? CrossFadeState.showFirst - : CrossFadeState.showSecond, - duration: const Duration(milliseconds: 200), - ), - title: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - "backup_controller_page_uploading_file_info", - style: context.textTheme.titleSmall, - ).tr(), - if (ref.watch(errorBackupListProvider).isNotEmpty) buildErrorChip(), - ], - ), - subtitle: Column( - children: [ - if (Platform.isIOS) buildiCloudDownloadProgerssBar(), - buildUploadProgressBar(), - buildUploadStats(), - Padding( - padding: const EdgeInsets.only(top: 8.0), - child: buildAssetInfoTable(), - ), - ], - ), ), ); } diff --git a/mobile/lib/widgets/backup/error_chip.dart b/mobile/lib/widgets/backup/error_chip.dart new file mode 100644 index 0000000000000..4df3e50f64df0 --- /dev/null +++ b/mobile/lib/widgets/backup/error_chip.dart @@ -0,0 +1,32 @@ +import 'package:auto_route/auto_route.dart'; +import 'package:flutter/material.dart'; +import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:immich_mobile/constants/colors.dart'; +import 'package:immich_mobile/providers/backup/error_backup_list.provider.dart'; +import 'package:immich_mobile/routing/router.dart'; +import 'package:immich_mobile/widgets/backup/error_chip_text.dart'; + +class BackupErrorChip extends ConsumerWidget { + const BackupErrorChip({super.key}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final hasErrors = + ref.watch(errorBackupListProvider.select((value) => value.isNotEmpty)); + if (!hasErrors) { + return const SizedBox(); + } + + return ActionChip( + avatar: const Icon( + Icons.info, + color: red400, + ), + elevation: 1, + visualDensity: VisualDensity.compact, + label: const BackupErrorChipText(), + backgroundColor: Colors.white, + onPressed: () => context.pushRoute(const FailedBackupStatusRoute()), + ); + } +} diff --git a/mobile/lib/widgets/backup/error_chip_text.dart b/mobile/lib/widgets/backup/error_chip_text.dart new file mode 100644 index 0000000000000..540e136722f78 --- /dev/null +++ b/mobile/lib/widgets/backup/error_chip_text.dart @@ -0,0 +1,28 @@ +import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter/material.dart'; +import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:immich_mobile/constants/colors.dart'; +import 'package:immich_mobile/providers/backup/error_backup_list.provider.dart'; + +class BackupErrorChipText extends ConsumerWidget { + const BackupErrorChipText({super.key}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final count = ref.watch(errorBackupListProvider).length; + if (count == 0) { + return const SizedBox(); + } + + return const Text( + "backup_controller_page_failed", + style: TextStyle( + color: red400, + fontWeight: FontWeight.bold, + fontSize: 11, + ), + ).tr( + args: [count.toString()], + ); + } +} diff --git a/mobile/lib/widgets/backup/icloud_download_progress_bar.dart b/mobile/lib/widgets/backup/icloud_download_progress_bar.dart new file mode 100644 index 0000000000000..c61fb1a0d1280 --- /dev/null +++ b/mobile/lib/widgets/backup/icloud_download_progress_bar.dart @@ -0,0 +1,61 @@ +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/models/backup/backup_state.model.dart'; +import 'package:immich_mobile/providers/backup/backup.provider.dart'; +import 'package:immich_mobile/providers/backup/manual_upload.provider.dart'; + +class IcloudDownloadProgressBar extends ConsumerWidget { + const IcloudDownloadProgressBar({super.key}); + @override + Widget build(BuildContext context, WidgetRef ref) { + final isManualUpload = ref.watch( + backupProvider.select( + (value) => value.backupProgress == BackUpProgressEnum.manualInProgress, + ), + ); + + final isIcloudAsset = isManualUpload + ? ref.watch( + manualUploadProvider + .select((value) => value.currentUploadAsset.isIcloudAsset), + ) + : ref.watch( + backupProvider + .select((value) => value.currentUploadAsset.isIcloudAsset), + ); + + if (!isIcloudAsset) { + return const SizedBox(); + } + + final iCloudDownloadProgress = ref + .watch(backupProvider.select((value) => value.iCloudDownloadProgress)); + + return Padding( + padding: const EdgeInsets.only(top: 8.0), + child: Row( + children: [ + SizedBox( + width: 110, + child: Text( + "iCloud Download", + style: context.textTheme.labelSmall, + ), + ), + Expanded( + child: LinearProgressIndicator( + minHeight: 10.0, + value: iCloudDownloadProgress / 100.0, + borderRadius: const BorderRadius.all(Radius.circular(10.0)), + ), + ), + Text( + " ${iCloudDownloadProgress ~/ 1}%", + style: const TextStyle(fontSize: 12), + ), + ], + ), + ); + } +} diff --git a/mobile/lib/widgets/backup/upload_progress_bar.dart b/mobile/lib/widgets/backup/upload_progress_bar.dart new file mode 100644 index 0000000000000..9281914d9cc50 --- /dev/null +++ b/mobile/lib/widgets/backup/upload_progress_bar.dart @@ -0,0 +1,64 @@ +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/models/backup/backup_state.model.dart'; +import 'package:immich_mobile/providers/backup/backup.provider.dart'; +import 'package:immich_mobile/providers/backup/manual_upload.provider.dart'; + +class BackupUploadProgressBar extends ConsumerWidget { + const BackupUploadProgressBar({super.key}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final isManualUpload = ref.watch( + backupProvider.select( + (value) => value.backupProgress == BackUpProgressEnum.manualInProgress, + ), + ); + + final isIcloudAsset = isManualUpload + ? ref.watch( + manualUploadProvider + .select((value) => value.currentUploadAsset.isIcloudAsset), + ) + : ref.watch( + backupProvider + .select((value) => value.currentUploadAsset.isIcloudAsset), + ); + + final uploadProgress = isManualUpload + ? ref.watch( + manualUploadProvider.select((value) => value.progressInPercentage), + ) + : ref.watch( + backupProvider.select((value) => value.progressInPercentage), + ); + + return Padding( + padding: const EdgeInsets.only(top: 8.0), + child: Row( + children: [ + if (isIcloudAsset) + SizedBox( + width: 110, + child: Text( + "Immich Upload", + style: context.textTheme.labelSmall, + ), + ), + Expanded( + child: LinearProgressIndicator( + minHeight: 10.0, + value: uploadProgress / 100.0, + borderRadius: const BorderRadius.all(Radius.circular(10.0)), + ), + ), + Text( + " ${uploadProgress.toStringAsFixed(0)}%", + style: const TextStyle(fontSize: 12, fontFamily: "OverpassMono"), + ), + ], + ), + ); + } +} diff --git a/mobile/lib/widgets/backup/upload_stats.dart b/mobile/lib/widgets/backup/upload_stats.dart new file mode 100644 index 0000000000000..965202ce33523 --- /dev/null +++ b/mobile/lib/widgets/backup/upload_stats.dart @@ -0,0 +1,62 @@ +import 'package:flutter/material.dart'; +import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:immich_mobile/models/backup/backup_state.model.dart'; +import 'package:immich_mobile/providers/backup/backup.provider.dart'; +import 'package:immich_mobile/providers/backup/manual_upload.provider.dart'; + +class BackupUploadStats extends ConsumerWidget { + const BackupUploadStats({super.key}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final isManualUpload = ref.watch( + backupProvider.select( + (value) => value.backupProgress == BackUpProgressEnum.manualInProgress, + ), + ); + + final uploadFileProgress = isManualUpload + ? ref.watch( + manualUploadProvider.select((value) => value.progressInFileSize), + ) + : ref.watch(backupProvider.select((value) => value.progressInFileSize)); + + final uploadFileSpeed = isManualUpload + ? ref.watch( + manualUploadProvider.select((value) => value.progressInFileSpeed), + ) + : ref.watch( + backupProvider.select((value) => value.progressInFileSpeed), + ); + + return Padding( + padding: const EdgeInsets.only(top: 2.0, bottom: 2.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + uploadFileProgress, + style: const TextStyle(fontSize: 10, fontFamily: "OverpassMono"), + ), + Text( + _formatUploadFileSpeed(uploadFileSpeed), + style: const TextStyle(fontSize: 10, fontFamily: "OverpassMono"), + ), + ], + ), + ); + } + + @pragma('vm:prefer-inline') + String _formatUploadFileSpeed(double uploadFileSpeed) { + if (uploadFileSpeed < 1024) { + return '${uploadFileSpeed.toStringAsFixed(2)} B/s'; + } else if (uploadFileSpeed < 1024 * 1024) { + return '${(uploadFileSpeed / 1024).toStringAsFixed(2)} KB/s'; + } else if (uploadFileSpeed < 1024 * 1024 * 1024) { + return '${(uploadFileSpeed / (1024 * 1024)).toStringAsFixed(2)} MB/s'; + } else { + return '${(uploadFileSpeed / (1024 * 1024 * 1024)).toStringAsFixed(2)} GB/s'; + } + } +} diff --git a/mobile/lib/widgets/common/app_bar_dialog/app_bar_dialog.dart b/mobile/lib/widgets/common/app_bar_dialog/app_bar_dialog.dart index cd694336bc5af..218e17cbe1046 100644 --- a/mobile/lib/widgets/common/app_bar_dialog/app_bar_dialog.dart +++ b/mobile/lib/widgets/common/app_bar_dialog/app_bar_dialog.dart @@ -7,7 +7,7 @@ import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/models/backup/backup_state.model.dart'; import 'package:immich_mobile/providers/backup/backup.provider.dart'; import 'package:immich_mobile/providers/backup/manual_upload.provider.dart'; -import 'package:immich_mobile/providers/authentication.provider.dart'; +import 'package:immich_mobile/providers/auth.provider.dart'; import 'package:immich_mobile/routing/router.dart'; import 'package:immich_mobile/providers/asset.provider.dart'; import 'package:immich_mobile/providers/user.provider.dart'; @@ -28,6 +28,7 @@ class ImmichAppBarDialog extends HookConsumerWidget { bool isHorizontal = !context.isMobile; final horizontalPadding = isHorizontal ? 100.0 : 20.0; final user = ref.watch(currentUserProvider); + final isLoggingOut = useState(false); useEffect( () { @@ -63,11 +64,16 @@ class ImmichAppBarDialog extends HookConsumerWidget { ); } - buildActionButton(IconData icon, String text, Function() onTap) { + buildActionButton( + IconData icon, + String text, + Function() onTap, { + Widget? trailing, + }) { return ListTile( dense: true, visualDensity: VisualDensity.standard, - contentPadding: const EdgeInsets.only(left: 30), + contentPadding: const EdgeInsets.only(left: 30, right: 30), minLeadingWidth: 40, leading: SizedBox( child: Icon( @@ -83,6 +89,7 @@ class ImmichAppBarDialog extends HookConsumerWidget { ), ).tr(), onTap: onTap, + trailing: trailing, ); } @@ -107,6 +114,10 @@ class ImmichAppBarDialog extends HookConsumerWidget { Icons.logout_rounded, "profile_drawer_sign_out", () async { + if (isLoggingOut.value) { + return; + } + showDialog( context: context, builder: (BuildContext ctx) { @@ -115,7 +126,11 @@ class ImmichAppBarDialog extends HookConsumerWidget { content: "app_bar_signout_dialog_content", ok: "app_bar_signout_dialog_ok", onOk: () async { - await ref.read(authenticationProvider.notifier).logout(); + isLoggingOut.value = true; + await ref + .read(authProvider.notifier) + .logout() + .whenComplete(() => isLoggingOut.value = false); ref.read(manualUploadProvider.notifier).cancelBackup(); ref.read(backupProvider.notifier).cancelBackup(); @@ -127,6 +142,12 @@ class ImmichAppBarDialog extends HookConsumerWidget { }, ); }, + trailing: isLoggingOut.value + ? const SizedBox.square( + dimension: 20, + child: CircularProgressIndicator(strokeWidth: 2), + ) + : null, ); } @@ -238,8 +259,9 @@ class ImmichAppBarDialog extends HookConsumerWidget { } return Dismissible( + behavior: HitTestBehavior.translucent, direction: DismissDirection.down, - onDismissed: (_) => Navigator.of(context).pop(), + onDismissed: (_) => context.pop(), key: const Key('app_bar_dialog'), child: Dialog( clipBehavior: Clip.hardEdge, 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 a40dcf914e2cd..f0006d1ada9b0 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 @@ -7,8 +7,7 @@ import 'package:immich_mobile/providers/upload_profile_image.provider.dart'; import 'package:immich_mobile/entities/store.entity.dart'; import 'package:immich_mobile/providers/user.provider.dart'; import 'package:immich_mobile/widgets/common/user_circle_avatar.dart'; -import 'package:immich_mobile/models/authentication/authentication_state.model.dart'; -import 'package:immich_mobile/providers/authentication.provider.dart'; +import 'package:immich_mobile/providers/auth.provider.dart'; import 'package:immich_mobile/widgets/common/immich_loading_indicator.dart'; class AppBarProfileInfoBox extends HookConsumerWidget { @@ -18,7 +17,7 @@ class AppBarProfileInfoBox extends HookConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { - AuthenticationState authState = ref.watch(authenticationProvider); + final authState = ref.watch(authProvider); final uploadProfileImageStatus = ref.watch(uploadProfileImageProvider).status; final user = Store.tryGet(StoreKey.currentUser); @@ -63,7 +62,7 @@ class AppBarProfileInfoBox extends HookConsumerWidget { if (success) { final profileImagePath = ref.read(uploadProfileImageProvider).profileImagePath; - ref.watch(authenticationProvider.notifier).updateUserProfileImagePath( + ref.watch(authProvider.notifier).updateUserProfileImagePath( profileImagePath, ); if (user != null) { diff --git a/mobile/lib/widgets/common/immich_image.dart b/mobile/lib/widgets/common/immich_image.dart index 5946dee453ad5..ab0f2584b554c 100644 --- a/mobile/lib/widgets/common/immich_image.dart +++ b/mobile/lib/widgets/common/immich_image.dart @@ -28,12 +28,11 @@ class ImmichImage extends StatelessWidget { // either by using the asset ID or the asset itself /// [asset] is the Asset to request, or else use [assetId] to get a remote /// image provider - /// Use [isThumbnail] and [thumbnailSize] if you'd like to request a thumbnail - /// The size of the square thumbnail to request. Ignored if isThumbnail - /// is not true static ImageProvider imageProvider({ Asset? asset, String? assetId, + double width = 1080, + double height = 1920, }) { if (asset == null && assetId == null) { throw Exception('Must supply either asset or assetId'); @@ -48,6 +47,8 @@ class ImmichImage extends StatelessWidget { if (useLocal(asset)) { return ImmichLocalImageProvider( asset: asset, + width: width, + height: height, ); } else { return ImmichRemoteImageProvider( @@ -87,6 +88,8 @@ class ImmichImage extends StatelessWidget { }, image: ImmichImage.imageProvider( asset: asset, + width: context.width, + height: context.height, ), width: width, height: height, diff --git a/mobile/lib/widgets/common/user_circle_avatar.dart b/mobile/lib/widgets/common/user_circle_avatar.dart index bf3bd8a5a8ff5..50da0096764ad 100644 --- a/mobile/lib/widgets/common/user_circle_avatar.dart +++ b/mobile/lib/widgets/common/user_circle_avatar.dart @@ -5,6 +5,7 @@ import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/entities/store.entity.dart'; import 'package:immich_mobile/entities/user.entity.dart'; +import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/services/api.service.dart'; import 'package:immich_mobile/widgets/common/transparent_image.dart'; @@ -23,7 +24,7 @@ class UserCircleAvatar extends ConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { - bool isDarkTheme = Theme.of(context).brightness == Brightness.dark; + bool isDarkTheme = context.themeData.brightness == Brightness.dark; final profileImageUrl = '${Store.get(StoreKey.serverEndpoint)}/users/${user.id}/profile-image?d=${Random().nextInt(1024)}'; diff --git a/mobile/lib/widgets/forms/change_password_form.dart b/mobile/lib/widgets/forms/change_password_form.dart index 98ce66d2d17f5..fbb8fd927bf17 100644 --- a/mobile/lib/widgets/forms/change_password_form.dart +++ b/mobile/lib/widgets/forms/change_password_form.dart @@ -7,7 +7,7 @@ import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/providers/backup/backup.provider.dart'; import 'package:immich_mobile/providers/backup/manual_upload.provider.dart'; -import 'package:immich_mobile/providers/authentication.provider.dart'; +import 'package:immich_mobile/providers/auth.provider.dart'; import 'package:immich_mobile/providers/asset.provider.dart'; import 'package:immich_mobile/providers/websocket.provider.dart'; import 'package:immich_mobile/widgets/common/immich_toast.dart'; @@ -21,7 +21,7 @@ class ChangePasswordForm extends HookConsumerWidget { useTextEditingController.fromValue(TextEditingValue.empty); final confirmPasswordController = useTextEditingController.fromValue(TextEditingValue.empty); - final authState = ref.watch(authenticationProvider); + final authState = ref.watch(authProvider); final formKey = GlobalKey(); return Center( @@ -73,13 +73,11 @@ class ChangePasswordForm extends HookConsumerWidget { onPressed: () async { if (formKey.currentState!.validate()) { var isSuccess = await ref - .read(authenticationProvider.notifier) + .read(authProvider.notifier) .changePassword(passwordController.value.text); if (isSuccess) { - await ref - .read(authenticationProvider.notifier) - .logout(); + await ref.read(authProvider.notifier).logout(); ref .read(manualUploadProvider.notifier) diff --git a/mobile/lib/widgets/forms/login/login_form.dart b/mobile/lib/widgets/forms/login/login_form.dart index 51383fe1950f0..30b6a74bb137d 100644 --- a/mobile/lib/widgets/forms/login/login_form.dart +++ b/mobile/lib/widgets/forms/login/login_form.dart @@ -11,9 +11,7 @@ import 'package:immich_mobile/providers/oauth.provider.dart'; import 'package:immich_mobile/providers/gallery_permission.provider.dart'; import 'package:immich_mobile/routing/router.dart'; import 'package:immich_mobile/entities/store.entity.dart'; -import 'package:immich_mobile/providers/api.provider.dart'; -import 'package:immich_mobile/providers/asset.provider.dart'; -import 'package:immich_mobile/providers/authentication.provider.dart'; +import 'package:immich_mobile/providers/auth.provider.dart'; import 'package:immich_mobile/providers/backup/backup.provider.dart'; import 'package:immich_mobile/providers/server_info.provider.dart'; import 'package:immich_mobile/utils/provider_utils.dart'; @@ -40,13 +38,12 @@ class LoginForm extends HookConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { - final usernameController = + final emailController = useTextEditingController.fromValue(TextEditingValue.empty); final passwordController = useTextEditingController.fromValue(TextEditingValue.empty); final serverEndpointController = useTextEditingController.fromValue(TextEditingValue.empty); - final apiService = ref.watch(apiServiceProvider); final emailFocusNode = useFocusNode(); final passwordFocusNode = useFocusNode(); final serverEndpointFocusNode = useFocusNode(); @@ -85,7 +82,7 @@ class LoginForm extends HookConsumerWidget { /// Fetch the server login credential and enables oAuth login if necessary /// Returns true if successful, false otherwise - Future getServerLoginCredential() async { + Future getServerAuthSettings() async { final serverUrl = sanitizeUrl(serverEndpointController.text); // Guard empty URL @@ -95,13 +92,12 @@ class LoginForm extends HookConsumerWidget { msg: "login_form_server_empty".tr(), toastType: ToastType.error, ); - - return false; } try { isLoadingServer.value = true; - final endpoint = await apiService.resolveAndSetEndpoint(serverUrl); + final endpoint = + await ref.read(authProvider.notifier).validateServerUrl(serverUrl); // Fetch and load server config and features await ref.read(serverInfoProvider.notifier).getServerInfo(); @@ -127,7 +123,6 @@ class LoginForm extends HookConsumerWidget { isOauthEnable.value = false; isPasswordLoginEnable.value = true; isLoadingServer.value = false; - return false; } on HandshakeException { ImmichToast.show( context: context, @@ -138,7 +133,6 @@ class LoginForm extends HookConsumerWidget { isOauthEnable.value = false; isPasswordLoginEnable.value = true; isLoadingServer.value = false; - return false; } catch (e) { ImmichToast.show( context: context, @@ -149,11 +143,9 @@ class LoginForm extends HookConsumerWidget { isOauthEnable.value = false; isPasswordLoginEnable.value = true; isLoadingServer.value = false; - return false; } isLoadingServer.value = false; - return true; } useEffect( @@ -168,67 +160,50 @@ class LoginForm extends HookConsumerWidget { ); populateTestLoginInfo() { - usernameController.text = 'demo@immich.app'; + emailController.text = 'demo@immich.app'; passwordController.text = 'demo'; serverEndpointController.text = 'https://demo.immich.app'; } populateTestLoginInfo1() { - usernameController.text = 'testuser@email.com'; + emailController.text = 'testuser@email.com'; passwordController.text = 'password'; - serverEndpointController.text = 'http://10.1.15.216:2283/api'; + serverEndpointController.text = 'http://10.1.15.216:3000/api'; } login() async { TextInput.finishAutofillContext(); - // Start loading - isLoading.value = true; - // This will remove current cache asset state of previous user login. - ref.read(assetProvider.notifier).clearAllAsset(); + isLoading.value = true; // Invalidate all api repository provider instance to take into account new access token invalidateAllApiRepositoryProviders(ref); try { - final isAuthenticated = - await ref.read(authenticationProvider.notifier).login( - usernameController.text, - passwordController.text, - sanitizeUrl(serverEndpointController.text), - ); - if (isAuthenticated) { - // Resume backup (if enable) then navigate - if (ref.read(authenticationProvider).shouldChangePassword && - !ref.read(authenticationProvider).isAdmin) { - context.pushRoute(const ChangePasswordRoute()); - } else { - final hasPermission = await ref - .read(galleryPermissionNotifier.notifier) - .hasPermission; - if (hasPermission) { - // Don't resume the backup until we have gallery permission - ref.read(backupProvider.notifier).resumeBackup(); - } - context.replaceRoute(const TabControllerRoute()); - } + final result = await ref.read(authProvider.notifier).login( + emailController.text, + passwordController.text, + ); + + if (result.shouldChangePassword && !result.isAdmin) { + context.pushRoute(const ChangePasswordRoute()); } else { - ImmichToast.show( - context: context, - msg: "login_form_failed_login".tr(), - toastType: ToastType.error, - gravity: ToastGravity.TOP, - ); + context.replaceRoute(const TabControllerRoute()); } + } catch (error) { + ImmichToast.show( + context: context, + msg: "login_form_failed_login".tr(), + toastType: ToastType.error, + gravity: ToastGravity.TOP, + ); } finally { - // Make sure we stop loading isLoading.value = false; } } oAuthLogin() async { var oAuthService = ref.watch(oAuthServiceProvider); - ref.watch(assetProvider.notifier).clearAllAsset(); String? oAuthServerUrl; try { @@ -262,11 +237,8 @@ class LoginForm extends HookConsumerWidget { "Finished OAuth login with response: ${loginResponseDto.userEmail}", ); - final isSuccess = await ref - .watch(authenticationProvider.notifier) - .setSuccessLoginInfo( + final isSuccess = await ref.watch(authProvider.notifier).saveAuthInfo( accessToken: loginResponseDto.accessToken, - serverUrl: sanitizeUrl(serverEndpointController.text), ); if (isSuccess) { @@ -309,7 +281,7 @@ class LoginForm extends HookConsumerWidget { ServerEndpointInput( controller: serverEndpointController, focusNode: serverEndpointFocusNode, - onSubmit: getServerLoginCredential, + onSubmit: getServerAuthSettings, ), const SizedBox(height: 18), Row( @@ -344,7 +316,7 @@ class LoginForm extends HookConsumerWidget { ), ), onPressed: - isLoadingServer.value ? null : getServerLoginCredential, + isLoadingServer.value ? null : getServerAuthSettings, icon: const Icon(Icons.arrow_forward_rounded), label: const Text( 'login_form_next_button', @@ -402,7 +374,7 @@ class LoginForm extends HookConsumerWidget { if (isPasswordLoginEnable.value) ...[ const SizedBox(height: 18), EmailInput( - controller: usernameController, + controller: emailController, focusNode: emailFocusNode, onSubmit: passwordFocusNode.requestFocus, ), diff --git a/mobile/lib/widgets/map/map_app_bar.dart b/mobile/lib/widgets/map/map_app_bar.dart index 42bc598915a49..4de5721486007 100644 --- a/mobile/lib/widgets/map/map_app_bar.dart +++ b/mobile/lib/widgets/map/map_app_bar.dart @@ -19,7 +19,7 @@ class MapAppBar extends HookWidget implements PreferredSizeWidget { @override Widget build(BuildContext context) { return Padding( - padding: EdgeInsets.only(top: MediaQuery.paddingOf(context).top + 25), + padding: EdgeInsets.only(top: context.padding.top + 25), child: ValueListenableBuilder( valueListenable: selectedAssets, builder: (ctx, value, child) => value.isNotEmpty diff --git a/mobile/lib/widgets/map/map_theme_override.dart b/mobile/lib/widgets/map/map_theme_override.dart index 3b66a1cc35350..65425f9e78748 100644 --- a/mobile/lib/widgets/map/map_theme_override.dart +++ b/mobile/lib/widgets/map/map_theme_override.dart @@ -1,22 +1,24 @@ import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:immich_mobile/providers/locale_provider.dart'; import 'package:immich_mobile/providers/map/map_state.provider.dart'; -import 'package:immich_mobile/utils/immich_app_theme.dart'; +import 'package:immich_mobile/providers/theme.provider.dart'; +import 'package:immich_mobile/theme/theme_data.dart'; /// Overrides the theme below the widget tree to use the theme data based on the /// map settings instead of the one from the app settings -class MapThemeOveride extends StatefulHookConsumerWidget { +class MapThemeOverride extends StatefulHookConsumerWidget { final ThemeMode? themeMode; final Widget Function(AsyncValue style) mapBuilder; - const MapThemeOveride({required this.mapBuilder, this.themeMode, super.key}); + const MapThemeOverride({required this.mapBuilder, this.themeMode, super.key}); @override - ConsumerState createState() => _MapThemeOverideState(); + ConsumerState createState() => _MapThemeOverrideState(); } -class _MapThemeOverideState extends ConsumerState +class _MapThemeOverrideState extends ConsumerState with WidgetsBindingObserver { late ThemeMode _theme; bool _isDarkTheme = false; @@ -71,6 +73,7 @@ class _MapThemeOverideState extends ConsumerState _theme = widget.themeMode ?? ref.watch(mapStateNotifierProvider.select((v) => v.themeMode)); var appTheme = ref.watch(immichThemeProvider); + final locale = ref.watch(localeProvider); useValueChanged(_theme, (_, __) { if (_theme == ThemeMode.system) { @@ -85,8 +88,8 @@ class _MapThemeOverideState extends ConsumerState return Theme( data: _isDarkTheme - ? getThemeData(colorScheme: appTheme.dark) - : getThemeData(colorScheme: appTheme.light), + ? getThemeData(colorScheme: appTheme.dark, locale: locale) + : getThemeData(colorScheme: appTheme.light, locale: locale), child: widget.mapBuilder.call( ref.watch( mapStateNotifierProvider.select( diff --git a/mobile/lib/widgets/map/map_thumbnail.dart b/mobile/lib/widgets/map/map_thumbnail.dart index d02c01679169e..b856f097877f4 100644 --- a/mobile/lib/widgets/map/map_thumbnail.dart +++ b/mobile/lib/widgets/map/map_thumbnail.dart @@ -62,7 +62,7 @@ class MapThumbnail extends HookConsumerWidget { } } - return MapThemeOveride( + return MapThemeOverride( themeMode: themeMode, mapBuilder: (style) => SizedBox( height: height, diff --git a/mobile/lib/widgets/map/positioned_asset_marker_icon.dart b/mobile/lib/widgets/map/positioned_asset_marker_icon.dart index ac176b4701fd7..2cf82517ae589 100644 --- a/mobile/lib/widgets/map/positioned_asset_marker_icon.dart +++ b/mobile/lib/widgets/map/positioned_asset_marker_icon.dart @@ -26,7 +26,7 @@ class PositionedAssetMarkerIcon extends StatelessWidget { @override Widget build(BuildContext context) { - final ratio = Platform.isIOS ? 1.0 : MediaQuery.devicePixelRatioOf(context); + final ratio = Platform.isIOS ? 1.0 : context.devicePixelRatio; return AnimatedPositioned( left: point.x / ratio - size / 2, top: point.y / ratio - size, diff --git a/mobile/lib/widgets/memories/memory_card.dart b/mobile/lib/widgets/memories/memory_card.dart index fb7cc882a0d31..4954d0bfccc8d 100644 --- a/mobile/lib/widgets/memories/memory_card.dart +++ b/mobile/lib/widgets/memories/memory_card.dart @@ -2,9 +2,9 @@ import 'dart:ui'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; -import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/entities/asset.entity.dart'; -import 'package:immich_mobile/pages/common/video_viewer.page.dart'; +import 'package:immich_mobile/extensions/build_context_extensions.dart'; +import 'package:immich_mobile/pages/common/native_video_viewer.page.dart'; import 'package:immich_mobile/utils/hooks/blurhash_hook.dart'; import 'package:immich_mobile/widgets/common/immich_image.dart'; @@ -68,18 +68,20 @@ class MemoryCard extends StatelessWidget { } else { return Hero( tag: 'memory-${asset.id}', - child: VideoViewerPage( - key: ValueKey(asset), - asset: asset, - showDownloadingIndicator: false, - placeholder: SizedBox.expand( - child: ImmichImage( + child: SizedBox( + width: context.width, + height: context.height, + child: NativeVideoViewerPage( + key: ValueKey(asset.id), + asset: asset, + showControls: false, + image: ImmichImage( asset, + width: context.width, + height: context.height, fit: fit, ), ), - hideControlsTimer: const Duration(seconds: 2), - showControls: false, ), ); } @@ -137,6 +139,8 @@ class _BlurredBackdrop extends HookWidget { image: DecorationImage( image: ImmichImage.imageProvider( asset: asset, + height: context.height, + width: context.width, ), fit: BoxFit.cover, ), diff --git a/mobile/lib/widgets/search/search_filter/filter_bottom_sheet_scaffold.dart b/mobile/lib/widgets/search/search_filter/filter_bottom_sheet_scaffold.dart index d636c8c7ce47f..bda9335c77186 100644 --- a/mobile/lib/widgets/search/search_filter/filter_bottom_sheet_scaffold.dart +++ b/mobile/lib/widgets/search/search_filter/filter_bottom_sheet_scaffold.dart @@ -47,7 +47,7 @@ class FilterBottomSheetScaffold extends StatelessWidget { OutlinedButton( onPressed: () { onClear(); - Navigator.of(context).pop(); + context.pop(); }, child: const Text('action_common_clear').tr(), ), @@ -55,7 +55,7 @@ class FilterBottomSheetScaffold extends StatelessWidget { ElevatedButton( onPressed: () { onSearch(); - Navigator.of(context).pop(); + context.pop(); }, child: const Text('search_filter_apply').tr(), ), diff --git a/mobile/lib/widgets/settings/backup_settings/background_settings.dart b/mobile/lib/widgets/settings/backup_settings/background_settings.dart index a772aaaf5d8a7..4cdeb501c1a21 100644 --- a/mobile/lib/widgets/settings/backup_settings/background_settings.dart +++ b/mobile/lib/widgets/settings/backup_settings/background_settings.dart @@ -33,7 +33,7 @@ class BackgroundBackupSettings extends ConsumerWidget { ), backgroundColor: Colors.red, ); - ScaffoldMessenger.of(context).showSnackBar(snackBar); + context.scaffoldMessenger.showSnackBar(snackBar); } void showBatteryOptimizationInfoToUser() { diff --git a/mobile/lib/widgets/settings/backup_settings/backup_settings.dart b/mobile/lib/widgets/settings/backup_settings/backup_settings.dart index 2cecba6c4bdd2..6c681e01dfebe 100644 --- a/mobile/lib/widgets/settings/backup_settings/backup_settings.dart +++ b/mobile/lib/widgets/settings/backup_settings/backup_settings.dart @@ -54,7 +54,7 @@ class BackupSettings extends HookConsumerWidget { if (Platform.isAndroid && isAdvancedTroubleshooting.value) SettingsButtonListTile( icon: Icons.warning_rounded, - title: 'Check for corrupt asset backups', + title: 'check_corrupt_asset_backup'.tr(), subtitle: isCorruptCheckInProgress ? const Column( children: [ @@ -65,9 +65,9 @@ class BackupSettings extends HookConsumerWidget { ) : null, subtileText: !isCorruptCheckInProgress - ? 'Run this check only over Wi-Fi and once all assets have been backed-up. The procedure might take a few minutes.' + ? 'check_corrupt_asset_backup_description'.tr() : null, - buttonText: 'Perform check', + buttonText: 'check_corrupt_asset_backup_button'.tr(), onButtonTap: !isCorruptCheckInProgress ? () => ref .read(backupVerificationProvider.notifier) diff --git a/mobile/lib/widgets/settings/networking_settings/endpoint_input.dart b/mobile/lib/widgets/settings/networking_settings/endpoint_input.dart new file mode 100644 index 0000000000000..6302f9422ab95 --- /dev/null +++ b/mobile/lib/widgets/settings/networking_settings/endpoint_input.dart @@ -0,0 +1,155 @@ +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'; +import 'package:immich_mobile/models/auth/auxilary_endpoint.model.dart'; +import 'package:immich_mobile/providers/auth.provider.dart'; +import 'package:immich_mobile/widgets/settings/networking_settings/networking_settings.dart'; + +class EndpointInput extends StatefulHookConsumerWidget { + const EndpointInput({ + super.key, + required this.initialValue, + required this.index, + required this.onValidated, + required this.onDismissed, + this.enabled = true, + }); + + final AuxilaryEndpoint initialValue; + final int index; + final Function(String url, int index, AuxCheckStatus status) onValidated; + final Function(int index) onDismissed; + final bool enabled; + + @override + EndpointInputState createState() => EndpointInputState(); +} + +class EndpointInputState extends ConsumerState { + late final TextEditingController controller; + late final FocusNode focusNode; + late AuxCheckStatus auxCheckStatus; + bool isInputValid = false; + + @override + void initState() { + super.initState(); + controller = TextEditingController(text: widget.initialValue.url); + focusNode = FocusNode()..addListener(_onOutFocus); + + setState(() { + auxCheckStatus = widget.initialValue.status; + }); + } + + @override + void dispose() { + focusNode.removeListener(_onOutFocus); + focusNode.dispose(); + controller.dispose(); + super.dispose(); + } + + void _onOutFocus() { + if (!focusNode.hasFocus && isInputValid) { + validateAuxilaryServerUrl(); + } + } + + Future validateAuxilaryServerUrl() async { + final url = controller.text; + setState(() => auxCheckStatus = AuxCheckStatus.loading); + + final isValid = + await ref.read(authProvider.notifier).validateAuxilaryServerUrl(url); + + setState(() { + if (mounted) { + auxCheckStatus = isValid ? AuxCheckStatus.valid : AuxCheckStatus.error; + } + }); + + widget.onValidated(url, widget.index, auxCheckStatus); + } + + String? validateUrl(String? url) { + try { + if (url == null || url.isEmpty || !Uri.parse(url).isAbsolute) { + isInputValid = false; + return 'validate_endpoint_error'.tr(); + } + } catch (_) { + isInputValid = false; + return 'validate_endpoint_error'.tr(); + } + + isInputValid = true; + return null; + } + + @override + Widget build(BuildContext context) { + return Dismissible( + key: ValueKey(widget.index.toString()), + direction: DismissDirection.endToStart, + onDismissed: (_) => widget.onDismissed(widget.index), + background: Container( + color: Colors.red, + alignment: Alignment.centerRight, + padding: const EdgeInsets.only(right: 16), + child: const Icon( + Icons.delete, + color: Colors.white, + ), + ), + child: ListTile( + contentPadding: const EdgeInsets.symmetric(horizontal: 24), + trailing: ReorderableDragStartListener( + enabled: widget.enabled, + index: widget.index, + child: const Icon(Icons.drag_handle_rounded), + ), + leading: NetworkStatusIcon( + key: ValueKey('status_$auxCheckStatus'), + status: auxCheckStatus, + enabled: widget.enabled, + ), + subtitle: TextFormField( + enabled: widget.enabled, + onTapOutside: (_) => focusNode.unfocus(), + autovalidateMode: AutovalidateMode.onUserInteraction, + validator: validateUrl, + keyboardType: TextInputType.url, + style: const TextStyle( + fontFamily: 'Inconsolata', + fontWeight: FontWeight.w600, + fontSize: 14, + ), + decoration: InputDecoration( + hintText: 'http(s)://immich.domain.com', + contentPadding: const EdgeInsets.all(16), + filled: true, + fillColor: context.colorScheme.surfaceContainer, + border: const OutlineInputBorder( + borderRadius: BorderRadius.all(Radius.circular(16)), + ), + errorBorder: OutlineInputBorder( + borderSide: BorderSide(color: Colors.red[300]!), + borderRadius: const BorderRadius.all(Radius.circular(16)), + ), + disabledBorder: OutlineInputBorder( + borderSide: BorderSide( + color: + context.isDarkTheme ? Colors.grey[900]! : Colors.grey[300]!, + ), + borderRadius: const BorderRadius.all(Radius.circular(16)), + ), + ), + controller: controller, + focusNode: focusNode, + ), + ), + ); + } +} diff --git a/mobile/lib/widgets/settings/networking_settings/external_network_preference.dart b/mobile/lib/widgets/settings/networking_settings/external_network_preference.dart new file mode 100644 index 0000000000000..13c109fa0e3f1 --- /dev/null +++ b/mobile/lib/widgets/settings/networking_settings/external_network_preference.dart @@ -0,0 +1,189 @@ +import 'dart:convert'; + +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/extensions/build_context_extensions.dart'; +import 'package:immich_mobile/models/auth/auxilary_endpoint.model.dart'; +import 'package:immich_mobile/entities/store.entity.dart' as db_store; +import 'package:immich_mobile/widgets/settings/networking_settings/endpoint_input.dart'; + +class ExternalNetworkPreference extends HookConsumerWidget { + const ExternalNetworkPreference({super.key, required this.enabled}); + + final bool enabled; + + @override + Widget build(BuildContext context, WidgetRef ref) { + final entries = + useState([AuxilaryEndpoint(url: '', status: AuxCheckStatus.unknown)]); + final canSave = useState(false); + + saveEndpointList() { + canSave.value = + entries.value.every((e) => e.status == AuxCheckStatus.valid); + + final endpointList = entries.value + .where((url) => url.status == AuxCheckStatus.valid) + .toList(); + + final jsonString = jsonEncode(endpointList); + + db_store.Store.put( + db_store.StoreKey.externalEndpointList, + jsonString, + ); + } + + updateValidationStatus(String url, int index, AuxCheckStatus status) { + entries.value[index] = + entries.value[index].copyWith(url: url, status: status); + + saveEndpointList(); + } + + handleReorder(int oldIndex, int newIndex) { + if (oldIndex < newIndex) { + newIndex -= 1; + } + + final entry = entries.value.removeAt(oldIndex); + entries.value.insert(newIndex, entry); + entries.value = [...entries.value]; + + saveEndpointList(); + } + + handleDismiss(int index) { + entries.value = [...entries.value..removeAt(index)]; + + saveEndpointList(); + } + + Widget proxyDecorator( + Widget child, + int index, + Animation animation, + ) { + return AnimatedBuilder( + animation: animation, + builder: (BuildContext context, Widget? child) { + return Material( + color: context.colorScheme.surfaceContainerHighest, + shadowColor: context.colorScheme.primary.withOpacity(0.2), + child: child, + ); + }, + child: child, + ); + } + + useEffect( + () { + final jsonString = + db_store.Store.tryGet(db_store.StoreKey.externalEndpointList); + + if (jsonString == null) { + return null; + } + + final List jsonList = jsonDecode(jsonString); + entries.value = + jsonList.map((e) => AuxilaryEndpoint.fromJson(e)).toList(); + return null; + }, + const [], + ); + + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 16.0), + child: Container( + clipBehavior: Clip.antiAlias, + decoration: BoxDecoration( + borderRadius: const BorderRadius.all(Radius.circular(16)), + color: context.colorScheme.surfaceContainerLow, + border: Border.all( + color: context.colorScheme.surfaceContainerHighest, + width: 1, + ), + ), + child: Stack( + children: [ + Positioned( + bottom: -36, + right: -36, + child: Icon( + Icons.dns_rounded, + size: 120, + color: context.primaryColor.withOpacity(0.05), + ), + ), + ListView( + padding: const EdgeInsets.symmetric(vertical: 16.0), + physics: const ClampingScrollPhysics(), + shrinkWrap: true, + children: [ + Padding( + padding: const EdgeInsets.symmetric( + vertical: 4.0, + horizontal: 24, + ), + child: Text( + "external_network_sheet_info".tr(), + style: context.textTheme.bodyMedium, + ), + ), + const SizedBox(height: 4), + Divider(color: context.colorScheme.surfaceContainerHighest), + Form( + key: GlobalKey(), + child: ReorderableListView.builder( + buildDefaultDragHandles: false, + proxyDecorator: proxyDecorator, + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + itemCount: entries.value.length, + onReorder: handleReorder, + itemBuilder: (context, index) { + return EndpointInput( + key: Key(index.toString()), + index: index, + initialValue: entries.value[index], + onValidated: updateValidationStatus, + onDismissed: handleDismiss, + enabled: enabled, + ); + }, + ), + ), + const SizedBox(height: 24), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 24.0), + child: SizedBox( + height: 48, + child: OutlinedButton.icon( + icon: const Icon(Icons.add), + label: Text('add_endpoint'.tr().toUpperCase()), + onPressed: enabled + ? () { + entries.value = [ + ...entries.value, + AuxilaryEndpoint( + url: '', + status: AuxCheckStatus.unknown, + ), + ]; + } + : null, + ), + ), + ), + ], + ), + ], + ), + ), + ); + } +} diff --git a/mobile/lib/widgets/settings/networking_settings/local_network_preference.dart b/mobile/lib/widgets/settings/networking_settings/local_network_preference.dart new file mode 100644 index 0000000000000..0258cc38474a4 --- /dev/null +++ b/mobile/lib/widgets/settings/networking_settings/local_network_preference.dart @@ -0,0 +1,256 @@ +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/extensions/build_context_extensions.dart'; +import 'package:immich_mobile/providers/auth.provider.dart'; +import 'package:immich_mobile/providers/network.provider.dart'; + +class LocalNetworkPreference extends HookConsumerWidget { + const LocalNetworkPreference({ + super.key, + required this.enabled, + }); + + final bool enabled; + + Future _showEditDialog( + BuildContext context, + String title, + String hintText, + String initialValue, + ) { + final controller = TextEditingController(text: initialValue); + + return showDialog( + context: context, + builder: (context) => AlertDialog( + title: Text(title), + content: TextField( + controller: controller, + autofocus: true, + decoration: InputDecoration( + border: const OutlineInputBorder(), + hintText: hintText, + ), + ), + actions: [ + TextButton( + onPressed: () => Navigator.pop(context), + child: Text( + 'cancel'.tr().toUpperCase(), + style: const TextStyle(color: Colors.red), + ), + ), + TextButton( + onPressed: () => Navigator.pop(context, controller.text), + child: Text('save'.tr().toUpperCase()), + ), + ], + ), + ); + } + + @override + Widget build(BuildContext context, WidgetRef ref) { + final wifiNameText = useState(""); + final localEndpointText = useState(""); + + useEffect( + () { + final wifiName = ref.read(authProvider.notifier).getSavedWifiName(); + final localEndpoint = + ref.read(authProvider.notifier).getSavedLocalEndpoint(); + + if (wifiName != null) { + wifiNameText.value = wifiName; + } + + if (localEndpoint != null) { + localEndpointText.value = localEndpoint; + } + + return null; + }, + [], + ); + + saveWifiName(String wifiName) { + wifiNameText.value = wifiName; + return ref.read(authProvider.notifier).saveWifiName(wifiName); + } + + saveLocalEndpoint(String url) { + localEndpointText.value = url; + return ref.read(authProvider.notifier).saveLocalEndpoint(url); + } + + handleEditWifiName() async { + final wifiName = await _showEditDialog( + context, + "wifi_name".tr(), + "your_wifi_name".tr(), + wifiNameText.value, + ); + + if (wifiName != null) { + await saveWifiName(wifiName); + } + } + + handleEditServerEndpoint() async { + final localEndpoint = await _showEditDialog( + context, + "server_endpoint".tr(), + "http://local-ip:2283/api", + localEndpointText.value, + ); + + if (localEndpoint != null) { + await saveLocalEndpoint(localEndpoint); + } + } + + autofillCurrentNetwork() async { + final wifiName = await ref.read(networkProvider.notifier).getWifiName(); + + if (wifiName == null) { + context.showSnackBar( + SnackBar( + content: Text( + "get_wifiname_error".tr(), + style: context.textTheme.bodyMedium?.copyWith( + fontWeight: FontWeight.w500, + color: context.colorScheme.onSecondary, + ), + ), + backgroundColor: context.colorScheme.secondary, + ), + ); + } else { + saveWifiName(wifiName); + } + + final serverEndpoint = + ref.read(authProvider.notifier).getServerEndpoint(); + + if (serverEndpoint != null) { + saveLocalEndpoint(serverEndpoint); + } + } + + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 16.0), + child: Stack( + children: [ + Container( + clipBehavior: Clip.antiAlias, + decoration: BoxDecoration( + borderRadius: const BorderRadius.all(Radius.circular(16)), + color: context.colorScheme.surfaceContainerLow, + border: Border.all( + color: context.colorScheme.surfaceContainerHighest, + width: 1, + ), + ), + child: Stack( + children: [ + Positioned( + bottom: -36, + right: -36, + child: Icon( + Icons.home_outlined, + size: 120, + color: context.primaryColor.withOpacity(0.05), + ), + ), + ListView( + padding: const EdgeInsets.symmetric(vertical: 16.0), + physics: const ClampingScrollPhysics(), + shrinkWrap: true, + children: [ + Padding( + padding: const EdgeInsets.symmetric( + vertical: 4.0, + horizontal: 24, + ), + child: Text( + "local_network_sheet_info".tr(), + style: context.textTheme.bodyMedium, + ), + ), + const SizedBox(height: 4), + Divider( + color: context.colorScheme.surfaceContainerHighest, + ), + ListTile( + enabled: enabled, + contentPadding: const EdgeInsets.only(left: 24, right: 8), + leading: const Icon(Icons.wifi_rounded), + title: Text("wifi_name".tr()), + subtitle: wifiNameText.value.isEmpty + ? Text("enter_wifi_name".tr()) + : Text( + wifiNameText.value, + style: context.textTheme.labelLarge?.copyWith( + fontWeight: FontWeight.bold, + color: enabled + ? context.primaryColor + : context.colorScheme.onSurface + .withAlpha(100), + fontFamily: 'Inconsolata', + ), + ), + trailing: IconButton( + onPressed: enabled ? handleEditWifiName : null, + icon: const Icon(Icons.edit_rounded), + ), + ), + ListTile( + enabled: enabled, + contentPadding: const EdgeInsets.only(left: 24, right: 8), + leading: const Icon(Icons.lan_rounded), + title: Text("server_endpoint".tr()), + subtitle: localEndpointText.value.isEmpty + ? const Text("http://local-ip:2283/api") + : Text( + localEndpointText.value, + style: context.textTheme.labelLarge?.copyWith( + fontWeight: FontWeight.bold, + color: enabled + ? context.primaryColor + : context.colorScheme.onSurface + .withAlpha(100), + fontFamily: 'Inconsolata', + ), + ), + trailing: IconButton( + onPressed: enabled ? handleEditServerEndpoint : null, + icon: const Icon(Icons.edit_rounded), + ), + ), + const SizedBox(height: 16), + Padding( + padding: const EdgeInsets.symmetric( + horizontal: 24.0, + ), + child: SizedBox( + height: 48, + child: OutlinedButton.icon( + icon: const Icon(Icons.wifi_find_rounded), + label: + Text('use_current_connection'.tr().toUpperCase()), + onPressed: enabled ? autofillCurrentNetwork : null, + ), + ), + ), + ], + ), + ], + ), + ), + ], + ), + ); + } +} diff --git a/mobile/lib/widgets/settings/networking_settings/networking_settings.dart b/mobile/lib/widgets/settings/networking_settings/networking_settings.dart new file mode 100644 index 0000000000000..59d05fd4cf525 --- /dev/null +++ b/mobile/lib/widgets/settings/networking_settings/networking_settings.dart @@ -0,0 +1,266 @@ +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/models/auth/auxilary_endpoint.model.dart'; +import 'package:immich_mobile/providers/network.provider.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/widgets/settings/networking_settings/external_network_preference.dart'; +import 'package:immich_mobile/widgets/settings/networking_settings/local_network_preference.dart'; +import 'package:immich_mobile/widgets/settings/settings_switch_list_tile.dart'; + +import 'package:immich_mobile/entities/store.entity.dart' as db_store; +import 'package:immich_mobile/extensions/build_context_extensions.dart'; + +class NetworkingSettings extends HookConsumerWidget { + const NetworkingSettings({super.key}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final currentEndpoint = + db_store.Store.get(db_store.StoreKey.serverEndpoint); + final featureEnabled = + useAppSettingsState(AppSettingsEnum.autoEndpointSwitching); + + Future checkWifiReadPermission() async { + final [hasLocationInUse, hasLocationAlways] = await Future.wait([ + ref.read(networkProvider.notifier).getWifiReadPermission(), + ref.read(networkProvider.notifier).getWifiReadBackgroundPermission(), + ]); + + bool? isGrantLocationAlwaysPermission; + + if (!hasLocationInUse) { + await showDialog( + context: context, + builder: (context) { + return AlertDialog( + title: Text("location_permission".tr()), + content: Text("location_permission_content".tr()), + actions: [ + TextButton( + onPressed: () async { + final isGrant = await ref + .read(networkProvider.notifier) + .requestWifiReadPermission(); + + Navigator.pop(context, isGrant); + }, + child: Text("grant_permission".tr()), + ), + ], + ); + }, + ); + } + + if (!hasLocationAlways) { + isGrantLocationAlwaysPermission = await showDialog( + context: context, + builder: (context) { + return AlertDialog( + title: Text("background_location_permission".tr()), + content: Text("background_location_permission_content".tr()), + actions: [ + TextButton( + onPressed: () async { + final isGrant = await ref + .read(networkProvider.notifier) + .requestWifiReadBackgroundPermission(); + + Navigator.pop(context, isGrant); + }, + child: Text("grant_permission".tr()), + ), + ], + ); + }, + ); + } + + if (isGrantLocationAlwaysPermission != null && + !isGrantLocationAlwaysPermission) { + await ref.read(networkProvider.notifier).openSettings(); + } + } + + useEffect( + () { + if (featureEnabled.value == true) { + checkWifiReadPermission(); + } + return null; + }, + [featureEnabled.value], + ); + + return ListView( + padding: const EdgeInsets.only(bottom: 96), + physics: const ClampingScrollPhysics(), + children: [ + Padding( + padding: const EdgeInsets.only(top: 8, left: 16, bottom: 8), + child: NetworkPreferenceTitle( + title: "current_server_address".tr().toUpperCase(), + icon: currentEndpoint.startsWith('https') + ? Icons.https_outlined + : Icons.http_outlined, + ), + ), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 8), + child: Card( + elevation: 0, + shape: RoundedRectangleBorder( + borderRadius: const BorderRadius.all(Radius.circular(16)), + side: BorderSide( + color: context.colorScheme.surfaceContainerHighest, + width: 1, + ), + ), + child: ListTile( + leading: + const Icon(Icons.check_circle_rounded, color: Colors.green), + title: Text( + currentEndpoint, + style: TextStyle( + fontSize: 16, + fontFamily: 'Inconsolata', + fontWeight: FontWeight.bold, + color: context.primaryColor, + ), + ), + ), + ), + ), + Padding( + padding: const EdgeInsets.only(top: 10.0), + child: Divider( + color: context.colorScheme.surfaceContainerHighest, + ), + ), + SettingsSwitchListTile( + enabled: true, + valueNotifier: featureEnabled, + title: "automatic_endpoint_switching_title".tr(), + subtitle: "automatic_endpoint_switching_subtitle".tr(), + ), + Padding( + padding: const EdgeInsets.only(top: 8, left: 16, bottom: 16), + child: NetworkPreferenceTitle( + title: "local_network".tr().toUpperCase(), + icon: Icons.home_outlined, + ), + ), + LocalNetworkPreference( + enabled: featureEnabled.value, + ), + Padding( + padding: const EdgeInsets.only(top: 32, left: 16, bottom: 16), + child: NetworkPreferenceTitle( + title: "external_network".tr().toUpperCase(), + icon: Icons.dns_outlined, + ), + ), + ExternalNetworkPreference( + enabled: featureEnabled.value, + ), + ], + ); + } +} + +class NetworkPreferenceTitle extends StatelessWidget { + const NetworkPreferenceTitle({ + super.key, + required this.icon, + required this.title, + }); + + final IconData icon; + final String title; + + @override + Widget build(BuildContext context) { + return Row( + children: [ + Icon( + icon, + color: context.colorScheme.onSurface.withAlpha(150), + ), + const SizedBox(width: 8), + Text( + title, + style: context.textTheme.displaySmall?.copyWith( + color: context.colorScheme.onSurface.withAlpha(200), + fontWeight: FontWeight.w500, + ), + ), + ], + ); + } +} + +class NetworkStatusIcon extends StatelessWidget { + const NetworkStatusIcon({ + super.key, + required this.status, + this.enabled = true, + }) : super(); + + final AuxCheckStatus status; + final bool enabled; + + @override + Widget build(BuildContext context) { + return AnimatedSwitcher( + duration: const Duration(milliseconds: 200), + child: _buildIcon(context), + ); + } + + Widget _buildIcon(BuildContext context) { + switch (status) { + case AuxCheckStatus.loading: + return Padding( + padding: const EdgeInsets.only(left: 4.0), + child: SizedBox( + width: 18, + height: 18, + child: CircularProgressIndicator( + color: context.primaryColor, + strokeWidth: 2, + key: const ValueKey('loading'), + ), + ), + ); + case AuxCheckStatus.valid: + return enabled + ? const Icon( + Icons.check_circle_rounded, + color: Colors.green, + key: ValueKey('success'), + ) + : Icon( + Icons.check_circle_rounded, + color: context.colorScheme.onSurface.withAlpha(100), + key: const ValueKey('success'), + ); + case AuxCheckStatus.error: + return enabled + ? const Icon( + Icons.error_rounded, + color: Colors.red, + key: ValueKey('error'), + ) + : const Icon( + Icons.error_rounded, + color: Colors.grey, + key: ValueKey('error'), + ); + default: + return const Icon(Icons.circle_outlined, key: ValueKey('unknown')); + } + } +} 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 1c7cd1f2070cd..119407ccad942 100644 --- a/mobile/lib/widgets/settings/preference_settings/primary_color_setting.dart +++ b/mobile/lib/widgets/settings/preference_settings/primary_color_setting.dart @@ -2,12 +2,14 @@ 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/constants/immich_colors.dart'; +import 'package:immich_mobile/constants/colors.dart'; import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/extensions/theme_extensions.dart'; +import 'package:immich_mobile/providers/theme.provider.dart'; import 'package:immich_mobile/services/app_settings.service.dart'; -import 'package:immich_mobile/utils/immich_app_theme.dart'; import 'package:immich_mobile/utils/hooks/app_settings_update_hook.dart'; +import 'package:immich_mobile/theme/color_scheme.dart'; +import 'package:immich_mobile/theme/dynamic_theme.dart'; class PrimaryColorSetting extends HookConsumerWidget { const PrimaryColorSetting({ @@ -124,7 +126,7 @@ class PrimaryColorSetting extends HookConsumerWidget { style: context.textTheme.titleLarge, ), ), - if (isDynamicThemeAvailable) + if (DynamicTheme.isAvailable) Container( padding: const EdgeInsets.symmetric(horizontal: 20), margin: const EdgeInsets.only(top: 10), @@ -153,16 +155,16 @@ class PrimaryColorSetting extends HookConsumerWidget { padding: const EdgeInsets.symmetric(horizontal: 20), child: Wrap( crossAxisAlignment: WrapCrossAlignment.center, - children: ImmichColorPreset.values.map((themePreset) { - var theme = themePreset.getTheme(); + children: ImmichColorPreset.values.map((preset) { + final theme = preset.themeOfPreset; return GestureDetector( - onTap: () => onPrimaryColorChange(themePreset), + onTap: () => onPrimaryColorChange(preset), child: buildPrimaryColorTile( topColor: theme.light.primary, bottomColor: theme.dark.primary, tileSize: tileSize, - showSelector: currentPreset.value == themePreset && + showSelector: currentPreset.value == preset && !systemPrimaryColorSetting.value, ), ); diff --git a/mobile/lib/widgets/settings/preference_settings/theme_setting.dart b/mobile/lib/widgets/settings/preference_settings/theme_setting.dart index 050593a2297f8..b9ba7aa7b7fee 100644 --- a/mobile/lib/widgets/settings/preference_settings/theme_setting.dart +++ b/mobile/lib/widgets/settings/preference_settings/theme_setting.dart @@ -2,12 +2,13 @@ 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/extensions/build_context_extensions.dart'; +import 'package:immich_mobile/providers/theme.provider.dart'; import 'package:immich_mobile/services/app_settings.service.dart'; import 'package:immich_mobile/widgets/settings/preference_settings/primary_color_setting.dart'; import 'package:immich_mobile/widgets/settings/settings_sub_title.dart'; import 'package:immich_mobile/widgets/settings/settings_switch_list_tile.dart'; import 'package:immich_mobile/utils/hooks/app_settings_update_hook.dart'; -import 'package:immich_mobile/utils/immich_app_theme.dart'; class ThemeSetting extends HookConsumerWidget { const ThemeSetting({ @@ -58,8 +59,7 @@ class ThemeSetting extends HookConsumerWidget { isSystemTheme.value = true; ref.watch(immichThemeModeProvider.notifier).state = ThemeMode.system; } else { - final currentSystemBrightness = - MediaQuery.platformBrightnessOf(context); + final currentSystemBrightness = context.platformBrightness; isSystemTheme.value = false; isDarkTheme.value = currentSystemBrightness == Brightness.dark; if (currentSystemBrightness == Brightness.light) { diff --git a/mobile/lib/widgets/shared_link/shared_link_item.dart b/mobile/lib/widgets/shared_link/shared_link_item.dart index 9e29f5f9a05b9..a9ed359280b43 100644 --- a/mobile/lib/widgets/shared_link/shared_link_item.dart +++ b/mobile/lib/widgets/shared_link/shared_link_item.dart @@ -94,7 +94,7 @@ class SharedLinkItem extends ConsumerWidget { Clipboard.setData( ClipboardData(text: "${serverUrl}share/${sharedLink.key}"), ).then((_) { - ScaffoldMessenger.of(context).showSnackBar( + context.scaffoldMessenger.showSnackBar( SnackBar( content: Text( "shared_link_clipboard_copied_massage", diff --git a/mobile/openapi/README.md b/mobile/openapi/README.md index 4cdb08ce9988a..a28035c01a9d2 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.119.1 +- API version: 1.123.0 - Generator version: 7.8.0 - Build package: org.openapitools.codegen.languages.DartClientCodegen @@ -93,17 +93,17 @@ Class | Method | HTTP request | Description *AlbumsApi* | [**removeUserFromAlbum**](doc//AlbumsApi.md#removeuserfromalbum) | **DELETE** /albums/{id}/user/{userId} | *AlbumsApi* | [**updateAlbumInfo**](doc//AlbumsApi.md#updatealbuminfo) | **PATCH** /albums/{id} | *AlbumsApi* | [**updateAlbumUser**](doc//AlbumsApi.md#updatealbumuser) | **PUT** /albums/{id}/user/{userId} | -*AssetsApi* | [**checkBulkUpload**](doc//AssetsApi.md#checkbulkupload) | **POST** /assets/bulk-upload-check | -*AssetsApi* | [**checkExistingAssets**](doc//AssetsApi.md#checkexistingassets) | **POST** /assets/exist | +*AssetsApi* | [**checkBulkUpload**](doc//AssetsApi.md#checkbulkupload) | **POST** /assets/bulk-upload-check | Checks if assets exist by checksums +*AssetsApi* | [**checkExistingAssets**](doc//AssetsApi.md#checkexistingassets) | **POST** /assets/exist | Checks if multiple assets exist on the server and returns all existing - used by background backup *AssetsApi* | [**deleteAssets**](doc//AssetsApi.md#deleteassets) | **DELETE** /assets | *AssetsApi* | [**downloadAsset**](doc//AssetsApi.md#downloadasset) | **GET** /assets/{id}/original | -*AssetsApi* | [**getAllUserAssetsByDeviceId**](doc//AssetsApi.md#getalluserassetsbydeviceid) | **GET** /assets/device/{deviceId} | +*AssetsApi* | [**getAllUserAssetsByDeviceId**](doc//AssetsApi.md#getalluserassetsbydeviceid) | **GET** /assets/device/{deviceId} | Get all asset of a device that are in the database, ID only. *AssetsApi* | [**getAssetInfo**](doc//AssetsApi.md#getassetinfo) | **GET** /assets/{id} | *AssetsApi* | [**getAssetStatistics**](doc//AssetsApi.md#getassetstatistics) | **GET** /assets/statistics | *AssetsApi* | [**getMemoryLane**](doc//AssetsApi.md#getmemorylane) | **GET** /assets/memory-lane | *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 | +*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* | [**updateAssets**](doc//AssetsApi.md#updateassets) | **PUT** /assets | @@ -144,6 +144,7 @@ Class | Method | HTTP request | Description *MemoriesApi* | [**removeMemoryAssets**](doc//MemoriesApi.md#removememoryassets) | **DELETE** /memories/{id}/assets | *MemoriesApi* | [**searchMemories**](doc//MemoriesApi.md#searchmemories) | **GET** /memories | *MemoriesApi* | [**updateMemory**](doc//MemoriesApi.md#updatememory) | **PUT** /memories/{id} | +*NotificationsApi* | [**getNotificationTemplate**](doc//NotificationsApi.md#getnotificationtemplate) | **POST** /notifications/templates/{name} | *NotificationsApi* | [**sendTestEmail**](doc//NotificationsApi.md#sendtestemail) | **POST** /notifications/test-email | *OAuthApi* | [**finishOAuth**](doc//OAuthApi.md#finishoauth) | **POST** /oauth/callback | *OAuthApi* | [**linkOAuthAccount**](doc//OAuthApi.md#linkoauthaccount) | **POST** /oauth/link | @@ -166,7 +167,7 @@ Class | Method | HTTP request | Description *SearchApi* | [**getAssetsByCity**](doc//SearchApi.md#getassetsbycity) | **GET** /search/cities | *SearchApi* | [**getExploreData**](doc//SearchApi.md#getexploredata) | **GET** /search/explore | *SearchApi* | [**getSearchSuggestions**](doc//SearchApi.md#getsearchsuggestions) | **GET** /search/suggestions | -*SearchApi* | [**searchMetadata**](doc//SearchApi.md#searchmetadata) | **POST** /search/metadata | +*SearchApi* | [**searchAssets**](doc//SearchApi.md#searchassets) | **POST** /search/metadata | *SearchApi* | [**searchPerson**](doc//SearchApi.md#searchperson) | **GET** /search/person | *SearchApi* | [**searchPlaces**](doc//SearchApi.md#searchplaces) | **GET** /search/places | *SearchApi* | [**searchRandom**](doc//SearchApi.md#searchrandom) | **POST** /search/random | @@ -408,7 +409,6 @@ Class | Method | HTTP request | Description - [SharedLinkResponseDto](doc//SharedLinkResponseDto.md) - [SharedLinkType](doc//SharedLinkType.md) - [SignUpDto](doc//SignUpDto.md) - - [SmartInfoResponseDto](doc//SmartInfoResponseDto.md) - [SmartSearchDto](doc//SmartSearchDto.md) - [SourceType](doc//SourceType.md) - [StackCreateDto](doc//StackCreateDto.md) @@ -437,7 +437,9 @@ Class | Method | HTTP request | Description - [SystemConfigSmtpDto](doc//SystemConfigSmtpDto.md) - [SystemConfigSmtpTransportDto](doc//SystemConfigSmtpTransportDto.md) - [SystemConfigStorageTemplateDto](doc//SystemConfigStorageTemplateDto.md) + - [SystemConfigTemplateEmailsDto](doc//SystemConfigTemplateEmailsDto.md) - [SystemConfigTemplateStorageOptionDto](doc//SystemConfigTemplateStorageOptionDto.md) + - [SystemConfigTemplatesDto](doc//SystemConfigTemplatesDto.md) - [SystemConfigThemeDto](doc//SystemConfigThemeDto.md) - [SystemConfigTrashDto](doc//SystemConfigTrashDto.md) - [SystemConfigUserDto](doc//SystemConfigUserDto.md) @@ -449,6 +451,8 @@ Class | Method | HTTP request | Description - [TagUpsertDto](doc//TagUpsertDto.md) - [TagsResponse](doc//TagsResponse.md) - [TagsUpdate](doc//TagsUpdate.md) + - [TemplateDto](doc//TemplateDto.md) + - [TemplateResponseDto](doc//TemplateResponseDto.md) - [TestEmailResponseDto](doc//TestEmailResponseDto.md) - [TimeBucketResponseDto](doc//TimeBucketResponseDto.md) - [TimeBucketSize](doc//TimeBucketSize.md) diff --git a/mobile/openapi/lib/api.dart b/mobile/openapi/lib/api.dart index b4c51c8e997e3..73eb02d89ed7a 100644 --- a/mobile/openapi/lib/api.dart +++ b/mobile/openapi/lib/api.dart @@ -222,7 +222,6 @@ part 'model/shared_link_edit_dto.dart'; part 'model/shared_link_response_dto.dart'; part 'model/shared_link_type.dart'; part 'model/sign_up_dto.dart'; -part 'model/smart_info_response_dto.dart'; part 'model/smart_search_dto.dart'; part 'model/source_type.dart'; part 'model/stack_create_dto.dart'; @@ -251,7 +250,9 @@ part 'model/system_config_server_dto.dart'; part 'model/system_config_smtp_dto.dart'; part 'model/system_config_smtp_transport_dto.dart'; part 'model/system_config_storage_template_dto.dart'; +part 'model/system_config_template_emails_dto.dart'; part 'model/system_config_template_storage_option_dto.dart'; +part 'model/system_config_templates_dto.dart'; part 'model/system_config_theme_dto.dart'; part 'model/system_config_trash_dto.dart'; part 'model/system_config_user_dto.dart'; @@ -263,6 +264,8 @@ part 'model/tag_update_dto.dart'; part 'model/tag_upsert_dto.dart'; part 'model/tags_response.dart'; part 'model/tags_update.dart'; +part 'model/template_dto.dart'; +part 'model/template_response_dto.dart'; part 'model/test_email_response_dto.dart'; part 'model/time_bucket_response_dto.dart'; part 'model/time_bucket_size.dart'; diff --git a/mobile/openapi/lib/api/notifications_api.dart b/mobile/openapi/lib/api/notifications_api.dart index 0681d582479ad..323fbcc3d6bc0 100644 --- a/mobile/openapi/lib/api/notifications_api.dart +++ b/mobile/openapi/lib/api/notifications_api.dart @@ -16,6 +16,58 @@ class NotificationsApi { final ApiClient apiClient; + /// Performs an HTTP 'POST /notifications/templates/{name}' operation and returns the [Response]. + /// Parameters: + /// + /// * [String] name (required): + /// + /// * [TemplateDto] templateDto (required): + Future getNotificationTemplateWithHttpInfo(String name, TemplateDto templateDto,) async { + // ignore: prefer_const_declarations + final path = r'/notifications/templates/{name}' + .replaceAll('{name}', name); + + // ignore: prefer_final_locals + Object? postBody = templateDto; + + final queryParams = []; + final headerParams = {}; + final formParams = {}; + + const contentTypes = ['application/json']; + + + return apiClient.invokeAPI( + path, + 'POST', + queryParams, + postBody, + headerParams, + formParams, + contentTypes.isEmpty ? null : contentTypes.first, + ); + } + + /// Parameters: + /// + /// * [String] name (required): + /// + /// * [TemplateDto] templateDto (required): + Future getNotificationTemplate(String name, TemplateDto templateDto,) async { + final response = await getNotificationTemplateWithHttpInfo(name, templateDto,); + if (response.statusCode >= HttpStatus.badRequest) { + throw ApiException(response.statusCode, await _decodeBodyBytes(response)); + } + // When a remote server returns no body with a status of 204, we shall not decode it. + // At the time of writing this, `dart:convert` will throw an "Unexpected end of input" + // FormatException when trying to decode an empty string. + if (response.body.isNotEmpty && response.statusCode != HttpStatus.noContent) { + return await apiClient.deserializeAsync(await _decodeBodyBytes(response), 'TemplateResponseDto',) as TemplateResponseDto; + + } + return null; + } + /// Performs an HTTP 'POST /notifications/test-email' operation and returns the [Response]. /// Parameters: /// diff --git a/mobile/openapi/lib/api/people_api.dart b/mobile/openapi/lib/api/people_api.dart index 7df0d66c79cfb..92bd0fdeeacbf 100644 --- a/mobile/openapi/lib/api/people_api.dart +++ b/mobile/openapi/lib/api/people_api.dart @@ -66,6 +66,10 @@ class PeopleApi { /// Performs an HTTP 'GET /people' operation and returns the [Response]. /// Parameters: /// + /// * [String] closestAssetId: + /// + /// * [String] closestPersonId: + /// /// * [num] page: /// Page number for pagination /// @@ -73,7 +77,7 @@ class PeopleApi { /// Number of items per page /// /// * [bool] withHidden: - Future getAllPeopleWithHttpInfo({ num? page, num? size, bool? withHidden, }) async { + Future getAllPeopleWithHttpInfo({ String? closestAssetId, String? closestPersonId, num? page, num? size, bool? withHidden, }) async { // ignore: prefer_const_declarations final path = r'/people'; @@ -84,6 +88,12 @@ class PeopleApi { final headerParams = {}; final formParams = {}; + if (closestAssetId != null) { + queryParams.addAll(_queryParams('', 'closestAssetId', closestAssetId)); + } + if (closestPersonId != null) { + queryParams.addAll(_queryParams('', 'closestPersonId', closestPersonId)); + } if (page != null) { queryParams.addAll(_queryParams('', 'page', page)); } @@ -110,6 +120,10 @@ class PeopleApi { /// Parameters: /// + /// * [String] closestAssetId: + /// + /// * [String] closestPersonId: + /// /// * [num] page: /// Page number for pagination /// @@ -117,8 +131,8 @@ class PeopleApi { /// Number of items per page /// /// * [bool] withHidden: - Future getAllPeople({ num? page, num? size, bool? withHidden, }) async { - final response = await getAllPeopleWithHttpInfo( page: page, size: size, withHidden: withHidden, ); + Future getAllPeople({ String? closestAssetId, String? closestPersonId, num? page, num? size, bool? withHidden, }) async { + final response = await getAllPeopleWithHttpInfo( closestAssetId: closestAssetId, closestPersonId: closestPersonId, page: page, size: size, withHidden: withHidden, ); if (response.statusCode >= HttpStatus.badRequest) { throw ApiException(response.statusCode, await _decodeBodyBytes(response)); } diff --git a/mobile/openapi/lib/api/search_api.dart b/mobile/openapi/lib/api/search_api.dart index 985029f106d27..70af3ab0a393a 100644 --- a/mobile/openapi/lib/api/search_api.dart +++ b/mobile/openapi/lib/api/search_api.dart @@ -197,7 +197,7 @@ class SearchApi { /// Parameters: /// /// * [MetadataSearchDto] metadataSearchDto (required): - Future searchMetadataWithHttpInfo(MetadataSearchDto metadataSearchDto,) async { + Future searchAssetsWithHttpInfo(MetadataSearchDto metadataSearchDto,) async { // ignore: prefer_const_declarations final path = r'/search/metadata'; @@ -225,8 +225,8 @@ class SearchApi { /// Parameters: /// /// * [MetadataSearchDto] metadataSearchDto (required): - Future searchMetadata(MetadataSearchDto metadataSearchDto,) async { - final response = await searchMetadataWithHttpInfo(metadataSearchDto,); + Future searchAssets(MetadataSearchDto metadataSearchDto,) async { + final response = await searchAssetsWithHttpInfo(metadataSearchDto,); 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 b6ddf86e70dfc..a6f8d551da81c 100644 --- a/mobile/openapi/lib/api_client.dart +++ b/mobile/openapi/lib/api_client.dart @@ -498,8 +498,6 @@ class ApiClient { return SharedLinkTypeTypeTransformer().decode(value); case 'SignUpDto': return SignUpDto.fromJson(value); - case 'SmartInfoResponseDto': - return SmartInfoResponseDto.fromJson(value); case 'SmartSearchDto': return SmartSearchDto.fromJson(value); case 'SourceType': @@ -556,8 +554,12 @@ class ApiClient { return SystemConfigSmtpTransportDto.fromJson(value); case 'SystemConfigStorageTemplateDto': return SystemConfigStorageTemplateDto.fromJson(value); + case 'SystemConfigTemplateEmailsDto': + return SystemConfigTemplateEmailsDto.fromJson(value); case 'SystemConfigTemplateStorageOptionDto': return SystemConfigTemplateStorageOptionDto.fromJson(value); + case 'SystemConfigTemplatesDto': + return SystemConfigTemplatesDto.fromJson(value); case 'SystemConfigThemeDto': return SystemConfigThemeDto.fromJson(value); case 'SystemConfigTrashDto': @@ -580,6 +582,10 @@ class ApiClient { return TagsResponse.fromJson(value); case 'TagsUpdate': return TagsUpdate.fromJson(value); + case 'TemplateDto': + return TemplateDto.fromJson(value); + case 'TemplateResponseDto': + return TemplateResponseDto.fromJson(value); case 'TestEmailResponseDto': return TestEmailResponseDto.fromJson(value); case 'TimeBucketResponseDto': diff --git a/mobile/openapi/lib/model/album_user_add_dto.dart b/mobile/openapi/lib/model/album_user_add_dto.dart index 3f72d5c893e18..e1f24377d728c 100644 --- a/mobile/openapi/lib/model/album_user_add_dto.dart +++ b/mobile/openapi/lib/model/album_user_add_dto.dart @@ -13,17 +13,11 @@ part of openapi.api; class AlbumUserAddDto { /// Returns a new [AlbumUserAddDto] instance. AlbumUserAddDto({ - this.role, + this.role = AlbumUserRole.editor, required this.userId, }); - /// - /// Please note: This property should have been non-nullable! Since the specification file - /// does not include a default value (using the "default:" property), however, the generated - /// source code must fall back to having a nullable type. - /// Consider adding a "default:" property in the specification file to hide this note. - /// - AlbumUserRole? role; + AlbumUserRole role; String userId; @@ -35,7 +29,7 @@ class AlbumUserAddDto { @override int get hashCode => // ignore: unnecessary_parenthesis - (role == null ? 0 : role!.hashCode) + + (role.hashCode) + (userId.hashCode); @override @@ -43,11 +37,7 @@ class AlbumUserAddDto { Map toJson() { final json = {}; - if (this.role != null) { json[r'role'] = this.role; - } else { - // json[r'role'] = null; - } json[r'userId'] = this.userId; return json; } @@ -61,7 +51,7 @@ class AlbumUserAddDto { final json = value.cast(); return AlbumUserAddDto( - role: AlbumUserRole.fromJson(json[r'role']), + role: AlbumUserRole.fromJson(json[r'role']) ?? AlbumUserRole.editor, userId: mapValueOfType(json, r'userId')!, ); } diff --git a/mobile/openapi/lib/model/asset_response_dto.dart b/mobile/openapi/lib/model/asset_response_dto.dart index c11dedcbfd230..5f01f84419e4e 100644 --- a/mobile/openapi/lib/model/asset_response_dto.dart +++ b/mobile/openapi/lib/model/asset_response_dto.dart @@ -37,7 +37,6 @@ class AssetResponseDto { required this.ownerId, this.people = const [], this.resized, - this.smartInfo, this.stack, this.tags = const [], required this.thumbhash, @@ -121,14 +120,6 @@ class AssetResponseDto { /// bool? resized; - /// - /// 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. - /// - SmartInfoResponseDto? smartInfo; - AssetStackResponseDto? stack; List tags; @@ -167,7 +158,6 @@ class AssetResponseDto { other.ownerId == ownerId && _deepEquality.equals(other.people, people) && other.resized == resized && - other.smartInfo == smartInfo && other.stack == stack && _deepEquality.equals(other.tags, tags) && other.thumbhash == thumbhash && @@ -202,7 +192,6 @@ class AssetResponseDto { (ownerId.hashCode) + (people.hashCode) + (resized == null ? 0 : resized!.hashCode) + - (smartInfo == null ? 0 : smartInfo!.hashCode) + (stack == null ? 0 : stack!.hashCode) + (tags.hashCode) + (thumbhash == null ? 0 : thumbhash!.hashCode) + @@ -211,7 +200,7 @@ class AssetResponseDto { (updatedAt.hashCode); @override - String toString() => 'AssetResponseDto[checksum=$checksum, deviceAssetId=$deviceAssetId, deviceId=$deviceId, duplicateId=$duplicateId, duration=$duration, exifInfo=$exifInfo, fileCreatedAt=$fileCreatedAt, fileModifiedAt=$fileModifiedAt, hasMetadata=$hasMetadata, id=$id, isArchived=$isArchived, isFavorite=$isFavorite, isOffline=$isOffline, isTrashed=$isTrashed, libraryId=$libraryId, livePhotoVideoId=$livePhotoVideoId, localDateTime=$localDateTime, originalFileName=$originalFileName, originalMimeType=$originalMimeType, originalPath=$originalPath, owner=$owner, ownerId=$ownerId, people=$people, resized=$resized, smartInfo=$smartInfo, stack=$stack, tags=$tags, thumbhash=$thumbhash, type=$type, unassignedFaces=$unassignedFaces, updatedAt=$updatedAt]'; + String toString() => 'AssetResponseDto[checksum=$checksum, deviceAssetId=$deviceAssetId, deviceId=$deviceId, duplicateId=$duplicateId, duration=$duration, exifInfo=$exifInfo, fileCreatedAt=$fileCreatedAt, fileModifiedAt=$fileModifiedAt, hasMetadata=$hasMetadata, id=$id, isArchived=$isArchived, isFavorite=$isFavorite, isOffline=$isOffline, isTrashed=$isTrashed, libraryId=$libraryId, livePhotoVideoId=$livePhotoVideoId, localDateTime=$localDateTime, originalFileName=$originalFileName, originalMimeType=$originalMimeType, originalPath=$originalPath, owner=$owner, ownerId=$ownerId, people=$people, resized=$resized, stack=$stack, tags=$tags, thumbhash=$thumbhash, type=$type, unassignedFaces=$unassignedFaces, updatedAt=$updatedAt]'; Map toJson() { final json = {}; @@ -267,11 +256,6 @@ class AssetResponseDto { } else { // json[r'resized'] = null; } - if (this.smartInfo != null) { - json[r'smartInfo'] = this.smartInfo; - } else { - // json[r'smartInfo'] = null; - } if (this.stack != null) { json[r'stack'] = this.stack; } else { @@ -322,7 +306,6 @@ class AssetResponseDto { ownerId: mapValueOfType(json, r'ownerId')!, people: PersonWithFacesResponseDto.listFromJson(json[r'people']), resized: mapValueOfType(json, r'resized'), - smartInfo: SmartInfoResponseDto.fromJson(json[r'smartInfo']), stack: AssetStackResponseDto.fromJson(json[r'stack']), tags: TagResponseDto.listFromJson(json[r'tags']), thumbhash: mapValueOfType(json, r'thumbhash'), diff --git a/mobile/openapi/lib/model/create_library_dto.dart b/mobile/openapi/lib/model/create_library_dto.dart index bffa5f427950d..2b8085be6f3a6 100644 --- a/mobile/openapi/lib/model/create_library_dto.dart +++ b/mobile/openapi/lib/model/create_library_dto.dart @@ -13,15 +13,15 @@ part of openapi.api; class CreateLibraryDto { /// Returns a new [CreateLibraryDto] instance. CreateLibraryDto({ - this.exclusionPatterns = const [], - this.importPaths = const [], + this.exclusionPatterns = const {}, + this.importPaths = const {}, this.name, required this.ownerId, }); - List exclusionPatterns; + Set exclusionPatterns; - List importPaths; + Set importPaths; /// /// Please note: This property should have been non-nullable! Since the specification file @@ -53,8 +53,8 @@ class CreateLibraryDto { Map toJson() { final json = {}; - json[r'exclusionPatterns'] = this.exclusionPatterns; - json[r'importPaths'] = this.importPaths; + json[r'exclusionPatterns'] = this.exclusionPatterns.toList(growable: false); + json[r'importPaths'] = this.importPaths.toList(growable: false); if (this.name != null) { json[r'name'] = this.name; } else { @@ -74,11 +74,11 @@ class CreateLibraryDto { return CreateLibraryDto( exclusionPatterns: json[r'exclusionPatterns'] is Iterable - ? (json[r'exclusionPatterns'] as Iterable).cast().toList(growable: false) - : const [], + ? (json[r'exclusionPatterns'] as Iterable).cast().toSet() + : const {}, importPaths: json[r'importPaths'] is Iterable - ? (json[r'importPaths'] as Iterable).cast().toList(growable: false) - : const [], + ? (json[r'importPaths'] as Iterable).cast().toSet() + : const {}, name: mapValueOfType(json, r'name'), ownerId: mapValueOfType(json, r'ownerId')!, ); diff --git a/mobile/openapi/lib/model/server_config_dto.dart b/mobile/openapi/lib/model/server_config_dto.dart index bd5c2405e29d3..01c82af4d9880 100644 --- a/mobile/openapi/lib/model/server_config_dto.dart +++ b/mobile/openapi/lib/model/server_config_dto.dart @@ -20,6 +20,7 @@ class ServerConfigDto { required this.mapDarkStyleUrl, required this.mapLightStyleUrl, required this.oauthButtonText, + required this.publicUsers, required this.trashDays, required this.userDeleteDelay, }); @@ -38,6 +39,8 @@ class ServerConfigDto { String oauthButtonText; + bool publicUsers; + int trashDays; int userDeleteDelay; @@ -51,6 +54,7 @@ class ServerConfigDto { other.mapDarkStyleUrl == mapDarkStyleUrl && other.mapLightStyleUrl == mapLightStyleUrl && other.oauthButtonText == oauthButtonText && + other.publicUsers == publicUsers && other.trashDays == trashDays && other.userDeleteDelay == userDeleteDelay; @@ -64,11 +68,12 @@ class ServerConfigDto { (mapDarkStyleUrl.hashCode) + (mapLightStyleUrl.hashCode) + (oauthButtonText.hashCode) + + (publicUsers.hashCode) + (trashDays.hashCode) + (userDeleteDelay.hashCode); @override - String toString() => 'ServerConfigDto[externalDomain=$externalDomain, isInitialized=$isInitialized, isOnboarded=$isOnboarded, loginPageMessage=$loginPageMessage, mapDarkStyleUrl=$mapDarkStyleUrl, mapLightStyleUrl=$mapLightStyleUrl, oauthButtonText=$oauthButtonText, trashDays=$trashDays, userDeleteDelay=$userDeleteDelay]'; + String toString() => 'ServerConfigDto[externalDomain=$externalDomain, isInitialized=$isInitialized, isOnboarded=$isOnboarded, loginPageMessage=$loginPageMessage, mapDarkStyleUrl=$mapDarkStyleUrl, mapLightStyleUrl=$mapLightStyleUrl, oauthButtonText=$oauthButtonText, publicUsers=$publicUsers, trashDays=$trashDays, userDeleteDelay=$userDeleteDelay]'; Map toJson() { final json = {}; @@ -79,6 +84,7 @@ class ServerConfigDto { json[r'mapDarkStyleUrl'] = this.mapDarkStyleUrl; json[r'mapLightStyleUrl'] = this.mapLightStyleUrl; json[r'oauthButtonText'] = this.oauthButtonText; + json[r'publicUsers'] = this.publicUsers; json[r'trashDays'] = this.trashDays; json[r'userDeleteDelay'] = this.userDeleteDelay; return json; @@ -100,6 +106,7 @@ class ServerConfigDto { mapDarkStyleUrl: mapValueOfType(json, r'mapDarkStyleUrl')!, mapLightStyleUrl: mapValueOfType(json, r'mapLightStyleUrl')!, oauthButtonText: mapValueOfType(json, r'oauthButtonText')!, + publicUsers: mapValueOfType(json, r'publicUsers')!, trashDays: mapValueOfType(json, r'trashDays')!, userDeleteDelay: mapValueOfType(json, r'userDeleteDelay')!, ); @@ -156,6 +163,7 @@ class ServerConfigDto { 'mapDarkStyleUrl', 'mapLightStyleUrl', 'oauthButtonText', + 'publicUsers', 'trashDays', 'userDeleteDelay', }; diff --git a/mobile/openapi/lib/model/server_stats_response_dto.dart b/mobile/openapi/lib/model/server_stats_response_dto.dart index 654a34ee6b0e7..531fa8f03e16a 100644 --- a/mobile/openapi/lib/model/server_stats_response_dto.dart +++ b/mobile/openapi/lib/model/server_stats_response_dto.dart @@ -16,6 +16,8 @@ class ServerStatsResponseDto { this.photos = 0, this.usage = 0, this.usageByUser = const [], + this.usagePhotos = 0, + this.usageVideos = 0, this.videos = 0, }); @@ -25,6 +27,10 @@ class ServerStatsResponseDto { List usageByUser; + int usagePhotos; + + int usageVideos; + int videos; @override @@ -32,6 +38,8 @@ class ServerStatsResponseDto { other.photos == photos && other.usage == usage && _deepEquality.equals(other.usageByUser, usageByUser) && + other.usagePhotos == usagePhotos && + other.usageVideos == usageVideos && other.videos == videos; @override @@ -40,16 +48,20 @@ class ServerStatsResponseDto { (photos.hashCode) + (usage.hashCode) + (usageByUser.hashCode) + + (usagePhotos.hashCode) + + (usageVideos.hashCode) + (videos.hashCode); @override - String toString() => 'ServerStatsResponseDto[photos=$photos, usage=$usage, usageByUser=$usageByUser, videos=$videos]'; + String toString() => 'ServerStatsResponseDto[photos=$photos, usage=$usage, usageByUser=$usageByUser, usagePhotos=$usagePhotos, usageVideos=$usageVideos, videos=$videos]'; Map toJson() { final json = {}; json[r'photos'] = this.photos; json[r'usage'] = this.usage; json[r'usageByUser'] = this.usageByUser; + json[r'usagePhotos'] = this.usagePhotos; + json[r'usageVideos'] = this.usageVideos; json[r'videos'] = this.videos; return json; } @@ -66,6 +78,8 @@ class ServerStatsResponseDto { photos: mapValueOfType(json, r'photos')!, usage: mapValueOfType(json, r'usage')!, usageByUser: UsageByUserDto.listFromJson(json[r'usageByUser']), + usagePhotos: mapValueOfType(json, r'usagePhotos')!, + usageVideos: mapValueOfType(json, r'usageVideos')!, videos: mapValueOfType(json, r'videos')!, ); } @@ -117,6 +131,8 @@ class ServerStatsResponseDto { 'photos', 'usage', 'usageByUser', + 'usagePhotos', + 'usageVideos', 'videos', }; } diff --git a/mobile/openapi/lib/model/smart_info_response_dto.dart b/mobile/openapi/lib/model/smart_info_response_dto.dart deleted file mode 100644 index 4631eccf2cb1c..0000000000000 --- a/mobile/openapi/lib/model/smart_info_response_dto.dart +++ /dev/null @@ -1,117 +0,0 @@ -// -// AUTO-GENERATED FILE, DO NOT MODIFY! -// -// @dart=2.18 - -// ignore_for_file: unused_element, unused_import -// ignore_for_file: always_put_required_named_parameters_first -// ignore_for_file: constant_identifier_names -// ignore_for_file: lines_longer_than_80_chars - -part of openapi.api; - -class SmartInfoResponseDto { - /// Returns a new [SmartInfoResponseDto] instance. - SmartInfoResponseDto({ - this.objects = const [], - this.tags = const [], - }); - - List? objects; - - List? tags; - - @override - bool operator ==(Object other) => identical(this, other) || other is SmartInfoResponseDto && - _deepEquality.equals(other.objects, objects) && - _deepEquality.equals(other.tags, tags); - - @override - int get hashCode => - // ignore: unnecessary_parenthesis - (objects == null ? 0 : objects!.hashCode) + - (tags == null ? 0 : tags!.hashCode); - - @override - String toString() => 'SmartInfoResponseDto[objects=$objects, tags=$tags]'; - - Map toJson() { - final json = {}; - if (this.objects != null) { - json[r'objects'] = this.objects; - } else { - // json[r'objects'] = null; - } - if (this.tags != null) { - json[r'tags'] = this.tags; - } else { - // json[r'tags'] = null; - } - return json; - } - - /// Returns a new [SmartInfoResponseDto] instance and imports its values from - /// [value] if it's a [Map], null otherwise. - // ignore: prefer_constructors_over_static_methods - static SmartInfoResponseDto? fromJson(dynamic value) { - upgradeDto(value, "SmartInfoResponseDto"); - if (value is Map) { - final json = value.cast(); - - return SmartInfoResponseDto( - objects: json[r'objects'] is Iterable - ? (json[r'objects'] as Iterable).cast().toList(growable: false) - : const [], - tags: json[r'tags'] is Iterable - ? (json[r'tags'] as Iterable).cast().toList(growable: false) - : const [], - ); - } - 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 = SmartInfoResponseDto.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 = SmartInfoResponseDto.fromJson(entry.value); - if (value != null) { - map[entry.key] = value; - } - } - } - return map; - } - - // maps a json object with a list of SmartInfoResponseDto-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] = SmartInfoResponseDto.listFromJson(entry.value, growable: growable,); - } - } - return map; - } - - /// The list of required keys that must be present in a JSON. - static const requiredKeys = { - }; -} - diff --git a/mobile/openapi/lib/model/system_config_dto.dart b/mobile/openapi/lib/model/system_config_dto.dart index 4215953906601..59d5f09fc9467 100644 --- a/mobile/openapi/lib/model/system_config_dto.dart +++ b/mobile/openapi/lib/model/system_config_dto.dart @@ -29,6 +29,7 @@ class SystemConfigDto { required this.reverseGeocoding, required this.server, required this.storageTemplate, + required this.templates, required this.theme, required this.trash, required this.user, @@ -66,6 +67,8 @@ class SystemConfigDto { SystemConfigStorageTemplateDto storageTemplate; + SystemConfigTemplatesDto templates; + SystemConfigThemeDto theme; SystemConfigTrashDto trash; @@ -90,6 +93,7 @@ class SystemConfigDto { other.reverseGeocoding == reverseGeocoding && other.server == server && other.storageTemplate == storageTemplate && + other.templates == templates && other.theme == theme && other.trash == trash && other.user == user; @@ -113,12 +117,13 @@ class SystemConfigDto { (reverseGeocoding.hashCode) + (server.hashCode) + (storageTemplate.hashCode) + + (templates.hashCode) + (theme.hashCode) + (trash.hashCode) + (user.hashCode); @override - String toString() => 'SystemConfigDto[backup=$backup, ffmpeg=$ffmpeg, image=$image, job=$job, library_=$library_, logging=$logging, machineLearning=$machineLearning, map=$map, metadata=$metadata, newVersionCheck=$newVersionCheck, notifications=$notifications, oauth=$oauth, passwordLogin=$passwordLogin, reverseGeocoding=$reverseGeocoding, server=$server, storageTemplate=$storageTemplate, theme=$theme, trash=$trash, user=$user]'; + String toString() => 'SystemConfigDto[backup=$backup, ffmpeg=$ffmpeg, image=$image, job=$job, library_=$library_, logging=$logging, machineLearning=$machineLearning, map=$map, metadata=$metadata, newVersionCheck=$newVersionCheck, notifications=$notifications, oauth=$oauth, passwordLogin=$passwordLogin, reverseGeocoding=$reverseGeocoding, server=$server, storageTemplate=$storageTemplate, templates=$templates, theme=$theme, trash=$trash, user=$user]'; Map toJson() { final json = {}; @@ -138,6 +143,7 @@ class SystemConfigDto { json[r'reverseGeocoding'] = this.reverseGeocoding; json[r'server'] = this.server; json[r'storageTemplate'] = this.storageTemplate; + json[r'templates'] = this.templates; json[r'theme'] = this.theme; json[r'trash'] = this.trash; json[r'user'] = this.user; @@ -169,6 +175,7 @@ class SystemConfigDto { reverseGeocoding: SystemConfigReverseGeocodingDto.fromJson(json[r'reverseGeocoding'])!, server: SystemConfigServerDto.fromJson(json[r'server'])!, storageTemplate: SystemConfigStorageTemplateDto.fromJson(json[r'storageTemplate'])!, + templates: SystemConfigTemplatesDto.fromJson(json[r'templates'])!, theme: SystemConfigThemeDto.fromJson(json[r'theme'])!, trash: SystemConfigTrashDto.fromJson(json[r'trash'])!, user: SystemConfigUserDto.fromJson(json[r'user'])!, @@ -235,6 +242,7 @@ class SystemConfigDto { 'reverseGeocoding', 'server', 'storageTemplate', + 'templates', 'theme', 'trash', 'user', diff --git a/mobile/openapi/lib/model/system_config_f_fmpeg_dto.dart b/mobile/openapi/lib/model/system_config_f_fmpeg_dto.dart index 73f7d35aecc30..0acfc9e8fbf9d 100644 --- a/mobile/openapi/lib/model/system_config_f_fmpeg_dto.dart +++ b/mobile/openapi/lib/model/system_config_f_fmpeg_dto.dart @@ -23,7 +23,6 @@ class SystemConfigFFmpegDto { required this.crf, required this.gopSize, required this.maxBitrate, - required this.npl, required this.preferredHwDevice, required this.preset, required this.refs, @@ -62,9 +61,6 @@ class SystemConfigFFmpegDto { String maxBitrate; - /// Minimum value: 0 - int npl; - String preferredHwDevice; String preset; @@ -102,7 +98,6 @@ class SystemConfigFFmpegDto { other.crf == crf && other.gopSize == gopSize && other.maxBitrate == maxBitrate && - other.npl == npl && other.preferredHwDevice == preferredHwDevice && other.preset == preset && other.refs == refs && @@ -128,7 +123,6 @@ class SystemConfigFFmpegDto { (crf.hashCode) + (gopSize.hashCode) + (maxBitrate.hashCode) + - (npl.hashCode) + (preferredHwDevice.hashCode) + (preset.hashCode) + (refs.hashCode) + @@ -142,7 +136,7 @@ class SystemConfigFFmpegDto { (twoPass.hashCode); @override - String toString() => 'SystemConfigFFmpegDto[accel=$accel, accelDecode=$accelDecode, acceptedAudioCodecs=$acceptedAudioCodecs, acceptedContainers=$acceptedContainers, acceptedVideoCodecs=$acceptedVideoCodecs, bframes=$bframes, cqMode=$cqMode, crf=$crf, gopSize=$gopSize, maxBitrate=$maxBitrate, npl=$npl, preferredHwDevice=$preferredHwDevice, preset=$preset, refs=$refs, targetAudioCodec=$targetAudioCodec, targetResolution=$targetResolution, targetVideoCodec=$targetVideoCodec, temporalAQ=$temporalAQ, threads=$threads, tonemap=$tonemap, transcode=$transcode, twoPass=$twoPass]'; + String toString() => 'SystemConfigFFmpegDto[accel=$accel, accelDecode=$accelDecode, acceptedAudioCodecs=$acceptedAudioCodecs, acceptedContainers=$acceptedContainers, acceptedVideoCodecs=$acceptedVideoCodecs, bframes=$bframes, cqMode=$cqMode, crf=$crf, gopSize=$gopSize, maxBitrate=$maxBitrate, preferredHwDevice=$preferredHwDevice, preset=$preset, refs=$refs, targetAudioCodec=$targetAudioCodec, targetResolution=$targetResolution, targetVideoCodec=$targetVideoCodec, temporalAQ=$temporalAQ, threads=$threads, tonemap=$tonemap, transcode=$transcode, twoPass=$twoPass]'; Map toJson() { final json = {}; @@ -156,7 +150,6 @@ class SystemConfigFFmpegDto { json[r'crf'] = this.crf; json[r'gopSize'] = this.gopSize; json[r'maxBitrate'] = this.maxBitrate; - json[r'npl'] = this.npl; json[r'preferredHwDevice'] = this.preferredHwDevice; json[r'preset'] = this.preset; json[r'refs'] = this.refs; @@ -190,7 +183,6 @@ class SystemConfigFFmpegDto { crf: mapValueOfType(json, r'crf')!, gopSize: mapValueOfType(json, r'gopSize')!, maxBitrate: mapValueOfType(json, r'maxBitrate')!, - npl: mapValueOfType(json, r'npl')!, preferredHwDevice: mapValueOfType(json, r'preferredHwDevice')!, preset: mapValueOfType(json, r'preset')!, refs: mapValueOfType(json, r'refs')!, @@ -259,7 +251,6 @@ class SystemConfigFFmpegDto { 'crf', 'gopSize', 'maxBitrate', - 'npl', 'preferredHwDevice', 'preset', 'refs', 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 d665f0bfa56a7..a4a9ca7d82bdf 100644 --- a/mobile/openapi/lib/model/system_config_machine_learning_dto.dart +++ b/mobile/openapi/lib/model/system_config_machine_learning_dto.dart @@ -17,7 +17,8 @@ class SystemConfigMachineLearningDto { required this.duplicateDetection, required this.enabled, required this.facialRecognition, - required this.url, + this.url, + this.urls = const [], }); CLIPConfig clip; @@ -28,7 +29,16 @@ class SystemConfigMachineLearningDto { FacialRecognitionConfig facialRecognition; - String url; + /// 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 && @@ -36,7 +46,8 @@ class SystemConfigMachineLearningDto { other.duplicateDetection == duplicateDetection && other.enabled == enabled && other.facialRecognition == facialRecognition && - other.url == url; + other.url == url && + _deepEquality.equals(other.urls, urls); @override int get hashCode => @@ -45,10 +56,11 @@ class SystemConfigMachineLearningDto { (duplicateDetection.hashCode) + (enabled.hashCode) + (facialRecognition.hashCode) + - (url.hashCode); + (url == null ? 0 : url!.hashCode) + + (urls.hashCode); @override - String toString() => 'SystemConfigMachineLearningDto[clip=$clip, duplicateDetection=$duplicateDetection, enabled=$enabled, facialRecognition=$facialRecognition, url=$url]'; + String toString() => 'SystemConfigMachineLearningDto[clip=$clip, duplicateDetection=$duplicateDetection, enabled=$enabled, facialRecognition=$facialRecognition, url=$url, urls=$urls]'; Map toJson() { final json = {}; @@ -56,7 +68,12 @@ class SystemConfigMachineLearningDto { 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; } @@ -73,7 +90,10 @@ class SystemConfigMachineLearningDto { duplicateDetection: DuplicateDetectionConfig.fromJson(json[r'duplicateDetection'])!, enabled: mapValueOfType(json, r'enabled')!, facialRecognition: FacialRecognitionConfig.fromJson(json[r'facialRecognition'])!, - url: mapValueOfType(json, r'url')!, + url: mapValueOfType(json, r'url'), + urls: json[r'urls'] is Iterable + ? (json[r'urls'] as Iterable).cast().toList(growable: false) + : const [], ); } return null; @@ -125,7 +145,7 @@ class SystemConfigMachineLearningDto { 'duplicateDetection', 'enabled', 'facialRecognition', - 'url', + 'urls', }; } diff --git a/mobile/openapi/lib/model/system_config_server_dto.dart b/mobile/openapi/lib/model/system_config_server_dto.dart index b1b92c9515d5b..8099292dd052b 100644 --- a/mobile/openapi/lib/model/system_config_server_dto.dart +++ b/mobile/openapi/lib/model/system_config_server_dto.dart @@ -15,30 +15,36 @@ class SystemConfigServerDto { SystemConfigServerDto({ required this.externalDomain, required this.loginPageMessage, + required this.publicUsers, }); String externalDomain; String loginPageMessage; + bool publicUsers; + @override bool operator ==(Object other) => identical(this, other) || other is SystemConfigServerDto && other.externalDomain == externalDomain && - other.loginPageMessage == loginPageMessage; + other.loginPageMessage == loginPageMessage && + other.publicUsers == publicUsers; @override int get hashCode => // ignore: unnecessary_parenthesis (externalDomain.hashCode) + - (loginPageMessage.hashCode); + (loginPageMessage.hashCode) + + (publicUsers.hashCode); @override - String toString() => 'SystemConfigServerDto[externalDomain=$externalDomain, loginPageMessage=$loginPageMessage]'; + String toString() => 'SystemConfigServerDto[externalDomain=$externalDomain, loginPageMessage=$loginPageMessage, publicUsers=$publicUsers]'; Map toJson() { final json = {}; json[r'externalDomain'] = this.externalDomain; json[r'loginPageMessage'] = this.loginPageMessage; + json[r'publicUsers'] = this.publicUsers; return json; } @@ -53,6 +59,7 @@ class SystemConfigServerDto { return SystemConfigServerDto( externalDomain: mapValueOfType(json, r'externalDomain')!, loginPageMessage: mapValueOfType(json, r'loginPageMessage')!, + publicUsers: mapValueOfType(json, r'publicUsers')!, ); } return null; @@ -102,6 +109,7 @@ class SystemConfigServerDto { static const requiredKeys = { 'externalDomain', 'loginPageMessage', + 'publicUsers', }; } diff --git a/mobile/openapi/lib/model/system_config_template_emails_dto.dart b/mobile/openapi/lib/model/system_config_template_emails_dto.dart new file mode 100644 index 0000000000000..9db85509f58eb --- /dev/null +++ b/mobile/openapi/lib/model/system_config_template_emails_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 SystemConfigTemplateEmailsDto { + /// Returns a new [SystemConfigTemplateEmailsDto] instance. + SystemConfigTemplateEmailsDto({ + required this.albumInviteTemplate, + required this.albumUpdateTemplate, + required this.welcomeTemplate, + }); + + String albumInviteTemplate; + + String albumUpdateTemplate; + + String welcomeTemplate; + + @override + bool operator ==(Object other) => identical(this, other) || other is SystemConfigTemplateEmailsDto && + other.albumInviteTemplate == albumInviteTemplate && + other.albumUpdateTemplate == albumUpdateTemplate && + other.welcomeTemplate == welcomeTemplate; + + @override + int get hashCode => + // ignore: unnecessary_parenthesis + (albumInviteTemplate.hashCode) + + (albumUpdateTemplate.hashCode) + + (welcomeTemplate.hashCode); + + @override + String toString() => 'SystemConfigTemplateEmailsDto[albumInviteTemplate=$albumInviteTemplate, albumUpdateTemplate=$albumUpdateTemplate, welcomeTemplate=$welcomeTemplate]'; + + Map toJson() { + final json = {}; + json[r'albumInviteTemplate'] = this.albumInviteTemplate; + json[r'albumUpdateTemplate'] = this.albumUpdateTemplate; + json[r'welcomeTemplate'] = this.welcomeTemplate; + return json; + } + + /// Returns a new [SystemConfigTemplateEmailsDto] instance and imports its values from + /// [value] if it's a [Map], null otherwise. + // ignore: prefer_constructors_over_static_methods + static SystemConfigTemplateEmailsDto? fromJson(dynamic value) { + upgradeDto(value, "SystemConfigTemplateEmailsDto"); + if (value is Map) { + final json = value.cast(); + + return SystemConfigTemplateEmailsDto( + albumInviteTemplate: mapValueOfType(json, r'albumInviteTemplate')!, + albumUpdateTemplate: mapValueOfType(json, r'albumUpdateTemplate')!, + welcomeTemplate: mapValueOfType(json, r'welcomeTemplate')!, + ); + } + 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 = SystemConfigTemplateEmailsDto.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 = SystemConfigTemplateEmailsDto.fromJson(entry.value); + if (value != null) { + map[entry.key] = value; + } + } + } + return map; + } + + // maps a json object with a list of SystemConfigTemplateEmailsDto-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] = SystemConfigTemplateEmailsDto.listFromJson(entry.value, growable: growable,); + } + } + return map; + } + + /// The list of required keys that must be present in a JSON. + static const requiredKeys = { + 'albumInviteTemplate', + 'albumUpdateTemplate', + 'welcomeTemplate', + }; +} + diff --git a/mobile/openapi/lib/model/system_config_templates_dto.dart b/mobile/openapi/lib/model/system_config_templates_dto.dart new file mode 100644 index 0000000000000..a5e883497881f --- /dev/null +++ b/mobile/openapi/lib/model/system_config_templates_dto.dart @@ -0,0 +1,99 @@ +// +// 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 SystemConfigTemplatesDto { + /// Returns a new [SystemConfigTemplatesDto] instance. + SystemConfigTemplatesDto({ + required this.email, + }); + + SystemConfigTemplateEmailsDto email; + + @override + bool operator ==(Object other) => identical(this, other) || other is SystemConfigTemplatesDto && + other.email == email; + + @override + int get hashCode => + // ignore: unnecessary_parenthesis + (email.hashCode); + + @override + String toString() => 'SystemConfigTemplatesDto[email=$email]'; + + Map toJson() { + final json = {}; + json[r'email'] = this.email; + return json; + } + + /// Returns a new [SystemConfigTemplatesDto] instance and imports its values from + /// [value] if it's a [Map], null otherwise. + // ignore: prefer_constructors_over_static_methods + static SystemConfigTemplatesDto? fromJson(dynamic value) { + upgradeDto(value, "SystemConfigTemplatesDto"); + if (value is Map) { + final json = value.cast(); + + return SystemConfigTemplatesDto( + email: SystemConfigTemplateEmailsDto.fromJson(json[r'email'])!, + ); + } + 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 = SystemConfigTemplatesDto.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 = SystemConfigTemplatesDto.fromJson(entry.value); + if (value != null) { + map[entry.key] = value; + } + } + } + return map; + } + + // maps a json object with a list of SystemConfigTemplatesDto-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] = SystemConfigTemplatesDto.listFromJson(entry.value, growable: growable,); + } + } + return map; + } + + /// The list of required keys that must be present in a JSON. + static const requiredKeys = { + 'email', + }; +} + diff --git a/mobile/openapi/lib/model/template_dto.dart b/mobile/openapi/lib/model/template_dto.dart new file mode 100644 index 0000000000000..f818e0508acab --- /dev/null +++ b/mobile/openapi/lib/model/template_dto.dart @@ -0,0 +1,99 @@ +// +// 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 TemplateDto { + /// Returns a new [TemplateDto] instance. + TemplateDto({ + required this.template, + }); + + String template; + + @override + bool operator ==(Object other) => identical(this, other) || other is TemplateDto && + other.template == template; + + @override + int get hashCode => + // ignore: unnecessary_parenthesis + (template.hashCode); + + @override + String toString() => 'TemplateDto[template=$template]'; + + Map toJson() { + final json = {}; + json[r'template'] = this.template; + return json; + } + + /// Returns a new [TemplateDto] instance and imports its values from + /// [value] if it's a [Map], null otherwise. + // ignore: prefer_constructors_over_static_methods + static TemplateDto? fromJson(dynamic value) { + upgradeDto(value, "TemplateDto"); + if (value is Map) { + final json = value.cast(); + + return TemplateDto( + template: mapValueOfType(json, r'template')!, + ); + } + 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 = TemplateDto.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 = TemplateDto.fromJson(entry.value); + if (value != null) { + map[entry.key] = value; + } + } + } + return map; + } + + // maps a json object with a list of TemplateDto-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] = TemplateDto.listFromJson(entry.value, growable: growable,); + } + } + return map; + } + + /// The list of required keys that must be present in a JSON. + static const requiredKeys = { + 'template', + }; +} + diff --git a/mobile/openapi/lib/model/template_response_dto.dart b/mobile/openapi/lib/model/template_response_dto.dart new file mode 100644 index 0000000000000..3c3224a54beb0 --- /dev/null +++ b/mobile/openapi/lib/model/template_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 TemplateResponseDto { + /// Returns a new [TemplateResponseDto] instance. + TemplateResponseDto({ + required this.html, + required this.name, + }); + + String html; + + String name; + + @override + bool operator ==(Object other) => identical(this, other) || other is TemplateResponseDto && + other.html == html && + other.name == name; + + @override + int get hashCode => + // ignore: unnecessary_parenthesis + (html.hashCode) + + (name.hashCode); + + @override + String toString() => 'TemplateResponseDto[html=$html, name=$name]'; + + Map toJson() { + final json = {}; + json[r'html'] = this.html; + json[r'name'] = this.name; + return json; + } + + /// Returns a new [TemplateResponseDto] instance and imports its values from + /// [value] if it's a [Map], null otherwise. + // ignore: prefer_constructors_over_static_methods + static TemplateResponseDto? fromJson(dynamic value) { + upgradeDto(value, "TemplateResponseDto"); + if (value is Map) { + final json = value.cast(); + + return TemplateResponseDto( + html: mapValueOfType(json, r'html')!, + name: mapValueOfType(json, r'name')!, + ); + } + 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 = TemplateResponseDto.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 = TemplateResponseDto.fromJson(entry.value); + if (value != null) { + map[entry.key] = value; + } + } + } + return map; + } + + // maps a json object with a list of TemplateResponseDto-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] = TemplateResponseDto.listFromJson(entry.value, growable: growable,); + } + } + return map; + } + + /// The list of required keys that must be present in a JSON. + static const requiredKeys = { + 'html', + 'name', + }; +} + diff --git a/mobile/openapi/lib/model/update_library_dto.dart b/mobile/openapi/lib/model/update_library_dto.dart index b85df40172e69..6a4f36906f74a 100644 --- a/mobile/openapi/lib/model/update_library_dto.dart +++ b/mobile/openapi/lib/model/update_library_dto.dart @@ -13,14 +13,14 @@ part of openapi.api; class UpdateLibraryDto { /// Returns a new [UpdateLibraryDto] instance. UpdateLibraryDto({ - this.exclusionPatterns = const [], - this.importPaths = const [], + this.exclusionPatterns = const {}, + this.importPaths = const {}, this.name, }); - List exclusionPatterns; + Set exclusionPatterns; - List importPaths; + Set importPaths; /// /// Please note: This property should have been non-nullable! Since the specification file @@ -48,8 +48,8 @@ class UpdateLibraryDto { Map toJson() { final json = {}; - json[r'exclusionPatterns'] = this.exclusionPatterns; - json[r'importPaths'] = this.importPaths; + json[r'exclusionPatterns'] = this.exclusionPatterns.toList(growable: false); + json[r'importPaths'] = this.importPaths.toList(growable: false); if (this.name != null) { json[r'name'] = this.name; } else { @@ -68,11 +68,11 @@ class UpdateLibraryDto { return UpdateLibraryDto( exclusionPatterns: json[r'exclusionPatterns'] is Iterable - ? (json[r'exclusionPatterns'] as Iterable).cast().toList(growable: false) - : const [], + ? (json[r'exclusionPatterns'] as Iterable).cast().toSet() + : const {}, importPaths: json[r'importPaths'] is Iterable - ? (json[r'importPaths'] as Iterable).cast().toList(growable: false) - : const [], + ? (json[r'importPaths'] as Iterable).cast().toSet() + : const {}, name: mapValueOfType(json, r'name'), ); } diff --git a/mobile/openapi/lib/model/usage_by_user_dto.dart b/mobile/openapi/lib/model/usage_by_user_dto.dart index e6f9216d74572..80235915fea8e 100644 --- a/mobile/openapi/lib/model/usage_by_user_dto.dart +++ b/mobile/openapi/lib/model/usage_by_user_dto.dart @@ -16,6 +16,8 @@ class UsageByUserDto { required this.photos, required this.quotaSizeInBytes, required this.usage, + required this.usagePhotos, + required this.usageVideos, required this.userId, required this.userName, required this.videos, @@ -27,6 +29,10 @@ class UsageByUserDto { int usage; + int usagePhotos; + + int usageVideos; + String userId; String userName; @@ -38,6 +44,8 @@ class UsageByUserDto { other.photos == photos && other.quotaSizeInBytes == quotaSizeInBytes && other.usage == usage && + other.usagePhotos == usagePhotos && + other.usageVideos == usageVideos && other.userId == userId && other.userName == userName && other.videos == videos; @@ -48,12 +56,14 @@ class UsageByUserDto { (photos.hashCode) + (quotaSizeInBytes == null ? 0 : quotaSizeInBytes!.hashCode) + (usage.hashCode) + + (usagePhotos.hashCode) + + (usageVideos.hashCode) + (userId.hashCode) + (userName.hashCode) + (videos.hashCode); @override - String toString() => 'UsageByUserDto[photos=$photos, quotaSizeInBytes=$quotaSizeInBytes, usage=$usage, userId=$userId, userName=$userName, videos=$videos]'; + String toString() => 'UsageByUserDto[photos=$photos, quotaSizeInBytes=$quotaSizeInBytes, usage=$usage, usagePhotos=$usagePhotos, usageVideos=$usageVideos, userId=$userId, userName=$userName, videos=$videos]'; Map toJson() { final json = {}; @@ -64,6 +74,8 @@ class UsageByUserDto { // json[r'quotaSizeInBytes'] = null; } json[r'usage'] = this.usage; + json[r'usagePhotos'] = this.usagePhotos; + json[r'usageVideos'] = this.usageVideos; json[r'userId'] = this.userId; json[r'userName'] = this.userName; json[r'videos'] = this.videos; @@ -82,6 +94,8 @@ class UsageByUserDto { photos: mapValueOfType(json, r'photos')!, quotaSizeInBytes: mapValueOfType(json, r'quotaSizeInBytes'), usage: mapValueOfType(json, r'usage')!, + usagePhotos: mapValueOfType(json, r'usagePhotos')!, + usageVideos: mapValueOfType(json, r'usageVideos')!, userId: mapValueOfType(json, r'userId')!, userName: mapValueOfType(json, r'userName')!, videos: mapValueOfType(json, r'videos')!, @@ -135,6 +149,8 @@ class UsageByUserDto { 'photos', 'quotaSizeInBytes', 'usage', + 'usagePhotos', + 'usageVideos', 'userId', 'userName', 'videos', diff --git a/mobile/openapi/lib/model/validate_library_dto.dart b/mobile/openapi/lib/model/validate_library_dto.dart index 08199e3aa66c8..79ddb9a540359 100644 --- a/mobile/openapi/lib/model/validate_library_dto.dart +++ b/mobile/openapi/lib/model/validate_library_dto.dart @@ -13,13 +13,13 @@ part of openapi.api; class ValidateLibraryDto { /// Returns a new [ValidateLibraryDto] instance. ValidateLibraryDto({ - this.exclusionPatterns = const [], - this.importPaths = const [], + this.exclusionPatterns = const {}, + this.importPaths = const {}, }); - List exclusionPatterns; + Set exclusionPatterns; - List importPaths; + Set importPaths; @override bool operator ==(Object other) => identical(this, other) || other is ValidateLibraryDto && @@ -37,8 +37,8 @@ class ValidateLibraryDto { Map toJson() { final json = {}; - json[r'exclusionPatterns'] = this.exclusionPatterns; - json[r'importPaths'] = this.importPaths; + json[r'exclusionPatterns'] = this.exclusionPatterns.toList(growable: false); + json[r'importPaths'] = this.importPaths.toList(growable: false); return json; } @@ -52,11 +52,11 @@ class ValidateLibraryDto { return ValidateLibraryDto( exclusionPatterns: json[r'exclusionPatterns'] is Iterable - ? (json[r'exclusionPatterns'] as Iterable).cast().toList(growable: false) - : const [], + ? (json[r'exclusionPatterns'] as Iterable).cast().toSet() + : const {}, importPaths: json[r'importPaths'] is Iterable - ? (json[r'importPaths'] as Iterable).cast().toList(growable: false) - : const [], + ? (json[r'importPaths'] as Iterable).cast().toSet() + : const {}, ); } return null; diff --git a/mobile/pubspec.lock b/mobile/pubspec.lock index fe40017ba85ee..34eb217828102 100644 --- a/mobile/pubspec.lock +++ b/mobile/pubspec.lock @@ -214,14 +214,6 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.3" - chewie: - dependency: "direct main" - description: - name: chewie - sha256: "2243e41e79e865d426d9dd9c1a9624aa33c4ad11de2d0cd680f826e2cd30e879" - url: "https://pub.dev" - source: hosted - version: "1.8.3" ci: dependency: transitive description: @@ -318,14 +310,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.0" - cupertino_icons: - dependency: transitive - description: - name: cupertino_icons - sha256: ba631d1c7f7bef6b729a622b7b752645a2d076dba9976925b8f25725a30e1ee6 - url: "https://pub.dev" - source: hosted - version: "1.0.8" custom_lint: dependency: "direct dev" description: @@ -378,10 +362,10 @@ packages: dependency: "direct main" description: name: device_info_plus - sha256: db03b2d2a3fa466a4627709e1db58692c3f7f658e36a5942d342d86efedc4091 + sha256: f545ffbadee826f26f2e1a0f0cbd667ae9a6011cc0f77c0f8f00a969655e6e95 url: "https://pub.dev" source: hosted - version: "11.0.0" + version: "11.1.1" device_info_plus_platform_interface: dependency: transitive description: @@ -450,10 +434,10 @@ packages: dependency: "direct main" description: name: file_picker - sha256: "167bb619cdddaa10ef2907609feb8a79c16dfa479d3afaf960f8e223f754bf12" + sha256: aac85f20436608e01a6ffd1fdd4e746a7f33c93a2c83752e626bdfaea139b877 url: "https://pub.dev" source: hosted - version: "8.1.2" + version: "8.1.3" file_selector_linux: dependency: transitive description: @@ -622,10 +606,10 @@ packages: dependency: "direct main" description: name: flutter_web_auth - sha256: a69fa8f43b9e4d86ac72176bf747b735e7b977dd7cf215076d95b87cb05affdd + sha256: "95e4856e24fb6ac1678f5ff334743b63f782d839ab324543d29ccbd295176209" url: "https://pub.dev" source: hosted - version: "0.5.0" + version: "0.6.0" flutter_web_plugins: dependency: transitive description: flutter @@ -876,26 +860,26 @@ packages: dependency: "direct main" description: name: isar - sha256: "99165dadb2cf2329d3140198363a7e7bff9bbd441871898a87e26914d25cf1ea" - url: "https://pub.dev" + sha256: e17a9555bc7f22ff26568b8c64d019b4ffa2dc6bd4cb1c8d9b269aefd32e53ad + url: "https://pub.isar-community.dev" source: hosted - version: "3.1.0+1" + version: "3.1.8" isar_flutter_libs: dependency: "direct main" description: name: isar_flutter_libs - sha256: bc6768cc4b9c61aabff77152e7f33b4b17d2fc93134f7af1c3dd51500fe8d5e8 - url: "https://pub.dev" + sha256: "78710781e658ce4bff59b3f38c5b2735e899e627f4e926e1221934e77b95231a" + url: "https://pub.isar-community.dev" source: hosted - version: "3.1.0+1" + version: "3.1.8" isar_generator: dependency: "direct dev" description: name: isar_generator - sha256: "76c121e1295a30423604f2f819bc255bc79f852f3bc8743a24017df6068ad133" - url: "https://pub.dev" + sha256: "484e73d3b7e81dbd816852fe0b9497333118a9aeb646fd2d349a62cc8980ffe1" + url: "https://pub.isar-community.dev" source: hosted - version: "3.1.0+1" + version: "3.1.8" js: dependency: transitive description: @@ -1024,14 +1008,31 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.4" - nested: + native_video_player: + dependency: "direct main" + description: + path: "." + ref: ac78487 + resolved-ref: ac78487b9a87c9e72cd15b428270a905ac551f29 + url: "https://github.com/immich-app/native_video_player" + source: git + version: "1.3.1" + network_info_plus: + dependency: "direct main" + description: + name: network_info_plus + sha256: bf9e39e523e9951d741868dc33ac386b0bc24301e9b7c8a7d60dbc34879150a8 + url: "https://pub.dev" + source: hosted + version: "6.1.1" + network_info_plus_platform_interface: dependency: transitive description: - name: nested - sha256: "03bac4c528c64c95c722ec99280375a6f2fc708eec17c7b3f07253b626cd2a20" + name: network_info_plus_platform_interface + sha256: b7f35f4a7baef511159e524499f3c15464a49faa5ec10e92ee0bce265e664906 url: "https://pub.dev" source: hosted - version: "1.0.0" + version: "2.0.1" nm: dependency: transitive description: @@ -1067,10 +1068,10 @@ packages: dependency: "direct main" description: name: package_info_plus - sha256: "894f37107424311bdae3e476552229476777b8752c5a2a2369c0cb9a2d5442ef" + sha256: da8d9ac8c4b1df253d1a328b7bf01ae77ef132833479ab40763334db13b91cce url: "https://pub.dev" source: hosted - version: "8.0.3" + version: "8.1.1" package_info_plus_platform_interface: dependency: transitive description: @@ -1211,10 +1212,10 @@ packages: dependency: "direct main" description: name: photo_manager - sha256: "70159eee32203e8162d49d588232f0299ed3f383c63eef1e899cb6b83dee6b26" + sha256: f5ef2618870e9a50d8bfeb81a02c242d580ae8614bd5ea9e1b80dbb7e49d4260 url: "https://pub.dev" source: hosted - version: "3.5.1" + version: "3.6.1" photo_manager_image_provider: dependency: "direct main" description: @@ -1255,14 +1256,6 @@ packages: url: "https://pub.dev" source: hosted version: "5.0.2" - provider: - dependency: transitive - description: - name: provider - sha256: c8a055ee5ce3fd98d6fc872478b03823ffdb448699c6ebdbbc71d59b596fd48c - url: "https://pub.dev" - source: hosted - version: "6.1.2" pub_semver: dependency: transitive description: @@ -1339,10 +1332,10 @@ packages: dependency: "direct main" description: name: share_plus - sha256: fec12c3c39f01e4df1ec6ad92b6e85503c5ca64ffd6e28d18c9ffe53fcc4cb11 + sha256: "9c9bafd4060728d7cdb2464c341743adbd79d327cb067ec7afb64583540b47c8" url: "https://pub.dev" source: hosted - version: "10.0.3" + version: "10.1.2" share_plus_platform_interface: dependency: transitive description: @@ -1708,46 +1701,6 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.4" - video_player: - dependency: "direct main" - description: - name: video_player - sha256: e30df0d226c4ef82e2c150ebf6834b3522cf3f654d8e2f9419d376cdc071425d - url: "https://pub.dev" - source: hosted - version: "2.9.1" - video_player_android: - dependency: transitive - description: - name: video_player_android - sha256: "4de50df9ee786f5891d3281e1e633d7b142ef1acf47392592eb91cba5d355849" - url: "https://pub.dev" - source: hosted - version: "2.6.0" - video_player_avfoundation: - dependency: transitive - description: - name: video_player_avfoundation - sha256: d1e9a824f2b324000dc8fb2dcb2a3285b6c1c7c487521c63306cc5b394f68a7c - url: "https://pub.dev" - source: hosted - version: "2.6.1" - video_player_platform_interface: - dependency: transitive - description: - name: video_player_platform_interface - sha256: "236454725fafcacf98f0f39af0d7c7ab2ce84762e3b63f2cbb3ef9a7e0550bc6" - url: "https://pub.dev" - source: hosted - version: "6.2.2" - video_player_web: - dependency: transitive - description: - name: video_player_web - sha256: "6dcdd298136523eaf7dfc31abaf0dfba9aa8a8dbc96670e87e9d42b6f2caf774" - url: "https://pub.dev" - source: hosted - version: "2.3.2" vm_service: dependency: transitive description: @@ -1861,5 +1814,5 @@ packages: source: hosted version: "3.1.2" sdks: - dart: ">=3.5.0 <4.0.0" - flutter: ">=3.24.3" + dart: ">=3.5.3 <4.0.0" + flutter: ">=3.24.5" diff --git a/mobile/pubspec.yaml b/mobile/pubspec.yaml index 15d4a057f64ef..beabbd89b6cd7 100644 --- a/mobile/pubspec.yaml +++ b/mobile/pubspec.yaml @@ -2,18 +2,20 @@ name: immich_mobile description: Immich - selfhosted backup media file on mobile phone publish_to: 'none' -version: 1.119.1+164 +version: 1.123.0+172 environment: sdk: '>=3.3.0 <4.0.0' - flutter: 3.24.3 + flutter: 3.24.5 + +isar_version: &isar_version 3.1.8 # define the version to be used dependencies: flutter: sdk: flutter path_provider_ios: - photo_manager: ^3.5.1 + photo_manager: ^3.6.1 photo_manager_image_provider: ^2.2.0 flutter_hooks: ^0.20.4 hooks_riverpod: ^2.4.9 @@ -23,8 +25,6 @@ dependencies: intl: ^0.19.0 auto_route: ^9.2.0 fluttertoast: ^8.2.4 - video_player: ^2.8.2 - chewie: ^1.7.4 socket_io_client: ^2.0.3+1 maplibre_gl: 0.19.0+2 geolocator: ^11.0.0 # used to move to current location in map view @@ -42,10 +42,14 @@ dependencies: path_provider: ^2.1.2 collection: ^1.18.0 http_parser: ^4.0.2 - flutter_web_auth: ^0.5.0 + flutter_web_auth: 0.6.0 easy_image_viewer: ^1.4.0 - isar: ^3.1.0+1 - isar_flutter_libs: ^3.1.0+1 + 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/ permission_handler: ^11.2.0 device_info_plus: ^11.0.0 connectivity_plus: ^6.0.0 @@ -57,6 +61,11 @@ dependencies: async: ^2.11.0 dynamic_color: ^1.7.0 #package to apply system theme background_downloader: ^8.5.5 + network_info_plus: ^6.1.1 + native_video_player: + git: + url: https://github.com/immich-app/native_video_player + ref: ac78487 #image editing packages crop_image: ^1.0.13 @@ -92,7 +101,9 @@ dev_dependencies: auto_route_generator: ^9.0.0 flutter_launcher_icons: ^0.14.0 flutter_native_splash: ^2.3.9 - isar_generator: ^3.1.0+1 + isar_generator: + version: *isar_version + hosted: https://pub.isar-community.dev/ integration_test: sdk: flutter custom_lint: ^0.6.4 diff --git a/mobile/scripts/fdroid_build_isar.sh b/mobile/scripts/fdroid_build_isar.sh index 41517737c94f5..f42bc51d9a09f 100755 --- a/mobile/scripts/fdroid_build_isar.sh +++ b/mobile/scripts/fdroid_build_isar.sh @@ -8,11 +8,11 @@ bash tool/build_android.sh x64 bash tool/build_android.sh armv7 bash tool/build_android.sh arm64 mv libisar_android_arm64.so libisar.so -mv libisar.so ../.pub-cache/hosted/pub.dev/isar_flutter_libs-*/android/src/main/jniLibs/arm64-v8a/ +mv libisar.so ../.pub-cache/hosted/pub.isar-community.dev/isar_flutter_libs-*/android/src/main/jniLibs/arm64-v8a/ mv libisar_android_armv7.so libisar.so -mv libisar.so ../.pub-cache/hosted/pub.dev/isar_flutter_libs-*/android/src/main/jniLibs/armeabi-v7a/ +mv libisar.so ../.pub-cache/hosted/pub.isar-community.dev/isar_flutter_libs-*/android/src/main/jniLibs/armeabi-v7a/ mv libisar_android_x64.so libisar.so -mv libisar.so ../.pub-cache/hosted/pub.dev/isar_flutter_libs-*/android/src/main/jniLibs/x86_64/ +mv libisar.so ../.pub-cache/hosted/pub.isar-community.dev/isar_flutter_libs-*/android/src/main/jniLibs/x86_64/ mv libisar_android_x86.so libisar.so -mv libisar.so ../.pub-cache/hosted/pub.dev/isar_flutter_libs-*/android/src/main/jniLibs/x86/ +mv libisar.so ../.pub-cache/hosted/pub.isar-community.dev/isar_flutter_libs-*/android/src/main/jniLibs/x86/ ) \ No newline at end of file diff --git a/mobile/test/fixtures/album.stub.dart b/mobile/test/fixtures/album.stub.dart index 4fa0dac1d243b..e820f193d5450 100644 --- a/mobile/test/fixtures/album.stub.dart +++ b/mobile/test/fixtures/album.stub.dart @@ -54,4 +54,49 @@ final class AlbumStub { ..assets.addAll([AssetStub.image1, AssetStub.image2]) ..activityEnabled = true ..owner.value = UserStub.admin; + + static final create2020end2020Album = Album( + name: "create2020update2020Album", + localId: "create2020update2020Album-local", + remoteId: "create2020update2020Album-remote", + createdAt: DateTime(2020), + modifiedAt: DateTime(2020), + shared: false, + activityEnabled: false, + startDate: DateTime(2020), + endDate: DateTime(2020), + ); + static final create2020end2022Album = Album( + name: "create2020update2021Album", + localId: "create2020update2021Album-local", + remoteId: "create2020update2021Album-remote", + createdAt: DateTime(2020), + modifiedAt: DateTime(2022), + shared: false, + activityEnabled: false, + startDate: DateTime(2020), + endDate: DateTime(2022), + ); + static final create2020end2024Album = Album( + name: "create2020update2022Album", + localId: "create2020update2022Album-local", + remoteId: "create2020update2022Album-remote", + createdAt: DateTime(2020), + modifiedAt: DateTime(2024), + shared: false, + activityEnabled: false, + startDate: DateTime(2020), + endDate: DateTime(2024), + ); + static final create2020end2026Album = Album( + name: "create2020update2023Album", + localId: "create2020update2023Album-local", + remoteId: "create2020update2023Album-remote", + createdAt: DateTime(2020), + modifiedAt: DateTime(2026), + shared: false, + activityEnabled: false, + startDate: DateTime(2020), + endDate: DateTime(2026), + ); } diff --git a/mobile/test/modules/album/album_sort_by_options_provider_test.dart b/mobile/test/modules/album/album_sort_by_options_provider_test.dart index 84a7e6e9b8465..bfb61ef4029f7 100644 --- a/mobile/test/modules/album/album_sort_by_options_provider_test.dart +++ b/mobile/test/modules/album/album_sort_by_options_provider_test.dart @@ -147,24 +147,40 @@ void main() { group("Album sort - Most Recent", () { const mostRecent = AlbumSortMode.mostRecent; - test("Most Recent - ASC", () { - final sorted = mostRecent.sortFn(albums, false); + test("Most Recent - DESC", () { + final sorted = mostRecent.sortFn( + [ + AlbumStub.create2020end2020Album, + AlbumStub.create2020end2022Album, + AlbumStub.create2020end2024Album, + AlbumStub.create2020end2026Album, + ], + false, + ); final sortedList = [ - AlbumStub.sharedWithUser, - AlbumStub.twoAsset, - AlbumStub.oneAsset, - AlbumStub.emptyAlbum, + AlbumStub.create2020end2026Album, + AlbumStub.create2020end2024Album, + AlbumStub.create2020end2022Album, + AlbumStub.create2020end2020Album, ]; expect(sorted, orderedEquals(sortedList)); }); - test("Most Recent - DESC", () { - final sorted = mostRecent.sortFn(albums, true); + test("Most Recent - ASC", () { + final sorted = mostRecent.sortFn( + [ + AlbumStub.create2020end2020Album, + AlbumStub.create2020end2022Album, + AlbumStub.create2020end2024Album, + AlbumStub.create2020end2026Album, + ], + true, + ); final sortedList = [ - AlbumStub.emptyAlbum, - AlbumStub.oneAsset, - AlbumStub.twoAsset, - AlbumStub.sharedWithUser, + AlbumStub.create2020end2020Album, + AlbumStub.create2020end2022Album, + AlbumStub.create2020end2024Album, + AlbumStub.create2020end2026Album, ]; expect(sorted, orderedEquals(sortedList)); }); diff --git a/mobile/test/modules/map/map_theme_override_test.dart b/mobile/test/modules/map/map_theme_override_test.dart index f399625ac2867..bd000c8715f70 100644 --- a/mobile/test/modules/map/map_theme_override_test.dart +++ b/mobile/test/modules/map/map_theme_override_test.dart @@ -5,6 +5,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/models/map/map_state.model.dart'; +import 'package:immich_mobile/providers/locale_provider.dart'; import 'package:immich_mobile/providers/map/map_state.provider.dart'; import 'package:immich_mobile/widgets/map/map_theme_override.dart'; @@ -24,14 +25,17 @@ void main() { setUp(() { mapState = MapState(themeMode: ThemeMode.dark); mapStateNotifier = MockMapStateNotifier(mapState); - overrides = [mapStateNotifierProvider.overrideWith(() => mapStateNotifier)]; + overrides = [ + mapStateNotifierProvider.overrideWith(() => mapStateNotifier), + localeProvider.overrideWithValue(const Locale("en")), + ]; }); testWidgets("Return dark theme style when theme mode is dark", (tester) async { AsyncValue? mapStyle; await tester.pumpConsumerWidget( - MapThemeOveride( + MapThemeOverride( mapBuilder: (AsyncValue style) { mapStyle = style; return const Text("Mock"); @@ -49,7 +53,7 @@ void main() { testWidgets("Return error when style is not fetched", (tester) async { AsyncValue? mapStyle; await tester.pumpConsumerWidget( - MapThemeOveride( + MapThemeOverride( mapBuilder: (AsyncValue style) { mapStyle = style; return const Text("Mock"); @@ -69,7 +73,7 @@ void main() { (tester) async { AsyncValue? mapStyle; await tester.pumpConsumerWidget( - MapThemeOveride( + MapThemeOverride( mapBuilder: (AsyncValue style) { mapStyle = style; return const Text("Mock"); @@ -90,7 +94,7 @@ void main() { testWidgets("Return dark theme style when system is dark", (tester) async { AsyncValue? mapStyle; await tester.pumpConsumerWidget( - MapThemeOveride( + MapThemeOverride( mapBuilder: (AsyncValue style) { mapStyle = style; return const Text("Mock"); @@ -114,7 +118,7 @@ void main() { (tester) async { AsyncValue? mapStyle; await tester.pumpConsumerWidget( - MapThemeOveride( + MapThemeOverride( mapBuilder: (AsyncValue style) { mapStyle = style; return const Text("Mock"); @@ -138,7 +142,7 @@ void main() { (tester) async { AsyncValue? mapStyle; await tester.pumpConsumerWidget( - MapThemeOveride( + MapThemeOverride( mapBuilder: (AsyncValue style) { mapStyle = style; return const Text("Mock"); diff --git a/mobile/test/repository.mocks.dart b/mobile/test/repository.mocks.dart index c76a003eec2a0..3dda932cac428 100644 --- a/mobile/test/repository.mocks.dart +++ b/mobile/test/repository.mocks.dart @@ -3,6 +3,8 @@ import 'package:immich_mobile/interfaces/album_api.interface.dart'; import 'package:immich_mobile/interfaces/album_media.interface.dart'; import 'package:immich_mobile/interfaces/asset.interface.dart'; import 'package:immich_mobile/interfaces/asset_media.interface.dart'; +import 'package:immich_mobile/interfaces/auth.interface.dart'; +import 'package:immich_mobile/interfaces/auth_api.interface.dart'; import 'package:immich_mobile/interfaces/backup.interface.dart'; import 'package:immich_mobile/interfaces/etag.interface.dart'; import 'package:immich_mobile/interfaces/exif_info.interface.dart'; @@ -29,3 +31,7 @@ class MockAssetMediaRepository extends Mock implements IAssetMediaRepository {} class MockFileMediaRepository extends Mock implements IFileMediaRepository {} class MockAlbumApiRepository extends Mock implements IAlbumApiRepository {} + +class MockAuthApiRepository extends Mock implements IAuthApiRepository {} + +class MockAuthRepository extends Mock implements IAuthRepository {} diff --git a/mobile/test/service.mocks.dart b/mobile/test/service.mocks.dart index de49a98cc4e5a..507b4f281b4fb 100644 --- a/mobile/test/service.mocks.dart +++ b/mobile/test/service.mocks.dart @@ -1,6 +1,7 @@ import 'package:immich_mobile/services/api.service.dart'; import 'package:immich_mobile/services/entity.service.dart'; import 'package:immich_mobile/services/hash.service.dart'; +import 'package:immich_mobile/services/network.service.dart'; import 'package:immich_mobile/services/sync.service.dart'; import 'package:immich_mobile/services/user.service.dart'; import 'package:mocktail/mocktail.dart'; @@ -14,3 +15,5 @@ class MockSyncService extends Mock implements SyncService {} class MockHashService extends Mock implements HashService {} class MockEntityService extends Mock implements EntityService {} + +class MockNetworkService extends Mock implements NetworkService {} diff --git a/mobile/test/services/album.service_test.dart b/mobile/test/services/album.service_test.dart index 848d7cfad7078..c0775a1c3e070 100644 --- a/mobile/test/services/album.service_test.dart +++ b/mobile/test/services/album.service_test.dart @@ -54,6 +54,7 @@ void main() { .thenAnswer((_) async => []); when(() => backupRepository.getIdsBySelection(BackupSelection.select)) .thenAnswer((_) async => []); + when(() => albumMediaRepository.getAll()).thenAnswer((_) async => []); when(() => albumRepository.count(local: true)).thenAnswer((_) async => 1); when(() => syncService.removeAllLocalAlbumsAndAssets()) .thenAnswer((_) async => true); diff --git a/mobile/test/services/auth.service_test.dart b/mobile/test/services/auth.service_test.dart new file mode 100644 index 0000000000000..edbf6495e3e48 --- /dev/null +++ b/mobile/test/services/auth.service_test.dart @@ -0,0 +1,308 @@ +import 'package:flutter/widgets.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:immich_mobile/entities/store.entity.dart'; +import 'package:immich_mobile/models/auth/auxilary_endpoint.model.dart'; +import 'package:immich_mobile/services/auth.service.dart'; +import 'package:mocktail/mocktail.dart'; +import 'package:openapi/api.dart'; +import '../repository.mocks.dart'; +import '../service.mocks.dart'; +import '../test_utils.dart'; + +void main() { + late AuthService sut; + late MockAuthApiRepository authApiRepository; + late MockAuthRepository authRepository; + late MockApiService apiService; + late MockNetworkService networkService; + + setUp(() async { + authApiRepository = MockAuthApiRepository(); + authRepository = MockAuthRepository(); + apiService = MockApiService(); + networkService = MockNetworkService(); + + sut = AuthService( + authApiRepository, + authRepository, + apiService, + networkService, + ); + + registerFallbackValue(Uri()); + }); + + group('validateServerUrl', () { + setUpAll(() async { + WidgetsFlutterBinding.ensureInitialized(); + final db = await TestUtils.initIsar(); + db.writeTxnSync(() => db.clearSync()); + Store.init(db); + }); + + test('Should resolve HTTP endpoint', () async { + const testUrl = 'http://ip:2283'; + const resolvedUrl = 'http://ip:2283/api'; + + when(() => apiService.resolveAndSetEndpoint(testUrl)) + .thenAnswer((_) async => resolvedUrl); + when(() => apiService.setDeviceInfoHeader()).thenAnswer((_) async => {}); + + final result = await sut.validateServerUrl(testUrl); + + expect(result, resolvedUrl); + + verify(() => apiService.resolveAndSetEndpoint(testUrl)).called(1); + verify(() => apiService.setDeviceInfoHeader()).called(1); + }); + + test('Should resolve HTTPS endpoint', () async { + const testUrl = 'https://immich.domain.com'; + const resolvedUrl = 'https://immich.domain.com/api'; + + when(() => apiService.resolveAndSetEndpoint(testUrl)) + .thenAnswer((_) async => resolvedUrl); + when(() => apiService.setDeviceInfoHeader()).thenAnswer((_) async => {}); + + final result = await sut.validateServerUrl(testUrl); + + expect(result, resolvedUrl); + + verify(() => apiService.resolveAndSetEndpoint(testUrl)).called(1); + verify(() => apiService.setDeviceInfoHeader()).called(1); + }); + + test('Should throw error on invalid URL', () async { + const testUrl = 'invalid-url'; + + when(() => apiService.resolveAndSetEndpoint(testUrl)) + .thenThrow(Exception('Invalid URL')); + + expect( + () async => await sut.validateServerUrl(testUrl), + throwsA(isA()), + ); + + verify(() => apiService.resolveAndSetEndpoint(testUrl)).called(1); + verifyNever(() => apiService.setDeviceInfoHeader()); + }); + + test('Should throw error on unreachable server', () async { + const testUrl = 'https://unreachable.server'; + + when(() => apiService.resolveAndSetEndpoint(testUrl)) + .thenThrow(Exception('Server is not reachable')); + + expect( + () async => await sut.validateServerUrl(testUrl), + throwsA(isA()), + ); + + verify(() => apiService.resolveAndSetEndpoint(testUrl)).called(1); + verifyNever(() => apiService.setDeviceInfoHeader()); + }); + }); + + group('logout', () { + test('Should logout user', () async { + when(() => authApiRepository.logout()).thenAnswer((_) async => {}); + when(() => authRepository.clearLocalData()) + .thenAnswer((_) => Future.value(null)); + + await sut.logout(); + + verify(() => authApiRepository.logout()).called(1); + verify(() => authRepository.clearLocalData()).called(1); + }); + + test('Should clear local data even on server error', () async { + when(() => authApiRepository.logout()) + .thenThrow(Exception('Server error')); + when(() => authRepository.clearLocalData()) + .thenAnswer((_) => Future.value(null)); + + await sut.logout(); + + verify(() => authApiRepository.logout()).called(1); + verify(() => authRepository.clearLocalData()).called(1); + }); + }); + + group('setOpenApiServiceEndpoint', () { + setUp(() { + when(() => networkService.getWifiName()) + .thenAnswer((_) async => 'TestWifi'); + }); + + test('Should return null if auto endpoint switching is disabled', () async { + when(() => authRepository.getEndpointSwitchingFeature()) + .thenReturn((false)); + + final result = await sut.setOpenApiServiceEndpoint(); + + expect(result, isNull); + verify(() => authRepository.getEndpointSwitchingFeature()).called(1); + verifyNever(() => networkService.getWifiName()); + }); + + test('Should set local connection if wifi name matches', () async { + when(() => authRepository.getEndpointSwitchingFeature()).thenReturn(true); + when(() => authRepository.getPreferredWifiName()).thenReturn('TestWifi'); + when(() => authRepository.getLocalEndpoint()) + .thenReturn('http://local.endpoint'); + when(() => apiService.resolveAndSetEndpoint('http://local.endpoint')) + .thenAnswer((_) async => 'http://local.endpoint'); + + final result = await sut.setOpenApiServiceEndpoint(); + + expect(result, 'http://local.endpoint'); + verify(() => authRepository.getEndpointSwitchingFeature()).called(1); + verify(() => networkService.getWifiName()).called(1); + verify(() => authRepository.getPreferredWifiName()).called(1); + verify(() => authRepository.getLocalEndpoint()).called(1); + verify(() => apiService.resolveAndSetEndpoint('http://local.endpoint')) + .called(1); + }); + + test('Should set external endpoint if wifi name not matching', () async { + when(() => authRepository.getEndpointSwitchingFeature()).thenReturn(true); + when(() => authRepository.getPreferredWifiName()) + .thenReturn('DifferentWifi'); + when(() => authRepository.getExternalEndpointList()).thenReturn([ + AuxilaryEndpoint( + url: 'https://external.endpoint', + status: AuxCheckStatus.valid, + ), + ]); + when( + () => apiService.resolveAndSetEndpoint('https://external.endpoint'), + ).thenAnswer((_) async => 'https://external.endpoint/api'); + + final result = await sut.setOpenApiServiceEndpoint(); + + expect(result, 'https://external.endpoint/api'); + verify(() => authRepository.getEndpointSwitchingFeature()).called(1); + verify(() => networkService.getWifiName()).called(1); + verify(() => authRepository.getPreferredWifiName()).called(1); + verify(() => authRepository.getExternalEndpointList()).called(1); + verify( + () => apiService.resolveAndSetEndpoint('https://external.endpoint'), + ).called(1); + }); + + test('Should set second external endpoint if the first throw any error', + () async { + when(() => authRepository.getEndpointSwitchingFeature()).thenReturn(true); + when(() => authRepository.getPreferredWifiName()) + .thenReturn('DifferentWifi'); + when(() => authRepository.getExternalEndpointList()).thenReturn([ + AuxilaryEndpoint( + url: 'https://external.endpoint', + status: AuxCheckStatus.valid, + ), + AuxilaryEndpoint( + url: 'https://external.endpoint2', + status: AuxCheckStatus.valid, + ), + ]); + + when( + () => apiService.resolveAndSetEndpoint('https://external.endpoint'), + ).thenThrow(Exception('Invalid endpoint')); + when( + () => apiService.resolveAndSetEndpoint('https://external.endpoint2'), + ).thenAnswer((_) async => 'https://external.endpoint2/api'); + + final result = await sut.setOpenApiServiceEndpoint(); + + expect(result, 'https://external.endpoint2/api'); + verify(() => authRepository.getEndpointSwitchingFeature()).called(1); + verify(() => networkService.getWifiName()).called(1); + verify(() => authRepository.getPreferredWifiName()).called(1); + verify(() => authRepository.getExternalEndpointList()).called(1); + verify( + () => apiService.resolveAndSetEndpoint('https://external.endpoint2'), + ).called(1); + }); + + test('Should set second external endpoint if the first throw ApiException', + () async { + when(() => authRepository.getEndpointSwitchingFeature()).thenReturn(true); + when(() => authRepository.getPreferredWifiName()) + .thenReturn('DifferentWifi'); + when(() => authRepository.getExternalEndpointList()).thenReturn([ + AuxilaryEndpoint( + url: 'https://external.endpoint', + status: AuxCheckStatus.valid, + ), + AuxilaryEndpoint( + url: 'https://external.endpoint2', + status: AuxCheckStatus.valid, + ), + ]); + + when( + () => apiService.resolveAndSetEndpoint('https://external.endpoint'), + ).thenThrow(ApiException(503, 'Invalid endpoint')); + when( + () => apiService.resolveAndSetEndpoint('https://external.endpoint2'), + ).thenAnswer((_) async => 'https://external.endpoint2/api'); + + final result = await sut.setOpenApiServiceEndpoint(); + + expect(result, 'https://external.endpoint2/api'); + verify(() => authRepository.getEndpointSwitchingFeature()).called(1); + verify(() => networkService.getWifiName()).called(1); + verify(() => authRepository.getPreferredWifiName()).called(1); + verify(() => authRepository.getExternalEndpointList()).called(1); + verify( + () => apiService.resolveAndSetEndpoint('https://external.endpoint2'), + ).called(1); + }); + + test('Should handle error when setting local connection', () async { + when(() => authRepository.getEndpointSwitchingFeature()).thenReturn(true); + when(() => authRepository.getPreferredWifiName()).thenReturn('TestWifi'); + when(() => authRepository.getLocalEndpoint()) + .thenReturn('http://local.endpoint'); + when(() => apiService.resolveAndSetEndpoint('http://local.endpoint')) + .thenThrow(Exception('Local endpoint error')); + + final result = await sut.setOpenApiServiceEndpoint(); + + expect(result, isNull); + verify(() => authRepository.getEndpointSwitchingFeature()).called(1); + verify(() => networkService.getWifiName()).called(1); + verify(() => authRepository.getPreferredWifiName()).called(1); + verify(() => authRepository.getLocalEndpoint()).called(1); + verify(() => apiService.resolveAndSetEndpoint('http://local.endpoint')) + .called(1); + }); + + test('Should handle error when setting external connection', () async { + when(() => authRepository.getEndpointSwitchingFeature()).thenReturn(true); + when(() => authRepository.getPreferredWifiName()) + .thenReturn('DifferentWifi'); + when(() => authRepository.getExternalEndpointList()).thenReturn([ + AuxilaryEndpoint( + url: 'https://external.endpoint', + status: AuxCheckStatus.valid, + ), + ]); + when( + () => apiService.resolveAndSetEndpoint('https://external.endpoint'), + ).thenThrow(Exception('External endpoint error')); + + final result = await sut.setOpenApiServiceEndpoint(); + + expect(result, isNull); + verify(() => authRepository.getEndpointSwitchingFeature()).called(1); + verify(() => networkService.getWifiName()).called(1); + verify(() => authRepository.getPreferredWifiName()).called(1); + verify(() => authRepository.getExternalEndpointList()).called(1); + verify( + () => apiService.resolveAndSetEndpoint('https://external.endpoint'), + ).called(1); + }); + }); +} diff --git a/open-api/immich-openapi-specs.json b/open-api/immich-openapi-specs.json index ef488fe5c00cc..2686d4f96d69f 100644 --- a/open-api/immich-openapi-specs.json +++ b/open-api/immich-openapi-specs.json @@ -1424,7 +1424,6 @@ }, "/assets/bulk-upload-check": { "post": { - "description": "Checks if assets exist by checksums", "operationId": "checkBulkUpload", "parameters": [], "requestBody": { @@ -1460,6 +1459,7 @@ "api_key": [] } ], + "summary": "Checks if assets exist by checksums", "tags": [ "Assets" ] @@ -1467,7 +1467,6 @@ }, "/assets/device/{deviceId}": { "get": { - "description": "Get all asset of a device that are in the database, ID only.", "operationId": "getAllUserAssetsByDeviceId", "parameters": [ { @@ -1505,6 +1504,7 @@ "api_key": [] } ], + "summary": "Get all asset of a device that are in the database, ID only.", "tags": [ "Assets" ] @@ -1512,7 +1512,6 @@ }, "/assets/exist": { "post": { - "description": "Checks if multiple assets exist on the server and returns all existing - used by background backup", "operationId": "checkExistingAssets", "parameters": [], "requestBody": { @@ -1548,6 +1547,7 @@ "api_key": [] } ], + "summary": "Checks if multiple assets exist on the server and returns all existing - used by background backup", "tags": [ "Assets" ] @@ -1903,7 +1903,6 @@ ] }, "put": { - "description": "Replace the asset with new file, without changing its id", "operationId": "replaceAsset", "parameters": [ { @@ -1957,6 +1956,7 @@ "api_key": [] } ], + "summary": "Replace the asset with new file, without changing its id", "tags": [ "Assets" ], @@ -3430,6 +3430,57 @@ ] } }, + "/notifications/templates/{name}": { + "post": { + "operationId": "getNotificationTemplate", + "parameters": [ + { + "name": "name", + "required": true, + "in": "path", + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TemplateDto" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TemplateResponseDto" + } + } + }, + "description": "" + } + }, + "security": [ + { + "bearer": [] + }, + { + "cookie": [] + }, + { + "api_key": [] + } + ], + "tags": [ + "Notifications" + ] + } + }, "/notifications/test-email": { "post": { "operationId": "sendTestEmail", @@ -3795,6 +3846,24 @@ "get": { "operationId": "getAllPeople", "parameters": [ + { + "name": "closestAssetId", + "required": false, + "in": "query", + "schema": { + "format": "uuid", + "type": "string" + } + }, + { + "name": "closestPersonId", + "required": false, + "in": "query", + "schema": { + "format": "uuid", + "type": "string" + } + }, { "name": "page", "required": false, @@ -4409,7 +4478,7 @@ }, "/search/metadata": { "post": { - "operationId": "searchMetadata", + "operationId": "searchAssets", "parameters": [], "requestBody": { "content": { @@ -7385,7 +7454,7 @@ "info": { "title": "Immich", "description": "Immich API", - "version": "1.119.1", + "version": "1.123.0", "contact": {} }, "tags": [], @@ -7423,6 +7492,7 @@ "items": { "$ref": "#/components/schemas/Permission" }, + "minItems": 1, "type": "array" } }, @@ -7503,7 +7573,11 @@ "type": "string" }, "type": { - "$ref": "#/components/schemas/ReactionType" + "allOf": [ + { + "$ref": "#/components/schemas/ReactionType" + } + ] } }, "required": [ @@ -7530,7 +7604,11 @@ "type": "string" }, "type": { - "$ref": "#/components/schemas/ReactionType" + "allOf": [ + { + "$ref": "#/components/schemas/ReactionType" + } + ] }, "user": { "$ref": "#/components/schemas/UserResponseDto" @@ -7562,6 +7640,7 @@ "items": { "$ref": "#/components/schemas/AlbumUserAddDto" }, + "minItems": 1, "type": "array" } }, @@ -7630,7 +7709,11 @@ "type": "string" }, "order": { - "$ref": "#/components/schemas/AssetOrder" + "allOf": [ + { + "$ref": "#/components/schemas/AssetOrder" + } + ] }, "owner": { "$ref": "#/components/schemas/UserResponseDto" @@ -7690,7 +7773,12 @@ "AlbumUserAddDto": { "properties": { "role": { - "$ref": "#/components/schemas/AlbumUserRole" + "allOf": [ + { + "$ref": "#/components/schemas/AlbumUserRole" + } + ], + "default": "editor" }, "userId": { "format": "uuid", @@ -7705,7 +7793,11 @@ "AlbumUserCreateDto": { "properties": { "role": { - "$ref": "#/components/schemas/AlbumUserRole" + "allOf": [ + { + "$ref": "#/components/schemas/AlbumUserRole" + } + ] }, "userId": { "format": "uuid", @@ -7721,7 +7813,11 @@ "AlbumUserResponseDto": { "properties": { "role": { - "$ref": "#/components/schemas/AlbumUserRole" + "allOf": [ + { + "$ref": "#/components/schemas/AlbumUserRole" + } + ] }, "user": { "$ref": "#/components/schemas/UserResponseDto" @@ -8018,7 +8114,11 @@ "nullable": true }, "sourceType": { - "$ref": "#/components/schemas/SourceType" + "allOf": [ + { + "$ref": "#/components/schemas/SourceType" + } + ] } }, "required": [ @@ -8089,7 +8189,11 @@ "type": "integer" }, "sourceType": { - "$ref": "#/components/schemas/SourceType" + "allOf": [ + { + "$ref": "#/components/schemas/SourceType" + } + ] } }, "required": [ @@ -8185,7 +8289,11 @@ "type": "array" }, "name": { - "$ref": "#/components/schemas/AssetJobName" + "allOf": [ + { + "$ref": "#/components/schemas/AssetJobName" + } + ] } }, "required": [ @@ -8283,7 +8391,11 @@ "type": "string" }, "status": { - "$ref": "#/components/schemas/AssetMediaStatus" + "allOf": [ + { + "$ref": "#/components/schemas/AssetMediaStatus" + } + ] } }, "required": [ @@ -8402,9 +8514,6 @@ "description": "This property was deprecated in v1.113.0", "type": "boolean" }, - "smartInfo": { - "$ref": "#/components/schemas/SmartInfoResponseDto" - }, "stack": { "allOf": [ { @@ -8424,7 +8533,11 @@ "type": "string" }, "type": { - "$ref": "#/components/schemas/AssetTypeEnum" + "allOf": [ + { + "$ref": "#/components/schemas/AssetTypeEnum" + } + ] }, "unassignedFaces": { "items": { @@ -8537,7 +8650,11 @@ "AvatarResponse": { "properties": { "color": { - "$ref": "#/components/schemas/UserAvatarColor" + "allOf": [ + { + "$ref": "#/components/schemas/UserAvatarColor" + } + ] } }, "required": [ @@ -8548,7 +8665,11 @@ "AvatarUpdate": { "properties": { "color": { - "$ref": "#/components/schemas/UserAvatarColor" + "allOf": [ + { + "$ref": "#/components/schemas/UserAvatarColor" + } + ] } }, "type": "object" @@ -8639,6 +8760,7 @@ "items": { "type": "string" }, + "minItems": 1, "type": "array" }, "deviceId": { @@ -8705,13 +8827,17 @@ "items": { "type": "string" }, - "type": "array" + "maxItems": 128, + "type": "array", + "uniqueItems": true }, "importPaths": { "items": { "type": "string" }, - "type": "array" + "maxItems": 128, + "type": "array", + "uniqueItems": true }, "name": { "type": "string" @@ -9180,10 +9306,18 @@ "type": "string" }, "entityType": { - "$ref": "#/components/schemas/PathEntityType" + "allOf": [ + { + "$ref": "#/components/schemas/PathEntityType" + } + ] }, "pathType": { - "$ref": "#/components/schemas/PathType" + "allOf": [ + { + "$ref": "#/components/schemas/PathType" + } + ] }, "pathValue": { "type": "string" @@ -9245,7 +9379,11 @@ "JobCommandDto": { "properties": { "command": { - "$ref": "#/components/schemas/JobCommand" + "allOf": [ + { + "$ref": "#/components/schemas/JobCommand" + } + ] }, "force": { "type": "boolean" @@ -9290,7 +9428,11 @@ "JobCreateDto": { "properties": { "name": { - "$ref": "#/components/schemas/ManualJobName" + "allOf": [ + { + "$ref": "#/components/schemas/ManualJobName" + } + ] } }, "required": [ @@ -9478,6 +9620,7 @@ "properties": { "email": { "example": "testuser@email.com", + "format": "email", "type": "string" }, "password": { @@ -9651,7 +9794,11 @@ "type": "string" }, "type": { - "$ref": "#/components/schemas/MemoryType" + "allOf": [ + { + "$ref": "#/components/schemas/MemoryType" + } + ] } }, "required": [ @@ -9716,7 +9863,11 @@ "type": "string" }, "type": { - "$ref": "#/components/schemas/MemoryType" + "allOf": [ + { + "$ref": "#/components/schemas/MemoryType" + } + ] }, "updatedAt": { "format": "date-time", @@ -9845,7 +9996,11 @@ "type": "string" }, "order": { - "$ref": "#/components/schemas/AssetOrder" + "allOf": [ + { + "$ref": "#/components/schemas/AssetOrder" + } + ] }, "originalFileName": { "type": "string" @@ -9896,7 +10051,11 @@ "type": "string" }, "type": { - "$ref": "#/components/schemas/AssetTypeEnum" + "allOf": [ + { + "$ref": "#/components/schemas/AssetTypeEnum" + } + ] }, "updatedAfter": { "format": "date-time", @@ -9980,7 +10139,11 @@ "PartnerResponseDto": { "properties": { "avatarColor": { - "$ref": "#/components/schemas/UserAvatarColor" + "allOf": [ + { + "$ref": "#/components/schemas/UserAvatarColor" + } + ] }, "email": { "type": "string" @@ -10498,7 +10661,11 @@ "type": "string" }, "type": { - "$ref": "#/components/schemas/AssetTypeEnum" + "allOf": [ + { + "$ref": "#/components/schemas/AssetTypeEnum" + } + ] }, "updatedAfter": { "format": "date-time", @@ -10828,6 +10995,9 @@ "oauthButtonText": { "type": "string" }, + "publicUsers": { + "type": "boolean" + }, "trashDays": { "type": "integer" }, @@ -10843,6 +11013,7 @@ "mapDarkStyleUrl", "mapLightStyleUrl", "oauthButtonText", + "publicUsers", "trashDays", "userDeleteDelay" ], @@ -10969,7 +11140,9 @@ { "photos": 1, "videos": 1, - "diskUsageRaw": 1 + "diskUsageRaw": 2, + "usagePhotos": 1, + "usageVideos": 1 } ], "items": { @@ -10978,6 +11151,16 @@ "title": "Array of usage for each user", "type": "array" }, + "usagePhotos": { + "default": 0, + "format": "int64", + "type": "integer" + }, + "usageVideos": { + "default": 0, + "format": "int64", + "type": "integer" + }, "videos": { "default": 0, "type": "integer" @@ -10987,6 +11170,8 @@ "photos", "usage", "usageByUser", + "usagePhotos", + "usageVideos", "videos" ], "type": "object" @@ -11148,7 +11333,11 @@ "type": "boolean" }, "type": { - "$ref": "#/components/schemas/SharedLinkType" + "allOf": [ + { + "$ref": "#/components/schemas/SharedLinkType" + } + ] } }, "required": [ @@ -11233,7 +11422,11 @@ "type": "string" }, "type": { - "$ref": "#/components/schemas/SharedLinkType" + "allOf": [ + { + "$ref": "#/components/schemas/SharedLinkType" + } + ] }, "userId": { "type": "string" @@ -11266,6 +11459,7 @@ "properties": { "email": { "example": "testuser@email.com", + "format": "email", "type": "string" }, "name": { @@ -11284,25 +11478,6 @@ ], "type": "object" }, - "SmartInfoResponseDto": { - "properties": { - "objects": { - "items": { - "type": "string" - }, - "nullable": true, - "type": "array" - }, - "tags": { - "items": { - "type": "string" - }, - "nullable": true, - "type": "array" - } - }, - "type": "object" - }, "SmartSearchDto": { "properties": { "city": { @@ -11401,7 +11576,11 @@ "type": "string" }, "type": { - "$ref": "#/components/schemas/AssetTypeEnum" + "allOf": [ + { + "$ref": "#/components/schemas/AssetTypeEnum" + } + ] }, "updatedAfter": { "format": "date-time", @@ -11442,6 +11621,7 @@ "format": "uuid", "type": "string" }, + "minItems": 2, "type": "array" } }, @@ -11542,6 +11722,9 @@ "storageTemplate": { "$ref": "#/components/schemas/SystemConfigStorageTemplateDto" }, + "templates": { + "$ref": "#/components/schemas/SystemConfigTemplatesDto" + }, "theme": { "$ref": "#/components/schemas/SystemConfigThemeDto" }, @@ -11569,6 +11752,7 @@ "reverseGeocoding", "server", "storageTemplate", + "templates", "theme", "trash", "user" @@ -11578,7 +11762,11 @@ "SystemConfigFFmpegDto": { "properties": { "accel": { - "$ref": "#/components/schemas/TranscodeHWAccel" + "allOf": [ + { + "$ref": "#/components/schemas/TranscodeHWAccel" + } + ] }, "accelDecode": { "type": "boolean" @@ -11607,7 +11795,11 @@ "type": "integer" }, "cqMode": { - "$ref": "#/components/schemas/CQMode" + "allOf": [ + { + "$ref": "#/components/schemas/CQMode" + } + ] }, "crf": { "maximum": 51, @@ -11621,10 +11813,6 @@ "maxBitrate": { "type": "string" }, - "npl": { - "minimum": 0, - "type": "integer" - }, "preferredHwDevice": { "type": "string" }, @@ -11637,13 +11825,21 @@ "type": "integer" }, "targetAudioCodec": { - "$ref": "#/components/schemas/AudioCodec" + "allOf": [ + { + "$ref": "#/components/schemas/AudioCodec" + } + ] }, "targetResolution": { "type": "string" }, "targetVideoCodec": { - "$ref": "#/components/schemas/VideoCodec" + "allOf": [ + { + "$ref": "#/components/schemas/VideoCodec" + } + ] }, "temporalAQ": { "type": "boolean" @@ -11653,10 +11849,18 @@ "type": "integer" }, "tonemap": { - "$ref": "#/components/schemas/ToneMapping" + "allOf": [ + { + "$ref": "#/components/schemas/ToneMapping" + } + ] }, "transcode": { - "$ref": "#/components/schemas/TranscodePolicy" + "allOf": [ + { + "$ref": "#/components/schemas/TranscodePolicy" + } + ] }, "twoPass": { "type": "boolean" @@ -11673,7 +11877,6 @@ "crf", "gopSize", "maxBitrate", - "npl", "preferredHwDevice", "preset", "refs", @@ -11702,7 +11905,11 @@ "SystemConfigGeneratedImageDto": { "properties": { "format": { - "$ref": "#/components/schemas/ImageFormat" + "allOf": [ + { + "$ref": "#/components/schemas/ImageFormat" + } + ] }, "quality": { "maximum": 100, @@ -11724,7 +11931,11 @@ "SystemConfigImageDto": { "properties": { "colorspace": { - "$ref": "#/components/schemas/Colorspace" + "allOf": [ + { + "$ref": "#/components/schemas/Colorspace" + } + ] }, "extractEmbedded": { "type": "boolean" @@ -11842,7 +12053,11 @@ "type": "boolean" }, "level": { - "$ref": "#/components/schemas/LogLevel" + "allOf": [ + { + "$ref": "#/components/schemas/LogLevel" + } + ] } }, "required": [ @@ -11866,7 +12081,18 @@ "$ref": "#/components/schemas/FacialRecognitionConfig" }, "url": { + "deprecated": true, + "description": "This property was deprecated in v1.122.0", "type": "string" + }, + "urls": { + "format": "uri", + "items": { + "format": "uri", + "type": "string" + }, + "minItems": 1, + "type": "array" } }, "required": [ @@ -11874,19 +12100,21 @@ "duplicateDetection", "enabled", "facialRecognition", - "url" + "urls" ], "type": "object" }, "SystemConfigMapDto": { "properties": { "darkStyle": { + "format": "uri", "type": "string" }, "enabled": { "type": "boolean" }, "lightStyle": { + "format": "uri", "type": "string" } }, @@ -11961,6 +12189,7 @@ "type": "boolean" }, "mobileRedirectUri": { + "format": "uri", "type": "string" }, "profileSigningAlgorithm": { @@ -12023,15 +12252,20 @@ "SystemConfigServerDto": { "properties": { "externalDomain": { + "format": "uri", "type": "string" }, "loginPageMessage": { "type": "string" + }, + "publicUsers": { + "type": "boolean" } }, "required": [ "externalDomain", - "loginPageMessage" + "loginPageMessage", + "publicUsers" ], "type": "object" }, @@ -12106,6 +12340,25 @@ ], "type": "object" }, + "SystemConfigTemplateEmailsDto": { + "properties": { + "albumInviteTemplate": { + "type": "string" + }, + "albumUpdateTemplate": { + "type": "string" + }, + "welcomeTemplate": { + "type": "string" + } + }, + "required": [ + "albumInviteTemplate", + "albumUpdateTemplate", + "welcomeTemplate" + ], + "type": "object" + }, "SystemConfigTemplateStorageOptionDto": { "properties": { "dayOptions": { @@ -12169,6 +12422,17 @@ ], "type": "object" }, + "SystemConfigTemplatesDto": { + "properties": { + "email": { + "$ref": "#/components/schemas/SystemConfigTemplateEmailsDto" + } + }, + "required": [ + "email" + ], + "type": "object" + }, "SystemConfigThemeDto": { "properties": { "customCss": { @@ -12245,6 +12509,7 @@ "TagCreateDto": { "properties": { "color": { + "pattern": "^#?([0-9A-F]{3}|[0-9A-F]{4}|[0-9A-F]{6}|[0-9A-F]{8})$", "type": "string" }, "name": { @@ -12300,6 +12565,7 @@ "properties": { "color": { "nullable": true, + "pattern": "^#?([0-9A-F]{3}|[0-9A-F]{4}|[0-9A-F]{6}|[0-9A-F]{8})$", "type": "string" } }, @@ -12347,6 +12613,32 @@ }, "type": "object" }, + "TemplateDto": { + "properties": { + "template": { + "type": "string" + } + }, + "required": [ + "template" + ], + "type": "object" + }, + "TemplateResponseDto": { + "properties": { + "html": { + "type": "string" + }, + "name": { + "type": "string" + } + }, + "required": [ + "html", + "name" + ], + "type": "object" + }, "TestEmailResponseDto": { "properties": { "messageId": { @@ -12436,7 +12728,11 @@ "type": "boolean" }, "order": { - "$ref": "#/components/schemas/AssetOrder" + "allOf": [ + { + "$ref": "#/components/schemas/AssetOrder" + } + ] } }, "type": "object" @@ -12444,7 +12740,11 @@ "UpdateAlbumUserDto": { "properties": { "role": { - "$ref": "#/components/schemas/AlbumUserRole" + "allOf": [ + { + "$ref": "#/components/schemas/AlbumUserRole" + } + ] } }, "required": [ @@ -12491,13 +12791,17 @@ "items": { "type": "string" }, - "type": "array" + "maxItems": 128, + "type": "array", + "uniqueItems": true }, "importPaths": { "items": { "type": "string" }, - "type": "array" + "maxItems": 128, + "type": "array", + "uniqueItems": true }, "name": { "type": "string" @@ -12530,6 +12834,14 @@ "format": "int64", "type": "integer" }, + "usagePhotos": { + "format": "int64", + "type": "integer" + }, + "usageVideos": { + "format": "int64", + "type": "integer" + }, "userId": { "type": "string" }, @@ -12544,6 +12856,8 @@ "photos", "quotaSizeInBytes", "usage", + "usagePhotos", + "usageVideos", "userId", "userName", "videos" @@ -12553,6 +12867,7 @@ "UserAdminCreateDto": { "properties": { "email": { + "format": "email", "type": "string" }, "name": { @@ -12596,7 +12911,11 @@ "UserAdminResponseDto": { "properties": { "avatarColor": { - "$ref": "#/components/schemas/UserAvatarColor" + "allOf": [ + { + "$ref": "#/components/schemas/UserAvatarColor" + } + ] }, "createdAt": { "format": "date-time", @@ -12651,7 +12970,11 @@ "type": "boolean" }, "status": { - "$ref": "#/components/schemas/UserStatus" + "allOf": [ + { + "$ref": "#/components/schemas/UserStatus" + } + ] }, "storageLabel": { "nullable": true, @@ -12686,6 +13009,7 @@ "UserAdminUpdateDto": { "properties": { "email": { + "format": "email", "type": "string" }, "name": { @@ -12823,7 +13147,11 @@ "UserResponseDto": { "properties": { "avatarColor": { - "$ref": "#/components/schemas/UserAvatarColor" + "allOf": [ + { + "$ref": "#/components/schemas/UserAvatarColor" + } + ] }, "email": { "type": "string" @@ -12863,6 +13191,7 @@ "UserUpdateMeDto": { "properties": { "email": { + "format": "email", "type": "string" }, "name": { @@ -12891,13 +13220,17 @@ "items": { "type": "string" }, - "type": "array" + "maxItems": 128, + "type": "array", + "uniqueItems": true }, "importPaths": { "items": { "type": "string" }, - "type": "array" + "maxItems": 128, + "type": "array", + "uniqueItems": true } }, "type": "object" diff --git a/open-api/typescript-sdk/.nvmrc b/open-api/typescript-sdk/.nvmrc index 7af24b7ddbde0..1d9b7831ba9d9 100644 --- a/open-api/typescript-sdk/.nvmrc +++ b/open-api/typescript-sdk/.nvmrc @@ -1 +1 @@ -22.11.0 +22.12.0 diff --git a/open-api/typescript-sdk/package-lock.json b/open-api/typescript-sdk/package-lock.json index 74bac2b924b99..bef7d9d690dbe 100644 --- a/open-api/typescript-sdk/package-lock.json +++ b/open-api/typescript-sdk/package-lock.json @@ -1,18 +1,18 @@ { "name": "@immich/sdk", - "version": "1.119.1", + "version": "1.123.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@immich/sdk", - "version": "1.119.1", + "version": "1.123.0", "license": "GNU Affero General Public License version 3", "dependencies": { "@oazapfts/runtime": "^1.0.2" }, "devDependencies": { - "@types/node": "^22.8.1", + "@types/node": "^22.10.2", "typescript": "^5.3.3" } }, @@ -22,13 +22,13 @@ "integrity": "sha512-8tKiYffhwTGHSHYGnZ3oneLGCjX0po/XAXQ5Ng9fqKkvIdl/xz8+Vh8i+6xjzZqvZ2pLVpUcuSfnvNI/x67L0g==" }, "node_modules/@types/node": { - "version": "22.8.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.8.5.tgz", - "integrity": "sha512-5iYk6AMPtsMbkZqCO1UGF9W5L38twq11S2pYWkybGHH2ogPUvXWNlQqJBzuEZWKj/WRH+QTeiv6ySWqJtvIEgA==", + "version": "22.10.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.2.tgz", + "integrity": "sha512-Xxr6BBRCAOQixvonOye19wnzyDiUtTeqldOOmj3CkeblonbccA12PFwlufvRdrpjXxqnmUaeiU5EOA+7s5diUQ==", "dev": true, "license": "MIT", "dependencies": { - "undici-types": "~6.19.8" + "undici-types": "~6.20.0" } }, "node_modules/typescript": { @@ -46,9 +46,9 @@ } }, "node_modules/undici-types": { - "version": "6.19.8", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", - "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", + "version": "6.20.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", + "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", "dev": true, "license": "MIT" } diff --git a/open-api/typescript-sdk/package.json b/open-api/typescript-sdk/package.json index 726c63da8eecd..01a7543a69c97 100644 --- a/open-api/typescript-sdk/package.json +++ b/open-api/typescript-sdk/package.json @@ -1,6 +1,6 @@ { "name": "@immich/sdk", - "version": "1.119.1", + "version": "1.123.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.8.1", + "@types/node": "^22.10.2", "typescript": "^5.3.3" }, "repository": { @@ -28,6 +28,6 @@ "directory": "open-api/typescript-sdk" }, "volta": { - "node": "22.11.0" + "node": "22.12.0" } } diff --git a/open-api/typescript-sdk/src/fetch-client.ts b/open-api/typescript-sdk/src/fetch-client.ts index 23181554739ae..c31e71d05e961 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.119.1 + * 1.123.0 * DO NOT MODIFY - This file has been generated using oazapfts. * See https://www.npmjs.com/package/oazapfts */ @@ -221,10 +221,6 @@ export type PersonWithFacesResponseDto = { /** This property was added in v1.107.0 */ updatedAt?: string; }; -export type SmartInfoResponseDto = { - objects?: string[] | null; - tags?: string[] | null; -}; export type AssetStackResponseDto = { assetCount: number; id: string; @@ -267,7 +263,6 @@ export type AssetResponseDto = { people?: PersonWithFacesResponseDto[]; /** This property was deprecated in v1.113.0 */ resized?: boolean; - smartInfo?: SmartInfoResponseDto; stack?: (AssetStackResponseDto) | null; tags?: TagResponseDto[]; thumbhash: string | null; @@ -639,6 +634,13 @@ export type MemoryUpdateDto = { memoryAt?: string; seenAt?: string; }; +export type TemplateDto = { + template: string; +}; +export type TemplateResponseDto = { + html: string; + name: string; +}; export type SystemConfigSmtpTransportDto = { host: string; ignoreCert: boolean; @@ -933,6 +935,7 @@ export type ServerConfigDto = { mapDarkStyleUrl: string; mapLightStyleUrl: string; oauthButtonText: string; + publicUsers: boolean; trashDays: number; userDeleteDelay: number; }; @@ -974,6 +977,8 @@ export type UsageByUserDto = { photos: number; quotaSizeInBytes: number | null; usage: number; + usagePhotos: number; + usageVideos: number; userId: string; userName: string; videos: number; @@ -982,6 +987,8 @@ export type ServerStatsResponseDto = { photos: number; usage: number; usageByUser: UsageByUserDto[]; + usagePhotos: number; + usageVideos: number; videos: number; }; export type ServerStorageResponseDto = { @@ -1104,7 +1111,6 @@ export type SystemConfigFFmpegDto = { crf: number; gopSize: number; maxBitrate: string; - npl: number; preferredHwDevice: string; preset: string; refs: number; @@ -1179,7 +1185,9 @@ export type SystemConfigMachineLearningDto = { duplicateDetection: DuplicateDetectionConfig; enabled: boolean; facialRecognition: FacialRecognitionConfig; - url: string; + /** This property was deprecated in v1.122.0 */ + url?: string; + urls: string[]; }; export type SystemConfigMapDto = { darkStyle: string; @@ -1224,12 +1232,21 @@ export type SystemConfigReverseGeocodingDto = { export type SystemConfigServerDto = { externalDomain: string; loginPageMessage: string; + publicUsers: boolean; }; export type SystemConfigStorageTemplateDto = { enabled: boolean; hashVerificationEnabled: boolean; template: string; }; +export type SystemConfigTemplateEmailsDto = { + albumInviteTemplate: string; + albumUpdateTemplate: string; + welcomeTemplate: string; +}; +export type SystemConfigTemplatesDto = { + email: SystemConfigTemplateEmailsDto; +}; export type SystemConfigThemeDto = { customCss: string; }; @@ -1257,6 +1274,7 @@ export type SystemConfigDto = { reverseGeocoding: SystemConfigReverseGeocodingDto; server: SystemConfigServerDto; storageTemplate: SystemConfigStorageTemplateDto; + templates: SystemConfigTemplatesDto; theme: SystemConfigThemeDto; trash: SystemConfigTrashDto; user: SystemConfigUserDto; @@ -2225,6 +2243,19 @@ export function addMemoryAssets({ id, bulkIdsDto }: { body: bulkIdsDto }))); } +export function getNotificationTemplate({ name, templateDto }: { + name: string; + templateDto: TemplateDto; +}, opts?: Oazapfts.RequestOpts) { + return oazapfts.ok(oazapfts.fetchJson<{ + status: 200; + data: TemplateResponseDto; + }>(`/notifications/templates/${encodeURIComponent(name)}`, oazapfts.json({ + ...opts, + method: "POST", + body: templateDto + }))); +} export function sendTestEmail({ systemConfigSmtpDto }: { systemConfigSmtpDto: SystemConfigSmtpDto; }, opts?: Oazapfts.RequestOpts) { @@ -2331,7 +2362,9 @@ export function updatePartner({ id, updatePartnerDto }: { body: updatePartnerDto }))); } -export function getAllPeople({ page, size, withHidden }: { +export function getAllPeople({ closestAssetId, closestPersonId, page, size, withHidden }: { + closestAssetId?: string; + closestPersonId?: string; page?: number; size?: number; withHidden?: boolean; @@ -2340,6 +2373,8 @@ export function getAllPeople({ page, size, withHidden }: { status: 200; data: PeopleResponseDto; }>(`/people${QS.query(QS.explode({ + closestAssetId, + closestPersonId, page, size, withHidden @@ -2485,7 +2520,7 @@ export function getExploreData(opts?: Oazapfts.RequestOpts) { ...opts })); } -export function searchMetadata({ metadataSearchDto }: { +export function searchAssets({ metadataSearchDto }: { metadataSearchDto: MetadataSearchDto; }, opts?: Oazapfts.RequestOpts) { return oazapfts.ok(oazapfts.fetchJson<{ diff --git a/server/.nvmrc b/server/.nvmrc index 7af24b7ddbde0..1d9b7831ba9d9 100644 --- a/server/.nvmrc +++ b/server/.nvmrc @@ -1 +1 @@ -22.11.0 +22.12.0 diff --git a/server/Dockerfile b/server/Dockerfile index f14178dd9fff0..3b2ac262d0702 100644 --- a/server/Dockerfile +++ b/server/Dockerfile @@ -1,5 +1,5 @@ # dev build -FROM ghcr.io/immich-app/base-server-dev:20241029@sha256:31c2d6cba42253680ff7738dffa66e97dfe5b1c7faf23b29d07ab456e9c1e2b9 AS dev +FROM ghcr.io/immich-app/base-server-dev:20241217@sha256:7e69fa317cf90a0345927bbea13438dc39efc584bac13ff77ea5735c57cd008a AS dev RUN apt-get install --no-install-recommends -yqq tini WORKDIR /usr/src/app @@ -25,7 +25,7 @@ COPY --from=dev /usr/src/app/node_modules/@img ./node_modules/@img COPY --from=dev /usr/src/app/node_modules/exiftool-vendored.pl ./node_modules/exiftool-vendored.pl # web build -FROM node:22.10.0-alpine3.20@sha256:fc95a044b87e95507c60c1f8c829e5d98ddf46401034932499db370c494ef0ff AS web +FROM node:22.12.0-alpine3.20@sha256:96cc8323e25c8cc6ddcb8b965e135cfd57846e8003ec0d7bcec16c5fd5f6d39f AS web WORKDIR /usr/src/open-api/typescript-sdk COPY open-api/typescript-sdk/package*.json open-api/typescript-sdk/tsconfig*.json ./ @@ -42,7 +42,7 @@ RUN npm run build # prod build -FROM ghcr.io/immich-app/base-server-prod:20241029@sha256:669cc57091e3d2924b9e3001acb4998ed9c9585370017adcdf7beed21d249aae +FROM ghcr.io/immich-app/base-server-prod:20241217@sha256:040c83a6d3e45755419837747fa70fa68cf92433d483c116a971b3400bb8415d WORKDIR /usr/src/app ENV NODE_ENV=production \ diff --git a/server/bin/immich-healthcheck b/server/bin/immich-healthcheck index cf0accb8ddb32..81528157e4ae6 100755 --- a/server/bin/immich-healthcheck +++ b/server/bin/immich-healthcheck @@ -1,3 +1,22 @@ #!/usr/bin/env bash -node /usr/src/app/dist/bin/healthcheck.js +if [[ ( $IMMICH_WORKERS_INCLUDE != '' && $IMMICH_WORKERS_INCLUDE != *api* ) || $IMMICH_WORKERS_EXCLUDE == *api* ]]; then + echo "API worker excluded, skipping"; + exit 0; +fi + +IMMICH_HOST="${IMMICH_HOST:-localhost}" +IMMICH_PORT="${IMMICH_PORT:-2283}" + +result=$(curl -fsS -m 2 http://"$IMMICH_HOST":"$IMMICH_PORT"/api/server/ping) +result_exit=$? + +if [ $result_exit != 0 ]; then + echo "Fail: exit code is $result_exit"; + exit 1; +fi + +if [ "$result" != "{\"res\":\"pong\"}" ]; then + echo "Fail: didn't reply with pong"; + exit 1; +fi diff --git a/server/package-lock.json b/server/package-lock.json index eb428e2eac0da..3bdc0dc3dab5c 100644 --- a/server/package-lock.json +++ b/server/package-lock.json @@ -1,12 +1,12 @@ { "name": "immich", - "version": "1.119.1", - "lockfileVersion": 2, + "version": "1.123.0", + "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "immich", - "version": "1.119.1", + "version": "1.123.0", "license": "GNU Affero General Public License version 3", "dependencies": { "@nestjs/bullmq": "^10.0.1", @@ -16,14 +16,14 @@ "@nestjs/platform-express": "^10.2.2", "@nestjs/platform-socket.io": "^10.2.2", "@nestjs/schedule": "^4.0.0", - "@nestjs/swagger": "^7.1.8", + "@nestjs/swagger": "^8.0.0", "@nestjs/typeorm": "^10.0.0", "@nestjs/websockets": "^10.2.2", - "@opentelemetry/auto-instrumentations-node": "^0.52.0", + "@opentelemetry/auto-instrumentations-node": "^0.54.0", "@opentelemetry/context-async-hooks": "^1.24.0", - "@opentelemetry/exporter-prometheus": "^0.54.0", - "@opentelemetry/sdk-node": "^0.54.0", - "@react-email/components": "^0.0.25", + "@opentelemetry/exporter-prometheus": "^0.56.0", + "@opentelemetry/sdk-node": "^0.56.0", + "@react-email/components": "^0.0.31", "@socket.io/redis-adapter": "^8.3.0", "archiver": "^7.0.0", "async-lock": "^1.4.0", @@ -51,8 +51,8 @@ "openid-client": "^5.4.3", "pg": "^8.11.3", "picomatch": "^4.0.2", - "react": "^18.3.1", - "react-email": "^3.0.0", + "react": "^19.0.0", + "react-email": "^3.0.4", "reflect-metadata": "^0.2.0", "rxjs": "^7.8.1", "sanitize-filename": "^1.6.3", @@ -83,21 +83,21 @@ "@types/lodash": "^4.14.197", "@types/mock-fs": "^4.13.1", "@types/multer": "^1.4.7", - "@types/node": "^22.8.1", + "@types/node": "^22.10.2", "@types/nodemailer": "^6.4.14", "@types/picomatch": "^3.0.0", "@types/pngjs": "^6.0.5", - "@types/react": "^18.3.4", + "@types/react": "^19.0.0", "@types/semver": "^7.5.8", "@types/supertest": "^6.0.0", "@types/ua-parser-js": "^0.7.36", - "@typescript-eslint/eslint-plugin": "^8.0.0", - "@typescript-eslint/parser": "^8.0.0", + "@typescript-eslint/eslint-plugin": "^8.15.0", + "@typescript-eslint/parser": "^8.15.0", "@vitest/coverage-v8": "^2.0.5", - "eslint": "^9.0.0", + "eslint": "^9.14.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-prettier": "^5.1.3", - "eslint-plugin-unicorn": "^55.0.0", + "eslint-plugin-unicorn": "^56.0.1", "globals": "^15.9.0", "mock-fs": "^5.2.0", "pngjs": "^7.0.0", @@ -114,19 +114,11 @@ "vitest": "^2.0.5" } }, - "node_modules/@aashutoshrathi/word-wrap": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", - "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/@alloc/quick-lru": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", + "license": "MIT", "peer": true, "engines": { "node": ">=10" @@ -139,6 +131,7 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", + "license": "Apache-2.0", "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" @@ -148,10 +141,11 @@ } }, "node_modules/@angular-devkit/core": { - "version": "17.3.8", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-17.3.8.tgz", - "integrity": "sha512-Q8q0voCGudbdCgJ7lXdnyaxKHbNQBARH68zPQV72WT8NWy+Gw/tys870i6L58NWbBaCJEUcIj/kb6KoakSRu+Q==", + "version": "17.3.11", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-17.3.11.tgz", + "integrity": "sha512-vTNDYNsLIWpYk2I969LMQFH29GTsLzxNk/0cLw5q56ARF0v5sIWfHYwGTS88jdDqIpuuettcSczbxeA7EuAmqQ==", "dev": true, + "license": "MIT", "dependencies": { "ajv": "8.12.0", "ajv-formats": "2.1.1", @@ -174,11 +168,36 @@ } } }, + "node_modules/@angular-devkit/core/node_modules/ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@angular-devkit/core/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true, + "license": "MIT" + }, "node_modules/@angular-devkit/core/node_modules/picomatch": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.1.tgz", "integrity": "sha512-xUXwsxNjwTQ8K3GnT4pCJm+xq3RUPQbmkYJTP5aFIfNIvbcc/4MUxgBaaRSZJ6yGJZiGSyYlM6MzwTsRk8SYCg==", "dev": true, + "license": "MIT", "engines": { "node": ">=12" }, @@ -187,12 +206,13 @@ } }, "node_modules/@angular-devkit/schematics": { - "version": "17.3.8", - "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-17.3.8.tgz", - "integrity": "sha512-QRVEYpIfgkprNHc916JlPuNbLzOgrm9DZalHasnLUz4P6g7pR21olb8YCyM2OTJjombNhya9ZpckcADU5Qyvlg==", + "version": "17.3.11", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-17.3.11.tgz", + "integrity": "sha512-I5wviiIqiFwar9Pdk30Lujk8FczEEc18i22A5c6Z9lbmhPQdTroDnEQdsfXjy404wPe8H62s0I15o4pmMGfTYQ==", "dev": true, + "license": "MIT", "dependencies": { - "@angular-devkit/core": "17.3.8", + "@angular-devkit/core": "17.3.11", "jsonc-parser": "3.2.1", "magic-string": "0.30.8", "ora": "5.4.1", @@ -205,13 +225,14 @@ } }, "node_modules/@angular-devkit/schematics-cli": { - "version": "17.3.8", - "resolved": "https://registry.npmjs.org/@angular-devkit/schematics-cli/-/schematics-cli-17.3.8.tgz", - "integrity": "sha512-TjmiwWJarX7oqvNiRAroQ5/LeKUatxBOCNEuKXO/PV8e7pn/Hr/BqfFm+UcYrQoFdZplmtNAfqmbqgVziKvCpA==", + "version": "17.3.11", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics-cli/-/schematics-cli-17.3.11.tgz", + "integrity": "sha512-kcOMqp+PHAKkqRad7Zd7PbpqJ0LqLaNZdY1+k66lLWmkEBozgq8v4ASn/puPWf9Bo0HpCiK+EzLf0VHE8Z/y6Q==", "dev": true, + "license": "MIT", "dependencies": { - "@angular-devkit/core": "17.3.8", - "@angular-devkit/schematics": "17.3.8", + "@angular-devkit/core": "17.3.11", + "@angular-devkit/schematics": "17.3.11", "ansi-colors": "4.1.3", "inquirer": "9.2.15", "symbol-observable": "4.0.0", @@ -231,6 +252,7 @@ "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", "dev": true, + "license": "MIT", "engines": { "node": "^12.17.0 || ^14.13 || >=16.0.0" }, @@ -243,6 +265,7 @@ "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.1.0.tgz", "integrity": "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==", "dev": true, + "license": "ISC", "engines": { "node": ">= 12" } @@ -252,6 +275,7 @@ "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-9.2.15.tgz", "integrity": "sha512-vI2w4zl/mDluHt9YEQ/543VTCwPKWiHzKtm9dM2V0NdFcqEexDAjUHzO1oA60HRNaVifGXXM1tRRNluLVHa0Kg==", "dev": true, + "license": "MIT", "dependencies": { "@ljharb/through": "^2.3.12", "ansi-escapes": "^4.3.2", @@ -278,6 +302,7 @@ "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-1.0.0.tgz", "integrity": "sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==", "dev": true, + "license": "ISC", "engines": { "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } @@ -287,16 +312,19 @@ "resolved": "https://registry.npmjs.org/run-async/-/run-async-3.0.0.tgz", "integrity": "sha512-540WwVDOMxA6dN6We19EcT9sc3hkXPw5mzRNGM3FkdN/vtE9NFvj5lFAPNwUDmJjXidm3v7TC1cTE7t17Ulm1Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.12.0" } }, "node_modules/@babel/code-frame": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.6.tgz", - "integrity": "sha512-ZJhac6FkEd1yhG2AHOmfcXG4ceoLltoCVJjN5XsWN9BifBQr+cHJbWi0h68HZuSORq+3WtJ2z0hwF2NG1b5kcA==", + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", + "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", + "license": "MIT", "dependencies": { - "@babel/highlight": "^7.24.6", + "@babel/helper-validator-identifier": "^7.25.9", + "js-tokens": "^4.0.0", "picocolors": "^1.0.0" }, "engines": { @@ -304,9 +332,10 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.24.6.tgz", - "integrity": "sha512-aC2DGhBq5eEdyXWqrDInSqQjO0k8xtPRf5YylULqx8MCd6jBtzqfta/3ETMRpuKIc5hyswfO80ObyA1MvkCcUQ==", + "version": "7.26.3", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.3.tgz", + "integrity": "sha512-nHIxvKPniQXpmQLb0vhY3VaFb3S0YrTAwpOWJZh1wn3oJPjJk9Asva204PsBdmAE8vpzfHudT8DB0scYvy9q0g==", + "license": "MIT", "engines": { "node": ">=6.9.0" } @@ -315,6 +344,7 @@ "version": "7.24.5", "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.5.tgz", "integrity": "sha512-tVQRucExLQ02Boi4vdPp49svNGcfL2GhdTCT9aldhXgCJVAI21EtRfBettiuLUwce/7r6bFdgs6JFkcdTiFttA==", + "license": "MIT", "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.24.2", @@ -344,43 +374,36 @@ "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "license": "ISC", "bin": { "semver": "bin/semver.js" } }, "node_modules/@babel/generator": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.6.tgz", - "integrity": "sha512-S7m4eNa6YAPJRHmKsLHIDJhNAGNKoWNiWefz1MBbpnt8g9lvMDl1hir4P9bo/57bQEmuwEhnRU/AMWsD0G/Fbg==", + "version": "7.26.3", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.3.tgz", + "integrity": "sha512-6FF/urZvD0sTeO7k6/B15pMLC4CHUv1426lzr3N01aHJTl046uCAh9LXW/fzeXXjPNCJ6iABW5XaWOsIZB93aQ==", + "license": "MIT", "dependencies": { - "@babel/types": "^7.24.6", + "@babel/parser": "^7.26.3", + "@babel/types": "^7.26.3", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", - "jsesc": "^2.5.1" + "jsesc": "^3.0.2" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/generator/node_modules/jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.24.6.tgz", - "integrity": "sha512-VZQ57UsDGlX/5fFA7GkVPplZhHsVc+vuErWgdOiysI9Ksnw0Pbbd6pnPiR/mmJyKHgyIW0c7KT32gmhiF+cirg==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.9.tgz", + "integrity": "sha512-j9Db8Suy6yV/VHa4qzrj9yZfZxhLWQdVnRlXxmKLYlhWUVB1sB2G5sxuWYXk/whHD9iW76PmNzxZ4UCnTQTVEQ==", + "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.24.6", - "@babel/helper-validator-option": "^7.24.6", - "browserslist": "^4.22.2", + "@babel/compat-data": "^7.25.9", + "@babel/helper-validator-option": "^7.25.9", + "browserslist": "^4.24.0", "lru-cache": "^5.1.1", "semver": "^6.3.1" }, @@ -388,66 +411,52 @@ "node": ">=6.9.0" } }, + "node_modules/@babel/helper-compilation-targets/node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" + } + }, "node_modules/@babel/helper-compilation-targets/node_modules/semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "license": "ISC", "bin": { "semver": "bin/semver.js" } }, - "node_modules/@babel/helper-environment-visitor": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.24.6.tgz", - "integrity": "sha512-Y50Cg3k0LKLMjxdPjIl40SdJgMB85iXn27Vk/qbHZCFx/o5XO3PSnpi675h1KEmmDb6OFArfd5SCQEQ5Q4H88g==", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-function-name": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.24.6.tgz", - "integrity": "sha512-xpeLqeeRkbxhnYimfr2PC+iA0Q7ljX/d1eZ9/inYbmfG2jpl8Lu3DyXvpOAnrS5kxkfOWJjioIMQsaMBXFI05w==", - "dependencies": { - "@babel/template": "^7.24.6", - "@babel/types": "^7.24.6" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-hoist-variables": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.24.6.tgz", - "integrity": "sha512-SF/EMrC3OD7dSta1bLJIlrsVxwtd0UpjRJqLno6125epQMJ/kyFmpTT4pbvPbdQHzCHg+biQ7Syo8lnDtbR+uA==", - "dependencies": { - "@babel/types": "^7.24.6" - }, - "engines": { - "node": ">=6.9.0" - } + "node_modules/@babel/helper-compilation-targets/node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "license": "ISC" }, "node_modules/@babel/helper-module-imports": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.6.tgz", - "integrity": "sha512-a26dmxFJBF62rRO9mmpgrfTLsAuyHk4e1hKTUkD/fcMfynt8gvEKwQPQDVxWhca8dHoDck+55DFt42zV0QMw5g==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz", + "integrity": "sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==", + "license": "MIT", "dependencies": { - "@babel/types": "^7.24.6" + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.24.6.tgz", - "integrity": "sha512-Y/YMPm83mV2HJTbX1Qh2sjgjqcacvOlhbzdCCsSlblOKjSYmQqEbO6rUniWQyRo9ncyfjT8hnUjlG06RXDEmcA==", + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz", + "integrity": "sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==", + "license": "MIT", "dependencies": { - "@babel/helper-environment-visitor": "^7.24.6", - "@babel/helper-module-imports": "^7.24.6", - "@babel/helper-simple-access": "^7.24.6", - "@babel/helper-split-export-declaration": "^7.24.6", - "@babel/helper-validator-identifier": "^7.24.6" + "@babel/helper-module-imports": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9", + "@babel/traverse": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -456,146 +465,54 @@ "@babel/core": "^7.0.0" } }, - "node_modules/@babel/helper-simple-access": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.24.6.tgz", - "integrity": "sha512-nZzcMMD4ZhmB35MOOzQuiGO5RzL6tJbsT37Zx8M5L/i9KSrukGXWTjLe1knIbb/RmxoJE9GON9soq0c0VEMM5g==", - "dependencies": { - "@babel/types": "^7.24.6" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-split-export-declaration": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.6.tgz", - "integrity": "sha512-CvLSkwXGWnYlF9+J3iZUvwgAxKiYzK3BWuo+mLzD/MDGOZDj7Gq8+hqaOkMxmJwmlv0iu86uH5fdADd9Hxkymw==", - "dependencies": { - "@babel/types": "^7.24.6" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/helper-string-parser": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.6.tgz", - "integrity": "sha512-WdJjwMEkmBicq5T9fm/cHND3+UlFa2Yj8ALLgmoSQAJZysYbBjw+azChSGPN4DSPLXOcooGRvDwZWMcF/mLO2Q==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", + "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.6.tgz", - "integrity": "sha512-4yA7s865JHaqUdRbnaxarZREuPTHrjpDT+pXoAZ1yhyo6uFnIEpS8VMu16siFOHDpZNKYv5BObhsB//ycbICyw==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", + "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-option": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.24.6.tgz", - "integrity": "sha512-Jktc8KkF3zIkePb48QO+IapbXlSapOW9S+ogZZkcO6bABgYAxtZcjZ/O005111YLf+j4M84uEgwYoidDkXbCkQ==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz", + "integrity": "sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==", + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helpers": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.6.tgz", - "integrity": "sha512-V2PI+NqnyFu1i0GyTd/O/cTpxzQCYioSkUIRmgo7gFEHKKCg5w46+r/A6WeUR1+P3TeQ49dspGPNd/E3n9AnnA==", - "dependencies": { - "@babel/template": "^7.24.6", - "@babel/types": "^7.24.6" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.6.tgz", - "integrity": "sha512-2YnuOp4HAk2BsBrJJvYCbItHx0zWscI1C3zgWkz+wDyD9I7GIVrfnLyrR4Y1VR+7p+chAEcrgRQYZAGIKMV7vQ==", + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.26.0.tgz", + "integrity": "sha512-tbhNuIxNcVb21pInl3ZSjksLCvgdZy9KwJ8brv993QtIVKJBBkYXz4q4ZbAv31GdnC+R90np23L5FbEBlthAEw==", + "license": "MIT", "dependencies": { - "@babel/helper-validator-identifier": "^7.24.6", - "chalk": "^2.4.2", - "js-tokens": "^4.0.0", - "picocolors": "^1.0.0" + "@babel/template": "^7.25.9", + "@babel/types": "^7.26.0" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/highlight/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/@babel/highlight/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" - }, - "node_modules/@babel/highlight/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/@babel/highlight/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "node_modules/@babel/parser": { + "version": "7.26.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.3.tgz", + "integrity": "sha512-WJ/CvmY8Mea8iDXo6a7RK2wbmJITT5fN3BEkRuFlxVyNx8jOKIIhmC4fSkTcPcf8JyavbBwIe6OpiCOBXt/IcA==", + "license": "MIT", "dependencies": { - "has-flag": "^3.0.0" + "@babel/types": "^7.26.3" }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/parser": { - "version": "7.24.5", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.5.tgz", - "integrity": "sha512-EOv5IK8arwh3LI47dz1b0tKUb/1uhHAnHJOrjgtQMIpu1uXd9mlFrJg9IUgGUgZ41Ch0K8REPTYpO7B76b4vJg==", "bin": { "parser": "bin/babel-parser.js" }, @@ -604,42 +521,30 @@ } }, "node_modules/@babel/template": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.24.6.tgz", - "integrity": "sha512-3vgazJlLwNXi9jhrR1ef8qiB65L1RK90+lEQwv4OxveHnqC3BfmnHdgySwRLzf6akhlOYenT+b7AfWq+a//AHw==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.9.tgz", + "integrity": "sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg==", + "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.24.6", - "@babel/parser": "^7.24.6", - "@babel/types": "^7.24.6" + "@babel/code-frame": "^7.25.9", + "@babel/parser": "^7.25.9", + "@babel/types": "^7.25.9" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/template/node_modules/@babel/parser": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.6.tgz", - "integrity": "sha512-eNZXdfU35nJC2h24RznROuOpO94h6x8sg9ju0tT9biNtLZ2vuP8SduLqqV+/8+cebSLV9SJEAN5Z3zQbJG/M+Q==", - "bin": { - "parser": "bin/babel-parser.js" - }, - "engines": { - "node": ">=6.0.0" - } - }, "node_modules/@babel/traverse": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.6.tgz", - "integrity": "sha512-OsNjaJwT9Zn8ozxcfoBc+RaHdj3gFmCmYoQLUII1o6ZrUwku0BMg80FoOTPx+Gi6XhcQxAYE4xyjPTo4SxEQqw==", - "dependencies": { - "@babel/code-frame": "^7.24.6", - "@babel/generator": "^7.24.6", - "@babel/helper-environment-visitor": "^7.24.6", - "@babel/helper-function-name": "^7.24.6", - "@babel/helper-hoist-variables": "^7.24.6", - "@babel/helper-split-export-declaration": "^7.24.6", - "@babel/parser": "^7.24.6", - "@babel/types": "^7.24.6", + "version": "7.26.4", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.26.4.tgz", + "integrity": "sha512-fH+b7Y4p3yqvApJALCPJcwb0/XaOSgtK4pzV6WVjPR5GLFQBRI7pfoX2V2iM48NXvX07NUxxm1Vw98YjqTcU5w==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.26.2", + "@babel/generator": "^7.26.3", + "@babel/parser": "^7.26.3", + "@babel/template": "^7.25.9", + "@babel/types": "^7.26.3", "debug": "^4.3.1", "globals": "^11.1.0" }, @@ -647,33 +552,23 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/traverse/node_modules/@babel/parser": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.6.tgz", - "integrity": "sha512-eNZXdfU35nJC2h24RznROuOpO94h6x8sg9ju0tT9biNtLZ2vuP8SduLqqV+/8+cebSLV9SJEAN5Z3zQbJG/M+Q==", - "bin": { - "parser": "bin/babel-parser.js" - }, - "engines": { - "node": ">=6.0.0" - } - }, "node_modules/@babel/traverse/node_modules/globals": { "version": "11.12.0", "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "license": "MIT", "engines": { "node": ">=4" } }, "node_modules/@babel/types": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.6.tgz", - "integrity": "sha512-WaMsgi6Q8zMgMth93GvWPXkhAIEobfsIkLTacoVZoK1J0CevIPGYY2Vo5YvJGqyHqXM6P4ppOYGsIRU8MM9pFQ==", + "version": "7.26.3", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.3.tgz", + "integrity": "sha512-vN5p+1kl59GVKMvTHt55NzzmYVxprfJD+ql7U9NFIfKCBkYE55LYtS+WtPlaYOyzydrKI8Nezd+aZextrd+FMA==", + "license": "MIT", "dependencies": { - "@babel/helper-string-parser": "^7.24.6", - "@babel/helper-validator-identifier": "^7.24.6", - "to-fast-properties": "^2.0.0" + "@babel/helper-string-parser": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -683,65 +578,45 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/@balena/dockerignore/-/dockerignore-1.0.2.tgz", "integrity": "sha512-wMue2Sy4GAVTk6Ic4tJVcnfdau+gx2EnG7S+uAEe+TWJFqE4YoWN4/H8MSLj4eYJKxGg26lZwboEniNiNwZQ6Q==", - "dev": true + "dev": true, + "license": "Apache-2.0" }, "node_modules/@bcoe/v8-coverage": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@colors/colors": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", "dev": true, + "license": "MIT", "optional": true, "engines": { "node": ">=0.1.90" } }, - "node_modules/@cspotcode/source-map-support": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", - "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", - "optional": true, - "peer": true, - "dependencies": { - "@jridgewell/trace-mapping": "0.3.9" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", - "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", - "optional": true, - "peer": true, - "dependencies": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" - } - }, "node_modules/@emnapi/runtime": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.2.0.tgz", - "integrity": "sha512-bV21/9LQmcQeCPEg3BDFtvwL6cwiTMksYNWQQ4KOxCZikEGalWtenoZ0wCiukJINlGCIi2KXx01g4FoH/LxpzQ==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.3.1.tgz", + "integrity": "sha512-kEBmG8KyqtxJZv+ygbEim+KCGtIq1fC22Ms3S4ziXmYKm8uyoLX0MHONVKwp+9opg390VaKRNt4a7A9NwmpNhw==", + "license": "MIT", "optional": true, "dependencies": { "tslib": "^2.4.0" } }, "node_modules/@esbuild/aix-ppc64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", - "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.19.11.tgz", + "integrity": "sha512-FnzU0LyE3ySQk7UntJO4+qIiQgI7KoODnZg5xzXIrFJlKd2P2gwHsHY4927xj9y5PJmJSzULiUCWmv7iWnNa7g==", "cpu": [ "ppc64" ], - "dev": true, + "license": "MIT", "optional": true, "os": [ "aix" @@ -751,13 +626,13 @@ } }, "node_modules/@esbuild/android-arm": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", - "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.11.tgz", + "integrity": "sha512-5OVapq0ClabvKvQ58Bws8+wkLCV+Rxg7tUVbo9xu034Nm536QTII4YzhaFriQ7rMrorfnFKUsArD2lqKbFY4vw==", "cpu": [ "arm" ], - "dev": true, + "license": "MIT", "optional": true, "os": [ "android" @@ -767,13 +642,13 @@ } }, "node_modules/@esbuild/android-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", - "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.19.11.tgz", + "integrity": "sha512-aiu7K/5JnLj//KOnOfEZ0D90obUkRzDMyqd/wNAUQ34m4YUPVhRZpnqKV9uqDGxT7cToSDnIHsGooyIczu9T+Q==", "cpu": [ "arm64" ], - "dev": true, + "license": "MIT", "optional": true, "os": [ "android" @@ -783,13 +658,13 @@ } }, "node_modules/@esbuild/android-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", - "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.19.11.tgz", + "integrity": "sha512-eccxjlfGw43WYoY9QgB82SgGgDbibcqyDTlk3l3C0jOVHKxrjdc9CTwDUQd0vkvYg5um0OH+GpxYvp39r+IPOg==", "cpu": [ "x64" ], - "dev": true, + "license": "MIT", "optional": true, "os": [ "android" @@ -799,13 +674,13 @@ } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", - "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.11.tgz", + "integrity": "sha512-ETp87DRWuSt9KdDVkqSoKoLFHYTrkyz2+65fj9nfXsaV3bMhTCjtQfw3y+um88vGRKRiF7erPrh/ZuIdLUIVxQ==", "cpu": [ "arm64" ], - "dev": true, + "license": "MIT", "optional": true, "os": [ "darwin" @@ -815,13 +690,13 @@ } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", - "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.19.11.tgz", + "integrity": "sha512-fkFUiS6IUK9WYUO/+22omwetaSNl5/A8giXvQlcinLIjVkxwTLSktbF5f/kJMftM2MJp9+fXqZ5ezS7+SALp4g==", "cpu": [ "x64" ], - "dev": true, + "license": "MIT", "optional": true, "os": [ "darwin" @@ -831,13 +706,13 @@ } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", - "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.11.tgz", + "integrity": "sha512-lhoSp5K6bxKRNdXUtHoNc5HhbXVCS8V0iZmDvyWvYq9S5WSfTIHU2UGjcGt7UeS6iEYp9eeymIl5mJBn0yiuxA==", "cpu": [ "arm64" ], - "dev": true, + "license": "MIT", "optional": true, "os": [ "freebsd" @@ -847,13 +722,13 @@ } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", - "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.19.11.tgz", + "integrity": "sha512-JkUqn44AffGXitVI6/AbQdoYAq0TEullFdqcMY/PCUZ36xJ9ZJRtQabzMA+Vi7r78+25ZIBosLTOKnUXBSi1Kw==", "cpu": [ "x64" ], - "dev": true, + "license": "MIT", "optional": true, "os": [ "freebsd" @@ -863,13 +738,13 @@ } }, "node_modules/@esbuild/linux-arm": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", - "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.19.11.tgz", + "integrity": "sha512-3CRkr9+vCV2XJbjwgzjPtO8T0SZUmRZla+UL1jw+XqHZPkPgZiyWvbDvl9rqAN8Zl7qJF0O/9ycMtjU67HN9/Q==", "cpu": [ "arm" ], - "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -879,13 +754,13 @@ } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", - "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", - "cpu": [ - "arm64" + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.19.11.tgz", + "integrity": "sha512-LneLg3ypEeveBSMuoa0kwMpCGmpu8XQUh+mL8XXwoYZ6Be2qBnVtcDI5azSvh7vioMDhoJFZzp9GWp9IWpYoUg==", + "cpu": [ + "arm64" ], - "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -895,13 +770,13 @@ } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", - "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.19.11.tgz", + "integrity": "sha512-caHy++CsD8Bgq2V5CodbJjFPEiDPq8JJmBdeyZ8GWVQMjRD0sU548nNdwPNvKjVpamYYVL40AORekgfIubwHoA==", "cpu": [ "ia32" ], - "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -911,13 +786,13 @@ } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", - "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.19.11.tgz", + "integrity": "sha512-ppZSSLVpPrwHccvC6nQVZaSHlFsvCQyjnvirnVjbKSHuE5N24Yl8F3UwYUUR1UEPaFObGD2tSvVKbvR+uT1Nrg==", "cpu": [ "loong64" ], - "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -927,13 +802,13 @@ } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", - "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.19.11.tgz", + "integrity": "sha512-B5x9j0OgjG+v1dF2DkH34lr+7Gmv0kzX6/V0afF41FkPMMqaQ77pH7CrhWeR22aEeHKaeZVtZ6yFwlxOKPVFyg==", "cpu": [ "mips64el" ], - "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -943,13 +818,13 @@ } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", - "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.19.11.tgz", + "integrity": "sha512-MHrZYLeCG8vXblMetWyttkdVRjQlQUb/oMgBNurVEnhj4YWOr4G5lmBfZjHYQHHN0g6yDmCAQRR8MUHldvvRDA==", "cpu": [ "ppc64" ], - "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -959,13 +834,13 @@ } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", - "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.19.11.tgz", + "integrity": "sha512-f3DY++t94uVg141dozDu4CCUkYW+09rWtaWfnb3bqe4w5NqmZd6nPVBm+qbz7WaHZCoqXqHz5p6CM6qv3qnSSQ==", "cpu": [ "riscv64" ], - "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -975,13 +850,13 @@ } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", - "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.19.11.tgz", + "integrity": "sha512-A5xdUoyWJHMMlcSMcPGVLzYzpcY8QP1RtYzX5/bS4dvjBGVxdhuiYyFwp7z74ocV7WDc0n1harxmpq2ePOjI0Q==", "cpu": [ "s390x" ], - "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -991,13 +866,13 @@ } }, "node_modules/@esbuild/linux-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", - "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.19.11.tgz", + "integrity": "sha512-grbyMlVCvJSfxFQUndw5mCtWs5LO1gUlwP4CDi4iJBbVpZcqLVT29FxgGuBJGSzyOxotFG4LoO5X+M1350zmPA==", "cpu": [ "x64" ], - "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -1007,13 +882,13 @@ } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", - "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.19.11.tgz", + "integrity": "sha512-13jvrQZJc3P230OhU8xgwUnDeuC/9egsjTkXN49b3GcS5BKvJqZn86aGM8W9pd14Kd+u7HuFBMVtrNGhh6fHEQ==", "cpu": [ "x64" ], - "dev": true, + "license": "MIT", "optional": true, "os": [ "netbsd" @@ -1023,13 +898,13 @@ } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", - "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.19.11.tgz", + "integrity": "sha512-ysyOGZuTp6SNKPE11INDUeFVVQFrhcNDVUgSQVDzqsqX38DjhPEPATpid04LCoUr2WXhQTEZ8ct/EgJCUDpyNw==", "cpu": [ "x64" ], - "dev": true, + "license": "MIT", "optional": true, "os": [ "openbsd" @@ -1039,13 +914,13 @@ } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", - "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.19.11.tgz", + "integrity": "sha512-Hf+Sad9nVwvtxy4DXCZQqLpgmRTQqyFyhT3bZ4F2XlJCjxGmRFF0Shwn9rzhOYRB61w9VMXUkxlBy56dk9JJiQ==", "cpu": [ "x64" ], - "dev": true, + "license": "MIT", "optional": true, "os": [ "sunos" @@ -1055,13 +930,13 @@ } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", - "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.19.11.tgz", + "integrity": "sha512-0P58Sbi0LctOMOQbpEOvOL44Ne0sqbS0XWHMvvrg6NE5jQ1xguCSSw9jQeUk2lfrXYsKDdOe6K+oZiwKPilYPQ==", "cpu": [ "arm64" ], - "dev": true, + "license": "MIT", "optional": true, "os": [ "win32" @@ -1071,13 +946,13 @@ } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", - "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.19.11.tgz", + "integrity": "sha512-6YOrWS+sDJDmshdBIQU+Uoyh7pQKrdykdefC1avn76ss5c+RN6gut3LZA4E2cH5xUEp5/cA0+YxRaVtRAb0xBg==", "cpu": [ "ia32" ], - "dev": true, + "license": "MIT", "optional": true, "os": [ "win32" @@ -1087,13 +962,13 @@ } }, "node_modules/@esbuild/win32-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", - "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.19.11.tgz", + "integrity": "sha512-vfkhltrjCAb603XaFhqhAF4LGDi2M4OrCRrFusyQ+iTLQ/o60QQXxc9cZC/FFpihBI9N1Grn6SMKVJ4KP7Fuiw==", "cpu": [ "x64" ], - "dev": true, + "license": "MIT", "optional": true, "os": [ "win32" @@ -1103,36 +978,42 @@ } }, "node_modules/@eslint-community/eslint-utils": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", - "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz", + "integrity": "sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==", "dev": true, + "license": "MIT", "dependencies": { - "eslint-visitor-keys": "^3.3.0" + "eslint-visitor-keys": "^3.4.3" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, + "funding": { + "url": "https://opencollective.com/eslint" + }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "node_modules/@eslint-community/regexpp": { - "version": "4.11.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.0.tgz", - "integrity": "sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A==", + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", + "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", "dev": true, + "license": "MIT", "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, "node_modules/@eslint/config-array": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.18.0.tgz", - "integrity": "sha512-fTxvnS1sRMu3+JjXwJG0j/i4RT9u4qJ+lqS/yCGap4lH4zZGzQ7tu+xZqQmcMZq5OBZDL4QRxQzRjkWcGt8IVw==", + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.19.1.tgz", + "integrity": "sha512-fo6Mtm5mWyKjA/Chy1BYTdn5mGJoDNjC7C64ug20ADsRDGrA85bN3uK3MaKbeRkRuuIEAR5N33Jr1pbm411/PA==", "dev": true, + "license": "Apache-2.0", "dependencies": { - "@eslint/object-schema": "^2.1.4", + "@eslint/object-schema": "^2.1.5", "debug": "^4.3.1", "minimatch": "^3.1.2" }, @@ -1141,18 +1022,22 @@ } }, "node_modules/@eslint/core": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.7.0.tgz", - "integrity": "sha512-xp5Jirz5DyPYlPiKat8jaq0EmYvDXKKpzTbxXMpT9eqlRJkRKIz9AGMdlvYjih+im+QlhWrpvVjl8IPC/lHlUw==", + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.9.1.tgz", + "integrity": "sha512-GuUdqkyyzQI5RMIWkHhvTWLCyLo1jNK3vzkSyaExH5kHPDHcuL2VOpHjmMY+y3+NC69qAKToBqldTBgYeLSr9Q==", "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.15" + }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, "node_modules/@eslint/eslintrc": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.1.0.tgz", - "integrity": "sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.2.0.tgz", + "integrity": "sha512-grOjVNN8P3hjJn/eIETF1wwd12DdnwFDoyceUJLYYdkpbwq3nLi+4fqrTAONx7XDALqlL220wC/RHSC/QTI/0w==", "dev": true, "license": "MIT", "dependencies": { @@ -1173,22 +1058,6 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/@eslint/eslintrc/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, "node_modules/@eslint/eslintrc/node_modules/globals": { "version": "14.0.0", "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", @@ -1202,35 +1071,32 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, "node_modules/@eslint/js": { - "version": "9.13.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.13.0.tgz", - "integrity": "sha512-IFLyoY4d72Z5y/6o/BazFBezupzI/taV8sGumxTAVw3lXG9A6md1Dc34T9s1FoD/an9pJH8RHbAxsaEbBed9lA==", + "version": "9.17.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.17.0.tgz", + "integrity": "sha512-Sxc4hqcs1kTu0iID3kcZDW3JHq2a77HO9P8CP6YEA/FpH3Ll8UXE2r/86Rz9YJLKme39S9vU5OWNjC6Xl0Cr3w==", "dev": true, + "license": "MIT", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, "node_modules/@eslint/object-schema": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.4.tgz", - "integrity": "sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==", + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.5.tgz", + "integrity": "sha512-o0bhxnL89h5Bae5T318nFoFzGy+YE5i/gGkoPAgkmTVdRKTiv3p8JHevPiPaMwoloKfEiiaHlawCqaZMqRm+XQ==", "dev": true, + "license": "Apache-2.0", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, "node_modules/@eslint/plugin-kit": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.0.tgz", - "integrity": "sha512-vH9PiIMMwvhCx31Af3HiGzsVNULDbyVkHXwlemn/B0TFj/00ho3y55efXrUZTfQipxoHC5u4xq6zblww1zm1Ig==", + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.4.tgz", + "integrity": "sha512-zSkKow6H5Kdm0ZUQUB2kV5JIXqoG0+uH5YADhaEHswm664N9Db8dXSi0nMJpacpMf+MyyglF1vnZohpEg5yUtg==", "dev": true, + "license": "Apache-2.0", "dependencies": { "levn": "^0.4.1" }, @@ -1243,6 +1109,7 @@ "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.1.tgz", "integrity": "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==", "dev": true, + "license": "MIT", "engines": { "node": ">=14" } @@ -1251,6 +1118,7 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/@golevelup/nestjs-discovery/-/nestjs-discovery-4.0.1.tgz", "integrity": "sha512-HFXBJayEkYcU/bbxOztozONdWaZR34ZeJ2zRbZIWY8d5K26oPZQTvJ4L0STW3XVRGWtoE0WBpmx2YPNgYvcmJQ==", + "license": "MIT", "dependencies": { "lodash": "^4.17.21" }, @@ -1260,9 +1128,10 @@ } }, "node_modules/@grpc/grpc-js": { - "version": "1.12.2", - "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.12.2.tgz", - "integrity": "sha512-bgxdZmgTrJZX50OjyVwz3+mNEnCTNkh3cIqGPWVNeW9jX6bn1ZkU80uPd+67/ZpIJIjRQ9qaHCjhavyoWYxumg==", + "version": "1.12.4", + "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.12.4.tgz", + "integrity": "sha512-NBhrxEWnFh0FxeA0d//YP95lRFsSx2TNLEUQg4/W+5f/BMxcCjgOOIT24iD+ZB/tZw057j44DaIxja7w4XMrhg==", + "license": "Apache-2.0", "dependencies": { "@grpc/proto-loader": "^0.7.13", "@js-sdsl/ordered-map": "^4.4.2" @@ -1275,6 +1144,7 @@ "version": "0.7.13", "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.7.13.tgz", "integrity": "sha512-AiXO/bfe9bmxBjxxtYxFAXGZvMaN5s8kO+jBHAJCON8rJoB5YS/D6X7ZNc6XQkuHNmyl4CYaMI1fJ/Gn27RGGw==", + "license": "Apache-2.0", "dependencies": { "lodash.camelcase": "^4.3.0", "long": "^5.0.0", @@ -1288,92 +1158,65 @@ "node": ">=6" } }, - "node_modules/@grpc/proto-loader/node_modules/cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@grpc/proto-loader/node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/@grpc/proto-loader/node_modules/yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - }, - "engines": { - "node": ">=12" - } - }, "node_modules/@hapi/hoek": { "version": "9.3.0", "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz", - "integrity": "sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==" + "integrity": "sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==", + "license": "BSD-3-Clause" }, "node_modules/@hapi/topo": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.1.0.tgz", "integrity": "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==", + "license": "BSD-3-Clause", "dependencies": { "@hapi/hoek": "^9.0.0" } }, "node_modules/@humanfs/core": { - "version": "0.19.0", - "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.0.tgz", - "integrity": "sha512-2cbWIHbZVEweE853g8jymffCA+NCMiuqeECeBBLm8dg2oFdjuGJhgN4UAbI+6v0CKbbhvtXA4qV8YR5Ji86nmw==", + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", + "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", "dev": true, + "license": "Apache-2.0", "engines": { "node": ">=18.18.0" } }, "node_modules/@humanfs/node": { - "version": "0.16.5", - "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.5.tgz", - "integrity": "sha512-KSPA4umqSG4LHYRodq31VDwKAvaTF4xmVlzM8Aeh4PlU1JQ3IG0wiA8C25d3RQ9nJyM3mBHyI53K06VVL/oFFg==", + "version": "0.16.6", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.6.tgz", + "integrity": "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==", "dev": true, + "license": "Apache-2.0", "dependencies": { - "@humanfs/core": "^0.19.0", + "@humanfs/core": "^0.19.1", "@humanwhocodes/retry": "^0.3.0" }, "engines": { "node": ">=18.18.0" } }, + "node_modules/@humanfs/node/node_modules/@humanwhocodes/retry": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz", + "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, "node_modules/@humanwhocodes/module-importer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", "dev": true, + "license": "Apache-2.0", "engines": { "node": ">=12.22" }, @@ -1383,10 +1226,11 @@ } }, "node_modules/@humanwhocodes/retry": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz", - "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==", + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.1.tgz", + "integrity": "sha512-c7hNEllBlenFTHBky65mhq8WD2kbN9Q6gk0bTk8lSBvc554jpXSkST1iePudpt7+A/AQvuHs9EMqjHDXMY1lrA==", "dev": true, + "license": "Apache-2.0", "engines": { "node": ">=18.18" }, @@ -1402,6 +1246,7 @@ "cpu": [ "arm64" ], + "license": "Apache-2.0", "optional": true, "os": [ "darwin" @@ -1423,6 +1268,7 @@ "cpu": [ "x64" ], + "license": "Apache-2.0", "optional": true, "os": [ "darwin" @@ -1444,6 +1290,7 @@ "cpu": [ "arm64" ], + "license": "LGPL-3.0-or-later", "optional": true, "os": [ "darwin" @@ -1459,6 +1306,7 @@ "cpu": [ "x64" ], + "license": "LGPL-3.0-or-later", "optional": true, "os": [ "darwin" @@ -1474,6 +1322,7 @@ "cpu": [ "arm" ], + "license": "LGPL-3.0-or-later", "optional": true, "os": [ "linux" @@ -1489,6 +1338,7 @@ "cpu": [ "arm64" ], + "license": "LGPL-3.0-or-later", "optional": true, "os": [ "linux" @@ -1504,6 +1354,7 @@ "cpu": [ "s390x" ], + "license": "LGPL-3.0-or-later", "optional": true, "os": [ "linux" @@ -1519,6 +1370,7 @@ "cpu": [ "x64" ], + "license": "LGPL-3.0-or-later", "optional": true, "os": [ "linux" @@ -1534,6 +1386,7 @@ "cpu": [ "arm64" ], + "license": "LGPL-3.0-or-later", "optional": true, "os": [ "linux" @@ -1549,6 +1402,7 @@ "cpu": [ "x64" ], + "license": "LGPL-3.0-or-later", "optional": true, "os": [ "linux" @@ -1564,6 +1418,7 @@ "cpu": [ "arm" ], + "license": "Apache-2.0", "optional": true, "os": [ "linux" @@ -1585,6 +1440,7 @@ "cpu": [ "arm64" ], + "license": "Apache-2.0", "optional": true, "os": [ "linux" @@ -1606,6 +1462,7 @@ "cpu": [ "s390x" ], + "license": "Apache-2.0", "optional": true, "os": [ "linux" @@ -1627,6 +1484,7 @@ "cpu": [ "x64" ], + "license": "Apache-2.0", "optional": true, "os": [ "linux" @@ -1648,6 +1506,7 @@ "cpu": [ "arm64" ], + "license": "Apache-2.0", "optional": true, "os": [ "linux" @@ -1669,6 +1528,7 @@ "cpu": [ "x64" ], + "license": "Apache-2.0", "optional": true, "os": [ "linux" @@ -1690,6 +1550,7 @@ "cpu": [ "wasm32" ], + "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", "optional": true, "dependencies": { "@emnapi/runtime": "^1.2.0" @@ -1708,6 +1569,7 @@ "cpu": [ "ia32" ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", "optional": true, "os": [ "win32" @@ -1726,6 +1588,7 @@ "cpu": [ "x64" ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", "optional": true, "os": [ "win32" @@ -1740,12 +1603,14 @@ "node_modules/@ioredis/commands": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@ioredis/commands/-/commands-1.2.0.tgz", - "integrity": "sha512-Sx1pU8EM64o2BrqNpEO1CNLtKQwyhuXuqyfH7oGKCk+1a33d2r5saW8zNwm3j6BTExtjrv2BxTgzzkMwts6vGg==" + "integrity": "sha512-Sx1pU8EM64o2BrqNpEO1CNLtKQwyhuXuqyfH7oGKCk+1a33d2r5saW8zNwm3j6BTExtjrv2BxTgzzkMwts6vGg==", + "license": "MIT" }, "node_modules/@isaacs/cliui": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "license": "ISC", "dependencies": { "string-width": "^5.1.2", "string-width-cjs": "npm:string-width@^4.2.0", @@ -1759,9 +1624,10 @@ } }, "node_modules/@isaacs/cliui/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "license": "MIT", "engines": { "node": ">=12" }, @@ -1773,6 +1639,7 @@ "version": "6.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "license": "MIT", "engines": { "node": ">=12" }, @@ -1783,12 +1650,14 @@ "node_modules/@isaacs/cliui/node_modules/emoji-regex": { "version": "9.2.2", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "license": "MIT" }, "node_modules/@isaacs/cliui/node_modules/string-width": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "license": "MIT", "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", @@ -1805,6 +1674,7 @@ "version": "7.1.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "license": "MIT", "dependencies": { "ansi-regex": "^6.0.1" }, @@ -1819,6 +1689,7 @@ "version": "8.1.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "license": "MIT", "dependencies": { "ansi-styles": "^6.1.0", "string-width": "^5.0.1", @@ -1836,14 +1707,16 @@ "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", - "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz", + "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==", + "license": "MIT", "dependencies": { "@jridgewell/set-array": "^1.2.1", "@jridgewell/sourcemap-codec": "^1.4.10", @@ -1854,9 +1727,10 @@ } }, "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", - "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "license": "MIT", "engines": { "node": ">=6.0.0" } @@ -1865,29 +1739,33 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "license": "MIT", "engines": { "node": ">=6.0.0" } }, "node_modules/@jridgewell/source-map": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.5.tgz", - "integrity": "sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==", + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz", + "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==", "dev": true, + "license": "MIT", "dependencies": { - "@jridgewell/gen-mapping": "^0.3.0", - "@jridgewell/trace-mapping": "^0.3.9" + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25" } }, "node_modules/@jridgewell/sourcemap-codec": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", - "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==" + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", + "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { "version": "0.3.25", "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "license": "MIT", "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" @@ -1897,6 +1775,7 @@ "version": "4.4.2", "resolved": "https://registry.npmjs.org/@js-sdsl/ordered-map/-/ordered-map-4.4.2.tgz", "integrity": "sha512-iUKgm52T8HOE/makSxjqoWhe95ZJA1/G1sYsGev2JDKUSS14KAgg1LHb+Ba+IPow0xflbnSkOsZcO08C7w1gYw==", + "license": "MIT", "funding": { "type": "opencollective", "url": "https://opencollective.com/js-sdsl" @@ -1907,6 +1786,7 @@ "resolved": "https://registry.npmjs.org/@ljharb/through/-/through-2.3.13.tgz", "integrity": "sha512-/gKJun8NNiWGZJkGzI/Ragc53cOdcLNdzjLaIa+GEjguQs0ulsurx8WN0jijdK9yPqDvziX995sMRLyLt1uZMQ==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.7" }, @@ -1918,6 +1798,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/@lukeed/csprng/-/csprng-1.1.0.tgz", "integrity": "sha512-Z7C/xXCiGWsg0KuKsHTKJxbWhpI3Vs5GwLfOean7MGyVFGqdRgBbAjOCh6u4bbjPc/8MJ2pZmK/0DLdCbivLDA==", + "license": "MIT", "engines": { "node": ">=8" } @@ -1926,6 +1807,7 @@ "version": "1.0.11", "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz", "integrity": "sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==", + "license": "BSD-3-Clause", "dependencies": { "detect-libc": "^2.0.0", "https-proxy-agent": "^5.0.0", @@ -1945,6 +1827,8 @@ "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "license": "ISC", "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -1964,6 +1848,8 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "license": "ISC", "dependencies": { "glob": "^7.1.3" }, @@ -1975,72 +1861,142 @@ } }, "node_modules/@microsoft/tsdoc": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/@microsoft/tsdoc/-/tsdoc-0.15.0.tgz", - "integrity": "sha512-HZpPoABogPvjeJOdzCOSJsXeL/SMCBgBZMVC3X3d7YYp2gf31MfxhUoYUNwf1ERPJOnQc0wkFn9trqI6ZEdZuA==" + "version": "0.15.1", + "resolved": "https://registry.npmjs.org/@microsoft/tsdoc/-/tsdoc-0.15.1.tgz", + "integrity": "sha512-4aErSrCR/On/e5G2hDP0wjooqDdauzEbIq8hIkIe5pXV0rtWJZvdCEKL0ykZxex+IxIwBp0eGeV48hQN07dXtw==", + "license": "MIT" }, "node_modules/@msgpackr-extract/msgpackr-extract-darwin-arm64": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-arm64/-/msgpackr-extract-darwin-arm64-3.0.2.tgz", - "integrity": "sha512-9bfjwDxIDWmmOKusUcqdS4Rw+SETlp9Dy39Xui9BEGEk19dDwH0jhipwFzEff/pFg95NKymc6TOTbRKcWeRqyQ==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-arm64/-/msgpackr-extract-darwin-arm64-3.0.3.tgz", + "integrity": "sha512-QZHtlVgbAdy2zAqNA9Gu1UpIuI8Xvsd1v8ic6B2pZmeFnFcMWiPLfWXh7TVw4eGEZ/C9TH281KwhVoeQUKbyjw==", "cpu": [ "arm64" ], + "license": "MIT", "optional": true, "os": [ "darwin" ] }, - "node_modules/@nestjs/bull-shared": { - "version": "10.2.1", - "resolved": "https://registry.npmjs.org/@nestjs/bull-shared/-/bull-shared-10.2.1.tgz", - "integrity": "sha512-zvnTvSq6OJ92omcsFUwaUmPbM3PRgWkIusHPB5TE3IFS7nNdM3OwF+kfe56sgKjMtQQMe/56lok0S04OtPMX5Q==", - "dependencies": { - "tslib": "2.6.3" - }, - "peerDependencies": { - "@nestjs/common": "^8.0.0 || ^9.0.0 || ^10.0.0", - "@nestjs/core": "^8.0.0 || ^9.0.0 || ^10.0.0" - } + "node_modules/@msgpackr-extract/msgpackr-extract-darwin-x64": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-x64/-/msgpackr-extract-darwin-x64-3.0.3.tgz", + "integrity": "sha512-mdzd3AVzYKuUmiWOQ8GNhl64/IoFGol569zNRdkLReh6LRLHOXxU4U8eq0JwaD8iFHdVGqSy4IjFL4reoWCDFw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] }, - "node_modules/@nestjs/bullmq": { - "version": "10.2.1", - "resolved": "https://registry.npmjs.org/@nestjs/bullmq/-/bullmq-10.2.1.tgz", - "integrity": "sha512-nDR0hDabmtXt5gsb5R786BJsGIJoWh/79sVmRETXf4S45+fvdqG1XkCKAeHF9TO9USodw9m+XBNKysTnkY41gw==", - "dependencies": { - "@nestjs/bull-shared": "^10.2.1", - "tslib": "2.6.3" - }, - "peerDependencies": { + "node_modules/@msgpackr-extract/msgpackr-extract-linux-arm": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm/-/msgpackr-extract-linux-arm-3.0.3.tgz", + "integrity": "sha512-fg0uy/dG/nZEXfYilKoRe7yALaNmHoYeIoJuJ7KJ+YyU2bvY8vPv27f7UKhGRpY6euFYqEVhxCFZgAUNQBM3nw==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@msgpackr-extract/msgpackr-extract-linux-arm64": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm64/-/msgpackr-extract-linux-arm64-3.0.3.tgz", + "integrity": "sha512-YxQL+ax0XqBJDZiKimS2XQaf+2wDGVa1enVRGzEvLLVFeqa5kx2bWbtcSXgsxjQB7nRqqIGFIcLteF/sHeVtQg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@msgpackr-extract/msgpackr-extract-linux-x64": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-x64/-/msgpackr-extract-linux-x64-3.0.3.tgz", + "integrity": "sha512-cvwNfbP07pKUfq1uH+S6KJ7dT9K8WOE4ZiAcsrSes+UY55E/0jLYc+vq+DO7jlmqRb5zAggExKm0H7O/CBaesg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@msgpackr-extract/msgpackr-extract-win32-x64": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-win32-x64/-/msgpackr-extract-win32-x64-3.0.3.tgz", + "integrity": "sha512-x0fWaQtYp4E6sktbsdAqnehxDgEc/VwM7uLsRCYWaiGu0ykYdZPiS8zCWdnjHwyiumousxfBm4SO31eXqwEZhQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@nestjs/bull-shared": { + "version": "10.2.3", + "resolved": "https://registry.npmjs.org/@nestjs/bull-shared/-/bull-shared-10.2.3.tgz", + "integrity": "sha512-XcgAjNOgq6b5DVCytxhR5BKiwWo7hsusVeyE7sfFnlXRHeEtIuC2hYWBr/ZAtvL/RH0/O0tqtq0rVl972nbhJw==", + "license": "MIT", + "dependencies": { + "tslib": "2.8.1" + }, + "peerDependencies": { + "@nestjs/common": "^8.0.0 || ^9.0.0 || ^10.0.0", + "@nestjs/core": "^8.0.0 || ^9.0.0 || ^10.0.0" + } + }, + "node_modules/@nestjs/bullmq": { + "version": "10.2.3", + "resolved": "https://registry.npmjs.org/@nestjs/bullmq/-/bullmq-10.2.3.tgz", + "integrity": "sha512-Lo4W5kWD61/246Y6H70RNgV73ybfRbZyKKS4CBRDaMELpxgt89O+EgYZUB4pdoNrWH16rKcaT0AoVsB/iDztKg==", + "license": "MIT", + "dependencies": { + "@nestjs/bull-shared": "^10.2.3", + "tslib": "2.8.1" + }, + "peerDependencies": { "@nestjs/common": "^8.0.0 || ^9.0.0 || ^10.0.0", "@nestjs/core": "^8.0.0 || ^9.0.0 || ^10.0.0", "bullmq": "^3.0.0 || ^4.0.0 || ^5.0.0" } }, "node_modules/@nestjs/cli": { - "version": "10.4.5", - "resolved": "https://registry.npmjs.org/@nestjs/cli/-/cli-10.4.5.tgz", - "integrity": "sha512-FP7Rh13u8aJbHe+zZ7hM0CC4785g9Pw4lz4r2TTgRtf0zTxSWMkJaPEwyjX8SK9oWK2GsYxl+fKpwVZNbmnj9A==", + "version": "10.4.9", + "resolved": "https://registry.npmjs.org/@nestjs/cli/-/cli-10.4.9.tgz", + "integrity": "sha512-s8qYd97bggqeK7Op3iD49X2MpFtW4LVNLAwXFkfbRxKME6IYT7X0muNTJ2+QfI8hpbNx9isWkrLWIp+g5FOhiA==", "dev": true, + "license": "MIT", "dependencies": { - "@angular-devkit/core": "17.3.8", - "@angular-devkit/schematics": "17.3.8", - "@angular-devkit/schematics-cli": "17.3.8", + "@angular-devkit/core": "17.3.11", + "@angular-devkit/schematics": "17.3.11", + "@angular-devkit/schematics-cli": "17.3.11", "@nestjs/schematics": "^10.0.1", "chalk": "4.1.2", "chokidar": "3.6.0", "cli-table3": "0.6.5", "commander": "4.1.1", "fork-ts-checker-webpack-plugin": "9.0.2", - "glob": "10.4.2", + "glob": "10.4.5", "inquirer": "8.2.6", "node-emoji": "1.11.0", "ora": "5.4.1", "tree-kill": "1.2.2", "tsconfig-paths": "4.2.0", - "tsconfig-paths-webpack-plugin": "4.1.0", - "typescript": "5.3.3", - "webpack": "5.94.0", + "tsconfig-paths-webpack-plugin": "4.2.0", + "typescript": "5.7.2", + "webpack": "5.97.1", "webpack-node-externals": "3.0.0" }, "bin": { @@ -2050,7 +2006,7 @@ "node": ">= 16.14" }, "peerDependencies": { - "@swc/cli": "^0.1.62 || ^0.3.0 || ^0.4.0", + "@swc/cli": "^0.1.62 || ^0.3.0 || ^0.4.0 || ^0.5.0", "@swc/core": "^1.3.62" }, "peerDependenciesMeta": { @@ -2062,26 +2018,14 @@ } } }, - "node_modules/@nestjs/cli/node_modules/typescript": { - "version": "5.3.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", - "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", - "dev": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, "node_modules/@nestjs/common": { - "version": "10.4.6", - "resolved": "https://registry.npmjs.org/@nestjs/common/-/common-10.4.6.tgz", - "integrity": "sha512-KkezkZvU9poWaNq4L+lNvx+386hpOxPJkfXBBeSMrcqBOx8kVr36TGN2uYkF4Ta4zNu1KbCjmZbc0rhHSg296g==", + "version": "10.4.15", + "resolved": "https://registry.npmjs.org/@nestjs/common/-/common-10.4.15.tgz", + "integrity": "sha512-vaLg1ZgwhG29BuLDxPA9OAcIlgqzp9/N8iG0wGapyUNTf4IY4O6zAHgN6QalwLhFxq7nOI021vdRojR1oF3bqg==", + "license": "MIT", "dependencies": { "iterare": "1.2.1", - "tslib": "2.7.0", + "tslib": "2.8.1", "uid": "2.0.2" }, "funding": { @@ -2103,22 +2047,18 @@ } } }, - "node_modules/@nestjs/common/node_modules/tslib": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", - "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==" - }, "node_modules/@nestjs/core": { - "version": "10.4.6", - "resolved": "https://registry.npmjs.org/@nestjs/core/-/core-10.4.6.tgz", - "integrity": "sha512-zXVPxCNRfO6gAy0yvEDjUxE/8gfZICJFpsl2lZAUH31bPb6m+tXuhUq2mVCTEltyMYQ+DYtRe+fEYM2v152N1g==", + "version": "10.4.15", + "resolved": "https://registry.npmjs.org/@nestjs/core/-/core-10.4.15.tgz", + "integrity": "sha512-UBejmdiYwaH6fTsz2QFBlC1cJHM+3UDeLZN+CiP9I1fRv2KlBZsmozGLbV5eS1JAVWJB4T5N5yQ0gjN8ZvcS2w==", "hasInstallScript": true, + "license": "MIT", "dependencies": { "@nuxtjs/opencollective": "0.3.2", "fast-safe-stringify": "2.1.1", "iterare": "1.2.1", "path-to-regexp": "3.3.0", - "tslib": "2.7.0", + "tslib": "2.8.1", "uid": "2.0.2" }, "funding": { @@ -2145,15 +2085,11 @@ } } }, - "node_modules/@nestjs/core/node_modules/tslib": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", - "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==" - }, "node_modules/@nestjs/event-emitter": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/@nestjs/event-emitter/-/event-emitter-2.1.1.tgz", "integrity": "sha512-6L6fBOZTyfFlL7Ih/JDdqlCzZeCW0RjCX28wnzGyg/ncv5F/EOeT1dfopQr1loBRQ3LTgu8OWM7n4zLN4xigsg==", + "license": "MIT", "dependencies": { "eventemitter2": "6.4.9" }, @@ -2163,9 +2099,10 @@ } }, "node_modules/@nestjs/mapped-types": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nestjs/mapped-types/-/mapped-types-2.0.5.tgz", - "integrity": "sha512-bSJv4pd6EY99NX9CjBIyn4TVDoSit82DUZlL4I3bqNfy5Gt+gXTa86i3I/i0iIV9P4hntcGM5GyO+FhZAhxtyg==", + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@nestjs/mapped-types/-/mapped-types-2.0.6.tgz", + "integrity": "sha512-84ze+CPfp1OWdpRi1/lOu59hOhTz38eVzJvRKrg9ykRFwDz+XleKfMsG0gUqNZYFa6v53XYzeD+xItt8uDW7NQ==", + "license": "MIT", "peerDependencies": { "@nestjs/common": "^8.0.0 || ^9.0.0 || ^10.0.0", "class-transformer": "^0.4.0 || ^0.5.0", @@ -2182,15 +2119,16 @@ } }, "node_modules/@nestjs/platform-express": { - "version": "10.4.6", - "resolved": "https://registry.npmjs.org/@nestjs/platform-express/-/platform-express-10.4.6.tgz", - "integrity": "sha512-HcyCpAKccAasrLSGRTGWv5BKRs0rwTIFOSsk6laNyqfqvgvYcJQAedarnm4jmaemtmSJ0PFI9PmtEZADd2ahCg==", + "version": "10.4.15", + "resolved": "https://registry.npmjs.org/@nestjs/platform-express/-/platform-express-10.4.15.tgz", + "integrity": "sha512-63ZZPkXHjoDyO7ahGOVcybZCRa7/Scp6mObQKjcX/fTEq1YJeU75ELvMsuQgc8U2opMGOBD7GVuc4DV0oeDHoA==", + "license": "MIT", "dependencies": { "body-parser": "1.20.3", "cors": "2.8.5", - "express": "4.21.1", + "express": "4.21.2", "multer": "1.4.4-lts.1", - "tslib": "2.7.0" + "tslib": "2.8.1" }, "funding": { "type": "opencollective", @@ -2201,18 +2139,14 @@ "@nestjs/core": "^10.0.0" } }, - "node_modules/@nestjs/platform-express/node_modules/tslib": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", - "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==" - }, "node_modules/@nestjs/platform-socket.io": { - "version": "10.4.6", - "resolved": "https://registry.npmjs.org/@nestjs/platform-socket.io/-/platform-socket.io-10.4.6.tgz", - "integrity": "sha512-lGv99O7C00wtnGq9M0mcwrOpH2qmuqAXQyvo/d/I7rmaf3OO1Sg8qWDLAnPKHdaumwOL2mnET3kvCJ06MaL6WA==", + "version": "10.4.15", + "resolved": "https://registry.npmjs.org/@nestjs/platform-socket.io/-/platform-socket.io-10.4.15.tgz", + "integrity": "sha512-KZAxNEADPwoORixh3NJgGYWMVGORVPKeTqjD7hbF8TPDLKWWxru9yasBQwEz2/wXH/WgpkQbbaYwx4nUjCIVpw==", + "license": "MIT", "dependencies": { - "socket.io": "4.8.0", - "tslib": "2.7.0" + "socket.io": "4.8.1", + "tslib": "2.8.1" }, "funding": { "type": "opencollective", @@ -2224,89 +2158,29 @@ "rxjs": "^7.1.0" } }, - "node_modules/@nestjs/platform-socket.io/node_modules/cookie": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", - "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/@nestjs/platform-socket.io/node_modules/engine.io": { - "version": "6.6.2", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.6.2.tgz", - "integrity": "sha512-gmNvsYi9C8iErnZdVcJnvCpSKbWTt1E8+JZo8b+daLninywUWi5NQ5STSHZ9rFjFO7imNcvb8Pc5pe/wMR5xEw==", - "dependencies": { - "@types/cookie": "^0.4.1", - "@types/cors": "^2.8.12", - "@types/node": ">=10.0.0", - "accepts": "~1.3.4", - "base64id": "2.0.0", - "cookie": "~0.7.2", - "cors": "~2.8.5", - "debug": "~4.3.1", - "engine.io-parser": "~5.2.1", - "ws": "~8.17.1" - }, - "engines": { - "node": ">=10.2.0" - } - }, - "node_modules/@nestjs/platform-socket.io/node_modules/socket.io": { - "version": "4.8.0", - "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.8.0.tgz", - "integrity": "sha512-8U6BEgGjQOfGz3HHTYaC/L1GaxDCJ/KM0XTkJly0EhZ5U/du9uNEZy4ZgYzEzIqlx2CMm25CrCqr1ck899eLNA==", - "dependencies": { - "accepts": "~1.3.4", - "base64id": "~2.0.0", - "cors": "~2.8.5", - "debug": "~4.3.2", - "engine.io": "~6.6.0", - "socket.io-adapter": "~2.5.2", - "socket.io-parser": "~4.2.4" - }, - "engines": { - "node": ">=10.2.0" - } - }, - "node_modules/@nestjs/platform-socket.io/node_modules/tslib": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", - "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==" - }, "node_modules/@nestjs/schedule": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/@nestjs/schedule/-/schedule-4.1.1.tgz", - "integrity": "sha512-VxAnCiU4HP0wWw8IdWAVfsGC/FGjyToNjjUtXDEQL6oj+w/N5QDd2VT9k6d7Jbr8PlZuBZNdWtDKSkH5bZ+RXQ==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/@nestjs/schedule/-/schedule-4.1.2.tgz", + "integrity": "sha512-hCTQ1lNjIA5EHxeu8VvQu2Ed2DBLS1GSC6uKPYlBiQe6LL9a7zfE9iVSK+zuK8E2odsApteEBmfAQchc8Hx0Gg==", + "license": "MIT", "dependencies": { - "cron": "3.1.7", - "uuid": "10.0.0" + "cron": "3.2.1", + "uuid": "11.0.3" }, "peerDependencies": { "@nestjs/common": "^8.0.0 || ^9.0.0 || ^10.0.0", "@nestjs/core": "^8.0.0 || ^9.0.0 || ^10.0.0" } }, - "node_modules/@nestjs/schedule/node_modules/uuid": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-10.0.0.tgz", - "integrity": "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==", - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" - ], - "bin": { - "uuid": "dist/bin/uuid" - } - }, "node_modules/@nestjs/schematics": { - "version": "10.2.2", - "resolved": "https://registry.npmjs.org/@nestjs/schematics/-/schematics-10.2.2.tgz", - "integrity": "sha512-D4pJ46E8llCA7WPr3cV6sfRqDlvnTjQWnF1fLyKYD3Ldl+KPtlLyIcxaqlLTB0YR9ItKNKIZTJzUehRxR7UUsQ==", + "version": "10.2.3", + "resolved": "https://registry.npmjs.org/@nestjs/schematics/-/schematics-10.2.3.tgz", + "integrity": "sha512-4e8gxaCk7DhBxVUly2PjYL4xC2ifDFexCqq1/u4TtivLGXotVk0wHdYuPYe1tHTHuR1lsOkRbfOCpkdTnigLVg==", "dev": true, + "license": "MIT", "dependencies": { - "@angular-devkit/core": "17.3.10", - "@angular-devkit/schematics": "17.3.10", + "@angular-devkit/core": "17.3.11", + "@angular-devkit/schematics": "17.3.11", "comment-json": "4.2.5", "jsonc-parser": "3.3.1", "pluralize": "8.0.0" @@ -2315,92 +2189,25 @@ "typescript": ">=4.8.2" } }, - "node_modules/@nestjs/schematics/node_modules/@angular-devkit/core": { - "version": "17.3.10", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-17.3.10.tgz", - "integrity": "sha512-czdl54yxU5DOAGy/uUPNjJruoBDTgwi/V+eOgLNybYhgrc+TsY0f7uJ11yEk/pz5sCov7xIiS7RdRv96waS7vg==", - "dev": true, - "dependencies": { - "ajv": "8.12.0", - "ajv-formats": "2.1.1", - "jsonc-parser": "3.2.1", - "picomatch": "4.0.1", - "rxjs": "7.8.1", - "source-map": "0.7.4" - }, - "engines": { - "node": "^18.13.0 || >=20.9.0", - "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", - "yarn": ">= 1.13.0" - }, - "peerDependencies": { - "chokidar": "^3.5.2" - }, - "peerDependenciesMeta": { - "chokidar": { - "optional": true - } - } - }, - "node_modules/@nestjs/schematics/node_modules/@angular-devkit/core/node_modules/jsonc-parser": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.1.tgz", - "integrity": "sha512-AilxAyFOAcK5wA1+LeaySVBrHsGQvUFCDWXKpZjzaL0PqW+xfBOttn8GNtWKFWqneyMZj41MWF9Kl6iPWLwgOA==", - "dev": true - }, - "node_modules/@nestjs/schematics/node_modules/@angular-devkit/schematics": { - "version": "17.3.10", - "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-17.3.10.tgz", - "integrity": "sha512-FHcNa1ktYRd0SKExCsNJpR75RffsyuPIV8kvBXzXnLHmXMqvl25G2te3yYJ9yYqy9OLy/58HZznZTxWRyUdHOg==", - "dev": true, - "dependencies": { - "@angular-devkit/core": "17.3.10", - "jsonc-parser": "3.2.1", - "magic-string": "0.30.8", - "ora": "5.4.1", - "rxjs": "7.8.1" - }, - "engines": { - "node": "^18.13.0 || >=20.9.0", - "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", - "yarn": ">= 1.13.0" - } - }, - "node_modules/@nestjs/schematics/node_modules/@angular-devkit/schematics/node_modules/jsonc-parser": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.1.tgz", - "integrity": "sha512-AilxAyFOAcK5wA1+LeaySVBrHsGQvUFCDWXKpZjzaL0PqW+xfBOttn8GNtWKFWqneyMZj41MWF9Kl6iPWLwgOA==", - "dev": true - }, "node_modules/@nestjs/schematics/node_modules/jsonc-parser": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.3.1.tgz", "integrity": "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==", - "dev": true - }, - "node_modules/@nestjs/schematics/node_modules/picomatch": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.1.tgz", - "integrity": "sha512-xUXwsxNjwTQ8K3GnT4pCJm+xq3RUPQbmkYJTP5aFIfNIvbcc/4MUxgBaaRSZJ6yGJZiGSyYlM6MzwTsRk8SYCg==", "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } + "license": "MIT" }, "node_modules/@nestjs/swagger": { - "version": "7.4.2", - "resolved": "https://registry.npmjs.org/@nestjs/swagger/-/swagger-7.4.2.tgz", - "integrity": "sha512-Mu6TEn1M/owIvAx2B4DUQObQXqo2028R2s9rSZ/hJEgBK95+doTwS0DjmVA2wTeZTyVtXOoN7CsoM5pONBzvKQ==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@nestjs/swagger/-/swagger-8.1.0.tgz", + "integrity": "sha512-8hzH+r/31XshzXHC9vww4T0xjDAxMzvOaT1xAOvvY1LtXTWyNRCUP2iQsCYJOnnMrR+vydWjvRZiuB3hdvaHxA==", + "license": "MIT", "dependencies": { "@microsoft/tsdoc": "^0.15.0", - "@nestjs/mapped-types": "2.0.5", + "@nestjs/mapped-types": "2.0.6", "js-yaml": "4.1.0", "lodash": "4.17.21", "path-to-regexp": "3.3.0", - "swagger-ui-dist": "5.17.14" + "swagger-ui-dist": "5.18.2" }, "peerDependencies": { "@fastify/static": "^6.0.0 || ^7.0.0", @@ -2423,12 +2230,13 @@ } }, "node_modules/@nestjs/testing": { - "version": "10.4.6", - "resolved": "https://registry.npmjs.org/@nestjs/testing/-/testing-10.4.6.tgz", - "integrity": "sha512-aiDicKhlGibVGNYuew399H5qZZXaseOBT/BS+ERJxxCmco7ZdAqaujsNjSaSbTK9ojDPf27crLT0C4opjqJe3A==", + "version": "10.4.15", + "resolved": "https://registry.npmjs.org/@nestjs/testing/-/testing-10.4.15.tgz", + "integrity": "sha512-eGlWESkACMKti+iZk1hs6FUY/UqObmMaa8HAN9JLnaYkoLf1Jeh+EuHlGnfqo/Rq77oznNLIyaA3PFjrFDlNUg==", "dev": true, + "license": "MIT", "dependencies": { - "tslib": "2.7.0" + "tslib": "2.8.1" }, "funding": { "type": "opencollective", @@ -2449,16 +2257,11 @@ } } }, - "node_modules/@nestjs/testing/node_modules/tslib": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", - "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", - "dev": true - }, "node_modules/@nestjs/typeorm": { "version": "10.0.2", "resolved": "https://registry.npmjs.org/@nestjs/typeorm/-/typeorm-10.0.2.tgz", "integrity": "sha512-H738bJyydK4SQkRCTeh1aFBxoO1E9xdL/HaLGThwrqN95os5mEyAtK7BLADOS+vldP4jDZ2VQPLj4epWwRqCeQ==", + "license": "MIT", "dependencies": { "uuid": "9.0.1" }, @@ -2470,14 +2273,28 @@ "typeorm": "^0.3.0" } }, + "node_modules/@nestjs/typeorm/node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, "node_modules/@nestjs/websockets": { - "version": "10.4.6", - "resolved": "https://registry.npmjs.org/@nestjs/websockets/-/websockets-10.4.6.tgz", - "integrity": "sha512-53YqDQylPAOudNFiiBvrN8QrRl/sZ9oEjKbD3wBVgrFREbaiuTySoyyy6HwVs60HW29uQwck+Bp7qkKGjhtQKg==", + "version": "10.4.15", + "resolved": "https://registry.npmjs.org/@nestjs/websockets/-/websockets-10.4.15.tgz", + "integrity": "sha512-OmCUJwvtagzXfMVko595O98UI3M9zg+URL+/HV7vd3QPMCZ3uGCKSq15YYJ99LHJn9NyK4e4Szm2KnHtUg2QzA==", + "license": "MIT", "dependencies": { "iterare": "1.2.1", "object-hash": "3.0.0", - "tslib": "2.7.0" + "tslib": "2.8.1" }, "peerDependencies": { "@nestjs/common": "^10.0.0", @@ -2492,23 +2309,20 @@ } } }, - "node_modules/@nestjs/websockets/node_modules/tslib": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", - "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==" - }, "node_modules/@next/env": { - "version": "14.2.3", - "resolved": "https://registry.npmjs.org/@next/env/-/env-14.2.3.tgz", - "integrity": "sha512-W7fd7IbkfmeeY2gXrzJYDx8D2lWKbVoTIj1o1ScPHNzvp30s1AuoEFSdr39bC5sjxJaxTtq3OTCZboNp0lNWHA==" + "version": "15.0.4", + "resolved": "https://registry.npmjs.org/@next/env/-/env-15.0.4.tgz", + "integrity": "sha512-WNRvtgnRVDD4oM8gbUcRc27IAhaL4eXQ/2ovGbgLnPGUvdyDr8UdXP4Q/IBDdAdojnD2eScryIDirv0YUCjUVw==", + "license": "MIT" }, "node_modules/@next/swc-darwin-arm64": { - "version": "14.2.3", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.2.3.tgz", - "integrity": "sha512-3pEYo/RaGqPP0YzwnlmPN2puaF2WMLM3apt5jLW2fFdXD9+pqcoTzRk+iZsf8ta7+quAe4Q6Ms0nR0SFGFdS1A==", + "version": "15.0.4", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-15.0.4.tgz", + "integrity": "sha512-QecQXPD0yRHxSXWL5Ff80nD+A56sUXZG9koUsjWJwA2Z0ZgVQfuy7gd0/otjxoOovPVHR2eVEvPMHbtZP+pf9w==", "cpu": [ "arm64" ], + "license": "MIT", "optional": true, "os": [ "darwin" @@ -2518,12 +2332,13 @@ } }, "node_modules/@next/swc-darwin-x64": { - "version": "14.2.3", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-14.2.3.tgz", - "integrity": "sha512-6adp7waE6P1TYFSXpY366xwsOnEXM+y1kgRpjSRVI2CBDOcbRjsJ67Z6EgKIqWIue52d2q/Mx8g9MszARj8IEA==", + "version": "15.0.4", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-15.0.4.tgz", + "integrity": "sha512-pb7Bye3y1Og3PlCtnz2oO4z+/b3pH2/HSYkLbL0hbVuTGil7fPen8/3pyyLjdiTLcFJ+ymeU3bck5hd4IPFFCA==", "cpu": [ "x64" ], + "license": "MIT", "optional": true, "os": [ "darwin" @@ -2533,12 +2348,13 @@ } }, "node_modules/@next/swc-linux-arm64-gnu": { - "version": "14.2.3", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.2.3.tgz", - "integrity": "sha512-cuzCE/1G0ZSnTAHJPUT1rPgQx1w5tzSX7POXSLaS7w2nIUJUD+e25QoXD/hMfxbsT9rslEXugWypJMILBj/QsA==", + "version": "15.0.4", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-15.0.4.tgz", + "integrity": "sha512-12oSaBFjGpB227VHzoXF3gJoK2SlVGmFJMaBJSu5rbpaoT5OjP5OuCLuR9/jnyBF1BAWMs/boa6mLMoJPRriMA==", "cpu": [ "arm64" ], + "license": "MIT", "optional": true, "os": [ "linux" @@ -2548,12 +2364,13 @@ } }, "node_modules/@next/swc-linux-arm64-musl": { - "version": "14.2.3", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.2.3.tgz", - "integrity": "sha512-0D4/oMM2Y9Ta3nGuCcQN8jjJjmDPYpHX9OJzqk42NZGJocU2MqhBq5tWkJrUQOQY9N+In9xOdymzapM09GeiZw==", + "version": "15.0.4", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-15.0.4.tgz", + "integrity": "sha512-QARO88fR/a+wg+OFC3dGytJVVviiYFEyjc/Zzkjn/HevUuJ7qGUUAUYy5PGVWY1YgTzeRYz78akQrVQ8r+sMjw==", "cpu": [ "arm64" ], + "license": "MIT", "optional": true, "os": [ "linux" @@ -2563,12 +2380,13 @@ } }, "node_modules/@next/swc-linux-x64-gnu": { - "version": "14.2.3", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.2.3.tgz", - "integrity": "sha512-ENPiNnBNDInBLyUU5ii8PMQh+4XLr4pG51tOp6aJ9xqFQ2iRI6IH0Ds2yJkAzNV1CfyagcyzPfROMViS2wOZ9w==", + "version": "15.0.4", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-15.0.4.tgz", + "integrity": "sha512-Z50b0gvYiUU1vLzfAMiChV8Y+6u/T2mdfpXPHraqpypP7yIT2UV9YBBhcwYkxujmCvGEcRTVWOj3EP7XW/wUnw==", "cpu": [ "x64" ], + "license": "MIT", "optional": true, "os": [ "linux" @@ -2578,12 +2396,13 @@ } }, "node_modules/@next/swc-linux-x64-musl": { - "version": "14.2.3", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.2.3.tgz", - "integrity": "sha512-BTAbq0LnCbF5MtoM7I/9UeUu/8ZBY0i8SFjUMCbPDOLv+un67e2JgyN4pmgfXBwy/I+RHu8q+k+MCkDN6P9ViQ==", + "version": "15.0.4", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-15.0.4.tgz", + "integrity": "sha512-7H9C4FAsrTAbA/ENzvFWsVytqRYhaJYKa2B3fyQcv96TkOGVMcvyS6s+sj4jZlacxxTcn7ygaMXUPkEk7b78zw==", "cpu": [ "x64" ], + "license": "MIT", "optional": true, "os": [ "linux" @@ -2593,27 +2412,13 @@ } }, "node_modules/@next/swc-win32-arm64-msvc": { - "version": "14.2.3", - "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.2.3.tgz", - "integrity": "sha512-AEHIw/dhAMLNFJFJIJIyOFDzrzI5bAjI9J26gbO5xhAKHYTZ9Or04BesFPXiAYXDNdrwTP2dQceYA4dL1geu8A==", + "version": "15.0.4", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-15.0.4.tgz", + "integrity": "sha512-Z/v3WV5xRaeWlgJzN9r4PydWD8sXV35ywc28W63i37G2jnUgScA4OOgS8hQdiXLxE3gqfSuHTicUhr7931OXPQ==", "cpu": [ "arm64" ], - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-win32-ia32-msvc": { - "version": "14.2.3", - "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.2.3.tgz", - "integrity": "sha512-vga40n1q6aYb0CLrM+eEmisfKCR45ixQYXuBXxOOmmoV8sYST9k7E3US32FsY+CkkF7NtzdcebiFT4CHuMSyZw==", - "cpu": [ - "ia32" - ], + "license": "MIT", "optional": true, "os": [ "win32" @@ -2623,12 +2428,13 @@ } }, "node_modules/@next/swc-win32-x64-msvc": { - "version": "14.2.3", - "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.2.3.tgz", - "integrity": "sha512-Q1/zm43RWynxrO7lW4ehciQVj+5ePBhOK+/K2P7pLFX3JaJ/IZVC69SHidrmZSOkqz7ECIOhhy7XhAFG4JYyHA==", + "version": "15.0.4", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-15.0.4.tgz", + "integrity": "sha512-NGLchGruagh8lQpDr98bHLyWJXOBSmkEAfK980OiNBa7vNm6PsNoPvzTfstT78WyOeMRQphEQ455rggd7Eo+Dw==", "cpu": [ "x64" ], + "license": "MIT", "optional": true, "os": [ "win32" @@ -2641,6 +2447,7 @@ "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "license": "MIT", "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" @@ -2653,6 +2460,7 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "license": "MIT", "engines": { "node": ">= 8" } @@ -2661,6 +2469,7 @@ "version": "1.2.8", "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "license": "MIT", "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" @@ -2673,6 +2482,7 @@ "version": "0.3.2", "resolved": "https://registry.npmjs.org/@nuxtjs/opencollective/-/opencollective-0.3.2.tgz", "integrity": "sha512-um0xL3fO7Mf4fDxcqx9KryrB7zgRM5JSlvGN5AGkP6JLM5XEKyjeAiPbNxdXVXQ16isuAhYpvP88NgL2BGd6aA==", + "license": "MIT", "dependencies": { "chalk": "^4.1.0", "consola": "^2.15.0", @@ -2686,23 +2496,20 @@ "npm": ">=5.0.0" } }, - "node_modules/@one-ini/wasm": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@one-ini/wasm/-/wasm-0.1.1.tgz", - "integrity": "sha512-XuySG1E38YScSJoMlqovLru4KTUNSjgVTIjyh7qMX6aNN5HY5Ct5LhRJdxO79JtTzKfzV/bnWpz+zquYrISsvw==" - }, "node_modules/@opentelemetry/api": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.8.0.tgz", - "integrity": "sha512-I/s6F7yKUDdtMsoBWXJe8Qz40Tui5vsuKCWJEWVL+5q9sSWRzzx6v2KeNsOBEwd94j0eWkpWCH4yB6rZg9Mf0w==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.9.0.tgz", + "integrity": "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==", + "license": "Apache-2.0", "engines": { "node": ">=8.0.0" } }, "node_modules/@opentelemetry/api-logs": { - "version": "0.54.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.54.0.tgz", - "integrity": "sha512-9HhEh5GqFrassUndqJsyW7a0PzfyWr2eV2xwzHLIS+wX3125+9HE9FMRAKmJRwxZhgZGwH3HNQQjoMGZqmOeVA==", + "version": "0.56.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.56.0.tgz", + "integrity": "sha512-Wr39+94UNNG3Ei9nv3pHd4AJ63gq5nSemMRpCd8fPwDL9rN3vK26lzxfH27mw16XzOSO+TpyQwBAMaLxaPWG0g==", + "license": "Apache-2.0", "dependencies": { "@opentelemetry/api": "^1.3.0" }, @@ -2711,57 +2518,58 @@ } }, "node_modules/@opentelemetry/auto-instrumentations-node": { - "version": "0.52.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/auto-instrumentations-node/-/auto-instrumentations-node-0.52.0.tgz", - "integrity": "sha512-J9SgX7NOpTvQ7itvlOlHP3lTlsMWtVh5WQSHUSTlg2m3A9HlZBri2DtZ8QgNj8rYWe0EQxQ3TQ3H6vabfun4vw==", - "dependencies": { - "@opentelemetry/instrumentation": "^0.54.0", - "@opentelemetry/instrumentation-amqplib": "^0.43.0", - "@opentelemetry/instrumentation-aws-lambda": "^0.46.0", - "@opentelemetry/instrumentation-aws-sdk": "^0.45.0", - "@opentelemetry/instrumentation-bunyan": "^0.42.0", - "@opentelemetry/instrumentation-cassandra-driver": "^0.42.0", - "@opentelemetry/instrumentation-connect": "^0.40.0", - "@opentelemetry/instrumentation-cucumber": "^0.10.0", - "@opentelemetry/instrumentation-dataloader": "^0.13.0", - "@opentelemetry/instrumentation-dns": "^0.40.0", - "@opentelemetry/instrumentation-express": "^0.44.0", - "@opentelemetry/instrumentation-fastify": "^0.41.0", - "@opentelemetry/instrumentation-fs": "^0.16.0", - "@opentelemetry/instrumentation-generic-pool": "^0.40.0", - "@opentelemetry/instrumentation-graphql": "^0.44.0", - "@opentelemetry/instrumentation-grpc": "^0.54.0", - "@opentelemetry/instrumentation-hapi": "^0.42.0", - "@opentelemetry/instrumentation-http": "^0.54.0", - "@opentelemetry/instrumentation-ioredis": "^0.44.0", - "@opentelemetry/instrumentation-kafkajs": "^0.4.0", - "@opentelemetry/instrumentation-knex": "^0.41.0", - "@opentelemetry/instrumentation-koa": "^0.44.0", - "@opentelemetry/instrumentation-lru-memoizer": "^0.41.0", - "@opentelemetry/instrumentation-memcached": "^0.40.0", - "@opentelemetry/instrumentation-mongodb": "^0.48.0", - "@opentelemetry/instrumentation-mongoose": "^0.43.0", - "@opentelemetry/instrumentation-mysql": "^0.42.0", - "@opentelemetry/instrumentation-mysql2": "^0.42.0", - "@opentelemetry/instrumentation-nestjs-core": "^0.41.0", - "@opentelemetry/instrumentation-net": "^0.40.0", - "@opentelemetry/instrumentation-pg": "^0.47.0", - "@opentelemetry/instrumentation-pino": "^0.43.0", - "@opentelemetry/instrumentation-redis": "^0.43.0", - "@opentelemetry/instrumentation-redis-4": "^0.43.0", - "@opentelemetry/instrumentation-restify": "^0.42.0", - "@opentelemetry/instrumentation-router": "^0.41.0", - "@opentelemetry/instrumentation-socket.io": "^0.43.0", - "@opentelemetry/instrumentation-tedious": "^0.15.0", - "@opentelemetry/instrumentation-undici": "^0.7.0", - "@opentelemetry/instrumentation-winston": "^0.41.0", - "@opentelemetry/resource-detector-alibaba-cloud": "^0.29.4", - "@opentelemetry/resource-detector-aws": "^1.7.0", - "@opentelemetry/resource-detector-azure": "^0.2.12", - "@opentelemetry/resource-detector-container": "^0.5.0", - "@opentelemetry/resource-detector-gcp": "^0.29.13", + "version": "0.54.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/auto-instrumentations-node/-/auto-instrumentations-node-0.54.0.tgz", + "integrity": "sha512-MJYh3hUN7FupIXGy/cOiMoTIM3lTELXFiu9dFXD6YK9AE/Uez2YfgRnHyotD9h/qJeL7uDcI5DHAGkbb/2EdOQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.56.0", + "@opentelemetry/instrumentation-amqplib": "^0.45.0", + "@opentelemetry/instrumentation-aws-lambda": "^0.49.0", + "@opentelemetry/instrumentation-aws-sdk": "^0.48.0", + "@opentelemetry/instrumentation-bunyan": "^0.44.0", + "@opentelemetry/instrumentation-cassandra-driver": "^0.44.0", + "@opentelemetry/instrumentation-connect": "^0.42.0", + "@opentelemetry/instrumentation-cucumber": "^0.12.0", + "@opentelemetry/instrumentation-dataloader": "^0.15.0", + "@opentelemetry/instrumentation-dns": "^0.42.0", + "@opentelemetry/instrumentation-express": "^0.46.0", + "@opentelemetry/instrumentation-fastify": "^0.43.0", + "@opentelemetry/instrumentation-fs": "^0.18.0", + "@opentelemetry/instrumentation-generic-pool": "^0.42.0", + "@opentelemetry/instrumentation-graphql": "^0.46.0", + "@opentelemetry/instrumentation-grpc": "^0.56.0", + "@opentelemetry/instrumentation-hapi": "^0.44.0", + "@opentelemetry/instrumentation-http": "^0.56.0", + "@opentelemetry/instrumentation-ioredis": "^0.46.0", + "@opentelemetry/instrumentation-kafkajs": "^0.6.0", + "@opentelemetry/instrumentation-knex": "^0.43.0", + "@opentelemetry/instrumentation-koa": "^0.46.0", + "@opentelemetry/instrumentation-lru-memoizer": "^0.43.0", + "@opentelemetry/instrumentation-memcached": "^0.42.0", + "@opentelemetry/instrumentation-mongodb": "^0.50.0", + "@opentelemetry/instrumentation-mongoose": "^0.45.0", + "@opentelemetry/instrumentation-mysql": "^0.44.0", + "@opentelemetry/instrumentation-mysql2": "^0.44.0", + "@opentelemetry/instrumentation-nestjs-core": "^0.43.0", + "@opentelemetry/instrumentation-net": "^0.42.0", + "@opentelemetry/instrumentation-pg": "^0.49.0", + "@opentelemetry/instrumentation-pino": "^0.45.0", + "@opentelemetry/instrumentation-redis": "^0.45.0", + "@opentelemetry/instrumentation-redis-4": "^0.45.0", + "@opentelemetry/instrumentation-restify": "^0.44.0", + "@opentelemetry/instrumentation-router": "^0.43.0", + "@opentelemetry/instrumentation-socket.io": "^0.45.0", + "@opentelemetry/instrumentation-tedious": "^0.17.0", + "@opentelemetry/instrumentation-undici": "^0.9.0", + "@opentelemetry/instrumentation-winston": "^0.43.0", + "@opentelemetry/resource-detector-alibaba-cloud": "^0.29.6", + "@opentelemetry/resource-detector-aws": "^1.9.0", + "@opentelemetry/resource-detector-azure": "^0.4.0", + "@opentelemetry/resource-detector-container": "^0.5.2", + "@opentelemetry/resource-detector-gcp": "^0.31.0", "@opentelemetry/resources": "^1.24.0", - "@opentelemetry/sdk-node": "^0.54.0" + "@opentelemetry/sdk-node": "^0.56.0" }, "engines": { "node": ">=14" @@ -2771,9 +2579,10 @@ } }, "node_modules/@opentelemetry/context-async-hooks": { - "version": "1.27.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/context-async-hooks/-/context-async-hooks-1.27.0.tgz", - "integrity": "sha512-CdZ3qmHCwNhFAzjTgHqrDQ44Qxcpz43cVxZRhOs+Ns/79ug+Mr84Bkb626bkJLkA3+BLimA5YAEVRlJC6pFb7g==", + "version": "1.29.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/context-async-hooks/-/context-async-hooks-1.29.0.tgz", + "integrity": "sha512-TKT91jcFXgHyIDF1lgJF3BHGIakn6x0Xp7Tq3zoS3TMPzT9IlP0xEavWP8C1zGjU9UmZP2VR1tJhW9Az1A3w8Q==", + "license": "Apache-2.0", "engines": { "node": ">=14" }, @@ -2782,11 +2591,12 @@ } }, "node_modules/@opentelemetry/core": { - "version": "1.27.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.27.0.tgz", - "integrity": "sha512-yQPKnK5e+76XuiqUH/gKyS8wv/7qITd5ln56QkBTf3uggr0VkXOXfcaAuG330UfdYu83wsyoBwqwxigpIG+Jkg==", + "version": "1.29.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.29.0.tgz", + "integrity": "sha512-gmT7vAreXl0DTHD2rVZcw3+l2g84+5XiHIqdBUxXbExymPCvSsGOpiwMmn8nkiJur28STV31wnhIDrzWDPzjfA==", + "license": "Apache-2.0", "dependencies": { - "@opentelemetry/semantic-conventions": "1.27.0" + "@opentelemetry/semantic-conventions": "1.28.0" }, "engines": { "node": ">=14" @@ -2796,15 +2606,16 @@ } }, "node_modules/@opentelemetry/exporter-logs-otlp-grpc": { - "version": "0.54.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-logs-otlp-grpc/-/exporter-logs-otlp-grpc-0.54.0.tgz", - "integrity": "sha512-CQC9xl9p8EIvx2KggdM7yffbpmUArKjiqAcjTTTEvqE8kOOf71NSuBU0FXs14FU8vBGTUlsr3oI4vGeWF8FakA==", + "version": "0.56.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-logs-otlp-grpc/-/exporter-logs-otlp-grpc-0.56.0.tgz", + "integrity": "sha512-/ef8wcphVKZ0uI7A1oqQI/gEMiBUlkeBkM9AGx6AviQFIbgPVSdNK3+bHBkyq5qMkyWgkeQCSJ0uhc5vJpf0dw==", + "license": "Apache-2.0", "dependencies": { "@grpc/grpc-js": "^1.7.1", - "@opentelemetry/core": "1.27.0", - "@opentelemetry/otlp-grpc-exporter-base": "0.54.0", - "@opentelemetry/otlp-transformer": "0.54.0", - "@opentelemetry/sdk-logs": "0.54.0" + "@opentelemetry/core": "1.29.0", + "@opentelemetry/otlp-grpc-exporter-base": "0.56.0", + "@opentelemetry/otlp-transformer": "0.56.0", + "@opentelemetry/sdk-logs": "0.56.0" }, "engines": { "node": ">=14" @@ -2814,15 +2625,16 @@ } }, "node_modules/@opentelemetry/exporter-logs-otlp-http": { - "version": "0.54.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-logs-otlp-http/-/exporter-logs-otlp-http-0.54.0.tgz", - "integrity": "sha512-EX/5YPtFw5hugURWSmOtJEGsjphkwTRAiv2yay40ADCLEzajhI/tM3v/7hFCj+rm37sGFMNawpi3mGLvfKGexQ==", + "version": "0.56.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-logs-otlp-http/-/exporter-logs-otlp-http-0.56.0.tgz", + "integrity": "sha512-gN/itg2B30pa+yAqiuIHBCf3E77sSBlyWVzb+U/MDLzEMOwfnexlMvOWULnIO1l2xR2MNLEuPCQAOrL92JHEJg==", + "license": "Apache-2.0", "dependencies": { - "@opentelemetry/api-logs": "0.54.0", - "@opentelemetry/core": "1.27.0", - "@opentelemetry/otlp-exporter-base": "0.54.0", - "@opentelemetry/otlp-transformer": "0.54.0", - "@opentelemetry/sdk-logs": "0.54.0" + "@opentelemetry/api-logs": "0.56.0", + "@opentelemetry/core": "1.29.0", + "@opentelemetry/otlp-exporter-base": "0.56.0", + "@opentelemetry/otlp-transformer": "0.56.0", + "@opentelemetry/sdk-logs": "0.56.0" }, "engines": { "node": ">=14" @@ -2832,17 +2644,18 @@ } }, "node_modules/@opentelemetry/exporter-logs-otlp-proto": { - "version": "0.54.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-logs-otlp-proto/-/exporter-logs-otlp-proto-0.54.0.tgz", - "integrity": "sha512-Q8p1eLP6BGu26VdiR8qBiyufXTZimUl2kv6EwZZPLRU0CJWAFR562UOyUtDxbwQioQFq57DVjCd6mQWBvydAlg==", + "version": "0.56.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-logs-otlp-proto/-/exporter-logs-otlp-proto-0.56.0.tgz", + "integrity": "sha512-MaO+eGrdksd8MpEbDDLbWegHc3w6ualZV6CENxNOm3wqob0iOx78/YL2NVIKyP/0ktTUIs7xIppUYqfY3ogFLQ==", + "license": "Apache-2.0", "dependencies": { - "@opentelemetry/api-logs": "0.54.0", - "@opentelemetry/core": "1.27.0", - "@opentelemetry/otlp-exporter-base": "0.54.0", - "@opentelemetry/otlp-transformer": "0.54.0", - "@opentelemetry/resources": "1.27.0", - "@opentelemetry/sdk-logs": "0.54.0", - "@opentelemetry/sdk-trace-base": "1.27.0" + "@opentelemetry/api-logs": "0.56.0", + "@opentelemetry/core": "1.29.0", + "@opentelemetry/otlp-exporter-base": "0.56.0", + "@opentelemetry/otlp-transformer": "0.56.0", + "@opentelemetry/resources": "1.29.0", + "@opentelemetry/sdk-logs": "0.56.0", + "@opentelemetry/sdk-trace-base": "1.29.0" }, "engines": { "node": ">=14" @@ -2852,13 +2665,14 @@ } }, "node_modules/@opentelemetry/exporter-prometheus": { - "version": "0.54.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-prometheus/-/exporter-prometheus-0.54.0.tgz", - "integrity": "sha512-httb+/c36hZvkIR9SqwXj+fLeE2XDdWfZqGO24MboNMHihmnvjE0/LN29I9CjsJqC2jEi8FErfQha/JeOfsFaA==", + "version": "0.56.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-prometheus/-/exporter-prometheus-0.56.0.tgz", + "integrity": "sha512-5kFcTumUveNREskg6n4aaXx2o3ADc9YxDkArGCIegzErlc3zfzreO4Y7HDc/fYBnV9aIhJUk5P8yotyVCuymkQ==", + "license": "Apache-2.0", "dependencies": { - "@opentelemetry/core": "1.27.0", - "@opentelemetry/resources": "1.27.0", - "@opentelemetry/sdk-metrics": "1.27.0" + "@opentelemetry/core": "1.29.0", + "@opentelemetry/resources": "1.29.0", + "@opentelemetry/sdk-metrics": "1.29.0" }, "engines": { "node": ">=14" @@ -2868,16 +2682,17 @@ } }, "node_modules/@opentelemetry/exporter-trace-otlp-grpc": { - "version": "0.54.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-trace-otlp-grpc/-/exporter-trace-otlp-grpc-0.54.0.tgz", - "integrity": "sha512-DOoK7yk/L/RHoyuYTxIyGY7PLFSTS7OGNks9htMS7eAFkm4Lsa6EtPlGANCT39NXWP4XIQR1c+Y+YIQ7lJdI+w==", + "version": "0.56.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-trace-otlp-grpc/-/exporter-trace-otlp-grpc-0.56.0.tgz", + "integrity": "sha512-9hRHue78CV2XShAt30HadBK8XEtOBiQmnkYquR1RQyf2RYIdJvhiypEZ+Jh3NGW8Qi14icTII/1oPTQlhuyQdQ==", + "license": "Apache-2.0", "dependencies": { "@grpc/grpc-js": "^1.7.1", - "@opentelemetry/core": "1.27.0", - "@opentelemetry/otlp-grpc-exporter-base": "0.54.0", - "@opentelemetry/otlp-transformer": "0.54.0", - "@opentelemetry/resources": "1.27.0", - "@opentelemetry/sdk-trace-base": "1.27.0" + "@opentelemetry/core": "1.29.0", + "@opentelemetry/otlp-grpc-exporter-base": "0.56.0", + "@opentelemetry/otlp-transformer": "0.56.0", + "@opentelemetry/resources": "1.29.0", + "@opentelemetry/sdk-trace-base": "1.29.0" }, "engines": { "node": ">=14" @@ -2887,15 +2702,16 @@ } }, "node_modules/@opentelemetry/exporter-trace-otlp-http": { - "version": "0.54.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-trace-otlp-http/-/exporter-trace-otlp-http-0.54.0.tgz", - "integrity": "sha512-00X6rtr6Ew59+MM9pPSH7Ww5ScpWKBLiBA49awbPqQuVL/Bp0qp7O1cTxKHgjWdNkhsELzJxAEYwuRnDGrMXyA==", + "version": "0.56.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-trace-otlp-http/-/exporter-trace-otlp-http-0.56.0.tgz", + "integrity": "sha512-vqVuJvcwameA0r0cNrRzrZqPLB0otS+95g0XkZdiKOXUo81wYdY6r4kyrwz4nSChqTBEFm0lqi/H2OWGboOa6g==", + "license": "Apache-2.0", "dependencies": { - "@opentelemetry/core": "1.27.0", - "@opentelemetry/otlp-exporter-base": "0.54.0", - "@opentelemetry/otlp-transformer": "0.54.0", - "@opentelemetry/resources": "1.27.0", - "@opentelemetry/sdk-trace-base": "1.27.0" + "@opentelemetry/core": "1.29.0", + "@opentelemetry/otlp-exporter-base": "0.56.0", + "@opentelemetry/otlp-transformer": "0.56.0", + "@opentelemetry/resources": "1.29.0", + "@opentelemetry/sdk-trace-base": "1.29.0" }, "engines": { "node": ">=14" @@ -2905,15 +2721,16 @@ } }, "node_modules/@opentelemetry/exporter-trace-otlp-proto": { - "version": "0.54.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-trace-otlp-proto/-/exporter-trace-otlp-proto-0.54.0.tgz", - "integrity": "sha512-cpDQj5wl7G8pLu3lW94SnMpn0C85A9Ehe7+JBow2IL5DGPWXTkynFngMtCC3PpQzQgzlyOVe0MVZfoBB3M5ECA==", + "version": "0.56.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-trace-otlp-proto/-/exporter-trace-otlp-proto-0.56.0.tgz", + "integrity": "sha512-UYVtz8Kp1QZpZFg83ZrnwRIxF2wavNyi1XaIKuQNFjlYuGCh8JH4+GOuHUU4G8cIzOkWdjNR559vv0Q+MCz+1w==", + "license": "Apache-2.0", "dependencies": { - "@opentelemetry/core": "1.27.0", - "@opentelemetry/otlp-exporter-base": "0.54.0", - "@opentelemetry/otlp-transformer": "0.54.0", - "@opentelemetry/resources": "1.27.0", - "@opentelemetry/sdk-trace-base": "1.27.0" + "@opentelemetry/core": "1.29.0", + "@opentelemetry/otlp-exporter-base": "0.56.0", + "@opentelemetry/otlp-transformer": "0.56.0", + "@opentelemetry/resources": "1.29.0", + "@opentelemetry/sdk-trace-base": "1.29.0" }, "engines": { "node": ">=14" @@ -2923,14 +2740,15 @@ } }, "node_modules/@opentelemetry/exporter-zipkin": { - "version": "1.27.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-zipkin/-/exporter-zipkin-1.27.0.tgz", - "integrity": "sha512-eGMY3s4QprspFZojqsuQyQpWNFpo+oNVE/aosTbtvAlrJBAlvXcwwsOROOHOd8Y9lkU4i0FpQW482rcXkgwCSw==", + "version": "1.29.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-zipkin/-/exporter-zipkin-1.29.0.tgz", + "integrity": "sha512-9wNUxbl/sju2AvA3UhL2kLF1nfhJ4dVJgvktc3hx80Bg/fWHvF6ik4R3woZ/5gYFqZ97dcuik0dWPQEzLPNBtg==", + "license": "Apache-2.0", "dependencies": { - "@opentelemetry/core": "1.27.0", - "@opentelemetry/resources": "1.27.0", - "@opentelemetry/sdk-trace-base": "1.27.0", - "@opentelemetry/semantic-conventions": "1.27.0" + "@opentelemetry/core": "1.29.0", + "@opentelemetry/resources": "1.29.0", + "@opentelemetry/sdk-trace-base": "1.29.0", + "@opentelemetry/semantic-conventions": "1.28.0" }, "engines": { "node": ">=14" @@ -2940,12 +2758,13 @@ } }, "node_modules/@opentelemetry/host-metrics": { - "version": "0.35.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/host-metrics/-/host-metrics-0.35.1.tgz", - "integrity": "sha512-d49/Un/pzqUSsGLeO8PvrX2bLxVAORcaoL3nxjJCzGikXA6gjWXxGOfT8D4qePlgnocozppWszefMHoRFS2MsA==", + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@opentelemetry/host-metrics/-/host-metrics-0.35.4.tgz", + "integrity": "sha512-3nPElbfYZ2oKNoMw2CkXkHxQryebqACcSgMbbKcn+GnGKp+h7MeOHyg21NmmTt9xgCvRHYiHNkWGkB4laP0oUw==", + "license": "Apache-2.0", "dependencies": { "@opentelemetry/sdk-metrics": "^1.8.0", - "systeminformation": "^5.21.20" + "systeminformation": "5.22.9" }, "engines": { "node": ">=14" @@ -2955,11 +2774,12 @@ } }, "node_modules/@opentelemetry/instrumentation": { - "version": "0.54.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.54.0.tgz", - "integrity": "sha512-B0Ydo9g9ehgNHwtpc97XivEzjz0XBKR6iQ83NTENIxEEf5NHE0otZQuZLgDdey1XNk+bP1cfRpIkSFWM5YlSyg==", + "version": "0.56.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.56.0.tgz", + "integrity": "sha512-2KkGBKE+FPXU1F0zKww+stnlUxUTlBvLCiWdP63Z9sqXYeNI/ziNzsxAp4LAdUcTQmXjw1IWgvm5CAb/BHy99w==", + "license": "Apache-2.0", "dependencies": { - "@opentelemetry/api-logs": "0.54.0", + "@opentelemetry/api-logs": "0.56.0", "@types/shimmer": "^1.2.0", "import-in-the-middle": "^1.8.1", "require-in-the-middle": "^7.1.1", @@ -2974,12 +2794,13 @@ } }, "node_modules/@opentelemetry/instrumentation-amqplib": { - "version": "0.43.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-amqplib/-/instrumentation-amqplib-0.43.0.tgz", - "integrity": "sha512-ALjfQC+0dnIEcvNYsbZl/VLh7D2P1HhFF4vicRKHhHFIUV3Shpg4kXgiek5PLhmeKSIPiUB25IYH5RIneclL4A==", + "version": "0.45.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-amqplib/-/instrumentation-amqplib-0.45.0.tgz", + "integrity": "sha512-SlKLsOS65NGMIBG1Lh/hLrMDU9WzTUF25apnV6ZmWZB1bBmUwan7qrwwrTu1cL5LzJWCXOdZPuTaxP7pC9qxnQ==", + "license": "Apache-2.0", "dependencies": { "@opentelemetry/core": "^1.8.0", - "@opentelemetry/instrumentation": "^0.54.0", + "@opentelemetry/instrumentation": "^0.56.0", "@opentelemetry/semantic-conventions": "^1.27.0" }, "engines": { @@ -2990,12 +2811,12 @@ } }, "node_modules/@opentelemetry/instrumentation-aws-lambda": { - "version": "0.46.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-aws-lambda/-/instrumentation-aws-lambda-0.46.0.tgz", - "integrity": "sha512-rNmhTC1e1qQD4jw+TZSHlpLYNhrkbKA0P5rlqPpTVHqZXHQctu9+dity2lLBh4DlFKt4p/ibVDLVDoBqjvetKA==", + "version": "0.49.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-aws-lambda/-/instrumentation-aws-lambda-0.49.0.tgz", + "integrity": "sha512-FIKQSzX/MSzfARqgm7lX9p/QUj7USyicioBYI5BFGuOOoLefxBlJINAcRs3EvCh1taEnJ7/LpbrhlcF7r4Yqvg==", + "license": "Apache-2.0", "dependencies": { - "@opentelemetry/instrumentation": "^0.54.0", - "@opentelemetry/propagator-aws-xray": "^1.3.1", + "@opentelemetry/instrumentation": "^0.56.0", "@opentelemetry/semantic-conventions": "^1.27.0", "@types/aws-lambda": "8.10.143" }, @@ -3007,13 +2828,14 @@ } }, "node_modules/@opentelemetry/instrumentation-aws-sdk": { - "version": "0.45.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-aws-sdk/-/instrumentation-aws-sdk-0.45.0.tgz", - "integrity": "sha512-3EGgC0LFZuFfXcOeslhXHhsiInVhhN046YQsYIPflsicAk7v0wN946sZKWuerEfmqx/kFXOsbOeI1SkkTRmqWQ==", + "version": "0.48.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-aws-sdk/-/instrumentation-aws-sdk-0.48.0.tgz", + "integrity": "sha512-Bl4geb9DS5Zxr5mOsDcDTLjwrfipQ4KDl1ZT5gmoOvVuZPp308reGdtnO1QmqbvMwcgMxD2aBdWUoYgtx1WgWw==", + "license": "Apache-2.0", "dependencies": { "@opentelemetry/core": "^1.8.0", - "@opentelemetry/instrumentation": "^0.54.0", - "@opentelemetry/propagation-utils": "^0.30.12", + "@opentelemetry/instrumentation": "^0.56.0", + "@opentelemetry/propagation-utils": "^0.30.14", "@opentelemetry/semantic-conventions": "^1.27.0" }, "engines": { @@ -3024,12 +2846,13 @@ } }, "node_modules/@opentelemetry/instrumentation-bunyan": { - "version": "0.42.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-bunyan/-/instrumentation-bunyan-0.42.0.tgz", - "integrity": "sha512-GBh6ybwKmFZjc86SyHVx72jHg+4pFPaXT3IZgJ4QtnMsMf0/q5m2aHAjid+yakmEkApsnRWX8pJ8nkl1e+6mag==", + "version": "0.44.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-bunyan/-/instrumentation-bunyan-0.44.0.tgz", + "integrity": "sha512-9JHcfUPejOx5ULuxrH5K5qOZ9GJSTisuMSZZFVkDigZJ42pMn26Zgmb1HhuiZXd/ZcFgOeLZcwQNpBmF1whftg==", + "license": "Apache-2.0", "dependencies": { - "@opentelemetry/api-logs": "^0.54.0", - "@opentelemetry/instrumentation": "^0.54.0", + "@opentelemetry/api-logs": "^0.56.0", + "@opentelemetry/instrumentation": "^0.56.0", "@types/bunyan": "1.8.9" }, "engines": { @@ -3040,11 +2863,12 @@ } }, "node_modules/@opentelemetry/instrumentation-cassandra-driver": { - "version": "0.42.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-cassandra-driver/-/instrumentation-cassandra-driver-0.42.0.tgz", - "integrity": "sha512-35I9Gw4BeSs9NPe7fugu9e/mWKaapc/N1wounHnGt259/Q3ISGMOQRrOwIBw+x/XJygJvn4Ss1c+r5h89TsVAw==", + "version": "0.44.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-cassandra-driver/-/instrumentation-cassandra-driver-0.44.0.tgz", + "integrity": "sha512-HbhNoqAelB1T4QtgKJbOy7wB26R15HToLyMmYwNFICyDtfY7nhRmGRSzPt6akpwXpyCq43/P+L6XYTmqSWTK/Q==", + "license": "Apache-2.0", "dependencies": { - "@opentelemetry/instrumentation": "^0.54.0", + "@opentelemetry/instrumentation": "^0.56.0", "@opentelemetry/semantic-conventions": "^1.27.0" }, "engines": { @@ -3055,12 +2879,13 @@ } }, "node_modules/@opentelemetry/instrumentation-connect": { - "version": "0.40.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-connect/-/instrumentation-connect-0.40.0.tgz", - "integrity": "sha512-3aR/3YBQ160siitwwRLjwqrv2KBT16897+bo6yz8wIfel6nWOxTZBJudcbsK3p42pTC7qrbotJ9t/1wRLpv79Q==", + "version": "0.42.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-connect/-/instrumentation-connect-0.42.0.tgz", + "integrity": "sha512-bOoYHBmbnq/jFaLHmXJ55VQ6jrH5fHDMAPjFM0d3JvR0dvIqW7anEoNC33QqYGFYUfVJ50S0d/eoyF61ALqQuA==", + "license": "Apache-2.0", "dependencies": { "@opentelemetry/core": "^1.8.0", - "@opentelemetry/instrumentation": "^0.54.0", + "@opentelemetry/instrumentation": "^0.56.0", "@opentelemetry/semantic-conventions": "^1.27.0", "@types/connect": "3.4.36" }, @@ -3072,11 +2897,12 @@ } }, "node_modules/@opentelemetry/instrumentation-cucumber": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-cucumber/-/instrumentation-cucumber-0.10.0.tgz", - "integrity": "sha512-5sT6Ap3W7StEL0Oax/vd1YTEcTPTefx+9myzkKrr72hxzFzSooGRCxlU3sfPwZqWptUV7+QWTMd7SqGEEPnE/w==", + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-cucumber/-/instrumentation-cucumber-0.12.0.tgz", + "integrity": "sha512-0sAhKYaxi5/SM+z8nbwmezNVlnJGkcZgMA7ClenVMIoH5xjow/b2gzJOWr3Ch7FPEXBcyoY/sIqfYWRwmRXWiw==", + "license": "Apache-2.0", "dependencies": { - "@opentelemetry/instrumentation": "^0.54.0", + "@opentelemetry/instrumentation": "^0.56.0", "@opentelemetry/semantic-conventions": "^1.27.0" }, "engines": { @@ -3087,11 +2913,12 @@ } }, "node_modules/@opentelemetry/instrumentation-dataloader": { - "version": "0.13.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-dataloader/-/instrumentation-dataloader-0.13.0.tgz", - "integrity": "sha512-wbU3WdgUAXljEIY2nfpkqID/VH70ThnES8mZZHKCZlV/Pl5T4+qmrVdT7U9/WUzz8flwsXfER6T6jl48Wbl+LQ==", + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-dataloader/-/instrumentation-dataloader-0.15.0.tgz", + "integrity": "sha512-5fP35A2jUPk4SerVcduEkpbRAIoqa2PaP5rWumn01T1uSbavXNccAr3Xvx1N6xFtZxXpLJq4FYqGFnMgDWgVng==", + "license": "Apache-2.0", "dependencies": { - "@opentelemetry/instrumentation": "^0.54.0" + "@opentelemetry/instrumentation": "^0.56.0" }, "engines": { "node": ">=14" @@ -3101,11 +2928,12 @@ } }, "node_modules/@opentelemetry/instrumentation-dns": { - "version": "0.40.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-dns/-/instrumentation-dns-0.40.0.tgz", - "integrity": "sha512-tLNR8XLPiYRKKk3/UqifXnPP2TVt1RcwvHU0R1ETL1xkZ1ZHMTmSC4x6TignnHOFtRixtJ05EgMGejnffaBXkQ==", + "version": "0.42.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-dns/-/instrumentation-dns-0.42.0.tgz", + "integrity": "sha512-HsKYWwMADJAcdY4UkNNbvcg9cm5Xhz5wxBPyT15z7wigatiEoCXPrbbbRDmCe+eKTc2tRxUPmg49u6MsIGcUmg==", + "license": "Apache-2.0", "dependencies": { - "@opentelemetry/instrumentation": "^0.54.0" + "@opentelemetry/instrumentation": "^0.56.0" }, "engines": { "node": ">=14" @@ -3115,12 +2943,13 @@ } }, "node_modules/@opentelemetry/instrumentation-express": { - "version": "0.44.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-express/-/instrumentation-express-0.44.0.tgz", - "integrity": "sha512-GWgibp6Q0wxyFaaU8ERIgMMYgzcHmGrw3ILUtGchLtLncHNOKk0SNoWGqiylXWWT4HTn5XdV8MGawUgpZh80cA==", + "version": "0.46.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-express/-/instrumentation-express-0.46.0.tgz", + "integrity": "sha512-BCEClDj/HPq/1xYRAlOr6z+OUnbp2eFp18DSrgyQz4IT9pkdYk8eWHnMi9oZSqlC6J5mQzkFmaW5RrKb1GLQhg==", + "license": "Apache-2.0", "dependencies": { "@opentelemetry/core": "^1.8.0", - "@opentelemetry/instrumentation": "^0.54.0", + "@opentelemetry/instrumentation": "^0.56.0", "@opentelemetry/semantic-conventions": "^1.27.0" }, "engines": { @@ -3131,12 +2960,13 @@ } }, "node_modules/@opentelemetry/instrumentation-fastify": { - "version": "0.41.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-fastify/-/instrumentation-fastify-0.41.0.tgz", - "integrity": "sha512-pNRjFvf0mvqfJueaeL/qEkuGJwgtE5pgjIHGYwjc2rMViNCrtY9/Sf+Nu8ww6dDd/Oyk2fwZZP7i0XZfCnETrA==", + "version": "0.43.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-fastify/-/instrumentation-fastify-0.43.0.tgz", + "integrity": "sha512-Lmdsg7tYiV+K3/NKVAQfnnLNGmakUOFdB0PhoTh2aXuSyCmyNnnDvhn2MsArAPTZ68wnD5Llh5HtmiuTkf+DyQ==", + "license": "Apache-2.0", "dependencies": { "@opentelemetry/core": "^1.8.0", - "@opentelemetry/instrumentation": "^0.54.0", + "@opentelemetry/instrumentation": "^0.56.0", "@opentelemetry/semantic-conventions": "^1.27.0" }, "engines": { @@ -3147,12 +2977,13 @@ } }, "node_modules/@opentelemetry/instrumentation-fs": { - "version": "0.16.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-fs/-/instrumentation-fs-0.16.0.tgz", - "integrity": "sha512-hMDRUxV38ln1R3lNz6osj3YjlO32ykbHqVrzG7gEhGXFQfu7LJUx8t9tEwE4r2h3CD4D0Rw4YGDU4yF4mP3ilg==", + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-fs/-/instrumentation-fs-0.18.0.tgz", + "integrity": "sha512-kC40y6CEMONm8/MWwoF5GHWIC7gOdF+g3sgsjfwJaUkgD6bdWV+FgG0XApqSbTQndICKzw3RonVk8i7s6mHqhA==", + "license": "Apache-2.0", "dependencies": { "@opentelemetry/core": "^1.8.0", - "@opentelemetry/instrumentation": "^0.54.0" + "@opentelemetry/instrumentation": "^0.56.0" }, "engines": { "node": ">=14" @@ -3162,11 +2993,12 @@ } }, "node_modules/@opentelemetry/instrumentation-generic-pool": { - "version": "0.40.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-generic-pool/-/instrumentation-generic-pool-0.40.0.tgz", - "integrity": "sha512-k+/JlNDHN3bPi/Cir+Ew6tKHFVCa1ZFeQyGUw5HQkRX/twCRaN3kJFXJW+rDAN90XwK3RtC9AWwBihDGh/oSlQ==", + "version": "0.42.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-generic-pool/-/instrumentation-generic-pool-0.42.0.tgz", + "integrity": "sha512-J4QxqiQ1imtB9ogzsOnHra0g3dmmLAx4JCeoK3o0rFes1OirljNHnO8Hsj4s1jAir8WmWvnEEQO1y8yk6j2tog==", + "license": "Apache-2.0", "dependencies": { - "@opentelemetry/instrumentation": "^0.54.0" + "@opentelemetry/instrumentation": "^0.56.0" }, "engines": { "node": ">=14" @@ -3176,11 +3008,12 @@ } }, "node_modules/@opentelemetry/instrumentation-graphql": { - "version": "0.44.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-graphql/-/instrumentation-graphql-0.44.0.tgz", - "integrity": "sha512-FYXTe3Bv96aNpYktqm86BFUTpjglKD0kWI5T5bxYkLUPEPvFn38vWGMJTGrDMVou/i55E4jlWvcm6hFIqLsMbg==", + "version": "0.46.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-graphql/-/instrumentation-graphql-0.46.0.tgz", + "integrity": "sha512-tplk0YWINSECcK89PGM7IVtOYenXyoOuhOQlN0X0YrcDUfMS4tZMKkVc0vyhNWYYrexnUHwNry2YNBNugSpjlQ==", + "license": "Apache-2.0", "dependencies": { - "@opentelemetry/instrumentation": "^0.54.0" + "@opentelemetry/instrumentation": "^0.56.0" }, "engines": { "node": ">=14" @@ -3190,12 +3023,13 @@ } }, "node_modules/@opentelemetry/instrumentation-grpc": { - "version": "0.54.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-grpc/-/instrumentation-grpc-0.54.0.tgz", - "integrity": "sha512-IwLwAf1uC6I5lYjUxfvG0jFuppqNuaBIiaDxYFHMWeRX1Rejh4eqtQi2u+VVtSOHsCn2sRnS9hOxQ2w7+zzPLw==", + "version": "0.56.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-grpc/-/instrumentation-grpc-0.56.0.tgz", + "integrity": "sha512-cmqCZqyKtyu4oLx3rQmPMeqAo69er7ULnbEBTFCW0++AAimIoAXJptrEvB5X9HYr0NP2TqF8As/vlV3IVmY5OQ==", + "license": "Apache-2.0", "dependencies": { - "@opentelemetry/instrumentation": "0.54.0", - "@opentelemetry/semantic-conventions": "1.27.0" + "@opentelemetry/instrumentation": "0.56.0", + "@opentelemetry/semantic-conventions": "1.28.0" }, "engines": { "node": ">=14" @@ -3205,12 +3039,13 @@ } }, "node_modules/@opentelemetry/instrumentation-hapi": { - "version": "0.42.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-hapi/-/instrumentation-hapi-0.42.0.tgz", - "integrity": "sha512-TQC0BtIWLHrp6nKsYdZ5t5B7aiZ16BwbRqZtYYQxeJVsq/HQTANWpknjtA7KMxv5tAUMCrU/eDo8F3qioUOSZg==", + "version": "0.44.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-hapi/-/instrumentation-hapi-0.44.0.tgz", + "integrity": "sha512-4HdNIMNXWK1O6nsaQOrACo83QWEVoyNODTdVDbUqtqXiv2peDfD0RAPhSQlSGWLPw3S4d9UoOmrV7s2HYj6T2A==", + "license": "Apache-2.0", "dependencies": { "@opentelemetry/core": "^1.8.0", - "@opentelemetry/instrumentation": "^0.54.0", + "@opentelemetry/instrumentation": "^0.56.0", "@opentelemetry/semantic-conventions": "^1.27.0" }, "engines": { @@ -3221,13 +3056,14 @@ } }, "node_modules/@opentelemetry/instrumentation-http": { - "version": "0.54.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-http/-/instrumentation-http-0.54.0.tgz", - "integrity": "sha512-ovl0UrL+vGpi0O7fdZ1mHRdiQkuv6NGMRBRKZZygVCUFNXdoqTpvJRRbTYih5U5FC+PHIFssEordmlblRCaGUg==", - "dependencies": { - "@opentelemetry/core": "1.27.0", - "@opentelemetry/instrumentation": "0.54.0", - "@opentelemetry/semantic-conventions": "1.27.0", + "version": "0.56.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-http/-/instrumentation-http-0.56.0.tgz", + "integrity": "sha512-/bWHBUAq8VoATnH9iLk5w8CE9+gj+RgYSUphe7hry472n6fYl7+4PvuScoQMdmSUTprKq/gyr2kOWL6zrC7FkQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "1.29.0", + "@opentelemetry/instrumentation": "0.56.0", + "@opentelemetry/semantic-conventions": "1.28.0", "forwarded-parse": "2.1.2", "semver": "^7.5.2" }, @@ -3239,11 +3075,12 @@ } }, "node_modules/@opentelemetry/instrumentation-ioredis": { - "version": "0.44.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-ioredis/-/instrumentation-ioredis-0.44.0.tgz", - "integrity": "sha512-312pE2xc0ihX9haTf9WC4OF9in5EfVO1y5I8Ef9aMQKJNhuSe3IgzQAqGoLfaYajC+ig0IZ9SQKU8mRbFwHU+A==", + "version": "0.46.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-ioredis/-/instrumentation-ioredis-0.46.0.tgz", + "integrity": "sha512-sOdsq8oGi29V58p1AkefHvuB3l2ymP1IbxRIX3y4lZesQWKL8fLhBmy8xYjINSQ5gHzWul2yoz7pe7boxhZcqQ==", + "license": "Apache-2.0", "dependencies": { - "@opentelemetry/instrumentation": "^0.54.0", + "@opentelemetry/instrumentation": "^0.56.0", "@opentelemetry/redis-common": "^0.36.2", "@opentelemetry/semantic-conventions": "^1.27.0" }, @@ -3255,11 +3092,12 @@ } }, "node_modules/@opentelemetry/instrumentation-kafkajs": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-kafkajs/-/instrumentation-kafkajs-0.4.0.tgz", - "integrity": "sha512-I9VwDG314g7SDL4t8kD/7+1ytaDBRbZQjhVaQaVIDR8K+mlsoBhLsWH79yHxhHQKvwCSZwqXF+TiTOhoQVUt7A==", + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-kafkajs/-/instrumentation-kafkajs-0.6.0.tgz", + "integrity": "sha512-MGQrzqEUAl0tacKJUFpuNHJesyTi51oUzSVizn7FdvJplkRIdS11FukyZBZJEscofSEdk7Ycmg+kNMLi5QHUFg==", + "license": "Apache-2.0", "dependencies": { - "@opentelemetry/instrumentation": "^0.54.0", + "@opentelemetry/instrumentation": "^0.56.0", "@opentelemetry/semantic-conventions": "^1.27.0" }, "engines": { @@ -3270,11 +3108,12 @@ } }, "node_modules/@opentelemetry/instrumentation-knex": { - "version": "0.41.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-knex/-/instrumentation-knex-0.41.0.tgz", - "integrity": "sha512-OhI1SlLv5qnsnm2dOVrian/x3431P75GngSpnR7c4fcVFv7prXGYu29Z6ILRWJf/NJt6fkbySmwdfUUnFnHCTg==", + "version": "0.43.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-knex/-/instrumentation-knex-0.43.0.tgz", + "integrity": "sha512-mOp0TRQNFFSBj5am0WF67fRO7UZMUmsF3/7HSDja9g3H4pnj+4YNvWWyZn4+q0rGrPtywminAXe0rxtgaGYIqg==", + "license": "Apache-2.0", "dependencies": { - "@opentelemetry/instrumentation": "^0.54.0", + "@opentelemetry/instrumentation": "^0.56.0", "@opentelemetry/semantic-conventions": "^1.27.0" }, "engines": { @@ -3285,12 +3124,13 @@ } }, "node_modules/@opentelemetry/instrumentation-koa": { - "version": "0.44.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-koa/-/instrumentation-koa-0.44.0.tgz", - "integrity": "sha512-ryPqGIQ4hpMGd85bAGjRMDAy/ic+Qdh1GtFGJo9KaXdzbcvZoF1ZgXVsKTYDxbD1n5C0BoQy6rcWg8Lu68iCJA==", + "version": "0.46.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-koa/-/instrumentation-koa-0.46.0.tgz", + "integrity": "sha512-RcWXMQdJQANnPUaXbHY5G0Fg6gmleZ/ZtZeSsekWPaZmQq12FGk0L1UwodIgs31OlYfviAZ4yTeytoSUkgo5vQ==", + "license": "Apache-2.0", "dependencies": { "@opentelemetry/core": "^1.8.0", - "@opentelemetry/instrumentation": "^0.54.0", + "@opentelemetry/instrumentation": "^0.56.0", "@opentelemetry/semantic-conventions": "^1.27.0" }, "engines": { @@ -3301,11 +3141,12 @@ } }, "node_modules/@opentelemetry/instrumentation-lru-memoizer": { - "version": "0.41.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-lru-memoizer/-/instrumentation-lru-memoizer-0.41.0.tgz", - "integrity": "sha512-6OePkk4RYCPVsnS0TroEK6UZzxxxjVWaE6EPdOn2qxGHMtm+Qb80tiBQ6BbmC+f7bjc27O85JY8gxeTybhHZXw==", + "version": "0.43.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-lru-memoizer/-/instrumentation-lru-memoizer-0.43.0.tgz", + "integrity": "sha512-fZc+1eJUV+tFxaB3zkbupiA8SL3vhDUq89HbDNg1asweYrEb9OlHIB+Ot14ZiHUc1qCmmWmZHbPTwa56mVVwzg==", + "license": "Apache-2.0", "dependencies": { - "@opentelemetry/instrumentation": "^0.54.0" + "@opentelemetry/instrumentation": "^0.56.0" }, "engines": { "node": ">=14" @@ -3315,11 +3156,12 @@ } }, "node_modules/@opentelemetry/instrumentation-memcached": { - "version": "0.40.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-memcached/-/instrumentation-memcached-0.40.0.tgz", - "integrity": "sha512-VzJUUH6cVz8yrb25RvvjhxCpwu4vUk28I0m5nnnhebULOo8p9lda5PgQeVde2+jQAd977C/vN714fkbYOmwb+A==", + "version": "0.42.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-memcached/-/instrumentation-memcached-0.42.0.tgz", + "integrity": "sha512-6peg2nImB4JNpK+kW95b12B6tRSwRpc0KCm6Ol41uDYPli800J9vWi+DGoPsmTrgZpkEfCe9Z9Ob9Z6Fth2zwg==", + "license": "Apache-2.0", "dependencies": { - "@opentelemetry/instrumentation": "^0.54.0", + "@opentelemetry/instrumentation": "^0.56.0", "@opentelemetry/semantic-conventions": "^1.27.0", "@types/memcached": "^2.2.6" }, @@ -3331,11 +3173,12 @@ } }, "node_modules/@opentelemetry/instrumentation-mongodb": { - "version": "0.48.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-mongodb/-/instrumentation-mongodb-0.48.0.tgz", - "integrity": "sha512-9YWvaGvrrcrydMsYGLu0w+RgmosLMKe3kv/UNlsPy8RLnCkN2z+bhhbjjjuxtUmvEuKZMCoXFluABVuBr1yhjw==", + "version": "0.50.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-mongodb/-/instrumentation-mongodb-0.50.0.tgz", + "integrity": "sha512-DtwJMjYFXFT5auAvv8aGrBj1h3ciA/dXQom11rxL7B1+Oy3FopSpanvwYxJ+z0qmBrQ1/iMuWELitYqU4LnlkQ==", + "license": "Apache-2.0", "dependencies": { - "@opentelemetry/instrumentation": "^0.54.0", + "@opentelemetry/instrumentation": "^0.56.0", "@opentelemetry/semantic-conventions": "^1.27.0" }, "engines": { @@ -3346,12 +3189,13 @@ } }, "node_modules/@opentelemetry/instrumentation-mongoose": { - "version": "0.43.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-mongoose/-/instrumentation-mongoose-0.43.0.tgz", - "integrity": "sha512-y1mWuL/zb6IKi199HkROgmStxF/ybEsnKYgx+/lpLATd57oZHOqrXP9tLmp9qRVI5c6P5XEWfe7ZCvrj07iDMQ==", + "version": "0.45.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-mongoose/-/instrumentation-mongoose-0.45.0.tgz", + "integrity": "sha512-zHgNh+A01C5baI2mb5dAGyMC7DWmUpOfwpV8axtC0Hd5Uzqv+oqKgKbVDIVhOaDkPxjgVJwYF9YQZl2pw2qxIA==", + "license": "Apache-2.0", "dependencies": { "@opentelemetry/core": "^1.8.0", - "@opentelemetry/instrumentation": "^0.54.0", + "@opentelemetry/instrumentation": "^0.56.0", "@opentelemetry/semantic-conventions": "^1.27.0" }, "engines": { @@ -3362,11 +3206,12 @@ } }, "node_modules/@opentelemetry/instrumentation-mysql": { - "version": "0.42.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-mysql/-/instrumentation-mysql-0.42.0.tgz", - "integrity": "sha512-1GN2EBGVSZABGQ25MSz3faeBW/DwhzmE10aNW1/A2mvQAxF1CvpMk17YmNUzwapVt29iKsiU3SXQG7vjh/019A==", + "version": "0.44.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-mysql/-/instrumentation-mysql-0.44.0.tgz", + "integrity": "sha512-al7jbXvT/uT1KV8gdNDzaWd5/WXf+mrjrsF0/NtbnqLa0UUFGgQnoK3cyborgny7I+KxWhL8h7YPTf6Zq4nKsg==", + "license": "Apache-2.0", "dependencies": { - "@opentelemetry/instrumentation": "^0.54.0", + "@opentelemetry/instrumentation": "^0.56.0", "@opentelemetry/semantic-conventions": "^1.27.0", "@types/mysql": "2.15.26" }, @@ -3378,11 +3223,12 @@ } }, "node_modules/@opentelemetry/instrumentation-mysql2": { - "version": "0.42.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-mysql2/-/instrumentation-mysql2-0.42.0.tgz", - "integrity": "sha512-CQqOjCbHwEnaC+Bd6Sms+82iJkSbPpd7jD7Jwif7q8qXo6yrKLVDYDVK+zKbfnmQtu2xHaHj+xiq4tyjb3sMfg==", + "version": "0.44.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-mysql2/-/instrumentation-mysql2-0.44.0.tgz", + "integrity": "sha512-e9QY4AGsjGFwmfHd6kBa4yPaQZjAq2FuxMb0BbKlXCAjG+jwqw+sr9xWdJGR60jMsTq52hx3mAlE3dUJ9BipxQ==", + "license": "Apache-2.0", "dependencies": { - "@opentelemetry/instrumentation": "^0.54.0", + "@opentelemetry/instrumentation": "^0.56.0", "@opentelemetry/semantic-conventions": "^1.27.0", "@opentelemetry/sql-common": "^0.40.1" }, @@ -3394,11 +3240,12 @@ } }, "node_modules/@opentelemetry/instrumentation-nestjs-core": { - "version": "0.41.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-nestjs-core/-/instrumentation-nestjs-core-0.41.0.tgz", - "integrity": "sha512-XCqtghFktpcJ2BOaJtFfqtTMsHffJADxfYhJl28WT6ygCChS2uZVxMKKLsy+i9VtPaw/i1IumPICL6mbhwq+Vw==", + "version": "0.43.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-nestjs-core/-/instrumentation-nestjs-core-0.43.0.tgz", + "integrity": "sha512-NEo4RU7HTjiaXk3curqXUvCb9alRiFWxQY//+hvDXwWLlADX2vB6QEmVCeEZrKO+6I/tBrI4vNdAnbCY9ldZVg==", + "license": "Apache-2.0", "dependencies": { - "@opentelemetry/instrumentation": "^0.54.0", + "@opentelemetry/instrumentation": "^0.56.0", "@opentelemetry/semantic-conventions": "^1.27.0" }, "engines": { @@ -3409,11 +3256,12 @@ } }, "node_modules/@opentelemetry/instrumentation-net": { - "version": "0.40.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-net/-/instrumentation-net-0.40.0.tgz", - "integrity": "sha512-abErnVRxTmtiF7EvBISW81Se2nj/j3Xtpfy//9++dgvDOXwbcD1Xz1via6ZHOm/VamboGhqPlYiO7ABzluPLwg==", + "version": "0.42.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-net/-/instrumentation-net-0.42.0.tgz", + "integrity": "sha512-RCX1e4aHBxpTdm3xyQWDF6dbfclRY1xXAzZnEwuFj1IO+DAqnu8oO11NRBIfH6TNRBmeBKbpiaGbmzCV9ULwIA==", + "license": "Apache-2.0", "dependencies": { - "@opentelemetry/instrumentation": "^0.54.0", + "@opentelemetry/instrumentation": "^0.56.0", "@opentelemetry/semantic-conventions": "^1.27.0" }, "engines": { @@ -3424,12 +3272,13 @@ } }, "node_modules/@opentelemetry/instrumentation-pg": { - "version": "0.47.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-pg/-/instrumentation-pg-0.47.0.tgz", - "integrity": "sha512-aKu5PCeUv3S8s1wq60JZ2o3DWV2wqvO7WAktjmkx5wXd2+tZRfyDCKFHbP90QuDG1HDzjJ138Ob4d4rJdPETCQ==", + "version": "0.49.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-pg/-/instrumentation-pg-0.49.0.tgz", + "integrity": "sha512-3alvNNjPXVdAPdY1G7nGRVINbDxRK02+KAugDiEpzw0jFQfU8IzFkSWA4jyU4/GbMxKvHD+XIOEfSjpieSodKw==", + "license": "Apache-2.0", "dependencies": { "@opentelemetry/core": "^1.26.0", - "@opentelemetry/instrumentation": "^0.54.0", + "@opentelemetry/instrumentation": "^0.56.0", "@opentelemetry/semantic-conventions": "1.27.0", "@opentelemetry/sql-common": "^0.40.1", "@types/pg": "8.6.1", @@ -3442,24 +3291,24 @@ "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@opentelemetry/instrumentation-pg/node_modules/@types/pg": { - "version": "8.6.1", - "resolved": "https://registry.npmjs.org/@types/pg/-/pg-8.6.1.tgz", - "integrity": "sha512-1Kc4oAGzAl7uqUStZCDvaLFqZrW9qWSjXOmBfdgyBP5La7Us6Mg4GBvRlSoaZMhQF/zSj1C8CtKMBkoiT8eL8w==", - "dependencies": { - "@types/node": "*", - "pg-protocol": "*", - "pg-types": "^2.2.0" + "node_modules/@opentelemetry/instrumentation-pg/node_modules/@opentelemetry/semantic-conventions": { + "version": "1.27.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.27.0.tgz", + "integrity": "sha512-sAay1RrB+ONOem0OZanAR1ZI/k7yDpnOQSQmTMuGImUQb2y8EbSaCJ94FQluM74xoU03vlb2d2U90hZluL6nQg==", + "license": "Apache-2.0", + "engines": { + "node": ">=14" } }, "node_modules/@opentelemetry/instrumentation-pino": { - "version": "0.43.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-pino/-/instrumentation-pino-0.43.0.tgz", - "integrity": "sha512-jlOOgbODWRRNknWXY1VLgmqgG0SO4kLgU3XnejjO/3De4OisroAsMGk+1cRB5AQ6WZ8WLAMkMyTShaOe6j2Asw==", + "version": "0.45.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-pino/-/instrumentation-pino-0.45.0.tgz", + "integrity": "sha512-u7XwRdMDPzB6PHRo1EJNxTmjpHPnLpssYlr5t89aWFXP6fP3M2oRKjyX8EZHTSky/6GOMy860mzmded2VVFvfg==", + "license": "Apache-2.0", "dependencies": { - "@opentelemetry/api-logs": "^0.54.0", + "@opentelemetry/api-logs": "^0.56.0", "@opentelemetry/core": "^1.25.0", - "@opentelemetry/instrumentation": "^0.54.0" + "@opentelemetry/instrumentation": "^0.56.0" }, "engines": { "node": ">=14" @@ -3469,11 +3318,12 @@ } }, "node_modules/@opentelemetry/instrumentation-redis": { - "version": "0.43.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-redis/-/instrumentation-redis-0.43.0.tgz", - "integrity": "sha512-dufe08W3sCOjutbTJmV6tg2Y3+7IBe59oQrnIW2RCgjRhsW0Jjaenezt490eawO0MdXjUfFyrIUg8WetKhE4xA==", + "version": "0.45.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-redis/-/instrumentation-redis-0.45.0.tgz", + "integrity": "sha512-IKooJ9pUwPhL5nGEMi9QXvO6pMhwgJe6BzmZ0BMoZweKasC0Y0GekKjPw86Lhx+X1xoJCOFJhoWE9c5SnBJVcw==", + "license": "Apache-2.0", "dependencies": { - "@opentelemetry/instrumentation": "^0.54.0", + "@opentelemetry/instrumentation": "^0.56.0", "@opentelemetry/redis-common": "^0.36.2", "@opentelemetry/semantic-conventions": "^1.27.0" }, @@ -3485,11 +3335,12 @@ } }, "node_modules/@opentelemetry/instrumentation-redis-4": { - "version": "0.43.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-redis-4/-/instrumentation-redis-4-0.43.0.tgz", - "integrity": "sha512-6B2+CFRY9xRnkeZrSvlTyY2yB/zAgxjbXS5EwXhE3ZAKR1hWWoUzaTADIKT5xe9/VbDW42U3UoOPCcaCmeAXww==", + "version": "0.45.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-redis-4/-/instrumentation-redis-4-0.45.0.tgz", + "integrity": "sha512-Sjgym1xn3mdxPRH5CNZtoz+bFd3E3NlGIu7FoYr4YrQouCc9PbnmoBcmSkEdDy5LYgzNildPgsjx9l0EKNjKTQ==", + "license": "Apache-2.0", "dependencies": { - "@opentelemetry/instrumentation": "^0.54.0", + "@opentelemetry/instrumentation": "^0.56.0", "@opentelemetry/redis-common": "^0.36.2", "@opentelemetry/semantic-conventions": "^1.27.0" }, @@ -3501,12 +3352,13 @@ } }, "node_modules/@opentelemetry/instrumentation-restify": { - "version": "0.42.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-restify/-/instrumentation-restify-0.42.0.tgz", - "integrity": "sha512-ApDD9HNy6de6xrHmISEfkQHwwX1f1JrBj0ADnlk6tVdJ0j/vNmsZNLwaU2IA2K3mHqbp2YLarLgxAZp6rjcfWg==", + "version": "0.44.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-restify/-/instrumentation-restify-0.44.0.tgz", + "integrity": "sha512-JUIs6NcSkH+AtUgaUknD+1M4GQA5vOPKqwJqdaJbaEQzHo+QTDn8GY1iiSKXktL68OwRddbyQv6tu2NyCGcKSw==", + "license": "Apache-2.0", "dependencies": { "@opentelemetry/core": "^1.8.0", - "@opentelemetry/instrumentation": "^0.54.0", + "@opentelemetry/instrumentation": "^0.56.0", "@opentelemetry/semantic-conventions": "^1.27.0" }, "engines": { @@ -3517,11 +3369,12 @@ } }, "node_modules/@opentelemetry/instrumentation-router": { - "version": "0.41.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-router/-/instrumentation-router-0.41.0.tgz", - "integrity": "sha512-IbvzgaoylMqStOOtwucEvSu5CDbfQN+H1ZZ2p6c9Kmvzptqh6G441GFy0FFVVqxOAHNhQm2w6n0Ag8trdBjCfw==", + "version": "0.43.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-router/-/instrumentation-router-0.43.0.tgz", + "integrity": "sha512-IkSBWfzlpwLZSJMj3rDG21bDYqbWvW3D/HEx5yCxjUUWVbcz9tRKXjxwG1LB6ZJfnXwwVIOgbz+7XW0HyAXr9Q==", + "license": "Apache-2.0", "dependencies": { - "@opentelemetry/instrumentation": "^0.54.0", + "@opentelemetry/instrumentation": "^0.56.0", "@opentelemetry/semantic-conventions": "^1.27.0" }, "engines": { @@ -3532,11 +3385,12 @@ } }, "node_modules/@opentelemetry/instrumentation-socket.io": { - "version": "0.43.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-socket.io/-/instrumentation-socket.io-0.43.0.tgz", - "integrity": "sha512-HAQoIZ6N/ey1L4jF69gmqo7RyeSv5rc4sZZAd1v6SVaB8ZolTEyWEzGlu1NRZZTnqfWNxDkX6J1/omWpDd9k0w==", + "version": "0.45.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-socket.io/-/instrumentation-socket.io-0.45.0.tgz", + "integrity": "sha512-X/CUjHqX1mZHEqXjD4AgVA5VXW1JHIauj1LDEjUDky/3RCsUTysj031x0Sq+8yBwcPyHF6k9vZ8DNw+CfxscOQ==", + "license": "Apache-2.0", "dependencies": { - "@opentelemetry/instrumentation": "^0.54.0", + "@opentelemetry/instrumentation": "^0.56.0", "@opentelemetry/semantic-conventions": "^1.27.0" }, "engines": { @@ -3547,11 +3401,12 @@ } }, "node_modules/@opentelemetry/instrumentation-tedious": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-tedious/-/instrumentation-tedious-0.15.0.tgz", - "integrity": "sha512-Kb7yo8Zsq2TUwBbmwYgTAMPK0VbhoS8ikJ6Bup9KrDtCx2JC01nCb+M0VJWXt7tl0+5jARUbKWh5jRSoImxdCw==", + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-tedious/-/instrumentation-tedious-0.17.0.tgz", + "integrity": "sha512-yRBz2409an03uVd1Q2jWMt3SqwZqRFyKoWYYX3hBAtPDazJ4w5L+1VOij71TKwgZxZZNdDBXImTQjii+VeuzLg==", + "license": "Apache-2.0", "dependencies": { - "@opentelemetry/instrumentation": "^0.54.0", + "@opentelemetry/instrumentation": "^0.56.0", "@opentelemetry/semantic-conventions": "^1.27.0", "@types/tedious": "^4.0.14" }, @@ -3563,12 +3418,13 @@ } }, "node_modules/@opentelemetry/instrumentation-undici": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-undici/-/instrumentation-undici-0.7.0.tgz", - "integrity": "sha512-1AAqbVt1QOLgnc9DEkHS2R/0FIPI74ud5qgitwP9sVYzRg6e66bPSoAIARCyuANJrWCUrfgI69vLTfRxhBM+3A==", + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-undici/-/instrumentation-undici-0.9.0.tgz", + "integrity": "sha512-lxc3cpUZ28CqbrWcUHxGW/ObDpMOYbuxF/ZOzeFZq54P9uJ2Cpa8gcrC9F716mtuiMaekwk8D6n34vg/JtkkxQ==", + "license": "Apache-2.0", "dependencies": { "@opentelemetry/core": "^1.8.0", - "@opentelemetry/instrumentation": "^0.54.0" + "@opentelemetry/instrumentation": "^0.56.0" }, "engines": { "node": ">=14" @@ -3578,12 +3434,13 @@ } }, "node_modules/@opentelemetry/instrumentation-winston": { - "version": "0.41.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-winston/-/instrumentation-winston-0.41.0.tgz", - "integrity": "sha512-qtqGDx2Plu71s9xaeXut0YgZFG/y68ENG9vvo/SODeEC+4/APiS/htQ5YNJIxxjOuxYowdFYRqV9Kmef2EUzmw==", + "version": "0.43.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-winston/-/instrumentation-winston-0.43.0.tgz", + "integrity": "sha512-TVvRwqjmf4+CcjsdkXc+VHiIG0Qzzim5dx8cN5wXRt4+UYIjyZpnhi/WmSjC0fJdkKb6DNjTIw7ktmB/eRj/jQ==", + "license": "Apache-2.0", "dependencies": { - "@opentelemetry/api-logs": "^0.54.0", - "@opentelemetry/instrumentation": "^0.54.0" + "@opentelemetry/api-logs": "^0.56.0", + "@opentelemetry/instrumentation": "^0.56.0" }, "engines": { "node": ">=14" @@ -3593,12 +3450,13 @@ } }, "node_modules/@opentelemetry/otlp-exporter-base": { - "version": "0.54.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-exporter-base/-/otlp-exporter-base-0.54.0.tgz", - "integrity": "sha512-g+H7+QleVF/9lz4zhaR9Dt4VwApjqG5WWupy5CTMpWJfHB/nLxBbX73GBZDgdiNfh08nO3rNa6AS7fK8OhgF5g==", + "version": "0.56.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-exporter-base/-/otlp-exporter-base-0.56.0.tgz", + "integrity": "sha512-eURvv0fcmBE+KE1McUeRo+u0n18ZnUeSc7lDlW/dzlqFYasEbsztTK4v0Qf8C4vEY+aMTjPKUxBG0NX2Te3Pmw==", + "license": "Apache-2.0", "dependencies": { - "@opentelemetry/core": "1.27.0", - "@opentelemetry/otlp-transformer": "0.54.0" + "@opentelemetry/core": "1.29.0", + "@opentelemetry/otlp-transformer": "0.56.0" }, "engines": { "node": ">=14" @@ -3608,14 +3466,15 @@ } }, "node_modules/@opentelemetry/otlp-grpc-exporter-base": { - "version": "0.54.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-grpc-exporter-base/-/otlp-grpc-exporter-base-0.54.0.tgz", - "integrity": "sha512-Yl2Dw0jlRWisEia9Hv/N8u2JLITCvzA6gAIKEvxpEu6nwHEftD2WhTJMIclkTtfmSW0rLmEEXymwmboG4xDN0Q==", + "version": "0.56.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-grpc-exporter-base/-/otlp-grpc-exporter-base-0.56.0.tgz", + "integrity": "sha512-QqM4si8Ew8CW5xVk4mYbfusJzMXyk6tkYA5SI0w/5NBxmiZZaYPwQQ2cu58XUH2IMPAsi71yLJVJQaWBBCta0A==", + "license": "Apache-2.0", "dependencies": { "@grpc/grpc-js": "^1.7.1", - "@opentelemetry/core": "1.27.0", - "@opentelemetry/otlp-exporter-base": "0.54.0", - "@opentelemetry/otlp-transformer": "0.54.0" + "@opentelemetry/core": "1.29.0", + "@opentelemetry/otlp-exporter-base": "0.56.0", + "@opentelemetry/otlp-transformer": "0.56.0" }, "engines": { "node": ">=14" @@ -3625,16 +3484,17 @@ } }, "node_modules/@opentelemetry/otlp-transformer": { - "version": "0.54.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-transformer/-/otlp-transformer-0.54.0.tgz", - "integrity": "sha512-jRexIASQQzdK4AjfNIBfn94itAq4Q8EXR9d3b/OVbhd3kKQKvMr7GkxYDjbeTbY7hHCOLcLfJ3dpYQYGOe8qOQ==", - "dependencies": { - "@opentelemetry/api-logs": "0.54.0", - "@opentelemetry/core": "1.27.0", - "@opentelemetry/resources": "1.27.0", - "@opentelemetry/sdk-logs": "0.54.0", - "@opentelemetry/sdk-metrics": "1.27.0", - "@opentelemetry/sdk-trace-base": "1.27.0", + "version": "0.56.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-transformer/-/otlp-transformer-0.56.0.tgz", + "integrity": "sha512-kVkH/W2W7EpgWWpyU5VnnjIdSD7Y7FljQYObAQSKdRcejiwMj2glypZtUdfq1LTJcv4ht0jyTrw1D3CCxssNtQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "0.56.0", + "@opentelemetry/core": "1.29.0", + "@opentelemetry/resources": "1.29.0", + "@opentelemetry/sdk-logs": "0.56.0", + "@opentelemetry/sdk-metrics": "1.29.0", + "@opentelemetry/sdk-trace-base": "1.29.0", "protobufjs": "^7.3.0" }, "engines": { @@ -3645,23 +3505,10 @@ } }, "node_modules/@opentelemetry/propagation-utils": { - "version": "0.30.12", - "resolved": "https://registry.npmjs.org/@opentelemetry/propagation-utils/-/propagation-utils-0.30.12.tgz", - "integrity": "sha512-bgab3q/4dYUutUpQCEaSDa+mLoQJG3vJKeSiGuhM4iZaSpkz8ov0fs1MGil5PfxCo6Hhw3bB3bFYhUtnsfT/Pg==", - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.0.0" - } - }, - "node_modules/@opentelemetry/propagator-aws-xray": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/propagator-aws-xray/-/propagator-aws-xray-1.3.1.tgz", - "integrity": "sha512-6fDMzFlt5r6VWv7MUd0eOpglXPFqykW8CnOuUxJ1VZyLy6mV1bzBlzpsqEmhx1bjvZYvH93vhGkQZqrm95mlrQ==", - "dependencies": { - "@opentelemetry/core": "^1.0.0" - }, + "version": "0.30.14", + "resolved": "https://registry.npmjs.org/@opentelemetry/propagation-utils/-/propagation-utils-0.30.14.tgz", + "integrity": "sha512-RsdKGFd0PYG5Aop9aq8khYbR8Oq+lYTQBX/9/pk7b+8+0WwdFqrvGDmRxpBAH9hgIvtUgETeshlYctwjo2l9SQ==", + "license": "Apache-2.0", "engines": { "node": ">=14" }, @@ -3670,11 +3517,12 @@ } }, "node_modules/@opentelemetry/propagator-b3": { - "version": "1.27.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/propagator-b3/-/propagator-b3-1.27.0.tgz", - "integrity": "sha512-pTsko3gnMioe3FeWcwTQR3omo5C35tYsKKwjgTCTVCgd3EOWL9BZrMfgLBmszrwXABDfUrlAEFN/0W0FfQGynQ==", + "version": "1.29.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/propagator-b3/-/propagator-b3-1.29.0.tgz", + "integrity": "sha512-ktsNDlqhu+/IPGEJRMj81upg2JupUp+SwW3n1ZVZTnrDiYUiMUW41vhaziA7Q6UDhbZvZ58skDpQhe2ZgNIPvg==", + "license": "Apache-2.0", "dependencies": { - "@opentelemetry/core": "1.27.0" + "@opentelemetry/core": "1.29.0" }, "engines": { "node": ">=14" @@ -3684,11 +3532,12 @@ } }, "node_modules/@opentelemetry/propagator-jaeger": { - "version": "1.27.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/propagator-jaeger/-/propagator-jaeger-1.27.0.tgz", - "integrity": "sha512-EI1bbK0wn0yIuKlc2Qv2LKBRw6LiUWevrjCF80fn/rlaB+7StAi8Y5s8DBqAYNpY7v1q86+NjU18v7hj2ejU3A==", + "version": "1.29.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/propagator-jaeger/-/propagator-jaeger-1.29.0.tgz", + "integrity": "sha512-EXIEYmFgybnFMijVgqx1mq/diWwSQcd0JWVksytAVQEnAiaDvP45WuncEVQkFIAC0gVxa2+Xr8wL5pF5jCVKbg==", + "license": "Apache-2.0", "dependencies": { - "@opentelemetry/core": "1.27.0" + "@opentelemetry/core": "1.29.0" }, "engines": { "node": ">=14" @@ -3701,14 +3550,16 @@ "version": "0.36.2", "resolved": "https://registry.npmjs.org/@opentelemetry/redis-common/-/redis-common-0.36.2.tgz", "integrity": "sha512-faYX1N0gpLhej/6nyp6bgRjzAKXn5GOEMYY7YhciSfCoITAktLUtQ36d24QEWNA1/WA1y6qQunCe0OhHRkVl9g==", + "license": "Apache-2.0", "engines": { "node": ">=14" } }, "node_modules/@opentelemetry/resource-detector-alibaba-cloud": { - "version": "0.29.4", - "resolved": "https://registry.npmjs.org/@opentelemetry/resource-detector-alibaba-cloud/-/resource-detector-alibaba-cloud-0.29.4.tgz", - "integrity": "sha512-U3sWPoBXiEE51jJGhRrW19hLvrRbBbZWTp3Yc7IaRVFODNNzmibOolyi2ow1XN68UgRT4BRuwgwbnM5GbG/E5Q==", + "version": "0.29.6", + "resolved": "https://registry.npmjs.org/@opentelemetry/resource-detector-alibaba-cloud/-/resource-detector-alibaba-cloud-0.29.6.tgz", + "integrity": "sha512-BrwutS9Koh08jFhwencsc1t60qEUueMxN+YcN78LE+3r6JMkYgrQzk7C8rJe0nww8KpjZ6A2n7PW+C0FAr8oxg==", + "license": "Apache-2.0", "dependencies": { "@opentelemetry/core": "^1.26.0", "@opentelemetry/resources": "^1.10.0", @@ -3722,9 +3573,10 @@ } }, "node_modules/@opentelemetry/resource-detector-aws": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/resource-detector-aws/-/resource-detector-aws-1.7.0.tgz", - "integrity": "sha512-VxrwUi/9QcVIV+40d/jOKQthfD/E4/ppQ9FsYpDH7qy16cOO5519QOdihCQJYpVNbgDqf6q3hVrCy1f8UuG8YA==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/resource-detector-aws/-/resource-detector-aws-1.9.0.tgz", + "integrity": "sha512-oah9Gek5rrpohjMhQYESnXMDw79wrfhOp0NhjMSjKY9EvNJuDurk/HU3TJ8r2xd/xpGZlcHRZcsJ+qR+tLiQ4g==", + "license": "Apache-2.0", "dependencies": { "@opentelemetry/core": "^1.0.0", "@opentelemetry/resources": "^1.10.0", @@ -3738,9 +3590,10 @@ } }, "node_modules/@opentelemetry/resource-detector-azure": { - "version": "0.2.12", - "resolved": "https://registry.npmjs.org/@opentelemetry/resource-detector-azure/-/resource-detector-azure-0.2.12.tgz", - "integrity": "sha512-iIarQu6MiCjEEp8dOzmBvCSlRITPFTinFB2oNKAjU6xhx8d7eUcjNOKhBGQTvuCriZrxrEvDaEEY9NfrPQ6uYQ==", + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/resource-detector-azure/-/resource-detector-azure-0.4.0.tgz", + "integrity": "sha512-Ix3DwsbUWyLbBCZ1yqT3hJxc5wFPaJ6dvsIgJA/nmjScwscRCWQqTWXywY4+Q+tytLPnuAKZWbBhxcNvNlcn5Q==", + "license": "Apache-2.0", "dependencies": { "@opentelemetry/core": "^1.25.1", "@opentelemetry/resources": "^1.10.1", @@ -3754,9 +3607,10 @@ } }, "node_modules/@opentelemetry/resource-detector-container": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/resource-detector-container/-/resource-detector-container-0.5.0.tgz", - "integrity": "sha512-ozp+ggcbl17xFfL91+DFgP8nmfzthNLxVTDOQUVgQgngVsSaBb5/I1Tnt63ZX2GCMdBJTxUBbFsqFvO0CjfGLg==", + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/@opentelemetry/resource-detector-container/-/resource-detector-container-0.5.2.tgz", + "integrity": "sha512-P06PiIC3kDa/UTLupClJvhLeub84x3eNkDth2yXaMP3UZe/BRGv+R6eeUbMN/MvZhARkpSFnoWpXBHpnq/JiYQ==", + "license": "Apache-2.0", "dependencies": { "@opentelemetry/core": "^1.26.0", "@opentelemetry/resources": "^1.10.0", @@ -3770,9 +3624,10 @@ } }, "node_modules/@opentelemetry/resource-detector-gcp": { - "version": "0.29.13", - "resolved": "https://registry.npmjs.org/@opentelemetry/resource-detector-gcp/-/resource-detector-gcp-0.29.13.tgz", - "integrity": "sha512-vdotx+l3Q+89PeyXMgKEGnZ/CwzwMtuMi/ddgD9/5tKZ08DfDGB2Npz9m2oXPHRCjc4Ro6ifMqFlRyzIvgOjhg==", + "version": "0.31.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/resource-detector-gcp/-/resource-detector-gcp-0.31.0.tgz", + "integrity": "sha512-KNd2Ab3hc0PsBVtWMie11AbQ7i1KXNPYlgTsyGPCHBed6KARVfPekfjWbPEbTXwart4la98abxL0sJLsfgyJSA==", + "license": "Apache-2.0", "dependencies": { "@opentelemetry/core": "^1.0.0", "@opentelemetry/resources": "^1.10.0", @@ -3787,12 +3642,13 @@ } }, "node_modules/@opentelemetry/resources": { - "version": "1.27.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.27.0.tgz", - "integrity": "sha512-jOwt2VJ/lUD5BLc+PMNymDrUCpm5PKi1E9oSVYAvz01U/VdndGmrtV3DU1pG4AwlYhJRHbHfOUIlpBeXCPw6QQ==", + "version": "1.29.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.29.0.tgz", + "integrity": "sha512-s7mLXuHZE7RQr1wwweGcaRp3Q4UJJ0wazeGlc/N5/XSe6UyXfsh1UQGMADYeg7YwD+cEdMtU1yJAUXdnFzYzyQ==", + "license": "Apache-2.0", "dependencies": { - "@opentelemetry/core": "1.27.0", - "@opentelemetry/semantic-conventions": "1.27.0" + "@opentelemetry/core": "1.29.0", + "@opentelemetry/semantic-conventions": "1.28.0" }, "engines": { "node": ">=14" @@ -3802,13 +3658,14 @@ } }, "node_modules/@opentelemetry/sdk-logs": { - "version": "0.54.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-logs/-/sdk-logs-0.54.0.tgz", - "integrity": "sha512-HeWvOPiWhEw6lWvg+lCIi1WhJnIPbI4/OFZgHq9tKfpwF3LX6/kk3+GR8sGUGAEZfbjPElkkngzvd2s03zbD7Q==", + "version": "0.56.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-logs/-/sdk-logs-0.56.0.tgz", + "integrity": "sha512-OS0WPBJF++R/cSl+terUjQH5PebloidB1Jbbecgg2rnCmQbTST9xsRes23bLfDQVRvmegmHqDh884h0aRdJyLw==", + "license": "Apache-2.0", "dependencies": { - "@opentelemetry/api-logs": "0.54.0", - "@opentelemetry/core": "1.27.0", - "@opentelemetry/resources": "1.27.0" + "@opentelemetry/api-logs": "0.56.0", + "@opentelemetry/core": "1.29.0", + "@opentelemetry/resources": "1.29.0" }, "engines": { "node": ">=14" @@ -3818,12 +3675,13 @@ } }, "node_modules/@opentelemetry/sdk-metrics": { - "version": "1.27.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-metrics/-/sdk-metrics-1.27.0.tgz", - "integrity": "sha512-JzWgzlutoXCydhHWIbLg+r76m+m3ncqvkCcsswXAQ4gqKS+LOHKhq+t6fx1zNytvLuaOUBur7EvWxECc4jPQKg==", + "version": "1.29.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-metrics/-/sdk-metrics-1.29.0.tgz", + "integrity": "sha512-MkVtuzDjXZaUJSuJlHn6BSXjcQlMvHcsDV7LjY4P6AJeffMa4+kIGDjzsCf6DkAh6Vqlwag5EWEam3KZOX5Drw==", + "license": "Apache-2.0", "dependencies": { - "@opentelemetry/core": "1.27.0", - "@opentelemetry/resources": "1.27.0" + "@opentelemetry/core": "1.29.0", + "@opentelemetry/resources": "1.29.0" }, "engines": { "node": ">=14" @@ -3833,26 +3691,27 @@ } }, "node_modules/@opentelemetry/sdk-node": { - "version": "0.54.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-node/-/sdk-node-0.54.0.tgz", - "integrity": "sha512-F0mdwb4WPFJNypcmkxQnj3sIfh/73zkBgYePXMK8ghsBwYw4+PgM3/85WT6NzNUeOvWtiXacx5CFft2o7rGW3w==", - "dependencies": { - "@opentelemetry/api-logs": "0.54.0", - "@opentelemetry/core": "1.27.0", - "@opentelemetry/exporter-logs-otlp-grpc": "0.54.0", - "@opentelemetry/exporter-logs-otlp-http": "0.54.0", - "@opentelemetry/exporter-logs-otlp-proto": "0.54.0", - "@opentelemetry/exporter-trace-otlp-grpc": "0.54.0", - "@opentelemetry/exporter-trace-otlp-http": "0.54.0", - "@opentelemetry/exporter-trace-otlp-proto": "0.54.0", - "@opentelemetry/exporter-zipkin": "1.27.0", - "@opentelemetry/instrumentation": "0.54.0", - "@opentelemetry/resources": "1.27.0", - "@opentelemetry/sdk-logs": "0.54.0", - "@opentelemetry/sdk-metrics": "1.27.0", - "@opentelemetry/sdk-trace-base": "1.27.0", - "@opentelemetry/sdk-trace-node": "1.27.0", - "@opentelemetry/semantic-conventions": "1.27.0" + "version": "0.56.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-node/-/sdk-node-0.56.0.tgz", + "integrity": "sha512-FOY7tWboBBxqftLNHPJFmDXo9fRoPd2PlzfEvSd6058BJM9gY4pWCg8lbVlu03aBrQjcfCTAhXk/tz1Yqd/m6g==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "0.56.0", + "@opentelemetry/core": "1.29.0", + "@opentelemetry/exporter-logs-otlp-grpc": "0.56.0", + "@opentelemetry/exporter-logs-otlp-http": "0.56.0", + "@opentelemetry/exporter-logs-otlp-proto": "0.56.0", + "@opentelemetry/exporter-trace-otlp-grpc": "0.56.0", + "@opentelemetry/exporter-trace-otlp-http": "0.56.0", + "@opentelemetry/exporter-trace-otlp-proto": "0.56.0", + "@opentelemetry/exporter-zipkin": "1.29.0", + "@opentelemetry/instrumentation": "0.56.0", + "@opentelemetry/resources": "1.29.0", + "@opentelemetry/sdk-logs": "0.56.0", + "@opentelemetry/sdk-metrics": "1.29.0", + "@opentelemetry/sdk-trace-base": "1.29.0", + "@opentelemetry/sdk-trace-node": "1.29.0", + "@opentelemetry/semantic-conventions": "1.28.0" }, "engines": { "node": ">=14" @@ -3862,13 +3721,14 @@ } }, "node_modules/@opentelemetry/sdk-trace-base": { - "version": "1.27.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.27.0.tgz", - "integrity": "sha512-btz6XTQzwsyJjombpeqCX6LhiMQYpzt2pIYNPnw0IPO/3AhT6yjnf8Mnv3ZC2A4eRYOjqrg+bfaXg9XHDRJDWQ==", + "version": "1.29.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.29.0.tgz", + "integrity": "sha512-hEOpAYLKXF3wGJpXOtWsxEtqBgde0SCv+w+jvr3/UusR4ll3QrENEGnSl1WDCyRrpqOQ5NCNOvZch9UFVa7MnQ==", + "license": "Apache-2.0", "dependencies": { - "@opentelemetry/core": "1.27.0", - "@opentelemetry/resources": "1.27.0", - "@opentelemetry/semantic-conventions": "1.27.0" + "@opentelemetry/core": "1.29.0", + "@opentelemetry/resources": "1.29.0", + "@opentelemetry/semantic-conventions": "1.28.0" }, "engines": { "node": ">=14" @@ -3878,15 +3738,16 @@ } }, "node_modules/@opentelemetry/sdk-trace-node": { - "version": "1.27.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-node/-/sdk-trace-node-1.27.0.tgz", - "integrity": "sha512-dWZp/dVGdUEfRBjBq2BgNuBlFqHCxyyMc8FsN0NX15X07mxSUO0SZRLyK/fdAVrde8nqFI/FEdMH4rgU9fqJfQ==", - "dependencies": { - "@opentelemetry/context-async-hooks": "1.27.0", - "@opentelemetry/core": "1.27.0", - "@opentelemetry/propagator-b3": "1.27.0", - "@opentelemetry/propagator-jaeger": "1.27.0", - "@opentelemetry/sdk-trace-base": "1.27.0", + "version": "1.29.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-node/-/sdk-trace-node-1.29.0.tgz", + "integrity": "sha512-ZpGYt+VnMu6O0SRKzhuIivr7qJm3GpWnTCMuJspu4kt3QWIpIenwixo5Vvjuu3R4h2Onl/8dtqAiPIs92xd5ww==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/context-async-hooks": "1.29.0", + "@opentelemetry/core": "1.29.0", + "@opentelemetry/propagator-b3": "1.29.0", + "@opentelemetry/propagator-jaeger": "1.29.0", + "@opentelemetry/sdk-trace-base": "1.29.0", "semver": "^7.5.2" }, "engines": { @@ -3897,9 +3758,10 @@ } }, "node_modules/@opentelemetry/semantic-conventions": { - "version": "1.27.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.27.0.tgz", - "integrity": "sha512-sAay1RrB+ONOem0OZanAR1ZI/k7yDpnOQSQmTMuGImUQb2y8EbSaCJ94FQluM74xoU03vlb2d2U90hZluL6nQg==", + "version": "1.28.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.28.0.tgz", + "integrity": "sha512-lp4qAiMTD4sNWW4DbKLBkfiMZ4jbAboJIGOQr5DvciMRI494OapieI9qiODpOt0XBr1LjIDy1xAGAnVs5supTA==", + "license": "Apache-2.0", "engines": { "node": ">=14" } @@ -3908,6 +3770,7 @@ "version": "0.40.1", "resolved": "https://registry.npmjs.org/@opentelemetry/sql-common/-/sql-common-0.40.1.tgz", "integrity": "sha512-nSDlnHSqzC3pXn/wZEZVLuAuJ1MYMXPBwtv2qAbCa3847SaHItdE7SzUq/Jtb0KZmh1zfAbNi3AAMjztTT4Ugg==", + "license": "Apache-2.0", "dependencies": { "@opentelemetry/core": "^1.1.0" }, @@ -3921,22 +3784,25 @@ "node_modules/@photostructure/tz-lookup": { "version": "11.0.0", "resolved": "https://registry.npmjs.org/@photostructure/tz-lookup/-/tz-lookup-11.0.0.tgz", - "integrity": "sha512-QMV5/dWtY/MdVPXZs/EApqzyhnqDq1keYEqpS+Xj2uidyaqw2Nk/fWcsszdruIXjdqp1VoWNzsgrO6bUHU1mFw==" + "integrity": "sha512-QMV5/dWtY/MdVPXZs/EApqzyhnqDq1keYEqpS+Xj2uidyaqw2Nk/fWcsszdruIXjdqp1VoWNzsgrO6bUHU1mFw==", + "license": "CC0-1.0" }, "node_modules/@pkgjs/parseargs": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "license": "MIT", "optional": true, "engines": { "node": ">=14" } }, "node_modules/@pkgr/core": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.0.tgz", - "integrity": "sha512-Zwq5OCzuwJC2jwqmpEQt7Ds1DTi6BWSwoGkbb1n9pO3hzb35BoJELx7c0T23iDkBGkh2e7tvOtjF3tr3OaQHDQ==", + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.1.tgz", + "integrity": "sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==", "dev": true, + "license": "MIT", "engines": { "node": "^12.20.0 || ^14.18.0 || >=16.0.0" }, @@ -3945,34 +3811,40 @@ } }, "node_modules/@polka/url": { - "version": "1.0.0-next.25", - "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.25.tgz", - "integrity": "sha512-j7P6Rgr3mmtdkeDGTe0E/aYyWEWVtc5yFXtHCRHs28/jptDEWfaVOc5T7cblqy1XKPPfCxJc/8DwQ5YgLOZOVQ==" + "version": "1.0.0-next.28", + "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.28.tgz", + "integrity": "sha512-8LduaNlMZGwdZ6qWrKlfa+2M4gahzFkprZiAt2TF8uS0qQgBizKXpXURqvTJ4WtmupWxaLqjRb2UCTe72mu+Aw==", + "license": "MIT" }, "node_modules/@protobufjs/aspromise": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", - "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==" + "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==", + "license": "BSD-3-Clause" }, "node_modules/@protobufjs/base64": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", - "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==" + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==", + "license": "BSD-3-Clause" }, "node_modules/@protobufjs/codegen": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", - "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==" + "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==", + "license": "BSD-3-Clause" }, "node_modules/@protobufjs/eventemitter": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", - "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==" + "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==", + "license": "BSD-3-Clause" }, "node_modules/@protobufjs/fetch": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", + "license": "BSD-3-Clause", "dependencies": { "@protobufjs/aspromise": "^1.1.1", "@protobufjs/inquire": "^1.1.0" @@ -3981,40 +3853,47 @@ "node_modules/@protobufjs/float": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", - "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==" + "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==", + "license": "BSD-3-Clause" }, "node_modules/@protobufjs/inquire": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", - "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==" + "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==", + "license": "BSD-3-Clause" }, "node_modules/@protobufjs/path": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", - "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==" + "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==", + "license": "BSD-3-Clause" }, "node_modules/@protobufjs/pool": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", - "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==" + "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==", + "license": "BSD-3-Clause" }, "node_modules/@protobufjs/utf8": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", - "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==" + "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==", + "license": "BSD-3-Clause" }, "node_modules/@react-email/body": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/@react-email/body/-/body-0.0.10.tgz", - "integrity": "sha512-dMJyL9aU25ieatdPtVjCyQ/WHZYHwNc+Hy/XpF8Cc18gu21cUynVEeYQzFSeigDRMeBQ3PGAyjVDPIob7YlGwA==", + "version": "0.0.11", + "resolved": "https://registry.npmjs.org/@react-email/body/-/body-0.0.11.tgz", + "integrity": "sha512-ZSD2SxVSgUjHGrB0Wi+4tu3MEpB4fYSbezsFNEJk2xCWDBkFiOeEsjTmR5dvi+CxTK691hQTQlHv0XWuP7ENTg==", + "license": "MIT", "peerDependencies": { "react": "^18.0 || ^19.0 || ^19.0.0-rc" } }, "node_modules/@react-email/button": { - "version": "0.0.17", - "resolved": "https://registry.npmjs.org/@react-email/button/-/button-0.0.17.tgz", - "integrity": "sha512-ioHdsk+BpGS/PqjU6JS7tUrVy9yvbUx92Z+Cem2+MbYp55oEwQ9VHf7u4f5NoM0gdhfKSehBwRdYlHt/frEMcg==", + "version": "0.0.19", + "resolved": "https://registry.npmjs.org/@react-email/button/-/button-0.0.19.tgz", + "integrity": "sha512-HYHrhyVGt7rdM/ls6FuuD6XE7fa7bjZTJqB2byn6/oGsfiEZaogY77OtoLL/mrQHjHjZiJadtAMSik9XLcm7+A==", + "license": "MIT", "engines": { "node": ">=18.0.0" }, @@ -4023,9 +3902,10 @@ } }, "node_modules/@react-email/code-block": { - "version": "0.0.9", - "resolved": "https://registry.npmjs.org/@react-email/code-block/-/code-block-0.0.9.tgz", - "integrity": "sha512-Zrhc71VYrSC1fVXJuaViKoB/dBjxLw6nbE53Bm/eUuZPdnnZ1+ZUIh8jfaRKC5MzMjgnLGQTweGXVnfIrhyxtQ==", + "version": "0.0.11", + "resolved": "https://registry.npmjs.org/@react-email/code-block/-/code-block-0.0.11.tgz", + "integrity": "sha512-4D43p+LIMjDzm66gTDrZch0Flkip5je91mAT7iGs6+SbPyalHgIA+lFQoQwhz/VzHHLxuD0LV6gwmU/WUQ2WEg==", + "license": "MIT", "dependencies": { "prismjs": "1.29.0" }, @@ -4037,9 +3917,10 @@ } }, "node_modules/@react-email/code-inline": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/@react-email/code-inline/-/code-inline-0.0.4.tgz", - "integrity": "sha512-zj3oMQiiUCZbddSNt3k0zNfIBFK0ZNDIzzDyBaJKy6ZASTtWfB+1WFX0cpTX8q0gUiYK+A94rk5Qp68L6YXjXQ==", + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/@react-email/code-inline/-/code-inline-0.0.5.tgz", + "integrity": "sha512-MmAsOzdJpzsnY2cZoPHFPk6uDO/Ncpb4Kh1hAt9UZc1xOW3fIzpe1Pi9y9p6wwUmpaeeDalJxAxH6/fnTquinA==", + "license": "MIT", "engines": { "node": ">=18.0.0" }, @@ -4048,9 +3929,10 @@ } }, "node_modules/@react-email/column": { - "version": "0.0.12", - "resolved": "https://registry.npmjs.org/@react-email/column/-/column-0.0.12.tgz", - "integrity": "sha512-Rsl7iSdDaeHZO938xb+0wR5ud0Z3MVfdtPbNKJNojZi2hApwLAQXmDrnn/AcPDM5Lpl331ZljJS8vHTWxxkvKw==", + "version": "0.0.13", + "resolved": "https://registry.npmjs.org/@react-email/column/-/column-0.0.13.tgz", + "integrity": "sha512-Lqq17l7ShzJG/d3b1w/+lVO+gp2FM05ZUo/nW0rjxB8xBICXOVv6PqjDnn3FXKssvhO5qAV20lHM6S+spRhEwQ==", + "license": "MIT", "engines": { "node": ">=18.0.0" }, @@ -4059,30 +3941,31 @@ } }, "node_modules/@react-email/components": { - "version": "0.0.25", - "resolved": "https://registry.npmjs.org/@react-email/components/-/components-0.0.25.tgz", - "integrity": "sha512-lnfVVrThEcET5NPoeaXvrz9UxtWpGRcut2a07dLbyKgNbP7vj/cXTI5TuHtanCvhCddFpMDnElNRghDOfPzwUg==", - "dependencies": { - "@react-email/body": "0.0.10", - "@react-email/button": "0.0.17", - "@react-email/code-block": "0.0.9", - "@react-email/code-inline": "0.0.4", - "@react-email/column": "0.0.12", - "@react-email/container": "0.0.14", - "@react-email/font": "0.0.8", - "@react-email/head": "0.0.11", - "@react-email/heading": "0.0.14", - "@react-email/hr": "0.0.10", - "@react-email/html": "0.0.10", - "@react-email/img": "0.0.10", - "@react-email/link": "0.0.10", - "@react-email/markdown": "0.0.12", - "@react-email/preview": "0.0.11", - "@react-email/render": "1.0.1", - "@react-email/row": "0.0.10", - "@react-email/section": "0.0.14", - "@react-email/tailwind": "0.1.0", - "@react-email/text": "0.0.10" + "version": "0.0.31", + "resolved": "https://registry.npmjs.org/@react-email/components/-/components-0.0.31.tgz", + "integrity": "sha512-rQsTY9ajobncix9raexhBjC7O6cXUMc87eNez2gnB1FwtkUO8DqWZcktbtwOJi7GKmuAPTx0o/IOFtiBNXziKA==", + "license": "MIT", + "dependencies": { + "@react-email/body": "0.0.11", + "@react-email/button": "0.0.19", + "@react-email/code-block": "0.0.11", + "@react-email/code-inline": "0.0.5", + "@react-email/column": "0.0.13", + "@react-email/container": "0.0.15", + "@react-email/font": "0.0.9", + "@react-email/head": "0.0.12", + "@react-email/heading": "0.0.15", + "@react-email/hr": "0.0.11", + "@react-email/html": "0.0.11", + "@react-email/img": "0.0.11", + "@react-email/link": "0.0.12", + "@react-email/markdown": "0.0.14", + "@react-email/preview": "0.0.12", + "@react-email/render": "1.0.3", + "@react-email/row": "0.0.12", + "@react-email/section": "0.0.16", + "@react-email/tailwind": "1.0.4", + "@react-email/text": "0.0.11" }, "engines": { "node": ">=18.0.0" @@ -4092,9 +3975,10 @@ } }, "node_modules/@react-email/container": { - "version": "0.0.14", - "resolved": "https://registry.npmjs.org/@react-email/container/-/container-0.0.14.tgz", - "integrity": "sha512-NgoaJJd9tTtsrveL86Ocr/AYLkGyN3prdXKd/zm5fQpfDhy/NXezyT3iF6VlwAOEUIu64ErHpAJd+P6ygR+vjg==", + "version": "0.0.15", + "resolved": "https://registry.npmjs.org/@react-email/container/-/container-0.0.15.tgz", + "integrity": "sha512-Qo2IQo0ru2kZq47REmHW3iXjAQaKu4tpeq/M8m1zHIVwKduL2vYOBQWbC2oDnMtWPmkBjej6XxgtZByxM6cCFg==", + "license": "MIT", "engines": { "node": ">=18.0.0" }, @@ -4103,17 +3987,19 @@ } }, "node_modules/@react-email/font": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/@react-email/font/-/font-0.0.8.tgz", - "integrity": "sha512-fSBEqYyVPAyyACBBHcs3wEYzNknpHMuwcSAAKE8fOoDfGqURr/vSxKPdh4tOa9z7G4hlcEfgGrCYEa2iPT22cw==", + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/@react-email/font/-/font-0.0.9.tgz", + "integrity": "sha512-4zjq23oT9APXkerqeslPH3OZWuh5X4crHK6nx82mVHV2SrLba8+8dPEnWbaACWTNjOCbcLIzaC9unk7Wq2MIXw==", + "license": "MIT", "peerDependencies": { "react": "^18.0 || ^19.0 || ^19.0.0-rc" } }, "node_modules/@react-email/head": { - "version": "0.0.11", - "resolved": "https://registry.npmjs.org/@react-email/head/-/head-0.0.11.tgz", - "integrity": "sha512-skw5FUgyamIMK+LN+fZQ5WIKQYf0dPiRAvsUAUR2eYoZp9oRsfkIpFHr0GWPkKAYjFEj+uJjaxQ/0VzQH7svVg==", + "version": "0.0.12", + "resolved": "https://registry.npmjs.org/@react-email/head/-/head-0.0.12.tgz", + "integrity": "sha512-X2Ii6dDFMF+D4niNwMAHbTkeCjlYYnMsd7edXOsi0JByxt9wNyZ9EnhFiBoQdqkE+SMDcu8TlNNttMrf5sJeMA==", + "license": "MIT", "engines": { "node": ">=18.0.0" }, @@ -4122,9 +4008,10 @@ } }, "node_modules/@react-email/heading": { - "version": "0.0.14", - "resolved": "https://registry.npmjs.org/@react-email/heading/-/heading-0.0.14.tgz", - "integrity": "sha512-jZM7IVuZOXa0G110ES8OkxajPTypIKlzlO1K1RIe1auk76ukQRiCg1IRV4HZlWk1GGUbec5hNxsvZa2kU8cb9w==", + "version": "0.0.15", + "resolved": "https://registry.npmjs.org/@react-email/heading/-/heading-0.0.15.tgz", + "integrity": "sha512-xF2GqsvBrp/HbRHWEfOgSfRFX+Q8I5KBEIG5+Lv3Vb2R/NYr0s8A5JhHHGf2pWBMJdbP4B2WHgj/VUrhy8dkIg==", + "license": "MIT", "engines": { "node": ">=18.0.0" }, @@ -4133,9 +4020,10 @@ } }, "node_modules/@react-email/hr": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/@react-email/hr/-/hr-0.0.10.tgz", - "integrity": "sha512-3AA4Yjgl3zEid/KVx6uf6TuLJHVZvUc2cG9Wm9ZpWeAX4ODA+8g9HyuC0tfnjbRsVMhMcCGiECuWWXINi+60vA==", + "version": "0.0.11", + "resolved": "https://registry.npmjs.org/@react-email/hr/-/hr-0.0.11.tgz", + "integrity": "sha512-S1gZHVhwOsd1Iad5IFhpfICwNPMGPJidG/Uysy1AwmspyoAP5a4Iw3OWEpINFdgh9MHladbxcLKO2AJO+cA9Lw==", + "license": "MIT", "engines": { "node": ">=18.0.0" }, @@ -4144,9 +4032,10 @@ } }, "node_modules/@react-email/html": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/@react-email/html/-/html-0.0.10.tgz", - "integrity": "sha512-06uiuSKJBWQJfhCKv4MPupELei4Lepyz9Sth7Yq7Fq29CAeB1ejLgKkGqn1I+FZ72hQxPLdYF4iq4yloKv3JCg==", + "version": "0.0.11", + "resolved": "https://registry.npmjs.org/@react-email/html/-/html-0.0.11.tgz", + "integrity": "sha512-qJhbOQy5VW5qzU74AimjAR9FRFQfrMa7dn4gkEXKMB/S9xZN8e1yC1uA9C15jkXI/PzmJ0muDIWmFwatm5/+VA==", + "license": "MIT", "engines": { "node": ">=18.0.0" }, @@ -4155,9 +4044,10 @@ } }, "node_modules/@react-email/img": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/@react-email/img/-/img-0.0.10.tgz", - "integrity": "sha512-pJ8glJjDNaJ53qoM95pvX9SK05yh0bNQY/oyBKmxlBDdUII6ixuMc3SCwYXPMl+tgkQUyDgwEBpSTrLAnjL3hA==", + "version": "0.0.11", + "resolved": "https://registry.npmjs.org/@react-email/img/-/img-0.0.11.tgz", + "integrity": "sha512-aGc8Y6U5C3igoMaqAJKsCpkbm1XjguQ09Acd+YcTKwjnC2+0w3yGUJkjWB2vTx4tN8dCqQCXO8FmdJpMfOA9EQ==", + "license": "MIT", "engines": { "node": ">=18.0.0" }, @@ -4166,9 +4056,10 @@ } }, "node_modules/@react-email/link": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/@react-email/link/-/link-0.0.10.tgz", - "integrity": "sha512-tva3wvAWSR10lMJa9fVA09yRn7pbEki0ZZpHE6GD1jKbFhmzt38VgLO9B797/prqoDZdAr4rVK7LJFcdPx3GwA==", + "version": "0.0.12", + "resolved": "https://registry.npmjs.org/@react-email/link/-/link-0.0.12.tgz", + "integrity": "sha512-vF+xxQk2fGS1CN7UPQDbzvcBGfffr+GjTPNiWM38fhBfsLv6A/YUfaqxWlmL7zLzVmo0K2cvvV9wxlSyNba1aQ==", + "license": "MIT", "engines": { "node": ">=18.0.0" }, @@ -4177,11 +4068,12 @@ } }, "node_modules/@react-email/markdown": { - "version": "0.0.12", - "resolved": "https://registry.npmjs.org/@react-email/markdown/-/markdown-0.0.12.tgz", - "integrity": "sha512-wsuvj1XAb6O63aizCLNEeqVgKR3oFjAwt9vjfg2y2oh4G1dZeo8zonZM2x1fmkEkBZhzwSHraNi70jSXhA3A9w==", + "version": "0.0.14", + "resolved": "https://registry.npmjs.org/@react-email/markdown/-/markdown-0.0.14.tgz", + "integrity": "sha512-5IsobCyPkb4XwnQO8uFfGcNOxnsg3311GRXhJ3uKv51P7Jxme4ycC/MITnwIZ10w2zx7HIyTiqVzTj4XbuIHbg==", + "license": "MIT", "dependencies": { - "md-to-react-email": "5.0.2" + "md-to-react-email": "5.0.5" }, "engines": { "node": ">=18.0.0" @@ -4191,9 +4083,10 @@ } }, "node_modules/@react-email/preview": { - "version": "0.0.11", - "resolved": "https://registry.npmjs.org/@react-email/preview/-/preview-0.0.11.tgz", - "integrity": "sha512-7O/CT4b16YlSGrj18htTPx3Vbhu2suCGv/cSe5c+fuSrIM/nMiBSZ3Js16Vj0XJbAmmmlVmYFZw9L20wXJ+LjQ==", + "version": "0.0.12", + "resolved": "https://registry.npmjs.org/@react-email/preview/-/preview-0.0.12.tgz", + "integrity": "sha512-g/H5fa9PQPDK6WUEG7iTlC19sAktI23qyoiJtMLqQiXFCfWeQMhqjLGKeLSKkfzszqmfJCjZtpSiKtBoOdxp3Q==", + "license": "MIT", "engines": { "node": ">=18.0.0" }, @@ -4202,12 +4095,13 @@ } }, "node_modules/@react-email/render": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@react-email/render/-/render-1.0.1.tgz", - "integrity": "sha512-W3gTrcmLOVYnG80QuUp22ReIT/xfLsVJ+n7ghSlG2BITB8evNABn1AO2rGQoXuK84zKtDAlxCdm3hRyIpZdGSA==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@react-email/render/-/render-1.0.3.tgz", + "integrity": "sha512-VQ8g4SuIq/jWdfBTdTjb7B8Np0jj+OoD7VebfdHhLTZzVQKesR2aigpYqE/ZXmwj4juVxDm8T2b6WIIu48rPCg==", + "license": "MIT", "dependencies": { "html-to-text": "9.0.5", - "js-beautify": "^1.14.11", + "prettier": "3.3.3", "react-promise-suspense": "0.3.4" }, "engines": { @@ -4218,10 +4112,26 @@ "react-dom": "^18.0 || ^19.0 || ^19.0.0-rc" } }, + "node_modules/@react-email/render/node_modules/prettier": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.3.tgz", + "integrity": "sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==", + "license": "MIT", + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, "node_modules/@react-email/row": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/@react-email/row/-/row-0.0.10.tgz", - "integrity": "sha512-jPyEhG3gsLX+Eb9U+A30fh0gK6hXJwF4ghJ+ZtFQtlKAKqHX+eCpWlqB3Xschd/ARJLod8WAswg0FB+JD9d0/A==", + "version": "0.0.12", + "resolved": "https://registry.npmjs.org/@react-email/row/-/row-0.0.12.tgz", + "integrity": "sha512-HkCdnEjvK3o+n0y0tZKXYhIXUNPDx+2vq1dJTmqappVHXS5tXS6W5JOPZr5j+eoZ8gY3PShI2LWj5rWF7ZEtIQ==", + "license": "MIT", "engines": { "node": ">=18.0.0" }, @@ -4230,9 +4140,10 @@ } }, "node_modules/@react-email/section": { - "version": "0.0.14", - "resolved": "https://registry.npmjs.org/@react-email/section/-/section-0.0.14.tgz", - "integrity": "sha512-+fYWLb4tPU1A/+GE5J1+SEMA7/wR3V30lQ+OR9t2kAJqNrARDbMx0bLnYnR1QL5TiFRz0pCF05SQUobk6gHEDQ==", + "version": "0.0.16", + "resolved": "https://registry.npmjs.org/@react-email/section/-/section-0.0.16.tgz", + "integrity": "sha512-FjqF9xQ8FoeUZYKSdt8sMIKvoT9XF8BrzhT3xiFKdEMwYNbsDflcjfErJe3jb7Wj/es/lKTbV5QR1dnLzGpL3w==", + "license": "MIT", "engines": { "node": ">=18.0.0" }, @@ -4241,9 +4152,10 @@ } }, "node_modules/@react-email/tailwind": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@react-email/tailwind/-/tailwind-0.1.0.tgz", - "integrity": "sha512-qysVUEY+M3SKUvu35XDpzn7yokhqFOT3tPU6Mj/pgc62TL5tQFj6msEbBtwoKs2qO3WZvai0DIHdLhaOxBQSow==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@react-email/tailwind/-/tailwind-1.0.4.tgz", + "integrity": "sha512-tJdcusncdqgvTUYZIuhNC6LYTfL9vNTSQpwWdTCQhQ1lsrNCEE4OKCSdzSV3S9F32pi0i0xQ+YPJHKIzGjdTSA==", + "license": "MIT", "engines": { "node": ">=18.0.0" }, @@ -4252,9 +4164,10 @@ } }, "node_modules/@react-email/text": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/@react-email/text/-/text-0.0.10.tgz", - "integrity": "sha512-wNAnxeEAiFs6N+SxS0y6wTJWfewEzUETuyS2aZmT00xk50VijwyFRuhm4sYSjusMyshevomFwz5jNISCxRsGWw==", + "version": "0.0.11", + "resolved": "https://registry.npmjs.org/@react-email/text/-/text-0.0.11.tgz", + "integrity": "sha512-a7nl/2KLpRHOYx75YbYZpWspUbX1DFY7JIZbOv5x0QU8SvwDbJt+Hm01vG34PffFyYvHEXrc6Qnip2RTjljNjg==", + "license": "MIT", "engines": { "node": ">=18.0.0" }, @@ -4263,14 +4176,15 @@ } }, "node_modules/@rollup/pluginutils": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.0.tgz", - "integrity": "sha512-XTIWOPPcpvyKI6L1NHo0lFlCyznUEyPmPY1mc3KpPVDYulHSTvyeLNVW00QTLIAFNhR3kYnJTQHeGqU4M3n09g==", + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.4.tgz", + "integrity": "sha512-USm05zrsFxYLPdWWq+K3STlWiT/3ELn3RcV5hJMghpeAIhxfsUIg6mt12CBJBInWMV4VneoV7SfGv8xIwo2qNQ==", "dev": true, + "license": "MIT", "dependencies": { "@types/estree": "^1.0.0", "estree-walker": "^2.0.2", - "picomatch": "^2.3.1" + "picomatch": "^4.0.2" }, "engines": { "node": ">=14.0.0" @@ -4284,236 +4198,284 @@ } } }, - "node_modules/@rollup/pluginutils/node_modules/estree-walker": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", - "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", - "dev": true - }, - "node_modules/@rollup/pluginutils/node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.22.4.tgz", - "integrity": "sha512-Fxamp4aEZnfPOcGA8KSNEohV8hX7zVHOemC8jVBoBUHu5zpJK/Eu3uJwt6BMgy9fkvzxDaurgj96F/NiLukF2w==", + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.28.1.tgz", + "integrity": "sha512-2aZp8AES04KI2dy3Ss6/MDjXbwBzj+i0GqKtWXgw2/Ma6E4jJvujryO6gJAghIRVz7Vwr9Gtl/8na3nDUKpraQ==", "cpu": [ "arm" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "android" ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.22.4.tgz", - "integrity": "sha512-VXoK5UMrgECLYaMuGuVTOx5kcuap1Jm8g/M83RnCHBKOqvPPmROFJGQaZhGccnsFtfXQ3XYa4/jMCJvZnbJBdA==", + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.28.1.tgz", + "integrity": "sha512-EbkK285O+1YMrg57xVA+Dp0tDBRB93/BZKph9XhMjezf6F4TpYjaUSuPt5J0fZXlSag0LmZAsTmdGGqPp4pQFA==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "android" ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.22.4.tgz", - "integrity": "sha512-xMM9ORBqu81jyMKCDP+SZDhnX2QEVQzTcC6G18KlTQEzWK8r/oNZtKuZaCcHhnsa6fEeOBionoyl5JsAbE/36Q==", + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.28.1.tgz", + "integrity": "sha512-prduvrMKU6NzMq6nxzQw445zXgaDBbMQvmKSJaxpaZ5R1QDM8w+eGxo6Y/jhT/cLoCvnZI42oEqf9KQNYz1fqQ==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "darwin" ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.22.4.tgz", - "integrity": "sha512-aJJyYKQwbHuhTUrjWjxEvGnNNBCnmpHDvrb8JFDbeSH3m2XdHcxDd3jthAzvmoI8w/kSjd2y0udT+4okADsZIw==", + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.28.1.tgz", + "integrity": "sha512-WsvbOunsUk0wccO/TV4o7IKgloJ942hVFK1CLatwv6TJspcCZb9umQkPdvB7FihmdxgaKR5JyxDjWpCOp4uZlQ==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "darwin" ] }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.28.1.tgz", + "integrity": "sha512-HTDPdY1caUcU4qK23FeeGxCdJF64cKkqajU0iBnTVxS8F7H/7BewvYoG+va1KPSL63kQ1PGNyiwKOfReavzvNA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.28.1.tgz", + "integrity": "sha512-m/uYasxkUevcFTeRSM9TeLyPe2QDuqtjkeoTpP9SW0XxUWfcYrGDMkO/m2tTw+4NMAF9P2fU3Mw4ahNvo7QmsQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.22.4.tgz", - "integrity": "sha512-j63YtCIRAzbO+gC2L9dWXRh5BFetsv0j0va0Wi9epXDgU/XUi5dJKo4USTttVyK7fGw2nPWK0PbAvyliz50SCQ==", + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.28.1.tgz", + "integrity": "sha512-QAg11ZIt6mcmzpNE6JZBpKfJaKkqTm1A9+y9O+frdZJEuhQxiugM05gnCWiANHj4RmbgeVJpTdmKRmH/a+0QbA==", "cpu": [ "arm" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.22.4.tgz", - "integrity": "sha512-dJnWUgwWBX1YBRsuKKMOlXCzh2Wu1mlHzv20TpqEsfdZLb3WoJW2kIEsGwLkroYf24IrPAvOT/ZQ2OYMV6vlrg==", + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.28.1.tgz", + "integrity": "sha512-dRP9PEBfolq1dmMcFqbEPSd9VlRuVWEGSmbxVEfiq2cs2jlZAl0YNxFzAQS2OrQmsLBLAATDMb3Z6MFv5vOcXg==", "cpu": [ "arm" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.22.4.tgz", - "integrity": "sha512-AdPRoNi3NKVLolCN/Sp4F4N1d98c4SBnHMKoLuiG6RXgoZ4sllseuGioszumnPGmPM2O7qaAX/IJdeDU8f26Aw==", + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.28.1.tgz", + "integrity": "sha512-uGr8khxO+CKT4XU8ZUH1TTEUtlktK6Kgtv0+6bIFSeiSlnGJHG1tSFSjm41uQ9sAO/5ULx9mWOz70jYLyv1QkA==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.22.4.tgz", - "integrity": "sha512-Gl0AxBtDg8uoAn5CCqQDMqAx22Wx22pjDOjBdmG0VIWX3qUBHzYmOKh8KXHL4UpogfJ14G4wk16EQogF+v8hmA==", + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.28.1.tgz", + "integrity": "sha512-QF54q8MYGAqMLrX2t7tNpi01nvq5RI59UBNx+3+37zoKX5KViPo/gk2QLhsuqok05sSCRluj0D00LzCwBikb0A==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loongarch64-gnu": { + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.28.1.tgz", + "integrity": "sha512-vPul4uodvWvLhRco2w0GcyZcdyBfpfDRgNKU+p35AWEbJ/HPs1tOUrkSueVbBS0RQHAf/A+nNtDpvw95PeVKOA==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.22.4.tgz", - "integrity": "sha512-3aVCK9xfWW1oGQpTsYJJPF6bfpWfhbRnhdlyhak2ZiyFLDaayz0EP5j9V1RVLAAxlmWKTDfS9wyRyY3hvhPoOg==", + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.28.1.tgz", + "integrity": "sha512-pTnTdBuC2+pt1Rmm2SV7JWRqzhYpEILML4PKODqLz+C7Ou2apEV52h19CR7es+u04KlqplggmN9sqZlekg3R1A==", "cpu": [ "ppc64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.22.4.tgz", - "integrity": "sha512-ePYIir6VYnhgv2C5Xe9u+ico4t8sZWXschR6fMgoPUK31yQu7hTEJb7bCqivHECwIClJfKgE7zYsh1qTP3WHUA==", + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.28.1.tgz", + "integrity": "sha512-vWXy1Nfg7TPBSuAncfInmAI/WZDd5vOklyLJDdIRKABcZWojNDY0NJwruY2AcnCLnRJKSaBgf/GiJfauu8cQZA==", "cpu": [ "riscv64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.22.4.tgz", - "integrity": "sha512-GqFJ9wLlbB9daxhVlrTe61vJtEY99/xB3C8e4ULVsVfflcpmR6c8UZXjtkMA6FhNONhj2eA5Tk9uAVw5orEs4Q==", + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.28.1.tgz", + "integrity": "sha512-/yqC2Y53oZjb0yz8PVuGOQQNOTwxcizudunl/tFs1aLvObTclTwZ0JhXF2XcPT/zuaymemCDSuuUPXJJyqeDOg==", "cpu": [ "s390x" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.22.4.tgz", - "integrity": "sha512-87v0ol2sH9GE3cLQLNEy0K/R0pz1nvg76o8M5nhMR0+Q+BBGLnb35P0fVz4CQxHYXaAOhE8HhlkaZfsdUOlHwg==", + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.28.1.tgz", + "integrity": "sha512-fzgeABz7rrAlKYB0y2kSEiURrI0691CSL0+KXwKwhxvj92VULEDQLpBYLHpF49MSiPG4sq5CK3qHMnb9tlCjBw==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.22.4.tgz", - "integrity": "sha512-UV6FZMUgePDZrFjrNGIWzDo/vABebuXBhJEqrHxrGiU6HikPy0Z3LfdtciIttEUQfuDdCn8fqh7wiFJjCNwO+g==", + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.28.1.tgz", + "integrity": "sha512-xQTDVzSGiMlSshpJCtudbWyRfLaNiVPXt1WgdWTwWz9n0U12cI2ZVtWe/Jgwyv/6wjL7b66uu61Vg0POWVfz4g==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.22.4.tgz", - "integrity": "sha512-BjI+NVVEGAXjGWYHz/vv0pBqfGoUH0IGZ0cICTn7kB9PyjrATSkX+8WkguNjWoj2qSr1im/+tTGRaY+4/PdcQw==", + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.28.1.tgz", + "integrity": "sha512-wSXmDRVupJstFP7elGMgv+2HqXelQhuNf+IS4V+nUpNVi/GUiBgDmfwD0UGN3pcAnWsgKG3I52wMOBnk1VHr/A==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "win32" ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.22.4.tgz", - "integrity": "sha512-SiWG/1TuUdPvYmzmYnmd3IEifzR61Tragkbx9D3+R8mzQqDBz8v+BvZNDlkiTtI9T15KYZhP0ehn3Dld4n9J5g==", + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.28.1.tgz", + "integrity": "sha512-ZkyTJ/9vkgrE/Rk9vhMXhf8l9D+eAhbAVbsGsXKy2ohmJaWg0LPQLnIxRdRp/bKyr8tXuPlXhIoGlEB5XpJnGA==", "cpu": [ "ia32" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "win32" ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.22.4.tgz", - "integrity": "sha512-j8pPKp53/lq9lMXN57S8cFz0MynJk8OWNuUnXct/9KCpKU7DgU3bYMJhwWmcqC0UU29p8Lr0/7KEVcaM6bf47Q==", + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.28.1.tgz", + "integrity": "sha512-ZvK2jBafvttJjoIdKm/Q/Bh7IJ1Ose9IBOwpOXcOvW3ikGTQGmKDgxTC6oCAzW6PynbkKP8+um1du81XJHZ0JA==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "win32" ] }, + "node_modules/@scarf/scarf": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@scarf/scarf/-/scarf-1.4.0.tgz", + "integrity": "sha512-xxeapPiUXdZAE3che6f3xogoJPeZgig6omHEy1rIY5WVsB3H2BHNnZH+gHG6x91SCWyQCzWGsuL2Hh3ClO5/qQ==", + "hasInstallScript": true, + "license": "Apache-2.0" + }, "node_modules/@selderee/plugin-htmlparser2": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/@selderee/plugin-htmlparser2/-/plugin-htmlparser2-0.11.0.tgz", "integrity": "sha512-P33hHGdldxGabLFjPPpaTxVolMrzrcegejx+0GxjrIb9Zv48D8yAIA/QTDR2dFl7Uz7urX8aX6+5bCZslr+gWQ==", + "license": "MIT", "dependencies": { "domhandler": "^5.0.3", "selderee": "^0.11.0" @@ -4526,6 +4488,7 @@ "version": "4.1.5", "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.5.tgz", "integrity": "sha512-IqO/DUQHUkPeixNQ8n0JA6102hT9CmaljNTPmQ1u8MEhBo/R4Q8eKLN/vGZxuebwOroDB4cbpjheD4+/sKFK4Q==", + "license": "BSD-3-Clause", "dependencies": { "@hapi/hoek": "^9.0.0" } @@ -4533,22 +4496,26 @@ "node_modules/@sideway/formula": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.1.tgz", - "integrity": "sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==" + "integrity": "sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==", + "license": "BSD-3-Clause" }, "node_modules/@sideway/pinpoint": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz", - "integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==" + "integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==", + "license": "BSD-3-Clause" }, "node_modules/@socket.io/component-emitter": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz", - "integrity": "sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg==" + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz", + "integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==", + "license": "MIT" }, "node_modules/@socket.io/redis-adapter": { "version": "8.3.0", "resolved": "https://registry.npmjs.org/@socket.io/redis-adapter/-/redis-adapter-8.3.0.tgz", "integrity": "sha512-ly0cra+48hDmChxmIpnESKrc94LjRL80TEmZVscuQ/WWkRP81nNj8W8cCGMqbI4L6NCuAaPRSzZF1a9GlAxxnA==", + "license": "MIT", "dependencies": { "debug": "~4.3.1", "notepack.io": "~3.0.1", @@ -4561,21 +4528,40 @@ "socket.io-adapter": "^2.5.4" } }, - "node_modules/@sqltools/formatter": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/@sqltools/formatter/-/formatter-1.2.5.tgz", - "integrity": "sha512-Uy0+khmZqUrUGm5dmMqVlnvufZRSK0FbYzVgp0UMstm+F5+W2/jnEEQyc9vo1ZR/E5ZI/B1WjjoTqBqwJL6Krw==" - }, - "node_modules/@swc/core": { - "version": "1.7.39", - "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.7.39.tgz", - "integrity": "sha512-jns6VFeOT49uoTKLWIEfiQqJAlyqldNAt80kAr8f7a5YjX0zgnG3RBiLMpksx4Ka4SlK4O6TJ/lumIM3Trp82g==", - "devOptional": true, - "hasInstallScript": true, - "dependencies": { - "@swc/counter": "^0.1.3", - "@swc/types": "^0.1.13" - }, + "node_modules/@socket.io/redis-adapter/node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@sqltools/formatter": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/@sqltools/formatter/-/formatter-1.2.5.tgz", + "integrity": "sha512-Uy0+khmZqUrUGm5dmMqVlnvufZRSK0FbYzVgp0UMstm+F5+W2/jnEEQyc9vo1ZR/E5ZI/B1WjjoTqBqwJL6Krw==", + "license": "MIT" + }, + "node_modules/@swc/core": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.10.1.tgz", + "integrity": "sha512-rQ4dS6GAdmtzKiCRt3LFVxl37FaY1cgL9kSUTnhQ2xc3fmHOd7jdJK/V4pSZMG1ruGTd0bsi34O2R0Olg9Zo/w==", + "dev": true, + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "@swc/counter": "^0.1.3", + "@swc/types": "^0.1.17" + }, "engines": { "node": ">=10" }, @@ -4584,16 +4570,16 @@ "url": "https://opencollective.com/swc" }, "optionalDependencies": { - "@swc/core-darwin-arm64": "1.7.39", - "@swc/core-darwin-x64": "1.7.39", - "@swc/core-linux-arm-gnueabihf": "1.7.39", - "@swc/core-linux-arm64-gnu": "1.7.39", - "@swc/core-linux-arm64-musl": "1.7.39", - "@swc/core-linux-x64-gnu": "1.7.39", - "@swc/core-linux-x64-musl": "1.7.39", - "@swc/core-win32-arm64-msvc": "1.7.39", - "@swc/core-win32-ia32-msvc": "1.7.39", - "@swc/core-win32-x64-msvc": "1.7.39" + "@swc/core-darwin-arm64": "1.10.1", + "@swc/core-darwin-x64": "1.10.1", + "@swc/core-linux-arm-gnueabihf": "1.10.1", + "@swc/core-linux-arm64-gnu": "1.10.1", + "@swc/core-linux-arm64-musl": "1.10.1", + "@swc/core-linux-x64-gnu": "1.10.1", + "@swc/core-linux-x64-musl": "1.10.1", + "@swc/core-win32-arm64-msvc": "1.10.1", + "@swc/core-win32-ia32-msvc": "1.10.1", + "@swc/core-win32-x64-msvc": "1.10.1" }, "peerDependencies": { "@swc/helpers": "*" @@ -4605,13 +4591,14 @@ } }, "node_modules/@swc/core-darwin-arm64": { - "version": "1.7.39", - "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.7.39.tgz", - "integrity": "sha512-o2nbEL6scMBMCTvY9OnbyVXtepLuNbdblV9oNJEFia5v5eGj9WMrnRQiylH3Wp/G2NYkW7V1/ZVW+kfvIeYe9A==", + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.10.1.tgz", + "integrity": "sha512-NyELPp8EsVZtxH/mEqvzSyWpfPJ1lugpTQcSlMduZLj1EASLO4sC8wt8hmL1aizRlsbjCX+r0PyL+l0xQ64/6Q==", "cpu": [ "arm64" ], "dev": true, + "license": "Apache-2.0 AND MIT", "optional": true, "os": [ "darwin" @@ -4621,13 +4608,14 @@ } }, "node_modules/@swc/core-darwin-x64": { - "version": "1.7.39", - "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.7.39.tgz", - "integrity": "sha512-qMlv3XPgtPi/Fe11VhiPDHSLiYYk2dFYl747oGsHZPq+6tIdDQjIhijXPcsUHIXYDyG7lNpODPL8cP/X1sc9MA==", + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.10.1.tgz", + "integrity": "sha512-L4BNt1fdQ5ZZhAk5qoDfUnXRabDOXKnXBxMDJ+PWLSxOGBbWE6aJTnu4zbGjJvtot0KM46m2LPAPY8ttknqaZA==", "cpu": [ "x64" ], "dev": true, + "license": "Apache-2.0 AND MIT", "optional": true, "os": [ "darwin" @@ -4637,13 +4625,14 @@ } }, "node_modules/@swc/core-linux-arm-gnueabihf": { - "version": "1.7.39", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.7.39.tgz", - "integrity": "sha512-NP+JIkBs1ZKnpa3Lk2W1kBJMwHfNOxCUJXuTa2ckjFsuZ8OUu2gwdeLFkTHbR43dxGwH5UzSmuGocXeMowra/Q==", + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.10.1.tgz", + "integrity": "sha512-Y1u9OqCHgvVp2tYQAJ7hcU9qO5brDMIrA5R31rwWQIAKDkJKtv3IlTHF0hrbWk1wPR0ZdngkQSJZple7G+Grvw==", "cpu": [ "arm" ], "dev": true, + "license": "Apache-2.0", "optional": true, "os": [ "linux" @@ -4653,13 +4642,14 @@ } }, "node_modules/@swc/core-linux-arm64-gnu": { - "version": "1.7.39", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.7.39.tgz", - "integrity": "sha512-cPc+/HehyHyHcvAsk3ML/9wYcpWVIWax3YBaA+ScecJpSE04l/oBHPfdqKUPslqZ+Gcw0OWnIBGJT/fBZW2ayw==", + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.10.1.tgz", + "integrity": "sha512-tNQHO/UKdtnqjc7o04iRXng1wTUXPgVd8Y6LI4qIbHVoVPwksZydISjMcilKNLKIwOoUQAkxyJ16SlOAeADzhQ==", "cpu": [ "arm64" ], "dev": true, + "license": "Apache-2.0 AND MIT", "optional": true, "os": [ "linux" @@ -4669,13 +4659,14 @@ } }, "node_modules/@swc/core-linux-arm64-musl": { - "version": "1.7.39", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.7.39.tgz", - "integrity": "sha512-8RxgBC6ubFem66bk9XJ0vclu3exJ6eD7x7CwDhp5AD/tulZslTYXM7oNPjEtje3xxabXuj/bEUMNvHZhQRFdqA==", + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.10.1.tgz", + "integrity": "sha512-x0L2Pd9weQ6n8dI1z1Isq00VHFvpBClwQJvrt3NHzmR+1wCT/gcYl1tp9P5xHh3ldM8Cn4UjWCw+7PaUgg8FcQ==", "cpu": [ "arm64" ], "dev": true, + "license": "Apache-2.0 AND MIT", "optional": true, "os": [ "linux" @@ -4685,13 +4676,14 @@ } }, "node_modules/@swc/core-linux-x64-gnu": { - "version": "1.7.39", - "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.7.39.tgz", - "integrity": "sha512-3gtCPEJuXLQEolo9xsXtuPDocmXQx12vewEyFFSMSjOfakuPOBmOQMa0sVL8Wwius8C1eZVeD1fgk0omMqeC+Q==", + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.10.1.tgz", + "integrity": "sha512-yyYEwQcObV3AUsC79rSzN9z6kiWxKAVJ6Ntwq2N9YoZqSPYph+4/Am5fM1xEQYf/kb99csj0FgOelomJSobxQA==", "cpu": [ "x64" ], "dev": true, + "license": "Apache-2.0 AND MIT", "optional": true, "os": [ "linux" @@ -4701,13 +4693,14 @@ } }, "node_modules/@swc/core-linux-x64-musl": { - "version": "1.7.39", - "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.7.39.tgz", - "integrity": "sha512-mg39pW5x/eqqpZDdtjZJxrUvQNSvJF4O8wCl37fbuFUqOtXs4TxsjZ0aolt876HXxxhsQl7rS+N4KioEMSgTZw==", + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.10.1.tgz", + "integrity": "sha512-tcaS43Ydd7Fk7sW5ROpaf2Kq1zR+sI5K0RM+0qYLYYurvsJruj3GhBCaiN3gkzd8m/8wkqNqtVklWaQYSDsyqA==", "cpu": [ "x64" ], "dev": true, + "license": "Apache-2.0 AND MIT", "optional": true, "os": [ "linux" @@ -4717,13 +4710,14 @@ } }, "node_modules/@swc/core-win32-arm64-msvc": { - "version": "1.7.39", - "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.7.39.tgz", - "integrity": "sha512-NZwuS0mNJowH3e9bMttr7B1fB8bW5svW/yyySigv9qmV5VcQRNz1kMlCvrCLYRsa93JnARuiaBI6FazSeG8mpA==", + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.10.1.tgz", + "integrity": "sha512-D3Qo1voA7AkbOzQ2UGuKNHfYGKL6eejN8VWOoQYtGHHQi1p5KK/Q7V1ku55oxXBsj79Ny5FRMqiRJpVGad7bjQ==", "cpu": [ "arm64" ], "dev": true, + "license": "Apache-2.0 AND MIT", "optional": true, "os": [ "win32" @@ -4733,13 +4727,14 @@ } }, "node_modules/@swc/core-win32-ia32-msvc": { - "version": "1.7.39", - "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.7.39.tgz", - "integrity": "sha512-qFmvv5UExbJPXhhvCVDBnjK5Duqxr048dlVB6ZCgGzbRxuarOlawCzzLK4N172230pzlAWGLgn9CWl3+N6zfHA==", + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.10.1.tgz", + "integrity": "sha512-WalYdFoU3454Og+sDKHM1MrjvxUGwA2oralknXkXL8S0I/8RkWZOB++p3pLaGbTvOO++T+6znFbQdR8KRaa7DA==", "cpu": [ "ia32" ], "dev": true, + "license": "Apache-2.0 AND MIT", "optional": true, "os": [ "win32" @@ -4749,13 +4744,14 @@ } }, "node_modules/@swc/core-win32-x64-msvc": { - "version": "1.7.39", - "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.7.39.tgz", - "integrity": "sha512-o+5IMqgOtj9+BEOp16atTfBgCogVak9svhBpwsbcJQp67bQbxGYhAPPDW/hZ2rpSSF7UdzbY9wudoX9G4trcuQ==", + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.10.1.tgz", + "integrity": "sha512-JWobfQDbTnoqaIwPKQ3DVSywihVXlQMbDuwik/dDWlj33A8oEHcjPOGs4OqcA3RHv24i+lfCQpM3Mn4FAMfacA==", "cpu": [ "x64" ], "dev": true, + "license": "Apache-2.0 AND MIT", "optional": true, "os": [ "win32" @@ -4767,67 +4763,43 @@ "node_modules/@swc/counter": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz", - "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==" + "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==", + "license": "Apache-2.0" }, "node_modules/@swc/helpers": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.5.tgz", - "integrity": "sha512-KGYxvIOXcceOAbEk4bi/dVLEK9z8sZ0uBB3Il5b1rhfClSpcX0yfRO0KmTkqR2cnQDymwLB+25ZyMzICg/cm/A==", + "version": "0.5.13", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.13.tgz", + "integrity": "sha512-UoKGxQ3r5kYI9dALKJapMmuK+1zWM/H17Z1+iwnNmzcJRnfFuevZs375TA5rW31pu4BS4NoSy1fRsexDXfWn5w==", + "license": "Apache-2.0", "dependencies": { - "@swc/counter": "^0.1.3", "tslib": "^2.4.0" } }, "node_modules/@swc/types": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.13.tgz", - "integrity": "sha512-JL7eeCk6zWCbiYQg2xQSdLXQJl8Qoc9rXmG2cEKvHe3CKwMHwHGpfOb8frzNLmbycOo6I51qxnLnn9ESf4I20Q==", - "devOptional": true, + "version": "0.1.17", + "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.17.tgz", + "integrity": "sha512-V5gRru+aD8YVyCOMAjMpWR1Ui577DD5KSJsHP8RAxopAH22jFz6GZd/qxqjO6MJHQhcsjvjOFXyDhyLQUnMveQ==", + "dev": true, + "license": "Apache-2.0", "dependencies": { "@swc/counter": "^0.1.3" } }, "node_modules/@testcontainers/postgresql": { - "version": "10.13.2", - "resolved": "https://registry.npmjs.org/@testcontainers/postgresql/-/postgresql-10.13.2.tgz", - "integrity": "sha512-xd3u/rL8FrOBHFMu1aU+2d4sqPz9ffEb19ITtopT/tyBZWW9qCsgR6wSg0r2BJUd+2hT4UR5nR5cymi+ROkehw==", + "version": "10.16.0", + "resolved": "https://registry.npmjs.org/@testcontainers/postgresql/-/postgresql-10.16.0.tgz", + "integrity": "sha512-zWFQI+3QxlEELRvVv27i6zlVEPNUz9zKaSh7iWmFlCdfhcyr78daS0FG8FIfdQ79VK7YXA4jv+dTYXa2SwXu/w==", "dev": true, + "license": "MIT", "dependencies": { - "testcontainers": "^10.13.2" + "testcontainers": "^10.16.0" } }, - "node_modules/@tsconfig/node10": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", - "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==", - "optional": true, - "peer": true - }, - "node_modules/@tsconfig/node12": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", - "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", - "optional": true, - "peer": true - }, - "node_modules/@tsconfig/node14": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", - "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", - "optional": true, - "peer": true - }, - "node_modules/@tsconfig/node16": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", - "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", - "optional": true, - "peer": true - }, "node_modules/@turf/boolean-point-in-polygon": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/@turf/boolean-point-in-polygon/-/boolean-point-in-polygon-7.1.0.tgz", "integrity": "sha512-mprVsyIQ+ijWTZwbnO4Jhxu94ZW2M2CheqLiRTsGJy0Ooay9v6Av5/Nl3/Gst7ZVXxPqMeMaFYkSzcTc87AKew==", + "license": "MIT", "dependencies": { "@turf/helpers": "^7.1.0", "@turf/invariant": "^7.1.0", @@ -4843,6 +4815,7 @@ "version": "7.1.0", "resolved": "https://registry.npmjs.org/@turf/helpers/-/helpers-7.1.0.tgz", "integrity": "sha512-dTeILEUVeNbaEeoZUOhxH5auv7WWlOShbx7QSd4s0T4Z0/iz90z9yaVCtZOLbU89umKotwKaJQltBNO9CzVgaQ==", + "license": "MIT", "dependencies": { "@types/geojson": "^7946.0.10", "tslib": "^2.6.2" @@ -4855,6 +4828,7 @@ "version": "7.1.0", "resolved": "https://registry.npmjs.org/@turf/invariant/-/invariant-7.1.0.tgz", "integrity": "sha512-OCLNqkItBYIP1nE9lJGuIUatWGtQ4rhBKAyTfFu0z8npVzGEYzvguEeof8/6LkKmTTEHW53tCjoEhSSzdRh08Q==", + "license": "MIT", "dependencies": { "@turf/helpers": "^7.1.0", "@types/geojson": "^7946.0.10", @@ -4869,6 +4843,7 @@ "resolved": "https://registry.npmjs.org/@types/archiver/-/archiver-6.0.3.tgz", "integrity": "sha512-a6wUll6k3zX6qs5KlxIggs1P1JcYJaTCx2gnlr+f0S1yd2DoaEwoIK10HmBaLnZwWneBz+JBm0dwcZu0zECBcQ==", "dev": true, + "license": "MIT", "dependencies": { "@types/readdir-glob": "*" } @@ -4877,27 +4852,31 @@ "version": "1.4.2", "resolved": "https://registry.npmjs.org/@types/async-lock/-/async-lock-1.4.2.tgz", "integrity": "sha512-HlZ6Dcr205BmNhwkdXqrg2vkFMN2PluI7Lgr8In3B3wE5PiQHhjRqtW/lGdVU9gw+sM0JcIDx2AN+cW8oSWIcw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/aws-lambda": { "version": "8.10.143", "resolved": "https://registry.npmjs.org/@types/aws-lambda/-/aws-lambda-8.10.143.tgz", - "integrity": "sha512-u5vzlcR14ge/4pMTTMDQr3MF0wEe38B2F9o84uC4F43vN5DGTy63npRrB6jQhyt+C0lGv4ZfiRcRkqJoZuPnmg==" + "integrity": "sha512-u5vzlcR14ge/4pMTTMDQr3MF0wEe38B2F9o84uC4F43vN5DGTy63npRrB6jQhyt+C0lGv4ZfiRcRkqJoZuPnmg==", + "license": "MIT" }, "node_modules/@types/bcrypt": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/@types/bcrypt/-/bcrypt-5.0.2.tgz", "integrity": "sha512-6atioO8Y75fNcbmj0G7UjI9lXN2pQ/IGJ2FWT4a/btd0Lk9lQalHLKhkgKVZ3r+spnmWUKfbMi1GEe9wyHQfNQ==", "dev": true, + "license": "MIT", "dependencies": { "@types/node": "*" } }, "node_modules/@types/body-parser": { - "version": "1.19.3", - "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.3.tgz", - "integrity": "sha512-oyl4jvAfTGX9Bt6Or4H9ni1Z447/tQuxnZsytsCaExKlmJiU8sFgnIBRzJUpKwB5eWn9HuBYlUlVA74q/yN0eQ==", + "version": "1.19.5", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", + "integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==", "dev": true, + "license": "MIT", "dependencies": { "@types/connect": "*", "@types/node": "*" @@ -4907,6 +4886,7 @@ "version": "1.8.9", "resolved": "https://registry.npmjs.org/@types/bunyan/-/bunyan-1.8.9.tgz", "integrity": "sha512-ZqS9JGpBxVOvsawzmVt30sP++gSQMTejCkIAQ3VdadOcRE8izTyW66hufvwLeH+YEGP6Js2AW7Gz+RMyvrEbmw==", + "license": "MIT", "dependencies": { "@types/node": "*" } @@ -4915,6 +4895,7 @@ "version": "3.4.36", "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.36.tgz", "integrity": "sha512-P63Zd/JUGq+PdrM1lv0Wv5SBYeA2+CORvbrXbngriYY0jzLUWfQMQQxOhjONEz/wlHOAxOdY7CY65rgQdTjq2w==", + "license": "MIT", "dependencies": { "@types/node": "*" } @@ -4922,14 +4903,16 @@ "node_modules/@types/cookie": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.1.tgz", - "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==" + "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==", + "license": "MIT" }, "node_modules/@types/cookie-parser": { - "version": "1.4.7", - "resolved": "https://registry.npmjs.org/@types/cookie-parser/-/cookie-parser-1.4.7.tgz", - "integrity": "sha512-Fvuyi354Z+uayxzIGCwYTayFKocfV7TuDYZClCdIP9ckhvAu/ixDtCB6qx2TT0FKjPLf1f3P/J1rgf6lPs64mw==", + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/@types/cookie-parser/-/cookie-parser-1.4.8.tgz", + "integrity": "sha512-l37JqFrOJ9yQfRQkljb41l0xVphc7kg5JTjjr+pLRZ0IyZ49V4BQ8vbF4Ut2C2e+WH4al3xD3ZwYwIUfnbT4NQ==", "dev": true, - "dependencies": { + "license": "MIT", + "peerDependencies": { "@types/express": "*" } }, @@ -4937,12 +4920,14 @@ "version": "2.1.5", "resolved": "https://registry.npmjs.org/@types/cookiejar/-/cookiejar-2.1.5.tgz", "integrity": "sha512-he+DHOWReW0nghN24E1WUqM0efK4kI9oTqDm6XmK8ZPe2djZ90BSNdGnIyCLzCPw7/pogPlGbzI2wHGGmi4O/Q==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/cors": { - "version": "2.8.14", - "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.14.tgz", - "integrity": "sha512-RXHUvNWYICtbP6s18PnOCaqToK8y14DnLd75c6HfyKf228dxy7pHNOQkxPtvXKp/hINFMDjbYzsj63nnpPMSRQ==", + "version": "2.8.17", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.17.tgz", + "integrity": "sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA==", + "license": "MIT", "dependencies": { "@types/node": "*" } @@ -4952,16 +4937,18 @@ "resolved": "https://registry.npmjs.org/@types/docker-modem/-/docker-modem-3.0.6.tgz", "integrity": "sha512-yKpAGEuKRSS8wwx0joknWxsmLha78wNMe9R2S3UNsVOkZded8UqOrV8KoeDXoXsjndxwyF3eIhyClGbO1SEhEg==", "dev": true, + "license": "MIT", "dependencies": { "@types/node": "*", "@types/ssh2": "*" } }, "node_modules/@types/dockerode": { - "version": "3.3.29", - "resolved": "https://registry.npmjs.org/@types/dockerode/-/dockerode-3.3.29.tgz", - "integrity": "sha512-5PRRq/yt5OT/Jf77ltIdz4EiR9+VLnPF+HpU4xGFwUqmV24Co2HKBNW3w+slqZ1CYchbcDeqJASHDYWzZCcMiQ==", + "version": "3.3.32", + "resolved": "https://registry.npmjs.org/@types/dockerode/-/dockerode-3.3.32.tgz", + "integrity": "sha512-xxcG0g5AWKtNyh7I7wswLdFvym4Mlqks5ZlKzxEUrGHS0r0PUOfxm2T0mspwu10mHQqu3Ck3MI3V2HqvLWE1fg==", "dev": true, + "license": "MIT", "dependencies": { "@types/docker-modem": "*", "@types/node": "*", @@ -4969,28 +4956,40 @@ } }, "node_modules/@types/eslint": { - "version": "8.44.3", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.44.3.tgz", - "integrity": "sha512-iM/WfkwAhwmPff3wZuPLYiHX18HI24jU8k1ZSH7P8FHwxTjZ2P6CoX2wnF43oprR+YXJM6UUxATkNvyv/JHd+g==", + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.1.tgz", + "integrity": "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==", "dev": true, - "optional": true, - "peer": true, + "license": "MIT", "dependencies": { "@types/estree": "*", "@types/json-schema": "*" } }, + "node_modules/@types/eslint-scope": { + "version": "3.7.7", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", + "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/eslint": "*", + "@types/estree": "*" + } + }, "node_modules/@types/estree": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", - "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", - "dev": true + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", + "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", + "dev": true, + "license": "MIT" }, "node_modules/@types/express": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz", "integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==", "dev": true, + "license": "MIT", "dependencies": { "@types/body-parser": "*", "@types/express-serve-static-core": "^4.17.33", @@ -4999,10 +4998,11 @@ } }, "node_modules/@types/express-serve-static-core": { - "version": "4.17.37", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.37.tgz", - "integrity": "sha512-ZohaCYTgGFcOP7u6aJOhY9uIZQgZ2vxC2yWoArY+FeDXlqeH66ZVBjgvg+RLVAS/DWNq4Ap9ZXu1+SUQiiWYMg==", + "version": "4.19.6", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.6.tgz", + "integrity": "sha512-N4LZ2xG7DatVqhCZzOGb1Yi5lMbXSZcmdLDe9EzSndPV2HpWYWzRbaerl2n27irrm94EPpprqa8KpskPT085+A==", "dev": true, + "license": "MIT", "dependencies": { "@types/node": "*", "@types/qs": "*", @@ -5011,29 +5011,33 @@ } }, "node_modules/@types/fluent-ffmpeg": { - "version": "2.1.26", - "resolved": "https://registry.npmjs.org/@types/fluent-ffmpeg/-/fluent-ffmpeg-2.1.26.tgz", - "integrity": "sha512-0JVF3wdQG+pN0ImwWD0bNgJiKF2OHg/7CDBHw5UIbRTvlnkgGHK6V5doE54ltvhud4o31/dEiHm23CAlxFiUQg==", + "version": "2.1.27", + "resolved": "https://registry.npmjs.org/@types/fluent-ffmpeg/-/fluent-ffmpeg-2.1.27.tgz", + "integrity": "sha512-QiDWjihpUhriISNoBi2hJBRUUmoj/BMTYcfz+F+ZM9hHWBYABFAE6hjP/TbCZC0GWwlpa3FzvHH9RzFeRusZ7A==", "dev": true, + "license": "MIT", "dependencies": { "@types/node": "*" } }, "node_modules/@types/geojson": { - "version": "7946.0.14", - "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.14.tgz", - "integrity": "sha512-WCfD5Ht3ZesJUsONdhvm84dmzWOiOzOAqOncN0++w0lBw1o8OuDNJF2McvvCef/yBqb/HYRahp1BYtODFQ8bRg==" + "version": "7946.0.15", + "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.15.tgz", + "integrity": "sha512-9oSxFzDCT2Rj6DfcHF8G++jxBKS7mBqXl5xrRW+Kbvjry6Uduya2iiwqHPhVXpasAVMBYKkEPGgKhd3+/HZ6xA==", + "license": "MIT" }, "node_modules/@types/http-errors": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.2.tgz", - "integrity": "sha512-lPG6KlZs88gef6aD85z3HNkztpj7w2R7HmR3gygjfXCQmsLloWNARFkMuzKiiY8FGdh1XDpgBdrSf4aKDiA7Kg==", - "dev": true + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", + "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==", + "dev": true, + "license": "MIT" }, "node_modules/@types/inquirer": { - "version": "8.2.6", - "resolved": "https://registry.npmjs.org/@types/inquirer/-/inquirer-8.2.6.tgz", - "integrity": "sha512-3uT88kxg8lNzY8ay2ZjP44DKcRaTGztqeIvN2zHvhzIBH/uAPaL75aBtdNRKbA7xXoMbBt5kX0M00VKAnfOYlA==", + "version": "8.2.10", + "resolved": "https://registry.npmjs.org/@types/inquirer/-/inquirer-8.2.10.tgz", + "integrity": "sha512-IdD5NmHyVjWM8SHWo/kPBgtzXatwPkfwzyP3fN1jF2g9BWt5WO+8hL2F4o2GKIYsU40PpqeevuUWvkS/roXJkA==", + "license": "MIT", "peer": true, "dependencies": { "@types/through": "*", @@ -5044,29 +5048,34 @@ "version": "4.0.9", "resolved": "https://registry.npmjs.org/@types/js-yaml/-/js-yaml-4.0.9.tgz", "integrity": "sha512-k4MGaQl5TGo/iipqb2UDG2UwjXziSWkh0uysQelTlJpX1qGlpUZYm8PnO4DxG1qBomtJUdYJ6qR6xdIah10JLg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/json-schema": { "version": "7.0.15", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/lodash": { - "version": "4.17.12", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.12.tgz", - "integrity": "sha512-sviUmCE8AYdaF/KIHLDJBQgeYzPBI0vf/17NaYehBJfYD1j6/L95Slh07NlyK2iNyBNaEkb3En2jRt+a8y3xZQ==", - "dev": true + "version": "4.17.13", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.13.tgz", + "integrity": "sha512-lfx+dftrEZcdBPczf9d0Qv0x+j/rfNCMuC6OcfXmO8gkfeNAY88PgKUbvG56whcN23gc27yenwF6oJZXGFpYxg==", + "dev": true, + "license": "MIT" }, "node_modules/@types/luxon": { "version": "3.4.2", "resolved": "https://registry.npmjs.org/@types/luxon/-/luxon-3.4.2.tgz", - "integrity": "sha512-TifLZlFudklWlMBfhubvgqTXRzLDI5pCbGa4P8a3wPyUQSW+1xQ5eDsreP9DWHX3tjq1ke96uYG/nwundroWcA==" + "integrity": "sha512-TifLZlFudklWlMBfhubvgqTXRzLDI5pCbGa4P8a3wPyUQSW+1xQ5eDsreP9DWHX3tjq1ke96uYG/nwundroWcA==", + "license": "MIT" }, "node_modules/@types/memcached": { "version": "2.2.10", "resolved": "https://registry.npmjs.org/@types/memcached/-/memcached-2.2.10.tgz", "integrity": "sha512-AM9smvZN55Gzs2wRrqeMHVP7KE8KWgCJO/XL5yCly2xF6EKa4YlbpK+cLSAH4NG/Ah64HrlegmGqW8kYws7Vxg==", + "license": "MIT", "dependencies": { "@types/node": "*" } @@ -5075,19 +5084,22 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/@types/methods/-/methods-1.1.4.tgz", "integrity": "sha512-ymXWVrDiCxTBE3+RIrrP533E70eA+9qu7zdWoHuOmGujkYtzf4HQF96b8nwHLqhuf4ykX61IGRIB38CC6/sImQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/mime": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.3.tgz", - "integrity": "sha512-Ys+/St+2VF4+xuY6+kDIXGxbNRO0mesVg0bbxEfB97Od1Vjpjx9KD1qxs64Gcb3CWPirk9Xe+PT4YiiHQ9T+eg==", - "dev": true + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", + "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", + "dev": true, + "license": "MIT" }, "node_modules/@types/mock-fs": { "version": "4.13.4", "resolved": "https://registry.npmjs.org/@types/mock-fs/-/mock-fs-4.13.4.tgz", "integrity": "sha512-mXmM0o6lULPI8z3XNnQCpL0BGxPwx1Ul1wXYEPBGl4efShyxW2Rln0JOPEWGyZaYZMM6OVXM/15zUuFMY52ljg==", "dev": true, + "license": "MIT", "dependencies": { "@types/node": "*" } @@ -5097,6 +5109,7 @@ "resolved": "https://registry.npmjs.org/@types/multer/-/multer-1.4.12.tgz", "integrity": "sha512-pQ2hoqvXiJt2FP9WQVLPRO+AmiIm/ZYkavPlIQnx282u4ZrVdztx0pkh3jjpQt0Kz+YI0YhSG264y08UJKoUQg==", "dev": true, + "license": "MIT", "dependencies": { "@types/express": "*" } @@ -5105,23 +5118,26 @@ "version": "2.15.26", "resolved": "https://registry.npmjs.org/@types/mysql/-/mysql-2.15.26.tgz", "integrity": "sha512-DSLCOXhkvfS5WNNPbfn2KdICAmk8lLc+/PNvnPnF7gOdMZCxopXduqv0OQ13y/yA/zXTSikZZqVgybUxOEg6YQ==", + "license": "MIT", "dependencies": { "@types/node": "*" } }, "node_modules/@types/node": { - "version": "22.8.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.8.5.tgz", - "integrity": "sha512-5iYk6AMPtsMbkZqCO1UGF9W5L38twq11S2pYWkybGHH2ogPUvXWNlQqJBzuEZWKj/WRH+QTeiv6ySWqJtvIEgA==", + "version": "22.10.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.2.tgz", + "integrity": "sha512-Xxr6BBRCAOQixvonOye19wnzyDiUtTeqldOOmj3CkeblonbccA12PFwlufvRdrpjXxqnmUaeiU5EOA+7s5diUQ==", + "license": "MIT", "dependencies": { - "undici-types": "~6.19.8" + "undici-types": "~6.20.0" } }, "node_modules/@types/nodemailer": { - "version": "6.4.16", - "resolved": "https://registry.npmjs.org/@types/nodemailer/-/nodemailer-6.4.16.tgz", - "integrity": "sha512-uz6hN6Pp0upXMcilM61CoKyjT7sskBoOWpptkjjJp8jIMlTdc3xG01U7proKkXzruMS4hS0zqtHNkNPFB20rKQ==", + "version": "6.4.17", + "resolved": "https://registry.npmjs.org/@types/nodemailer/-/nodemailer-6.4.17.tgz", + "integrity": "sha512-I9CCaIp6DTldEg7vyUTZi8+9Vo0hi1/T8gv3C89yk1rSAAzoKQ8H8ki/jBYJSFoH/BisgLP8tkZMlQ91CIquww==", "dev": true, + "license": "MIT", "dependencies": { "@types/node": "*" } @@ -5130,83 +5146,35 @@ "version": "2.4.4", "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz", "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/pg": { - "version": "8.11.10", - "resolved": "https://registry.npmjs.org/@types/pg/-/pg-8.11.10.tgz", - "integrity": "sha512-LczQUW4dbOQzsH2RQ5qoeJ6qJPdrcM/DcMLoqWQkMLMsq83J5lAX3LXjdkWdpscFy67JSOWDnh7Ny/sPFykmkg==", + "version": "8.6.1", + "resolved": "https://registry.npmjs.org/@types/pg/-/pg-8.6.1.tgz", + "integrity": "sha512-1Kc4oAGzAl7uqUStZCDvaLFqZrW9qWSjXOmBfdgyBP5La7Us6Mg4GBvRlSoaZMhQF/zSj1C8CtKMBkoiT8eL8w==", + "license": "MIT", "dependencies": { "@types/node": "*", "pg-protocol": "*", - "pg-types": "^4.0.1" + "pg-types": "^2.2.0" } }, "node_modules/@types/pg-pool": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/@types/pg-pool/-/pg-pool-2.0.6.tgz", "integrity": "sha512-TaAUE5rq2VQYxab5Ts7WZhKNmuN78Q6PiFonTDdpbx8a1H0M1vhy3rhiMjl+e2iHmogyMw7jZF4FrE6eJUy5HQ==", + "license": "MIT", "dependencies": { "@types/pg": "*" } }, - "node_modules/@types/pg/node_modules/pg-types": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-4.0.2.tgz", - "integrity": "sha512-cRL3JpS3lKMGsKaWndugWQoLOCoP+Cic8oseVcbr0qhPzYD5DWXK+RZ9LY9wxRf7RQia4SCwQlXk0q6FCPrVng==", - "dependencies": { - "pg-int8": "1.0.1", - "pg-numeric": "1.0.2", - "postgres-array": "~3.0.1", - "postgres-bytea": "~3.0.0", - "postgres-date": "~2.1.0", - "postgres-interval": "^3.0.0", - "postgres-range": "^1.1.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@types/pg/node_modules/postgres-array": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-3.0.2.tgz", - "integrity": "sha512-6faShkdFugNQCLwucjPcY5ARoW1SlbnrZjmGl0IrrqewpvxvhSLHimCVzqeuULCbG0fQv7Dtk1yDbG3xv7Veog==", - "engines": { - "node": ">=12" - } - }, - "node_modules/@types/pg/node_modules/postgres-bytea": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-3.0.0.tgz", - "integrity": "sha512-CNd4jim9RFPkObHSjVHlVrxoVQXz7quwNFpz7RY1okNNme49+sVyiTvTRobiLV548Hx/hb1BG+iE7h9493WzFw==", - "dependencies": { - "obuf": "~1.1.2" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/@types/pg/node_modules/postgres-date": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-2.1.0.tgz", - "integrity": "sha512-K7Juri8gtgXVcDfZttFKVmhglp7epKb1K4pgrkLxehjqkrgPhfG6OO8LHLkfaqkbpjNRnra018XwAr1yQFWGcA==", - "engines": { - "node": ">=12" - } - }, - "node_modules/@types/pg/node_modules/postgres-interval": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-3.0.0.tgz", - "integrity": "sha512-BSNDnbyZCXSxgA+1f5UU2GmwhoI0aU5yMxRGO8CdFEcY2BQF9xm/7MqKnYoM1nJDk8nONNWDk9WeSmePFhQdlw==", - "engines": { - "node": ">=12" - } - }, "node_modules/@types/picomatch": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/@types/picomatch/-/picomatch-3.0.1.tgz", "integrity": "sha512-1MRgzpzY0hOp9pW/kLRxeQhUWwil6gnrUYd3oEpeYBqp/FexhaCPv3F8LsYr47gtUU45fO2cm1dbwkSrHEo8Uw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/pngjs": { "version": "6.0.5", @@ -5218,39 +5186,36 @@ "@types/node": "*" } }, - "node_modules/@types/prop-types": { - "version": "15.7.12", - "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz", - "integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==", - "dev": true - }, "node_modules/@types/qs": { - "version": "6.9.8", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.8.tgz", - "integrity": "sha512-u95svzDlTysU5xecFNTgfFG5RUWu1A9P0VzgpcIiGZA9iraHOdSzcxMxQ55DyeRaGCSxQi7LxXDI4rzq/MYfdg==", - "dev": true + "version": "6.9.17", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.17.tgz", + "integrity": "sha512-rX4/bPcfmvxHDv0XjfJELTTr+iB+tn032nPILqHm5wbthUUUuVtNGGqzhya9XUxjTP8Fpr0qYgSZZKxGY++svQ==", + "dev": true, + "license": "MIT" }, "node_modules/@types/range-parser": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.5.tgz", - "integrity": "sha512-xrO9OoVPqFuYyR/loIHjnbvvyRZREYKLjxV4+dY6v3FQR3stQ9ZxIGkaclF7YhI9hfjpuTbu14hZEy94qKLtOA==", - "dev": true + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", + "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", + "dev": true, + "license": "MIT" }, "node_modules/@types/react": { - "version": "18.3.12", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.12.tgz", - "integrity": "sha512-D2wOSq/d6Agt28q7rSI3jhU7G6aiuzljDGZ2hTZHIkrTLUI+AF3WMeKkEZ9nN2fkBAlcktT6vcZjDFiIhMYEQw==", + "version": "19.0.1", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.0.1.tgz", + "integrity": "sha512-YW6614BDhqbpR5KtUYzTA+zlA7nayzJRA9ljz9CQoxthR0sDisYZLuvSMsil36t4EH/uAt8T52Xb4sVw17G+SQ==", "dev": true, + "license": "MIT", "dependencies": { - "@types/prop-types": "*", "csstype": "^3.0.2" } }, "node_modules/@types/readdir-glob": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@types/readdir-glob/-/readdir-glob-1.1.2.tgz", - "integrity": "sha512-vwAYrNN/8yhp/FJRU6HUSD0yk6xfoOS8HrZa8ZL7j+X8hJpaC1hTcAiXX2IxaAkkvrz9mLyoEhYZTE3cEYvA9Q==", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@types/readdir-glob/-/readdir-glob-1.1.5.tgz", + "integrity": "sha512-raiuEPUYqXu+nvtY2Pe8s8FEmZ3x5yAH4VkLdihcPdalvsHltomrRC9BzuStrJ9yk06470hS0Crw0f1pXqD+Hg==", "dev": true, + "license": "MIT", "dependencies": { "@types/node": "*" } @@ -5259,62 +5224,86 @@ "version": "7.5.8", "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/send": { - "version": "0.17.2", - "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.2.tgz", - "integrity": "sha512-aAG6yRf6r0wQ29bkS+x97BIs64ZLxeE/ARwyS6wrldMm3C1MdKwCcnnEwMC1slI8wuxJOpiUH9MioC0A0i+GJw==", + "version": "0.17.4", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", + "integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==", "dev": true, + "license": "MIT", "dependencies": { "@types/mime": "^1", "@types/node": "*" } }, "node_modules/@types/serve-static": { - "version": "1.15.3", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.3.tgz", - "integrity": "sha512-yVRvFsEMrv7s0lGhzrggJjNOSmZCdgCjw9xWrPr/kNNLp6FaDfMC1KaYl3TSJ0c58bECwNBMoQrZJ8hA8E1eFg==", + "version": "1.15.7", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.7.tgz", + "integrity": "sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==", "dev": true, + "license": "MIT", "dependencies": { "@types/http-errors": "*", - "@types/mime": "*", - "@types/node": "*" + "@types/node": "*", + "@types/send": "*" } }, "node_modules/@types/shimmer": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@types/shimmer/-/shimmer-1.2.0.tgz", - "integrity": "sha512-UE7oxhQLLd9gub6JKIAhDq06T0F6FnztwMNRvYgjeQSBeMc1ZG/tA47EwfduvkuQS8apbkM/lpLpWsaCeYsXVg==" + "integrity": "sha512-UE7oxhQLLd9gub6JKIAhDq06T0F6FnztwMNRvYgjeQSBeMc1ZG/tA47EwfduvkuQS8apbkM/lpLpWsaCeYsXVg==", + "license": "MIT" }, "node_modules/@types/ssh2": { - "version": "0.5.52", - "resolved": "https://registry.npmjs.org/@types/ssh2/-/ssh2-0.5.52.tgz", - "integrity": "sha512-lbLLlXxdCZOSJMCInKH2+9V/77ET2J6NPQHpFI0kda61Dd1KglJs+fPQBchizmzYSOJBgdTajhPqBO1xxLywvg==", + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/@types/ssh2/-/ssh2-1.15.1.tgz", + "integrity": "sha512-ZIbEqKAsi5gj35y4P4vkJYly642wIbY6PqoN0xiyQGshKUGXR9WQjF/iF9mXBQ8uBKy3ezfsCkcoHKhd0BzuDA==", "dev": true, + "license": "MIT", "dependencies": { - "@types/node": "*", - "@types/ssh2-streams": "*" + "@types/node": "^18.11.18" } }, "node_modules/@types/ssh2-streams": { - "version": "0.1.10", - "resolved": "https://registry.npmjs.org/@types/ssh2-streams/-/ssh2-streams-0.1.10.tgz", - "integrity": "sha512-r3HYPL0kPxRwk7Nk1P4JxaWPyJ2Mfnfm5efuK0vYgYZu16RerZUTyun6Yqu5KEfc3AR7BvTL1x+nzf7+kbKftQ==", + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/@types/ssh2-streams/-/ssh2-streams-0.1.12.tgz", + "integrity": "sha512-Sy8tpEmCce4Tq0oSOYdfqaBpA3hDM8SoxoFh5vzFsu2oL+znzGz8oVWW7xb4K920yYMUY+PIG31qZnFMfPWNCg==", "dev": true, + "license": "MIT", "dependencies": { "@types/node": "*" } }, + "node_modules/@types/ssh2/node_modules/@types/node": { + "version": "18.19.68", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.68.tgz", + "integrity": "sha512-QGtpFH1vB99ZmTa63K4/FU8twThj4fuVSBkGddTp7uIL/cuoLWIUSL2RcOaigBhfR+hg5pgGkBnkoOxrTVBMKw==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@types/ssh2/node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/superagent": { - "version": "8.1.6", - "resolved": "https://registry.npmjs.org/@types/superagent/-/superagent-8.1.6.tgz", - "integrity": "sha512-yzBOv+6meEHSzV2NThYYOA6RtqvPr3Hbob9ZLp3i07SH27CrYVfm8CrF7ydTmidtelsFiKx2I4gZAiAOamGgvQ==", + "version": "8.1.9", + "resolved": "https://registry.npmjs.org/@types/superagent/-/superagent-8.1.9.tgz", + "integrity": "sha512-pTVjI73witn+9ILmoJdajHGW2jkSaOzhiFYF1Rd3EQ94kymLqB9PjD9ISg7WaALC7+dCHT0FGe9T2LktLq/3GQ==", "dev": true, + "license": "MIT", "dependencies": { "@types/cookiejar": "^2.1.5", "@types/methods": "^1.1.4", - "@types/node": "*" + "@types/node": "*", + "form-data": "^4.0.0" } }, "node_modules/@types/supertest": { @@ -5322,6 +5311,7 @@ "resolved": "https://registry.npmjs.org/@types/supertest/-/supertest-6.0.2.tgz", "integrity": "sha512-137ypx2lk/wTQbW6An6safu9hXmajAifU/s7szAHLN/FeIm5w7yR0Wkl9fdJMRSHwOn4HLAI0DaB2TOORuhPDg==", "dev": true, + "license": "MIT", "dependencies": { "@types/methods": "^1.1.4", "@types/superagent": "^8.1.0" @@ -5331,14 +5321,16 @@ "version": "4.0.14", "resolved": "https://registry.npmjs.org/@types/tedious/-/tedious-4.0.14.tgz", "integrity": "sha512-KHPsfX/FoVbUGbyYvk1q9MMQHLPeRZhRJZdO45Q4YjvFkv4hMNghCWTvy7rdKessBsmtz4euWCWAB6/tVpI1Iw==", + "license": "MIT", "dependencies": { "@types/node": "*" } }, "node_modules/@types/through": { - "version": "0.0.31", - "resolved": "https://registry.npmjs.org/@types/through/-/through-0.0.31.tgz", - "integrity": "sha512-LpKpmb7FGevYgXnBXYs6HWnmiFyVG07Pt1cnbgM1IhEacITTiUaBXXvOR3Y50ksaJWGSfhbEvQFivQEFGCC55w==", + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/@types/through/-/through-0.0.33.tgz", + "integrity": "sha512-HsJ+z3QuETzP3cswwtzt2vEIiHBk/dCcHGhbmG5X3ecnwFD/lPrMpliGXxSCg03L9AhrdwA4Oz/qfspkDW+xGQ==", + "license": "MIT", "peer": true, "dependencies": { "@types/node": "*" @@ -5348,24 +5340,27 @@ "version": "0.7.39", "resolved": "https://registry.npmjs.org/@types/ua-parser-js/-/ua-parser-js-0.7.39.tgz", "integrity": "sha512-P/oDfpofrdtF5xw433SPALpdSchtJmY7nsJItf8h3KXqOslkbySh8zq4dSWXH2oTjRvJ5PczVEoCZPow6GicLg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/validator": { - "version": "13.11.8", - "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.11.8.tgz", - "integrity": "sha512-c/hzNDBh7eRF+KbCf+OoZxKbnkpaK/cKp9iLQWqB7muXtM+MtL9SUUH8vCFcLn6dH1Qm05jiexK0ofWY7TfOhQ==" + "version": "13.12.2", + "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.12.2.tgz", + "integrity": "sha512-6SlHBzUW8Jhf3liqrGGXyTJSIFe4nqlJ5A5KaMZ2l/vbM3Wh3KSybots/wfWVzNLK4D1NZluDlSQIbIEPx6oyA==", + "license": "MIT" }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.11.0.tgz", - "integrity": "sha512-KhGn2LjW1PJT2A/GfDpiyOfS4a8xHQv2myUagTM5+zsormOmBlYsnQ6pobJ8XxJmh6hnHwa2Mbe3fPrDJoDhbA==", + "version": "8.18.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.18.1.tgz", + "integrity": "sha512-Ncvsq5CT3Gvh+uJG0Lwlho6suwDfUXH0HztslDf5I+F2wAFAZMRwYLEorumpKLzmO2suAXZ/td1tBg4NZIi9CQ==", "dev": true, + "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.11.0", - "@typescript-eslint/type-utils": "8.11.0", - "@typescript-eslint/utils": "8.11.0", - "@typescript-eslint/visitor-keys": "8.11.0", + "@typescript-eslint/scope-manager": "8.18.1", + "@typescript-eslint/type-utils": "8.18.1", + "@typescript-eslint/utils": "8.18.1", + "@typescript-eslint/visitor-keys": "8.18.1", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", @@ -5380,24 +5375,21 @@ }, "peerDependencies": { "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", - "eslint": "^8.57.0 || ^9.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.8.0" } }, "node_modules/@typescript-eslint/parser": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.11.0.tgz", - "integrity": "sha512-lmt73NeHdy1Q/2ul295Qy3uninSqi6wQI18XwSpm8w0ZbQXUpjCAWP1Vlv/obudoBiIjJVjlztjQ+d/Md98Yxg==", + "version": "8.18.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.18.1.tgz", + "integrity": "sha512-rBnTWHCdbYM2lh7hjyXqxk70wvon3p2FyaniZuey5TrcGBpfhVp0OxOa6gxr9Q9YhZFKyfbEnxc24ZnVbbUkCA==", "dev": true, + "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "8.11.0", - "@typescript-eslint/types": "8.11.0", - "@typescript-eslint/typescript-estree": "8.11.0", - "@typescript-eslint/visitor-keys": "8.11.0", + "@typescript-eslint/scope-manager": "8.18.1", + "@typescript-eslint/types": "8.18.1", + "@typescript-eslint/typescript-estree": "8.18.1", + "@typescript-eslint/visitor-keys": "8.18.1", "debug": "^4.3.4" }, "engines": { @@ -5408,22 +5400,19 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.8.0" } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.11.0.tgz", - "integrity": "sha512-Uholz7tWhXmA4r6epo+vaeV7yjdKy5QFCERMjs1kMVsLRKIrSdM6o21W2He9ftp5PP6aWOVpD5zvrvuHZC0bMQ==", + "version": "8.18.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.18.1.tgz", + "integrity": "sha512-HxfHo2b090M5s2+/9Z3gkBhI6xBH8OJCFjH9MhQ+nnoZqxU3wNxkLT+VWXWSFWc3UF3Z+CfPAyqdCTdoXtDPCQ==", "dev": true, + "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.11.0", - "@typescript-eslint/visitor-keys": "8.11.0" + "@typescript-eslint/types": "8.18.1", + "@typescript-eslint/visitor-keys": "8.18.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -5434,13 +5423,14 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.11.0.tgz", - "integrity": "sha512-ItiMfJS6pQU0NIKAaybBKkuVzo6IdnAhPFZA/2Mba/uBjuPQPet/8+zh5GtLHwmuFRShZx+8lhIs7/QeDHflOg==", + "version": "8.18.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.18.1.tgz", + "integrity": "sha512-jAhTdK/Qx2NJPNOTxXpMwlOiSymtR2j283TtPqXkKBdH8OAMmhiUfP0kJjc/qSE51Xrq02Gj9NY7MwK+UxVwHQ==", "dev": true, + "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "8.11.0", - "@typescript-eslint/utils": "8.11.0", + "@typescript-eslint/typescript-estree": "8.18.1", + "@typescript-eslint/utils": "8.18.1", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" }, @@ -5451,17 +5441,17 @@ "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.8.0" } }, "node_modules/@typescript-eslint/types": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.11.0.tgz", - "integrity": "sha512-tn6sNMHf6EBAYMvmPUaKaVeYvhUsrE6x+bXQTxjQRp360h1giATU0WvgeEys1spbvb5R+VpNOZ+XJmjD8wOUHw==", + "version": "8.18.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.18.1.tgz", + "integrity": "sha512-7uoAUsCj66qdNQNpH2G8MyTFlgerum8ubf21s3TSM3XmKXuIn+H2Sifh/ES2nPOPiYSRJWAk0fDkW0APBWcpfw==", "dev": true, + "license": "MIT", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, @@ -5471,13 +5461,14 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.11.0.tgz", - "integrity": "sha512-yHC3s1z1RCHoCz5t06gf7jH24rr3vns08XXhfEqzYpd6Hll3z/3g23JRi0jM8A47UFKNc3u/y5KIMx8Ynbjohg==", + "version": "8.18.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.18.1.tgz", + "integrity": "sha512-z8U21WI5txzl2XYOW7i9hJhxoKKNG1kcU4RzyNvKrdZDmbjkmLBo8bgeiOJmA06kizLI76/CCBAAGlTlEeUfyg==", "dev": true, + "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.11.0", - "@typescript-eslint/visitor-keys": "8.11.0", + "@typescript-eslint/types": "8.18.1", + "@typescript-eslint/visitor-keys": "8.18.1", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -5492,10 +5483,8 @@ "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "peerDependencies": { + "typescript": ">=4.8.4 <5.8.0" } }, "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { @@ -5503,6 +5492,7 @@ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" } @@ -5512,6 +5502,7 @@ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" }, @@ -5523,15 +5514,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.11.0.tgz", - "integrity": "sha512-CYiX6WZcbXNJV7UNB4PLDIBtSdRmRI/nb0FMyqHPTQD1rMjA0foPLaPUV39C/MxkTd/QKSeX+Gb34PPsDVC35g==", + "version": "8.18.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.18.1.tgz", + "integrity": "sha512-8vikiIj2ebrC4WRdcAdDcmnu9Q/MXXwg+STf40BVfT8exDqBCUPdypvzcUPxEqRGKg9ALagZ0UWcYCtn+4W2iQ==", "dev": true, + "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.11.0", - "@typescript-eslint/types": "8.11.0", - "@typescript-eslint/typescript-estree": "8.11.0" + "@typescript-eslint/scope-manager": "8.18.1", + "@typescript-eslint/types": "8.18.1", + "@typescript-eslint/typescript-estree": "8.18.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -5541,17 +5533,19 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0" + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.8.0" } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.11.0.tgz", - "integrity": "sha512-EaewX6lxSjRJnc+99+dqzTeoDZUfyrA52d2/HRrkI830kgovWsmIiTfmr0NZorzqic7ga+1bS60lRBUgR3n/Bw==", + "version": "8.18.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.18.1.tgz", + "integrity": "sha512-Vj0WLm5/ZsD013YeUKn+K0y8p1M0jPpxOkKdbD1wB0ns53a5piVY02zjf072TblEweAbcYiFiPoSMF3kp+VhhQ==", "dev": true, + "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.11.0", - "eslint-visitor-keys": "^3.4.3" + "@typescript-eslint/types": "8.18.1", + "eslint-visitor-keys": "^4.2.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -5561,22 +5555,36 @@ "url": "https://opencollective.com/typescript-eslint" } }, + "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", + "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, "node_modules/@vitest/coverage-v8": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-2.1.3.tgz", - "integrity": "sha512-2OJ3c7UPoFSmBZwqD2VEkUw6A/tzPF0LmW0ZZhhB8PFxuc+9IBG/FaSM+RLEenc7ljzFvGN+G0nGQoZnh7sy2A==", + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-2.1.8.tgz", + "integrity": "sha512-2Y7BPlKH18mAZYAW1tYByudlCYrQyl5RGvnnDYJKW5tCiO5qg3KSAy3XAxcxKz900a0ZXxWtKrMuZLe3lKBpJw==", "dev": true, + "license": "MIT", "dependencies": { "@ampproject/remapping": "^2.3.0", "@bcoe/v8-coverage": "^0.2.3", - "debug": "^4.3.6", + "debug": "^4.3.7", "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.11", - "magicast": "^0.3.4", - "std-env": "^3.7.0", + "magic-string": "^0.30.12", + "magicast": "^0.3.5", + "std-env": "^3.8.0", "test-exclude": "^7.0.1", "tinyrainbow": "^1.2.0" }, @@ -5584,8 +5592,8 @@ "url": "https://opencollective.com/vitest" }, "peerDependencies": { - "@vitest/browser": "2.1.3", - "vitest": "2.1.3" + "@vitest/browser": "2.1.8", + "vitest": "2.1.8" }, "peerDependenciesMeta": { "@vitest/browser": { @@ -5594,23 +5602,25 @@ } }, "node_modules/@vitest/coverage-v8/node_modules/magic-string": { - "version": "0.30.12", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.12.tgz", - "integrity": "sha512-Ea8I3sQMVXr8JhN4z+H/d8zwo+tYDgHE9+5G4Wnrwhs0gaK9fXTKx0Tw5Xwsd/bCPTTZNRAdpyzvoeORe9LYpw==", + "version": "0.30.17", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", + "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==", "dev": true, + "license": "MIT", "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0" } }, "node_modules/@vitest/expect": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-2.1.3.tgz", - "integrity": "sha512-SNBoPubeCJhZ48agjXruCI57DvxcsivVDdWz+SSsmjTT4QN/DfHk3zB/xKsJqMs26bLZ/pNRLnCf0j679i0uWQ==", + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-2.1.8.tgz", + "integrity": "sha512-8ytZ/fFHq2g4PJVAtDX57mayemKgDR6X3Oa2Foro+EygiOJHUXhCqBAAKQYYajZpFoIfvBCF1j6R6IYRSIUFuw==", "dev": true, + "license": "MIT", "dependencies": { - "@vitest/spy": "2.1.3", - "@vitest/utils": "2.1.3", - "chai": "^5.1.1", + "@vitest/spy": "2.1.8", + "@vitest/utils": "2.1.8", + "chai": "^5.1.2", "tinyrainbow": "^1.2.0" }, "funding": { @@ -5618,21 +5628,21 @@ } }, "node_modules/@vitest/mocker": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-2.1.3.tgz", - "integrity": "sha512-eSpdY/eJDuOvuTA3ASzCjdithHa+GIF1L4PqtEELl6Qa3XafdMLBpBlZCIUCX2J+Q6sNmjmxtosAG62fK4BlqQ==", + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-2.1.8.tgz", + "integrity": "sha512-7guJ/47I6uqfttp33mgo6ga5Gr1VnL58rcqYKyShoRK9ebu8T5Rs6HN3s1NABiBeVTdWNrwUMcHH54uXZBN4zA==", "dev": true, + "license": "MIT", "dependencies": { - "@vitest/spy": "2.1.3", + "@vitest/spy": "2.1.8", "estree-walker": "^3.0.3", - "magic-string": "^0.30.11" + "magic-string": "^0.30.12" }, "funding": { "url": "https://opencollective.com/vitest" }, "peerDependencies": { - "@vitest/spy": "2.1.3", - "msw": "^2.3.5", + "msw": "^2.4.9", "vite": "^5.0.0" }, "peerDependenciesMeta": { @@ -5644,20 +5654,32 @@ } } }, + "node_modules/@vitest/mocker/node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0" + } + }, "node_modules/@vitest/mocker/node_modules/magic-string": { - "version": "0.30.11", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.11.tgz", - "integrity": "sha512-+Wri9p0QHMy+545hKww7YAu5NyzF8iomPL/RQazugQ9+Ez4Ic3mERMd8ZTX5rfK944j+560ZJi8iAwgak1Ac7A==", + "version": "0.30.17", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", + "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==", "dev": true, + "license": "MIT", "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0" } }, "node_modules/@vitest/pretty-format": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-2.1.3.tgz", - "integrity": "sha512-XH1XdtoLZCpqV59KRbPrIhFCOO0hErxrQCMcvnQete3Vibb9UeIOX02uFPfVn3Z9ZXsq78etlfyhnkmIZSzIwQ==", + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-2.1.8.tgz", + "integrity": "sha512-9HiSZ9zpqNLKlbIDRWOnAWqgcA7xu+8YxXSekhr0Ykab7PAYFkhkwoqVArPOtJhPmYeE2YHgKZlj3CP36z2AJQ==", "dev": true, + "license": "MIT", "dependencies": { "tinyrainbow": "^1.2.0" }, @@ -5666,12 +5688,13 @@ } }, "node_modules/@vitest/runner": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-2.1.3.tgz", - "integrity": "sha512-JGzpWqmFJ4fq5ZKHtVO3Xuy1iF2rHGV4d/pdzgkYHm1+gOzNZtqjvyiaDGJytRyMU54qkxpNzCx+PErzJ1/JqQ==", + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-2.1.8.tgz", + "integrity": "sha512-17ub8vQstRnRlIU5k50bG+QOMLHRhYPAna5tw8tYbj+jzjcspnwnwtPtiOlkuKC4+ixDPTuLZiqiWWQ2PSXHVg==", "dev": true, + "license": "MIT", "dependencies": { - "@vitest/utils": "2.1.3", + "@vitest/utils": "2.1.8", "pathe": "^1.1.2" }, "funding": { @@ -5679,13 +5702,14 @@ } }, "node_modules/@vitest/snapshot": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-2.1.3.tgz", - "integrity": "sha512-qWC2mWc7VAXmjAkEKxrScWHWFyCQx/cmiZtuGqMi+WwqQJ2iURsVY4ZfAK6dVo6K2smKRU6l3BPwqEBvhnpQGg==", + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-2.1.8.tgz", + "integrity": "sha512-20T7xRFbmnkfcmgVEz+z3AU/3b0cEzZOt/zmnvZEctg64/QZbSDJEVm9fLnnlSi74KibmRsO9/Qabi+t0vCRPg==", "dev": true, + "license": "MIT", "dependencies": { - "@vitest/pretty-format": "2.1.3", - "magic-string": "^0.30.11", + "@vitest/pretty-format": "2.1.8", + "magic-string": "^0.30.12", "pathe": "^1.1.2" }, "funding": { @@ -5693,34 +5717,37 @@ } }, "node_modules/@vitest/snapshot/node_modules/magic-string": { - "version": "0.30.11", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.11.tgz", - "integrity": "sha512-+Wri9p0QHMy+545hKww7YAu5NyzF8iomPL/RQazugQ9+Ez4Ic3mERMd8ZTX5rfK944j+560ZJi8iAwgak1Ac7A==", + "version": "0.30.17", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", + "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==", "dev": true, + "license": "MIT", "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0" } }, "node_modules/@vitest/spy": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-2.1.3.tgz", - "integrity": "sha512-Nb2UzbcUswzeSP7JksMDaqsI43Sj5+Kry6ry6jQJT4b5gAK+NS9NED6mDb8FlMRCX8m5guaHCDZmqYMMWRy5nQ==", + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-2.1.8.tgz", + "integrity": "sha512-5swjf2q95gXeYPevtW0BLk6H8+bPlMb4Vw/9Em4hFxDcaOxS+e0LOX4yqNxoHzMR2akEB2xfpnWUzkZokmgWDg==", "dev": true, + "license": "MIT", "dependencies": { - "tinyspy": "^3.0.0" + "tinyspy": "^3.0.2" }, "funding": { "url": "https://opencollective.com/vitest" } }, "node_modules/@vitest/utils": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-2.1.3.tgz", - "integrity": "sha512-xpiVfDSg1RrYT0tX6czgerkpcKFmFOF/gCr30+Mve5V2kewCy4Prn1/NDMSRwaSmT7PRaOF83wu+bEtsY1wrvA==", + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-2.1.8.tgz", + "integrity": "sha512-dwSoui6djdwbfFmIgbIjX2ZhIoG7Ex/+xpxyiEgIGzjliY8xGkcpITKTlp6B4MgtGkF2ilvm97cPM96XZaAgcA==", "dev": true, + "license": "MIT", "dependencies": { - "@vitest/pretty-format": "2.1.3", - "loupe": "^3.1.1", + "@vitest/pretty-format": "2.1.8", + "loupe": "^3.1.2", "tinyrainbow": "^1.2.0" }, "funding": { @@ -5728,148 +5755,163 @@ } }, "node_modules/@webassemblyjs/ast": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.12.1.tgz", - "integrity": "sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.14.1.tgz", + "integrity": "sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==", "dev": true, + "license": "MIT", "dependencies": { - "@webassemblyjs/helper-numbers": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6" + "@webassemblyjs/helper-numbers": "1.13.2", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2" } }, "node_modules/@webassemblyjs/floating-point-hex-parser": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", - "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==", - "dev": true + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.13.2.tgz", + "integrity": "sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==", + "dev": true, + "license": "MIT" }, "node_modules/@webassemblyjs/helper-api-error": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", - "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==", - "dev": true - }, + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.13.2.tgz", + "integrity": "sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==", + "dev": true, + "license": "MIT" + }, "node_modules/@webassemblyjs/helper-buffer": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.12.1.tgz", - "integrity": "sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw==", - "dev": true + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.14.1.tgz", + "integrity": "sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==", + "dev": true, + "license": "MIT" }, "node_modules/@webassemblyjs/helper-numbers": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", - "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.13.2.tgz", + "integrity": "sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA==", "dev": true, + "license": "MIT", "dependencies": { - "@webassemblyjs/floating-point-hex-parser": "1.11.6", - "@webassemblyjs/helper-api-error": "1.11.6", + "@webassemblyjs/floating-point-hex-parser": "1.13.2", + "@webassemblyjs/helper-api-error": "1.13.2", "@xtuc/long": "4.2.2" } }, "node_modules/@webassemblyjs/helper-wasm-bytecode": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", - "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==", - "dev": true + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.13.2.tgz", + "integrity": "sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==", + "dev": true, + "license": "MIT" }, "node_modules/@webassemblyjs/helper-wasm-section": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.12.1.tgz", - "integrity": "sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.14.1.tgz", + "integrity": "sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw==", "dev": true, + "license": "MIT", "dependencies": { - "@webassemblyjs/ast": "1.12.1", - "@webassemblyjs/helper-buffer": "1.12.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/wasm-gen": "1.12.1" + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/wasm-gen": "1.14.1" } }, "node_modules/@webassemblyjs/ieee754": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", - "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.13.2.tgz", + "integrity": "sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw==", "dev": true, + "license": "MIT", "dependencies": { "@xtuc/ieee754": "^1.2.0" } }, "node_modules/@webassemblyjs/leb128": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", - "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.13.2.tgz", + "integrity": "sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw==", "dev": true, + "license": "Apache-2.0", "dependencies": { "@xtuc/long": "4.2.2" } }, "node_modules/@webassemblyjs/utf8": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", - "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==", - "dev": true + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.13.2.tgz", + "integrity": "sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ==", + "dev": true, + "license": "MIT" }, "node_modules/@webassemblyjs/wasm-edit": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.12.1.tgz", - "integrity": "sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.14.1.tgz", + "integrity": "sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ==", "dev": true, + "license": "MIT", "dependencies": { - "@webassemblyjs/ast": "1.12.1", - "@webassemblyjs/helper-buffer": "1.12.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/helper-wasm-section": "1.12.1", - "@webassemblyjs/wasm-gen": "1.12.1", - "@webassemblyjs/wasm-opt": "1.12.1", - "@webassemblyjs/wasm-parser": "1.12.1", - "@webassemblyjs/wast-printer": "1.12.1" + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/helper-wasm-section": "1.14.1", + "@webassemblyjs/wasm-gen": "1.14.1", + "@webassemblyjs/wasm-opt": "1.14.1", + "@webassemblyjs/wasm-parser": "1.14.1", + "@webassemblyjs/wast-printer": "1.14.1" } }, "node_modules/@webassemblyjs/wasm-gen": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.12.1.tgz", - "integrity": "sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.14.1.tgz", + "integrity": "sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg==", "dev": true, + "license": "MIT", "dependencies": { - "@webassemblyjs/ast": "1.12.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/ieee754": "1.11.6", - "@webassemblyjs/leb128": "1.11.6", - "@webassemblyjs/utf8": "1.11.6" + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/ieee754": "1.13.2", + "@webassemblyjs/leb128": "1.13.2", + "@webassemblyjs/utf8": "1.13.2" } }, "node_modules/@webassemblyjs/wasm-opt": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.12.1.tgz", - "integrity": "sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.14.1.tgz", + "integrity": "sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw==", "dev": true, + "license": "MIT", "dependencies": { - "@webassemblyjs/ast": "1.12.1", - "@webassemblyjs/helper-buffer": "1.12.1", - "@webassemblyjs/wasm-gen": "1.12.1", - "@webassemblyjs/wasm-parser": "1.12.1" + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/wasm-gen": "1.14.1", + "@webassemblyjs/wasm-parser": "1.14.1" } }, "node_modules/@webassemblyjs/wasm-parser": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.12.1.tgz", - "integrity": "sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.14.1.tgz", + "integrity": "sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ==", "dev": true, + "license": "MIT", "dependencies": { - "@webassemblyjs/ast": "1.12.1", - "@webassemblyjs/helper-api-error": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/ieee754": "1.11.6", - "@webassemblyjs/leb128": "1.11.6", - "@webassemblyjs/utf8": "1.11.6" + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-api-error": "1.13.2", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/ieee754": "1.13.2", + "@webassemblyjs/leb128": "1.13.2", + "@webassemblyjs/utf8": "1.13.2" } }, "node_modules/@webassemblyjs/wast-printer": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.12.1.tgz", - "integrity": "sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.14.1.tgz", + "integrity": "sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==", "dev": true, + "license": "MIT", "dependencies": { - "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/ast": "1.14.1", "@xtuc/long": "4.2.2" } }, @@ -5877,23 +5919,27 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", - "dev": true + "dev": true, + "license": "BSD-3-Clause" }, "node_modules/@xtuc/long": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", - "dev": true + "dev": true, + "license": "Apache-2.0" }, "node_modules/abbrev": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "license": "ISC" }, "node_modules/abort-controller": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "license": "MIT", "dependencies": { "event-target-shim": "^5.0.0" }, @@ -5905,6 +5951,7 @@ "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "license": "MIT", "dependencies": { "mime-types": "~2.1.34", "negotiator": "0.6.3" @@ -5914,9 +5961,10 @@ } }, "node_modules/acorn": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.0.tgz", - "integrity": "sha512-RTvkC4w+KNXrM39/lWCUaG0IbRkWdCv7W/IOW9oU6SawyxulvkQy5HQPVTKxEjczcUvapcrw3cFx/60VN/NRNw==", + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", + "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", + "license": "MIT", "bin": { "acorn": "bin/acorn" }, @@ -5928,6 +5976,7 @@ "version": "1.9.5", "resolved": "https://registry.npmjs.org/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz", "integrity": "sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==", + "license": "MIT", "peerDependencies": { "acorn": "^8" } @@ -5937,24 +5986,16 @@ "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", "dev": true, + "license": "MIT", "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, - "node_modules/acorn-walk": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.2.tgz", - "integrity": "sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==", - "optional": true, - "peer": true, - "engines": { - "node": ">=0.4.0" - } - }, "node_modules/agent-base": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "license": "MIT", "dependencies": { "debug": "4" }, @@ -5963,14 +6004,15 @@ } }, "node_modules/ajv": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", - "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, + "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" }, "funding": { @@ -5983,6 +6025,7 @@ "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", "dev": true, + "license": "MIT", "dependencies": { "ajv": "^8.0.0" }, @@ -5995,11 +6038,46 @@ } } }, + "node_modules/ajv-formats/node_modules/ajv": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-formats/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true, + "license": "MIT" + }, + "node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "ajv": "^6.9.1" + } + }, "node_modules/ansi-colors": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -6008,6 +6086,7 @@ "version": "4.3.2", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "license": "MIT", "dependencies": { "type-fest": "^0.21.3" }, @@ -6018,21 +6097,11 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/ansi-escapes/node_modules/type-fest": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", "engines": { "node": ">=8" } @@ -6041,6 +6110,7 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", "dependencies": { "color-convert": "^2.0.1" }, @@ -6054,12 +6124,14 @@ "node_modules/any-promise": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", - "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==" + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", + "license": "MIT" }, "node_modules/anymatch": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "license": "ISC", "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" @@ -6072,6 +6144,7 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "license": "MIT", "engines": { "node": ">=8.6" }, @@ -6083,6 +6156,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/app-root-path/-/app-root-path-3.1.0.tgz", "integrity": "sha512-biN3PwB2gUtjaYy/isrU3aNWI5w+fAfvHkSvCKeQGxhmYpwKFUxudR3Yya+KqVRHBmEDYh+/lTozYCFbmzX4nA==", + "license": "MIT", "engines": { "node": ">= 6.0.0" } @@ -6090,17 +6164,20 @@ "node_modules/append-field": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", - "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==" + "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==", + "license": "MIT" }, "node_modules/aproba": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", - "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==" + "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==", + "license": "ISC" }, "node_modules/archiver": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/archiver/-/archiver-7.0.1.tgz", "integrity": "sha512-ZcbTaIqJOfCc03QwD468Unz/5Ir8ATtvAHsK+FdXbDIbGfihqh9mrvdcYunQzqn4HrvWWaFyaxJhGZagaJJpPQ==", + "license": "MIT", "dependencies": { "archiver-utils": "^5.0.2", "async": "^3.2.4", @@ -6118,6 +6195,7 @@ "version": "5.0.2", "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-5.0.2.tgz", "integrity": "sha512-wuLJMmIBQYCsGZgYLTy5FIB2pF6Lfb6cXMSF8Qywwk3t20zWnAi7zLcQFdKQmIB8wyZpY5ER38x08GbwtR2cLA==", + "license": "MIT", "dependencies": { "glob": "^10.0.0", "graceful-fs": "^4.2.0", @@ -6131,94 +6209,12 @@ "node": ">= 14" } }, - "node_modules/archiver-utils/node_modules/buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" - } - }, - "node_modules/archiver-utils/node_modules/readable-stream": { - "version": "4.5.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz", - "integrity": "sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==", - "dependencies": { - "abort-controller": "^3.0.0", - "buffer": "^6.0.3", - "events": "^3.3.0", - "process": "^0.11.10", - "string_decoder": "^1.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/archiver/node_modules/buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" - } - }, - "node_modules/archiver/node_modules/buffer-crc32": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-1.0.0.tgz", - "integrity": "sha512-Db1SbgBS/fg/392AblrMJk97KggmvYhr4pB5ZIMTWtaivCPMWLkmb7m21cJvpvgK+J3nsU2CmmixNBZx4vFj/w==", - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/archiver/node_modules/readable-stream": { - "version": "4.5.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz", - "integrity": "sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==", - "dependencies": { - "abort-controller": "^3.0.0", - "buffer": "^6.0.3", - "events": "^3.3.0", - "process": "^0.11.10", - "string_decoder": "^1.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, "node_modules/are-we-there-yet": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", + "deprecated": "This package is no longer supported.", + "license": "ISC", "dependencies": { "delegates": "^1.0.0", "readable-stream": "^3.6.0" @@ -6227,39 +6223,58 @@ "node": ">=10" } }, + "node_modules/are-we-there-yet/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/arg": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", - "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "optional": true, + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", + "license": "MIT", "peer": true }, "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "license": "Python-2.0" }, "node_modules/array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", + "license": "MIT" }, "node_modules/array-source": { "version": "0.0.4", "resolved": "https://registry.npmjs.org/array-source/-/array-source-0.0.4.tgz", - "integrity": "sha512-frNdc+zBn80vipY+GdcJkLEbMWj3xmzArYApmUGxoiV8uAu/ygcs9icPdsGdA26h0MkHUMW6EN2piIvVx+M5Mw==" + "integrity": "sha512-frNdc+zBn80vipY+GdcJkLEbMWj3xmzArYApmUGxoiV8uAu/ygcs9icPdsGdA26h0MkHUMW6EN2piIvVx+M5Mw==", + "license": "BSD-3-Clause" }, "node_modules/array-timsort": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/array-timsort/-/array-timsort-1.0.3.tgz", "integrity": "sha512-/+3GRL7dDAGEfM6TseQk/U+mi18TU2Ms9I3UlLdUMhz2hbvGNTKdj9xniwXfUqgYhHxRx0+8UnKkvlNwVU+cWQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/asn1": { "version": "0.2.6", "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", "dev": true, + "license": "MIT", "dependencies": { "safer-buffer": "~2.1.0" } @@ -6269,41 +6284,55 @@ "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", "dev": true, + "license": "MIT", "engines": { "node": ">=12" } }, "node_modules/async": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", - "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==" + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", + "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", + "license": "MIT" }, "node_modules/async-lock": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/async-lock/-/async-lock-1.4.1.tgz", - "integrity": "sha512-Az2ZTpuytrtqENulXwO3GGv1Bztugx6TT37NIo7imr/Qo0gsYiGtSdBa2B6fsXhTpVZDNfu1Qn3pk531e3q+nQ==" + "integrity": "sha512-Az2ZTpuytrtqENulXwO3GGv1Bztugx6TT37NIo7imr/Qo0gsYiGtSdBa2B6fsXhTpVZDNfu1Qn3pk531e3q+nQ==", + "license": "MIT" + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "dev": true, + "license": "MIT" }, "node_modules/b4a": { - "version": "1.6.4", - "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.6.4.tgz", - "integrity": "sha512-fpWrvyVHEKyeEvbKZTVOeZF3VSKKWtJxFIxX/jaVPf+cLbGUSitjb49pHLqPV2BUNNZ0LcoeEGfE/YCpyDYHIw==" + "version": "1.6.7", + "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.6.7.tgz", + "integrity": "sha512-OnAYlL5b7LEkALw87fUVafQw5rVR9RjwGd4KUwNQ6DrrNmaVaUCgLipfVlzrPQ4tWOR9P0IXGNOx50jYCCdSJg==", + "license": "Apache-2.0" }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "license": "MIT" }, "node_modules/bare-events": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.4.2.tgz", - "integrity": "sha512-qMKFd2qG/36aA4GwvKq8MxnPgCQAmBWmSyLWsJcbn8v03wvIPQ/hG1Ms8bPzndZxMDoHpxez5VOS+gC9Yi24/Q==", + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.5.0.tgz", + "integrity": "sha512-/E8dDe9dsbLyh2qrZ64PEPadOQ0F4gbl1sUJOrmph7xOiIxfY8vwab/4bFLh4Y88/Hk/ujKcrQKc+ps0mv873A==", + "license": "Apache-2.0", "optional": true }, "node_modules/bare-fs": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/bare-fs/-/bare-fs-2.3.1.tgz", - "integrity": "sha512-W/Hfxc/6VehXlsgFtbB5B4xFcsCl+pAh30cYhoFyXErf6oGrwjh8SwiPAdHgpmWonKuYpZgGywN0SXt7dgsADA==", + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/bare-fs/-/bare-fs-2.3.5.tgz", + "integrity": "sha512-SlE9eTxifPDJrT6YgemQ1WGFleevzwY+XAP1Xqgl56HtcrisC2CHCZ2tq6dBpcH2TnNxwUEUGhweo+lrQtYuiw==", "dev": true, + "license": "Apache-2.0", "optional": true, "dependencies": { "bare-events": "^2.0.0", @@ -6312,10 +6341,11 @@ } }, "node_modules/bare-os": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/bare-os/-/bare-os-2.4.0.tgz", - "integrity": "sha512-v8DTT08AS/G0F9xrhyLtepoo9EJBJ85FRSMbu1pQUlAf6A8T0tEEQGMVObWeqpjhSPXsE0VGlluFBJu2fdoTNg==", + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/bare-os/-/bare-os-2.4.4.tgz", + "integrity": "sha512-z3UiI2yi1mK0sXeRdc4O1Kk8aOa/e+FNWZcTiPB/dfTWyLypuE99LibgRaQki914Jq//yAWylcAt+mknKdixRQ==", "dev": true, + "license": "Apache-2.0", "optional": true }, "node_modules/bare-path": { @@ -6323,19 +6353,21 @@ "resolved": "https://registry.npmjs.org/bare-path/-/bare-path-2.1.3.tgz", "integrity": "sha512-lh/eITfU8hrj9Ru5quUp0Io1kJWIk1bTjzo7JH1P5dWmQ2EL4hFUlfI8FonAhSlgIfhn63p84CDY/x+PisgcXA==", "dev": true, + "license": "Apache-2.0", "optional": true, "dependencies": { "bare-os": "^2.1.0" } }, "node_modules/bare-stream": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/bare-stream/-/bare-stream-2.1.3.tgz", - "integrity": "sha512-tiDAH9H/kP+tvNO5sczyn9ZAA7utrSMobyDchsnyyXBuUe2FSQWbxhtuHB8jwpHYYevVo2UJpcmvvjrbHboUUQ==", + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/bare-stream/-/bare-stream-2.6.1.tgz", + "integrity": "sha512-eVZbtKM+4uehzrsj49KtCy3Pbg7kO1pJ3SKZ1SFrIH/0pnj9scuGGgUlNDf/7qS8WKtGdiJY5Kyhs/ivYPTB/g==", "dev": true, + "license": "Apache-2.0", "optional": true, "dependencies": { - "streamx": "^2.18.0" + "streamx": "^2.21.0" } }, "node_modules/base64-js": { @@ -6355,12 +6387,14 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "MIT" }, "node_modules/base64id": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==", + "license": "MIT", "engines": { "node": "^4.5.0 || >= 5.9" } @@ -6369,6 +6403,7 @@ "version": "13.0.0", "resolved": "https://registry.npmjs.org/batch-cluster/-/batch-cluster-13.0.0.tgz", "integrity": "sha512-EreW0Vi8TwovhYUHBXXRA5tthuU2ynGsZFlboyMJHCCUXYa2AjgwnE3ubBOJs2xJLcuXFJbi6c/8pH5+FVj8Og==", + "license": "MIT", "engines": { "node": ">=14" } @@ -6378,6 +6413,7 @@ "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-5.1.1.tgz", "integrity": "sha512-AGBHOG5hPYZ5Xl9KXzU5iKq9516yEmvCKDg3ecP5kX2aB6UqTeXZxk2ELnDgDm6BQSMlLt9rDB4LoSMx0rYwww==", "hasInstallScript": true, + "license": "MIT", "dependencies": { "@mapbox/node-pre-gyp": "^1.0.11", "node-addon-api": "^5.0.0" @@ -6391,45 +6427,62 @@ "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "tweetnacl": "^0.14.3" } }, - "node_modules/bcrypt/node_modules/node-addon-api": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz", - "integrity": "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==" - }, "node_modules/bignumber.js": { "version": "9.1.2", "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.1.2.tgz", "integrity": "sha512-2/mKyZH9K85bzOEfhXDBFZTGd1CTs+5IHpeFQo9luiBG7hghdC851Pj2WAhb6E3R6b9tZj/XKhbg4fum+Kepug==", + "license": "MIT", "engines": { "node": "*" } }, "node_modules/binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "license": "MIT", "engines": { "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/bl": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "license": "MIT", "dependencies": { "buffer": "^5.5.0", "inherits": "^2.0.4", "readable-stream": "^3.4.0" } }, + "node_modules/bl/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/body-parser": { "version": "1.20.3", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", + "license": "MIT", "dependencies": { "bytes": "3.1.2", "content-type": "~1.0.5", @@ -6453,6 +6506,7 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", "dependencies": { "ms": "2.0.0" } @@ -6460,12 +6514,14 @@ "node_modules/body-parser/node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" }, "node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -6475,6 +6531,7 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "license": "MIT", "dependencies": { "fill-range": "^7.1.1" }, @@ -6483,9 +6540,9 @@ } }, "node_modules/browserslist": { - "version": "4.23.0", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz", - "integrity": "sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==", + "version": "4.24.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.3.tgz", + "integrity": "sha512-1CPmv8iobE2fyRMV97dAcMVegvvWKxmq94hkLiAkUGwKVTyDLw33K+ZxiFrREKmmps4rIw6grcCFCnTMSZ/YiA==", "funding": [ { "type": "opencollective", @@ -6500,11 +6557,12 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "dependencies": { - "caniuse-lite": "^1.0.30001587", - "electron-to-chromium": "^1.4.668", - "node-releases": "^2.0.14", - "update-browserslist-db": "^1.0.13" + "caniuse-lite": "^1.0.30001688", + "electron-to-chromium": "^1.5.73", + "node-releases": "^2.0.19", + "update-browserslist-db": "^1.1.1" }, "bin": { "browserslist": "cli.js" @@ -6531,15 +6589,26 @@ "url": "https://feross.org/support" } ], + "license": "MIT", "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.1.13" } }, + "node_modules/buffer-crc32": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-1.0.0.tgz", + "integrity": "sha512-Db1SbgBS/fg/392AblrMJk97KggmvYhr4pB5ZIMTWtaivCPMWLkmb7m21cJvpvgK+J3nsU2CmmixNBZx4vFj/w==", + "license": "MIT", + "engines": { + "node": ">=8.0.0" + } + }, "node_modules/buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "license": "MIT" }, "node_modules/buildcheck": { "version": "0.0.6", @@ -6556,6 +6625,7 @@ "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz", "integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" }, @@ -6567,6 +6637,7 @@ "version": "4.18.2", "resolved": "https://registry.npmjs.org/bullmq/-/bullmq-4.18.2.tgz", "integrity": "sha512-Cx0O98IlGiFw7UBa+zwGz+nH0Pcl1wfTvMVBlsMna3s0219hXroVovh1xPRgomyUcbyciHiugGCkW0RRNZDHYQ==", + "license": "MIT", "dependencies": { "cron-parser": "^4.6.0", "glob": "^8.0.3", @@ -6583,6 +6654,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" } @@ -6592,6 +6664,7 @@ "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", "deprecated": "Glob versions prior to v9 are no longer supported", + "license": "ISC", "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -6610,6 +6683,7 @@ "version": "5.1.6", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" }, @@ -6617,22 +6691,36 @@ "node": ">=10" } }, - "node_modules/busboy": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", - "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", - "dependencies": { - "streamsearch": "^1.1.0" - }, - "engines": { - "node": ">=10.16.0" - } - }, + "node_modules/bullmq/node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/busboy": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", + "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", + "dependencies": { + "streamsearch": "^1.1.0" + }, + "engines": { + "node": ">=10.16.0" + } + }, "node_modules/byline": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/byline/-/byline-5.0.0.tgz", "integrity": "sha512-s6webAy+R4SR8XVuJWt2V2rGvhnrhxN+9S15GNuTK3wKPOXFF6RNc+8ug2XhH+2s4f+uudG4kUVYmYOQWL2g0Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -6641,6 +6729,7 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "license": "MIT", "engines": { "node": ">= 0.8" } @@ -6650,20 +6739,51 @@ "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/call-bind": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", - "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", + "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==", + "dev": true, + "license": "MIT", "dependencies": { + "call-bind-apply-helpers": "^1.0.0", "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", "get-intrinsic": "^1.2.4", - "set-function-length": "^1.2.1" + "set-function-length": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.1.tgz", + "integrity": "sha512-BhYE+WDaywFg2TBWYNXAE+8B1ATnThNBqXHP5nQu0jWJdVvY2hvkpyB3qOmtmDePiS5/BDQ8wASEWGMWRG148g==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.3.tgz", + "integrity": "sha512-YTd+6wGlNlPxSuri7Y6X8tY2dmm12UMH66RpKMhiX6rsk5wXXnYgbUcOt8kiS31/AjfoTOvCsE+w8nZQLQnzHA==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "get-intrinsic": "^1.2.6" }, "engines": { "node": ">= 0.4" @@ -6676,6 +6796,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "license": "MIT", "engines": { "node": ">=6" } @@ -6684,15 +6805,16 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", + "license": "MIT", "peer": true, "engines": { "node": ">= 6" } }, "node_modules/caniuse-lite": { - "version": "1.0.30001618", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001618.tgz", - "integrity": "sha512-p407+D1tIkDvsEAPS22lJxLQQaG8OTBEqo0KhzfABGk0TU4juBNDSfH0hyAp/HRyx+M8L17z/ltyhxh27FTfQg==", + "version": "1.0.30001689", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001689.tgz", + "integrity": "sha512-CmeR2VBycfa+5/jOfnp/NpWPGd06nf1XYiefUvhXFfZE4GkRc9jv+eGPS4nT558WS/8lYCzV8SlANCIPvbWP1g==", "funding": [ { "type": "opencollective", @@ -6706,13 +6828,15 @@ "type": "github", "url": "https://github.com/sponsors/ai" } - ] + ], + "license": "CC-BY-4.0" }, "node_modules/chai": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/chai/-/chai-5.1.1.tgz", - "integrity": "sha512-pT1ZgP8rPNqUgieVaEY+ryQr6Q4HXNg8Ei9UnLUrjN4IA7dvQC5JB+/kxVcPNDHyBcc/26CXPkbNzq3qwrOEKA==", + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/chai/-/chai-5.1.2.tgz", + "integrity": "sha512-aGtmf24DW6MLHHG5gCx4zaI3uBq3KRtxeVs0DjFH6Z0rDNbsvTxFASFvdj79pxjxZ8/5u3PIiN3IwEIQkiiuPw==", "dev": true, + "license": "MIT", "dependencies": { "assertion-error": "^2.0.1", "check-error": "^2.1.1", @@ -6728,6 +6852,7 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -6742,13 +6867,15 @@ "node_modules/chardet": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", - "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==" + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", + "license": "MIT" }, "node_modules/check-error": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.1.tgz", "integrity": "sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==", "dev": true, + "license": "MIT", "engines": { "node": ">= 16" } @@ -6757,6 +6884,7 @@ "version": "3.6.0", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "license": "MIT", "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", @@ -6780,23 +6908,25 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "license": "ISC", "engines": { "node": ">=10" } }, "node_modules/chrome-trace-event": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", - "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz", + "integrity": "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.0" } }, "node_modules/ci-info": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.0.0.tgz", - "integrity": "sha512-TdHqgGf9odd8SXNuxtUBVx8Nv+qZOejE6qyqiy5NtbYYQOeFa6zmHkxlPzmaLxWWHsU6nJmB7AETdVPi+2NBUg==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.1.0.tgz", + "integrity": "sha512-HutrvTNsF48wnxkzERIXOe5/mlcfFcbfCmwcg6CJnizbSue78AbDt+1cgl26zwn61WFxhcPykPfZrbqjGmBb4A==", "dev": true, "funding": [ { @@ -6804,6 +6934,7 @@ "url": "https://github.com/sponsors/sibiraj-s" } ], + "license": "MIT", "engines": { "node": ">=8" } @@ -6811,17 +6942,20 @@ "node_modules/cjs-module-lexer": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.1.tgz", - "integrity": "sha512-cuSVIHi9/9E/+821Qjdvngor+xpnlwnuwIyZOaLmHBVdXL+gP+I6QQB9VkO7RI77YIcTV+S1W9AreJ5eN63JBA==" + "integrity": "sha512-cuSVIHi9/9E/+821Qjdvngor+xpnlwnuwIyZOaLmHBVdXL+gP+I6QQB9VkO7RI77YIcTV+S1W9AreJ5eN63JBA==", + "license": "MIT" }, "node_modules/class-transformer": { "version": "0.5.1", "resolved": "https://registry.npmjs.org/class-transformer/-/class-transformer-0.5.1.tgz", - "integrity": "sha512-SQa1Ws6hUbfC98vKGxZH3KFY0Y1lm5Zm0SY8XX9zbK7FJCyVEac3ATW0RIpwzW+oOfmHE5PMPufDG9hCfoEOMw==" + "integrity": "sha512-SQa1Ws6hUbfC98vKGxZH3KFY0Y1lm5Zm0SY8XX9zbK7FJCyVEac3ATW0RIpwzW+oOfmHE5PMPufDG9hCfoEOMw==", + "license": "MIT" }, "node_modules/class-validator": { "version": "0.14.1", "resolved": "https://registry.npmjs.org/class-validator/-/class-validator-0.14.1.tgz", "integrity": "sha512-2VEG9JICxIqTpoK1eMzZqaV+u/EiwEJkMGzTrZf6sU/fwsnOITVgYJ8yojSy6CaXtO9V0Cc6ZQZ8h8m4UBuLwQ==", + "license": "MIT", "dependencies": { "@types/validator": "^13.11.8", "libphonenumber-js": "^1.10.53", @@ -6833,6 +6967,7 @@ "resolved": "https://registry.npmjs.org/clean-regexp/-/clean-regexp-1.0.0.tgz", "integrity": "sha512-GfisEZEJvzKrmGWkvfhgzcz/BllN1USeqD2V6tg14OAOgaCD2Z/PUEuxnAZ/nPvmaHRG7a8y77p1T/IRQ4D1Hw==", "dev": true, + "license": "MIT", "dependencies": { "escape-string-regexp": "^1.0.5" }, @@ -6845,6 +6980,7 @@ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.8.0" } @@ -6853,6 +6989,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "license": "MIT", "dependencies": { "restore-cursor": "^3.1.0" }, @@ -6864,6 +7001,7 @@ "version": "2.1.11", "resolved": "https://registry.npmjs.org/cli-highlight/-/cli-highlight-2.1.11.tgz", "integrity": "sha512-9KDcoEVwyUXrjcJNvHD0NFc/hiwe/WPVYIleQh2O1N2Zro5gWJZ/K+3DGn8w8P/F6FxOgzyC5bxDyHIgCSPhGg==", + "license": "ISC", "dependencies": { "chalk": "^4.0.0", "highlight.js": "^10.7.1", @@ -6880,10 +7018,66 @@ "npm": ">=5.0.0" } }, + "node_modules/cli-highlight/node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/cli-highlight/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/cli-highlight/node_modules/yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "license": "MIT", + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/cli-highlight/node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "license": "ISC", + "engines": { + "node": ">=10" + } + }, "node_modules/cli-spinners": { - "version": "2.9.1", - "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.1.tgz", - "integrity": "sha512-jHgecW0pxkonBJdrKsqxgRX9AcG+u/5k0Q7WPDfi8AogLAdwxEkyYYNWwZ5GvVFoFx2uiY1eNcSK00fh+1+FyQ==", + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", + "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", + "license": "MIT", "engines": { "node": ">=6" }, @@ -6896,6 +7090,7 @@ "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.5.tgz", "integrity": "sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ==", "dev": true, + "license": "MIT", "dependencies": { "string-width": "^4.2.0" }, @@ -6910,6 +7105,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==", + "license": "ISC", "engines": { "node": ">= 10" } @@ -6917,22 +7113,28 @@ "node_modules/client-only": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", - "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==" + "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==", + "license": "MIT" }, "node_modules/cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "license": "ISC", "dependencies": { "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", + "strip-ansi": "^6.0.1", "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" } }, "node_modules/cliui/node_modules/wrap-ansi": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "license": "MIT", "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -6949,6 +7151,7 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", + "license": "MIT", "engines": { "node": ">=0.8" } @@ -6957,6 +7160,7 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz", "integrity": "sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==", + "license": "Apache-2.0", "engines": { "node": ">=0.10.0" } @@ -6965,6 +7169,7 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz", "integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==", + "license": "MIT", "dependencies": { "color-convert": "^2.0.1", "color-string": "^1.9.0" @@ -6977,6 +7182,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", "dependencies": { "color-name": "~1.1.4" }, @@ -6987,12 +7193,14 @@ "node_modules/color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT" }, "node_modules/color-string": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", + "license": "MIT", "dependencies": { "color-name": "^1.0.0", "simple-swizzle": "^0.2.2" @@ -7002,14 +7210,29 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "license": "ISC", "bin": { "color-support": "bin.js" } }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/commander": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "license": "MIT", "engines": { "node": ">= 6" } @@ -7019,6 +7242,7 @@ "resolved": "https://registry.npmjs.org/comment-json/-/comment-json-4.2.5.tgz", "integrity": "sha512-bKw/r35jR3HGt5PEPm1ljsQQGyCrR8sFGNiN5L+ykDHdpO8Smxkrkla9Yi6NkQyUrb8V54PGhfMs6NrIwtxtdw==", "dev": true, + "license": "MIT", "dependencies": { "array-timsort": "^1.0.3", "core-util-is": "^1.0.3", @@ -7034,6 +7258,7 @@ "version": "6.0.2", "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-6.0.2.tgz", "integrity": "sha512-6FqVXeETqWPoGcfzrXb37E50NP0LXT8kAMu5ooZayhWWdgEY4lBEEcbQNXtkuKQsGduxiIcI4gOTsxTmuq/bSg==", + "license": "MIT", "dependencies": { "crc-32": "^1.2.0", "crc32-stream": "^6.0.0", @@ -7045,48 +7270,11 @@ "node": ">= 14" } }, - "node_modules/compress-commons/node_modules/buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" - } - }, - "node_modules/compress-commons/node_modules/readable-stream": { - "version": "4.5.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz", - "integrity": "sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==", - "dependencies": { - "abort-controller": "^3.0.0", - "buffer": "^6.0.3", - "events": "^3.3.0", - "process": "^0.11.10", - "string_decoder": "^1.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "license": "MIT" }, "node_modules/concat-stream": { "version": "2.0.0", @@ -7095,6 +7283,7 @@ "engines": [ "node >= 6.0" ], + "license": "MIT", "dependencies": { "buffer-from": "^1.0.0", "inherits": "^2.0.3", @@ -7102,29 +7291,37 @@ "typedarray": "^0.0.6" } }, - "node_modules/config-chain": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz", - "integrity": "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==", + "node_modules/concat-stream/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "license": "MIT", "dependencies": { - "ini": "^1.3.4", - "proto-list": "~1.2.1" + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" } }, "node_modules/consola": { "version": "2.15.3", "resolved": "https://registry.npmjs.org/consola/-/consola-2.15.3.tgz", - "integrity": "sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw==" + "integrity": "sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw==", + "license": "MIT" }, "node_modules/console-control-strings": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", + "license": "ISC" }, "node_modules/content-disposition": { "version": "0.5.4", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "license": "MIT", "dependencies": { "safe-buffer": "5.2.1" }, @@ -7136,6 +7333,7 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -7143,12 +7341,14 @@ "node_modules/convert-source-map": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==" + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "license": "MIT" }, "node_modules/cookie": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz", - "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==", + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -7157,6 +7357,7 @@ "version": "1.4.7", "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.7.tgz", "integrity": "sha512-nGUvgXnotP3BsjiLX2ypbQnWoGUPIIfHQNZkkC668ntrzGWEZVW70HDEB1qnNGMicPje6EttlIgzo51YSwNQGw==", + "license": "MIT", "dependencies": { "cookie": "0.7.2", "cookie-signature": "1.0.6" @@ -7165,26 +7366,20 @@ "node": ">= 0.8.0" } }, - "node_modules/cookie-parser/node_modules/cookie": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", - "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", - "engines": { - "node": ">= 0.6" - } - }, "node_modules/cookie-signature": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", + "license": "MIT" }, "node_modules/core-js-compat": { - "version": "3.37.1", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.37.1.tgz", - "integrity": "sha512-9TNiImhKvQqSUkOvk/mMRZzOANTiEVC7WaBNhHcKM7x+/5E1l5NvsysR19zuDQScE8k+kfQXWRN3AtS/eOSHpg==", + "version": "3.39.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.39.0.tgz", + "integrity": "sha512-VgEUx3VwlExr5no0tXlBt+silBvhTryPwCXRI2Id1PN8WTKu7MreethvddqOubrYxkFdv/RnYrqlv1sFNAUelw==", "dev": true, + "license": "MIT", "dependencies": { - "browserslist": "^4.23.0" + "browserslist": "^4.24.2" }, "funding": { "type": "opencollective", @@ -7194,12 +7389,14 @@ "node_modules/core-util-is": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "license": "MIT" }, "node_modules/cors": { "version": "2.8.5", "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "license": "MIT", "dependencies": { "object-assign": "^4", "vary": "^1" @@ -7212,6 +7409,7 @@ "version": "8.3.6", "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", + "license": "MIT", "dependencies": { "import-fresh": "^3.3.0", "js-yaml": "^4.1.0", @@ -7234,15 +7432,15 @@ } }, "node_modules/cpu-features": { - "version": "0.0.9", - "resolved": "https://registry.npmjs.org/cpu-features/-/cpu-features-0.0.9.tgz", - "integrity": "sha512-AKjgn2rP2yJyfbepsmLfiYcmtNn/2eUvocUyM/09yB0YDiz39HteK/5/T4Onf0pmdYDMgkBoGvRLvEguzyL7wQ==", + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/cpu-features/-/cpu-features-0.0.10.tgz", + "integrity": "sha512-9IkYqtX3YHPCzoVg1Py+o9057a3i0fp7S530UWokCSaFVTc7CwXPRiOjRjBQQ18ZCNafx78YfnG+HALxtVmOGA==", "dev": true, "hasInstallScript": true, "optional": true, "dependencies": { "buildcheck": "~0.0.6", - "nan": "^2.17.0" + "nan": "^2.19.0" }, "engines": { "node": ">=10.0.0" @@ -7252,6 +7450,7 @@ "version": "1.2.2", "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz", "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==", + "license": "Apache-2.0", "bin": { "crc32": "bin/crc32.njs" }, @@ -7263,6 +7462,7 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-6.0.0.tgz", "integrity": "sha512-piICUB6ei4IlTv1+653yq5+KoqfBYmj9bw6LqXoOneTMDXk5nM1qt12mFW1caG3LlJXEKW1Bp0WggEmIfQB34g==", + "license": "MIT", "dependencies": { "crc-32": "^1.2.0", "readable-stream": "^4.0.0" @@ -7271,83 +7471,33 @@ "node": ">= 14" } }, - "node_modules/crc32-stream/node_modules/buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], + "node_modules/cron": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/cron/-/cron-3.2.1.tgz", + "integrity": "sha512-w2n5l49GMmmkBFEsH9FIDhjZ1n1QgTMOCMGuQtOXs5veNiosZmso6bQGuqOJSYAXXrG84WQFVneNk+Yt0Ua9iw==", + "license": "MIT", "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" + "@types/luxon": "~3.4.0", + "luxon": "~3.5.0" } }, - "node_modules/crc32-stream/node_modules/readable-stream": { - "version": "4.5.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz", - "integrity": "sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==", + "node_modules/cron-parser": { + "version": "4.9.0", + "resolved": "https://registry.npmjs.org/cron-parser/-/cron-parser-4.9.0.tgz", + "integrity": "sha512-p0SaNjrHOnQeR8/VnfGbmg9te2kfyYSQ7Sc/j/6DtPL3JQvKxmjO9TSjNFpujqV3vEYYBvNNvXSxzyksBWAx1Q==", + "license": "MIT", "dependencies": { - "abort-controller": "^3.0.0", - "buffer": "^6.0.3", - "events": "^3.3.0", - "process": "^0.11.10", - "string_decoder": "^1.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/create-require": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", - "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", - "optional": true, - "peer": true - }, - "node_modules/cron": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/cron/-/cron-3.1.7.tgz", - "integrity": "sha512-tlBg7ARsAMQLzgwqVxy8AZl/qlTc5nibqYwtNGoCrd+cV+ugI+tvZC1oT/8dFH8W455YrywGykx/KMmAqOr7Jw==", - "dependencies": { - "@types/luxon": "~3.4.0", - "luxon": "~3.4.0" - } - }, - "node_modules/cron-parser": { - "version": "4.9.0", - "resolved": "https://registry.npmjs.org/cron-parser/-/cron-parser-4.9.0.tgz", - "integrity": "sha512-p0SaNjrHOnQeR8/VnfGbmg9te2kfyYSQ7Sc/j/6DtPL3JQvKxmjO9TSjNFpujqV3vEYYBvNNvXSxzyksBWAx1Q==", - "dependencies": { - "luxon": "^3.2.1" + "luxon": "^3.2.1" }, "engines": { "node": ">=12.0.0" } }, - "node_modules/cron/node_modules/luxon": { - "version": "3.4.4", - "resolved": "https://registry.npmjs.org/luxon/-/luxon-3.4.4.tgz", - "integrity": "sha512-zobTr7akeGHnv7eBOXcRgMeCP6+uyYsczwmeRCauvpvaAltgNyTbLH/+VaEAPUeWBT+1GuNmz4wC/6jtQzbbVA==", - "engines": { - "node": ">=12" - } - }, "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "license": "MIT", "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -7361,6 +7511,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "license": "MIT", "peer": true, "bin": { "cssesc": "bin/cssesc" @@ -7373,17 +7524,20 @@ "version": "3.1.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/dayjs": { - "version": "1.11.10", - "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.10.tgz", - "integrity": "sha512-vjAczensTgRcqDERK0SR2XMwsF/tSvnvlv6VcF2GIhg6Sx4yOIt/irsr1RDJsKiIyBzJDpCoXiWWq28MqH2cnQ==" + "version": "1.11.13", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz", + "integrity": "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==", + "license": "MIT" }, "node_modules/debounce": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/debounce/-/debounce-2.0.0.tgz", "integrity": "sha512-xRetU6gL1VJbs85Mc4FoEGSjQxzpdxRyFhe3lmWFyy2EzydIcD4xzUvRJMD+NPDfMwKNhxa3PvsIOU32luIWeA==", + "license": "MIT", "engines": { "node": ">=18" }, @@ -7392,9 +7546,10 @@ } }, "node_modules/debug": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", - "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "license": "MIT", "dependencies": { "ms": "^2.1.3" }, @@ -7412,6 +7567,7 @@ "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz", "integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -7420,12 +7576,14 @@ "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/deepmerge": { "version": "4.3.1", "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -7434,6 +7592,7 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", + "license": "MIT", "dependencies": { "clone": "^1.0.2" }, @@ -7442,14 +7601,15 @@ } }, "node_modules/define-data-property": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.3.tgz", - "integrity": "sha512-h3GBouC+RPtNX2N0hHVLo2ZwPYurq8mLmXpOLTsw71gr7lHt5VaI4vVkDUNOfiWmm48JEXe3VM7PmLX45AMmmg==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dev": true, + "license": "MIT", "dependencies": { + "es-define-property": "^1.0.0", "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.1" + "gopd": "^1.0.1" }, "engines": { "node": ">= 0.4" @@ -7458,15 +7618,27 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/delegates": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", + "license": "MIT" }, "node_modules/denque": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==", + "license": "Apache-2.0", "engines": { "node": ">=0.10" } @@ -7475,6 +7647,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "license": "MIT", "engines": { "node": ">= 0.8" } @@ -7483,6 +7656,7 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "license": "MIT", "engines": { "node": ">= 0.8", "npm": "1.2.8000 || >= 1.4.16" @@ -7492,6 +7666,7 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz", "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==", + "license": "Apache-2.0", "engines": { "node": ">=8" } @@ -7499,34 +7674,28 @@ "node_modules/diacritics": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/diacritics/-/diacritics-1.3.0.tgz", - "integrity": "sha512-wlwEkqcsaxvPJML+rDh/2iS824jbREk6DUMUKkEaSlxdYHeS43cClJtsWglvw2RfeXGm6ohKDqsXteJ5sP5enA==" + "integrity": "sha512-wlwEkqcsaxvPJML+rDh/2iS824jbREk6DUMUKkEaSlxdYHeS43cClJtsWglvw2RfeXGm6ohKDqsXteJ5sP5enA==", + "license": "MIT" }, "node_modules/didyoumean": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", + "license": "Apache-2.0", "peer": true }, - "node_modules/diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "optional": true, - "peer": true, - "engines": { - "node": ">=0.3.1" - } - }, "node_modules/discontinuous-range": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/discontinuous-range/-/discontinuous-range-1.0.0.tgz", "integrity": "sha512-c68LpLbO+7kP/b1Hr1qs8/BJ09F5khZGTxqxZuhzxpmwJKOgRFHJWIb9/KmqnqHhLdO55aOxFH/EGBvUQbL/RQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/dlv": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", + "license": "MIT", "peer": true }, "node_modules/docker-compose": { @@ -7534,6 +7703,7 @@ "resolved": "https://registry.npmjs.org/docker-compose/-/docker-compose-0.24.8.tgz", "integrity": "sha512-plizRs/Vf15H+GCVxq2EUvyPK7ei9b/cVesHvjnX4xaXjM9spHe2Ytq0BitndFgvTJ3E3NljPNUEl7BAN43iZw==", "dev": true, + "license": "MIT", "dependencies": { "yaml": "^2.2.2" }, @@ -7546,6 +7716,7 @@ "resolved": "https://registry.npmjs.org/docker-modem/-/docker-modem-3.0.8.tgz", "integrity": "sha512-f0ReSURdM3pcKPNS30mxOHSbaFLcknGmQjwSfmbcdOw1XWKXVhukM3NJHhr7NpY9BIyyWQb0EBo3KQvvuU5egQ==", "dev": true, + "license": "Apache-2.0", "dependencies": { "debug": "^4.1.1", "readable-stream": "^3.5.0", @@ -7556,11 +7727,27 @@ "node": ">= 8.0" } }, + "node_modules/docker-modem/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/dockerode": { "version": "3.3.5", "resolved": "https://registry.npmjs.org/dockerode/-/dockerode-3.3.5.tgz", "integrity": "sha512-/0YNa3ZDNeLr/tSckmD69+Gq+qVNhvKfAHNeZJBnp7EOP6RGKV8ORrJHkUn20So5wU+xxT7+1n5u8PjHbfjbSA==", "dev": true, + "license": "Apache-2.0", "dependencies": { "@balena/dockerignore": "^1.0.2", "docker-modem": "^3.0.0", @@ -7574,13 +7761,30 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", - "dev": true + "dev": true, + "license": "ISC" + }, + "node_modules/dockerode/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } }, "node_modules/dockerode/node_modules/tar-fs": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.0.1.tgz", "integrity": "sha512-6tzWDMeroL87uF/+lin46k+Q+46rAJ0SyPGz7OW7wTgblI273hsBqk2C1j0/xNadNLKDTUL9BukSjB7cwgmlPA==", "dev": true, + "license": "MIT", "dependencies": { "chownr": "^1.1.1", "mkdirp-classic": "^0.5.2", @@ -7593,6 +7797,7 @@ "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", "dev": true, + "license": "MIT", "dependencies": { "bl": "^4.0.3", "end-of-stream": "^1.4.1", @@ -7608,6 +7813,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "license": "MIT", "dependencies": { "domelementtype": "^2.3.0", "domhandler": "^5.0.2", @@ -7626,12 +7832,14 @@ "type": "github", "url": "https://github.com/sponsors/fb55" } - ] + ], + "license": "BSD-2-Clause" }, "node_modules/domhandler": { "version": "5.0.3", "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "license": "BSD-2-Clause", "dependencies": { "domelementtype": "^2.3.0" }, @@ -7646,6 +7854,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz", "integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==", + "license": "BSD-2-Clause", "dependencies": { "dom-serializer": "^2.0.0", "domelementtype": "^2.3.0", @@ -7656,9 +7865,10 @@ } }, "node_modules/dotenv": { - "version": "16.4.5", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", - "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==", + "version": "16.4.7", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.7.tgz", + "integrity": "sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==", + "license": "BSD-2-Clause", "engines": { "node": ">=12" }, @@ -7666,77 +7876,49 @@ "url": "https://dotenvx.com" } }, - "node_modules/eastasianwidth": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" - }, - "node_modules/editorconfig": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-1.0.4.tgz", - "integrity": "sha512-L9Qe08KWTlqYMVvMcTIvMAdl1cDUubzRNYL+WfA4bLDMHe4nemKkpmYzkznE1FwLKu0EEmy6obgQKzMJrg4x9Q==", + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", "dependencies": { - "@one-ini/wasm": "0.1.1", - "commander": "^10.0.0", - "minimatch": "9.0.1", - "semver": "^7.5.3" - }, - "bin": { - "editorconfig": "bin/editorconfig" + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" }, "engines": { - "node": ">=14" - } - }, - "node_modules/editorconfig/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/editorconfig/node_modules/commander": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", - "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", - "engines": { - "node": ">=14" + "node": ">= 0.4" } }, - "node_modules/editorconfig/node_modules/minimatch": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.1.tgz", - "integrity": "sha512-0jWhJpD/MdhPXwPuiRkCbfYfSKp2qnn2eOc279qI7f+osl/l+prKSrvhg157zSYvx/1nmgn2NqdT6k2Z7zSH9w==", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "license": "MIT" }, "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "license": "MIT" }, "node_modules/electron-to-chromium": { - "version": "1.4.769", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.769.tgz", - "integrity": "sha512-bZu7p623NEA2rHTc9K1vykl57ektSPQYFFqQir8BOYf6EKOB+yIsbFB9Kpm7Cgt6tsLr9sRkqfqSZUw7LP1XxQ==" + "version": "1.5.74", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.74.tgz", + "integrity": "sha512-ck3//9RC+6oss/1Bh9tiAVFy5vfSKbRHAFh7Z3/eTRkEqJeWgymloShB17Vg3Z4nmDNp35vAd1BZ6CMW4Wt6Iw==", + "license": "ISC" }, "node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" }, "node_modules/encodeurl": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "license": "MIT", "engines": { "node": ">= 0.8" } @@ -7746,21 +7928,23 @@ "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", "dev": true, + "license": "MIT", "dependencies": { "once": "^1.4.0" } }, "node_modules/engine.io": { - "version": "6.5.5", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.5.5.tgz", - "integrity": "sha512-C5Pn8Wk+1vKBoHghJODM63yk8MvrO9EWZUfkAt5HAqIgPE4/8FF0PEGHXtEd40l223+cE5ABWuPzm38PHFXfMA==", + "version": "6.6.2", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.6.2.tgz", + "integrity": "sha512-gmNvsYi9C8iErnZdVcJnvCpSKbWTt1E8+JZo8b+daLninywUWi5NQ5STSHZ9rFjFO7imNcvb8Pc5pe/wMR5xEw==", + "license": "MIT", "dependencies": { "@types/cookie": "^0.4.1", "@types/cors": "^2.8.12", "@types/node": ">=10.0.0", "accepts": "~1.3.4", "base64id": "2.0.0", - "cookie": "~0.4.1", + "cookie": "~0.7.2", "cors": "~2.8.5", "debug": "~4.3.1", "engine.io-parser": "~5.2.1", @@ -7771,18 +7955,37 @@ } }, "node_modules/engine.io-parser": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.1.tgz", - "integrity": "sha512-9JktcM3u18nU9N2Lz3bWeBgxVgOKpw7yhRaoxQA3FUDZzzw+9WlA6p4G4u0RixNkg14fH7EfEc/RhpurtiROTQ==", + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.3.tgz", + "integrity": "sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==", + "license": "MIT", "engines": { "node": ">=10.0.0" } }, + "node_modules/engine.io/node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, "node_modules/enhanced-resolve": { "version": "5.17.1", "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz", "integrity": "sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==", "dev": true, + "license": "MIT", "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.2.0" @@ -7795,6 +7998,7 @@ "version": "4.5.0", "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "license": "BSD-2-Clause", "engines": { "node": ">=0.12" }, @@ -7806,17 +8010,16 @@ "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "license": "MIT", "dependencies": { "is-arrayish": "^0.2.1" } }, "node_modules/es-define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", - "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", - "dependencies": { - "get-intrinsic": "^1.2.4" - }, + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", "engines": { "node": ">= 0.4" } @@ -7825,22 +8028,36 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", "engines": { "node": ">= 0.4" } }, "node_modules/es-module-lexer": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.3.1.tgz", - "integrity": "sha512-JUFAyicQV9mXc3YRxPnDlrfBKpqt6hUYzz9/boprUJHs4e4KVr3XwOF70doO6gwXUor6EWZJAyWAfKki84t20Q==", - "dev": true + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.5.4.tgz", + "integrity": "sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==", + "dev": true, + "license": "MIT" + }, + "node_modules/es-object-atoms": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", + "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } }, "node_modules/esbuild": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", - "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", - "dev": true, + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.11.tgz", + "integrity": "sha512-HJ96Hev2hX/6i5cDVwcqiJBBtuo9+FeIJOtZ9W1kA5M6AMJRHUZlpYZ1/SbEwtO0ioNAW8rUooVpC/WehY2SfA==", "hasInstallScript": true, + "license": "MIT", "bin": { "esbuild": "bin/esbuild" }, @@ -7848,35 +8065,36 @@ "node": ">=12" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.21.5", - "@esbuild/android-arm": "0.21.5", - "@esbuild/android-arm64": "0.21.5", - "@esbuild/android-x64": "0.21.5", - "@esbuild/darwin-arm64": "0.21.5", - "@esbuild/darwin-x64": "0.21.5", - "@esbuild/freebsd-arm64": "0.21.5", - "@esbuild/freebsd-x64": "0.21.5", - "@esbuild/linux-arm": "0.21.5", - "@esbuild/linux-arm64": "0.21.5", - "@esbuild/linux-ia32": "0.21.5", - "@esbuild/linux-loong64": "0.21.5", - "@esbuild/linux-mips64el": "0.21.5", - "@esbuild/linux-ppc64": "0.21.5", - "@esbuild/linux-riscv64": "0.21.5", - "@esbuild/linux-s390x": "0.21.5", - "@esbuild/linux-x64": "0.21.5", - "@esbuild/netbsd-x64": "0.21.5", - "@esbuild/openbsd-x64": "0.21.5", - "@esbuild/sunos-x64": "0.21.5", - "@esbuild/win32-arm64": "0.21.5", - "@esbuild/win32-ia32": "0.21.5", - "@esbuild/win32-x64": "0.21.5" + "@esbuild/aix-ppc64": "0.19.11", + "@esbuild/android-arm": "0.19.11", + "@esbuild/android-arm64": "0.19.11", + "@esbuild/android-x64": "0.19.11", + "@esbuild/darwin-arm64": "0.19.11", + "@esbuild/darwin-x64": "0.19.11", + "@esbuild/freebsd-arm64": "0.19.11", + "@esbuild/freebsd-x64": "0.19.11", + "@esbuild/linux-arm": "0.19.11", + "@esbuild/linux-arm64": "0.19.11", + "@esbuild/linux-ia32": "0.19.11", + "@esbuild/linux-loong64": "0.19.11", + "@esbuild/linux-mips64el": "0.19.11", + "@esbuild/linux-ppc64": "0.19.11", + "@esbuild/linux-riscv64": "0.19.11", + "@esbuild/linux-s390x": "0.19.11", + "@esbuild/linux-x64": "0.19.11", + "@esbuild/netbsd-x64": "0.19.11", + "@esbuild/openbsd-x64": "0.19.11", + "@esbuild/sunos-x64": "0.19.11", + "@esbuild/win32-arm64": "0.19.11", + "@esbuild/win32-ia32": "0.19.11", + "@esbuild/win32-x64": "0.19.11" } }, "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "license": "MIT", "engines": { "node": ">=6" } @@ -7884,13 +8102,15 @@ "node_modules/escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "license": "MIT" }, "node_modules/escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -7899,31 +8119,32 @@ } }, "node_modules/eslint": { - "version": "9.13.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.13.0.tgz", - "integrity": "sha512-EYZK6SX6zjFHST/HRytOdA/zE72Cq/bfw45LSyuwrdvcclb/gqV8RRQxywOBEWO2+WDpva6UZa4CcDeJKzUCFA==", + "version": "9.17.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.17.0.tgz", + "integrity": "sha512-evtlNcpJg+cZLcnVKwsai8fExnqjGPicK7gnUtlNuzu+Fv9bI0aLpND5T44VLQtoMEnI57LoXO9XAkIXwohKrA==", "dev": true, + "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.11.0", - "@eslint/config-array": "^0.18.0", - "@eslint/core": "^0.7.0", - "@eslint/eslintrc": "^3.1.0", - "@eslint/js": "9.13.0", - "@eslint/plugin-kit": "^0.2.0", - "@humanfs/node": "^0.16.5", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.19.0", + "@eslint/core": "^0.9.0", + "@eslint/eslintrc": "^3.2.0", + "@eslint/js": "9.17.0", + "@eslint/plugin-kit": "^0.2.3", + "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", - "@humanwhocodes/retry": "^0.3.1", + "@humanwhocodes/retry": "^0.4.1", "@types/estree": "^1.0.6", "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", + "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^8.1.0", - "eslint-visitor-keys": "^4.1.0", - "espree": "^10.2.0", + "eslint-scope": "^8.2.0", + "eslint-visitor-keys": "^4.2.0", + "espree": "^10.3.0", "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", @@ -7937,8 +8158,7 @@ "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", - "optionator": "^0.9.3", - "text-table": "^0.2.0" + "optionator": "^0.9.3" }, "bin": { "eslint": "bin/eslint.js" @@ -7963,6 +8183,7 @@ "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz", "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==", "dev": true, + "license": "MIT", "bin": { "eslint-config-prettier": "bin/cli.js" }, @@ -7975,6 +8196,7 @@ "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.2.1.tgz", "integrity": "sha512-gH3iR3g4JfF+yYPaJYkN7jEl9QbweL/YfkoRlNnuIEHEz1vHVlCmWOS+eGGiRuzHQXdJFCOTxRgvju9b8VUmrw==", "dev": true, + "license": "MIT", "dependencies": { "prettier-linter-helpers": "^1.0.0", "synckit": "^0.9.1" @@ -8001,18 +8223,19 @@ } }, "node_modules/eslint-plugin-unicorn": { - "version": "55.0.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-unicorn/-/eslint-plugin-unicorn-55.0.0.tgz", - "integrity": "sha512-n3AKiVpY2/uDcGrS3+QsYDkjPfaOrNrsfQxU9nt5nitd9KuvVXrfAvgCO9DYPSfap+Gqjw9EOrXIsBp5tlHZjA==", + "version": "56.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-unicorn/-/eslint-plugin-unicorn-56.0.1.tgz", + "integrity": "sha512-FwVV0Uwf8XPfVnKSGpMg7NtlZh0G0gBarCaFcMUOoqPxXryxdYxTRRv4kH6B9TFCVIrjRXG+emcxIk2ayZilog==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-validator-identifier": "^7.24.5", + "@babel/helper-validator-identifier": "^7.24.7", "@eslint-community/eslint-utils": "^4.4.0", "ci-info": "^4.0.0", "clean-regexp": "^1.0.0", - "core-js-compat": "^3.37.0", - "esquery": "^1.5.0", - "globals": "^15.7.0", + "core-js-compat": "^3.38.1", + "esquery": "^1.6.0", + "globals": "^15.9.0", "indent-string": "^4.0.0", "is-builtin-module": "^3.2.1", "jsesc": "^3.0.2", @@ -8020,7 +8243,7 @@ "read-pkg-up": "^7.0.1", "regexp-tree": "^0.1.27", "regjsparser": "^0.10.0", - "semver": "^7.6.1", + "semver": "^7.6.3", "strip-indent": "^3.0.0" }, "engines": { @@ -8034,10 +8257,11 @@ } }, "node_modules/eslint-scope": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.1.0.tgz", - "integrity": "sha512-14dSvlhaVhKKsa9Fx1l8A17s7ah7Ef7wCakJ10LYk6+GYmP9yDti2oq2SEwcyndt6knfcZyhyxwY3i9yL78EQw==", + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.2.0.tgz", + "integrity": "sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" @@ -8054,6 +8278,7 @@ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", "dev": true, + "license": "Apache-2.0", "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, @@ -8061,33 +8286,12 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/eslint/node_modules/@types/estree": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", - "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", - "dev": true - }, - "node_modules/eslint/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/eslint/node_modules/eslint-visitor-keys": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", - "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", + "node_modules/eslint/node_modules/eslint-visitor-keys": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", + "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", "dev": true, + "license": "Apache-2.0", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, @@ -8100,6 +8304,7 @@ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", "dev": true, + "license": "ISC", "dependencies": { "is-glob": "^4.0.3" }, @@ -8107,21 +8312,16 @@ "node": ">=10.13.0" } }, - "node_modules/eslint/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, "node_modules/espree": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-10.2.0.tgz", - "integrity": "sha512-upbkBJbckcCNBDBDXEbuhjbP68n+scUd3k/U2EkyM9nw+I/jPiL4cLF/Al06CF96wRltFda16sxDFrxsI1v0/g==", + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.3.0.tgz", + "integrity": "sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "acorn": "^8.12.0", + "acorn": "^8.14.0", "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^4.1.0" + "eslint-visitor-keys": "^4.2.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -8131,10 +8331,11 @@ } }, "node_modules/espree/node_modules/eslint-visitor-keys": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.1.0.tgz", - "integrity": "sha512-Q7lok0mqMUSf5a/AdAZkA5a/gHcO6snwQClVNNvFKCAVlxXucdU8pKydU5ZVZjBx5xr37vGbFFWtLQYreLzrZg==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", + "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", "dev": true, + "license": "Apache-2.0", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, @@ -8147,6 +8348,7 @@ "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", "dev": true, + "license": "BSD-2-Clause", "bin": { "esparse": "bin/esparse.js", "esvalidate": "bin/esvalidate.js" @@ -8156,10 +8358,11 @@ } }, "node_modules/esquery": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", - "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "estraverse": "^5.1.0" }, @@ -8172,6 +8375,7 @@ "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "estraverse": "^5.2.0" }, @@ -8184,24 +8388,24 @@ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true, + "license": "BSD-2-Clause", "engines": { "node": ">=4.0" } }, "node_modules/estree-walker": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", - "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", "dev": true, - "dependencies": { - "@types/estree": "^1.0.0" - } + "license": "MIT" }, "node_modules/esutils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "dev": true, + "license": "BSD-2-Clause", "engines": { "node": ">=0.10.0" } @@ -8210,6 +8414,7 @@ "version": "1.8.1", "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -8218,6 +8423,7 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "license": "MIT", "engines": { "node": ">=6" } @@ -8225,20 +8431,23 @@ "node_modules/eventemitter2": { "version": "6.4.9", "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-6.4.9.tgz", - "integrity": "sha512-JEPTiaOt9f04oa6NOkc4aH+nVp5I3wEjpHbIPqfgCdD5v5bUzy7xQqwcVO2aDQgOWhI28da57HksMrzK9HlRxg==" + "integrity": "sha512-JEPTiaOt9f04oa6NOkc4aH+nVp5I3wEjpHbIPqfgCdD5v5bUzy7xQqwcVO2aDQgOWhI28da57HksMrzK9HlRxg==", + "license": "MIT" }, "node_modules/events": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "license": "MIT", "engines": { "node": ">=0.8.x" } }, "node_modules/exiftool-vendored": { - "version": "28.6.0", - "resolved": "https://registry.npmjs.org/exiftool-vendored/-/exiftool-vendored-28.6.0.tgz", - "integrity": "sha512-Cx8/8ov1tKEacHhsi7FNYdisIhKq/SeQfprYSpYzwBuJwkPmCV8w7tTIvUJRQX9rvopXhBA4eBf1FPXqTZW5vA==", + "version": "28.8.0", + "resolved": "https://registry.npmjs.org/exiftool-vendored/-/exiftool-vendored-28.8.0.tgz", + "integrity": "sha512-R7tirJLr9fWuH9JS/KFFLB+O7jNGKuPXGxREc6YybYangEudGb+X8ERsYXk9AifMiAWh/2agNfbgkbcQcF+MxA==", + "license": "MIT", "dependencies": { "@photostructure/tz-lookup": "^11.0.0", "@types/luxon": "^3.4.2", @@ -8247,32 +8456,45 @@ "luxon": "^3.5.0" }, "optionalDependencies": { - "exiftool-vendored.exe": "12.97.0", - "exiftool-vendored.pl": "12.97.0" + "exiftool-vendored.exe": "13.0.0", + "exiftool-vendored.pl": "13.0.1" } }, "node_modules/exiftool-vendored.exe": { - "version": "12.97.0", - "resolved": "https://registry.npmjs.org/exiftool-vendored.exe/-/exiftool-vendored.exe-12.97.0.tgz", - "integrity": "sha512-+HxyFigEJOtwRjP7PhEslhZKuVW2V0hvmHPHtbVtNKGfAUGcfc95xNTjASQfKJvc+9ZuvzdEBPkEQmyA/ZYdIw==", + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/exiftool-vendored.exe/-/exiftool-vendored.exe-13.0.0.tgz", + "integrity": "sha512-4zAMuFGgxZkOoyQIzZMHv1HlvgyJK3AkNqjAgm8A8V0UmOZO7yv3pH49cDV1OduzFJqgs6yQ6eG4OGydhKtxlg==", + "license": "MIT", "optional": true, "os": [ "win32" ] }, "node_modules/exiftool-vendored.pl": { - "version": "12.97.0", - "resolved": "https://registry.npmjs.org/exiftool-vendored.pl/-/exiftool-vendored.pl-12.97.0.tgz", - "integrity": "sha512-mXe9JEH3csfyPWcC7+H6IpfaokDMMr4S45n7MtiobGPdeeh+kFnf1SQ9cxg4sF403P6IKVeYYPbzgKMlpro9eQ==", + "version": "13.0.1", + "resolved": "https://registry.npmjs.org/exiftool-vendored.pl/-/exiftool-vendored.pl-13.0.1.tgz", + "integrity": "sha512-+BRRzjselpWudKR0ltAW5SUt9T82D+gzQN8DdOQUgnSVWWp7oLCeTGBRptbQz+436Ihn/mPzmo/xnf0cv/Qw1A==", + "license": "MIT", "optional": true, "os": [ "!win32" ] }, + "node_modules/expect-type": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.1.0.tgz", + "integrity": "sha512-bFi65yM+xZgk+u/KRIpekdSYkTB5W1pEf0Lt8Q8Msh7b+eQ7LXVtIB1Bkm4fvclDEL1b2CZkMhv2mOeF8tMdkA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/express": { - "version": "4.21.1", - "resolved": "https://registry.npmjs.org/express/-/express-4.21.1.tgz", - "integrity": "sha512-YSFlK1Ee0/GC8QaO91tHcDxJiE/X4FbpAyQWkxAvG6AXCuR65YzK8ua6D9hvi/TzUfZMpc+BwuM1IPw8fmQBiQ==", + "version": "4.21.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz", + "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==", + "license": "MIT", "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", @@ -8293,7 +8515,7 @@ "methods": "~1.1.2", "on-finished": "2.4.1", "parseurl": "~1.3.3", - "path-to-regexp": "0.1.10", + "path-to-regexp": "0.1.12", "proxy-addr": "~2.0.7", "qs": "6.13.0", "range-parser": "~1.2.1", @@ -8308,12 +8530,17 @@ }, "engines": { "node": ">= 0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/express/node_modules/cookie": { "version": "0.7.1", "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -8322,6 +8549,7 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", "dependencies": { "ms": "2.0.0" } @@ -8329,22 +8557,26 @@ "node_modules/express/node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" }, "node_modules/express/node_modules/path-to-regexp": { - "version": "0.1.10", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.10.tgz", - "integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==" + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", + "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", + "license": "MIT" }, "node_modules/extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "license": "MIT" }, "node_modules/external-editor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", + "license": "MIT", "dependencies": { "chardet": "^0.7.0", "iconv-lite": "^0.4.24", @@ -8358,23 +8590,27 @@ "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/fast-diff": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", - "dev": true + "dev": true, + "license": "Apache-2.0" }, "node_modules/fast-fifo": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz", - "integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==" + "integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==", + "license": "MIT" }, "node_modules/fast-glob": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "license": "MIT", "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", @@ -8390,23 +8626,34 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/fast-levenshtein": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/fast-safe-stringify": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", - "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==" + "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==", + "license": "MIT" + }, + "node_modules/fast-uri": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.3.tgz", + "integrity": "sha512-aLrHthzCjH5He4Z2H9YZ+v6Ujb9ocRuW6ZzkJQOrTxleEijANq4v1TsaPaVG1PZcuurEzrLcWRyYBYXD5cEiaw==", + "dev": true, + "license": "BSD-3-Clause" }, "node_modules/fastq": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", - "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "license": "ISC", "dependencies": { "reusify": "^1.0.4" } @@ -8415,6 +8662,7 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "license": "MIT", "dependencies": { "escape-string-regexp": "^1.0.5" }, @@ -8429,6 +8677,7 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "license": "MIT", "engines": { "node": ">=0.8.0" } @@ -8438,6 +8687,7 @@ "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", "dev": true, + "license": "MIT", "dependencies": { "flat-cache": "^4.0.0" }, @@ -8449,6 +8699,7 @@ "version": "0.6.1", "resolved": "https://registry.npmjs.org/file-source/-/file-source-0.6.1.tgz", "integrity": "sha512-1R1KneL7eTXmXfKxC10V/9NeGOdbsAXJ+lQ//fvvcHUgtaZcZDWNJNblxAoVOyV1cj45pOtUrR3vZTBwqcW8XA==", + "license": "BSD-3-Clause", "dependencies": { "stream-source": "0.3" } @@ -8457,6 +8708,7 @@ "version": "7.1.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "license": "MIT", "dependencies": { "to-regex-range": "^5.0.1" }, @@ -8468,6 +8720,7 @@ "version": "1.3.1", "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", + "license": "MIT", "dependencies": { "debug": "2.6.9", "encodeurl": "~2.0.0", @@ -8485,6 +8738,7 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", "dependencies": { "ms": "2.0.0" } @@ -8492,13 +8746,15 @@ "node_modules/finalhandler/node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" }, "node_modules/find-up": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "dev": true, + "license": "MIT", "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" @@ -8515,6 +8771,7 @@ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", "dev": true, + "license": "MIT", "dependencies": { "flatted": "^3.2.9", "keyv": "^4.5.4" @@ -8524,15 +8781,17 @@ } }, "node_modules/flatted": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", - "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", - "dev": true + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.2.tgz", + "integrity": "sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA==", + "dev": true, + "license": "ISC" }, "node_modules/fluent-ffmpeg": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/fluent-ffmpeg/-/fluent-ffmpeg-2.1.3.tgz", "integrity": "sha512-Be3narBNt2s6bsaqP6Jzq91heDgOEaDCJAXcE3qcma/EJBSy5FB4cvO31XBInuAuKBx8Kptf8dkhjK0IOru39Q==", + "license": "MIT", "dependencies": { "async": "^0.2.9", "which": "^1.1.1" @@ -8550,6 +8809,7 @@ "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "license": "ISC", "dependencies": { "isexe": "^2.0.0" }, @@ -8558,9 +8818,10 @@ } }, "node_modules/foreground-child": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", - "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", + "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==", + "license": "ISC", "dependencies": { "cross-spawn": "^7.0.0", "signal-exit": "^4.0.1" @@ -8577,6 +8838,7 @@ "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-9.0.2.tgz", "integrity": "sha512-Uochze2R8peoN1XqlSi/rGUkDQpRogtLFocP9+PGu68zk1BDAKXfdeCdyVZpgTk8V8WFVQXdEz426VKjXLO1Gg==", "dev": true, + "license": "MIT", "dependencies": { "@babel/code-frame": "^7.16.7", "chalk": "^4.1.2", @@ -8600,10 +8862,26 @@ "webpack": "^5.11.0" } }, + "node_modules/form-data": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz", + "integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==", + "dev": true, + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/forwarded": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -8611,12 +8889,14 @@ "node_modules/forwarded-parse": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/forwarded-parse/-/forwarded-parse-2.1.2.tgz", - "integrity": "sha512-alTFZZQDKMporBH77856pXgzhEzaUVmLCDk+egLgIgHst3Tpndzz8MnKe+GzRJRfvVdn69HhpW7cmXzvtLvJAw==" + "integrity": "sha512-alTFZZQDKMporBH77856pXgzhEzaUVmLCDk+egLgIgHst3Tpndzz8MnKe+GzRJRfvVdn69HhpW7cmXzvtLvJAw==", + "license": "MIT" }, "node_modules/fresh": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -8625,13 +8905,15 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/fs-extra": { "version": "10.1.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", "dev": true, + "license": "MIT", "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", @@ -8645,6 +8927,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "license": "ISC", "dependencies": { "minipass": "^3.0.0" }, @@ -8656,6 +8939,7 @@ "version": "3.3.6", "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "license": "ISC", "dependencies": { "yallist": "^4.0.0" }, @@ -8663,27 +8947,25 @@ "node": ">=8" } }, - "node_modules/fs-minipass/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, "node_modules/fs-monkey": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.5.tgz", - "integrity": "sha512-8uMbBjrhzW76TYgEV27Y5E//W2f/lTFmx78P2w19FZSxarhI/798APGQyuGCwmkNxgwGRhrLfvWyLBvNtuOmew==", - "dev": true + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.6.tgz", + "integrity": "sha512-b1FMfwetIKymC0eioW7mTywihSQE4oLzQn1dB6rZB5fx/3NpNEdAWeCSMB+60/AeT0TCXsxzAlcYVEFCTAksWg==", + "dev": true, + "license": "Unlicense" }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "license": "ISC" }, "node_modules/fsevents": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", "hasInstallScript": true, + "license": "MIT", "optional": true, "os": [ "darwin" @@ -8696,6 +8978,7 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -8704,6 +8987,8 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", + "deprecated": "This package is no longer supported.", + "license": "ISC", "dependencies": { "aproba": "^1.0.3 || ^2.0.0", "color-support": "^1.1.2", @@ -8722,49 +9007,65 @@ "node_modules/gauge/node_modules/signal-exit": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "license": "ISC" }, "node_modules/gaxios": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-6.2.0.tgz", - "integrity": "sha512-H6+bHeoEAU5D6XNc6mPKeN5dLZqEDs9Gpk6I+SZBEzK5So58JVrHPmevNi35fRl1J9Y5TaeLW0kYx3pCJ1U2mQ==", + "version": "6.7.1", + "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-6.7.1.tgz", + "integrity": "sha512-LDODD4TMYx7XXdpwxAVRAIAuB0bzv0s+ywFonY46k126qzQHT9ygyoa9tncmOiQmmDrik65UYsEkv3lbfqQ3yQ==", + "license": "Apache-2.0", "dependencies": { "extend": "^3.0.2", "https-proxy-agent": "^7.0.1", "is-stream": "^2.0.0", - "node-fetch": "^2.6.9" + "node-fetch": "^2.6.9", + "uuid": "^9.0.1" }, "engines": { "node": ">=14" } }, "node_modules/gaxios/node_modules/agent-base": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.0.tgz", - "integrity": "sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg==", - "dependencies": { - "debug": "^4.3.4" - }, + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.3.tgz", + "integrity": "sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==", + "license": "MIT", "engines": { "node": ">= 14" } }, "node_modules/gaxios/node_modules/https-proxy-agent": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.4.tgz", - "integrity": "sha512-wlwpilI7YdjSkWaQ/7omYBMTliDcmCN8OLihO6I9B86g06lMyAoqgoDpV0XqoaPOKj+0DIdAvnsWfyAAhmimcg==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", + "license": "MIT", "dependencies": { - "agent-base": "^7.0.2", + "agent-base": "^7.1.2", "debug": "4" }, "engines": { "node": ">= 14" } }, + "node_modules/gaxios/node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, "node_modules/gcp-metadata": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-6.1.0.tgz", "integrity": "sha512-Jh/AIwwgaxan+7ZUUmRLCjtchyDiqh4KjBJ5tW3plBZb5iL/BPcso8A5DlzeD9qlw0duCamnNdpFjxwaT0KyKg==", + "license": "Apache-2.0", "dependencies": { "gaxios": "^6.0.0", "json-bigint": "^1.0.0" @@ -8777,6 +9078,7 @@ "version": "1.0.0-beta.2", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "license": "MIT", "engines": { "node": ">=6.9.0" } @@ -8785,6 +9087,7 @@ "version": "8.1.2", "resolved": "https://registry.npmjs.org/geo-tz/-/geo-tz-8.1.2.tgz", "integrity": "sha512-S1udoP7MZ+CVu+7Iy/VayVNmEHTWgfJ52TjpfC2/4f+j0SB/ZXMjGrwZTqPMo6/O2m5lrGLCFCY0bkxUqiLN+g==", + "license": "MIT", "dependencies": { "@turf/boolean-point-in-polygon": "^7.1.0", "@turf/helpers": "^7.1.0", @@ -8802,6 +9105,7 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/geobuf/-/geobuf-3.0.2.tgz", "integrity": "sha512-ASgKwEAQQRnyNFHNvpd5uAwstbVYmiTW0Caw3fBb509tNTqXyAAPMyFs5NNihsLZhLxU1j/kjFhkhLWA9djuVg==", + "license": "ISC", "dependencies": { "concat-stream": "^2.0.0", "pbf": "^3.2.1", @@ -8817,20 +9121,27 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "license": "ISC", "engines": { "node": "6.* || 8.* || >= 10.*" } }, "node_modules/get-intrinsic": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", - "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.6.tgz", + "integrity": "sha512-qxsEs+9A+u85HhllWJJFicJfPDhRmjzoYdl64aMWW9yRIJmSyxdn8IEkuIM530/7T+lv0TIHd8L6Q/ra0tEoeA==", + "license": "MIT", "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "dunder-proto": "^1.0.0", + "es-define-property": "^1.0.1", "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", "function-bind": "^1.1.2", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "hasown": "^2.0.0" + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.0.0" }, "engines": { "node": ">= 0.4" @@ -8844,6 +9155,7 @@ "resolved": "https://registry.npmjs.org/get-port/-/get-port-5.1.1.tgz", "integrity": "sha512-g/Q1aTSDOxFpchXC4i8ZWvxA1lnPqx/JHqcpIw0/LX9T8x/GBbi6YnlN5nhaKIFkT8oFsscUKgDJYxfwfS6QsQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" }, @@ -8856,6 +9168,7 @@ "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-8.0.0.tgz", "integrity": "sha512-sY22aA6xchAzprjyqmSEQv4UbAAzRN0L2dQB0NlN5acTTK9Don6nhoc3eAbUnpZiCANAMfd/+40kVdKfFygohg==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -8864,9 +9177,10 @@ } }, "node_modules/glob": { - "version": "10.4.2", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.2.tgz", - "integrity": "sha512-GwMlUF6PkPo3Gk21UxkCohOv0PLcIXVtKyLlpEI28R/cO/4eNOdmLk3CMW1wROV/WR/EsZOWAfBbBOqYvs88/w==", + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "license": "ISC", "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", @@ -8878,9 +9192,6 @@ "bin": { "glob": "dist/esm/bin.mjs" }, - "engines": { - "node": ">=16 || 14 >=14.18" - }, "funding": { "url": "https://github.com/sponsors/isaacs" } @@ -8889,6 +9200,7 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "license": "ISC", "dependencies": { "is-glob": "^4.0.1" }, @@ -8900,37 +9212,23 @@ "version": "0.4.1", "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", - "dev": true + "dev": true, + "license": "BSD-2-Clause" }, "node_modules/glob/node_modules/brace-expansion": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" } }, - "node_modules/glob/node_modules/jackspeak": { - "version": "3.4.2", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.2.tgz", - "integrity": "sha512-qH3nOSj8q/8+Eg8LUPOq3C+6HWkpUioIjDsq1+D4zY91oZvpPttw8GwtF1nReRYKXl+1AORyFqtm2f5Q1SB6/Q==", - "dependencies": { - "@isaacs/cliui": "^8.0.2" - }, - "engines": { - "node": "14 >=14.21 || 16 >=16.20 || >=18" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - }, - "optionalDependencies": { - "@pkgjs/parseargs": "^0.11.0" - } - }, "node_modules/glob/node_modules/minimatch": { - "version": "9.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", - "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" }, @@ -8942,10 +9240,11 @@ } }, "node_modules/globals": { - "version": "15.11.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-15.11.0.tgz", - "integrity": "sha512-yeyNSjdbyVaWurlwCpcA6XNBrHTMIeDdj0/hnvX/OLJ9ekOXYbLsLinH/MucQyGvNnXhidTdNhTtJaffL2sMfw==", + "version": "15.13.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-15.13.0.tgz", + "integrity": "sha512-49TewVEz0UxZjr1WYYsWpPrhyC/B/pA8Bq0fUmet2n+eR7yn0IvNzNaoBwnK6mdkzcN+se7Ez9zUgULTz2QH4g==", "dev": true, + "license": "MIT", "engines": { "node": ">=18" }, @@ -8957,14 +9256,16 @@ "version": "0.1.2", "resolved": "https://registry.npmjs.org/globrex/-/globrex-0.1.2.tgz", "integrity": "sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/gopd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", - "dependencies": { - "get-intrinsic": "^1.1.3" + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -8973,18 +9274,21 @@ "node_modules/graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "license": "ISC" }, "node_modules/graphemer": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/handlebars": { "version": "4.7.8", "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==", + "license": "MIT", "dependencies": { "minimist": "^1.2.5", "neo-async": "^2.6.2", @@ -9005,25 +9309,16 @@ "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" } }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dependencies": { - "function-bind": "^1.1.1" - }, - "engines": { - "node": ">= 0.4.0" - } - }, "node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "license": "MIT", "engines": { "node": ">=8" } @@ -9033,36 +9328,29 @@ "resolved": "https://registry.npmjs.org/has-own-prop/-/has-own-prop-2.0.0.tgz", "integrity": "sha512-Pq0h+hvsVm6dDEa8x82GnLSYHOzNDt7f0ddFa3FqcQlgzEiptPqL+XrOJNavjOzSYiYWIrgeVYYgGlLmnxwilQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/has-property-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz", - "integrity": "sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dev": true, + "license": "MIT", "dependencies": { - "get-intrinsic": "^1.2.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", - "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", - "engines": { - "node": ">= 0.4" + "es-define-property": "^1.0.0" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -9073,12 +9361,14 @@ "node_modules/has-unicode": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", + "license": "ISC" }, "node_modules/hasown": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.1.tgz", - "integrity": "sha512-1/th4MHjnwncwXsIW6QMzlvYL9kG5e/CpVvLRZe4XPa8TOUNbCELqmvhDmnkNsAjwaG4+I8gJJL0JBvTTLO9qA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", "dependencies": { "function-bind": "^1.1.2" }, @@ -9090,6 +9380,7 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "license": "MIT", "bin": { "he": "bin/he" } @@ -9098,6 +9389,7 @@ "version": "10.7.3", "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.3.tgz", "integrity": "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==", + "license": "BSD-3-Clause", "engines": { "node": "*" } @@ -9106,18 +9398,21 @@ "version": "2.8.9", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/html-escaper": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/html-to-text": { "version": "9.0.5", "resolved": "https://registry.npmjs.org/html-to-text/-/html-to-text-9.0.5.tgz", "integrity": "sha512-qY60FjREgVZL03vJU6IfMV4GDjGBIoOyvuFdpBDIX9yTlDw0TjxVBQp+P8NvpdIXNJvfWBTNul7fsAQJq2FNpg==", + "license": "MIT", "dependencies": { "@selderee/plugin-htmlparser2": "^0.11.0", "deepmerge": "^4.3.1", @@ -9140,6 +9435,7 @@ "url": "https://github.com/sponsors/fb55" } ], + "license": "MIT", "dependencies": { "domelementtype": "^2.3.0", "domhandler": "^5.0.3", @@ -9151,6 +9447,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "license": "MIT", "dependencies": { "depd": "2.0.0", "inherits": "2.0.4", @@ -9166,6 +9463,7 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "license": "MIT", "dependencies": { "agent-base": "6", "debug": "4" @@ -9175,9 +9473,10 @@ } }, "node_modules/i18n-iso-countries": { - "version": "7.12.0", - "resolved": "https://registry.npmjs.org/i18n-iso-countries/-/i18n-iso-countries-7.12.0.tgz", - "integrity": "sha512-NDFf5j/raA5JrcPT/NcHP3RUMH7TkdkxQKAKdvDlgb+MS296WJzzqvV0Y5uwavSm7A6oYvBeSV0AxoHdDiHIiw==", + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/i18n-iso-countries/-/i18n-iso-countries-7.13.0.tgz", + "integrity": "sha512-pVh4CjdgAHZswI98hzG+1BItQlsQfR+yGDsjDISoWIV/jHDAvCmSyZ5vj2YWwAjfVZ8/BhBDqWcFvuGOyHe4vg==", + "license": "MIT", "dependencies": { "diacritics": "1.3.0" }, @@ -9189,6 +9488,7 @@ "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "license": "MIT", "dependencies": { "safer-buffer": ">= 2.1.2 < 3" }, @@ -9213,13 +9513,15 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "BSD-3-Clause" }, "node_modules/ignore": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", - "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", "dev": true, + "license": "MIT", "engines": { "node": ">= 4" } @@ -9228,6 +9530,7 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "license": "MIT", "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" @@ -9240,9 +9543,10 @@ } }, "node_modules/import-in-the-middle": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.11.0.tgz", - "integrity": "sha512-5DimNQGoe0pLUHbR9qK84iWaWjjbsxiqXnw6Qz64+azRgleqv9k2kTt5fw7QsOpmaGYtuxxursnPPsnTKEx10Q==", + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.12.0.tgz", + "integrity": "sha512-yAgSE7GmtRcu4ZUSFX/4v69UGXwugFFSdIQJ14LHPOPPQrWv8Y7O9PHsw8Ovk7bKCLe4sjXMbZFqGFcLHpZ89w==", + "license": "Apache-2.0", "dependencies": { "acorn": "^8.8.2", "acorn-import-attributes": "^1.9.5", @@ -9255,6 +9559,7 @@ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.8.19" } @@ -9264,6 +9569,7 @@ "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -9272,6 +9578,8 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "license": "ISC", "dependencies": { "once": "^1.3.0", "wrappy": "1" @@ -9280,17 +9588,14 @@ "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "node_modules/ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" }, "node_modules/inquirer": { "version": "8.2.6", "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.6.tgz", "integrity": "sha512-M1WuAmb7pn9zdFRtQYk26ZBoY043Sse0wVDdk4Bppr+JOXyQYybdtvK+l9wUibhtjdjvtoiNy8tk+EgsYIUqKg==", + "license": "MIT", "dependencies": { "ansi-escapes": "^4.2.1", "chalk": "^4.1.1", @@ -9316,6 +9621,7 @@ "version": "5.4.1", "resolved": "https://registry.npmjs.org/ioredis/-/ioredis-5.4.1.tgz", "integrity": "sha512-2YZsvl7jopIa1gaePkeMtd9rAcSjOOjPtpcLlOeusyO+XH2SK5ZcT+UCrElPP+WVIInh2TzeI4XW9ENaSLVVHA==", + "license": "MIT", "dependencies": { "@ioredis/commands": "^1.1.1", "cluster-key-slot": "^1.1.0", @@ -9339,6 +9645,7 @@ "version": "1.9.1", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "license": "MIT", "engines": { "node": ">= 0.10" } @@ -9346,12 +9653,14 @@ "node_modules/is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==" + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "license": "MIT" }, "node_modules/is-binary-path": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "license": "MIT", "dependencies": { "binary-extensions": "^2.0.0" }, @@ -9364,6 +9673,7 @@ "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-3.2.1.tgz", "integrity": "sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==", "dev": true, + "license": "MIT", "dependencies": { "builtin-modules": "^3.3.0" }, @@ -9375,11 +9685,15 @@ } }, "node_modules/is-core-module": { - "version": "2.13.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.0.tgz", - "integrity": "sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==", + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.0.tgz", + "integrity": "sha512-urTSINYfAYgcbLb0yDQ6egFm6h3Mo1DcF9EkyXSRjjzdHbsulg01qhwWuXdOoUBuTkbQ80KDboXa0vFJ+BDH+g==", + "license": "MIT", "dependencies": { - "has": "^1.0.3" + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -9389,6 +9703,7 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -9397,6 +9712,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", "engines": { "node": ">=8" } @@ -9405,6 +9721,7 @@ "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "license": "MIT", "dependencies": { "is-extglob": "^2.1.1" }, @@ -9416,6 +9733,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", + "license": "MIT", "engines": { "node": ">=8" } @@ -9424,6 +9742,7 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "license": "MIT", "engines": { "node": ">=0.12.0" } @@ -9432,6 +9751,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "license": "MIT", "engines": { "node": ">=8" }, @@ -9443,6 +9763,7 @@ "version": "0.1.0", "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "license": "MIT", "engines": { "node": ">=10" }, @@ -9453,18 +9774,21 @@ "node_modules/isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "license": "MIT" }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "license": "ISC" }, "node_modules/istanbul-lib-coverage": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", "dev": true, + "license": "BSD-3-Clause", "engines": { "node": ">=8" } @@ -9474,6 +9798,7 @@ "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "istanbul-lib-coverage": "^3.0.0", "make-dir": "^4.0.0", @@ -9488,6 +9813,7 @@ "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", "dev": true, + "license": "MIT", "dependencies": { "semver": "^7.5.3" }, @@ -9503,6 +9829,7 @@ "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-5.0.6.tgz", "integrity": "sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "@jridgewell/trace-mapping": "^0.3.23", "debug": "^4.1.1", @@ -9517,6 +9844,7 @@ "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz", "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "html-escaper": "^2.0.0", "istanbul-lib-report": "^3.0.0" @@ -9529,20 +9857,19 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/iterare/-/iterare-1.2.1.tgz", "integrity": "sha512-RKYVTCjAnRthyJes037NX/IiqeidgN1xc3j1RjFfECFp28A1GVwK9nA+i0rJPaHqSZwygLzRnFlzUuHFoWWy+Q==", + "license": "ISC", "engines": { "node": ">=6" } }, "node_modules/jackspeak": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", - "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "license": "BlueOak-1.0.0", "dependencies": { "@isaacs/cliui": "^8.0.2" }, - "engines": { - "node": ">=14" - }, "funding": { "url": "https://github.com/sponsors/isaacs" }, @@ -9550,94 +9877,80 @@ "@pkgjs/parseargs": "^0.11.0" } }, - "node_modules/jiti": { - "version": "1.21.0", - "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.0.tgz", - "integrity": "sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==", - "peer": true, - "bin": { - "jiti": "bin/jiti.js" - } - }, - "node_modules/joi": { - "version": "17.13.3", - "resolved": "https://registry.npmjs.org/joi/-/joi-17.13.3.tgz", - "integrity": "sha512-otDA4ldcIx+ZXsKHWmp0YizCweVRZG96J10b0FevjfuncLO1oX59THoAmHkNubYJ+9gWsYsp5k8v4ib6oDv1fA==", + "node_modules/jest-worker": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "dev": true, + "license": "MIT", "dependencies": { - "@hapi/hoek": "^9.3.0", - "@hapi/topo": "^5.1.0", - "@sideway/address": "^4.1.5", - "@sideway/formula": "^3.0.1", - "@sideway/pinpoint": "^2.0.0" + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": ">= 10.13.0" } }, - "node_modules/jose": { - "version": "4.15.9", - "resolved": "https://registry.npmjs.org/jose/-/jose-4.15.9.tgz", - "integrity": "sha512-1vUQX+IdDMVPj4k8kOxgUqlcK518yluMuGZwqlr44FS1ppZB/5GWh4rZG89erpOBOJjU/OBsnCVFfapsRz6nEA==", - "funding": { - "url": "https://github.com/sponsors/panva" - } - }, - "node_modules/js-beautify": { - "version": "1.15.1", - "resolved": "https://registry.npmjs.org/js-beautify/-/js-beautify-1.15.1.tgz", - "integrity": "sha512-ESjNzSlt/sWE8sciZH8kBF8BPlwXPwhR6pWKAw8bw4Bwj+iZcnKW6ONWUutJ7eObuBZQpiIb8S7OYspWrKt7rA==", + "node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "license": "MIT", "dependencies": { - "config-chain": "^1.1.13", - "editorconfig": "^1.0.4", - "glob": "^10.3.3", - "js-cookie": "^3.0.5", - "nopt": "^7.2.0" - }, - "bin": { - "css-beautify": "js/bin/css-beautify.js", - "html-beautify": "js/bin/html-beautify.js", - "js-beautify": "js/bin/js-beautify.js" + "has-flag": "^4.0.0" }, "engines": { - "node": ">=14" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/js-beautify/node_modules/abbrev": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-2.0.0.tgz", - "integrity": "sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==", - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node_modules/jiti": { + "version": "1.21.6", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.6.tgz", + "integrity": "sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==", + "license": "MIT", + "peer": true, + "bin": { + "jiti": "bin/jiti.js" } }, - "node_modules/js-beautify/node_modules/nopt": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-7.2.0.tgz", - "integrity": "sha512-CVDtwCdhYIvnAzFoJ6NJ6dX3oga9/HyciQDnG1vQDjSLMeKLJ4A93ZqYKDrgYSr1FBY5/hMYC+2VCi24pgpkGA==", + "node_modules/joi": { + "version": "17.13.3", + "resolved": "https://registry.npmjs.org/joi/-/joi-17.13.3.tgz", + "integrity": "sha512-otDA4ldcIx+ZXsKHWmp0YizCweVRZG96J10b0FevjfuncLO1oX59THoAmHkNubYJ+9gWsYsp5k8v4ib6oDv1fA==", + "license": "BSD-3-Clause", "dependencies": { - "abbrev": "^2.0.0" - }, - "bin": { - "nopt": "bin/nopt.js" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "@hapi/hoek": "^9.3.0", + "@hapi/topo": "^5.1.0", + "@sideway/address": "^4.1.5", + "@sideway/formula": "^3.0.1", + "@sideway/pinpoint": "^2.0.0" } }, - "node_modules/js-cookie": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.5.tgz", - "integrity": "sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==", - "engines": { - "node": ">=14" + "node_modules/jose": { + "version": "4.15.9", + "resolved": "https://registry.npmjs.org/jose/-/jose-4.15.9.tgz", + "integrity": "sha512-1vUQX+IdDMVPj4k8kOxgUqlcK518yluMuGZwqlr44FS1ppZB/5GWh4rZG89erpOBOJjU/OBsnCVFfapsRz6nEA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/panva" } }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "license": "MIT" }, "node_modules/js-yaml": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "license": "MIT", "dependencies": { "argparse": "^2.0.1" }, @@ -9646,10 +9959,10 @@ } }, "node_modules/jsesc": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz", - "integrity": "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==", - "dev": true, + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "license": "MIT", "bin": { "jsesc": "bin/jsesc" }, @@ -9661,6 +9974,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz", "integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==", + "license": "MIT", "dependencies": { "bignumber.js": "^9.0.0" } @@ -9669,29 +9983,34 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/json-parse-even-better-errors": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "license": "MIT" }, "node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" }, "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/json5": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "license": "MIT", "bin": { "json5": "lib/cli.js" }, @@ -9703,13 +10022,15 @@ "version": "3.2.1", "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.1.tgz", "integrity": "sha512-AilxAyFOAcK5wA1+LeaySVBrHsGQvUFCDWXKpZjzaL0PqW+xfBOttn8GNtWKFWqneyMZj41MWF9Kl6iPWLwgOA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/jsonfile": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", "dev": true, + "license": "MIT", "dependencies": { "universalify": "^2.0.0" }, @@ -9722,6 +10043,7 @@ "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", "dev": true, + "license": "MIT", "dependencies": { "json-buffer": "3.0.1" } @@ -9730,6 +10052,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.1.tgz", "integrity": "sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==", + "license": "MIT", "dependencies": { "readable-stream": "^2.0.5" }, @@ -9741,6 +10064,7 @@ "version": "2.3.8", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "license": "MIT", "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", @@ -9754,12 +10078,14 @@ "node_modules/lazystream/node_modules/safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "license": "MIT" }, "node_modules/lazystream/node_modules/string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "license": "MIT", "dependencies": { "safe-buffer": "~5.1.0" } @@ -9768,6 +10094,7 @@ "version": "0.6.0", "resolved": "https://registry.npmjs.org/leac/-/leac-0.6.0.tgz", "integrity": "sha512-y+SqErxb8h7nE/fiEX07jsbuhrpO9lL8eca7/Y1nuWV2moNlXhyd59iDGcRf6moVyDMbmTNzL40SUyrFU/yDpg==", + "license": "MIT", "funding": { "url": "https://ko-fi.com/killymxi" } @@ -9777,6 +10104,7 @@ "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", "dev": true, + "license": "MIT", "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" @@ -9786,29 +10114,36 @@ } }, "node_modules/libphonenumber-js": { - "version": "1.10.53", - "resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.10.53.tgz", - "integrity": "sha512-sDTnnqlWK4vH4AlDQuswz3n4Hx7bIQWTpIcScJX+Sp7St3LXHmfiax/ZFfyYxHmkdCvydOLSuvtAO/XpXiSySw==" + "version": "1.11.17", + "resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.11.17.tgz", + "integrity": "sha512-Jr6v8thd5qRlOlc6CslSTzGzzQW03uiscab7KHQZX1Dfo4R6n6FDhZ0Hri6/X7edLIDv9gl4VMZXhxTjLnl0VQ==", + "license": "MIT" }, "node_modules/lilconfig": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", - "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz", + "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==", + "license": "MIT", "peer": true, "engines": { - "node": ">=10" + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antonk52" } }, "node_modules/lines-and-columns": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "license": "MIT" }, "node_modules/load-tsconfig": { "version": "0.2.5", "resolved": "https://registry.npmjs.org/load-tsconfig/-/load-tsconfig-0.2.5.tgz", "integrity": "sha512-IXO6OCs9yg8tMKzfPZ1YmheJbZCiEsnBdcB03l0OcfK9prKnJb96siuHCr5Fl37/yo9DnKU+TLpxzTUspw9shg==", "dev": true, + "license": "MIT", "engines": { "node": "^12.20.0 || ^14.13.1 || >=16.0.0" } @@ -9818,6 +10153,7 @@ "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.11.5" } @@ -9827,6 +10163,7 @@ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dev": true, + "license": "MIT", "dependencies": { "p-locate": "^5.0.0" }, @@ -9840,33 +10177,39 @@ "node_modules/lodash": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "license": "MIT" }, "node_modules/lodash.camelcase": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", - "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==" + "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", + "license": "MIT" }, "node_modules/lodash.defaults": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", - "integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==" + "integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==", + "license": "MIT" }, "node_modules/lodash.isarguments": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", - "integrity": "sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg==" + "integrity": "sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg==", + "license": "MIT" }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/log-symbols": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "license": "MIT", "dependencies": { "chalk": "^4.1.0", "is-unicode-supported": "^0.1.0" @@ -9881,37 +10224,33 @@ "node_modules/long": { "version": "5.2.3", "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz", - "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==" - }, - "node_modules/loose-envify": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", - "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "dependencies": { - "js-tokens": "^3.0.0 || ^4.0.0" - }, - "bin": { - "loose-envify": "cli.js" - } + "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==", + "license": "Apache-2.0" }, "node_modules/loupe": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.1.2.tgz", "integrity": "sha512-23I4pFZHmAemUnz8WZXbYRSKYj801VDaNv9ETuMh7IrMc7VuVVSo+Z9iLE3ni30+U48iDWfi30d3twAXBYmnCg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "license": "ISC", "dependencies": { - "yallist": "^3.0.2" + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" } }, "node_modules/luxon": { "version": "3.5.0", "resolved": "https://registry.npmjs.org/luxon/-/luxon-3.5.0.tgz", "integrity": "sha512-rh+Zjr6DNfUYR3bPwJEnuwDdqMbxZW7LOQfUN4B54+Cl+0o5zaU9RJ6bcidfDtC1cWCZXQ+nvX8bf6bAji37QQ==", + "license": "MIT", "engines": { "node": ">=12" } @@ -9921,6 +10260,7 @@ "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.8.tgz", "integrity": "sha512-ISQTe55T2ao7XtlAStud6qwYPZjE4GK1S/BeVPus4jrq6JuOnQ00YKQC581RWhR122W7msZV263KzVeLoqidyQ==", "dev": true, + "license": "MIT", "dependencies": { "@jridgewell/sourcemap-codec": "^1.4.15" }, @@ -9929,13 +10269,14 @@ } }, "node_modules/magicast": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/magicast/-/magicast-0.3.4.tgz", - "integrity": "sha512-TyDF/Pn36bBji9rWKHlZe+PZb6Mx5V8IHCSxk7X4aljM4e/vyDvZZYwHewdVaqiA0nb3ghfHU/6AUpDxWoER2Q==", + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/magicast/-/magicast-0.3.5.tgz", + "integrity": "sha512-L0WhttDl+2BOsybvEOLK7fW3UA0OQ0IQ2d6Zl2x/a6vVRs3bAY0ECOSHHeL5jD+SbOpOCUEi0y1DgHEn9Qn1AQ==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/parser": "^7.24.4", - "@babel/types": "^7.24.0", + "@babel/parser": "^7.25.4", + "@babel/types": "^7.25.4", "source-map-js": "^1.2.0" } }, @@ -9943,6 +10284,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "license": "MIT", "dependencies": { "semver": "^6.0.0" }, @@ -9957,21 +10299,16 @@ "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "license": "ISC", "bin": { "semver": "bin/semver.js" } }, - "node_modules/make-error": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", - "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "optional": true, - "peer": true - }, "node_modules/marked": { "version": "7.0.4", "resolved": "https://registry.npmjs.org/marked/-/marked-7.0.4.tgz", "integrity": "sha512-t8eP0dXRJMtMvBojtkcsA7n48BkauktUKzfkPSCq85ZMTJ0v76Rke4DYz01omYpPTUh4p/f7HePgRo3ebG8+QQ==", + "license": "MIT", "bin": { "marked": "bin/marked.js" }, @@ -9979,21 +10316,32 @@ "node": ">= 16" } }, + "node_modules/math-intrinsics": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.0.0.tgz", + "integrity": "sha512-4MqMiKP90ybymYvsut0CH2g4XWbfLtmlCkXmtmdcDCxNB+mQcu1w/1+L/VD7vi/PSv7X2JYV7SCcR+jiPXnQtA==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/md-to-react-email": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/md-to-react-email/-/md-to-react-email-5.0.2.tgz", - "integrity": "sha512-x6kkpdzIzUhecda/yahltfEl53mH26QdWu4abUF9+S0Jgam8P//Ciro8cdhyMHnT5MQUJYrIbO6ORM2UxPiNNA==", + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/md-to-react-email/-/md-to-react-email-5.0.5.tgz", + "integrity": "sha512-OvAXqwq57uOk+WZqFFNCMZz8yDp8BD3WazW1wAKHUrPbbdr89K9DWS6JXY09vd9xNdPNeurI8DU/X4flcfaD8A==", + "license": "MIT", "dependencies": { "marked": "7.0.4" }, "peerDependencies": { - "react": "18.x" + "react": "^18.0 || ^19.0" } }, "node_modules/media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -10003,6 +10351,7 @@ "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.5.3.tgz", "integrity": "sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==", "dev": true, + "license": "Unlicense", "dependencies": { "fs-monkey": "^1.0.4" }, @@ -10014,6 +10363,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", + "license": "MIT", "funding": { "url": "https://github.com/sponsors/sindresorhus" } @@ -10022,12 +10372,14 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "license": "MIT", "engines": { "node": ">= 8" } @@ -10036,6 +10388,7 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -10044,6 +10397,7 @@ "version": "4.0.8", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "license": "MIT", "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" @@ -10056,6 +10410,7 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "license": "MIT", "engines": { "node": ">=8.6" }, @@ -10067,6 +10422,7 @@ "version": "1.6.0", "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "license": "MIT", "bin": { "mime": "cli.js" }, @@ -10078,6 +10434,7 @@ "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -10086,6 +10443,7 @@ "version": "2.1.35", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", "dependencies": { "mime-db": "1.52.0" }, @@ -10097,6 +10455,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "license": "MIT", "engines": { "node": ">=6" } @@ -10106,6 +10465,7 @@ "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } @@ -10114,6 +10474,7 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" }, @@ -10125,6 +10486,7 @@ "version": "1.2.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -10133,6 +10495,7 @@ "version": "7.1.2", "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "license": "ISC", "engines": { "node": ">=16 || 14 >=14.17" } @@ -10141,6 +10504,7 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "license": "MIT", "dependencies": { "minipass": "^3.0.0", "yallist": "^4.0.0" @@ -10153,6 +10517,7 @@ "version": "3.3.6", "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "license": "ISC", "dependencies": { "yallist": "^4.0.0" }, @@ -10160,15 +10525,11 @@ "node": ">=8" } }, - "node_modules/minizlib/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, "node_modules/mkdirp": { "version": "0.5.6", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "license": "MIT", "dependencies": { "minimist": "^1.2.6" }, @@ -10180,13 +10541,15 @@ "version": "0.5.3", "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/mock-fs": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/mock-fs/-/mock-fs-5.4.0.tgz", - "integrity": "sha512-3ROPnEMgBOkusBMYQUW2rnT3wZwsgfOKzJDLvx/TZ7FL1WmWvwSwn3j4aDR5fLDGtgcc1WF0Z1y0di7c9L4FKw==", + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/mock-fs/-/mock-fs-5.4.1.tgz", + "integrity": "sha512-sz/Q8K1gXXXHR+qr0GZg2ysxCRr323kuN10O7CtQjraJsFDJ4SJ+0I5MzALz7aRp9lHk8Cc/YdsT95h9Ka1aFw==", "dev": true, + "license": "MIT", "engines": { "node": ">=12.0.0" } @@ -10194,18 +10557,21 @@ "node_modules/module-details-from-path": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/module-details-from-path/-/module-details-from-path-1.0.3.tgz", - "integrity": "sha512-ySViT69/76t8VhE1xXHK6Ch4NcDd26gx0MzKXLO+F7NOtnqH68d9zF94nT8ZWSxXh8ELOERsnJO/sWt1xZYw5A==" + "integrity": "sha512-ySViT69/76t8VhE1xXHK6Ch4NcDd26gx0MzKXLO+F7NOtnqH68d9zF94nT8ZWSxXh8ELOERsnJO/sWt1xZYw5A==", + "license": "MIT" }, "node_modules/moo": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/moo/-/moo-0.5.2.tgz", "integrity": "sha512-iSAJLHYKnX41mKcJKjqvnAN9sf0LMDTXDEvFv+ffuRR9a1MIuXLjMNL6EsnDHSkKLTWNqQQ5uo61P4EbU4NU+Q==", - "dev": true + "dev": true, + "license": "BSD-3-Clause" }, "node_modules/mrmime": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.0.tgz", "integrity": "sha512-eu38+hdgojoyq63s+yTpN4XMBdt5l8HhMhc4VKLO9KM5caLIBvUm4thi7fFaxyTmCKeNnXZ5pAlBwCUnhA09uw==", + "license": "MIT", "engines": { "node": ">=10" } @@ -10213,41 +10579,45 @@ "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" }, "node_modules/msgpackr": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/msgpackr/-/msgpackr-1.10.1.tgz", - "integrity": "sha512-r5VRLv9qouXuLiIBrLpl2d5ZvPt8svdQTl5/vMvE4nzDMyEX4sgW5yWhuBBj5UmgwOTWj8CIdSXn5sAfsHAWIQ==", + "version": "1.11.2", + "resolved": "https://registry.npmjs.org/msgpackr/-/msgpackr-1.11.2.tgz", + "integrity": "sha512-F9UngXRlPyWCDEASDpTf6c9uNhGPTqnTeLVt7bN+bU1eajoR/8V9ys2BRaV5C/e5ihE6sJ9uPIKaYt6bFuO32g==", + "license": "MIT", "optionalDependencies": { "msgpackr-extract": "^3.0.2" } }, "node_modules/msgpackr-extract": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/msgpackr-extract/-/msgpackr-extract-3.0.2.tgz", - "integrity": "sha512-SdzXp4kD/Qf8agZ9+iTu6eql0m3kWm1A2y1hkpTeVNENutaB0BwHlSvAIaMxwntmRUAUjon2V4L8Z/njd0Ct8A==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/msgpackr-extract/-/msgpackr-extract-3.0.3.tgz", + "integrity": "sha512-P0efT1C9jIdVRefqjzOQ9Xml57zpOXnIuS+csaB4MdZbTdmGDLo8XhzBG1N7aO11gKDDkJvBLULeFTo46wwreA==", "hasInstallScript": true, + "license": "MIT", "optional": true, "dependencies": { - "node-gyp-build-optional-packages": "5.0.7" + "node-gyp-build-optional-packages": "5.2.2" }, "bin": { "download-msgpackr-prebuilds": "bin/download-prebuilds.js" }, "optionalDependencies": { - "@msgpackr-extract/msgpackr-extract-darwin-arm64": "3.0.2", - "@msgpackr-extract/msgpackr-extract-darwin-x64": "3.0.2", - "@msgpackr-extract/msgpackr-extract-linux-arm": "3.0.2", - "@msgpackr-extract/msgpackr-extract-linux-arm64": "3.0.2", - "@msgpackr-extract/msgpackr-extract-linux-x64": "3.0.2", - "@msgpackr-extract/msgpackr-extract-win32-x64": "3.0.2" + "@msgpackr-extract/msgpackr-extract-darwin-arm64": "3.0.3", + "@msgpackr-extract/msgpackr-extract-darwin-x64": "3.0.3", + "@msgpackr-extract/msgpackr-extract-linux-arm": "3.0.3", + "@msgpackr-extract/msgpackr-extract-linux-arm64": "3.0.3", + "@msgpackr-extract/msgpackr-extract-linux-x64": "3.0.3", + "@msgpackr-extract/msgpackr-extract-win32-x64": "3.0.3" } }, "node_modules/multer": { "version": "1.4.4-lts.1", "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.4-lts.1.tgz", "integrity": "sha512-WeSGziVj6+Z2/MwQo3GvqzgR+9Uc+qt8SwHKh3gvNPiISKfsMfG4SvCOFYlxxgkXt7yIV2i1yczehm0EOKIxIg==", + "license": "MIT", "dependencies": { "append-field": "^1.0.0", "busboy": "^1.0.0", @@ -10268,6 +10638,7 @@ "engines": [ "node >= 0.8" ], + "license": "MIT", "dependencies": { "buffer-from": "^1.0.0", "inherits": "^2.0.3", @@ -10279,6 +10650,7 @@ "version": "2.3.8", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "license": "MIT", "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", @@ -10292,12 +10664,14 @@ "node_modules/multer/node_modules/safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "license": "MIT" }, "node_modules/multer/node_modules/string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "license": "MIT", "dependencies": { "safe-buffer": "~5.1.0" } @@ -10305,12 +10679,14 @@ "node_modules/mute-stream": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", - "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==" + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", + "license": "ISC" }, "node_modules/mz": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "license": "MIT", "dependencies": { "any-promise": "^1.0.0", "object-assign": "^4.0.1", @@ -10318,22 +10694,24 @@ } }, "node_modules/nan": { - "version": "2.18.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.18.0.tgz", - "integrity": "sha512-W7tfG7vMOGtD30sHoZSSc/JVYiyDPEyQVso/Zz+/uQd0B0L46gtC+pHha5FFMRpil6fm/AoEcRWyOVi4+E/f8w==", + "version": "2.22.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.22.0.tgz", + "integrity": "sha512-nbajikzWTMwsW+eSsNm3QwlOs7het9gGJU5dDZzRTQGk03vyBOauxgI4VakDzE0PtsGTmXPsXTbbjVhRwR5mpw==", "dev": true, + "license": "MIT", "optional": true }, "node_modules/nanoid": { - "version": "3.3.7", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", - "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "version": "3.3.8", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz", + "integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==", "funding": [ { "type": "github", "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "bin": { "nanoid": "bin/nanoid.cjs" }, @@ -10345,13 +10723,15 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/nearley": { "version": "2.20.1", "resolved": "https://registry.npmjs.org/nearley/-/nearley-2.20.1.tgz", "integrity": "sha512-+Mc8UaAebFzgV+KpI5n7DasuuQCHA89dmwm7JXw3TV43ukfNQ9DnBH3Mdb2g/I4Fdxc26pwimBWvjIw0UAILSQ==", "dev": true, + "license": "MIT", "dependencies": { "commander": "^2.19.0", "moo": "^0.5.0", @@ -10373,12 +10753,14 @@ "version": "2.20.3", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/negotiator": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -10386,12 +10768,14 @@ "node_modules/neo-async": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "license": "MIT" }, "node_modules/nest-commander": { "version": "3.15.0", "resolved": "https://registry.npmjs.org/nest-commander/-/nest-commander-3.15.0.tgz", "integrity": "sha512-o9VEfFj/w2nm+hQi6fnkxL1GAFZW/KmuGcIE7/B/TX0gwm0QVy8svAF75EQm8wrDjcvWS7Cx/ArnkFn2C+iM2w==", + "license": "MIT", "dependencies": { "@fig/complete-commander": "^3.0.0", "@golevelup/nestjs-discovery": "4.0.1", @@ -10409,6 +10793,7 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/@fig/complete-commander/-/complete-commander-3.2.0.tgz", "integrity": "sha512-1Holl3XtRiANVKURZwgpjCnPuV4RsHp+XC0MhgvyAX/avQwj7F2HUItYOvGi/bXjJCkEzgBZmVfCr0HBA+q+Bw==", + "license": "MIT", "dependencies": { "prettier": "^3.2.5" }, @@ -10420,14 +10805,16 @@ "version": "11.1.0", "resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz", "integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==", + "license": "MIT", "engines": { "node": ">=16" } }, "node_modules/nestjs-cls": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/nestjs-cls/-/nestjs-cls-4.4.1.tgz", - "integrity": "sha512-4yhldwm/cJ02lQ8ZAdM8KQ7gMfjAc1z3fo5QAQgXNyN4N6X5So9BCwv+BTLRugDCkELUo3qtzQHnKhGYL/ftPg==", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/nestjs-cls/-/nestjs-cls-4.5.0.tgz", + "integrity": "sha512-oi3GNCc5pnsnVI5WJKMDwmg4NP+JyEw+edlwgepyUba5+RGGtJzpbVaaxXGW1iPbDuQde3/fA8Jdjq9j88BVcQ==", + "license": "MIT", "engines": { "node": ">=16" }, @@ -10442,6 +10829,7 @@ "version": "6.1.1", "resolved": "https://registry.npmjs.org/nestjs-otel/-/nestjs-otel-6.1.1.tgz", "integrity": "sha512-hWuhDYkkaZrBXpHmi2v0jGqKa61uPqzu2YsVhww8/s+v9SaDILylR7ZdoOiygCQisgHG9rw5odP12GfsMS8cBA==", + "license": "Apache-2.0", "dependencies": { "@opentelemetry/api": "^1.8.0", "@opentelemetry/host-metrics": "^0.35.1", @@ -10453,40 +10841,42 @@ } }, "node_modules/next": { - "version": "14.2.3", - "resolved": "https://registry.npmjs.org/next/-/next-14.2.3.tgz", - "integrity": "sha512-dowFkFTR8v79NPJO4QsBUtxv0g9BrS/phluVpMAt2ku7H+cbcBJlopXjkWlwxrk/xGqMemr7JkGPGemPrLLX7A==", + "version": "15.0.4", + "resolved": "https://registry.npmjs.org/next/-/next-15.0.4.tgz", + "integrity": "sha512-nuy8FH6M1FG0lktGotamQDCXhh5hZ19Vo0ht1AOIQWrYJLP598TIUagKtvJrfJ5AGwB/WmDqkKaKhMpVifvGPA==", + "license": "MIT", "dependencies": { - "@next/env": "14.2.3", - "@swc/helpers": "0.5.5", + "@next/env": "15.0.4", + "@swc/counter": "0.1.3", + "@swc/helpers": "0.5.13", "busboy": "1.6.0", "caniuse-lite": "^1.0.30001579", - "graceful-fs": "^4.2.11", "postcss": "8.4.31", - "styled-jsx": "5.1.1" + "styled-jsx": "5.1.6" }, "bin": { "next": "dist/bin/next" }, "engines": { - "node": ">=18.17.0" + "node": "^18.18.0 || ^19.8.0 || >= 20.0.0" }, "optionalDependencies": { - "@next/swc-darwin-arm64": "14.2.3", - "@next/swc-darwin-x64": "14.2.3", - "@next/swc-linux-arm64-gnu": "14.2.3", - "@next/swc-linux-arm64-musl": "14.2.3", - "@next/swc-linux-x64-gnu": "14.2.3", - "@next/swc-linux-x64-musl": "14.2.3", - "@next/swc-win32-arm64-msvc": "14.2.3", - "@next/swc-win32-ia32-msvc": "14.2.3", - "@next/swc-win32-x64-msvc": "14.2.3" + "@next/swc-darwin-arm64": "15.0.4", + "@next/swc-darwin-x64": "15.0.4", + "@next/swc-linux-arm64-gnu": "15.0.4", + "@next/swc-linux-arm64-musl": "15.0.4", + "@next/swc-linux-x64-gnu": "15.0.4", + "@next/swc-linux-x64-musl": "15.0.4", + "@next/swc-win32-arm64-msvc": "15.0.4", + "@next/swc-win32-x64-msvc": "15.0.4", + "sharp": "^0.33.5" }, "peerDependencies": { "@opentelemetry/api": "^1.1.0", "@playwright/test": "^1.41.2", - "react": "^18.2.0", - "react-dom": "^18.2.0", + "babel-plugin-react-compiler": "*", + "react": "^18.2.0 || 19.0.0-rc-66855b96-20241106 || ^19.0.0", + "react-dom": "^18.2.0 || 19.0.0-rc-66855b96-20241106 || ^19.0.0", "sass": "^1.3.0" }, "peerDependenciesMeta": { @@ -10496,48 +10886,32 @@ "@playwright/test": { "optional": true }, - "sass": { + "babel-plugin-react-compiler": { "optional": true - } - } - }, - "node_modules/next/node_modules/postcss": { - "version": "8.4.31", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", - "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" + "sass": { + "optional": true } - ], - "dependencies": { - "nanoid": "^3.3.6", - "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" - }, - "engines": { - "node": "^10 || ^12 || >=14" } }, "node_modules/node-abort-controller": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/node-abort-controller/-/node-abort-controller-3.1.1.tgz", - "integrity": "sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==" + "integrity": "sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==", + "license": "MIT" + }, + "node_modules/node-addon-api": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz", + "integrity": "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==", + "license": "MIT" }, "node_modules/node-emoji": { "version": "1.11.0", "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-1.11.0.tgz", "integrity": "sha512-wo2DpQkQp7Sjm2A0cq+sN7EHKO6Sl0ctXeBdFZrL9T9+UywORbufTcTZxom8YqpLQt/FqNMUkOpkZrJVYSKD3A==", "dev": true, + "license": "MIT", "dependencies": { "lodash": "^4.17.21" } @@ -10546,6 +10920,7 @@ "version": "2.7.0", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "license": "MIT", "dependencies": { "whatwg-url": "^5.0.0" }, @@ -10562,10 +10937,14 @@ } }, "node_modules/node-gyp-build-optional-packages": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/node-gyp-build-optional-packages/-/node-gyp-build-optional-packages-5.0.7.tgz", - "integrity": "sha512-YlCCc6Wffkx0kHkmam79GKvDQ6x+QZkMjFGrIMxgFNILFvGSbCp2fCBC55pGTT9gVaz8Na5CLmxt/urtzRv36w==", + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/node-gyp-build-optional-packages/-/node-gyp-build-optional-packages-5.2.2.tgz", + "integrity": "sha512-s+w+rBWnpTMwSFbaE0UXsRlg7hU4FjekKU4eyAih5T8nJuNZT1nNsskXpxmeqSK9UzkBl6UgRlnKc8hz8IEqOw==", + "license": "MIT", "optional": true, + "dependencies": { + "detect-libc": "^2.0.1" + }, "bin": { "node-gyp-build-optional-packages": "bin.js", "node-gyp-build-optional-packages-optional": "optional.js", @@ -10573,14 +10952,16 @@ } }, "node_modules/node-releases": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", - "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==" + "version": "2.0.19", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", + "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==", + "license": "MIT" }, "node_modules/nodemailer": { - "version": "6.9.15", - "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.15.tgz", - "integrity": "sha512-AHf04ySLC6CIfuRtRiEYtGEXgRfa6INgWGluDhnxTZhHSKvrBu7lc1VVchQ0d8nPc4cFaZoPq8vkyNoZr0TpGQ==", + "version": "6.9.16", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.16.tgz", + "integrity": "sha512-psAuZdTIRN08HKVd/E8ObdV6NO7NTBY3KsC30F7M4H1OnmLCUNaS56FpYxyb26zWLSyYF9Ozch9KYHhHegsiOQ==", + "license": "MIT-0", "engines": { "node": ">=6.0.0" } @@ -10589,6 +10970,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", + "license": "ISC", "dependencies": { "abbrev": "1" }, @@ -10604,6 +10986,7 @@ "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "hosted-git-info": "^2.1.4", "resolve": "^1.10.0", @@ -10616,6 +10999,7 @@ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", "dev": true, + "license": "ISC", "bin": { "semver": "bin/semver" } @@ -10624,6 +11008,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -10631,12 +11016,15 @@ "node_modules/notepack.io": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/notepack.io/-/notepack.io-3.0.1.tgz", - "integrity": "sha512-TKC/8zH5pXIAMVQio2TvVDTtPRX+DJPHDqjRbxogtFiByHyzKmy96RA0JtCQJ+WouyyL4A10xomQzgbUT+1jCg==" + "integrity": "sha512-TKC/8zH5pXIAMVQio2TvVDTtPRX+DJPHDqjRbxogtFiByHyzKmy96RA0JtCQJ+WouyyL4A10xomQzgbUT+1jCg==", + "license": "MIT" }, "node_modules/npmlog": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", + "deprecated": "This package is no longer supported.", + "license": "ISC", "dependencies": { "are-we-there-yet": "^2.0.0", "console-control-strings": "^1.1.0", @@ -10648,6 +11036,7 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -10656,14 +11045,16 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", + "license": "MIT", "engines": { "node": ">= 6" } }, "node_modules/object-inspect": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", - "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==", + "version": "1.13.3", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.3.tgz", + "integrity": "sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA==", + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -10671,15 +11062,11 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/obuf": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", - "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==" - }, "node_modules/oidc-token-hash": { "version": "5.0.3", "resolved": "https://registry.npmjs.org/oidc-token-hash/-/oidc-token-hash-5.0.3.tgz", "integrity": "sha512-IF4PcGgzAr6XXSff26Sk/+P4KZFJVuHAJZj3wgO3vX2bMdNVp/QXTP3P7CEm9V1IdG8lDLY3HhiqpsE/nOwpPw==", + "license": "MIT", "engines": { "node": "^10.13.0 || >=12.0.0" } @@ -10688,6 +11075,7 @@ "version": "2.4.1", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "license": "MIT", "dependencies": { "ee-first": "1.1.1" }, @@ -10699,6 +11087,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "license": "MIT", "engines": { "node": ">= 0.8" } @@ -10707,6 +11096,7 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "license": "ISC", "dependencies": { "wrappy": "1" } @@ -10715,6 +11105,7 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "license": "MIT", "dependencies": { "mimic-fn": "^2.1.0" }, @@ -10726,9 +11117,10 @@ } }, "node_modules/openid-client": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/openid-client/-/openid-client-5.7.0.tgz", - "integrity": "sha512-4GCCGZt1i2kTHpwvaC/sCpTpQqDnBzDzuJcJMbH+y1Q5qI8U8RBvoSh28svarXszZHR5BAMXbJPX1PGPRE3VOA==", + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/openid-client/-/openid-client-5.7.1.tgz", + "integrity": "sha512-jDBPgSVfTnkIh71Hg9pRvtJc6wTwqjRkN88+gCFtYWrlP4Yx2Dsrow8uPi3qLr/aeymPF3o2+dS+wOpglK04ew==", + "license": "MIT", "dependencies": { "jose": "^4.15.9", "lru-cache": "^6.0.0", @@ -10739,42 +11131,28 @@ "url": "https://github.com/sponsors/panva" } }, - "node_modules/openid-client/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/openid-client/node_modules/object-hash": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-2.2.0.tgz", "integrity": "sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw==", + "license": "MIT", "engines": { "node": ">= 6" } }, - "node_modules/openid-client/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, "node_modules/optionator": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", - "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", "dev": true, + "license": "MIT", "dependencies": { - "@aashutoshrathi/word-wrap": "^1.2.3", "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", "levn": "^0.4.1", "prelude-ls": "^1.2.1", - "type-check": "^0.4.0" + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" }, "engines": { "node": ">= 0.8.0" @@ -10784,6 +11162,7 @@ "version": "5.4.1", "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", + "license": "MIT", "dependencies": { "bl": "^4.1.0", "chalk": "^4.1.0", @@ -10806,6 +11185,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -10815,6 +11195,7 @@ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, + "license": "MIT", "dependencies": { "yocto-queue": "^0.1.0" }, @@ -10830,6 +11211,7 @@ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dev": true, + "license": "MIT", "dependencies": { "p-limit": "^3.0.2" }, @@ -10845,19 +11227,22 @@ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/package-json-from-dist": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.0.tgz", - "integrity": "sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw==" + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "license": "BlueOak-1.0.0" }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "license": "MIT", "dependencies": { "callsites": "^3.0.0" }, @@ -10869,6 +11254,7 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "license": "MIT", "dependencies": { "@babel/code-frame": "^7.0.0", "error-ex": "^1.3.1", @@ -10885,12 +11271,14 @@ "node_modules/parse5": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.1.tgz", - "integrity": "sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==" + "integrity": "sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==", + "license": "MIT" }, "node_modules/parse5-htmlparser2-tree-adapter": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz", "integrity": "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==", + "license": "MIT", "dependencies": { "parse5": "^6.0.1" } @@ -10898,12 +11286,14 @@ "node_modules/parse5-htmlparser2-tree-adapter/node_modules/parse5": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", - "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==" + "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", + "license": "MIT" }, "node_modules/parseley": { "version": "0.12.1", "resolved": "https://registry.npmjs.org/parseley/-/parseley-0.12.1.tgz", "integrity": "sha512-e6qHKe3a9HWr0oMRVDTRhKce+bRO8VGQR3NyVwcjwrbhMmFCX9KszEV35+rn4AdilFAq9VPxP/Fe1wC9Qjd2lw==", + "license": "MIT", "dependencies": { "leac": "^0.6.0", "peberminta": "^0.9.0" @@ -10916,6 +11306,7 @@ "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "license": "MIT", "engines": { "node": ">= 0.8" } @@ -10925,6 +11316,7 @@ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -10933,6 +11325,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -10941,6 +11334,7 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "license": "MIT", "engines": { "node": ">=8" } @@ -10948,12 +11342,14 @@ "node_modules/path-parse": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "license": "MIT" }, "node_modules/path-scurry": { "version": "1.11.1", "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "license": "BlueOak-1.0.0", "dependencies": { "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" @@ -10966,17 +11362,16 @@ } }, "node_modules/path-scurry/node_modules/lru-cache": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz", - "integrity": "sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==", - "engines": { - "node": "14 || >=16.14" - } + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "license": "ISC" }, "node_modules/path-source": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/path-source/-/path-source-0.1.3.tgz", "integrity": "sha512-dWRHm5mIw5kw0cs3QZLNmpUWty48f5+5v9nWD2dw3Y0Hf+s01Ag8iJEWV0Sm0kocE8kK27DrIowha03e1YR+Qw==", + "license": "BSD-3-Clause", "dependencies": { "array-source": "0.0", "file-source": "0.6" @@ -10985,12 +11380,14 @@ "node_modules/path-to-regexp": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-3.3.0.tgz", - "integrity": "sha512-qyCH421YQPS2WFDxDjftfc1ZR5WKQzVzqsp4n9M2kQhVOo/ByahFoUNJfl58kOcEGfQ//7weFTDhm+ss8Ecxgw==" + "integrity": "sha512-qyCH421YQPS2WFDxDjftfc1ZR5WKQzVzqsp4n9M2kQhVOo/ByahFoUNJfl58kOcEGfQ//7weFTDhm+ss8Ecxgw==", + "license": "MIT" }, "node_modules/path-type": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "license": "MIT", "engines": { "node": ">=8" } @@ -10999,21 +11396,24 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz", "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/pathval": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.0.tgz", "integrity": "sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==", "dev": true, + "license": "MIT", "engines": { "node": ">= 14.16" } }, "node_modules/pbf": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/pbf/-/pbf-3.2.1.tgz", - "integrity": "sha512-ClrV7pNOn7rtmoQVF4TS1vyU0WhYRnP92fzbfF75jAIwpnzdJXf8iTd4CMEqO4yUenH6NDqLiwjqlh6QgZzgLQ==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/pbf/-/pbf-3.3.0.tgz", + "integrity": "sha512-XDF38WCH3z5OV/OVa8GKUNtLAyneuzbCisx7QUCF8Q6Nutx0WnJrQe5O+kOtBlLfRNUws98Y58Lblp+NJG5T4Q==", + "license": "BSD-3-Clause", "dependencies": { "ieee754": "^1.1.12", "resolve-protobuf-schema": "^2.1.0" @@ -11026,6 +11426,7 @@ "version": "0.9.0", "resolved": "https://registry.npmjs.org/peberminta/-/peberminta-0.9.0.tgz", "integrity": "sha512-XIxfHpEuSJbITd1H3EeQwpcZbTLHc+VVr8ANI9t5sit565tsI4/xK3KWTUFE2e6QiangUkh3B0jihzmGnNrRsQ==", + "license": "MIT", "funding": { "url": "https://ko-fi.com/killymxi" } @@ -11034,6 +11435,7 @@ "version": "8.13.1", "resolved": "https://registry.npmjs.org/pg/-/pg-8.13.1.tgz", "integrity": "sha512-OUir1A0rPNZlX//c7ksiu7crsGZTKSOXJPgtNiHGIlC9H0lO+NC6ZDYksSgBYY/thSWhnSRBv8w1lieNNGATNQ==", + "license": "MIT", "dependencies": { "pg-connection-string": "^2.7.0", "pg-pool": "^3.7.0", @@ -11060,33 +11462,29 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.1.1.tgz", "integrity": "sha512-xWPagP/4B6BgFO+EKz3JONXv3YDgvkbVrGw2mTo3D6tVDQRh1e7cqVGvyR3BE+eQgAvx1XhW/iEASj4/jCWl3Q==", + "license": "MIT", "optional": true }, "node_modules/pg-connection-string": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.7.0.tgz", - "integrity": "sha512-PI2W9mv53rXJQEOb8xNR8lH7Hr+EKa6oJa38zsK0S/ky2er16ios1wLKhZyxzD7jUReiWokc9WK5nxSnC7W1TA==" + "integrity": "sha512-PI2W9mv53rXJQEOb8xNR8lH7Hr+EKa6oJa38zsK0S/ky2er16ios1wLKhZyxzD7jUReiWokc9WK5nxSnC7W1TA==", + "license": "MIT" }, "node_modules/pg-int8": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz", "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==", + "license": "ISC", "engines": { "node": ">=4.0.0" } }, - "node_modules/pg-numeric": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pg-numeric/-/pg-numeric-1.0.2.tgz", - "integrity": "sha512-BM/Thnrw5jm2kKLE5uJkXqqExRUY/toLHda65XgFTBTFYZyopbKjBe29Ii3RbkvlsMoFwD+tHeGaCjjv0gHlyw==", - "engines": { - "node": ">=4" - } - }, "node_modules/pg-pool": { "version": "3.7.0", "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.7.0.tgz", "integrity": "sha512-ZOBQForurqh4zZWjrgSwwAtzJ7QiRX0ovFkZr2klsen3Nm0aoh33Ls0fzfv3imeH/nw/O27cjdz5kzYJfeGp/g==", + "license": "MIT", "peerDependencies": { "pg": ">=8.0" } @@ -11094,12 +11492,14 @@ "node_modules/pg-protocol": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.7.0.tgz", - "integrity": "sha512-hTK/mE36i8fDDhgDFjy6xNOG+LCorxLG3WO17tku+ij6sVHXh1jQUJ8hYAnRhNla4QVD2H8er/FOjc/+EgC6yQ==" + "integrity": "sha512-hTK/mE36i8fDDhgDFjy6xNOG+LCorxLG3WO17tku+ij6sVHXh1jQUJ8hYAnRhNla4QVD2H8er/FOjc/+EgC6yQ==", + "license": "MIT" }, "node_modules/pg-types": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz", "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==", + "license": "MIT", "dependencies": { "pg-int8": "1.0.1", "postgres-array": "~2.0.0", @@ -11115,14 +11515,16 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.5.tgz", "integrity": "sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==", + "license": "MIT", "dependencies": { "split2": "^4.1.0" } }, "node_modules/picocolors": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.0.tgz", - "integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==" + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC" }, "node_modules/picomatch": { "version": "4.0.2", @@ -11140,6 +11542,7 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "license": "MIT", "peer": true, "engines": { "node": ">=0.10.0" @@ -11149,6 +11552,7 @@ "version": "4.0.6", "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", + "license": "MIT", "peer": true, "engines": { "node": ">= 6" @@ -11159,6 +11563,7 @@ "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } @@ -11174,14 +11579,18 @@ } }, "node_modules/point-in-polygon-hao": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/point-in-polygon-hao/-/point-in-polygon-hao-1.1.0.tgz", - "integrity": "sha512-3hTIM2j/v9Lio+wOyur3kckD4NxruZhpowUbEgmyikW+a2Kppjtu1eN+AhnMQtoHW46zld88JiYWv6fxpsDrTQ==" + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/point-in-polygon-hao/-/point-in-polygon-hao-1.2.3.tgz", + "integrity": "sha512-uZsWylGd8nthIYS8F7aSyM7Pot+4L/bgXheJcCNdRr4eLpsM/rMb3hIi5SqNxAVjUoDDao3QzCtdaVDzmeF9Cw==", + "license": "MIT", + "dependencies": { + "robust-predicates": "^3.0.2" + } }, "node_modules/postcss": { - "version": "8.4.47", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.47.tgz", - "integrity": "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==", + "version": "8.4.31", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", + "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", "funding": [ { "type": "opencollective", @@ -11196,10 +11605,11 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "dependencies": { - "nanoid": "^3.3.7", - "picocolors": "^1.1.0", - "source-map-js": "^1.2.1" + "nanoid": "^3.3.6", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" }, "engines": { "node": "^10 || ^12 || >=14" @@ -11209,6 +11619,7 @@ "version": "15.1.0", "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz", "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==", + "license": "MIT", "peer": true, "dependencies": { "postcss-value-parser": "^4.0.0", @@ -11226,6 +11637,7 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz", "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==", + "license": "MIT", "peer": true, "dependencies": { "camelcase-css": "^2.0.1" @@ -11255,6 +11667,7 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "peer": true, "dependencies": { "lilconfig": "^3.0.0", @@ -11276,41 +11689,37 @@ } } }, - "node_modules/postcss-load-config/node_modules/lilconfig": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.1.tgz", - "integrity": "sha512-O18pf7nyvHTckunPWCV1XUNXU1piu01y2b7ATJ0ppkUkk8ocqVWBrYjJBCwHDjD/ZWcfyrA0P4gKhzWGi5EINQ==", - "peer": true, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/antonk52" - } - }, "node_modules/postcss-nested": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.0.1.tgz", - "integrity": "sha512-mEp4xPMi5bSWiMbsgoPfcP74lsWLHkQbZc3sY+jWYd65CUwXrUaTp0fmNpa01ZcETKlIgUdFN/MpS2xZtqL9dQ==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz", + "integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", "peer": true, "dependencies": { - "postcss-selector-parser": "^6.0.11" + "postcss-selector-parser": "^6.1.1" }, "engines": { "node": ">=12.0" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, "peerDependencies": { "postcss": "^8.2.14" } }, "node_modules/postcss-selector-parser": { - "version": "6.0.16", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.16.tgz", - "integrity": "sha512-A0RVJrX+IUkVZbW3ClroRWurercFhieevHB38sr2+l9eUClMqome3LmEmnhlNy+5Mr2EYN6B2Kaw9wYdd+VHiw==", + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", + "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", + "license": "MIT", "peer": true, "dependencies": { "cssesc": "^3.0.0", @@ -11324,12 +11733,14 @@ "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "license": "MIT", "peer": true }, "node_modules/postgres-array": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz", "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==", + "license": "MIT", "engines": { "node": ">=4" } @@ -11338,6 +11749,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz", "integrity": "sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==", + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -11346,6 +11758,7 @@ "version": "1.0.7", "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz", "integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==", + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -11354,6 +11767,7 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz", "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==", + "license": "MIT", "dependencies": { "xtend": "^4.0.0" }, @@ -11361,24 +11775,21 @@ "node": ">=0.10.0" } }, - "node_modules/postgres-range": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/postgres-range/-/postgres-range-1.1.4.tgz", - "integrity": "sha512-i/hbxIE9803Alj/6ytL7UHQxRvZkI9O4Sy+J3HGc4F4oo/2eQAjTSNJ0bfxyse3bH0nuVesCk+3IRLaMtG3H6w==" - }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.8.0" } }, "node_modules/prettier": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.3.tgz", - "integrity": "sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==", + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.4.2.tgz", + "integrity": "sha512-e9MewbtFo+Fevyuxn/4rrcDAaq0IYxPGLvObpQjiZBMAzB9IGmzlnG9RZy3FFas+eBMu2vA0CszMeduow5dIuQ==", + "license": "MIT", "bin": { "prettier": "bin/prettier.cjs" }, @@ -11394,6 +11805,7 @@ "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", "dev": true, + "license": "MIT", "dependencies": { "fast-diff": "^1.1.2" }, @@ -11406,6 +11818,7 @@ "resolved": "https://registry.npmjs.org/prettier-plugin-organize-imports/-/prettier-plugin-organize-imports-4.1.0.tgz", "integrity": "sha512-5aWRdCgv645xaa58X8lOxzZoiHAldAPChljr/MT0crXVOWTZ+Svl4hIWlz+niYSlO6ikE5UXkN1JrRvIP2ut0A==", "dev": true, + "license": "MIT", "peerDependencies": { "prettier": ">=2.0", "typescript": ">=2.9", @@ -11421,6 +11834,7 @@ "version": "1.29.0", "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.29.0.tgz", "integrity": "sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q==", + "license": "MIT", "engines": { "node": ">=6" } @@ -11429,6 +11843,7 @@ "version": "0.11.10", "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "license": "MIT", "engines": { "node": ">= 0.6.0" } @@ -11436,13 +11851,15 @@ "node_modules/process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "license": "MIT" }, "node_modules/proper-lockfile": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/proper-lockfile/-/proper-lockfile-4.1.2.tgz", "integrity": "sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA==", "dev": true, + "license": "MIT", "dependencies": { "graceful-fs": "^4.2.4", "retry": "^0.12.0", @@ -11453,13 +11870,15 @@ "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/properties-reader": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/properties-reader/-/properties-reader-2.3.0.tgz", "integrity": "sha512-z597WicA7nDZxK12kZqHr2TcvwNU1GCfA5UwfDY/HDp3hXPoPlb5rlEx9bwGTiJnc0OqbBTkU975jDToth8Gxw==", "dev": true, + "license": "MIT", "dependencies": { "mkdirp": "^1.0.4" }, @@ -11476,6 +11895,7 @@ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", "dev": true, + "license": "MIT", "bin": { "mkdirp": "bin/cmd.js" }, @@ -11483,16 +11903,12 @@ "node": ">=10" } }, - "node_modules/proto-list": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", - "integrity": "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==" - }, "node_modules/protobufjs": { "version": "7.4.0", "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.4.0.tgz", "integrity": "sha512-mRUWCc3KUU4w1jU8sGxICXH/gNS94DvI1gxqDvBzhj1JpcsimQkYiOJfwsPUykUI5ZaspFbSgmBLER8IrQ3tqw==", "hasInstallScript": true, + "license": "BSD-3-Clause", "dependencies": { "@protobufjs/aspromise": "^1.1.2", "@protobufjs/base64": "^1.1.2", @@ -11514,12 +11930,14 @@ "node_modules/protocol-buffers-schema": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/protocol-buffers-schema/-/protocol-buffers-schema-3.6.0.tgz", - "integrity": "sha512-TdDRD+/QNdrCGCE7v8340QyuXd4kIWIgapsE2+n/SaGiSSbomYl4TjHlvIoCWRpE7wFt02EpB35VVA2ImcBVqw==" + "integrity": "sha512-TdDRD+/QNdrCGCE7v8340QyuXd4kIWIgapsE2+n/SaGiSSbomYl4TjHlvIoCWRpE7wFt02EpB35VVA2ImcBVqw==", + "license": "MIT" }, "node_modules/proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "license": "MIT", "dependencies": { "forwarded": "0.2.0", "ipaddr.js": "1.9.1" @@ -11529,20 +11947,22 @@ } }, "node_modules/pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz", + "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==", "dev": true, + "license": "MIT", "dependencies": { "end-of-stream": "^1.1.0", "once": "^1.3.1" } }, "node_modules/punycode": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", - "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -11551,6 +11971,7 @@ "version": "6.13.0", "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "license": "BSD-3-Clause", "dependencies": { "side-channel": "^1.0.6" }, @@ -11578,24 +11999,28 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "MIT" }, "node_modules/queue-tick": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/queue-tick/-/queue-tick-1.0.1.tgz", - "integrity": "sha512-kJt5qhMxoszgU/62PLP1CJytzd2NKetjSRnyuj31fDd3Rlcz3fzlFdFLD1SItunPwyqEOkca6GbV612BWfaBag==" + "integrity": "sha512-kJt5qhMxoszgU/62PLP1CJytzd2NKetjSRnyuj31fDd3Rlcz3fzlFdFLD1SItunPwyqEOkca6GbV612BWfaBag==", + "license": "MIT" }, "node_modules/railroad-diagrams": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/railroad-diagrams/-/railroad-diagrams-1.0.0.tgz", "integrity": "sha512-cz93DjNeLY0idrCNOH6PviZGRN9GJhsdm9hpn1YCS879fj4W+x5IFJhhkRZcwVgMmFF7R82UA/7Oh+R8lLZg6A==", - "dev": true + "dev": true, + "license": "CC0-1.0" }, "node_modules/randexp": { "version": "0.4.6", "resolved": "https://registry.npmjs.org/randexp/-/randexp-0.4.6.tgz", "integrity": "sha512-80WNmd9DA0tmZrw9qQa62GPPWfuXJknrmVmLcxvq4uZBdYqb1wYoKTmnlGUchvVWe0XiLupYkBoXVOxz3C8DYQ==", "dev": true, + "license": "MIT", "dependencies": { "discontinuous-range": "1.0.0", "ret": "~0.1.10" @@ -11609,6 +12034,7 @@ "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", "dev": true, + "license": "MIT", "dependencies": { "safe-buffer": "^5.1.0" } @@ -11617,6 +12043,7 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -11625,6 +12052,7 @@ "version": "2.5.2", "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "license": "MIT", "dependencies": { "bytes": "3.1.2", "http-errors": "2.0.0", @@ -11636,48 +12064,47 @@ } }, "node_modules/react": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", - "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", - "dependencies": { - "loose-envify": "^1.1.0" - }, + "version": "19.0.0", + "resolved": "https://registry.npmjs.org/react/-/react-19.0.0.tgz", + "integrity": "sha512-V8AVnmPIICiWpGfm6GLzCR/W5FXLchHop40W4nXBmdlEceh16rCN8O8LNWm5bh5XUX91fh7KpA+W0TgMKmgTpQ==", + "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/react-dom": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", - "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", + "version": "19.0.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.0.0.tgz", + "integrity": "sha512-4GV5sHFG0e/0AD4X+ySy6UJd3jVl1iNsNHdpad0qhABJ11twS3TTBnseqsKurKcsNqCEFeGL3uLpVChpIO3QfQ==", + "license": "MIT", "peer": true, "dependencies": { - "loose-envify": "^1.1.0", - "scheduler": "^0.23.2" + "scheduler": "^0.25.0" }, "peerDependencies": { - "react": "^18.3.1" + "react": "^19.0.0" } }, "node_modules/react-email": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/react-email/-/react-email-3.0.1.tgz", - "integrity": "sha512-G4Bkx2ULIScy/0Z8nnWywHt0W1iTkaYCdh9rWNuQ3eVZ6B3ttTUDE9uUy3VNQ8dtQbmG0cpt8+XmImw7mMBW6Q==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/react-email/-/react-email-3.0.4.tgz", + "integrity": "sha512-nXdo9P3V+qYSW6m5yN3XpFGhHb/bflX86m0EDQEqDIgayprj6InmBJoBnMSIyC5EP4tPtoAljlclJns4lJG/MQ==", + "license": "MIT", "dependencies": { "@babel/core": "7.24.5", "@babel/parser": "7.24.5", "chalk": "4.1.2", - "chokidar": "3.6.0", + "chokidar": "^4.0.1", "commander": "11.1.0", "debounce": "2.0.0", "esbuild": "0.19.11", "glob": "10.3.4", "log-symbols": "4.1.0", "mime-types": "2.1.35", - "next": "14.2.3", + "next": "15.0.4", "normalize-path": "3.0.0", "ora": "5.4.1", - "socket.io": "4.7.5" + "socket.io": "4.8.0" }, "bin": { "email": "dist/cli/index.js" @@ -11686,668 +12113,431 @@ "node": ">=18.0.0" } }, - "node_modules/react-email/node_modules/@esbuild/aix-ppc64": { - "version": "0.19.11", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.19.11.tgz", - "integrity": "sha512-FnzU0LyE3ySQk7UntJO4+qIiQgI7KoODnZg5xzXIrFJlKd2P2gwHsHY4927xj9y5PJmJSzULiUCWmv7iWnNa7g==", - "cpu": [ - "ppc64" - ], - "optional": true, - "os": [ - "aix" - ], + "node_modules/react-email/node_modules/@babel/parser": { + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.5.tgz", + "integrity": "sha512-EOv5IK8arwh3LI47dz1b0tKUb/1uhHAnHJOrjgtQMIpu1uXd9mlFrJg9IUgGUgZ41Ch0K8REPTYpO7B76b4vJg==", + "license": "MIT", + "bin": { + "parser": "bin/babel-parser.js" + }, "engines": { - "node": ">=12" + "node": ">=6.0.0" } }, - "node_modules/react-email/node_modules/@esbuild/android-arm": { - "version": "0.19.11", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.11.tgz", - "integrity": "sha512-5OVapq0ClabvKvQ58Bws8+wkLCV+Rxg7tUVbo9xu034Nm536QTII4YzhaFriQ7rMrorfnFKUsArD2lqKbFY4vw==", - "cpu": [ - "arm" - ], - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" + "node_modules/react-email/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" } }, - "node_modules/react-email/node_modules/@esbuild/android-arm64": { - "version": "0.19.11", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.19.11.tgz", - "integrity": "sha512-aiu7K/5JnLj//KOnOfEZ0D90obUkRzDMyqd/wNAUQ34m4YUPVhRZpnqKV9uqDGxT7cToSDnIHsGooyIczu9T+Q==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "android" - ], + "node_modules/react-email/node_modules/chokidar": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.2.tgz", + "integrity": "sha512-/b57FK+bblSU+dfewfFe0rT1YjVDfOmeLQwCAuC+vwvgLkXboATqqmy+Ipux6JrF6L5joe5CBnFOw+gLWH6yKg==", + "license": "MIT", + "dependencies": { + "readdirp": "^4.0.1" + }, "engines": { - "node": ">=12" + "node": ">= 14.16.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" } }, - "node_modules/react-email/node_modules/@esbuild/android-x64": { - "version": "0.19.11", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.19.11.tgz", - "integrity": "sha512-eccxjlfGw43WYoY9QgB82SgGgDbibcqyDTlk3l3C0jOVHKxrjdc9CTwDUQd0vkvYg5um0OH+GpxYvp39r+IPOg==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "android" - ], + "node_modules/react-email/node_modules/commander": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz", + "integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==", + "license": "MIT", "engines": { - "node": ">=12" + "node": ">=16" } }, - "node_modules/react-email/node_modules/@esbuild/darwin-arm64": { - "version": "0.19.11", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.11.tgz", - "integrity": "sha512-ETp87DRWuSt9KdDVkqSoKoLFHYTrkyz2+65fj9nfXsaV3bMhTCjtQfw3y+um88vGRKRiF7erPrh/ZuIdLUIVxQ==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "darwin" - ], + "node_modules/react-email/node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, "engines": { - "node": ">=12" + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, - "node_modules/react-email/node_modules/@esbuild/darwin-x64": { - "version": "0.19.11", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.19.11.tgz", - "integrity": "sha512-fkFUiS6IUK9WYUO/+22omwetaSNl5/A8giXvQlcinLIjVkxwTLSktbF5f/kJMftM2MJp9+fXqZ5ezS7+SALp4g==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "darwin" - ], + "node_modules/react-email/node_modules/glob": { + "version": "10.3.4", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.4.tgz", + "integrity": "sha512-6LFElP3A+i/Q8XQKEvZjkEWEOTgAIALR9AO2rwT8bgPhDd1anmqDJDZ6lLddI4ehxxxR1S5RIqKe1uapMQfYaQ==", + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^2.0.3", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" + }, + "bin": { + "glob": "dist/cjs/src/bin.js" + }, "engines": { - "node": ">=12" + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/react-email/node_modules/@esbuild/freebsd-arm64": { - "version": "0.19.11", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.11.tgz", - "integrity": "sha512-lhoSp5K6bxKRNdXUtHoNc5HhbXVCS8V0iZmDvyWvYq9S5WSfTIHU2UGjcGt7UeS6iEYp9eeymIl5mJBn0yiuxA==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "freebsd" - ], + "node_modules/react-email/node_modules/jackspeak": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", + "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, "engines": { - "node": ">=12" - } - }, - "node_modules/react-email/node_modules/@esbuild/freebsd-x64": { - "version": "0.19.11", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.19.11.tgz", - "integrity": "sha512-JkUqn44AffGXitVI6/AbQdoYAq0TEullFdqcMY/PCUZ36xJ9ZJRtQabzMA+Vi7r78+25ZIBosLTOKnUXBSi1Kw==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" } }, - "node_modules/react-email/node_modules/@esbuild/linux-arm": { - "version": "0.19.11", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.19.11.tgz", - "integrity": "sha512-3CRkr9+vCV2XJbjwgzjPtO8T0SZUmRZla+UL1jw+XqHZPkPgZiyWvbDvl9rqAN8Zl7qJF0O/9ycMtjU67HN9/Q==", - "cpu": [ - "arm" - ], - "optional": true, - "os": [ - "linux" - ], + "node_modules/react-email/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, "engines": { - "node": ">=12" + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/react-email/node_modules/@esbuild/linux-arm64": { - "version": "0.19.11", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.19.11.tgz", - "integrity": "sha512-LneLg3ypEeveBSMuoa0kwMpCGmpu8XQUh+mL8XXwoYZ6Be2qBnVtcDI5azSvh7vioMDhoJFZzp9GWp9IWpYoUg==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "linux" - ], + "node_modules/react-email/node_modules/readdirp": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.0.2.tgz", + "integrity": "sha512-yDMz9g+VaZkqBYS/ozoBJwaBhTbZo3UNYQHNRw1D3UFQB8oHB4uS/tAODO+ZLjGWmUbKnIlOWO+aaIiAxrUWHA==", + "license": "MIT", "engines": { - "node": ">=12" + "node": ">= 14.16.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" } }, - "node_modules/react-email/node_modules/@esbuild/linux-ia32": { - "version": "0.19.11", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.19.11.tgz", - "integrity": "sha512-caHy++CsD8Bgq2V5CodbJjFPEiDPq8JJmBdeyZ8GWVQMjRD0sU548nNdwPNvKjVpamYYVL40AORekgfIubwHoA==", - "cpu": [ - "ia32" - ], - "optional": true, - "os": [ - "linux" - ], + "node_modules/react-email/node_modules/socket.io": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.8.0.tgz", + "integrity": "sha512-8U6BEgGjQOfGz3HHTYaC/L1GaxDCJ/KM0XTkJly0EhZ5U/du9uNEZy4ZgYzEzIqlx2CMm25CrCqr1ck899eLNA==", + "license": "MIT", + "dependencies": { + "accepts": "~1.3.4", + "base64id": "~2.0.0", + "cors": "~2.8.5", + "debug": "~4.3.2", + "engine.io": "~6.6.0", + "socket.io-adapter": "~2.5.2", + "socket.io-parser": "~4.2.4" + }, "engines": { - "node": ">=12" + "node": ">=10.2.0" } }, - "node_modules/react-email/node_modules/@esbuild/linux-loong64": { - "version": "0.19.11", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.19.11.tgz", - "integrity": "sha512-ppZSSLVpPrwHccvC6nQVZaSHlFsvCQyjnvirnVjbKSHuE5N24Yl8F3UwYUUR1UEPaFObGD2tSvVKbvR+uT1Nrg==", - "cpu": [ - "loong64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" + "node_modules/react-promise-suspense": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/react-promise-suspense/-/react-promise-suspense-0.3.4.tgz", + "integrity": "sha512-I42jl7L3Ze6kZaq+7zXWSunBa3b1on5yfvUW6Eo/3fFOj6dZ5Bqmcd264nJbTK/gn1HjjILAjSwnZbV4RpSaNQ==", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^2.0.1" } }, - "node_modules/react-email/node_modules/@esbuild/linux-mips64el": { - "version": "0.19.11", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.19.11.tgz", - "integrity": "sha512-B5x9j0OgjG+v1dF2DkH34lr+7Gmv0kzX6/V0afF41FkPMMqaQ77pH7CrhWeR22aEeHKaeZVtZ6yFwlxOKPVFyg==", - "cpu": [ - "mips64el" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } + "node_modules/react-promise-suspense/node_modules/fast-deep-equal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha512-bCK/2Z4zLidyB4ReuIsvALH6w31YfAQDmXMqMx6FyfHqvBxtjC0eRumeSu4Bs3XtXwpyIywtSTrVT99BxY1f9w==", + "license": "MIT" }, - "node_modules/react-email/node_modules/@esbuild/linux-ppc64": { - "version": "0.19.11", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.19.11.tgz", - "integrity": "sha512-MHrZYLeCG8vXblMetWyttkdVRjQlQUb/oMgBNurVEnhj4YWOr4G5lmBfZjHYQHHN0g6yDmCAQRR8MUHldvvRDA==", - "cpu": [ - "ppc64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" + "node_modules/read-cache": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", + "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", + "license": "MIT", + "peer": true, + "dependencies": { + "pify": "^2.3.0" } }, - "node_modules/react-email/node_modules/@esbuild/linux-riscv64": { - "version": "0.19.11", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.19.11.tgz", - "integrity": "sha512-f3DY++t94uVg141dozDu4CCUkYW+09rWtaWfnb3bqe4w5NqmZd6nPVBm+qbz7WaHZCoqXqHz5p6CM6qv3qnSSQ==", - "cpu": [ - "riscv64" - ], - "optional": true, - "os": [ - "linux" - ], + "node_modules/read-pkg": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", + "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/normalize-package-data": "^2.4.0", + "normalize-package-data": "^2.5.0", + "parse-json": "^5.0.0", + "type-fest": "^0.6.0" + }, "engines": { - "node": ">=12" + "node": ">=8" } }, - "node_modules/react-email/node_modules/@esbuild/linux-s390x": { - "version": "0.19.11", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.19.11.tgz", - "integrity": "sha512-A5xdUoyWJHMMlcSMcPGVLzYzpcY8QP1RtYzX5/bS4dvjBGVxdhuiYyFwp7z74ocV7WDc0n1harxmpq2ePOjI0Q==", - "cpu": [ - "s390x" - ], - "optional": true, - "os": [ - "linux" - ], + "node_modules/read-pkg-up": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", + "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", + "dev": true, + "license": "MIT", + "dependencies": { + "find-up": "^4.1.0", + "read-pkg": "^5.2.0", + "type-fest": "^0.8.1" + }, "engines": { - "node": ">=12" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/react-email/node_modules/@esbuild/linux-x64": { - "version": "0.19.11", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.19.11.tgz", - "integrity": "sha512-grbyMlVCvJSfxFQUndw5mCtWs5LO1gUlwP4CDi4iJBbVpZcqLVT29FxgGuBJGSzyOxotFG4LoO5X+M1350zmPA==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "linux" - ], + "node_modules/read-pkg-up/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, "engines": { - "node": ">=12" + "node": ">=8" } }, - "node_modules/react-email/node_modules/@esbuild/netbsd-x64": { - "version": "0.19.11", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.19.11.tgz", - "integrity": "sha512-13jvrQZJc3P230OhU8xgwUnDeuC/9egsjTkXN49b3GcS5BKvJqZn86aGM8W9pd14Kd+u7HuFBMVtrNGhh6fHEQ==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "netbsd" - ], + "node_modules/read-pkg-up/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^4.1.0" + }, "engines": { - "node": ">=12" + "node": ">=8" } }, - "node_modules/react-email/node_modules/@esbuild/openbsd-x64": { - "version": "0.19.11", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.19.11.tgz", - "integrity": "sha512-ysyOGZuTp6SNKPE11INDUeFVVQFrhcNDVUgSQVDzqsqX38DjhPEPATpid04LCoUr2WXhQTEZ8ct/EgJCUDpyNw==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "openbsd" - ], + "node_modules/read-pkg-up/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, "engines": { - "node": ">=12" + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/react-email/node_modules/@esbuild/sunos-x64": { - "version": "0.19.11", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.19.11.tgz", - "integrity": "sha512-Hf+Sad9nVwvtxy4DXCZQqLpgmRTQqyFyhT3bZ4F2XlJCjxGmRFF0Shwn9rzhOYRB61w9VMXUkxlBy56dk9JJiQ==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "sunos" - ], + "node_modules/read-pkg-up/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^2.2.0" + }, "engines": { - "node": ">=12" + "node": ">=8" } }, - "node_modules/react-email/node_modules/@esbuild/win32-arm64": { - "version": "0.19.11", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.19.11.tgz", - "integrity": "sha512-0P58Sbi0LctOMOQbpEOvOL44Ne0sqbS0XWHMvvrg6NE5jQ1xguCSSw9jQeUk2lfrXYsKDdOe6K+oZiwKPilYPQ==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "win32" - ], + "node_modules/read-pkg-up/node_modules/type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true, + "license": "(MIT OR CC0-1.0)", "engines": { - "node": ">=12" + "node": ">=8" } }, - "node_modules/react-email/node_modules/@esbuild/win32-ia32": { - "version": "0.19.11", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.19.11.tgz", - "integrity": "sha512-6YOrWS+sDJDmshdBIQU+Uoyh7pQKrdykdefC1avn76ss5c+RN6gut3LZA4E2cH5xUEp5/cA0+YxRaVtRAb0xBg==", - "cpu": [ - "ia32" - ], - "optional": true, - "os": [ - "win32" - ], + "node_modules/read-pkg/node_modules/type-fest": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", + "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", + "dev": true, + "license": "(MIT OR CC0-1.0)", "engines": { - "node": ">=12" + "node": ">=8" } }, - "node_modules/react-email/node_modules/@esbuild/win32-x64": { - "version": "0.19.11", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.19.11.tgz", - "integrity": "sha512-vfkhltrjCAb603XaFhqhAF4LGDi2M4OrCRrFusyQ+iTLQ/o60QQXxc9cZC/FFpihBI9N1Grn6SMKVJ4KP7Fuiw==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "win32" - ], + "node_modules/readable-stream": { + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz", + "integrity": "sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==", + "license": "MIT", + "dependencies": { + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" + }, "engines": { - "node": ">=12" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, - "node_modules/react-email/node_modules/brace-expansion": { + "node_modules/readable-stream/node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/readdir-glob": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/readdir-glob/-/readdir-glob-1.1.3.tgz", + "integrity": "sha512-v05I2k7xN8zXvPD9N+z/uhXPaj0sUFCe2rcWZIpBsqxfP7xXFQ0tipAd/wjj1YxWyWtUS5IDJpOG82JKt2EAVA==", + "license": "Apache-2.0", + "dependencies": { + "minimatch": "^5.1.0" + } + }, + "node_modules/readdir-glob/node_modules/brace-expansion": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" } }, - "node_modules/react-email/node_modules/commander": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz", - "integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==", + "node_modules/readdir-glob/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, "engines": { - "node": ">=16" + "node": ">=10" } }, - "node_modules/react-email/node_modules/esbuild": { - "version": "0.19.11", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.11.tgz", - "integrity": "sha512-HJ96Hev2hX/6i5cDVwcqiJBBtuo9+FeIJOtZ9W1kA5M6AMJRHUZlpYZ1/SbEwtO0ioNAW8rUooVpC/WehY2SfA==", - "hasInstallScript": true, - "bin": { - "esbuild": "bin/esbuild" + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" }, "engines": { - "node": ">=12" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.19.11", - "@esbuild/android-arm": "0.19.11", - "@esbuild/android-arm64": "0.19.11", - "@esbuild/android-x64": "0.19.11", - "@esbuild/darwin-arm64": "0.19.11", - "@esbuild/darwin-x64": "0.19.11", - "@esbuild/freebsd-arm64": "0.19.11", - "@esbuild/freebsd-x64": "0.19.11", - "@esbuild/linux-arm": "0.19.11", - "@esbuild/linux-arm64": "0.19.11", - "@esbuild/linux-ia32": "0.19.11", - "@esbuild/linux-loong64": "0.19.11", - "@esbuild/linux-mips64el": "0.19.11", - "@esbuild/linux-ppc64": "0.19.11", - "@esbuild/linux-riscv64": "0.19.11", - "@esbuild/linux-s390x": "0.19.11", - "@esbuild/linux-x64": "0.19.11", - "@esbuild/netbsd-x64": "0.19.11", - "@esbuild/openbsd-x64": "0.19.11", - "@esbuild/sunos-x64": "0.19.11", - "@esbuild/win32-arm64": "0.19.11", - "@esbuild/win32-ia32": "0.19.11", - "@esbuild/win32-x64": "0.19.11" + "node": ">=8.10.0" } }, - "node_modules/react-email/node_modules/glob": { - "version": "10.3.4", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.4.tgz", - "integrity": "sha512-6LFElP3A+i/Q8XQKEvZjkEWEOTgAIALR9AO2rwT8bgPhDd1anmqDJDZ6lLddI4ehxxxR1S5RIqKe1uapMQfYaQ==", - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^2.0.3", - "minimatch": "^9.0.1", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", - "path-scurry": "^1.10.1" - }, - "bin": { - "glob": "dist/cjs/src/bin.js" - }, + "node_modules/readdirp/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "license": "MIT", "engines": { - "node": ">=16 || 14 >=14.17" + "node": ">=8.6" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/react-email/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dependencies": { - "brace-expansion": "^2.0.1" - }, + "node_modules/redis-errors": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/redis-errors/-/redis-errors-1.2.0.tgz", + "integrity": "sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w==", + "license": "MIT", "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": ">=4" } }, - "node_modules/react-promise-suspense": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/react-promise-suspense/-/react-promise-suspense-0.3.4.tgz", - "integrity": "sha512-I42jl7L3Ze6kZaq+7zXWSunBa3b1on5yfvUW6Eo/3fFOj6dZ5Bqmcd264nJbTK/gn1HjjILAjSwnZbV4RpSaNQ==", + "node_modules/redis-parser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-3.0.0.tgz", + "integrity": "sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A==", + "license": "MIT", "dependencies": { - "fast-deep-equal": "^2.0.1" + "redis-errors": "^1.0.0" + }, + "engines": { + "node": ">=4" } }, - "node_modules/react-promise-suspense/node_modules/fast-deep-equal": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", - "integrity": "sha512-bCK/2Z4zLidyB4ReuIsvALH6w31YfAQDmXMqMx6FyfHqvBxtjC0eRumeSu4Bs3XtXwpyIywtSTrVT99BxY1f9w==" + "node_modules/reflect-metadata": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.2.2.tgz", + "integrity": "sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==", + "license": "Apache-2.0" }, - "node_modules/read-cache": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", - "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", - "peer": true, - "dependencies": { - "pify": "^2.3.0" + "node_modules/regexp-tree": { + "version": "0.1.27", + "resolved": "https://registry.npmjs.org/regexp-tree/-/regexp-tree-0.1.27.tgz", + "integrity": "sha512-iETxpjK6YoRWJG5o6hXLwvjYAoW+FEZn9os0PD/b6AP6xQwsa/Y7lCVgIixBbUPMfhu+i2LtdeAqVTgGlQarfA==", + "dev": true, + "license": "MIT", + "bin": { + "regexp-tree": "bin/regexp-tree" } }, - "node_modules/read-pkg": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", - "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", + "node_modules/regjsparser": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.10.0.tgz", + "integrity": "sha512-qx+xQGZVsy55CH0a1hiVwHmqjLryfh7wQyF5HO07XJ9f7dQMY/gPQHhlyDkIzJKC+x2fUCpCcUODUUUFrm7SHA==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "@types/normalize-package-data": "^2.4.0", - "normalize-package-data": "^2.5.0", - "parse-json": "^5.0.0", - "type-fest": "^0.6.0" + "jsesc": "~0.5.0" }, - "engines": { - "node": ">=8" - } - }, - "node_modules/read-pkg-up": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", - "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", - "dev": true, - "dependencies": { - "find-up": "^4.1.0", - "read-pkg": "^5.2.0", - "type-fest": "^0.8.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/read-pkg-up/node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/read-pkg-up/node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/read-pkg-up/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/read-pkg-up/node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/read-pkg-up/node_modules/type-fest": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/read-pkg/node_modules/type-fest": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", - "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/readdir-glob": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/readdir-glob/-/readdir-glob-1.1.3.tgz", - "integrity": "sha512-v05I2k7xN8zXvPD9N+z/uhXPaj0sUFCe2rcWZIpBsqxfP7xXFQ0tipAd/wjj1YxWyWtUS5IDJpOG82JKt2EAVA==", - "dependencies": { - "minimatch": "^5.1.0" - } - }, - "node_modules/readdir-glob/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/readdir-glob/node_modules/minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/readdirp/node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/redis-errors": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/redis-errors/-/redis-errors-1.2.0.tgz", - "integrity": "sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w==", - "engines": { - "node": ">=4" - } - }, - "node_modules/redis-parser": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-3.0.0.tgz", - "integrity": "sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A==", - "dependencies": { - "redis-errors": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/reflect-metadata": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.2.2.tgz", - "integrity": "sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==" - }, - "node_modules/regexp-tree": { - "version": "0.1.27", - "resolved": "https://registry.npmjs.org/regexp-tree/-/regexp-tree-0.1.27.tgz", - "integrity": "sha512-iETxpjK6YoRWJG5o6hXLwvjYAoW+FEZn9os0PD/b6AP6xQwsa/Y7lCVgIixBbUPMfhu+i2LtdeAqVTgGlQarfA==", - "dev": true, - "bin": { - "regexp-tree": "bin/regexp-tree" - } - }, - "node_modules/regjsparser": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.10.0.tgz", - "integrity": "sha512-qx+xQGZVsy55CH0a1hiVwHmqjLryfh7wQyF5HO07XJ9f7dQMY/gPQHhlyDkIzJKC+x2fUCpCcUODUUUFrm7SHA==", - "dev": true, - "dependencies": { - "jsesc": "~0.5.0" - }, - "bin": { - "regjsparser": "bin/parser" + "bin": { + "regjsparser": "bin/parser" } }, "node_modules/regjsparser/node_modules/jsesc": { @@ -12364,6 +12554,7 @@ "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", "integrity": "sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10" } @@ -12372,6 +12563,7 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -12381,29 +12573,32 @@ "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/require-in-the-middle": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/require-in-the-middle/-/require-in-the-middle-7.2.0.tgz", - "integrity": "sha512-3TLx5TGyAY6AOqLBoXmHkNql0HIf2RGbuMgCDT2WO/uGVAPJs6h7Kl+bN6TIZGd9bWhWPwnDnTHGtW8Iu77sdw==", + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/require-in-the-middle/-/require-in-the-middle-7.4.0.tgz", + "integrity": "sha512-X34iHADNbNDfr6OTStIAHWSAvvKQRYgLO6duASaVf7J2VA3lvmNYboAHOuLC2huav1IwgZJtyEcJCKVzFxOSMQ==", + "license": "MIT", "dependencies": { - "debug": "^4.1.1", + "debug": "^4.3.5", "module-details-from-path": "^1.0.3", - "resolve": "^1.22.1" + "resolve": "^1.22.8" }, "engines": { "node": ">=8.6.0" } }, "node_modules/resolve": { - "version": "1.22.6", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.6.tgz", - "integrity": "sha512-njhxM7mV12JfufShqGy3Rz8j11RPdLy4xi15UurGJeoHLfJpVXKdh3ueuOqbYUcDZnffr6X739JBo5LzyahEsw==", + "version": "1.22.9", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.9.tgz", + "integrity": "sha512-QxrmX1DzraFIi9PxdG5VkRfRwIgjwyud+z/iBwfRRrVmHc+P9Q7u2lSSpQ6bjr2gy5lrqIiU9vb6iAeGf2400A==", + "license": "MIT", "dependencies": { - "is-core-module": "^2.13.0", + "is-core-module": "^2.16.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, @@ -12418,6 +12613,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "license": "MIT", "engines": { "node": ">=4" } @@ -12426,34 +12622,29 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/resolve-protobuf-schema/-/resolve-protobuf-schema-2.1.0.tgz", "integrity": "sha512-kI5ffTiZWmJaS/huM8wZfEMer1eRd7oJQhDuxeCLe3t7N7mX3z94CN0xPxBQxFYQTSNz9T0i+v6inKqSdK8xrQ==", + "license": "MIT", "dependencies": { "protocol-buffers-schema": "^3.3.1" } }, "node_modules/response-time": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/response-time/-/response-time-2.3.2.tgz", - "integrity": "sha512-MUIDaDQf+CVqflfTdQ5yam+aYCkXj1PY8fjlPDQ6ppxJlmgZb864pHtA750mayywNg8tx4rS7qH9JXd/OF+3gw==", + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/response-time/-/response-time-2.3.3.tgz", + "integrity": "sha512-SsjjOPHl/FfrTQNgmc5oen8Hr1Jxpn6LlHNXxCIFdYMHuK1kMeYMobb9XN3mvxaGQm3dbegqYFMX4+GDORfbWg==", + "license": "MIT", "dependencies": { - "depd": "~1.1.0", + "depd": "~2.0.0", "on-headers": "~1.0.1" }, "engines": { "node": ">= 0.8.0" } }, - "node_modules/response-time/node_modules/depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", - "engines": { - "node": ">= 0.6" - } - }, "node_modules/restore-cursor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "license": "MIT", "dependencies": { "onetime": "^5.1.0", "signal-exit": "^3.0.2" @@ -12465,13 +12656,15 @@ "node_modules/restore-cursor/node_modules/signal-exit": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "license": "ISC" }, "node_modules/ret": { "version": "0.1.15", "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.12" } @@ -12481,6 +12674,7 @@ "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", "dev": true, + "license": "MIT", "engines": { "node": ">= 4" } @@ -12489,6 +12683,7 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "license": "MIT", "engines": { "iojs": ">=1.0.0", "node": ">=0.10.0" @@ -12499,6 +12694,7 @@ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-6.0.1.tgz", "integrity": "sha512-9dkvaxAsk/xNXSJzMgFqqMCuFgt2+KsOFek3TMLfo8NCPfWpBmqwyNn5Y+NX56QUYfCtsyhF3ayiboEoUmJk/A==", "dev": true, + "license": "ISC", "dependencies": { "glob": "^11.0.0", "package-json-from-dist": "^1.0.0" @@ -12518,6 +12714,7 @@ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" } @@ -12527,6 +12724,7 @@ "resolved": "https://registry.npmjs.org/glob/-/glob-11.0.0.tgz", "integrity": "sha512-9UiX/Bl6J2yaBbxKoEBRm4Cipxgok8kQYcOPEhScPwebu2I0HoQOuYdIO6S3hLuWoZgpDpwQZMzTFxgpkyT76g==", "dev": true, + "license": "ISC", "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^4.0.1", @@ -12546,10 +12744,11 @@ } }, "node_modules/rimraf/node_modules/jackspeak": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.0.1.tgz", - "integrity": "sha512-cub8rahkh0Q/bw1+GxP7aeSe29hHHn2V4m29nnDlvCdlgU+3UGxkZp7Z53jLUdpX3jdTO0nJZUDl3xvbWc2Xog==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.0.2.tgz", + "integrity": "sha512-bZsjR/iRjl1Nk1UkjGpAzLNfQtzuijhn2g+pbZb98HQ1Gk8vM9hfbxeMBP+M2/UUdwj0RqGG3mlvk2MsAqwvEw==", "dev": true, + "license": "BlueOak-1.0.0", "dependencies": { "@isaacs/cliui": "^8.0.2" }, @@ -12558,16 +12757,14 @@ }, "funding": { "url": "https://github.com/sponsors/isaacs" - }, - "optionalDependencies": { - "@pkgjs/parseargs": "^0.11.0" } }, "node_modules/rimraf/node_modules/lru-cache": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.0.0.tgz", - "integrity": "sha512-Qv32eSV1RSCfhY3fpPE2GNZ8jgM9X7rdAfemLWqTUxwiyIC4jJ6Sy0fZ8H+oLWevO6i4/bizg7c8d8i6bxrzbA==", + "version": "11.0.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.0.2.tgz", + "integrity": "sha512-123qHRfJBmo2jXDbo/a5YOQrJoHF/GNQTLzQ5+IdK5pWpceK17yRc6ozlWd25FxvGKQbIUs91fDFkXmDHTKcyA==", "dev": true, + "license": "ISC", "engines": { "node": "20 || >=22" } @@ -12577,6 +12774,7 @@ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.1.tgz", "integrity": "sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" }, @@ -12592,6 +12790,7 @@ "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.0.tgz", "integrity": "sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==", "dev": true, + "license": "BlueOak-1.0.0", "dependencies": { "lru-cache": "^11.0.0", "minipass": "^7.1.2" @@ -12603,13 +12802,20 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/robust-predicates": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/robust-predicates/-/robust-predicates-3.0.2.tgz", + "integrity": "sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg==", + "license": "Unlicense" + }, "node_modules/rollup": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.22.4.tgz", - "integrity": "sha512-vD8HJ5raRcWOyymsR6Z3o6+RzfEPCnVLMFJ6vRslO1jt4LO6dUo5Qnpg7y4RkZFM2DMe3WUirkI5c16onjrc6A==", + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.28.1.tgz", + "integrity": "sha512-61fXYl/qNVinKmGSTHAZ6Yy8I3YIJC/r2m9feHo6SwVAVcLT5MPwOUFe7EuURA/4m0NR8lXG4BBXuo/IZEsjMg==", "dev": true, + "license": "MIT", "dependencies": { - "@types/estree": "1.0.5" + "@types/estree": "1.0.6" }, "bin": { "rollup": "dist/bin/rollup" @@ -12619,22 +12825,25 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.22.4", - "@rollup/rollup-android-arm64": "4.22.4", - "@rollup/rollup-darwin-arm64": "4.22.4", - "@rollup/rollup-darwin-x64": "4.22.4", - "@rollup/rollup-linux-arm-gnueabihf": "4.22.4", - "@rollup/rollup-linux-arm-musleabihf": "4.22.4", - "@rollup/rollup-linux-arm64-gnu": "4.22.4", - "@rollup/rollup-linux-arm64-musl": "4.22.4", - "@rollup/rollup-linux-powerpc64le-gnu": "4.22.4", - "@rollup/rollup-linux-riscv64-gnu": "4.22.4", - "@rollup/rollup-linux-s390x-gnu": "4.22.4", - "@rollup/rollup-linux-x64-gnu": "4.22.4", - "@rollup/rollup-linux-x64-musl": "4.22.4", - "@rollup/rollup-win32-arm64-msvc": "4.22.4", - "@rollup/rollup-win32-ia32-msvc": "4.22.4", - "@rollup/rollup-win32-x64-msvc": "4.22.4", + "@rollup/rollup-android-arm-eabi": "4.28.1", + "@rollup/rollup-android-arm64": "4.28.1", + "@rollup/rollup-darwin-arm64": "4.28.1", + "@rollup/rollup-darwin-x64": "4.28.1", + "@rollup/rollup-freebsd-arm64": "4.28.1", + "@rollup/rollup-freebsd-x64": "4.28.1", + "@rollup/rollup-linux-arm-gnueabihf": "4.28.1", + "@rollup/rollup-linux-arm-musleabihf": "4.28.1", + "@rollup/rollup-linux-arm64-gnu": "4.28.1", + "@rollup/rollup-linux-arm64-musl": "4.28.1", + "@rollup/rollup-linux-loongarch64-gnu": "4.28.1", + "@rollup/rollup-linux-powerpc64le-gnu": "4.28.1", + "@rollup/rollup-linux-riscv64-gnu": "4.28.1", + "@rollup/rollup-linux-s390x-gnu": "4.28.1", + "@rollup/rollup-linux-x64-gnu": "4.28.1", + "@rollup/rollup-linux-x64-musl": "4.28.1", + "@rollup/rollup-win32-arm64-msvc": "4.28.1", + "@rollup/rollup-win32-ia32-msvc": "4.28.1", + "@rollup/rollup-win32-x64-msvc": "4.28.1", "fsevents": "~2.3.2" } }, @@ -12642,6 +12851,7 @@ "version": "2.4.1", "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", + "license": "MIT", "engines": { "node": ">=0.12.0" } @@ -12664,6 +12874,7 @@ "url": "https://feross.org/support" } ], + "license": "MIT", "dependencies": { "queue-microtask": "^1.2.2" } @@ -12672,6 +12883,7 @@ "version": "7.8.1", "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", + "license": "Apache-2.0", "dependencies": { "tslib": "^2.1.0" } @@ -12693,35 +12905,37 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "MIT" }, "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" }, "node_modules/sanitize-filename": { "version": "1.6.3", "resolved": "https://registry.npmjs.org/sanitize-filename/-/sanitize-filename-1.6.3.tgz", "integrity": "sha512-y/52Mcy7aw3gRm7IrcGDFx/bCk4AhRh2eI9luHOQM86nZsqwiRkkq2GekHXBBD+SmPidc8i2PqtYZl+pWJ8Oeg==", + "license": "WTFPL OR ISC", "dependencies": { "truncate-utf8-bytes": "^1.0.0" } }, "node_modules/scheduler": { - "version": "0.23.2", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", - "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", - "peer": true, - "dependencies": { - "loose-envify": "^1.1.0" - } + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.25.0.tgz", + "integrity": "sha512-xFVuu11jh+xcO7JOAGJNOXld8/TcEHK/4CituBUeUb5hqxJLj9YuemAEuvm9gQ/+pgXYfbQuqAkiYu+u7YEsNA==", + "license": "MIT", + "peer": true }, "node_modules/schema-utils": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", "dev": true, + "license": "MIT", "dependencies": { "@types/json-schema": "^7.0.8", "ajv": "^6.12.5", @@ -12735,52 +12949,23 @@ "url": "https://opencollective.com/webpack" } }, - "node_modules/schema-utils/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, + "node_modules/selderee": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/selderee/-/selderee-0.11.0.tgz", + "integrity": "sha512-5TF+l7p4+OsnP8BCCvSyZiSPc4x4//p5uPwK8TCnVPJYRmU2aYKMpOXvw8zM5a5JvuuCGN1jmsMwuU2W02ukfA==", + "license": "MIT", "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" + "parseley": "^0.12.0" }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/schema-utils/node_modules/ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true, - "peerDependencies": { - "ajv": "^6.9.1" - } - }, - "node_modules/schema-utils/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "node_modules/selderee": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/selderee/-/selderee-0.11.0.tgz", - "integrity": "sha512-5TF+l7p4+OsnP8BCCvSyZiSPc4x4//p5uPwK8TCnVPJYRmU2aYKMpOXvw8zM5a5JvuuCGN1jmsMwuU2W02ukfA==", - "dependencies": { - "parseley": "^0.12.0" - }, - "funding": { - "url": "https://ko-fi.com/killymxi" + "url": "https://ko-fi.com/killymxi" } }, "node_modules/semver": { "version": "7.6.3", "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "license": "ISC", "bin": { "semver": "bin/semver.js" }, @@ -12792,6 +12977,7 @@ "version": "0.19.0", "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", + "license": "MIT", "dependencies": { "debug": "2.6.9", "depd": "2.0.0", @@ -12815,6 +13001,7 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", "dependencies": { "ms": "2.0.0" } @@ -12822,12 +13009,14 @@ "node_modules/send/node_modules/debug/node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" }, "node_modules/send/node_modules/encodeurl": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "license": "MIT", "engines": { "node": ">= 0.8" } @@ -12837,6 +13026,7 @@ "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "randombytes": "^2.1.0" } @@ -12845,6 +13035,7 @@ "version": "1.16.2", "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", + "license": "MIT", "dependencies": { "encodeurl": "~2.0.0", "escape-html": "~1.0.3", @@ -12858,19 +13049,22 @@ "node_modules/set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==" + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", + "license": "ISC" }, "node_modules/set-function-length": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.1.tgz", - "integrity": "sha512-j4t6ccc+VsKwYHso+kElc5neZpjtq9EnRICFZtWyBsLojhmeF/ZBd/elqm22WJh/BziDe/SBiOeAt0m2mfLD0g==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dev": true, + "license": "MIT", "dependencies": { - "define-data-property": "^1.1.2", + "define-data-property": "^1.1.4", "es-errors": "^1.3.0", "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.3", + "get-intrinsic": "^1.2.4", "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.1" + "has-property-descriptors": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -12879,12 +13073,14 @@ "node_modules/setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "license": "ISC" }, "node_modules/sha.js": { "version": "2.4.11", "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "license": "(MIT AND BSD-3-Clause)", "dependencies": { "inherits": "^2.0.1", "safe-buffer": "^5.0.1" @@ -12897,6 +13093,7 @@ "version": "0.6.6", "resolved": "https://registry.npmjs.org/shapefile/-/shapefile-0.6.6.tgz", "integrity": "sha512-rLGSWeK2ufzCVx05wYd+xrWnOOdSV7xNUW5/XFgx3Bc02hBkpMlrd2F1dDII7/jhWzv0MSyBFh5uJIy9hLdfuw==", + "license": "BSD-3-Clause", "dependencies": { "array-source": "0.0", "commander": "2", @@ -12913,13 +13110,15 @@ "node_modules/shapefile/node_modules/commander": { "version": "2.20.3", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "license": "MIT" }, "node_modules/sharp": { "version": "0.33.5", "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.33.5.tgz", "integrity": "sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw==", "hasInstallScript": true, + "license": "Apache-2.0", "dependencies": { "color": "^4.2.3", "detect-libc": "^2.0.3", @@ -12957,6 +13156,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "license": "MIT", "dependencies": { "shebang-regex": "^3.0.0" }, @@ -12968,6 +13168,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "license": "MIT", "engines": { "node": ">=8" } @@ -12975,17 +13176,73 @@ "node_modules/shimmer": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/shimmer/-/shimmer-1.2.1.tgz", - "integrity": "sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw==" + "integrity": "sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw==", + "license": "BSD-2-Clause" }, "node_modules/side-channel": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", - "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4", - "object-inspect": "^1.13.1" + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" }, "engines": { "node": ">= 0.4" @@ -12998,12 +13255,14 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/signal-exit": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "license": "ISC", "engines": { "node": ">=14" }, @@ -13015,6 +13274,7 @@ "version": "0.2.2", "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==", + "license": "MIT", "dependencies": { "is-arrayish": "^0.3.1" } @@ -13022,12 +13282,14 @@ "node_modules/simple-swizzle/node_modules/is-arrayish": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", - "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==" + "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==", + "license": "MIT" }, "node_modules/sirv": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/sirv/-/sirv-3.0.0.tgz", "integrity": "sha512-BPwJGUeDaDCHihkORDchNyyTvWFhcusy1XMmhEVTQTwGeybFbp8YEmB+njbPnth1FibULBSBVwCQni25XlCUDg==", + "license": "MIT", "dependencies": { "@polka/url": "^1.0.0-next.24", "mrmime": "^2.0.0", @@ -13040,18 +13302,20 @@ "node_modules/slice-source": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/slice-source/-/slice-source-0.4.1.tgz", - "integrity": "sha512-YiuPbxpCj4hD9Qs06hGAz/OZhQ0eDuALN0lRWJez0eD/RevzKqGdUx1IOMUnXgpr+sXZLq3g8ERwbAH0bCb8vg==" + "integrity": "sha512-YiuPbxpCj4hD9Qs06hGAz/OZhQ0eDuALN0lRWJez0eD/RevzKqGdUx1IOMUnXgpr+sXZLq3g8ERwbAH0bCb8vg==", + "license": "BSD-3-Clause" }, "node_modules/socket.io": { - "version": "4.7.5", - "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.7.5.tgz", - "integrity": "sha512-DmeAkF6cwM9jSfmp6Dr/5/mfMwb5Z5qRrSXLpo3Fq5SqyU8CMF15jIN4ZhfSwu35ksM1qmHZDQ/DK5XTccSTvA==", + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.8.1.tgz", + "integrity": "sha512-oZ7iUCxph8WYRHHcjBEc9unw3adt5CmSNlppj/5Q4k2RIrhl8Z5yY2Xr4j9zj0+wzVZ0bxmYoGSzKJnRl6A4yg==", + "license": "MIT", "dependencies": { "accepts": "~1.3.4", "base64id": "~2.0.0", "cors": "~2.8.5", "debug": "~4.3.2", - "engine.io": "~6.5.2", + "engine.io": "~6.6.0", "socket.io-adapter": "~2.5.2", "socket.io-parser": "~4.2.4" }, @@ -13063,15 +13327,34 @@ "version": "2.5.5", "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.5.tgz", "integrity": "sha512-eLDQas5dzPgOWCk9GuuJC2lBqItuhKI4uxGgo9aIV7MYbk2h9Q6uULEh8WBzThoI7l+qU9Ast9fVUmkqPP9wYg==", + "license": "MIT", "dependencies": { "debug": "~4.3.4", "ws": "~8.17.1" } }, + "node_modules/socket.io-adapter/node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, "node_modules/socket.io-parser": { "version": "4.2.4", "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz", "integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==", + "license": "MIT", "dependencies": { "@socket.io/component-emitter": "~3.1.0", "debug": "~4.3.1" @@ -13080,11 +13363,46 @@ "node": ">=10.0.0" } }, + "node_modules/socket.io-parser/node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/socket.io/node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, "node_modules/source-map": { "version": "0.7.4", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", "dev": true, + "license": "BSD-3-Clause", "engines": { "node": ">= 8" } @@ -13093,6 +13411,7 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" } @@ -13102,6 +13421,7 @@ "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", "dev": true, + "license": "MIT", "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" @@ -13112,6 +13432,7 @@ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true, + "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" } @@ -13121,52 +13442,59 @@ "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", "dev": true, + "license": "Apache-2.0", "dependencies": { "spdx-expression-parse": "^3.0.0", "spdx-license-ids": "^3.0.0" } }, "node_modules/spdx-exceptions": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.4.0.tgz", - "integrity": "sha512-hcjppoJ68fhxA/cjbN4T8N6uCUejN8yFw69ttpqtBeCbF3u13n7mb31NB9jKwGTTWWnt9IbRA/mf1FprYS8wfw==", - "dev": true + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", + "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==", + "dev": true, + "license": "CC-BY-3.0" }, "node_modules/spdx-expression-parse": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", "dev": true, + "license": "MIT", "dependencies": { "spdx-exceptions": "^2.1.0", "spdx-license-ids": "^3.0.0" } }, "node_modules/spdx-license-ids": { - "version": "3.0.16", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.16.tgz", - "integrity": "sha512-eWN+LnM3GR6gPu35WxNgbGl8rmY1AEmoMDvL/QD6zYmPWgywxWqJWNdLGT+ke8dKNWrcYgYjPpG5gbTfghP8rw==", - "dev": true + "version": "3.0.20", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.20.tgz", + "integrity": "sha512-jg25NiDV/1fLtSgEgyvVyDunvaNHbuwF9lfNV17gSmPFAlYzdfNBlLtLzXTevwkPj7DhGbmN9VnmJIgLnhvaBw==", + "dev": true, + "license": "CC0-1.0" }, "node_modules/split-ca": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/split-ca/-/split-ca-1.0.1.tgz", "integrity": "sha512-Q5thBSxp5t8WPTTJQS59LrGqOZqOsrhDGDVm8azCqIBjSBd7nd9o2PM+mDulQQkh8h//4U6hFZnc/mul8t5pWQ==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/split2": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", + "license": "ISC", "engines": { "node": ">= 10.x" } }, "node_modules/sql-formatter": { - "version": "15.4.5", - "resolved": "https://registry.npmjs.org/sql-formatter/-/sql-formatter-15.4.5.tgz", - "integrity": "sha512-dxYn0OzEmB19/9Y+yh8bqD8kJx2S/4pOTM4QLKxQDh7K6lp1Sx9MhmiF9RUJHSVjfV72KihW5R1h6Kecy6O5qA==", + "version": "15.4.6", + "resolved": "https://registry.npmjs.org/sql-formatter/-/sql-formatter-15.4.6.tgz", + "integrity": "sha512-aH6kwvJpylljHqXe+zpie0Q5snL3uerDLLhjPEBjDCVK1NMRFq4nMJbuPJWYp08LaaaJJgBhShAdAfspcBYY0Q==", "dev": true, + "license": "MIT", "dependencies": { "argparse": "^2.0.1", "get-stdin": "=8.0.0", @@ -13181,15 +13509,27 @@ "resolved": "https://registry.npmjs.org/ssh-remote-port-forward/-/ssh-remote-port-forward-1.0.4.tgz", "integrity": "sha512-x0LV1eVDwjf1gmG7TTnfqIzf+3VPRz7vrNIjX6oYLbeCrf/PeVY6hkT68Mg+q02qXxQhrLjB0jfgvhevoCRmLQ==", "dev": true, + "license": "MIT", "dependencies": { "@types/ssh2": "^0.5.48", "ssh2": "^1.4.0" } }, + "node_modules/ssh-remote-port-forward/node_modules/@types/ssh2": { + "version": "0.5.52", + "resolved": "https://registry.npmjs.org/@types/ssh2/-/ssh2-0.5.52.tgz", + "integrity": "sha512-lbLLlXxdCZOSJMCInKH2+9V/77ET2J6NPQHpFI0kda61Dd1KglJs+fPQBchizmzYSOJBgdTajhPqBO1xxLywvg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "@types/ssh2-streams": "*" + } + }, "node_modules/ssh2": { - "version": "1.14.0", - "resolved": "https://registry.npmjs.org/ssh2/-/ssh2-1.14.0.tgz", - "integrity": "sha512-AqzD1UCqit8tbOKoj6ztDDi1ffJZ2rV2SwlgrVVrHPkV5vWqGJOVp5pmtj18PunkPJAuKQsnInyKV+/Nb2bUnA==", + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/ssh2/-/ssh2-1.16.0.tgz", + "integrity": "sha512-r1X4KsBGedJqo7h8F5c4Ybpcr5RjyP+aWIG007uBPRjmdQWfEiVLzSK71Zji1B9sKxwaCvD8y8cwSkYrlLiRRg==", "dev": true, "hasInstallScript": true, "dependencies": { @@ -13200,39 +13540,44 @@ "node": ">=10.16.0" }, "optionalDependencies": { - "cpu-features": "~0.0.8", - "nan": "^2.17.0" + "cpu-features": "~0.0.10", + "nan": "^2.20.0" } }, "node_modules/stackback": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/standard-as-callback": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/standard-as-callback/-/standard-as-callback-2.1.0.tgz", - "integrity": "sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A==" + "integrity": "sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A==", + "license": "MIT" }, "node_modules/statuses": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "license": "MIT", "engines": { "node": ">= 0.8" } }, "node_modules/std-env": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.7.0.tgz", - "integrity": "sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg==", - "dev": true + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.8.0.tgz", + "integrity": "sha512-Bc3YwwCB+OzldMxOXJIIvC6cPRWr/LxOp48CdQTOkPyk/t4JWWJbrilwBd7RJzKV8QW7tJkcgAmeuLLJugl5/w==", + "dev": true, + "license": "MIT" }, "node_modules/stream-source": { "version": "0.3.5", "resolved": "https://registry.npmjs.org/stream-source/-/stream-source-0.3.5.tgz", - "integrity": "sha512-ZuEDP9sgjiAwUVoDModftG0JtYiLUV8K4ljYD1VyUMRWtbVf92474o4kuuul43iZ8t/hRuiDAx1dIJSvirrK/g==" + "integrity": "sha512-ZuEDP9sgjiAwUVoDModftG0JtYiLUV8K4ljYD1VyUMRWtbVf92474o4kuuul43iZ8t/hRuiDAx1dIJSvirrK/g==", + "license": "BSD-3-Clause" }, "node_modules/streamsearch": { "version": "1.1.0", @@ -13243,9 +13588,10 @@ } }, "node_modules/streamx": { - "version": "2.18.0", - "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.18.0.tgz", - "integrity": "sha512-LLUC1TWdjVdn1weXGcSxyTR3T4+acB6tVGXT95y0nGbca4t4o/ng1wKAGTljm9VicuCVLvRlqFYXYy5GwgM7sQ==", + "version": "2.21.1", + "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.21.1.tgz", + "integrity": "sha512-PhP9wUnFLa+91CPy3N6tiQsK+gnYyUNuk15S3YG/zjYE7RuPeCjJngqnzpC31ow0lzBHQ+QGO4cNJnd0djYUsw==", + "license": "MIT", "dependencies": { "fast-fifo": "^1.3.2", "queue-tick": "^1.0.1", @@ -13259,6 +13605,7 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "license": "MIT", "dependencies": { "safe-buffer": "~5.2.0" } @@ -13267,6 +13614,7 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -13281,6 +13629,7 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -13294,6 +13643,7 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" }, @@ -13306,6 +13656,7 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" }, @@ -13313,11 +13664,22 @@ "node": ">=8" } }, + "node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/strip-indent": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", "dev": true, + "license": "MIT", "dependencies": { "min-indent": "^1.0.0" }, @@ -13330,6 +13692,7 @@ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" }, @@ -13338,9 +13701,10 @@ } }, "node_modules/styled-jsx": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.1.tgz", - "integrity": "sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw==", + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.6.tgz", + "integrity": "sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA==", + "license": "MIT", "dependencies": { "client-only": "0.0.1" }, @@ -13348,7 +13712,7 @@ "node": ">= 12.0.0" }, "peerDependencies": { - "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0" + "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0 || ^19.0.0-0" }, "peerDependenciesMeta": { "@babel/core": { @@ -13363,6 +13727,7 @@ "version": "3.35.0", "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz", "integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==", + "license": "MIT", "peer": true, "dependencies": { "@jridgewell/gen-mapping": "^0.3.2", @@ -13385,6 +13750,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, @@ -13396,6 +13762,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -13404,24 +13771,30 @@ } }, "node_modules/swagger-ui-dist": { - "version": "5.17.14", - "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-5.17.14.tgz", - "integrity": "sha512-CVbSfaLpstV65OnSjbXfVd6Sta3q3F7Cj/yYuvHMp1P90LztOLs6PfUnKEVAeiIVQt9u2SaPwv0LiH/OyMjHRw==" + "version": "5.18.2", + "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-5.18.2.tgz", + "integrity": "sha512-J+y4mCw/zXh1FOj5wGJvnAajq6XgHOyywsa9yITmwxIlJbMqITq3gYRZHaeqLVH/eV/HOPphE6NjF+nbSNC5Zw==", + "license": "Apache-2.0", + "dependencies": { + "@scarf/scarf": "=1.4.0" + } }, "node_modules/symbol-observable": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-4.0.0.tgz", "integrity": "sha512-b19dMThMV4HVFynSAM1++gBHAbk2Tc/osgLIBZMKsyqh34jb2e8Os7T6ZW/Bt3pJFdBTd2JwAnAAEQV7rSNvcQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10" } }, "node_modules/synckit": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.9.1.tgz", - "integrity": "sha512-7gr8p9TQP6RAHusBOSLs46F4564ZrjV8xFmw5zCmgmhGUcw2hxsShhJ6CEiHQMgPDwAQ1fWHPM0ypc4RMAig4A==", + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.9.2.tgz", + "integrity": "sha512-vrozgXDQwYO72vHjUb/HnFbQx1exDjoKzqx23aXEg2a9VIg2TSFZ8FmeZpTjUCFMYw7mpX4BE2SFu8wI7asYsw==", "dev": true, + "license": "MIT", "dependencies": { "@pkgr/core": "^0.1.0", "tslib": "^2.6.2" @@ -13434,9 +13807,10 @@ } }, "node_modules/systeminformation": { - "version": "5.22.0", - "resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.22.0.tgz", - "integrity": "sha512-oAP80ymt8ssrAzjX8k3frbL7ys6AotqC35oikG6/SG15wBw+tG9nCk4oPaXIhEaAOAZ8XngxUv3ORq2IuR3r4Q==", + "version": "5.22.9", + "resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.22.9.tgz", + "integrity": "sha512-qUWJhQ9JSBhdjzNUQywpvc0icxUAjMY3sZqUoS0GOtaJV9Ijq8s9zEP8Gaqmymn1dOefcICyPXK1L3kgKxlUpg==", + "license": "MIT", "os": [ "darwin", "linux", @@ -13459,33 +13833,34 @@ } }, "node_modules/tailwindcss": { - "version": "3.4.6", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.6.tgz", - "integrity": "sha512-1uRHzPB+Vzu57ocybfZ4jh5Q3SdlH7XW23J5sQoM9LhE9eIOlzxer/3XPSsycvih3rboRsvt0QCmzSrqyOYUIA==", + "version": "3.4.17", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.17.tgz", + "integrity": "sha512-w33E2aCvSDP0tW9RZuNXadXlkHXqFzSkQew/aIa2i/Sj8fThxwovwlXHSPXTbAHwEIhBFXAedUhP2tueAKP8Og==", + "license": "MIT", "peer": true, "dependencies": { "@alloc/quick-lru": "^5.2.0", "arg": "^5.0.2", - "chokidar": "^3.5.3", + "chokidar": "^3.6.0", "didyoumean": "^1.2.2", "dlv": "^1.1.3", - "fast-glob": "^3.3.0", + "fast-glob": "^3.3.2", "glob-parent": "^6.0.2", "is-glob": "^4.0.3", - "jiti": "^1.21.0", - "lilconfig": "^2.1.0", - "micromatch": "^4.0.5", + "jiti": "^1.21.6", + "lilconfig": "^3.1.3", + "micromatch": "^4.0.8", "normalize-path": "^3.0.0", "object-hash": "^3.0.0", - "picocolors": "^1.0.0", - "postcss": "^8.4.23", + "picocolors": "^1.1.1", + "postcss": "^8.4.47", "postcss-import": "^15.1.0", "postcss-js": "^4.0.1", - "postcss-load-config": "^4.0.1", - "postcss-nested": "^6.0.1", - "postcss-selector-parser": "^6.0.11", - "resolve": "^1.22.2", - "sucrase": "^3.32.0" + "postcss-load-config": "^4.0.2", + "postcss-nested": "^6.2.0", + "postcss-selector-parser": "^6.1.2", + "resolve": "^1.22.8", + "sucrase": "^3.35.0" }, "bin": { "tailwind": "lib/cli.js", @@ -13496,9 +13871,10 @@ } }, "node_modules/tailwindcss-email-variants": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/tailwindcss-email-variants/-/tailwindcss-email-variants-3.0.1.tgz", - "integrity": "sha512-bRk4R2jnfaW7BBaL2kDgOdBl0SpVP/JPDE/yCkZb1n3YrPK9ZQyQGZoVX3OX06GxjMOrNO3wZACVdHJce7dm8w==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/tailwindcss-email-variants/-/tailwindcss-email-variants-3.0.3.tgz", + "integrity": "sha512-gchBYFNprLfRtmxnrglF4tayxFbv+hBV+3obXQycrBcluLj5CQF8uJsZH6ir0aIGQXfh5ukMdIkEgKOBzrBYxA==", + "license": "MIT", "engines": { "node": ">=18" }, @@ -13507,35 +13883,32 @@ } }, "node_modules/tailwindcss-mso": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/tailwindcss-mso/-/tailwindcss-mso-1.4.3.tgz", - "integrity": "sha512-8YfZ4xnIComDrhoSr8FUwm7EGz1FkxsZy07Fs4Jm/JxHrFiubdiZjyxLuHMc3S8o02+U4fjRGHPOzoVXRus10A==", + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/tailwindcss-mso/-/tailwindcss-mso-1.4.4.tgz", + "integrity": "sha512-bSA7vLRhkaHjFhKkKNgr1RyOn2YhaEJ2hQQOCV7MgRtQOvYkqfAYMTSoZ2Z1YgCvOD02W4Tazsz+ym6FiPFIjQ==", + "license": "MIT", "peerDependencies": { "tailwindcss": ">=3.4.0" } }, "node_modules/tailwindcss-preset-email": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/tailwindcss-preset-email/-/tailwindcss-preset-email-1.3.2.tgz", - "integrity": "sha512-kSPNZM5+tSi+uhCb4rk1XF9Q6zp8lhoNLCa3GQqe6gKmfI/nTqY8Y+5/DYNpwqhmUPCSHULlyI/LUCaF/q8sLg==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/tailwindcss-preset-email/-/tailwindcss-preset-email-1.3.3.tgz", + "integrity": "sha512-eB/qZrW9YPIDsGU2Spszbu+iBC3MdlZNqzkp85lBg1P/Dgxn7XWrfMt/46L6bTlmznr0zeMpgrMMOkuucJL7qQ==", + "license": "MIT", "dependencies": { - "tailwindcss-email-variants": "^3.0.0", - "tailwindcss-mso": "^1.4.3" + "tailwindcss-email-variants": "^3.0.2", + "tailwindcss-mso": "^1.4.4" }, "peerDependencies": { - "tailwindcss": ">=3.4.6" + "tailwindcss": ">=3.4.15" } }, - "node_modules/tailwindcss/node_modules/arg": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", - "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", - "peer": true - }, "node_modules/tailwindcss/node_modules/glob-parent": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "license": "ISC", "peer": true, "dependencies": { "is-glob": "^4.0.3" @@ -13544,11 +13917,41 @@ "node": ">=10.13.0" } }, + "node_modules/tailwindcss/node_modules/postcss": { + "version": "8.4.49", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.49.tgz", + "integrity": "sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "peer": true, + "dependencies": { + "nanoid": "^3.3.7", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, "node_modules/tapable": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -13557,6 +13960,7 @@ "version": "6.2.1", "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", + "license": "ISC", "dependencies": { "chownr": "^2.0.0", "fs-minipass": "^2.0.0", @@ -13574,6 +13978,7 @@ "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.0.6.tgz", "integrity": "sha512-iokBDQQkUyeXhgPYaZxmczGPhnhXZ0CmrqI+MOb/WFGS9DW5wnfrLgtjUJBvz50vQ3qfRwJ62QVoCFu8mPVu5w==", "dev": true, + "license": "MIT", "dependencies": { "pump": "^3.0.0", "tar-stream": "^3.1.5" @@ -13584,9 +13989,10 @@ } }, "node_modules/tar-stream": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-3.1.6.tgz", - "integrity": "sha512-B/UyjYwPpMBv+PaFSWAmtYjwdrlEaZQEhMIBFNC5oEG8lpiW8XjcSdmEaClj28ArfKScKHs2nshz3k2le6crsg==", + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-3.1.7.tgz", + "integrity": "sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==", + "license": "MIT", "dependencies": { "b4a": "^1.6.4", "fast-fifo": "^1.2.0", @@ -13597,6 +14003,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "license": "ISC", "engines": { "node": ">=8" } @@ -13605,6 +14012,7 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "license": "MIT", "bin": { "mkdirp": "bin/cmd.js" }, @@ -13612,16 +14020,12 @@ "node": ">=10" } }, - "node_modules/tar/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, "node_modules/terser": { - "version": "5.27.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.27.0.tgz", - "integrity": "sha512-bi1HRwVRskAjheeYl291n3JC4GgO/Ty4z1nVs5AAsmonJulGxpSektecnNedrwK9C7vpvVtcX3cw00VSLt7U2A==", + "version": "5.37.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.37.0.tgz", + "integrity": "sha512-B8wRRkmre4ERucLM/uXx4MOV5cbnOlVAqUst+1+iLKPI0dOgFO28f84ptoQt9HEI537PMzfYa/d+GEPKTRXmYA==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "@jridgewell/source-map": "^0.3.3", "acorn": "^8.8.2", @@ -13636,16 +14040,17 @@ } }, "node_modules/terser-webpack-plugin": { - "version": "5.3.10", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz", - "integrity": "sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==", + "version": "5.3.11", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.11.tgz", + "integrity": "sha512-RVCsMfuD0+cTt3EwX8hSl2Ks56EbFHWmhluwcqoPKtBnfjiT6olaq7PRIRfhyU8nnC2MrnDrBLfrD/RGE+cVXQ==", "dev": true, + "license": "MIT", "dependencies": { - "@jridgewell/trace-mapping": "^0.3.20", + "@jridgewell/trace-mapping": "^0.3.25", "jest-worker": "^27.4.5", - "schema-utils": "^3.1.1", - "serialize-javascript": "^6.0.1", - "terser": "^5.26.0" + "schema-utils": "^4.3.0", + "serialize-javascript": "^6.0.2", + "terser": "^5.31.1" }, "engines": { "node": ">= 10.13.0" @@ -13669,46 +14074,76 @@ } } }, - "node_modules/terser-webpack-plugin/node_modules/jest-worker": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", - "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "node_modules/terser-webpack-plugin/node_modules/ajv": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", "dev": true, + "license": "MIT", "dependencies": { - "@types/node": "*", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" }, - "engines": { - "node": ">= 10.13.0" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/terser-webpack-plugin/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "node_modules/terser-webpack-plugin/node_modules/ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", "dev": true, + "license": "MIT", "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" + "fast-deep-equal": "^3.1.3" }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" + "peerDependencies": { + "ajv": "^8.8.2" + } + }, + "node_modules/terser-webpack-plugin/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true, + "license": "MIT" + }, + "node_modules/terser-webpack-plugin/node_modules/schema-utils": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.0.tgz", + "integrity": "sha512-Gf9qqc58SpCA/xdziiHz35F4GNIWYWZrEshUc/G/r5BnLph6xpKuLeoJoQuj5WfBIx/eQLf+hmVPYHaxJu7V2g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.9.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.1.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" } }, "node_modules/terser/node_modules/commander": { "version": "2.20.3", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/test-exclude": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-7.0.1.tgz", "integrity": "sha512-pFYqmTw68LXVjeWJMST4+borgQP2AyMNbg1BpZh9LbyhUeNkeaPF9gzfPGUAnSMV3qPYdWUwDIjjCLiSDOl7vg==", "dev": true, + "license": "ISC", "dependencies": { "@istanbuljs/schema": "^0.1.2", "glob": "^10.4.1", @@ -13723,6 +14158,7 @@ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" } @@ -13732,6 +14168,7 @@ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" }, @@ -13743,10 +14180,11 @@ } }, "node_modules/testcontainers": { - "version": "10.13.2", - "resolved": "https://registry.npmjs.org/testcontainers/-/testcontainers-10.13.2.tgz", - "integrity": "sha512-LfEll+AG/1Ks3n4+IA5lpyBHLiYh/hSfI4+ERa6urwfQscbDU+M2iW1qPQrHQi+xJXQRYy4whyK1IEHdmxWa3Q==", + "version": "10.16.0", + "resolved": "https://registry.npmjs.org/testcontainers/-/testcontainers-10.16.0.tgz", + "integrity": "sha512-oxPLuOtrRWS11A+Yn0+zXB7GkmNarflWqmy6CQJk8KJ75LZs2/zlUXDpizTbPpCGtk4kE2EQYwFZjrE967F8Wg==", "dev": true, + "license": "MIT", "dependencies": { "@balena/dockerignore": "^1.0.2", "@types/dockerode": "^3.3.29", @@ -13770,14 +14208,16 @@ "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.3.tgz", "integrity": "sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==", "dev": true, + "license": "MIT", "engines": { "node": ">=14.14" } }, "node_modules/text-decoder": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.1.0.tgz", - "integrity": "sha512-TmLJNj6UgX8xcUZo4UDStGQtDiTzF7BzWlzn9g7UWrjkpHr5uJTK1ld16wZ3LXb2vb6jH8qU89dW5whuMdXYdw==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.2.3.tgz", + "integrity": "sha512-3/o9z3X0X0fTupwsYvR03pJ/DjWuqqrfwBgTQzdWDiQSm9KitAyz/9WqsT2JQW7KV2m+bC2ol/zqpW37NHxLaA==", + "license": "Apache-2.0", "dependencies": { "b4a": "^1.6.4" } @@ -13786,18 +14226,14 @@ "version": "0.6.4", "resolved": "https://registry.npmjs.org/text-encoding/-/text-encoding-0.6.4.tgz", "integrity": "sha512-hJnc6Qg3dWoOMkqP53F0dzRIgtmsAge09kxUIqGrEUS4qr5rWLckGYaQAVr+opBrIMRErGgy6f5aPnyPpyGRfg==", - "deprecated": "no longer maintained" - }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true + "deprecated": "no longer maintained", + "license": "Unlicense" }, "node_modules/thenify": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "license": "MIT", "dependencies": { "any-promise": "^1.0.0" } @@ -13806,6 +14242,7 @@ "version": "1.6.0", "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", + "license": "MIT", "dependencies": { "thenify": ">= 3.1.0 < 4" }, @@ -13816,30 +14253,35 @@ "node_modules/through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==" + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", + "license": "MIT" }, "node_modules/thumbhash": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/thumbhash/-/thumbhash-0.1.1.tgz", - "integrity": "sha512-kH5pKeIIBPQXAOni2AiY/Cu/NKdkFREdpH+TLdM0g6WA7RriCv0kPLgP731ady67MhTAqrVG/4mnEeibVuCJcg==" + "integrity": "sha512-kH5pKeIIBPQXAOni2AiY/Cu/NKdkFREdpH+TLdM0g6WA7RriCv0kPLgP731ady67MhTAqrVG/4mnEeibVuCJcg==", + "license": "MIT" }, "node_modules/tinybench": { "version": "2.9.0", "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/tinyexec": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.0.tgz", - "integrity": "sha512-tVGE0mVJPGb0chKhqmsoosjsS+qUnJVGJpZgsHYQcGoPlG3B51R3PouqTgEGH2Dc9jjFyOqOpix6ZHNMXp1FZg==", - "dev": true + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.1.tgz", + "integrity": "sha512-WiCJLEECkO18gwqIp6+hJg0//p23HXp4S+gGtAKu3mI2F2/sXC4FvHvXvB0zJVVaTPhx1/tOwdbRsa1sOBIKqQ==", + "dev": true, + "license": "MIT" }, "node_modules/tinypool": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.0.1.tgz", - "integrity": "sha512-URZYihUbRPcGv95En+sz6MfghfIc2OJ1sv/RmhWZLouPY0/8Vo80viwPvg3dlaS9fuq7fQMEfgRRK7BBZThBEA==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.0.2.tgz", + "integrity": "sha512-al6n+QEANGFOMf/dmUMsuS5/r9B06uwlyNjZZql/zv8J7ybHCgoihBNORZCY2mzUuAnomQa2JdhyHKzZxPCrFA==", "dev": true, + "license": "MIT", "engines": { "node": "^18.0.0 || >=20.0.0" } @@ -13849,6 +14291,7 @@ "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-1.2.0.tgz", "integrity": "sha512-weEDEq7Z5eTHPDh4xjX789+fHfF+P8boiFB+0vbWzpbnbsEr/GRaohi/uMKxg8RZMXnl1ItAi/IUHWMsjDV7kQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=14.0.0" } @@ -13858,6 +14301,7 @@ "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-3.0.2.tgz", "integrity": "sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=14.0.0" } @@ -13866,6 +14310,7 @@ "version": "0.0.33", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "license": "MIT", "dependencies": { "os-tmpdir": "~1.0.2" }, @@ -13873,18 +14318,11 @@ "node": ">=0.6.0" } }, - "node_modules/to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", - "engines": { - "node": ">=4" - } - }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "license": "MIT", "dependencies": { "is-number": "^7.0.0" }, @@ -13896,6 +14334,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "license": "MIT", "engines": { "node": ">=0.6" } @@ -13904,6 +14343,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz", "integrity": "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==", + "license": "MIT", "engines": { "node": ">=6" } @@ -13911,13 +14351,15 @@ "node_modules/tr46": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "license": "MIT" }, "node_modules/tree-kill": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", "dev": true, + "license": "MIT", "bin": { "tree-kill": "cli.js" } @@ -13926,15 +14368,17 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/truncate-utf8-bytes/-/truncate-utf8-bytes-1.0.2.tgz", "integrity": "sha512-95Pu1QXQvruGEhv62XCMO3Mm90GscOCClvrIUwCM0PYOXK3kaF3l3sIHxx71ThJfcbM2O5Au6SO3AWCSEfW4mQ==", + "license": "WTFPL", "dependencies": { "utf8-byte-length": "^1.0.1" } }, "node_modules/ts-api-utils": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", - "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.4.3.tgz", + "integrity": "sha512-i3eMG77UTMD0hZhgRS562pv83RC6ukSAC2GMNWc+9dieh/+jDM5u5YG+NHX6VNDRHQcHwmsTHctP9LhbC3WxVw==", "dev": true, + "license": "MIT", "engines": { "node": ">=16" }, @@ -13946,57 +14390,15 @@ "version": "0.1.13", "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", + "license": "Apache-2.0", "peer": true }, - "node_modules/ts-node": { - "version": "10.9.2", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", - "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", - "optional": true, - "peer": true, - "dependencies": { - "@cspotcode/source-map-support": "^0.8.0", - "@tsconfig/node10": "^1.0.7", - "@tsconfig/node12": "^1.0.7", - "@tsconfig/node14": "^1.0.0", - "@tsconfig/node16": "^1.0.2", - "acorn": "^8.4.1", - "acorn-walk": "^8.1.1", - "arg": "^4.1.0", - "create-require": "^1.1.0", - "diff": "^4.0.1", - "make-error": "^1.1.1", - "v8-compile-cache-lib": "^3.0.1", - "yn": "3.1.1" - }, - "bin": { - "ts-node": "dist/bin.js", - "ts-node-cwd": "dist/bin-cwd.js", - "ts-node-esm": "dist/bin-esm.js", - "ts-node-script": "dist/bin-script.js", - "ts-node-transpile-only": "dist/bin-transpile.js", - "ts-script": "dist/bin-script-deprecated.js" - }, - "peerDependencies": { - "@swc/core": ">=1.2.50", - "@swc/wasm": ">=1.2.50", - "@types/node": "*", - "typescript": ">=2.7" - }, - "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "@swc/wasm": { - "optional": true - } - } - }, "node_modules/tsconfck": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/tsconfck/-/tsconfck-3.1.1.tgz", - "integrity": "sha512-00eoI6WY57SvZEVjm13stEVE90VkEdJAFGgpFLTsZbJyW/LwFQ7uQxJHWpZ2hzSWgCPKc9AnBnNP+0X7o3hAmQ==", + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/tsconfck/-/tsconfck-3.1.4.tgz", + "integrity": "sha512-kdqWFGVJqe+KGYvlSO9NIaWn9jT1Ny4oKVzAJsKii5eoE9snzTJzL4+MMVOMn+fikWGFmKEylcXL710V/kIPJQ==", "dev": true, + "license": "MIT", "bin": { "tsconfck": "bin/tsconfck.js" }, @@ -14017,6 +14419,7 @@ "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz", "integrity": "sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==", "dev": true, + "license": "MIT", "dependencies": { "json5": "^2.2.2", "minimist": "^1.2.6", @@ -14027,44 +14430,40 @@ } }, "node_modules/tsconfig-paths-webpack-plugin": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/tsconfig-paths-webpack-plugin/-/tsconfig-paths-webpack-plugin-4.1.0.tgz", - "integrity": "sha512-xWFISjviPydmtmgeUAuXp4N1fky+VCtfhOkDUFIv5ea7p4wuTomI4QTrXvFBX2S4jZsmyTSrStQl+E+4w+RzxA==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths-webpack-plugin/-/tsconfig-paths-webpack-plugin-4.2.0.tgz", + "integrity": "sha512-zbem3rfRS8BgeNK50Zz5SIQgXzLafiHjOwUAvk/38/o1jHn/V5QAgVUcz884or7WYcPaH3N2CIfUc2u0ul7UcA==", "dev": true, + "license": "MIT", "dependencies": { "chalk": "^4.1.0", "enhanced-resolve": "^5.7.0", + "tapable": "^2.2.1", "tsconfig-paths": "^4.1.2" }, "engines": { "node": ">=10.13.0" } }, - "node_modules/tsconfig-paths/node_modules/strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", - "dev": true, - "engines": { - "node": ">=4" - } - }, "node_modules/tslib": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz", - "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==" + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" }, "node_modules/tweetnacl": { "version": "0.14.5", "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==", - "dev": true + "dev": true, + "license": "Unlicense" }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", "dev": true, + "license": "MIT", "dependencies": { "prelude-ls": "^1.2.1" }, @@ -14072,10 +14471,23 @@ "node": ">= 0.8.0" } }, + "node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/type-is": { "version": "1.6.18", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "license": "MIT", "dependencies": { "media-typer": "0.3.0", "mime-types": "~2.1.24" @@ -14087,12 +14499,14 @@ "node_modules/typedarray": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==" + "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==", + "license": "MIT" }, "node_modules/typeorm": { "version": "0.3.20", "resolved": "https://registry.npmjs.org/typeorm/-/typeorm-0.3.20.tgz", "integrity": "sha512-sJ0T08dV5eoZroaq9uPKBoNcGslHBR4E4y+EBHs//SiGbblGe7IeduP/IH4ddCcj0qp3PHwDwGnuvqEAnKlq/Q==", + "license": "MIT", "dependencies": { "@sqltools/formatter": "^1.2.5", "app-root-path": "^3.1.0", @@ -14212,28 +14626,17 @@ "url": "https://feross.org/support" } ], + "license": "MIT", "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.2.1" } }, - "node_modules/typeorm/node_modules/cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, "node_modules/typeorm/node_modules/mkdirp": { "version": "2.1.6", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-2.1.6.tgz", "integrity": "sha512-+hEnITedc8LAtIP9u3HJDFIdcLV2vXP33sqLLIzkv1Db1zO/1OxbvYf0Y1OC/S/Qo5dxHXepofhmxL02PsKe+A==", + "license": "MIT", "bin": { "mkdirp": "dist/cjs/src/bin.js" }, @@ -14244,44 +14647,25 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/typeorm/node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/typeorm/node_modules/yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - }, - "engines": { - "node": ">=12" + "node_modules/typeorm/node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" } }, "node_modules/typescript": { - "version": "5.6.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz", - "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==", + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.2.tgz", + "integrity": "sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg==", "devOptional": true, + "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -14308,6 +14692,7 @@ "url": "https://github.com/sponsors/faisalman" } ], + "license": "MIT", "bin": { "ua-parser-js": "script/cli.js" }, @@ -14316,9 +14701,10 @@ } }, "node_modules/uglify-js": { - "version": "3.17.4", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.4.tgz", - "integrity": "sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==", + "version": "3.19.3", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz", + "integrity": "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==", + "license": "BSD-2-Clause", "optional": true, "bin": { "uglifyjs": "bin/uglifyjs" @@ -14331,6 +14717,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/uid/-/uid-2.0.2.tgz", "integrity": "sha512-u3xV3X7uzvi5b1MncmZo3i2Aw222Zk1keqLA1YkHldREkAhAqi65wuPfe7lHx8H/Wzy+8CE7S7uS3jekIM5s8g==", + "license": "MIT", "dependencies": { "@lukeed/csprng": "^1.0.0" }, @@ -14342,6 +14729,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/uid2/-/uid2-1.0.0.tgz", "integrity": "sha512-+I6aJUv63YAcY9n4mQreLUt0d4lvwkkopDNmpomkAUz0fAkEMV9pRWxN0EjhW1YfRhcuyHg2v3mwddCDW1+LFQ==", + "license": "MIT", "engines": { "node": ">= 4.0.0" } @@ -14351,6 +14739,7 @@ "resolved": "https://registry.npmjs.org/undici/-/undici-5.28.4.tgz", "integrity": "sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g==", "dev": true, + "license": "MIT", "dependencies": { "@fastify/busboy": "^2.0.0" }, @@ -14359,15 +14748,17 @@ } }, "node_modules/undici-types": { - "version": "6.19.8", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", - "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==" + "version": "6.20.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", + "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", + "license": "MIT" }, "node_modules/universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", "dev": true, + "license": "MIT", "engines": { "node": ">= 10.0.0" } @@ -14376,20 +14767,20 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "license": "MIT", "engines": { "node": ">= 0.8" } }, "node_modules/unplugin": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/unplugin/-/unplugin-1.11.0.tgz", - "integrity": "sha512-3r7VWZ/webh0SGgJScpWl2/MRCZK5d3ZYFcNaeci/GQ7Teop7zf0Nl2pUuz7G21BwPd9pcUPOC5KmJ2L3WgC5g==", + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/unplugin/-/unplugin-1.16.0.tgz", + "integrity": "sha512-5liCNPuJW8dqh3+DM6uNM2EI3MLLpCKp/KY+9pB5M2S2SR2qvvDHhKgBOaTWEbZTAws3CXfB0rKTIolWKL05VQ==", "dev": true, + "license": "MIT", "dependencies": { - "acorn": "^8.11.3", - "chokidar": "^3.6.0", - "webpack-sources": "^3.2.3", - "webpack-virtual-modules": "^0.6.1" + "acorn": "^8.14.0", + "webpack-virtual-modules": "^0.6.2" }, "engines": { "node": ">=14.0.0" @@ -14400,6 +14791,7 @@ "resolved": "https://registry.npmjs.org/unplugin-swc/-/unplugin-swc-1.5.1.tgz", "integrity": "sha512-/ZLrPNjChhGx3Z95pxJ4tQgfI6rWqukgYHKflrNB4zAV1izOQuDhkTn55JWeivpBxDCoK7M/TStb2aS/14PS/g==", "dev": true, + "license": "MIT", "dependencies": { "@rollup/pluginutils": "^5.1.0", "load-tsconfig": "^0.2.5", @@ -14410,9 +14802,9 @@ } }, "node_modules/update-browserslist-db": { - "version": "1.0.13", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", - "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz", + "integrity": "sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==", "funding": [ { "type": "opencollective", @@ -14427,9 +14819,10 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "dependencies": { - "escalade": "^3.1.1", - "picocolors": "^1.0.0" + "escalade": "^3.2.0", + "picocolors": "^1.1.0" }, "bin": { "update-browserslist-db": "cli.js" @@ -14443,24 +14836,28 @@ "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "punycode": "^2.1.0" } }, "node_modules/utf8-byte-length": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/utf8-byte-length/-/utf8-byte-length-1.0.4.tgz", - "integrity": "sha512-4+wkEYLBbWxqTahEsWrhxepcoVOJ+1z5PGIjPZxRkytcdSUaNjIjBM7Xn8E+pdSuV7SzvWovBFA54FO0JSoqhA==" + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/utf8-byte-length/-/utf8-byte-length-1.0.5.tgz", + "integrity": "sha512-Xn0w3MtiQ6zoz2vFyUVruaCL53O/DwUvkEeOvj+uulMm0BkUGYWmBYVyElqZaSLhY6ZD0ulfU3aBra2aVT4xfA==", + "license": "(WTFPL OR MIT)" }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "license": "MIT" }, "node_modules/utils-merge": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "license": "MIT", "engines": { "node": ">= 0.4.0" } @@ -14471,6 +14868,7 @@ "integrity": "sha512-6S5mCapmzcxetOD/2UEjL0GF5e4+gB07Dh8qs63xylw5ay4XuyW6iQs70FOJo/puf10LCkvhp4jYMQSDUBYEFg==", "dev": true, "hasInstallScript": true, + "license": "MIT", "dependencies": { "@mapbox/node-pre-gyp": "^1.0.11", "node-addon-api": "^4.3.0" @@ -14483,32 +14881,28 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-4.3.0.tgz", "integrity": "sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.0.3.tgz", + "integrity": "sha512-d0z310fCWv5dJwnX1Y/MncBAqGMKEzlBb1AOf7z9K8ALnd0utBX/msg/fA0+sbyN1ihbMsLhrBlnl1ak7Wa0rg==", "funding": [ "https://github.com/sponsors/broofa", "https://github.com/sponsors/ctavan" ], + "license": "MIT", "bin": { - "uuid": "dist/bin/uuid" + "uuid": "dist/esm/bin/uuid" } }, - "node_modules/v8-compile-cache-lib": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", - "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", - "optional": true, - "peer": true - }, "node_modules/validate-npm-package-license": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", "dev": true, + "license": "Apache-2.0", "dependencies": { "spdx-correct": "^3.0.0", "spdx-expression-parse": "^3.0.0" @@ -14527,15 +14921,17 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "license": "MIT", "engines": { "node": ">= 0.8" } }, "node_modules/vite": { - "version": "5.4.7", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.7.tgz", - "integrity": "sha512-5l2zxqMEPVENgvzTuBpHer2awaetimj2BGkhBPdnwKbPNOlHsODU+oiazEZzLK7KhAnOrO+XGYJYn4ZlUhDtDQ==", + "version": "5.4.11", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.11.tgz", + "integrity": "sha512-c7jFQRklXua0mTzneGW9QVyxFjUgwcihC4bXEtujIo2ouWCe1Ajt/amn2PCxYnhYfd5k09JX3SB7OYWFKYqj8Q==", "dev": true, + "license": "MIT", "dependencies": { "esbuild": "^0.21.3", "postcss": "^8.4.43", @@ -14591,13 +14987,15 @@ } }, "node_modules/vite-node": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-2.1.3.tgz", - "integrity": "sha512-I1JadzO+xYX887S39Do+paRePCKoiDrWRRjp9kkG5he0t7RXNvPAJPCQSJqbGN4uCrFFeS3Kj3sLqY8NMYBEdA==", + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-2.1.8.tgz", + "integrity": "sha512-uPAwSr57kYjAUux+8E2j0q0Fxpn8M9VoyfGiRI8Kfktz9NcYMCenwY5RnZxnF1WTu3TGiYipirIzacLL3VVGFg==", "dev": true, + "license": "MIT", "dependencies": { "cac": "^6.7.14", - "debug": "^4.3.6", + "debug": "^4.3.7", + "es-module-lexer": "^1.5.4", "pathe": "^1.1.2", "vite": "^5.0.0" }, @@ -14612,10 +15010,11 @@ } }, "node_modules/vite-tsconfig-paths": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/vite-tsconfig-paths/-/vite-tsconfig-paths-5.0.1.tgz", - "integrity": "sha512-yqwv+LstU7NwPeNqajZzLEBVpUFU6Dugtb2P84FXuvaoYA+/70l9MHE+GYfYAycVyPSDYZ7mjOFuYBRqlEpTig==", + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/vite-tsconfig-paths/-/vite-tsconfig-paths-5.1.4.tgz", + "integrity": "sha512-cYj0LRuLV2c2sMqhqhGpaO3LretdtMn/BVX4cPLanIZuwwrkVl+lK84E/miEXkCHWXuq65rhNN4rXsBcOB3S4w==", "dev": true, + "license": "MIT", "dependencies": { "debug": "^4.1.1", "globrex": "^0.1.2", @@ -14630,10488 +15029,584 @@ } } }, - "node_modules/vitest": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-2.1.3.tgz", - "integrity": "sha512-Zrxbg/WiIvUP2uEzelDNTXmEMJXuzJ1kCpbDvaKByFA9MNeO95V+7r/3ti0qzJzrxdyuUw5VduN7k+D3VmVOSA==", - "dev": true, - "dependencies": { - "@vitest/expect": "2.1.3", - "@vitest/mocker": "2.1.3", - "@vitest/pretty-format": "^2.1.3", - "@vitest/runner": "2.1.3", - "@vitest/snapshot": "2.1.3", - "@vitest/spy": "2.1.3", - "@vitest/utils": "2.1.3", - "chai": "^5.1.1", - "debug": "^4.3.6", - "magic-string": "^0.30.11", - "pathe": "^1.1.2", - "std-env": "^3.7.0", - "tinybench": "^2.9.0", - "tinyexec": "^0.3.0", - "tinypool": "^1.0.0", - "tinyrainbow": "^1.2.0", - "vite": "^5.0.0", - "vite-node": "2.1.3", - "why-is-node-running": "^2.3.0" - }, - "bin": { - "vitest": "vitest.mjs" - }, + "node_modules/vite/node_modules/@esbuild/aix-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", + "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], "engines": { - "node": "^18.0.0 || >=20.0.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - }, - "peerDependencies": { - "@edge-runtime/vm": "*", - "@types/node": "^18.0.0 || >=20.0.0", - "@vitest/browser": "2.1.3", - "@vitest/ui": "2.1.3", - "happy-dom": "*", - "jsdom": "*" - }, - "peerDependenciesMeta": { - "@edge-runtime/vm": { - "optional": true - }, - "@types/node": { - "optional": true - }, - "@vitest/browser": { - "optional": true - }, - "@vitest/ui": { - "optional": true - }, - "happy-dom": { - "optional": true - }, - "jsdom": { - "optional": true - } + "node": ">=12" } }, - "node_modules/vitest/node_modules/magic-string": { - "version": "0.30.12", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.12.tgz", - "integrity": "sha512-Ea8I3sQMVXr8JhN4z+H/d8zwo+tYDgHE9+5G4Wnrwhs0gaK9fXTKx0Tw5Xwsd/bCPTTZNRAdpyzvoeORe9LYpw==", + "node_modules/vite/node_modules/@esbuild/android-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", + "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", + "cpu": [ + "arm" + ], "dev": true, - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.0" + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" } }, - "node_modules/watchpack": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.1.tgz", - "integrity": "sha512-8wrBCMtVhqcXP2Sup1ctSkga6uc2Bx0IIvKyT7yTFier5AXHooSI+QyQQAtTb7+E0IUCCKyTFmXqdqgum2XWGg==", + "node_modules/vite/node_modules/@esbuild/android-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", + "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.1.2" - }, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], "engines": { - "node": ">=10.13.0" + "node": ">=12" } }, - "node_modules/wcwidth": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", - "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", - "dependencies": { - "defaults": "^1.0.3" + "node_modules/vite/node_modules/@esbuild/android-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", + "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" } }, - "node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" - }, - "node_modules/webpack": { - "version": "5.94.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.94.0.tgz", - "integrity": "sha512-KcsGn50VT+06JH/iunZJedYGUJS5FGjow8wb9c0v5n1Om8O1g4L6LjtfxwlXIATopoQu+vOXXa7gYisWxCoPyg==", + "node_modules/vite/node_modules/@esbuild/darwin-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", + "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "@types/estree": "^1.0.5", - "@webassemblyjs/ast": "^1.12.1", - "@webassemblyjs/wasm-edit": "^1.12.1", - "@webassemblyjs/wasm-parser": "^1.12.1", - "acorn": "^8.7.1", - "acorn-import-attributes": "^1.9.5", - "browserslist": "^4.21.10", - "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.17.1", - "es-module-lexer": "^1.2.1", - "eslint-scope": "5.1.1", - "events": "^3.2.0", - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.2.11", - "json-parse-even-better-errors": "^2.3.1", - "loader-runner": "^4.2.0", - "mime-types": "^2.1.27", - "neo-async": "^2.6.2", - "schema-utils": "^3.2.0", - "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.3.10", - "watchpack": "^2.4.1", - "webpack-sources": "^3.2.3" - }, - "bin": { - "webpack": "bin/webpack.js" - }, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependenciesMeta": { - "webpack-cli": { - "optional": true - } + "node": ">=12" } }, - "node_modules/webpack-node-externals": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/webpack-node-externals/-/webpack-node-externals-3.0.0.tgz", - "integrity": "sha512-LnL6Z3GGDPht/AigwRh2dvL9PQPFQ8skEpVrWZXLWBYmqcaojHNN0onvHzie6rq7EWKrrBfPYqNEzTJgiwEQDQ==", + "node_modules/vite/node_modules/@esbuild/darwin-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", + "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", + "cpu": [ + "x64" + ], "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=6" + "node": ">=12" } }, - "node_modules/webpack-sources": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", - "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", + "node_modules/vite/node_modules/@esbuild/freebsd-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", + "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", + "cpu": [ + "arm64" + ], "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], "engines": { - "node": ">=10.13.0" + "node": ">=12" } }, - "node_modules/webpack-virtual-modules": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/webpack-virtual-modules/-/webpack-virtual-modules-0.6.1.tgz", - "integrity": "sha512-poXpCylU7ExuvZK8z+On3kX+S8o/2dQ/SVYueKA0D4WEMXROXgY8Ez50/bQEUmvoSMMrWcrJqCHuhAbsiwg7Dg==", - "dev": true - }, - "node_modules/webpack/node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "node_modules/vite/node_modules/@esbuild/freebsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", + "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - }, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], "engines": { - "node": ">=8.0.0" + "node": ">=12" } }, - "node_modules/webpack/node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "node_modules/vite/node_modules/@esbuild/linux-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", + "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", + "cpu": [ + "arm" + ], "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=4.0" + "node": ">=12" } }, - "node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" + "node_modules/vite/node_modules/@esbuild/linux-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", + "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" } }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, + "node_modules/vite/node_modules/@esbuild/linux-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", + "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">= 8" + "node": ">=12" } }, - "node_modules/why-is-node-running": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", - "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", + "node_modules/vite/node_modules/@esbuild/linux-loong64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", + "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", + "cpu": [ + "loong64" + ], "dev": true, - "dependencies": { - "siginfo": "^2.0.0", - "stackback": "0.0.2" - }, - "bin": { - "why-is-node-running": "cli.js" - }, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=8" + "node": ">=12" } }, - "node_modules/wide-align": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", - "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", - "dependencies": { - "string-width": "^1.0.2 || 2 || 3 || 4" + "node_modules/vite/node_modules/@esbuild/linux-mips64el": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", + "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" } }, - "node_modules/wordwrap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==" - }, - "node_modules/wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, + "node_modules/vite/node_modules/@esbuild/linux-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", + "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=8" + "node": ">=12" } }, - "node_modules/wrap-ansi-cjs": { - "name": "wrap-ansi", - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, + "node_modules/vite/node_modules/@esbuild/linux-riscv64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", + "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + "node": ">=12" } }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" - }, - "node_modules/ws": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", - "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", + "node_modules/vite/node_modules/@esbuild/linux-s390x": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", + "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } + "node": ">=12" } }, - "node_modules/xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "node_modules/vite/node_modules/@esbuild/linux-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", + "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=0.4" + "node": ">=12" } }, - "node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "node_modules/vite/node_modules/@esbuild/netbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", + "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], "engines": { - "node": ">=10" + "node": ">=12" } }, - "node_modules/yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" - }, - "node_modules/yaml": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.4.tgz", - "integrity": "sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA==", + "node_modules/vite/node_modules/@esbuild/openbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", + "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], "engines": { - "node": ">= 14" + "node": ">=12" } }, - "node_modules/yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "dependencies": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - }, + "node_modules/vite/node_modules/@esbuild/sunos-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", + "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], "engines": { - "node": ">=10" + "node": ">=12" } }, - "node_modules/yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "node_modules/vite/node_modules/@esbuild/win32-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", + "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], "engines": { "node": ">=12" } }, - "node_modules/yargs/node_modules/yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "node_modules/vite/node_modules/@esbuild/win32-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", + "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=10" + "node": ">=12" } }, - "node_modules/yn": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", - "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "node_modules/vite/node_modules/@esbuild/win32-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", + "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", "optional": true, - "peer": true, + "os": [ + "win32" + ], "engines": { - "node": ">=6" + "node": ">=12" } }, - "node_modules/yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "node_modules/vite/node_modules/esbuild": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", + "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, "engines": { - "node": ">=10" + "node": ">=12" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.21.5", + "@esbuild/android-arm": "0.21.5", + "@esbuild/android-arm64": "0.21.5", + "@esbuild/android-x64": "0.21.5", + "@esbuild/darwin-arm64": "0.21.5", + "@esbuild/darwin-x64": "0.21.5", + "@esbuild/freebsd-arm64": "0.21.5", + "@esbuild/freebsd-x64": "0.21.5", + "@esbuild/linux-arm": "0.21.5", + "@esbuild/linux-arm64": "0.21.5", + "@esbuild/linux-ia32": "0.21.5", + "@esbuild/linux-loong64": "0.21.5", + "@esbuild/linux-mips64el": "0.21.5", + "@esbuild/linux-ppc64": "0.21.5", + "@esbuild/linux-riscv64": "0.21.5", + "@esbuild/linux-s390x": "0.21.5", + "@esbuild/linux-x64": "0.21.5", + "@esbuild/netbsd-x64": "0.21.5", + "@esbuild/openbsd-x64": "0.21.5", + "@esbuild/sunos-x64": "0.21.5", + "@esbuild/win32-arm64": "0.21.5", + "@esbuild/win32-ia32": "0.21.5", + "@esbuild/win32-x64": "0.21.5" } }, - "node_modules/zip-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-6.0.1.tgz", - "integrity": "sha512-zK7YHHz4ZXpW89AHXUPbQVGKI7uvkd3hzusTdotCg1UxyaVtg0zFJSTfW/Dq5f7OBBVnq6cZIaC8Ti4hb6dtCA==", - "dependencies": { - "archiver-utils": "^5.0.0", - "compress-commons": "^6.0.2", - "readable-stream": "^4.0.0" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/zip-stream/node_modules/buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "node_modules/vite/node_modules/postcss": { + "version": "8.4.49", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.49.tgz", + "integrity": "sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==", + "dev": true, "funding": [ { - "type": "github", - "url": "https://github.com/sponsors/feross" + "type": "opencollective", + "url": "https://opencollective.com/postcss/" }, { - "type": "patreon", - "url": "https://www.patreon.com/feross" + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" }, { - "type": "consulting", - "url": "https://feross.org/support" + "type": "github", + "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" - } - }, - "node_modules/zip-stream/node_modules/readable-stream": { - "version": "4.5.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz", - "integrity": "sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==", - "dependencies": { - "abort-controller": "^3.0.0", - "buffer": "^6.0.3", - "events": "^3.3.0", - "process": "^0.11.10", - "string_decoder": "^1.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - } - }, - "dependencies": { - "@aashutoshrathi/word-wrap": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", - "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", - "dev": true - }, - "@alloc/quick-lru": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", - "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", - "peer": true - }, - "@ampproject/remapping": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", - "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", - "requires": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.24" - } - }, - "@angular-devkit/core": { - "version": "17.3.8", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-17.3.8.tgz", - "integrity": "sha512-Q8q0voCGudbdCgJ7lXdnyaxKHbNQBARH68zPQV72WT8NWy+Gw/tys870i6L58NWbBaCJEUcIj/kb6KoakSRu+Q==", - "dev": true, - "requires": { - "ajv": "8.12.0", - "ajv-formats": "2.1.1", - "jsonc-parser": "3.2.1", - "picomatch": "4.0.1", - "rxjs": "7.8.1", - "source-map": "0.7.4" - }, - "dependencies": { - "picomatch": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.1.tgz", - "integrity": "sha512-xUXwsxNjwTQ8K3GnT4pCJm+xq3RUPQbmkYJTP5aFIfNIvbcc/4MUxgBaaRSZJ6yGJZiGSyYlM6MzwTsRk8SYCg==", - "dev": true - } - } - }, - "@angular-devkit/schematics": { - "version": "17.3.8", - "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-17.3.8.tgz", - "integrity": "sha512-QRVEYpIfgkprNHc916JlPuNbLzOgrm9DZalHasnLUz4P6g7pR21olb8YCyM2OTJjombNhya9ZpckcADU5Qyvlg==", - "dev": true, - "requires": { - "@angular-devkit/core": "17.3.8", - "jsonc-parser": "3.2.1", - "magic-string": "0.30.8", - "ora": "5.4.1", - "rxjs": "7.8.1" - } - }, - "@angular-devkit/schematics-cli": { - "version": "17.3.8", - "resolved": "https://registry.npmjs.org/@angular-devkit/schematics-cli/-/schematics-cli-17.3.8.tgz", - "integrity": "sha512-TjmiwWJarX7oqvNiRAroQ5/LeKUatxBOCNEuKXO/PV8e7pn/Hr/BqfFm+UcYrQoFdZplmtNAfqmbqgVziKvCpA==", - "dev": true, - "requires": { - "@angular-devkit/core": "17.3.8", - "@angular-devkit/schematics": "17.3.8", - "ansi-colors": "4.1.3", - "inquirer": "9.2.15", - "symbol-observable": "4.0.0", - "yargs-parser": "21.1.1" - }, - "dependencies": { - "chalk": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", - "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", - "dev": true - }, - "cli-width": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.1.0.tgz", - "integrity": "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==", - "dev": true - }, - "inquirer": { - "version": "9.2.15", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-9.2.15.tgz", - "integrity": "sha512-vI2w4zl/mDluHt9YEQ/543VTCwPKWiHzKtm9dM2V0NdFcqEexDAjUHzO1oA60HRNaVifGXXM1tRRNluLVHa0Kg==", - "dev": true, - "requires": { - "@ljharb/through": "^2.3.12", - "ansi-escapes": "^4.3.2", - "chalk": "^5.3.0", - "cli-cursor": "^3.1.0", - "cli-width": "^4.1.0", - "external-editor": "^3.1.0", - "figures": "^3.2.0", - "lodash": "^4.17.21", - "mute-stream": "1.0.0", - "ora": "^5.4.1", - "run-async": "^3.0.0", - "rxjs": "^7.8.1", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^6.2.0" - } - }, - "mute-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-1.0.0.tgz", - "integrity": "sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==", - "dev": true - }, - "run-async": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/run-async/-/run-async-3.0.0.tgz", - "integrity": "sha512-540WwVDOMxA6dN6We19EcT9sc3hkXPw5mzRNGM3FkdN/vtE9NFvj5lFAPNwUDmJjXidm3v7TC1cTE7t17Ulm1Q==", - "dev": true - } - } - }, - "@babel/code-frame": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.6.tgz", - "integrity": "sha512-ZJhac6FkEd1yhG2AHOmfcXG4ceoLltoCVJjN5XsWN9BifBQr+cHJbWi0h68HZuSORq+3WtJ2z0hwF2NG1b5kcA==", - "requires": { - "@babel/highlight": "^7.24.6", - "picocolors": "^1.0.0" - } - }, - "@babel/compat-data": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.24.6.tgz", - "integrity": "sha512-aC2DGhBq5eEdyXWqrDInSqQjO0k8xtPRf5YylULqx8MCd6jBtzqfta/3ETMRpuKIc5hyswfO80ObyA1MvkCcUQ==" - }, - "@babel/core": { - "version": "7.24.5", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.5.tgz", - "integrity": "sha512-tVQRucExLQ02Boi4vdPp49svNGcfL2GhdTCT9aldhXgCJVAI21EtRfBettiuLUwce/7r6bFdgs6JFkcdTiFttA==", - "requires": { - "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.24.2", - "@babel/generator": "^7.24.5", - "@babel/helper-compilation-targets": "^7.23.6", - "@babel/helper-module-transforms": "^7.24.5", - "@babel/helpers": "^7.24.5", - "@babel/parser": "^7.24.5", - "@babel/template": "^7.24.0", - "@babel/traverse": "^7.24.5", - "@babel/types": "^7.24.5", - "convert-source-map": "^2.0.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.3", - "semver": "^6.3.1" - }, - "dependencies": { - "semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" - } - } - }, - "@babel/generator": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.6.tgz", - "integrity": "sha512-S7m4eNa6YAPJRHmKsLHIDJhNAGNKoWNiWefz1MBbpnt8g9lvMDl1hir4P9bo/57bQEmuwEhnRU/AMWsD0G/Fbg==", - "requires": { - "@babel/types": "^7.24.6", - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25", - "jsesc": "^2.5.1" - }, - "dependencies": { - "jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==" - } - } - }, - "@babel/helper-compilation-targets": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.24.6.tgz", - "integrity": "sha512-VZQ57UsDGlX/5fFA7GkVPplZhHsVc+vuErWgdOiysI9Ksnw0Pbbd6pnPiR/mmJyKHgyIW0c7KT32gmhiF+cirg==", - "requires": { - "@babel/compat-data": "^7.24.6", - "@babel/helper-validator-option": "^7.24.6", - "browserslist": "^4.22.2", - "lru-cache": "^5.1.1", - "semver": "^6.3.1" - }, - "dependencies": { - "semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" - } - } - }, - "@babel/helper-environment-visitor": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.24.6.tgz", - "integrity": "sha512-Y50Cg3k0LKLMjxdPjIl40SdJgMB85iXn27Vk/qbHZCFx/o5XO3PSnpi675h1KEmmDb6OFArfd5SCQEQ5Q4H88g==" - }, - "@babel/helper-function-name": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.24.6.tgz", - "integrity": "sha512-xpeLqeeRkbxhnYimfr2PC+iA0Q7ljX/d1eZ9/inYbmfG2jpl8Lu3DyXvpOAnrS5kxkfOWJjioIMQsaMBXFI05w==", - "requires": { - "@babel/template": "^7.24.6", - "@babel/types": "^7.24.6" - } - }, - "@babel/helper-hoist-variables": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.24.6.tgz", - "integrity": "sha512-SF/EMrC3OD7dSta1bLJIlrsVxwtd0UpjRJqLno6125epQMJ/kyFmpTT4pbvPbdQHzCHg+biQ7Syo8lnDtbR+uA==", - "requires": { - "@babel/types": "^7.24.6" - } - }, - "@babel/helper-module-imports": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.6.tgz", - "integrity": "sha512-a26dmxFJBF62rRO9mmpgrfTLsAuyHk4e1hKTUkD/fcMfynt8gvEKwQPQDVxWhca8dHoDck+55DFt42zV0QMw5g==", - "requires": { - "@babel/types": "^7.24.6" - } - }, - "@babel/helper-module-transforms": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.24.6.tgz", - "integrity": "sha512-Y/YMPm83mV2HJTbX1Qh2sjgjqcacvOlhbzdCCsSlblOKjSYmQqEbO6rUniWQyRo9ncyfjT8hnUjlG06RXDEmcA==", - "requires": { - "@babel/helper-environment-visitor": "^7.24.6", - "@babel/helper-module-imports": "^7.24.6", - "@babel/helper-simple-access": "^7.24.6", - "@babel/helper-split-export-declaration": "^7.24.6", - "@babel/helper-validator-identifier": "^7.24.6" - } - }, - "@babel/helper-simple-access": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.24.6.tgz", - "integrity": "sha512-nZzcMMD4ZhmB35MOOzQuiGO5RzL6tJbsT37Zx8M5L/i9KSrukGXWTjLe1knIbb/RmxoJE9GON9soq0c0VEMM5g==", - "requires": { - "@babel/types": "^7.24.6" - } - }, - "@babel/helper-split-export-declaration": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.6.tgz", - "integrity": "sha512-CvLSkwXGWnYlF9+J3iZUvwgAxKiYzK3BWuo+mLzD/MDGOZDj7Gq8+hqaOkMxmJwmlv0iu86uH5fdADd9Hxkymw==", - "requires": { - "@babel/types": "^7.24.6" - } - }, - "@babel/helper-string-parser": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.6.tgz", - "integrity": "sha512-WdJjwMEkmBicq5T9fm/cHND3+UlFa2Yj8ALLgmoSQAJZysYbBjw+azChSGPN4DSPLXOcooGRvDwZWMcF/mLO2Q==" - }, - "@babel/helper-validator-identifier": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.6.tgz", - "integrity": "sha512-4yA7s865JHaqUdRbnaxarZREuPTHrjpDT+pXoAZ1yhyo6uFnIEpS8VMu16siFOHDpZNKYv5BObhsB//ycbICyw==" - }, - "@babel/helper-validator-option": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.24.6.tgz", - "integrity": "sha512-Jktc8KkF3zIkePb48QO+IapbXlSapOW9S+ogZZkcO6bABgYAxtZcjZ/O005111YLf+j4M84uEgwYoidDkXbCkQ==" - }, - "@babel/helpers": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.6.tgz", - "integrity": "sha512-V2PI+NqnyFu1i0GyTd/O/cTpxzQCYioSkUIRmgo7gFEHKKCg5w46+r/A6WeUR1+P3TeQ49dspGPNd/E3n9AnnA==", - "requires": { - "@babel/template": "^7.24.6", - "@babel/types": "^7.24.6" - } - }, - "@babel/highlight": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.6.tgz", - "integrity": "sha512-2YnuOp4HAk2BsBrJJvYCbItHx0zWscI1C3zgWkz+wDyD9I7GIVrfnLyrR4Y1VR+7p+chAEcrgRQYZAGIKMV7vQ==", - "requires": { - "@babel/helper-validator-identifier": "^7.24.6", - "chalk": "^2.4.2", - "js-tokens": "^4.0.0", - "picocolors": "^1.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==" - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==" - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "@babel/parser": { - "version": "7.24.5", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.5.tgz", - "integrity": "sha512-EOv5IK8arwh3LI47dz1b0tKUb/1uhHAnHJOrjgtQMIpu1uXd9mlFrJg9IUgGUgZ41Ch0K8REPTYpO7B76b4vJg==" - }, - "@babel/template": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.24.6.tgz", - "integrity": "sha512-3vgazJlLwNXi9jhrR1ef8qiB65L1RK90+lEQwv4OxveHnqC3BfmnHdgySwRLzf6akhlOYenT+b7AfWq+a//AHw==", - "requires": { - "@babel/code-frame": "^7.24.6", - "@babel/parser": "^7.24.6", - "@babel/types": "^7.24.6" - }, - "dependencies": { - "@babel/parser": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.6.tgz", - "integrity": "sha512-eNZXdfU35nJC2h24RznROuOpO94h6x8sg9ju0tT9biNtLZ2vuP8SduLqqV+/8+cebSLV9SJEAN5Z3zQbJG/M+Q==" - } - } - }, - "@babel/traverse": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.6.tgz", - "integrity": "sha512-OsNjaJwT9Zn8ozxcfoBc+RaHdj3gFmCmYoQLUII1o6ZrUwku0BMg80FoOTPx+Gi6XhcQxAYE4xyjPTo4SxEQqw==", - "requires": { - "@babel/code-frame": "^7.24.6", - "@babel/generator": "^7.24.6", - "@babel/helper-environment-visitor": "^7.24.6", - "@babel/helper-function-name": "^7.24.6", - "@babel/helper-hoist-variables": "^7.24.6", - "@babel/helper-split-export-declaration": "^7.24.6", - "@babel/parser": "^7.24.6", - "@babel/types": "^7.24.6", - "debug": "^4.3.1", - "globals": "^11.1.0" + "nanoid": "^3.3.7", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" }, - "dependencies": { - "@babel/parser": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.6.tgz", - "integrity": "sha512-eNZXdfU35nJC2h24RznROuOpO94h6x8sg9ju0tT9biNtLZ2vuP8SduLqqV+/8+cebSLV9SJEAN5Z3zQbJG/M+Q==" - }, - "globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==" - } - } - }, - "@babel/types": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.6.tgz", - "integrity": "sha512-WaMsgi6Q8zMgMth93GvWPXkhAIEobfsIkLTacoVZoK1J0CevIPGYY2Vo5YvJGqyHqXM6P4ppOYGsIRU8MM9pFQ==", - "requires": { - "@babel/helper-string-parser": "^7.24.6", - "@babel/helper-validator-identifier": "^7.24.6", - "to-fast-properties": "^2.0.0" - } - }, - "@balena/dockerignore": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@balena/dockerignore/-/dockerignore-1.0.2.tgz", - "integrity": "sha512-wMue2Sy4GAVTk6Ic4tJVcnfdau+gx2EnG7S+uAEe+TWJFqE4YoWN4/H8MSLj4eYJKxGg26lZwboEniNiNwZQ6Q==", - "dev": true - }, - "@bcoe/v8-coverage": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", - "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", - "dev": true - }, - "@colors/colors": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", - "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", - "dev": true, - "optional": true - }, - "@cspotcode/source-map-support": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", - "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", - "optional": true, - "peer": true, - "requires": { - "@jridgewell/trace-mapping": "0.3.9" - }, - "dependencies": { - "@jridgewell/trace-mapping": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", - "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", - "optional": true, - "peer": true, - "requires": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" - } - } - } - }, - "@emnapi/runtime": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.2.0.tgz", - "integrity": "sha512-bV21/9LQmcQeCPEg3BDFtvwL6cwiTMksYNWQQ4KOxCZikEGalWtenoZ0wCiukJINlGCIi2KXx01g4FoH/LxpzQ==", - "optional": true, - "requires": { - "tslib": "^2.4.0" - } - }, - "@esbuild/aix-ppc64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", - "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", - "dev": true, - "optional": true - }, - "@esbuild/android-arm": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", - "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", - "dev": true, - "optional": true - }, - "@esbuild/android-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", - "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", - "dev": true, - "optional": true - }, - "@esbuild/android-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", - "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", - "dev": true, - "optional": true - }, - "@esbuild/darwin-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", - "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", - "dev": true, - "optional": true - }, - "@esbuild/darwin-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", - "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", - "dev": true, - "optional": true - }, - "@esbuild/freebsd-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", - "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", - "dev": true, - "optional": true - }, - "@esbuild/freebsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", - "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", - "dev": true, - "optional": true - }, - "@esbuild/linux-arm": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", - "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", - "dev": true, - "optional": true - }, - "@esbuild/linux-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", - "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", - "dev": true, - "optional": true - }, - "@esbuild/linux-ia32": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", - "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", - "dev": true, - "optional": true - }, - "@esbuild/linux-loong64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", - "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", - "dev": true, - "optional": true - }, - "@esbuild/linux-mips64el": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", - "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", - "dev": true, - "optional": true - }, - "@esbuild/linux-ppc64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", - "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", - "dev": true, - "optional": true - }, - "@esbuild/linux-riscv64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", - "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", - "dev": true, - "optional": true - }, - "@esbuild/linux-s390x": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", - "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", - "dev": true, - "optional": true - }, - "@esbuild/linux-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", - "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", - "dev": true, - "optional": true - }, - "@esbuild/netbsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", - "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", - "dev": true, - "optional": true - }, - "@esbuild/openbsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", - "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", - "dev": true, - "optional": true - }, - "@esbuild/sunos-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", - "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", - "dev": true, - "optional": true - }, - "@esbuild/win32-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", - "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", - "dev": true, - "optional": true - }, - "@esbuild/win32-ia32": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", - "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", - "dev": true, - "optional": true - }, - "@esbuild/win32-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", - "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", - "dev": true, - "optional": true - }, - "@eslint-community/eslint-utils": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", - "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", - "dev": true, - "requires": { - "eslint-visitor-keys": "^3.3.0" - } - }, - "@eslint-community/regexpp": { - "version": "4.11.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.0.tgz", - "integrity": "sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A==", - "dev": true - }, - "@eslint/config-array": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.18.0.tgz", - "integrity": "sha512-fTxvnS1sRMu3+JjXwJG0j/i4RT9u4qJ+lqS/yCGap4lH4zZGzQ7tu+xZqQmcMZq5OBZDL4QRxQzRjkWcGt8IVw==", - "dev": true, - "requires": { - "@eslint/object-schema": "^2.1.4", - "debug": "^4.3.1", - "minimatch": "^3.1.2" - } - }, - "@eslint/core": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.7.0.tgz", - "integrity": "sha512-xp5Jirz5DyPYlPiKat8jaq0EmYvDXKKpzTbxXMpT9eqlRJkRKIz9AGMdlvYjih+im+QlhWrpvVjl8IPC/lHlUw==", - "dev": true - }, - "@eslint/eslintrc": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.1.0.tgz", - "integrity": "sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==", - "dev": true, - "requires": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^10.0.1", - "globals": "^14.0.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - }, - "dependencies": { - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "globals": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", - "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", - "dev": true - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - } - } - }, - "@eslint/js": { - "version": "9.13.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.13.0.tgz", - "integrity": "sha512-IFLyoY4d72Z5y/6o/BazFBezupzI/taV8sGumxTAVw3lXG9A6md1Dc34T9s1FoD/an9pJH8RHbAxsaEbBed9lA==", - "dev": true - }, - "@eslint/object-schema": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.4.tgz", - "integrity": "sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==", - "dev": true - }, - "@eslint/plugin-kit": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.0.tgz", - "integrity": "sha512-vH9PiIMMwvhCx31Af3HiGzsVNULDbyVkHXwlemn/B0TFj/00ho3y55efXrUZTfQipxoHC5u4xq6zblww1zm1Ig==", - "dev": true, - "requires": { - "levn": "^0.4.1" - } - }, - "@fastify/busboy": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.1.tgz", - "integrity": "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==", - "dev": true - }, - "@golevelup/nestjs-discovery": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@golevelup/nestjs-discovery/-/nestjs-discovery-4.0.1.tgz", - "integrity": "sha512-HFXBJayEkYcU/bbxOztozONdWaZR34ZeJ2zRbZIWY8d5K26oPZQTvJ4L0STW3XVRGWtoE0WBpmx2YPNgYvcmJQ==", - "requires": { - "lodash": "^4.17.21" - } - }, - "@grpc/grpc-js": { - "version": "1.12.2", - "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.12.2.tgz", - "integrity": "sha512-bgxdZmgTrJZX50OjyVwz3+mNEnCTNkh3cIqGPWVNeW9jX6bn1ZkU80uPd+67/ZpIJIjRQ9qaHCjhavyoWYxumg==", - "requires": { - "@grpc/proto-loader": "^0.7.13", - "@js-sdsl/ordered-map": "^4.4.2" - } - }, - "@grpc/proto-loader": { - "version": "0.7.13", - "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.7.13.tgz", - "integrity": "sha512-AiXO/bfe9bmxBjxxtYxFAXGZvMaN5s8kO+jBHAJCON8rJoB5YS/D6X7ZNc6XQkuHNmyl4CYaMI1fJ/Gn27RGGw==", - "requires": { - "lodash.camelcase": "^4.3.0", - "long": "^5.0.0", - "protobufjs": "^7.2.5", - "yargs": "^17.7.2" - }, - "dependencies": { - "cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - } - }, - "wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - } - }, - "yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "requires": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - } - } - } - }, - "@hapi/hoek": { - "version": "9.3.0", - "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz", - "integrity": "sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==" - }, - "@hapi/topo": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.1.0.tgz", - "integrity": "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==", - "requires": { - "@hapi/hoek": "^9.0.0" - } - }, - "@humanfs/core": { - "version": "0.19.0", - "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.0.tgz", - "integrity": "sha512-2cbWIHbZVEweE853g8jymffCA+NCMiuqeECeBBLm8dg2oFdjuGJhgN4UAbI+6v0CKbbhvtXA4qV8YR5Ji86nmw==", - "dev": true - }, - "@humanfs/node": { - "version": "0.16.5", - "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.5.tgz", - "integrity": "sha512-KSPA4umqSG4LHYRodq31VDwKAvaTF4xmVlzM8Aeh4PlU1JQ3IG0wiA8C25d3RQ9nJyM3mBHyI53K06VVL/oFFg==", - "dev": true, - "requires": { - "@humanfs/core": "^0.19.0", - "@humanwhocodes/retry": "^0.3.0" - } - }, - "@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", - "dev": true - }, - "@humanwhocodes/retry": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz", - "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==", - "dev": true - }, - "@img/sharp-darwin-arm64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.33.5.tgz", - "integrity": "sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ==", - "optional": true, - "requires": { - "@img/sharp-libvips-darwin-arm64": "1.0.4" - } - }, - "@img/sharp-darwin-x64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.33.5.tgz", - "integrity": "sha512-fyHac4jIc1ANYGRDxtiqelIbdWkIuQaI84Mv45KvGRRxSAa7o7d1ZKAOBaYbnepLC1WqxfpimdeWfvqqSGwR2Q==", - "optional": true, - "requires": { - "@img/sharp-libvips-darwin-x64": "1.0.4" - } - }, - "@img/sharp-libvips-darwin-arm64": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.0.4.tgz", - "integrity": "sha512-XblONe153h0O2zuFfTAbQYAX2JhYmDHeWikp1LM9Hul9gVPjFY427k6dFEcOL72O01QxQsWi761svJ/ev9xEDg==", - "optional": true - }, - "@img/sharp-libvips-darwin-x64": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.0.4.tgz", - "integrity": "sha512-xnGR8YuZYfJGmWPvmlunFaWJsb9T/AO2ykoP3Fz/0X5XV2aoYBPkX6xqCQvUTKKiLddarLaxpzNe+b1hjeWHAQ==", - "optional": true - }, - "@img/sharp-libvips-linux-arm": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.0.5.tgz", - "integrity": "sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g==", - "optional": true - }, - "@img/sharp-libvips-linux-arm64": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.0.4.tgz", - "integrity": "sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA==", - "optional": true - }, - "@img/sharp-libvips-linux-s390x": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.0.4.tgz", - "integrity": "sha512-u7Wz6ntiSSgGSGcjZ55im6uvTrOxSIS8/dgoVMoiGE9I6JAfU50yH5BoDlYA1tcuGS7g/QNtetJnxA6QEsCVTA==", - "optional": true - }, - "@img/sharp-libvips-linux-x64": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.0.4.tgz", - "integrity": "sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw==", - "optional": true - }, - "@img/sharp-libvips-linuxmusl-arm64": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.0.4.tgz", - "integrity": "sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA==", - "optional": true - }, - "@img/sharp-libvips-linuxmusl-x64": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.0.4.tgz", - "integrity": "sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw==", - "optional": true - }, - "@img/sharp-linux-arm": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.33.5.tgz", - "integrity": "sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ==", - "optional": true, - "requires": { - "@img/sharp-libvips-linux-arm": "1.0.5" - } - }, - "@img/sharp-linux-arm64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.33.5.tgz", - "integrity": "sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA==", - "optional": true, - "requires": { - "@img/sharp-libvips-linux-arm64": "1.0.4" - } - }, - "@img/sharp-linux-s390x": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.33.5.tgz", - "integrity": "sha512-y/5PCd+mP4CA/sPDKl2961b+C9d+vPAveS33s6Z3zfASk2j5upL6fXVPZi7ztePZ5CuH+1kW8JtvxgbuXHRa4Q==", - "optional": true, - "requires": { - "@img/sharp-libvips-linux-s390x": "1.0.4" - } - }, - "@img/sharp-linux-x64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.33.5.tgz", - "integrity": "sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA==", - "optional": true, - "requires": { - "@img/sharp-libvips-linux-x64": "1.0.4" - } - }, - "@img/sharp-linuxmusl-arm64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.33.5.tgz", - "integrity": "sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g==", - "optional": true, - "requires": { - "@img/sharp-libvips-linuxmusl-arm64": "1.0.4" - } - }, - "@img/sharp-linuxmusl-x64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.33.5.tgz", - "integrity": "sha512-WT+d/cgqKkkKySYmqoZ8y3pxx7lx9vVejxW/W4DOFMYVSkErR+w7mf2u8m/y4+xHe7yY9DAXQMWQhpnMuFfScw==", - "optional": true, - "requires": { - "@img/sharp-libvips-linuxmusl-x64": "1.0.4" - } - }, - "@img/sharp-wasm32": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.33.5.tgz", - "integrity": "sha512-ykUW4LVGaMcU9lu9thv85CbRMAwfeadCJHRsg2GmeRa/cJxsVY9Rbd57JcMxBkKHag5U/x7TSBpScF4U8ElVzg==", - "optional": true, - "requires": { - "@emnapi/runtime": "^1.2.0" - } - }, - "@img/sharp-win32-ia32": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.33.5.tgz", - "integrity": "sha512-T36PblLaTwuVJ/zw/LaH0PdZkRz5rd3SmMHX8GSmR7vtNSP5Z6bQkExdSK7xGWyxLw4sUknBuugTelgw2faBbQ==", - "optional": true - }, - "@img/sharp-win32-x64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.33.5.tgz", - "integrity": "sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg==", - "optional": true - }, - "@ioredis/commands": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@ioredis/commands/-/commands-1.2.0.tgz", - "integrity": "sha512-Sx1pU8EM64o2BrqNpEO1CNLtKQwyhuXuqyfH7oGKCk+1a33d2r5saW8zNwm3j6BTExtjrv2BxTgzzkMwts6vGg==" - }, - "@isaacs/cliui": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", - "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", - "requires": { - "string-width": "^5.1.2", - "string-width-cjs": "npm:string-width@^4.2.0", - "strip-ansi": "^7.0.1", - "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", - "wrap-ansi": "^8.1.0", - "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==" - }, - "ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==" - }, - "emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" - }, - "string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "requires": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - } - }, - "strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "requires": { - "ansi-regex": "^6.0.1" - } - }, - "wrap-ansi": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", - "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", - "requires": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" - } - } - } - }, - "@istanbuljs/schema": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", - "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", - "dev": true - }, - "@jridgewell/gen-mapping": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", - "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", - "requires": { - "@jridgewell/set-array": "^1.2.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.24" - } - }, - "@jridgewell/resolve-uri": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", - "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==" - }, - "@jridgewell/set-array": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", - "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==" - }, - "@jridgewell/source-map": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.5.tgz", - "integrity": "sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==", - "dev": true, - "requires": { - "@jridgewell/gen-mapping": "^0.3.0", - "@jridgewell/trace-mapping": "^0.3.9" - } - }, - "@jridgewell/sourcemap-codec": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", - "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==" - }, - "@jridgewell/trace-mapping": { - "version": "0.3.25", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", - "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", - "requires": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "@js-sdsl/ordered-map": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/@js-sdsl/ordered-map/-/ordered-map-4.4.2.tgz", - "integrity": "sha512-iUKgm52T8HOE/makSxjqoWhe95ZJA1/G1sYsGev2JDKUSS14KAgg1LHb+Ba+IPow0xflbnSkOsZcO08C7w1gYw==" - }, - "@ljharb/through": { - "version": "2.3.13", - "resolved": "https://registry.npmjs.org/@ljharb/through/-/through-2.3.13.tgz", - "integrity": "sha512-/gKJun8NNiWGZJkGzI/Ragc53cOdcLNdzjLaIa+GEjguQs0ulsurx8WN0jijdK9yPqDvziX995sMRLyLt1uZMQ==", - "dev": true, - "requires": { - "call-bind": "^1.0.7" - } - }, - "@lukeed/csprng": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@lukeed/csprng/-/csprng-1.1.0.tgz", - "integrity": "sha512-Z7C/xXCiGWsg0KuKsHTKJxbWhpI3Vs5GwLfOean7MGyVFGqdRgBbAjOCh6u4bbjPc/8MJ2pZmK/0DLdCbivLDA==" - }, - "@mapbox/node-pre-gyp": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz", - "integrity": "sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==", - "requires": { - "detect-libc": "^2.0.0", - "https-proxy-agent": "^5.0.0", - "make-dir": "^3.1.0", - "node-fetch": "^2.6.7", - "nopt": "^5.0.0", - "npmlog": "^5.0.1", - "rimraf": "^3.0.2", - "semver": "^7.3.5", - "tar": "^6.1.11" - }, - "dependencies": { - "glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "requires": { - "glob": "^7.1.3" - } - } - } - }, - "@microsoft/tsdoc": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/@microsoft/tsdoc/-/tsdoc-0.15.0.tgz", - "integrity": "sha512-HZpPoABogPvjeJOdzCOSJsXeL/SMCBgBZMVC3X3d7YYp2gf31MfxhUoYUNwf1ERPJOnQc0wkFn9trqI6ZEdZuA==" - }, - "@msgpackr-extract/msgpackr-extract-darwin-arm64": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-arm64/-/msgpackr-extract-darwin-arm64-3.0.2.tgz", - "integrity": "sha512-9bfjwDxIDWmmOKusUcqdS4Rw+SETlp9Dy39Xui9BEGEk19dDwH0jhipwFzEff/pFg95NKymc6TOTbRKcWeRqyQ==", - "optional": true - }, - "@nestjs/bull-shared": { - "version": "10.2.1", - "resolved": "https://registry.npmjs.org/@nestjs/bull-shared/-/bull-shared-10.2.1.tgz", - "integrity": "sha512-zvnTvSq6OJ92omcsFUwaUmPbM3PRgWkIusHPB5TE3IFS7nNdM3OwF+kfe56sgKjMtQQMe/56lok0S04OtPMX5Q==", - "requires": { - "tslib": "2.6.3" - } - }, - "@nestjs/bullmq": { - "version": "10.2.1", - "resolved": "https://registry.npmjs.org/@nestjs/bullmq/-/bullmq-10.2.1.tgz", - "integrity": "sha512-nDR0hDabmtXt5gsb5R786BJsGIJoWh/79sVmRETXf4S45+fvdqG1XkCKAeHF9TO9USodw9m+XBNKysTnkY41gw==", - "requires": { - "@nestjs/bull-shared": "^10.2.1", - "tslib": "2.6.3" - } - }, - "@nestjs/cli": { - "version": "10.4.5", - "resolved": "https://registry.npmjs.org/@nestjs/cli/-/cli-10.4.5.tgz", - "integrity": "sha512-FP7Rh13u8aJbHe+zZ7hM0CC4785g9Pw4lz4r2TTgRtf0zTxSWMkJaPEwyjX8SK9oWK2GsYxl+fKpwVZNbmnj9A==", - "dev": true, - "requires": { - "@angular-devkit/core": "17.3.8", - "@angular-devkit/schematics": "17.3.8", - "@angular-devkit/schematics-cli": "17.3.8", - "@nestjs/schematics": "^10.0.1", - "chalk": "4.1.2", - "chokidar": "3.6.0", - "cli-table3": "0.6.5", - "commander": "4.1.1", - "fork-ts-checker-webpack-plugin": "9.0.2", - "glob": "10.4.2", - "inquirer": "8.2.6", - "node-emoji": "1.11.0", - "ora": "5.4.1", - "tree-kill": "1.2.2", - "tsconfig-paths": "4.2.0", - "tsconfig-paths-webpack-plugin": "4.1.0", - "typescript": "5.3.3", - "webpack": "5.94.0", - "webpack-node-externals": "3.0.0" - }, - "dependencies": { - "typescript": { - "version": "5.3.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", - "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", - "dev": true - } - } - }, - "@nestjs/common": { - "version": "10.4.6", - "resolved": "https://registry.npmjs.org/@nestjs/common/-/common-10.4.6.tgz", - "integrity": "sha512-KkezkZvU9poWaNq4L+lNvx+386hpOxPJkfXBBeSMrcqBOx8kVr36TGN2uYkF4Ta4zNu1KbCjmZbc0rhHSg296g==", - "requires": { - "iterare": "1.2.1", - "tslib": "2.7.0", - "uid": "2.0.2" - }, - "dependencies": { - "tslib": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", - "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==" - } - } - }, - "@nestjs/core": { - "version": "10.4.6", - "resolved": "https://registry.npmjs.org/@nestjs/core/-/core-10.4.6.tgz", - "integrity": "sha512-zXVPxCNRfO6gAy0yvEDjUxE/8gfZICJFpsl2lZAUH31bPb6m+tXuhUq2mVCTEltyMYQ+DYtRe+fEYM2v152N1g==", - "requires": { - "@nuxtjs/opencollective": "0.3.2", - "fast-safe-stringify": "2.1.1", - "iterare": "1.2.1", - "path-to-regexp": "3.3.0", - "tslib": "2.7.0", - "uid": "2.0.2" - }, - "dependencies": { - "tslib": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", - "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==" - } - } - }, - "@nestjs/event-emitter": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@nestjs/event-emitter/-/event-emitter-2.1.1.tgz", - "integrity": "sha512-6L6fBOZTyfFlL7Ih/JDdqlCzZeCW0RjCX28wnzGyg/ncv5F/EOeT1dfopQr1loBRQ3LTgu8OWM7n4zLN4xigsg==", - "requires": { - "eventemitter2": "6.4.9" - } - }, - "@nestjs/mapped-types": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nestjs/mapped-types/-/mapped-types-2.0.5.tgz", - "integrity": "sha512-bSJv4pd6EY99NX9CjBIyn4TVDoSit82DUZlL4I3bqNfy5Gt+gXTa86i3I/i0iIV9P4hntcGM5GyO+FhZAhxtyg==", - "requires": {} - }, - "@nestjs/platform-express": { - "version": "10.4.6", - "resolved": "https://registry.npmjs.org/@nestjs/platform-express/-/platform-express-10.4.6.tgz", - "integrity": "sha512-HcyCpAKccAasrLSGRTGWv5BKRs0rwTIFOSsk6laNyqfqvgvYcJQAedarnm4jmaemtmSJ0PFI9PmtEZADd2ahCg==", - "requires": { - "body-parser": "1.20.3", - "cors": "2.8.5", - "express": "4.21.1", - "multer": "1.4.4-lts.1", - "tslib": "2.7.0" - }, - "dependencies": { - "tslib": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", - "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==" - } - } - }, - "@nestjs/platform-socket.io": { - "version": "10.4.6", - "resolved": "https://registry.npmjs.org/@nestjs/platform-socket.io/-/platform-socket.io-10.4.6.tgz", - "integrity": "sha512-lGv99O7C00wtnGq9M0mcwrOpH2qmuqAXQyvo/d/I7rmaf3OO1Sg8qWDLAnPKHdaumwOL2mnET3kvCJ06MaL6WA==", - "requires": { - "socket.io": "4.8.0", - "tslib": "2.7.0" - }, - "dependencies": { - "cookie": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", - "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==" - }, - "engine.io": { - "version": "6.6.2", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.6.2.tgz", - "integrity": "sha512-gmNvsYi9C8iErnZdVcJnvCpSKbWTt1E8+JZo8b+daLninywUWi5NQ5STSHZ9rFjFO7imNcvb8Pc5pe/wMR5xEw==", - "requires": { - "@types/cookie": "^0.4.1", - "@types/cors": "^2.8.12", - "@types/node": ">=10.0.0", - "accepts": "~1.3.4", - "base64id": "2.0.0", - "cookie": "~0.7.2", - "cors": "~2.8.5", - "debug": "~4.3.1", - "engine.io-parser": "~5.2.1", - "ws": "~8.17.1" - } - }, - "socket.io": { - "version": "4.8.0", - "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.8.0.tgz", - "integrity": "sha512-8U6BEgGjQOfGz3HHTYaC/L1GaxDCJ/KM0XTkJly0EhZ5U/du9uNEZy4ZgYzEzIqlx2CMm25CrCqr1ck899eLNA==", - "requires": { - "accepts": "~1.3.4", - "base64id": "~2.0.0", - "cors": "~2.8.5", - "debug": "~4.3.2", - "engine.io": "~6.6.0", - "socket.io-adapter": "~2.5.2", - "socket.io-parser": "~4.2.4" - } - }, - "tslib": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", - "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==" - } - } - }, - "@nestjs/schedule": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/@nestjs/schedule/-/schedule-4.1.1.tgz", - "integrity": "sha512-VxAnCiU4HP0wWw8IdWAVfsGC/FGjyToNjjUtXDEQL6oj+w/N5QDd2VT9k6d7Jbr8PlZuBZNdWtDKSkH5bZ+RXQ==", - "requires": { - "cron": "3.1.7", - "uuid": "10.0.0" - }, - "dependencies": { - "uuid": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-10.0.0.tgz", - "integrity": "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==" - } - } - }, - "@nestjs/schematics": { - "version": "10.2.2", - "resolved": "https://registry.npmjs.org/@nestjs/schematics/-/schematics-10.2.2.tgz", - "integrity": "sha512-D4pJ46E8llCA7WPr3cV6sfRqDlvnTjQWnF1fLyKYD3Ldl+KPtlLyIcxaqlLTB0YR9ItKNKIZTJzUehRxR7UUsQ==", - "dev": true, - "requires": { - "@angular-devkit/core": "17.3.10", - "@angular-devkit/schematics": "17.3.10", - "comment-json": "4.2.5", - "jsonc-parser": "3.3.1", - "pluralize": "8.0.0" - }, - "dependencies": { - "@angular-devkit/core": { - "version": "17.3.10", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-17.3.10.tgz", - "integrity": "sha512-czdl54yxU5DOAGy/uUPNjJruoBDTgwi/V+eOgLNybYhgrc+TsY0f7uJ11yEk/pz5sCov7xIiS7RdRv96waS7vg==", - "dev": true, - "requires": { - "ajv": "8.12.0", - "ajv-formats": "2.1.1", - "jsonc-parser": "3.2.1", - "picomatch": "4.0.1", - "rxjs": "7.8.1", - "source-map": "0.7.4" - }, - "dependencies": { - "jsonc-parser": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.1.tgz", - "integrity": "sha512-AilxAyFOAcK5wA1+LeaySVBrHsGQvUFCDWXKpZjzaL0PqW+xfBOttn8GNtWKFWqneyMZj41MWF9Kl6iPWLwgOA==", - "dev": true - } - } - }, - "@angular-devkit/schematics": { - "version": "17.3.10", - "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-17.3.10.tgz", - "integrity": "sha512-FHcNa1ktYRd0SKExCsNJpR75RffsyuPIV8kvBXzXnLHmXMqvl25G2te3yYJ9yYqy9OLy/58HZznZTxWRyUdHOg==", - "dev": true, - "requires": { - "@angular-devkit/core": "17.3.10", - "jsonc-parser": "3.2.1", - "magic-string": "0.30.8", - "ora": "5.4.1", - "rxjs": "7.8.1" - }, - "dependencies": { - "jsonc-parser": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.1.tgz", - "integrity": "sha512-AilxAyFOAcK5wA1+LeaySVBrHsGQvUFCDWXKpZjzaL0PqW+xfBOttn8GNtWKFWqneyMZj41MWF9Kl6iPWLwgOA==", - "dev": true - } - } - }, - "jsonc-parser": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.3.1.tgz", - "integrity": "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==", - "dev": true - }, - "picomatch": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.1.tgz", - "integrity": "sha512-xUXwsxNjwTQ8K3GnT4pCJm+xq3RUPQbmkYJTP5aFIfNIvbcc/4MUxgBaaRSZJ6yGJZiGSyYlM6MzwTsRk8SYCg==", - "dev": true - } - } - }, - "@nestjs/swagger": { - "version": "7.4.2", - "resolved": "https://registry.npmjs.org/@nestjs/swagger/-/swagger-7.4.2.tgz", - "integrity": "sha512-Mu6TEn1M/owIvAx2B4DUQObQXqo2028R2s9rSZ/hJEgBK95+doTwS0DjmVA2wTeZTyVtXOoN7CsoM5pONBzvKQ==", - "requires": { - "@microsoft/tsdoc": "^0.15.0", - "@nestjs/mapped-types": "2.0.5", - "js-yaml": "4.1.0", - "lodash": "4.17.21", - "path-to-regexp": "3.3.0", - "swagger-ui-dist": "5.17.14" - } - }, - "@nestjs/testing": { - "version": "10.4.6", - "resolved": "https://registry.npmjs.org/@nestjs/testing/-/testing-10.4.6.tgz", - "integrity": "sha512-aiDicKhlGibVGNYuew399H5qZZXaseOBT/BS+ERJxxCmco7ZdAqaujsNjSaSbTK9ojDPf27crLT0C4opjqJe3A==", - "dev": true, - "requires": { - "tslib": "2.7.0" - }, - "dependencies": { - "tslib": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", - "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", - "dev": true - } - } - }, - "@nestjs/typeorm": { - "version": "10.0.2", - "resolved": "https://registry.npmjs.org/@nestjs/typeorm/-/typeorm-10.0.2.tgz", - "integrity": "sha512-H738bJyydK4SQkRCTeh1aFBxoO1E9xdL/HaLGThwrqN95os5mEyAtK7BLADOS+vldP4jDZ2VQPLj4epWwRqCeQ==", - "requires": { - "uuid": "9.0.1" - } - }, - "@nestjs/websockets": { - "version": "10.4.6", - "resolved": "https://registry.npmjs.org/@nestjs/websockets/-/websockets-10.4.6.tgz", - "integrity": "sha512-53YqDQylPAOudNFiiBvrN8QrRl/sZ9oEjKbD3wBVgrFREbaiuTySoyyy6HwVs60HW29uQwck+Bp7qkKGjhtQKg==", - "requires": { - "iterare": "1.2.1", - "object-hash": "3.0.0", - "tslib": "2.7.0" - }, - "dependencies": { - "tslib": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", - "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==" - } - } - }, - "@next/env": { - "version": "14.2.3", - "resolved": "https://registry.npmjs.org/@next/env/-/env-14.2.3.tgz", - "integrity": "sha512-W7fd7IbkfmeeY2gXrzJYDx8D2lWKbVoTIj1o1ScPHNzvp30s1AuoEFSdr39bC5sjxJaxTtq3OTCZboNp0lNWHA==" - }, - "@next/swc-darwin-arm64": { - "version": "14.2.3", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.2.3.tgz", - "integrity": "sha512-3pEYo/RaGqPP0YzwnlmPN2puaF2WMLM3apt5jLW2fFdXD9+pqcoTzRk+iZsf8ta7+quAe4Q6Ms0nR0SFGFdS1A==", - "optional": true - }, - "@next/swc-darwin-x64": { - "version": "14.2.3", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-14.2.3.tgz", - "integrity": "sha512-6adp7waE6P1TYFSXpY366xwsOnEXM+y1kgRpjSRVI2CBDOcbRjsJ67Z6EgKIqWIue52d2q/Mx8g9MszARj8IEA==", - "optional": true - }, - "@next/swc-linux-arm64-gnu": { - "version": "14.2.3", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.2.3.tgz", - "integrity": "sha512-cuzCE/1G0ZSnTAHJPUT1rPgQx1w5tzSX7POXSLaS7w2nIUJUD+e25QoXD/hMfxbsT9rslEXugWypJMILBj/QsA==", - "optional": true - }, - "@next/swc-linux-arm64-musl": { - "version": "14.2.3", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.2.3.tgz", - "integrity": "sha512-0D4/oMM2Y9Ta3nGuCcQN8jjJjmDPYpHX9OJzqk42NZGJocU2MqhBq5tWkJrUQOQY9N+In9xOdymzapM09GeiZw==", - "optional": true - }, - "@next/swc-linux-x64-gnu": { - "version": "14.2.3", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.2.3.tgz", - "integrity": "sha512-ENPiNnBNDInBLyUU5ii8PMQh+4XLr4pG51tOp6aJ9xqFQ2iRI6IH0Ds2yJkAzNV1CfyagcyzPfROMViS2wOZ9w==", - "optional": true - }, - "@next/swc-linux-x64-musl": { - "version": "14.2.3", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.2.3.tgz", - "integrity": "sha512-BTAbq0LnCbF5MtoM7I/9UeUu/8ZBY0i8SFjUMCbPDOLv+un67e2JgyN4pmgfXBwy/I+RHu8q+k+MCkDN6P9ViQ==", - "optional": true - }, - "@next/swc-win32-arm64-msvc": { - "version": "14.2.3", - "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.2.3.tgz", - "integrity": "sha512-AEHIw/dhAMLNFJFJIJIyOFDzrzI5bAjI9J26gbO5xhAKHYTZ9Or04BesFPXiAYXDNdrwTP2dQceYA4dL1geu8A==", - "optional": true - }, - "@next/swc-win32-ia32-msvc": { - "version": "14.2.3", - "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.2.3.tgz", - "integrity": "sha512-vga40n1q6aYb0CLrM+eEmisfKCR45ixQYXuBXxOOmmoV8sYST9k7E3US32FsY+CkkF7NtzdcebiFT4CHuMSyZw==", - "optional": true - }, - "@next/swc-win32-x64-msvc": { - "version": "14.2.3", - "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.2.3.tgz", - "integrity": "sha512-Q1/zm43RWynxrO7lW4ehciQVj+5ePBhOK+/K2P7pLFX3JaJ/IZVC69SHidrmZSOkqz7ECIOhhy7XhAFG4JYyHA==", - "optional": true - }, - "@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "requires": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - } - }, - "@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==" - }, - "@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "requires": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - } - }, - "@nuxtjs/opencollective": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@nuxtjs/opencollective/-/opencollective-0.3.2.tgz", - "integrity": "sha512-um0xL3fO7Mf4fDxcqx9KryrB7zgRM5JSlvGN5AGkP6JLM5XEKyjeAiPbNxdXVXQ16isuAhYpvP88NgL2BGd6aA==", - "requires": { - "chalk": "^4.1.0", - "consola": "^2.15.0", - "node-fetch": "^2.6.1" - } - }, - "@one-ini/wasm": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@one-ini/wasm/-/wasm-0.1.1.tgz", - "integrity": "sha512-XuySG1E38YScSJoMlqovLru4KTUNSjgVTIjyh7qMX6aNN5HY5Ct5LhRJdxO79JtTzKfzV/bnWpz+zquYrISsvw==" - }, - "@opentelemetry/api": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.8.0.tgz", - "integrity": "sha512-I/s6F7yKUDdtMsoBWXJe8Qz40Tui5vsuKCWJEWVL+5q9sSWRzzx6v2KeNsOBEwd94j0eWkpWCH4yB6rZg9Mf0w==" - }, - "@opentelemetry/api-logs": { - "version": "0.54.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.54.0.tgz", - "integrity": "sha512-9HhEh5GqFrassUndqJsyW7a0PzfyWr2eV2xwzHLIS+wX3125+9HE9FMRAKmJRwxZhgZGwH3HNQQjoMGZqmOeVA==", - "requires": { - "@opentelemetry/api": "^1.3.0" - } - }, - "@opentelemetry/auto-instrumentations-node": { - "version": "0.52.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/auto-instrumentations-node/-/auto-instrumentations-node-0.52.0.tgz", - "integrity": "sha512-J9SgX7NOpTvQ7itvlOlHP3lTlsMWtVh5WQSHUSTlg2m3A9HlZBri2DtZ8QgNj8rYWe0EQxQ3TQ3H6vabfun4vw==", - "requires": { - "@opentelemetry/instrumentation": "^0.54.0", - "@opentelemetry/instrumentation-amqplib": "^0.43.0", - "@opentelemetry/instrumentation-aws-lambda": "^0.46.0", - "@opentelemetry/instrumentation-aws-sdk": "^0.45.0", - "@opentelemetry/instrumentation-bunyan": "^0.42.0", - "@opentelemetry/instrumentation-cassandra-driver": "^0.42.0", - "@opentelemetry/instrumentation-connect": "^0.40.0", - "@opentelemetry/instrumentation-cucumber": "^0.10.0", - "@opentelemetry/instrumentation-dataloader": "^0.13.0", - "@opentelemetry/instrumentation-dns": "^0.40.0", - "@opentelemetry/instrumentation-express": "^0.44.0", - "@opentelemetry/instrumentation-fastify": "^0.41.0", - "@opentelemetry/instrumentation-fs": "^0.16.0", - "@opentelemetry/instrumentation-generic-pool": "^0.40.0", - "@opentelemetry/instrumentation-graphql": "^0.44.0", - "@opentelemetry/instrumentation-grpc": "^0.54.0", - "@opentelemetry/instrumentation-hapi": "^0.42.0", - "@opentelemetry/instrumentation-http": "^0.54.0", - "@opentelemetry/instrumentation-ioredis": "^0.44.0", - "@opentelemetry/instrumentation-kafkajs": "^0.4.0", - "@opentelemetry/instrumentation-knex": "^0.41.0", - "@opentelemetry/instrumentation-koa": "^0.44.0", - "@opentelemetry/instrumentation-lru-memoizer": "^0.41.0", - "@opentelemetry/instrumentation-memcached": "^0.40.0", - "@opentelemetry/instrumentation-mongodb": "^0.48.0", - "@opentelemetry/instrumentation-mongoose": "^0.43.0", - "@opentelemetry/instrumentation-mysql": "^0.42.0", - "@opentelemetry/instrumentation-mysql2": "^0.42.0", - "@opentelemetry/instrumentation-nestjs-core": "^0.41.0", - "@opentelemetry/instrumentation-net": "^0.40.0", - "@opentelemetry/instrumentation-pg": "^0.47.0", - "@opentelemetry/instrumentation-pino": "^0.43.0", - "@opentelemetry/instrumentation-redis": "^0.43.0", - "@opentelemetry/instrumentation-redis-4": "^0.43.0", - "@opentelemetry/instrumentation-restify": "^0.42.0", - "@opentelemetry/instrumentation-router": "^0.41.0", - "@opentelemetry/instrumentation-socket.io": "^0.43.0", - "@opentelemetry/instrumentation-tedious": "^0.15.0", - "@opentelemetry/instrumentation-undici": "^0.7.0", - "@opentelemetry/instrumentation-winston": "^0.41.0", - "@opentelemetry/resource-detector-alibaba-cloud": "^0.29.4", - "@opentelemetry/resource-detector-aws": "^1.7.0", - "@opentelemetry/resource-detector-azure": "^0.2.12", - "@opentelemetry/resource-detector-container": "^0.5.0", - "@opentelemetry/resource-detector-gcp": "^0.29.13", - "@opentelemetry/resources": "^1.24.0", - "@opentelemetry/sdk-node": "^0.54.0" - } - }, - "@opentelemetry/context-async-hooks": { - "version": "1.27.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/context-async-hooks/-/context-async-hooks-1.27.0.tgz", - "integrity": "sha512-CdZ3qmHCwNhFAzjTgHqrDQ44Qxcpz43cVxZRhOs+Ns/79ug+Mr84Bkb626bkJLkA3+BLimA5YAEVRlJC6pFb7g==", - "requires": {} - }, - "@opentelemetry/core": { - "version": "1.27.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.27.0.tgz", - "integrity": "sha512-yQPKnK5e+76XuiqUH/gKyS8wv/7qITd5ln56QkBTf3uggr0VkXOXfcaAuG330UfdYu83wsyoBwqwxigpIG+Jkg==", - "requires": { - "@opentelemetry/semantic-conventions": "1.27.0" - } - }, - "@opentelemetry/exporter-logs-otlp-grpc": { - "version": "0.54.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-logs-otlp-grpc/-/exporter-logs-otlp-grpc-0.54.0.tgz", - "integrity": "sha512-CQC9xl9p8EIvx2KggdM7yffbpmUArKjiqAcjTTTEvqE8kOOf71NSuBU0FXs14FU8vBGTUlsr3oI4vGeWF8FakA==", - "requires": { - "@grpc/grpc-js": "^1.7.1", - "@opentelemetry/core": "1.27.0", - "@opentelemetry/otlp-grpc-exporter-base": "0.54.0", - "@opentelemetry/otlp-transformer": "0.54.0", - "@opentelemetry/sdk-logs": "0.54.0" - } - }, - "@opentelemetry/exporter-logs-otlp-http": { - "version": "0.54.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-logs-otlp-http/-/exporter-logs-otlp-http-0.54.0.tgz", - "integrity": "sha512-EX/5YPtFw5hugURWSmOtJEGsjphkwTRAiv2yay40ADCLEzajhI/tM3v/7hFCj+rm37sGFMNawpi3mGLvfKGexQ==", - "requires": { - "@opentelemetry/api-logs": "0.54.0", - "@opentelemetry/core": "1.27.0", - "@opentelemetry/otlp-exporter-base": "0.54.0", - "@opentelemetry/otlp-transformer": "0.54.0", - "@opentelemetry/sdk-logs": "0.54.0" - } - }, - "@opentelemetry/exporter-logs-otlp-proto": { - "version": "0.54.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-logs-otlp-proto/-/exporter-logs-otlp-proto-0.54.0.tgz", - "integrity": "sha512-Q8p1eLP6BGu26VdiR8qBiyufXTZimUl2kv6EwZZPLRU0CJWAFR562UOyUtDxbwQioQFq57DVjCd6mQWBvydAlg==", - "requires": { - "@opentelemetry/api-logs": "0.54.0", - "@opentelemetry/core": "1.27.0", - "@opentelemetry/otlp-exporter-base": "0.54.0", - "@opentelemetry/otlp-transformer": "0.54.0", - "@opentelemetry/resources": "1.27.0", - "@opentelemetry/sdk-logs": "0.54.0", - "@opentelemetry/sdk-trace-base": "1.27.0" - } - }, - "@opentelemetry/exporter-prometheus": { - "version": "0.54.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-prometheus/-/exporter-prometheus-0.54.0.tgz", - "integrity": "sha512-httb+/c36hZvkIR9SqwXj+fLeE2XDdWfZqGO24MboNMHihmnvjE0/LN29I9CjsJqC2jEi8FErfQha/JeOfsFaA==", - "requires": { - "@opentelemetry/core": "1.27.0", - "@opentelemetry/resources": "1.27.0", - "@opentelemetry/sdk-metrics": "1.27.0" - } - }, - "@opentelemetry/exporter-trace-otlp-grpc": { - "version": "0.54.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-trace-otlp-grpc/-/exporter-trace-otlp-grpc-0.54.0.tgz", - "integrity": "sha512-DOoK7yk/L/RHoyuYTxIyGY7PLFSTS7OGNks9htMS7eAFkm4Lsa6EtPlGANCT39NXWP4XIQR1c+Y+YIQ7lJdI+w==", - "requires": { - "@grpc/grpc-js": "^1.7.1", - "@opentelemetry/core": "1.27.0", - "@opentelemetry/otlp-grpc-exporter-base": "0.54.0", - "@opentelemetry/otlp-transformer": "0.54.0", - "@opentelemetry/resources": "1.27.0", - "@opentelemetry/sdk-trace-base": "1.27.0" - } - }, - "@opentelemetry/exporter-trace-otlp-http": { - "version": "0.54.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-trace-otlp-http/-/exporter-trace-otlp-http-0.54.0.tgz", - "integrity": "sha512-00X6rtr6Ew59+MM9pPSH7Ww5ScpWKBLiBA49awbPqQuVL/Bp0qp7O1cTxKHgjWdNkhsELzJxAEYwuRnDGrMXyA==", - "requires": { - "@opentelemetry/core": "1.27.0", - "@opentelemetry/otlp-exporter-base": "0.54.0", - "@opentelemetry/otlp-transformer": "0.54.0", - "@opentelemetry/resources": "1.27.0", - "@opentelemetry/sdk-trace-base": "1.27.0" - } - }, - "@opentelemetry/exporter-trace-otlp-proto": { - "version": "0.54.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-trace-otlp-proto/-/exporter-trace-otlp-proto-0.54.0.tgz", - "integrity": "sha512-cpDQj5wl7G8pLu3lW94SnMpn0C85A9Ehe7+JBow2IL5DGPWXTkynFngMtCC3PpQzQgzlyOVe0MVZfoBB3M5ECA==", - "requires": { - "@opentelemetry/core": "1.27.0", - "@opentelemetry/otlp-exporter-base": "0.54.0", - "@opentelemetry/otlp-transformer": "0.54.0", - "@opentelemetry/resources": "1.27.0", - "@opentelemetry/sdk-trace-base": "1.27.0" - } - }, - "@opentelemetry/exporter-zipkin": { - "version": "1.27.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-zipkin/-/exporter-zipkin-1.27.0.tgz", - "integrity": "sha512-eGMY3s4QprspFZojqsuQyQpWNFpo+oNVE/aosTbtvAlrJBAlvXcwwsOROOHOd8Y9lkU4i0FpQW482rcXkgwCSw==", - "requires": { - "@opentelemetry/core": "1.27.0", - "@opentelemetry/resources": "1.27.0", - "@opentelemetry/sdk-trace-base": "1.27.0", - "@opentelemetry/semantic-conventions": "1.27.0" - } - }, - "@opentelemetry/host-metrics": { - "version": "0.35.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/host-metrics/-/host-metrics-0.35.1.tgz", - "integrity": "sha512-d49/Un/pzqUSsGLeO8PvrX2bLxVAORcaoL3nxjJCzGikXA6gjWXxGOfT8D4qePlgnocozppWszefMHoRFS2MsA==", - "requires": { - "@opentelemetry/sdk-metrics": "^1.8.0", - "systeminformation": "^5.21.20" - } - }, - "@opentelemetry/instrumentation": { - "version": "0.54.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.54.0.tgz", - "integrity": "sha512-B0Ydo9g9ehgNHwtpc97XivEzjz0XBKR6iQ83NTENIxEEf5NHE0otZQuZLgDdey1XNk+bP1cfRpIkSFWM5YlSyg==", - "requires": { - "@opentelemetry/api-logs": "0.54.0", - "@types/shimmer": "^1.2.0", - "import-in-the-middle": "^1.8.1", - "require-in-the-middle": "^7.1.1", - "semver": "^7.5.2", - "shimmer": "^1.2.1" - } - }, - "@opentelemetry/instrumentation-amqplib": { - "version": "0.43.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-amqplib/-/instrumentation-amqplib-0.43.0.tgz", - "integrity": "sha512-ALjfQC+0dnIEcvNYsbZl/VLh7D2P1HhFF4vicRKHhHFIUV3Shpg4kXgiek5PLhmeKSIPiUB25IYH5RIneclL4A==", - "requires": { - "@opentelemetry/core": "^1.8.0", - "@opentelemetry/instrumentation": "^0.54.0", - "@opentelemetry/semantic-conventions": "^1.27.0" - } - }, - "@opentelemetry/instrumentation-aws-lambda": { - "version": "0.46.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-aws-lambda/-/instrumentation-aws-lambda-0.46.0.tgz", - "integrity": "sha512-rNmhTC1e1qQD4jw+TZSHlpLYNhrkbKA0P5rlqPpTVHqZXHQctu9+dity2lLBh4DlFKt4p/ibVDLVDoBqjvetKA==", - "requires": { - "@opentelemetry/instrumentation": "^0.54.0", - "@opentelemetry/propagator-aws-xray": "^1.3.1", - "@opentelemetry/semantic-conventions": "^1.27.0", - "@types/aws-lambda": "8.10.143" - } - }, - "@opentelemetry/instrumentation-aws-sdk": { - "version": "0.45.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-aws-sdk/-/instrumentation-aws-sdk-0.45.0.tgz", - "integrity": "sha512-3EGgC0LFZuFfXcOeslhXHhsiInVhhN046YQsYIPflsicAk7v0wN946sZKWuerEfmqx/kFXOsbOeI1SkkTRmqWQ==", - "requires": { - "@opentelemetry/core": "^1.8.0", - "@opentelemetry/instrumentation": "^0.54.0", - "@opentelemetry/propagation-utils": "^0.30.12", - "@opentelemetry/semantic-conventions": "^1.27.0" - } - }, - "@opentelemetry/instrumentation-bunyan": { - "version": "0.42.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-bunyan/-/instrumentation-bunyan-0.42.0.tgz", - "integrity": "sha512-GBh6ybwKmFZjc86SyHVx72jHg+4pFPaXT3IZgJ4QtnMsMf0/q5m2aHAjid+yakmEkApsnRWX8pJ8nkl1e+6mag==", - "requires": { - "@opentelemetry/api-logs": "^0.54.0", - "@opentelemetry/instrumentation": "^0.54.0", - "@types/bunyan": "1.8.9" - } - }, - "@opentelemetry/instrumentation-cassandra-driver": { - "version": "0.42.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-cassandra-driver/-/instrumentation-cassandra-driver-0.42.0.tgz", - "integrity": "sha512-35I9Gw4BeSs9NPe7fugu9e/mWKaapc/N1wounHnGt259/Q3ISGMOQRrOwIBw+x/XJygJvn4Ss1c+r5h89TsVAw==", - "requires": { - "@opentelemetry/instrumentation": "^0.54.0", - "@opentelemetry/semantic-conventions": "^1.27.0" - } - }, - "@opentelemetry/instrumentation-connect": { - "version": "0.40.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-connect/-/instrumentation-connect-0.40.0.tgz", - "integrity": "sha512-3aR/3YBQ160siitwwRLjwqrv2KBT16897+bo6yz8wIfel6nWOxTZBJudcbsK3p42pTC7qrbotJ9t/1wRLpv79Q==", - "requires": { - "@opentelemetry/core": "^1.8.0", - "@opentelemetry/instrumentation": "^0.54.0", - "@opentelemetry/semantic-conventions": "^1.27.0", - "@types/connect": "3.4.36" - } - }, - "@opentelemetry/instrumentation-cucumber": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-cucumber/-/instrumentation-cucumber-0.10.0.tgz", - "integrity": "sha512-5sT6Ap3W7StEL0Oax/vd1YTEcTPTefx+9myzkKrr72hxzFzSooGRCxlU3sfPwZqWptUV7+QWTMd7SqGEEPnE/w==", - "requires": { - "@opentelemetry/instrumentation": "^0.54.0", - "@opentelemetry/semantic-conventions": "^1.27.0" - } - }, - "@opentelemetry/instrumentation-dataloader": { - "version": "0.13.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-dataloader/-/instrumentation-dataloader-0.13.0.tgz", - "integrity": "sha512-wbU3WdgUAXljEIY2nfpkqID/VH70ThnES8mZZHKCZlV/Pl5T4+qmrVdT7U9/WUzz8flwsXfER6T6jl48Wbl+LQ==", - "requires": { - "@opentelemetry/instrumentation": "^0.54.0" - } - }, - "@opentelemetry/instrumentation-dns": { - "version": "0.40.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-dns/-/instrumentation-dns-0.40.0.tgz", - "integrity": "sha512-tLNR8XLPiYRKKk3/UqifXnPP2TVt1RcwvHU0R1ETL1xkZ1ZHMTmSC4x6TignnHOFtRixtJ05EgMGejnffaBXkQ==", - "requires": { - "@opentelemetry/instrumentation": "^0.54.0" - } - }, - "@opentelemetry/instrumentation-express": { - "version": "0.44.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-express/-/instrumentation-express-0.44.0.tgz", - "integrity": "sha512-GWgibp6Q0wxyFaaU8ERIgMMYgzcHmGrw3ILUtGchLtLncHNOKk0SNoWGqiylXWWT4HTn5XdV8MGawUgpZh80cA==", - "requires": { - "@opentelemetry/core": "^1.8.0", - "@opentelemetry/instrumentation": "^0.54.0", - "@opentelemetry/semantic-conventions": "^1.27.0" - } - }, - "@opentelemetry/instrumentation-fastify": { - "version": "0.41.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-fastify/-/instrumentation-fastify-0.41.0.tgz", - "integrity": "sha512-pNRjFvf0mvqfJueaeL/qEkuGJwgtE5pgjIHGYwjc2rMViNCrtY9/Sf+Nu8ww6dDd/Oyk2fwZZP7i0XZfCnETrA==", - "requires": { - "@opentelemetry/core": "^1.8.0", - "@opentelemetry/instrumentation": "^0.54.0", - "@opentelemetry/semantic-conventions": "^1.27.0" - } - }, - "@opentelemetry/instrumentation-fs": { - "version": "0.16.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-fs/-/instrumentation-fs-0.16.0.tgz", - "integrity": "sha512-hMDRUxV38ln1R3lNz6osj3YjlO32ykbHqVrzG7gEhGXFQfu7LJUx8t9tEwE4r2h3CD4D0Rw4YGDU4yF4mP3ilg==", - "requires": { - "@opentelemetry/core": "^1.8.0", - "@opentelemetry/instrumentation": "^0.54.0" - } - }, - "@opentelemetry/instrumentation-generic-pool": { - "version": "0.40.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-generic-pool/-/instrumentation-generic-pool-0.40.0.tgz", - "integrity": "sha512-k+/JlNDHN3bPi/Cir+Ew6tKHFVCa1ZFeQyGUw5HQkRX/twCRaN3kJFXJW+rDAN90XwK3RtC9AWwBihDGh/oSlQ==", - "requires": { - "@opentelemetry/instrumentation": "^0.54.0" - } - }, - "@opentelemetry/instrumentation-graphql": { - "version": "0.44.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-graphql/-/instrumentation-graphql-0.44.0.tgz", - "integrity": "sha512-FYXTe3Bv96aNpYktqm86BFUTpjglKD0kWI5T5bxYkLUPEPvFn38vWGMJTGrDMVou/i55E4jlWvcm6hFIqLsMbg==", - "requires": { - "@opentelemetry/instrumentation": "^0.54.0" - } - }, - "@opentelemetry/instrumentation-grpc": { - "version": "0.54.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-grpc/-/instrumentation-grpc-0.54.0.tgz", - "integrity": "sha512-IwLwAf1uC6I5lYjUxfvG0jFuppqNuaBIiaDxYFHMWeRX1Rejh4eqtQi2u+VVtSOHsCn2sRnS9hOxQ2w7+zzPLw==", - "requires": { - "@opentelemetry/instrumentation": "0.54.0", - "@opentelemetry/semantic-conventions": "1.27.0" - } - }, - "@opentelemetry/instrumentation-hapi": { - "version": "0.42.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-hapi/-/instrumentation-hapi-0.42.0.tgz", - "integrity": "sha512-TQC0BtIWLHrp6nKsYdZ5t5B7aiZ16BwbRqZtYYQxeJVsq/HQTANWpknjtA7KMxv5tAUMCrU/eDo8F3qioUOSZg==", - "requires": { - "@opentelemetry/core": "^1.8.0", - "@opentelemetry/instrumentation": "^0.54.0", - "@opentelemetry/semantic-conventions": "^1.27.0" - } - }, - "@opentelemetry/instrumentation-http": { - "version": "0.54.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-http/-/instrumentation-http-0.54.0.tgz", - "integrity": "sha512-ovl0UrL+vGpi0O7fdZ1mHRdiQkuv6NGMRBRKZZygVCUFNXdoqTpvJRRbTYih5U5FC+PHIFssEordmlblRCaGUg==", - "requires": { - "@opentelemetry/core": "1.27.0", - "@opentelemetry/instrumentation": "0.54.0", - "@opentelemetry/semantic-conventions": "1.27.0", - "forwarded-parse": "2.1.2", - "semver": "^7.5.2" - } - }, - "@opentelemetry/instrumentation-ioredis": { - "version": "0.44.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-ioredis/-/instrumentation-ioredis-0.44.0.tgz", - "integrity": "sha512-312pE2xc0ihX9haTf9WC4OF9in5EfVO1y5I8Ef9aMQKJNhuSe3IgzQAqGoLfaYajC+ig0IZ9SQKU8mRbFwHU+A==", - "requires": { - "@opentelemetry/instrumentation": "^0.54.0", - "@opentelemetry/redis-common": "^0.36.2", - "@opentelemetry/semantic-conventions": "^1.27.0" - } - }, - "@opentelemetry/instrumentation-kafkajs": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-kafkajs/-/instrumentation-kafkajs-0.4.0.tgz", - "integrity": "sha512-I9VwDG314g7SDL4t8kD/7+1ytaDBRbZQjhVaQaVIDR8K+mlsoBhLsWH79yHxhHQKvwCSZwqXF+TiTOhoQVUt7A==", - "requires": { - "@opentelemetry/instrumentation": "^0.54.0", - "@opentelemetry/semantic-conventions": "^1.27.0" - } - }, - "@opentelemetry/instrumentation-knex": { - "version": "0.41.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-knex/-/instrumentation-knex-0.41.0.tgz", - "integrity": "sha512-OhI1SlLv5qnsnm2dOVrian/x3431P75GngSpnR7c4fcVFv7prXGYu29Z6ILRWJf/NJt6fkbySmwdfUUnFnHCTg==", - "requires": { - "@opentelemetry/instrumentation": "^0.54.0", - "@opentelemetry/semantic-conventions": "^1.27.0" - } - }, - "@opentelemetry/instrumentation-koa": { - "version": "0.44.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-koa/-/instrumentation-koa-0.44.0.tgz", - "integrity": "sha512-ryPqGIQ4hpMGd85bAGjRMDAy/ic+Qdh1GtFGJo9KaXdzbcvZoF1ZgXVsKTYDxbD1n5C0BoQy6rcWg8Lu68iCJA==", - "requires": { - "@opentelemetry/core": "^1.8.0", - "@opentelemetry/instrumentation": "^0.54.0", - "@opentelemetry/semantic-conventions": "^1.27.0" - } - }, - "@opentelemetry/instrumentation-lru-memoizer": { - "version": "0.41.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-lru-memoizer/-/instrumentation-lru-memoizer-0.41.0.tgz", - "integrity": "sha512-6OePkk4RYCPVsnS0TroEK6UZzxxxjVWaE6EPdOn2qxGHMtm+Qb80tiBQ6BbmC+f7bjc27O85JY8gxeTybhHZXw==", - "requires": { - "@opentelemetry/instrumentation": "^0.54.0" - } - }, - "@opentelemetry/instrumentation-memcached": { - "version": "0.40.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-memcached/-/instrumentation-memcached-0.40.0.tgz", - "integrity": "sha512-VzJUUH6cVz8yrb25RvvjhxCpwu4vUk28I0m5nnnhebULOo8p9lda5PgQeVde2+jQAd977C/vN714fkbYOmwb+A==", - "requires": { - "@opentelemetry/instrumentation": "^0.54.0", - "@opentelemetry/semantic-conventions": "^1.27.0", - "@types/memcached": "^2.2.6" - } - }, - "@opentelemetry/instrumentation-mongodb": { - "version": "0.48.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-mongodb/-/instrumentation-mongodb-0.48.0.tgz", - "integrity": "sha512-9YWvaGvrrcrydMsYGLu0w+RgmosLMKe3kv/UNlsPy8RLnCkN2z+bhhbjjjuxtUmvEuKZMCoXFluABVuBr1yhjw==", - "requires": { - "@opentelemetry/instrumentation": "^0.54.0", - "@opentelemetry/semantic-conventions": "^1.27.0" - } - }, - "@opentelemetry/instrumentation-mongoose": { - "version": "0.43.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-mongoose/-/instrumentation-mongoose-0.43.0.tgz", - "integrity": "sha512-y1mWuL/zb6IKi199HkROgmStxF/ybEsnKYgx+/lpLATd57oZHOqrXP9tLmp9qRVI5c6P5XEWfe7ZCvrj07iDMQ==", - "requires": { - "@opentelemetry/core": "^1.8.0", - "@opentelemetry/instrumentation": "^0.54.0", - "@opentelemetry/semantic-conventions": "^1.27.0" - } - }, - "@opentelemetry/instrumentation-mysql": { - "version": "0.42.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-mysql/-/instrumentation-mysql-0.42.0.tgz", - "integrity": "sha512-1GN2EBGVSZABGQ25MSz3faeBW/DwhzmE10aNW1/A2mvQAxF1CvpMk17YmNUzwapVt29iKsiU3SXQG7vjh/019A==", - "requires": { - "@opentelemetry/instrumentation": "^0.54.0", - "@opentelemetry/semantic-conventions": "^1.27.0", - "@types/mysql": "2.15.26" - } - }, - "@opentelemetry/instrumentation-mysql2": { - "version": "0.42.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-mysql2/-/instrumentation-mysql2-0.42.0.tgz", - "integrity": "sha512-CQqOjCbHwEnaC+Bd6Sms+82iJkSbPpd7jD7Jwif7q8qXo6yrKLVDYDVK+zKbfnmQtu2xHaHj+xiq4tyjb3sMfg==", - "requires": { - "@opentelemetry/instrumentation": "^0.54.0", - "@opentelemetry/semantic-conventions": "^1.27.0", - "@opentelemetry/sql-common": "^0.40.1" - } - }, - "@opentelemetry/instrumentation-nestjs-core": { - "version": "0.41.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-nestjs-core/-/instrumentation-nestjs-core-0.41.0.tgz", - "integrity": "sha512-XCqtghFktpcJ2BOaJtFfqtTMsHffJADxfYhJl28WT6ygCChS2uZVxMKKLsy+i9VtPaw/i1IumPICL6mbhwq+Vw==", - "requires": { - "@opentelemetry/instrumentation": "^0.54.0", - "@opentelemetry/semantic-conventions": "^1.27.0" - } - }, - "@opentelemetry/instrumentation-net": { - "version": "0.40.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-net/-/instrumentation-net-0.40.0.tgz", - "integrity": "sha512-abErnVRxTmtiF7EvBISW81Se2nj/j3Xtpfy//9++dgvDOXwbcD1Xz1via6ZHOm/VamboGhqPlYiO7ABzluPLwg==", - "requires": { - "@opentelemetry/instrumentation": "^0.54.0", - "@opentelemetry/semantic-conventions": "^1.27.0" - } - }, - "@opentelemetry/instrumentation-pg": { - "version": "0.47.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-pg/-/instrumentation-pg-0.47.0.tgz", - "integrity": "sha512-aKu5PCeUv3S8s1wq60JZ2o3DWV2wqvO7WAktjmkx5wXd2+tZRfyDCKFHbP90QuDG1HDzjJ138Ob4d4rJdPETCQ==", - "requires": { - "@opentelemetry/core": "^1.26.0", - "@opentelemetry/instrumentation": "^0.54.0", - "@opentelemetry/semantic-conventions": "1.27.0", - "@opentelemetry/sql-common": "^0.40.1", - "@types/pg": "8.6.1", - "@types/pg-pool": "2.0.6" - }, - "dependencies": { - "@types/pg": { - "version": "8.6.1", - "resolved": "https://registry.npmjs.org/@types/pg/-/pg-8.6.1.tgz", - "integrity": "sha512-1Kc4oAGzAl7uqUStZCDvaLFqZrW9qWSjXOmBfdgyBP5La7Us6Mg4GBvRlSoaZMhQF/zSj1C8CtKMBkoiT8eL8w==", - "requires": { - "@types/node": "*", - "pg-protocol": "*", - "pg-types": "^2.2.0" - } - } - } - }, - "@opentelemetry/instrumentation-pino": { - "version": "0.43.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-pino/-/instrumentation-pino-0.43.0.tgz", - "integrity": "sha512-jlOOgbODWRRNknWXY1VLgmqgG0SO4kLgU3XnejjO/3De4OisroAsMGk+1cRB5AQ6WZ8WLAMkMyTShaOe6j2Asw==", - "requires": { - "@opentelemetry/api-logs": "^0.54.0", - "@opentelemetry/core": "^1.25.0", - "@opentelemetry/instrumentation": "^0.54.0" - } - }, - "@opentelemetry/instrumentation-redis": { - "version": "0.43.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-redis/-/instrumentation-redis-0.43.0.tgz", - "integrity": "sha512-dufe08W3sCOjutbTJmV6tg2Y3+7IBe59oQrnIW2RCgjRhsW0Jjaenezt490eawO0MdXjUfFyrIUg8WetKhE4xA==", - "requires": { - "@opentelemetry/instrumentation": "^0.54.0", - "@opentelemetry/redis-common": "^0.36.2", - "@opentelemetry/semantic-conventions": "^1.27.0" - } - }, - "@opentelemetry/instrumentation-redis-4": { - "version": "0.43.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-redis-4/-/instrumentation-redis-4-0.43.0.tgz", - "integrity": "sha512-6B2+CFRY9xRnkeZrSvlTyY2yB/zAgxjbXS5EwXhE3ZAKR1hWWoUzaTADIKT5xe9/VbDW42U3UoOPCcaCmeAXww==", - "requires": { - "@opentelemetry/instrumentation": "^0.54.0", - "@opentelemetry/redis-common": "^0.36.2", - "@opentelemetry/semantic-conventions": "^1.27.0" - } - }, - "@opentelemetry/instrumentation-restify": { - "version": "0.42.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-restify/-/instrumentation-restify-0.42.0.tgz", - "integrity": "sha512-ApDD9HNy6de6xrHmISEfkQHwwX1f1JrBj0ADnlk6tVdJ0j/vNmsZNLwaU2IA2K3mHqbp2YLarLgxAZp6rjcfWg==", - "requires": { - "@opentelemetry/core": "^1.8.0", - "@opentelemetry/instrumentation": "^0.54.0", - "@opentelemetry/semantic-conventions": "^1.27.0" - } - }, - "@opentelemetry/instrumentation-router": { - "version": "0.41.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-router/-/instrumentation-router-0.41.0.tgz", - "integrity": "sha512-IbvzgaoylMqStOOtwucEvSu5CDbfQN+H1ZZ2p6c9Kmvzptqh6G441GFy0FFVVqxOAHNhQm2w6n0Ag8trdBjCfw==", - "requires": { - "@opentelemetry/instrumentation": "^0.54.0", - "@opentelemetry/semantic-conventions": "^1.27.0" - } - }, - "@opentelemetry/instrumentation-socket.io": { - "version": "0.43.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-socket.io/-/instrumentation-socket.io-0.43.0.tgz", - "integrity": "sha512-HAQoIZ6N/ey1L4jF69gmqo7RyeSv5rc4sZZAd1v6SVaB8ZolTEyWEzGlu1NRZZTnqfWNxDkX6J1/omWpDd9k0w==", - "requires": { - "@opentelemetry/instrumentation": "^0.54.0", - "@opentelemetry/semantic-conventions": "^1.27.0" - } - }, - "@opentelemetry/instrumentation-tedious": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-tedious/-/instrumentation-tedious-0.15.0.tgz", - "integrity": "sha512-Kb7yo8Zsq2TUwBbmwYgTAMPK0VbhoS8ikJ6Bup9KrDtCx2JC01nCb+M0VJWXt7tl0+5jARUbKWh5jRSoImxdCw==", - "requires": { - "@opentelemetry/instrumentation": "^0.54.0", - "@opentelemetry/semantic-conventions": "^1.27.0", - "@types/tedious": "^4.0.14" - } - }, - "@opentelemetry/instrumentation-undici": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-undici/-/instrumentation-undici-0.7.0.tgz", - "integrity": "sha512-1AAqbVt1QOLgnc9DEkHS2R/0FIPI74ud5qgitwP9sVYzRg6e66bPSoAIARCyuANJrWCUrfgI69vLTfRxhBM+3A==", - "requires": { - "@opentelemetry/core": "^1.8.0", - "@opentelemetry/instrumentation": "^0.54.0" - } - }, - "@opentelemetry/instrumentation-winston": { - "version": "0.41.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-winston/-/instrumentation-winston-0.41.0.tgz", - "integrity": "sha512-qtqGDx2Plu71s9xaeXut0YgZFG/y68ENG9vvo/SODeEC+4/APiS/htQ5YNJIxxjOuxYowdFYRqV9Kmef2EUzmw==", - "requires": { - "@opentelemetry/api-logs": "^0.54.0", - "@opentelemetry/instrumentation": "^0.54.0" - } - }, - "@opentelemetry/otlp-exporter-base": { - "version": "0.54.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-exporter-base/-/otlp-exporter-base-0.54.0.tgz", - "integrity": "sha512-g+H7+QleVF/9lz4zhaR9Dt4VwApjqG5WWupy5CTMpWJfHB/nLxBbX73GBZDgdiNfh08nO3rNa6AS7fK8OhgF5g==", - "requires": { - "@opentelemetry/core": "1.27.0", - "@opentelemetry/otlp-transformer": "0.54.0" - } - }, - "@opentelemetry/otlp-grpc-exporter-base": { - "version": "0.54.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-grpc-exporter-base/-/otlp-grpc-exporter-base-0.54.0.tgz", - "integrity": "sha512-Yl2Dw0jlRWisEia9Hv/N8u2JLITCvzA6gAIKEvxpEu6nwHEftD2WhTJMIclkTtfmSW0rLmEEXymwmboG4xDN0Q==", - "requires": { - "@grpc/grpc-js": "^1.7.1", - "@opentelemetry/core": "1.27.0", - "@opentelemetry/otlp-exporter-base": "0.54.0", - "@opentelemetry/otlp-transformer": "0.54.0" - } - }, - "@opentelemetry/otlp-transformer": { - "version": "0.54.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-transformer/-/otlp-transformer-0.54.0.tgz", - "integrity": "sha512-jRexIASQQzdK4AjfNIBfn94itAq4Q8EXR9d3b/OVbhd3kKQKvMr7GkxYDjbeTbY7hHCOLcLfJ3dpYQYGOe8qOQ==", - "requires": { - "@opentelemetry/api-logs": "0.54.0", - "@opentelemetry/core": "1.27.0", - "@opentelemetry/resources": "1.27.0", - "@opentelemetry/sdk-logs": "0.54.0", - "@opentelemetry/sdk-metrics": "1.27.0", - "@opentelemetry/sdk-trace-base": "1.27.0", - "protobufjs": "^7.3.0" - } - }, - "@opentelemetry/propagation-utils": { - "version": "0.30.12", - "resolved": "https://registry.npmjs.org/@opentelemetry/propagation-utils/-/propagation-utils-0.30.12.tgz", - "integrity": "sha512-bgab3q/4dYUutUpQCEaSDa+mLoQJG3vJKeSiGuhM4iZaSpkz8ov0fs1MGil5PfxCo6Hhw3bB3bFYhUtnsfT/Pg==", - "requires": {} - }, - "@opentelemetry/propagator-aws-xray": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/propagator-aws-xray/-/propagator-aws-xray-1.3.1.tgz", - "integrity": "sha512-6fDMzFlt5r6VWv7MUd0eOpglXPFqykW8CnOuUxJ1VZyLy6mV1bzBlzpsqEmhx1bjvZYvH93vhGkQZqrm95mlrQ==", - "requires": { - "@opentelemetry/core": "^1.0.0" - } - }, - "@opentelemetry/propagator-b3": { - "version": "1.27.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/propagator-b3/-/propagator-b3-1.27.0.tgz", - "integrity": "sha512-pTsko3gnMioe3FeWcwTQR3omo5C35tYsKKwjgTCTVCgd3EOWL9BZrMfgLBmszrwXABDfUrlAEFN/0W0FfQGynQ==", - "requires": { - "@opentelemetry/core": "1.27.0" - } - }, - "@opentelemetry/propagator-jaeger": { - "version": "1.27.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/propagator-jaeger/-/propagator-jaeger-1.27.0.tgz", - "integrity": "sha512-EI1bbK0wn0yIuKlc2Qv2LKBRw6LiUWevrjCF80fn/rlaB+7StAi8Y5s8DBqAYNpY7v1q86+NjU18v7hj2ejU3A==", - "requires": { - "@opentelemetry/core": "1.27.0" - } - }, - "@opentelemetry/redis-common": { - "version": "0.36.2", - "resolved": "https://registry.npmjs.org/@opentelemetry/redis-common/-/redis-common-0.36.2.tgz", - "integrity": "sha512-faYX1N0gpLhej/6nyp6bgRjzAKXn5GOEMYY7YhciSfCoITAktLUtQ36d24QEWNA1/WA1y6qQunCe0OhHRkVl9g==" - }, - "@opentelemetry/resource-detector-alibaba-cloud": { - "version": "0.29.4", - "resolved": "https://registry.npmjs.org/@opentelemetry/resource-detector-alibaba-cloud/-/resource-detector-alibaba-cloud-0.29.4.tgz", - "integrity": "sha512-U3sWPoBXiEE51jJGhRrW19hLvrRbBbZWTp3Yc7IaRVFODNNzmibOolyi2ow1XN68UgRT4BRuwgwbnM5GbG/E5Q==", - "requires": { - "@opentelemetry/core": "^1.26.0", - "@opentelemetry/resources": "^1.10.0", - "@opentelemetry/semantic-conventions": "^1.27.0" - } - }, - "@opentelemetry/resource-detector-aws": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/resource-detector-aws/-/resource-detector-aws-1.7.0.tgz", - "integrity": "sha512-VxrwUi/9QcVIV+40d/jOKQthfD/E4/ppQ9FsYpDH7qy16cOO5519QOdihCQJYpVNbgDqf6q3hVrCy1f8UuG8YA==", - "requires": { - "@opentelemetry/core": "^1.0.0", - "@opentelemetry/resources": "^1.10.0", - "@opentelemetry/semantic-conventions": "^1.27.0" - } - }, - "@opentelemetry/resource-detector-azure": { - "version": "0.2.12", - "resolved": "https://registry.npmjs.org/@opentelemetry/resource-detector-azure/-/resource-detector-azure-0.2.12.tgz", - "integrity": "sha512-iIarQu6MiCjEEp8dOzmBvCSlRITPFTinFB2oNKAjU6xhx8d7eUcjNOKhBGQTvuCriZrxrEvDaEEY9NfrPQ6uYQ==", - "requires": { - "@opentelemetry/core": "^1.25.1", - "@opentelemetry/resources": "^1.10.1", - "@opentelemetry/semantic-conventions": "^1.27.0" - } - }, - "@opentelemetry/resource-detector-container": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/resource-detector-container/-/resource-detector-container-0.5.0.tgz", - "integrity": "sha512-ozp+ggcbl17xFfL91+DFgP8nmfzthNLxVTDOQUVgQgngVsSaBb5/I1Tnt63ZX2GCMdBJTxUBbFsqFvO0CjfGLg==", - "requires": { - "@opentelemetry/core": "^1.26.0", - "@opentelemetry/resources": "^1.10.0", - "@opentelemetry/semantic-conventions": "^1.27.0" - } - }, - "@opentelemetry/resource-detector-gcp": { - "version": "0.29.13", - "resolved": "https://registry.npmjs.org/@opentelemetry/resource-detector-gcp/-/resource-detector-gcp-0.29.13.tgz", - "integrity": "sha512-vdotx+l3Q+89PeyXMgKEGnZ/CwzwMtuMi/ddgD9/5tKZ08DfDGB2Npz9m2oXPHRCjc4Ro6ifMqFlRyzIvgOjhg==", - "requires": { - "@opentelemetry/core": "^1.0.0", - "@opentelemetry/resources": "^1.10.0", - "@opentelemetry/semantic-conventions": "^1.27.0", - "gcp-metadata": "^6.0.0" - } - }, - "@opentelemetry/resources": { - "version": "1.27.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.27.0.tgz", - "integrity": "sha512-jOwt2VJ/lUD5BLc+PMNymDrUCpm5PKi1E9oSVYAvz01U/VdndGmrtV3DU1pG4AwlYhJRHbHfOUIlpBeXCPw6QQ==", - "requires": { - "@opentelemetry/core": "1.27.0", - "@opentelemetry/semantic-conventions": "1.27.0" - } - }, - "@opentelemetry/sdk-logs": { - "version": "0.54.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-logs/-/sdk-logs-0.54.0.tgz", - "integrity": "sha512-HeWvOPiWhEw6lWvg+lCIi1WhJnIPbI4/OFZgHq9tKfpwF3LX6/kk3+GR8sGUGAEZfbjPElkkngzvd2s03zbD7Q==", - "requires": { - "@opentelemetry/api-logs": "0.54.0", - "@opentelemetry/core": "1.27.0", - "@opentelemetry/resources": "1.27.0" - } - }, - "@opentelemetry/sdk-metrics": { - "version": "1.27.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-metrics/-/sdk-metrics-1.27.0.tgz", - "integrity": "sha512-JzWgzlutoXCydhHWIbLg+r76m+m3ncqvkCcsswXAQ4gqKS+LOHKhq+t6fx1zNytvLuaOUBur7EvWxECc4jPQKg==", - "requires": { - "@opentelemetry/core": "1.27.0", - "@opentelemetry/resources": "1.27.0" - } - }, - "@opentelemetry/sdk-node": { - "version": "0.54.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-node/-/sdk-node-0.54.0.tgz", - "integrity": "sha512-F0mdwb4WPFJNypcmkxQnj3sIfh/73zkBgYePXMK8ghsBwYw4+PgM3/85WT6NzNUeOvWtiXacx5CFft2o7rGW3w==", - "requires": { - "@opentelemetry/api-logs": "0.54.0", - "@opentelemetry/core": "1.27.0", - "@opentelemetry/exporter-logs-otlp-grpc": "0.54.0", - "@opentelemetry/exporter-logs-otlp-http": "0.54.0", - "@opentelemetry/exporter-logs-otlp-proto": "0.54.0", - "@opentelemetry/exporter-trace-otlp-grpc": "0.54.0", - "@opentelemetry/exporter-trace-otlp-http": "0.54.0", - "@opentelemetry/exporter-trace-otlp-proto": "0.54.0", - "@opentelemetry/exporter-zipkin": "1.27.0", - "@opentelemetry/instrumentation": "0.54.0", - "@opentelemetry/resources": "1.27.0", - "@opentelemetry/sdk-logs": "0.54.0", - "@opentelemetry/sdk-metrics": "1.27.0", - "@opentelemetry/sdk-trace-base": "1.27.0", - "@opentelemetry/sdk-trace-node": "1.27.0", - "@opentelemetry/semantic-conventions": "1.27.0" - } - }, - "@opentelemetry/sdk-trace-base": { - "version": "1.27.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.27.0.tgz", - "integrity": "sha512-btz6XTQzwsyJjombpeqCX6LhiMQYpzt2pIYNPnw0IPO/3AhT6yjnf8Mnv3ZC2A4eRYOjqrg+bfaXg9XHDRJDWQ==", - "requires": { - "@opentelemetry/core": "1.27.0", - "@opentelemetry/resources": "1.27.0", - "@opentelemetry/semantic-conventions": "1.27.0" - } - }, - "@opentelemetry/sdk-trace-node": { - "version": "1.27.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-node/-/sdk-trace-node-1.27.0.tgz", - "integrity": "sha512-dWZp/dVGdUEfRBjBq2BgNuBlFqHCxyyMc8FsN0NX15X07mxSUO0SZRLyK/fdAVrde8nqFI/FEdMH4rgU9fqJfQ==", - "requires": { - "@opentelemetry/context-async-hooks": "1.27.0", - "@opentelemetry/core": "1.27.0", - "@opentelemetry/propagator-b3": "1.27.0", - "@opentelemetry/propagator-jaeger": "1.27.0", - "@opentelemetry/sdk-trace-base": "1.27.0", - "semver": "^7.5.2" - } - }, - "@opentelemetry/semantic-conventions": { - "version": "1.27.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.27.0.tgz", - "integrity": "sha512-sAay1RrB+ONOem0OZanAR1ZI/k7yDpnOQSQmTMuGImUQb2y8EbSaCJ94FQluM74xoU03vlb2d2U90hZluL6nQg==" - }, - "@opentelemetry/sql-common": { - "version": "0.40.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/sql-common/-/sql-common-0.40.1.tgz", - "integrity": "sha512-nSDlnHSqzC3pXn/wZEZVLuAuJ1MYMXPBwtv2qAbCa3847SaHItdE7SzUq/Jtb0KZmh1zfAbNi3AAMjztTT4Ugg==", - "requires": { - "@opentelemetry/core": "^1.1.0" - } - }, - "@photostructure/tz-lookup": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/@photostructure/tz-lookup/-/tz-lookup-11.0.0.tgz", - "integrity": "sha512-QMV5/dWtY/MdVPXZs/EApqzyhnqDq1keYEqpS+Xj2uidyaqw2Nk/fWcsszdruIXjdqp1VoWNzsgrO6bUHU1mFw==" - }, - "@pkgjs/parseargs": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", - "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", - "optional": true - }, - "@pkgr/core": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.0.tgz", - "integrity": "sha512-Zwq5OCzuwJC2jwqmpEQt7Ds1DTi6BWSwoGkbb1n9pO3hzb35BoJELx7c0T23iDkBGkh2e7tvOtjF3tr3OaQHDQ==", - "dev": true - }, - "@polka/url": { - "version": "1.0.0-next.25", - "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.25.tgz", - "integrity": "sha512-j7P6Rgr3mmtdkeDGTe0E/aYyWEWVtc5yFXtHCRHs28/jptDEWfaVOc5T7cblqy1XKPPfCxJc/8DwQ5YgLOZOVQ==" - }, - "@protobufjs/aspromise": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", - "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==" - }, - "@protobufjs/base64": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", - "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==" - }, - "@protobufjs/codegen": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", - "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==" - }, - "@protobufjs/eventemitter": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", - "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==" - }, - "@protobufjs/fetch": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", - "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", - "requires": { - "@protobufjs/aspromise": "^1.1.1", - "@protobufjs/inquire": "^1.1.0" - } - }, - "@protobufjs/float": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", - "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==" - }, - "@protobufjs/inquire": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", - "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==" - }, - "@protobufjs/path": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", - "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==" - }, - "@protobufjs/pool": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", - "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==" - }, - "@protobufjs/utf8": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", - "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==" - }, - "@react-email/body": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/@react-email/body/-/body-0.0.10.tgz", - "integrity": "sha512-dMJyL9aU25ieatdPtVjCyQ/WHZYHwNc+Hy/XpF8Cc18gu21cUynVEeYQzFSeigDRMeBQ3PGAyjVDPIob7YlGwA==", - "requires": {} - }, - "@react-email/button": { - "version": "0.0.17", - "resolved": "https://registry.npmjs.org/@react-email/button/-/button-0.0.17.tgz", - "integrity": "sha512-ioHdsk+BpGS/PqjU6JS7tUrVy9yvbUx92Z+Cem2+MbYp55oEwQ9VHf7u4f5NoM0gdhfKSehBwRdYlHt/frEMcg==", - "requires": {} - }, - "@react-email/code-block": { - "version": "0.0.9", - "resolved": "https://registry.npmjs.org/@react-email/code-block/-/code-block-0.0.9.tgz", - "integrity": "sha512-Zrhc71VYrSC1fVXJuaViKoB/dBjxLw6nbE53Bm/eUuZPdnnZ1+ZUIh8jfaRKC5MzMjgnLGQTweGXVnfIrhyxtQ==", - "requires": { - "prismjs": "1.29.0" - } - }, - "@react-email/code-inline": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/@react-email/code-inline/-/code-inline-0.0.4.tgz", - "integrity": "sha512-zj3oMQiiUCZbddSNt3k0zNfIBFK0ZNDIzzDyBaJKy6ZASTtWfB+1WFX0cpTX8q0gUiYK+A94rk5Qp68L6YXjXQ==", - "requires": {} - }, - "@react-email/column": { - "version": "0.0.12", - "resolved": "https://registry.npmjs.org/@react-email/column/-/column-0.0.12.tgz", - "integrity": "sha512-Rsl7iSdDaeHZO938xb+0wR5ud0Z3MVfdtPbNKJNojZi2hApwLAQXmDrnn/AcPDM5Lpl331ZljJS8vHTWxxkvKw==", - "requires": {} - }, - "@react-email/components": { - "version": "0.0.25", - "resolved": "https://registry.npmjs.org/@react-email/components/-/components-0.0.25.tgz", - "integrity": "sha512-lnfVVrThEcET5NPoeaXvrz9UxtWpGRcut2a07dLbyKgNbP7vj/cXTI5TuHtanCvhCddFpMDnElNRghDOfPzwUg==", - "requires": { - "@react-email/body": "0.0.10", - "@react-email/button": "0.0.17", - "@react-email/code-block": "0.0.9", - "@react-email/code-inline": "0.0.4", - "@react-email/column": "0.0.12", - "@react-email/container": "0.0.14", - "@react-email/font": "0.0.8", - "@react-email/head": "0.0.11", - "@react-email/heading": "0.0.14", - "@react-email/hr": "0.0.10", - "@react-email/html": "0.0.10", - "@react-email/img": "0.0.10", - "@react-email/link": "0.0.10", - "@react-email/markdown": "0.0.12", - "@react-email/preview": "0.0.11", - "@react-email/render": "1.0.1", - "@react-email/row": "0.0.10", - "@react-email/section": "0.0.14", - "@react-email/tailwind": "0.1.0", - "@react-email/text": "0.0.10" - } - }, - "@react-email/container": { - "version": "0.0.14", - "resolved": "https://registry.npmjs.org/@react-email/container/-/container-0.0.14.tgz", - "integrity": "sha512-NgoaJJd9tTtsrveL86Ocr/AYLkGyN3prdXKd/zm5fQpfDhy/NXezyT3iF6VlwAOEUIu64ErHpAJd+P6ygR+vjg==", - "requires": {} - }, - "@react-email/font": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/@react-email/font/-/font-0.0.8.tgz", - "integrity": "sha512-fSBEqYyVPAyyACBBHcs3wEYzNknpHMuwcSAAKE8fOoDfGqURr/vSxKPdh4tOa9z7G4hlcEfgGrCYEa2iPT22cw==", - "requires": {} - }, - "@react-email/head": { - "version": "0.0.11", - "resolved": "https://registry.npmjs.org/@react-email/head/-/head-0.0.11.tgz", - "integrity": "sha512-skw5FUgyamIMK+LN+fZQ5WIKQYf0dPiRAvsUAUR2eYoZp9oRsfkIpFHr0GWPkKAYjFEj+uJjaxQ/0VzQH7svVg==", - "requires": {} - }, - "@react-email/heading": { - "version": "0.0.14", - "resolved": "https://registry.npmjs.org/@react-email/heading/-/heading-0.0.14.tgz", - "integrity": "sha512-jZM7IVuZOXa0G110ES8OkxajPTypIKlzlO1K1RIe1auk76ukQRiCg1IRV4HZlWk1GGUbec5hNxsvZa2kU8cb9w==", - "requires": {} - }, - "@react-email/hr": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/@react-email/hr/-/hr-0.0.10.tgz", - "integrity": "sha512-3AA4Yjgl3zEid/KVx6uf6TuLJHVZvUc2cG9Wm9ZpWeAX4ODA+8g9HyuC0tfnjbRsVMhMcCGiECuWWXINi+60vA==", - "requires": {} - }, - "@react-email/html": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/@react-email/html/-/html-0.0.10.tgz", - "integrity": "sha512-06uiuSKJBWQJfhCKv4MPupELei4Lepyz9Sth7Yq7Fq29CAeB1ejLgKkGqn1I+FZ72hQxPLdYF4iq4yloKv3JCg==", - "requires": {} - }, - "@react-email/img": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/@react-email/img/-/img-0.0.10.tgz", - "integrity": "sha512-pJ8glJjDNaJ53qoM95pvX9SK05yh0bNQY/oyBKmxlBDdUII6ixuMc3SCwYXPMl+tgkQUyDgwEBpSTrLAnjL3hA==", - "requires": {} - }, - "@react-email/link": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/@react-email/link/-/link-0.0.10.tgz", - "integrity": "sha512-tva3wvAWSR10lMJa9fVA09yRn7pbEki0ZZpHE6GD1jKbFhmzt38VgLO9B797/prqoDZdAr4rVK7LJFcdPx3GwA==", - "requires": {} - }, - "@react-email/markdown": { - "version": "0.0.12", - "resolved": "https://registry.npmjs.org/@react-email/markdown/-/markdown-0.0.12.tgz", - "integrity": "sha512-wsuvj1XAb6O63aizCLNEeqVgKR3oFjAwt9vjfg2y2oh4G1dZeo8zonZM2x1fmkEkBZhzwSHraNi70jSXhA3A9w==", - "requires": { - "md-to-react-email": "5.0.2" - } - }, - "@react-email/preview": { - "version": "0.0.11", - "resolved": "https://registry.npmjs.org/@react-email/preview/-/preview-0.0.11.tgz", - "integrity": "sha512-7O/CT4b16YlSGrj18htTPx3Vbhu2suCGv/cSe5c+fuSrIM/nMiBSZ3Js16Vj0XJbAmmmlVmYFZw9L20wXJ+LjQ==", - "requires": {} - }, - "@react-email/render": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@react-email/render/-/render-1.0.1.tgz", - "integrity": "sha512-W3gTrcmLOVYnG80QuUp22ReIT/xfLsVJ+n7ghSlG2BITB8evNABn1AO2rGQoXuK84zKtDAlxCdm3hRyIpZdGSA==", - "requires": { - "html-to-text": "9.0.5", - "js-beautify": "^1.14.11", - "react-promise-suspense": "0.3.4" - } - }, - "@react-email/row": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/@react-email/row/-/row-0.0.10.tgz", - "integrity": "sha512-jPyEhG3gsLX+Eb9U+A30fh0gK6hXJwF4ghJ+ZtFQtlKAKqHX+eCpWlqB3Xschd/ARJLod8WAswg0FB+JD9d0/A==", - "requires": {} - }, - "@react-email/section": { - "version": "0.0.14", - "resolved": "https://registry.npmjs.org/@react-email/section/-/section-0.0.14.tgz", - "integrity": "sha512-+fYWLb4tPU1A/+GE5J1+SEMA7/wR3V30lQ+OR9t2kAJqNrARDbMx0bLnYnR1QL5TiFRz0pCF05SQUobk6gHEDQ==", - "requires": {} - }, - "@react-email/tailwind": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@react-email/tailwind/-/tailwind-0.1.0.tgz", - "integrity": "sha512-qysVUEY+M3SKUvu35XDpzn7yokhqFOT3tPU6Mj/pgc62TL5tQFj6msEbBtwoKs2qO3WZvai0DIHdLhaOxBQSow==", - "requires": {} - }, - "@react-email/text": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/@react-email/text/-/text-0.0.10.tgz", - "integrity": "sha512-wNAnxeEAiFs6N+SxS0y6wTJWfewEzUETuyS2aZmT00xk50VijwyFRuhm4sYSjusMyshevomFwz5jNISCxRsGWw==", - "requires": {} - }, - "@rollup/pluginutils": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.0.tgz", - "integrity": "sha512-XTIWOPPcpvyKI6L1NHo0lFlCyznUEyPmPY1mc3KpPVDYulHSTvyeLNVW00QTLIAFNhR3kYnJTQHeGqU4M3n09g==", - "dev": true, - "requires": { - "@types/estree": "^1.0.0", - "estree-walker": "^2.0.2", - "picomatch": "^2.3.1" - }, - "dependencies": { - "estree-walker": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", - "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", - "dev": true - }, - "picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true - } - } - }, - "@rollup/rollup-android-arm-eabi": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.22.4.tgz", - "integrity": "sha512-Fxamp4aEZnfPOcGA8KSNEohV8hX7zVHOemC8jVBoBUHu5zpJK/Eu3uJwt6BMgy9fkvzxDaurgj96F/NiLukF2w==", - "dev": true, - "optional": true - }, - "@rollup/rollup-android-arm64": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.22.4.tgz", - "integrity": "sha512-VXoK5UMrgECLYaMuGuVTOx5kcuap1Jm8g/M83RnCHBKOqvPPmROFJGQaZhGccnsFtfXQ3XYa4/jMCJvZnbJBdA==", - "dev": true, - "optional": true - }, - "@rollup/rollup-darwin-arm64": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.22.4.tgz", - "integrity": "sha512-xMM9ORBqu81jyMKCDP+SZDhnX2QEVQzTcC6G18KlTQEzWK8r/oNZtKuZaCcHhnsa6fEeOBionoyl5JsAbE/36Q==", - "dev": true, - "optional": true - }, - "@rollup/rollup-darwin-x64": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.22.4.tgz", - "integrity": "sha512-aJJyYKQwbHuhTUrjWjxEvGnNNBCnmpHDvrb8JFDbeSH3m2XdHcxDd3jthAzvmoI8w/kSjd2y0udT+4okADsZIw==", - "dev": true, - "optional": true - }, - "@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.22.4.tgz", - "integrity": "sha512-j63YtCIRAzbO+gC2L9dWXRh5BFetsv0j0va0Wi9epXDgU/XUi5dJKo4USTttVyK7fGw2nPWK0PbAvyliz50SCQ==", - "dev": true, - "optional": true - }, - "@rollup/rollup-linux-arm-musleabihf": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.22.4.tgz", - "integrity": "sha512-dJnWUgwWBX1YBRsuKKMOlXCzh2Wu1mlHzv20TpqEsfdZLb3WoJW2kIEsGwLkroYf24IrPAvOT/ZQ2OYMV6vlrg==", - "dev": true, - "optional": true - }, - "@rollup/rollup-linux-arm64-gnu": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.22.4.tgz", - "integrity": "sha512-AdPRoNi3NKVLolCN/Sp4F4N1d98c4SBnHMKoLuiG6RXgoZ4sllseuGioszumnPGmPM2O7qaAX/IJdeDU8f26Aw==", - "dev": true, - "optional": true - }, - "@rollup/rollup-linux-arm64-musl": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.22.4.tgz", - "integrity": "sha512-Gl0AxBtDg8uoAn5CCqQDMqAx22Wx22pjDOjBdmG0VIWX3qUBHzYmOKh8KXHL4UpogfJ14G4wk16EQogF+v8hmA==", - "dev": true, - "optional": true - }, - "@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.22.4.tgz", - "integrity": "sha512-3aVCK9xfWW1oGQpTsYJJPF6bfpWfhbRnhdlyhak2ZiyFLDaayz0EP5j9V1RVLAAxlmWKTDfS9wyRyY3hvhPoOg==", - "dev": true, - "optional": true - }, - "@rollup/rollup-linux-riscv64-gnu": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.22.4.tgz", - "integrity": "sha512-ePYIir6VYnhgv2C5Xe9u+ico4t8sZWXschR6fMgoPUK31yQu7hTEJb7bCqivHECwIClJfKgE7zYsh1qTP3WHUA==", - "dev": true, - "optional": true - }, - "@rollup/rollup-linux-s390x-gnu": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.22.4.tgz", - "integrity": "sha512-GqFJ9wLlbB9daxhVlrTe61vJtEY99/xB3C8e4ULVsVfflcpmR6c8UZXjtkMA6FhNONhj2eA5Tk9uAVw5orEs4Q==", - "dev": true, - "optional": true - }, - "@rollup/rollup-linux-x64-gnu": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.22.4.tgz", - "integrity": "sha512-87v0ol2sH9GE3cLQLNEy0K/R0pz1nvg76o8M5nhMR0+Q+BBGLnb35P0fVz4CQxHYXaAOhE8HhlkaZfsdUOlHwg==", - "dev": true, - "optional": true - }, - "@rollup/rollup-linux-x64-musl": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.22.4.tgz", - "integrity": "sha512-UV6FZMUgePDZrFjrNGIWzDo/vABebuXBhJEqrHxrGiU6HikPy0Z3LfdtciIttEUQfuDdCn8fqh7wiFJjCNwO+g==", - "dev": true, - "optional": true - }, - "@rollup/rollup-win32-arm64-msvc": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.22.4.tgz", - "integrity": "sha512-BjI+NVVEGAXjGWYHz/vv0pBqfGoUH0IGZ0cICTn7kB9PyjrATSkX+8WkguNjWoj2qSr1im/+tTGRaY+4/PdcQw==", - "dev": true, - "optional": true - }, - "@rollup/rollup-win32-ia32-msvc": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.22.4.tgz", - "integrity": "sha512-SiWG/1TuUdPvYmzmYnmd3IEifzR61Tragkbx9D3+R8mzQqDBz8v+BvZNDlkiTtI9T15KYZhP0ehn3Dld4n9J5g==", - "dev": true, - "optional": true - }, - "@rollup/rollup-win32-x64-msvc": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.22.4.tgz", - "integrity": "sha512-j8pPKp53/lq9lMXN57S8cFz0MynJk8OWNuUnXct/9KCpKU7DgU3bYMJhwWmcqC0UU29p8Lr0/7KEVcaM6bf47Q==", - "dev": true, - "optional": true - }, - "@selderee/plugin-htmlparser2": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@selderee/plugin-htmlparser2/-/plugin-htmlparser2-0.11.0.tgz", - "integrity": "sha512-P33hHGdldxGabLFjPPpaTxVolMrzrcegejx+0GxjrIb9Zv48D8yAIA/QTDR2dFl7Uz7urX8aX6+5bCZslr+gWQ==", - "requires": { - "domhandler": "^5.0.3", - "selderee": "^0.11.0" - } - }, - "@sideway/address": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.5.tgz", - "integrity": "sha512-IqO/DUQHUkPeixNQ8n0JA6102hT9CmaljNTPmQ1u8MEhBo/R4Q8eKLN/vGZxuebwOroDB4cbpjheD4+/sKFK4Q==", - "requires": { - "@hapi/hoek": "^9.0.0" - } - }, - "@sideway/formula": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.1.tgz", - "integrity": "sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==" - }, - "@sideway/pinpoint": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz", - "integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==" - }, - "@socket.io/component-emitter": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz", - "integrity": "sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg==" - }, - "@socket.io/redis-adapter": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/@socket.io/redis-adapter/-/redis-adapter-8.3.0.tgz", - "integrity": "sha512-ly0cra+48hDmChxmIpnESKrc94LjRL80TEmZVscuQ/WWkRP81nNj8W8cCGMqbI4L6NCuAaPRSzZF1a9GlAxxnA==", - "requires": { - "debug": "~4.3.1", - "notepack.io": "~3.0.1", - "uid2": "1.0.0" - } - }, - "@sqltools/formatter": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/@sqltools/formatter/-/formatter-1.2.5.tgz", - "integrity": "sha512-Uy0+khmZqUrUGm5dmMqVlnvufZRSK0FbYzVgp0UMstm+F5+W2/jnEEQyc9vo1ZR/E5ZI/B1WjjoTqBqwJL6Krw==" - }, - "@swc/core": { - "version": "1.7.39", - "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.7.39.tgz", - "integrity": "sha512-jns6VFeOT49uoTKLWIEfiQqJAlyqldNAt80kAr8f7a5YjX0zgnG3RBiLMpksx4Ka4SlK4O6TJ/lumIM3Trp82g==", - "devOptional": true, - "requires": { - "@swc/core-darwin-arm64": "1.7.39", - "@swc/core-darwin-x64": "1.7.39", - "@swc/core-linux-arm-gnueabihf": "1.7.39", - "@swc/core-linux-arm64-gnu": "1.7.39", - "@swc/core-linux-arm64-musl": "1.7.39", - "@swc/core-linux-x64-gnu": "1.7.39", - "@swc/core-linux-x64-musl": "1.7.39", - "@swc/core-win32-arm64-msvc": "1.7.39", - "@swc/core-win32-ia32-msvc": "1.7.39", - "@swc/core-win32-x64-msvc": "1.7.39", - "@swc/counter": "^0.1.3", - "@swc/types": "^0.1.13" - } - }, - "@swc/core-darwin-arm64": { - "version": "1.7.39", - "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.7.39.tgz", - "integrity": "sha512-o2nbEL6scMBMCTvY9OnbyVXtepLuNbdblV9oNJEFia5v5eGj9WMrnRQiylH3Wp/G2NYkW7V1/ZVW+kfvIeYe9A==", - "dev": true, - "optional": true - }, - "@swc/core-darwin-x64": { - "version": "1.7.39", - "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.7.39.tgz", - "integrity": "sha512-qMlv3XPgtPi/Fe11VhiPDHSLiYYk2dFYl747oGsHZPq+6tIdDQjIhijXPcsUHIXYDyG7lNpODPL8cP/X1sc9MA==", - "dev": true, - "optional": true - }, - "@swc/core-linux-arm-gnueabihf": { - "version": "1.7.39", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.7.39.tgz", - "integrity": "sha512-NP+JIkBs1ZKnpa3Lk2W1kBJMwHfNOxCUJXuTa2ckjFsuZ8OUu2gwdeLFkTHbR43dxGwH5UzSmuGocXeMowra/Q==", - "dev": true, - "optional": true - }, - "@swc/core-linux-arm64-gnu": { - "version": "1.7.39", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.7.39.tgz", - "integrity": "sha512-cPc+/HehyHyHcvAsk3ML/9wYcpWVIWax3YBaA+ScecJpSE04l/oBHPfdqKUPslqZ+Gcw0OWnIBGJT/fBZW2ayw==", - "dev": true, - "optional": true - }, - "@swc/core-linux-arm64-musl": { - "version": "1.7.39", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.7.39.tgz", - "integrity": "sha512-8RxgBC6ubFem66bk9XJ0vclu3exJ6eD7x7CwDhp5AD/tulZslTYXM7oNPjEtje3xxabXuj/bEUMNvHZhQRFdqA==", - "dev": true, - "optional": true - }, - "@swc/core-linux-x64-gnu": { - "version": "1.7.39", - "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.7.39.tgz", - "integrity": "sha512-3gtCPEJuXLQEolo9xsXtuPDocmXQx12vewEyFFSMSjOfakuPOBmOQMa0sVL8Wwius8C1eZVeD1fgk0omMqeC+Q==", - "dev": true, - "optional": true - }, - "@swc/core-linux-x64-musl": { - "version": "1.7.39", - "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.7.39.tgz", - "integrity": "sha512-mg39pW5x/eqqpZDdtjZJxrUvQNSvJF4O8wCl37fbuFUqOtXs4TxsjZ0aolt876HXxxhsQl7rS+N4KioEMSgTZw==", - "dev": true, - "optional": true - }, - "@swc/core-win32-arm64-msvc": { - "version": "1.7.39", - "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.7.39.tgz", - "integrity": "sha512-NZwuS0mNJowH3e9bMttr7B1fB8bW5svW/yyySigv9qmV5VcQRNz1kMlCvrCLYRsa93JnARuiaBI6FazSeG8mpA==", - "dev": true, - "optional": true - }, - "@swc/core-win32-ia32-msvc": { - "version": "1.7.39", - "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.7.39.tgz", - "integrity": "sha512-qFmvv5UExbJPXhhvCVDBnjK5Duqxr048dlVB6ZCgGzbRxuarOlawCzzLK4N172230pzlAWGLgn9CWl3+N6zfHA==", - "dev": true, - "optional": true - }, - "@swc/core-win32-x64-msvc": { - "version": "1.7.39", - "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.7.39.tgz", - "integrity": "sha512-o+5IMqgOtj9+BEOp16atTfBgCogVak9svhBpwsbcJQp67bQbxGYhAPPDW/hZ2rpSSF7UdzbY9wudoX9G4trcuQ==", - "dev": true, - "optional": true - }, - "@swc/counter": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz", - "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==" - }, - "@swc/helpers": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.5.tgz", - "integrity": "sha512-KGYxvIOXcceOAbEk4bi/dVLEK9z8sZ0uBB3Il5b1rhfClSpcX0yfRO0KmTkqR2cnQDymwLB+25ZyMzICg/cm/A==", - "requires": { - "@swc/counter": "^0.1.3", - "tslib": "^2.4.0" - } - }, - "@swc/types": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.13.tgz", - "integrity": "sha512-JL7eeCk6zWCbiYQg2xQSdLXQJl8Qoc9rXmG2cEKvHe3CKwMHwHGpfOb8frzNLmbycOo6I51qxnLnn9ESf4I20Q==", - "devOptional": true, - "requires": { - "@swc/counter": "^0.1.3" - } - }, - "@testcontainers/postgresql": { - "version": "10.13.2", - "resolved": "https://registry.npmjs.org/@testcontainers/postgresql/-/postgresql-10.13.2.tgz", - "integrity": "sha512-xd3u/rL8FrOBHFMu1aU+2d4sqPz9ffEb19ITtopT/tyBZWW9qCsgR6wSg0r2BJUd+2hT4UR5nR5cymi+ROkehw==", - "dev": true, - "requires": { - "testcontainers": "^10.13.2" - } - }, - "@tsconfig/node10": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", - "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==", - "optional": true, - "peer": true - }, - "@tsconfig/node12": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", - "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", - "optional": true, - "peer": true - }, - "@tsconfig/node14": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", - "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", - "optional": true, - "peer": true - }, - "@tsconfig/node16": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", - "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", - "optional": true, - "peer": true - }, - "@turf/boolean-point-in-polygon": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@turf/boolean-point-in-polygon/-/boolean-point-in-polygon-7.1.0.tgz", - "integrity": "sha512-mprVsyIQ+ijWTZwbnO4Jhxu94ZW2M2CheqLiRTsGJy0Ooay9v6Av5/Nl3/Gst7ZVXxPqMeMaFYkSzcTc87AKew==", - "requires": { - "@turf/helpers": "^7.1.0", - "@turf/invariant": "^7.1.0", - "@types/geojson": "^7946.0.10", - "point-in-polygon-hao": "^1.1.0", - "tslib": "^2.6.2" - } - }, - "@turf/helpers": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@turf/helpers/-/helpers-7.1.0.tgz", - "integrity": "sha512-dTeILEUVeNbaEeoZUOhxH5auv7WWlOShbx7QSd4s0T4Z0/iz90z9yaVCtZOLbU89umKotwKaJQltBNO9CzVgaQ==", - "requires": { - "@types/geojson": "^7946.0.10", - "tslib": "^2.6.2" - } - }, - "@turf/invariant": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@turf/invariant/-/invariant-7.1.0.tgz", - "integrity": "sha512-OCLNqkItBYIP1nE9lJGuIUatWGtQ4rhBKAyTfFu0z8npVzGEYzvguEeof8/6LkKmTTEHW53tCjoEhSSzdRh08Q==", - "requires": { - "@turf/helpers": "^7.1.0", - "@types/geojson": "^7946.0.10", - "tslib": "^2.6.2" - } - }, - "@types/archiver": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/@types/archiver/-/archiver-6.0.3.tgz", - "integrity": "sha512-a6wUll6k3zX6qs5KlxIggs1P1JcYJaTCx2gnlr+f0S1yd2DoaEwoIK10HmBaLnZwWneBz+JBm0dwcZu0zECBcQ==", - "dev": true, - "requires": { - "@types/readdir-glob": "*" - } - }, - "@types/async-lock": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/@types/async-lock/-/async-lock-1.4.2.tgz", - "integrity": "sha512-HlZ6Dcr205BmNhwkdXqrg2vkFMN2PluI7Lgr8In3B3wE5PiQHhjRqtW/lGdVU9gw+sM0JcIDx2AN+cW8oSWIcw==", - "dev": true - }, - "@types/aws-lambda": { - "version": "8.10.143", - "resolved": "https://registry.npmjs.org/@types/aws-lambda/-/aws-lambda-8.10.143.tgz", - "integrity": "sha512-u5vzlcR14ge/4pMTTMDQr3MF0wEe38B2F9o84uC4F43vN5DGTy63npRrB6jQhyt+C0lGv4ZfiRcRkqJoZuPnmg==" - }, - "@types/bcrypt": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/@types/bcrypt/-/bcrypt-5.0.2.tgz", - "integrity": "sha512-6atioO8Y75fNcbmj0G7UjI9lXN2pQ/IGJ2FWT4a/btd0Lk9lQalHLKhkgKVZ3r+spnmWUKfbMi1GEe9wyHQfNQ==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/body-parser": { - "version": "1.19.3", - "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.3.tgz", - "integrity": "sha512-oyl4jvAfTGX9Bt6Or4H9ni1Z447/tQuxnZsytsCaExKlmJiU8sFgnIBRzJUpKwB5eWn9HuBYlUlVA74q/yN0eQ==", - "dev": true, - "requires": { - "@types/connect": "*", - "@types/node": "*" - } - }, - "@types/bunyan": { - "version": "1.8.9", - "resolved": "https://registry.npmjs.org/@types/bunyan/-/bunyan-1.8.9.tgz", - "integrity": "sha512-ZqS9JGpBxVOvsawzmVt30sP++gSQMTejCkIAQ3VdadOcRE8izTyW66hufvwLeH+YEGP6Js2AW7Gz+RMyvrEbmw==", - "requires": { - "@types/node": "*" - } - }, - "@types/connect": { - "version": "3.4.36", - "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.36.tgz", - "integrity": "sha512-P63Zd/JUGq+PdrM1lv0Wv5SBYeA2+CORvbrXbngriYY0jzLUWfQMQQxOhjONEz/wlHOAxOdY7CY65rgQdTjq2w==", - "requires": { - "@types/node": "*" - } - }, - "@types/cookie": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.1.tgz", - "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==" - }, - "@types/cookie-parser": { - "version": "1.4.7", - "resolved": "https://registry.npmjs.org/@types/cookie-parser/-/cookie-parser-1.4.7.tgz", - "integrity": "sha512-Fvuyi354Z+uayxzIGCwYTayFKocfV7TuDYZClCdIP9ckhvAu/ixDtCB6qx2TT0FKjPLf1f3P/J1rgf6lPs64mw==", - "dev": true, - "requires": { - "@types/express": "*" - } - }, - "@types/cookiejar": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@types/cookiejar/-/cookiejar-2.1.5.tgz", - "integrity": "sha512-he+DHOWReW0nghN24E1WUqM0efK4kI9oTqDm6XmK8ZPe2djZ90BSNdGnIyCLzCPw7/pogPlGbzI2wHGGmi4O/Q==", - "dev": true - }, - "@types/cors": { - "version": "2.8.14", - "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.14.tgz", - "integrity": "sha512-RXHUvNWYICtbP6s18PnOCaqToK8y14DnLd75c6HfyKf228dxy7pHNOQkxPtvXKp/hINFMDjbYzsj63nnpPMSRQ==", - "requires": { - "@types/node": "*" - } - }, - "@types/docker-modem": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/@types/docker-modem/-/docker-modem-3.0.6.tgz", - "integrity": "sha512-yKpAGEuKRSS8wwx0joknWxsmLha78wNMe9R2S3UNsVOkZded8UqOrV8KoeDXoXsjndxwyF3eIhyClGbO1SEhEg==", - "dev": true, - "requires": { - "@types/node": "*", - "@types/ssh2": "*" - } - }, - "@types/dockerode": { - "version": "3.3.29", - "resolved": "https://registry.npmjs.org/@types/dockerode/-/dockerode-3.3.29.tgz", - "integrity": "sha512-5PRRq/yt5OT/Jf77ltIdz4EiR9+VLnPF+HpU4xGFwUqmV24Co2HKBNW3w+slqZ1CYchbcDeqJASHDYWzZCcMiQ==", - "dev": true, - "requires": { - "@types/docker-modem": "*", - "@types/node": "*", - "@types/ssh2": "*" - } - }, - "@types/eslint": { - "version": "8.44.3", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.44.3.tgz", - "integrity": "sha512-iM/WfkwAhwmPff3wZuPLYiHX18HI24jU8k1ZSH7P8FHwxTjZ2P6CoX2wnF43oprR+YXJM6UUxATkNvyv/JHd+g==", - "dev": true, - "optional": true, - "peer": true, - "requires": { - "@types/estree": "*", - "@types/json-schema": "*" - } - }, - "@types/estree": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", - "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", - "dev": true - }, - "@types/express": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz", - "integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==", - "dev": true, - "requires": { - "@types/body-parser": "*", - "@types/express-serve-static-core": "^4.17.33", - "@types/qs": "*", - "@types/serve-static": "*" - } - }, - "@types/express-serve-static-core": { - "version": "4.17.37", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.37.tgz", - "integrity": "sha512-ZohaCYTgGFcOP7u6aJOhY9uIZQgZ2vxC2yWoArY+FeDXlqeH66ZVBjgvg+RLVAS/DWNq4Ap9ZXu1+SUQiiWYMg==", - "dev": true, - "requires": { - "@types/node": "*", - "@types/qs": "*", - "@types/range-parser": "*", - "@types/send": "*" - } - }, - "@types/fluent-ffmpeg": { - "version": "2.1.26", - "resolved": "https://registry.npmjs.org/@types/fluent-ffmpeg/-/fluent-ffmpeg-2.1.26.tgz", - "integrity": "sha512-0JVF3wdQG+pN0ImwWD0bNgJiKF2OHg/7CDBHw5UIbRTvlnkgGHK6V5doE54ltvhud4o31/dEiHm23CAlxFiUQg==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/geojson": { - "version": "7946.0.14", - "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.14.tgz", - "integrity": "sha512-WCfD5Ht3ZesJUsONdhvm84dmzWOiOzOAqOncN0++w0lBw1o8OuDNJF2McvvCef/yBqb/HYRahp1BYtODFQ8bRg==" - }, - "@types/http-errors": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.2.tgz", - "integrity": "sha512-lPG6KlZs88gef6aD85z3HNkztpj7w2R7HmR3gygjfXCQmsLloWNARFkMuzKiiY8FGdh1XDpgBdrSf4aKDiA7Kg==", - "dev": true - }, - "@types/inquirer": { - "version": "8.2.6", - "resolved": "https://registry.npmjs.org/@types/inquirer/-/inquirer-8.2.6.tgz", - "integrity": "sha512-3uT88kxg8lNzY8ay2ZjP44DKcRaTGztqeIvN2zHvhzIBH/uAPaL75aBtdNRKbA7xXoMbBt5kX0M00VKAnfOYlA==", - "peer": true, - "requires": { - "@types/through": "*", - "rxjs": "^7.2.0" - } - }, - "@types/js-yaml": { - "version": "4.0.9", - "resolved": "https://registry.npmjs.org/@types/js-yaml/-/js-yaml-4.0.9.tgz", - "integrity": "sha512-k4MGaQl5TGo/iipqb2UDG2UwjXziSWkh0uysQelTlJpX1qGlpUZYm8PnO4DxG1qBomtJUdYJ6qR6xdIah10JLg==", - "dev": true - }, - "@types/json-schema": { - "version": "7.0.15", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", - "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", - "dev": true - }, - "@types/lodash": { - "version": "4.17.12", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.12.tgz", - "integrity": "sha512-sviUmCE8AYdaF/KIHLDJBQgeYzPBI0vf/17NaYehBJfYD1j6/L95Slh07NlyK2iNyBNaEkb3En2jRt+a8y3xZQ==", - "dev": true - }, - "@types/luxon": { - "version": "3.4.2", - "resolved": "https://registry.npmjs.org/@types/luxon/-/luxon-3.4.2.tgz", - "integrity": "sha512-TifLZlFudklWlMBfhubvgqTXRzLDI5pCbGa4P8a3wPyUQSW+1xQ5eDsreP9DWHX3tjq1ke96uYG/nwundroWcA==" - }, - "@types/memcached": { - "version": "2.2.10", - "resolved": "https://registry.npmjs.org/@types/memcached/-/memcached-2.2.10.tgz", - "integrity": "sha512-AM9smvZN55Gzs2wRrqeMHVP7KE8KWgCJO/XL5yCly2xF6EKa4YlbpK+cLSAH4NG/Ah64HrlegmGqW8kYws7Vxg==", - "requires": { - "@types/node": "*" - } - }, - "@types/methods": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/@types/methods/-/methods-1.1.4.tgz", - "integrity": "sha512-ymXWVrDiCxTBE3+RIrrP533E70eA+9qu7zdWoHuOmGujkYtzf4HQF96b8nwHLqhuf4ykX61IGRIB38CC6/sImQ==", - "dev": true - }, - "@types/mime": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.3.tgz", - "integrity": "sha512-Ys+/St+2VF4+xuY6+kDIXGxbNRO0mesVg0bbxEfB97Od1Vjpjx9KD1qxs64Gcb3CWPirk9Xe+PT4YiiHQ9T+eg==", - "dev": true - }, - "@types/mock-fs": { - "version": "4.13.4", - "resolved": "https://registry.npmjs.org/@types/mock-fs/-/mock-fs-4.13.4.tgz", - "integrity": "sha512-mXmM0o6lULPI8z3XNnQCpL0BGxPwx1Ul1wXYEPBGl4efShyxW2Rln0JOPEWGyZaYZMM6OVXM/15zUuFMY52ljg==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/multer": { - "version": "1.4.12", - "resolved": "https://registry.npmjs.org/@types/multer/-/multer-1.4.12.tgz", - "integrity": "sha512-pQ2hoqvXiJt2FP9WQVLPRO+AmiIm/ZYkavPlIQnx282u4ZrVdztx0pkh3jjpQt0Kz+YI0YhSG264y08UJKoUQg==", - "dev": true, - "requires": { - "@types/express": "*" - } - }, - "@types/mysql": { - "version": "2.15.26", - "resolved": "https://registry.npmjs.org/@types/mysql/-/mysql-2.15.26.tgz", - "integrity": "sha512-DSLCOXhkvfS5WNNPbfn2KdICAmk8lLc+/PNvnPnF7gOdMZCxopXduqv0OQ13y/yA/zXTSikZZqVgybUxOEg6YQ==", - "requires": { - "@types/node": "*" - } - }, - "@types/node": { - "version": "22.8.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.8.5.tgz", - "integrity": "sha512-5iYk6AMPtsMbkZqCO1UGF9W5L38twq11S2pYWkybGHH2ogPUvXWNlQqJBzuEZWKj/WRH+QTeiv6ySWqJtvIEgA==", - "requires": { - "undici-types": "~6.19.8" - } - }, - "@types/nodemailer": { - "version": "6.4.16", - "resolved": "https://registry.npmjs.org/@types/nodemailer/-/nodemailer-6.4.16.tgz", - "integrity": "sha512-uz6hN6Pp0upXMcilM61CoKyjT7sskBoOWpptkjjJp8jIMlTdc3xG01U7proKkXzruMS4hS0zqtHNkNPFB20rKQ==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/normalize-package-data": { - "version": "2.4.4", - "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz", - "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==", - "dev": true - }, - "@types/pg": { - "version": "8.11.10", - "resolved": "https://registry.npmjs.org/@types/pg/-/pg-8.11.10.tgz", - "integrity": "sha512-LczQUW4dbOQzsH2RQ5qoeJ6qJPdrcM/DcMLoqWQkMLMsq83J5lAX3LXjdkWdpscFy67JSOWDnh7Ny/sPFykmkg==", - "requires": { - "@types/node": "*", - "pg-protocol": "*", - "pg-types": "^4.0.1" - }, - "dependencies": { - "pg-types": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-4.0.2.tgz", - "integrity": "sha512-cRL3JpS3lKMGsKaWndugWQoLOCoP+Cic8oseVcbr0qhPzYD5DWXK+RZ9LY9wxRf7RQia4SCwQlXk0q6FCPrVng==", - "requires": { - "pg-int8": "1.0.1", - "pg-numeric": "1.0.2", - "postgres-array": "~3.0.1", - "postgres-bytea": "~3.0.0", - "postgres-date": "~2.1.0", - "postgres-interval": "^3.0.0", - "postgres-range": "^1.1.1" - } - }, - "postgres-array": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-3.0.2.tgz", - "integrity": "sha512-6faShkdFugNQCLwucjPcY5ARoW1SlbnrZjmGl0IrrqewpvxvhSLHimCVzqeuULCbG0fQv7Dtk1yDbG3xv7Veog==" - }, - "postgres-bytea": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-3.0.0.tgz", - "integrity": "sha512-CNd4jim9RFPkObHSjVHlVrxoVQXz7quwNFpz7RY1okNNme49+sVyiTvTRobiLV548Hx/hb1BG+iE7h9493WzFw==", - "requires": { - "obuf": "~1.1.2" - } - }, - "postgres-date": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-2.1.0.tgz", - "integrity": "sha512-K7Juri8gtgXVcDfZttFKVmhglp7epKb1K4pgrkLxehjqkrgPhfG6OO8LHLkfaqkbpjNRnra018XwAr1yQFWGcA==" - }, - "postgres-interval": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-3.0.0.tgz", - "integrity": "sha512-BSNDnbyZCXSxgA+1f5UU2GmwhoI0aU5yMxRGO8CdFEcY2BQF9xm/7MqKnYoM1nJDk8nONNWDk9WeSmePFhQdlw==" - } - } - }, - "@types/pg-pool": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/@types/pg-pool/-/pg-pool-2.0.6.tgz", - "integrity": "sha512-TaAUE5rq2VQYxab5Ts7WZhKNmuN78Q6PiFonTDdpbx8a1H0M1vhy3rhiMjl+e2iHmogyMw7jZF4FrE6eJUy5HQ==", - "requires": { - "@types/pg": "*" - } - }, - "@types/picomatch": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/picomatch/-/picomatch-3.0.1.tgz", - "integrity": "sha512-1MRgzpzY0hOp9pW/kLRxeQhUWwil6gnrUYd3oEpeYBqp/FexhaCPv3F8LsYr47gtUU45fO2cm1dbwkSrHEo8Uw==", - "dev": true - }, - "@types/pngjs": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/@types/pngjs/-/pngjs-6.0.5.tgz", - "integrity": "sha512-0k5eKfrA83JOZPppLtS2C7OUtyNAl2wKNxfyYl9Q5g9lPkgBl/9hNyAu6HuEH2J4XmIv2znEpkDd0SaZVxW6iQ==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/prop-types": { - "version": "15.7.12", - "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz", - "integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==", - "dev": true - }, - "@types/qs": { - "version": "6.9.8", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.8.tgz", - "integrity": "sha512-u95svzDlTysU5xecFNTgfFG5RUWu1A9P0VzgpcIiGZA9iraHOdSzcxMxQ55DyeRaGCSxQi7LxXDI4rzq/MYfdg==", - "dev": true - }, - "@types/range-parser": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.5.tgz", - "integrity": "sha512-xrO9OoVPqFuYyR/loIHjnbvvyRZREYKLjxV4+dY6v3FQR3stQ9ZxIGkaclF7YhI9hfjpuTbu14hZEy94qKLtOA==", - "dev": true - }, - "@types/react": { - "version": "18.3.12", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.12.tgz", - "integrity": "sha512-D2wOSq/d6Agt28q7rSI3jhU7G6aiuzljDGZ2hTZHIkrTLUI+AF3WMeKkEZ9nN2fkBAlcktT6vcZjDFiIhMYEQw==", - "dev": true, - "requires": { - "@types/prop-types": "*", - "csstype": "^3.0.2" - } - }, - "@types/readdir-glob": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@types/readdir-glob/-/readdir-glob-1.1.2.tgz", - "integrity": "sha512-vwAYrNN/8yhp/FJRU6HUSD0yk6xfoOS8HrZa8ZL7j+X8hJpaC1hTcAiXX2IxaAkkvrz9mLyoEhYZTE3cEYvA9Q==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/semver": { - "version": "7.5.8", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", - "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==", - "dev": true - }, - "@types/send": { - "version": "0.17.2", - "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.2.tgz", - "integrity": "sha512-aAG6yRf6r0wQ29bkS+x97BIs64ZLxeE/ARwyS6wrldMm3C1MdKwCcnnEwMC1slI8wuxJOpiUH9MioC0A0i+GJw==", - "dev": true, - "requires": { - "@types/mime": "^1", - "@types/node": "*" - } - }, - "@types/serve-static": { - "version": "1.15.3", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.3.tgz", - "integrity": "sha512-yVRvFsEMrv7s0lGhzrggJjNOSmZCdgCjw9xWrPr/kNNLp6FaDfMC1KaYl3TSJ0c58bECwNBMoQrZJ8hA8E1eFg==", - "dev": true, - "requires": { - "@types/http-errors": "*", - "@types/mime": "*", - "@types/node": "*" - } - }, - "@types/shimmer": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@types/shimmer/-/shimmer-1.2.0.tgz", - "integrity": "sha512-UE7oxhQLLd9gub6JKIAhDq06T0F6FnztwMNRvYgjeQSBeMc1ZG/tA47EwfduvkuQS8apbkM/lpLpWsaCeYsXVg==" - }, - "@types/ssh2": { - "version": "0.5.52", - "resolved": "https://registry.npmjs.org/@types/ssh2/-/ssh2-0.5.52.tgz", - "integrity": "sha512-lbLLlXxdCZOSJMCInKH2+9V/77ET2J6NPQHpFI0kda61Dd1KglJs+fPQBchizmzYSOJBgdTajhPqBO1xxLywvg==", - "dev": true, - "requires": { - "@types/node": "*", - "@types/ssh2-streams": "*" - } - }, - "@types/ssh2-streams": { - "version": "0.1.10", - "resolved": "https://registry.npmjs.org/@types/ssh2-streams/-/ssh2-streams-0.1.10.tgz", - "integrity": "sha512-r3HYPL0kPxRwk7Nk1P4JxaWPyJ2Mfnfm5efuK0vYgYZu16RerZUTyun6Yqu5KEfc3AR7BvTL1x+nzf7+kbKftQ==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/superagent": { - "version": "8.1.6", - "resolved": "https://registry.npmjs.org/@types/superagent/-/superagent-8.1.6.tgz", - "integrity": "sha512-yzBOv+6meEHSzV2NThYYOA6RtqvPr3Hbob9ZLp3i07SH27CrYVfm8CrF7ydTmidtelsFiKx2I4gZAiAOamGgvQ==", - "dev": true, - "requires": { - "@types/cookiejar": "^2.1.5", - "@types/methods": "^1.1.4", - "@types/node": "*" - } - }, - "@types/supertest": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/@types/supertest/-/supertest-6.0.2.tgz", - "integrity": "sha512-137ypx2lk/wTQbW6An6safu9hXmajAifU/s7szAHLN/FeIm5w7yR0Wkl9fdJMRSHwOn4HLAI0DaB2TOORuhPDg==", - "dev": true, - "requires": { - "@types/methods": "^1.1.4", - "@types/superagent": "^8.1.0" - } - }, - "@types/tedious": { - "version": "4.0.14", - "resolved": "https://registry.npmjs.org/@types/tedious/-/tedious-4.0.14.tgz", - "integrity": "sha512-KHPsfX/FoVbUGbyYvk1q9MMQHLPeRZhRJZdO45Q4YjvFkv4hMNghCWTvy7rdKessBsmtz4euWCWAB6/tVpI1Iw==", - "requires": { - "@types/node": "*" - } - }, - "@types/through": { - "version": "0.0.31", - "resolved": "https://registry.npmjs.org/@types/through/-/through-0.0.31.tgz", - "integrity": "sha512-LpKpmb7FGevYgXnBXYs6HWnmiFyVG07Pt1cnbgM1IhEacITTiUaBXXvOR3Y50ksaJWGSfhbEvQFivQEFGCC55w==", - "peer": true, - "requires": { - "@types/node": "*" - } - }, - "@types/ua-parser-js": { - "version": "0.7.39", - "resolved": "https://registry.npmjs.org/@types/ua-parser-js/-/ua-parser-js-0.7.39.tgz", - "integrity": "sha512-P/oDfpofrdtF5xw433SPALpdSchtJmY7nsJItf8h3KXqOslkbySh8zq4dSWXH2oTjRvJ5PczVEoCZPow6GicLg==", - "dev": true - }, - "@types/validator": { - "version": "13.11.8", - "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.11.8.tgz", - "integrity": "sha512-c/hzNDBh7eRF+KbCf+OoZxKbnkpaK/cKp9iLQWqB7muXtM+MtL9SUUH8vCFcLn6dH1Qm05jiexK0ofWY7TfOhQ==" - }, - "@typescript-eslint/eslint-plugin": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.11.0.tgz", - "integrity": "sha512-KhGn2LjW1PJT2A/GfDpiyOfS4a8xHQv2myUagTM5+zsormOmBlYsnQ6pobJ8XxJmh6hnHwa2Mbe3fPrDJoDhbA==", - "dev": true, - "requires": { - "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.11.0", - "@typescript-eslint/type-utils": "8.11.0", - "@typescript-eslint/utils": "8.11.0", - "@typescript-eslint/visitor-keys": "8.11.0", - "graphemer": "^1.4.0", - "ignore": "^5.3.1", - "natural-compare": "^1.4.0", - "ts-api-utils": "^1.3.0" - } - }, - "@typescript-eslint/parser": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.11.0.tgz", - "integrity": "sha512-lmt73NeHdy1Q/2ul295Qy3uninSqi6wQI18XwSpm8w0ZbQXUpjCAWP1Vlv/obudoBiIjJVjlztjQ+d/Md98Yxg==", - "dev": true, - "requires": { - "@typescript-eslint/scope-manager": "8.11.0", - "@typescript-eslint/types": "8.11.0", - "@typescript-eslint/typescript-estree": "8.11.0", - "@typescript-eslint/visitor-keys": "8.11.0", - "debug": "^4.3.4" - } - }, - "@typescript-eslint/scope-manager": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.11.0.tgz", - "integrity": "sha512-Uholz7tWhXmA4r6epo+vaeV7yjdKy5QFCERMjs1kMVsLRKIrSdM6o21W2He9ftp5PP6aWOVpD5zvrvuHZC0bMQ==", - "dev": true, - "requires": { - "@typescript-eslint/types": "8.11.0", - "@typescript-eslint/visitor-keys": "8.11.0" - } - }, - "@typescript-eslint/type-utils": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.11.0.tgz", - "integrity": "sha512-ItiMfJS6pQU0NIKAaybBKkuVzo6IdnAhPFZA/2Mba/uBjuPQPet/8+zh5GtLHwmuFRShZx+8lhIs7/QeDHflOg==", - "dev": true, - "requires": { - "@typescript-eslint/typescript-estree": "8.11.0", - "@typescript-eslint/utils": "8.11.0", - "debug": "^4.3.4", - "ts-api-utils": "^1.3.0" - } - }, - "@typescript-eslint/types": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.11.0.tgz", - "integrity": "sha512-tn6sNMHf6EBAYMvmPUaKaVeYvhUsrE6x+bXQTxjQRp360h1giATU0WvgeEys1spbvb5R+VpNOZ+XJmjD8wOUHw==", - "dev": true - }, - "@typescript-eslint/typescript-estree": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.11.0.tgz", - "integrity": "sha512-yHC3s1z1RCHoCz5t06gf7jH24rr3vns08XXhfEqzYpd6Hll3z/3g23JRi0jM8A47UFKNc3u/y5KIMx8Ynbjohg==", - "dev": true, - "requires": { - "@typescript-eslint/types": "8.11.0", - "@typescript-eslint/visitor-keys": "8.11.0", - "debug": "^4.3.4", - "fast-glob": "^3.3.2", - "is-glob": "^4.0.3", - "minimatch": "^9.0.4", - "semver": "^7.6.0", - "ts-api-utils": "^1.3.0" - }, - "dependencies": { - "brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0" - } - }, - "minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dev": true, - "requires": { - "brace-expansion": "^2.0.1" - } - } - } - }, - "@typescript-eslint/utils": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.11.0.tgz", - "integrity": "sha512-CYiX6WZcbXNJV7UNB4PLDIBtSdRmRI/nb0FMyqHPTQD1rMjA0foPLaPUV39C/MxkTd/QKSeX+Gb34PPsDVC35g==", - "dev": true, - "requires": { - "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.11.0", - "@typescript-eslint/types": "8.11.0", - "@typescript-eslint/typescript-estree": "8.11.0" - } - }, - "@typescript-eslint/visitor-keys": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.11.0.tgz", - "integrity": "sha512-EaewX6lxSjRJnc+99+dqzTeoDZUfyrA52d2/HRrkI830kgovWsmIiTfmr0NZorzqic7ga+1bS60lRBUgR3n/Bw==", - "dev": true, - "requires": { - "@typescript-eslint/types": "8.11.0", - "eslint-visitor-keys": "^3.4.3" - } - }, - "@vitest/coverage-v8": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-2.1.3.tgz", - "integrity": "sha512-2OJ3c7UPoFSmBZwqD2VEkUw6A/tzPF0LmW0ZZhhB8PFxuc+9IBG/FaSM+RLEenc7ljzFvGN+G0nGQoZnh7sy2A==", - "dev": true, - "requires": { - "@ampproject/remapping": "^2.3.0", - "@bcoe/v8-coverage": "^0.2.3", - "debug": "^4.3.6", - "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.11", - "magicast": "^0.3.4", - "std-env": "^3.7.0", - "test-exclude": "^7.0.1", - "tinyrainbow": "^1.2.0" - }, - "dependencies": { - "magic-string": { - "version": "0.30.12", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.12.tgz", - "integrity": "sha512-Ea8I3sQMVXr8JhN4z+H/d8zwo+tYDgHE9+5G4Wnrwhs0gaK9fXTKx0Tw5Xwsd/bCPTTZNRAdpyzvoeORe9LYpw==", - "dev": true, - "requires": { - "@jridgewell/sourcemap-codec": "^1.5.0" - } - } - } - }, - "@vitest/expect": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-2.1.3.tgz", - "integrity": "sha512-SNBoPubeCJhZ48agjXruCI57DvxcsivVDdWz+SSsmjTT4QN/DfHk3zB/xKsJqMs26bLZ/pNRLnCf0j679i0uWQ==", - "dev": true, - "requires": { - "@vitest/spy": "2.1.3", - "@vitest/utils": "2.1.3", - "chai": "^5.1.1", - "tinyrainbow": "^1.2.0" - } - }, - "@vitest/mocker": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-2.1.3.tgz", - "integrity": "sha512-eSpdY/eJDuOvuTA3ASzCjdithHa+GIF1L4PqtEELl6Qa3XafdMLBpBlZCIUCX2J+Q6sNmjmxtosAG62fK4BlqQ==", - "dev": true, - "requires": { - "@vitest/spy": "2.1.3", - "estree-walker": "^3.0.3", - "magic-string": "^0.30.11" - }, - "dependencies": { - "magic-string": { - "version": "0.30.11", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.11.tgz", - "integrity": "sha512-+Wri9p0QHMy+545hKww7YAu5NyzF8iomPL/RQazugQ9+Ez4Ic3mERMd8ZTX5rfK944j+560ZJi8iAwgak1Ac7A==", - "dev": true, - "requires": { - "@jridgewell/sourcemap-codec": "^1.5.0" - } - } - } - }, - "@vitest/pretty-format": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-2.1.3.tgz", - "integrity": "sha512-XH1XdtoLZCpqV59KRbPrIhFCOO0hErxrQCMcvnQete3Vibb9UeIOX02uFPfVn3Z9ZXsq78etlfyhnkmIZSzIwQ==", - "dev": true, - "requires": { - "tinyrainbow": "^1.2.0" - } - }, - "@vitest/runner": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-2.1.3.tgz", - "integrity": "sha512-JGzpWqmFJ4fq5ZKHtVO3Xuy1iF2rHGV4d/pdzgkYHm1+gOzNZtqjvyiaDGJytRyMU54qkxpNzCx+PErzJ1/JqQ==", - "dev": true, - "requires": { - "@vitest/utils": "2.1.3", - "pathe": "^1.1.2" - } - }, - "@vitest/snapshot": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-2.1.3.tgz", - "integrity": "sha512-qWC2mWc7VAXmjAkEKxrScWHWFyCQx/cmiZtuGqMi+WwqQJ2iURsVY4ZfAK6dVo6K2smKRU6l3BPwqEBvhnpQGg==", - "dev": true, - "requires": { - "@vitest/pretty-format": "2.1.3", - "magic-string": "^0.30.11", - "pathe": "^1.1.2" - }, - "dependencies": { - "magic-string": { - "version": "0.30.11", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.11.tgz", - "integrity": "sha512-+Wri9p0QHMy+545hKww7YAu5NyzF8iomPL/RQazugQ9+Ez4Ic3mERMd8ZTX5rfK944j+560ZJi8iAwgak1Ac7A==", - "dev": true, - "requires": { - "@jridgewell/sourcemap-codec": "^1.5.0" - } - } - } - }, - "@vitest/spy": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-2.1.3.tgz", - "integrity": "sha512-Nb2UzbcUswzeSP7JksMDaqsI43Sj5+Kry6ry6jQJT4b5gAK+NS9NED6mDb8FlMRCX8m5guaHCDZmqYMMWRy5nQ==", - "dev": true, - "requires": { - "tinyspy": "^3.0.0" - } - }, - "@vitest/utils": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-2.1.3.tgz", - "integrity": "sha512-xpiVfDSg1RrYT0tX6czgerkpcKFmFOF/gCr30+Mve5V2kewCy4Prn1/NDMSRwaSmT7PRaOF83wu+bEtsY1wrvA==", - "dev": true, - "requires": { - "@vitest/pretty-format": "2.1.3", - "loupe": "^3.1.1", - "tinyrainbow": "^1.2.0" - } - }, - "@webassemblyjs/ast": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.12.1.tgz", - "integrity": "sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg==", - "dev": true, - "requires": { - "@webassemblyjs/helper-numbers": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6" - } - }, - "@webassemblyjs/floating-point-hex-parser": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", - "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==", - "dev": true - }, - "@webassemblyjs/helper-api-error": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", - "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==", - "dev": true - }, - "@webassemblyjs/helper-buffer": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.12.1.tgz", - "integrity": "sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw==", - "dev": true - }, - "@webassemblyjs/helper-numbers": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", - "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", - "dev": true, - "requires": { - "@webassemblyjs/floating-point-hex-parser": "1.11.6", - "@webassemblyjs/helper-api-error": "1.11.6", - "@xtuc/long": "4.2.2" - } - }, - "@webassemblyjs/helper-wasm-bytecode": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", - "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==", - "dev": true - }, - "@webassemblyjs/helper-wasm-section": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.12.1.tgz", - "integrity": "sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.12.1", - "@webassemblyjs/helper-buffer": "1.12.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/wasm-gen": "1.12.1" - } - }, - "@webassemblyjs/ieee754": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", - "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", - "dev": true, - "requires": { - "@xtuc/ieee754": "^1.2.0" - } - }, - "@webassemblyjs/leb128": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", - "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", - "dev": true, - "requires": { - "@xtuc/long": "4.2.2" - } - }, - "@webassemblyjs/utf8": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", - "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==", - "dev": true - }, - "@webassemblyjs/wasm-edit": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.12.1.tgz", - "integrity": "sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.12.1", - "@webassemblyjs/helper-buffer": "1.12.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/helper-wasm-section": "1.12.1", - "@webassemblyjs/wasm-gen": "1.12.1", - "@webassemblyjs/wasm-opt": "1.12.1", - "@webassemblyjs/wasm-parser": "1.12.1", - "@webassemblyjs/wast-printer": "1.12.1" - } - }, - "@webassemblyjs/wasm-gen": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.12.1.tgz", - "integrity": "sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.12.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/ieee754": "1.11.6", - "@webassemblyjs/leb128": "1.11.6", - "@webassemblyjs/utf8": "1.11.6" - } - }, - "@webassemblyjs/wasm-opt": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.12.1.tgz", - "integrity": "sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.12.1", - "@webassemblyjs/helper-buffer": "1.12.1", - "@webassemblyjs/wasm-gen": "1.12.1", - "@webassemblyjs/wasm-parser": "1.12.1" - } - }, - "@webassemblyjs/wasm-parser": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.12.1.tgz", - "integrity": "sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.12.1", - "@webassemblyjs/helper-api-error": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/ieee754": "1.11.6", - "@webassemblyjs/leb128": "1.11.6", - "@webassemblyjs/utf8": "1.11.6" - } - }, - "@webassemblyjs/wast-printer": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.12.1.tgz", - "integrity": "sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.12.1", - "@xtuc/long": "4.2.2" - } - }, - "@xtuc/ieee754": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", - "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", - "dev": true - }, - "@xtuc/long": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", - "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", - "dev": true - }, - "abbrev": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" - }, - "abort-controller": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", - "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", - "requires": { - "event-target-shim": "^5.0.0" - } - }, - "accepts": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", - "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", - "requires": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" - } - }, - "acorn": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.0.tgz", - "integrity": "sha512-RTvkC4w+KNXrM39/lWCUaG0IbRkWdCv7W/IOW9oU6SawyxulvkQy5HQPVTKxEjczcUvapcrw3cFx/60VN/NRNw==" - }, - "acorn-import-attributes": { - "version": "1.9.5", - "resolved": "https://registry.npmjs.org/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz", - "integrity": "sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==", - "requires": {} - }, - "acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, - "requires": {} - }, - "acorn-walk": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.2.tgz", - "integrity": "sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==", - "optional": true, - "peer": true - }, - "agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "requires": { - "debug": "4" - } - }, - "ajv": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", - "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - } - }, - "ajv-formats": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", - "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", - "dev": true, - "requires": { - "ajv": "^8.0.0" - } - }, - "ansi-colors": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", - "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", - "dev": true - }, - "ansi-escapes": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", - "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", - "requires": { - "type-fest": "^0.21.3" - }, - "dependencies": { - "type-fest": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==" - } - } - }, - "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" - }, - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "requires": { - "color-convert": "^2.0.1" - } - }, - "any-promise": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", - "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==" - }, - "anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "requires": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "dependencies": { - "picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==" - } - } - }, - "app-root-path": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/app-root-path/-/app-root-path-3.1.0.tgz", - "integrity": "sha512-biN3PwB2gUtjaYy/isrU3aNWI5w+fAfvHkSvCKeQGxhmYpwKFUxudR3Yya+KqVRHBmEDYh+/lTozYCFbmzX4nA==" - }, - "append-field": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", - "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==" - }, - "aproba": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", - "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==" - }, - "archiver": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/archiver/-/archiver-7.0.1.tgz", - "integrity": "sha512-ZcbTaIqJOfCc03QwD468Unz/5Ir8ATtvAHsK+FdXbDIbGfihqh9mrvdcYunQzqn4HrvWWaFyaxJhGZagaJJpPQ==", - "requires": { - "archiver-utils": "^5.0.2", - "async": "^3.2.4", - "buffer-crc32": "^1.0.0", - "readable-stream": "^4.0.0", - "readdir-glob": "^1.1.2", - "tar-stream": "^3.0.0", - "zip-stream": "^6.0.1" - }, - "dependencies": { - "buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "requires": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" - } - }, - "buffer-crc32": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-1.0.0.tgz", - "integrity": "sha512-Db1SbgBS/fg/392AblrMJk97KggmvYhr4pB5ZIMTWtaivCPMWLkmb7m21cJvpvgK+J3nsU2CmmixNBZx4vFj/w==" - }, - "readable-stream": { - "version": "4.5.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz", - "integrity": "sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==", - "requires": { - "abort-controller": "^3.0.0", - "buffer": "^6.0.3", - "events": "^3.3.0", - "process": "^0.11.10", - "string_decoder": "^1.3.0" - } - } - } - }, - "archiver-utils": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-5.0.2.tgz", - "integrity": "sha512-wuLJMmIBQYCsGZgYLTy5FIB2pF6Lfb6cXMSF8Qywwk3t20zWnAi7zLcQFdKQmIB8wyZpY5ER38x08GbwtR2cLA==", - "requires": { - "glob": "^10.0.0", - "graceful-fs": "^4.2.0", - "is-stream": "^2.0.1", - "lazystream": "^1.0.0", - "lodash": "^4.17.15", - "normalize-path": "^3.0.0", - "readable-stream": "^4.0.0" - }, - "dependencies": { - "buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "requires": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" - } - }, - "readable-stream": { - "version": "4.5.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz", - "integrity": "sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==", - "requires": { - "abort-controller": "^3.0.0", - "buffer": "^6.0.3", - "events": "^3.3.0", - "process": "^0.11.10", - "string_decoder": "^1.3.0" - } - } - } - }, - "are-we-there-yet": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", - "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", - "requires": { - "delegates": "^1.0.0", - "readable-stream": "^3.6.0" - } - }, - "arg": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", - "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "optional": true, - "peer": true - }, - "argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" - }, - "array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" - }, - "array-source": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/array-source/-/array-source-0.0.4.tgz", - "integrity": "sha512-frNdc+zBn80vipY+GdcJkLEbMWj3xmzArYApmUGxoiV8uAu/ygcs9icPdsGdA26h0MkHUMW6EN2piIvVx+M5Mw==" - }, - "array-timsort": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/array-timsort/-/array-timsort-1.0.3.tgz", - "integrity": "sha512-/+3GRL7dDAGEfM6TseQk/U+mi18TU2Ms9I3UlLdUMhz2hbvGNTKdj9xniwXfUqgYhHxRx0+8UnKkvlNwVU+cWQ==", - "dev": true - }, - "asn1": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", - "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", - "dev": true, - "requires": { - "safer-buffer": "~2.1.0" - } - }, - "assertion-error": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", - "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", - "dev": true - }, - "async": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", - "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==" - }, - "async-lock": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/async-lock/-/async-lock-1.4.1.tgz", - "integrity": "sha512-Az2ZTpuytrtqENulXwO3GGv1Bztugx6TT37NIo7imr/Qo0gsYiGtSdBa2B6fsXhTpVZDNfu1Qn3pk531e3q+nQ==" - }, - "b4a": { - "version": "1.6.4", - "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.6.4.tgz", - "integrity": "sha512-fpWrvyVHEKyeEvbKZTVOeZF3VSKKWtJxFIxX/jaVPf+cLbGUSitjb49pHLqPV2BUNNZ0LcoeEGfE/YCpyDYHIw==" - }, - "balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" - }, - "bare-events": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.4.2.tgz", - "integrity": "sha512-qMKFd2qG/36aA4GwvKq8MxnPgCQAmBWmSyLWsJcbn8v03wvIPQ/hG1Ms8bPzndZxMDoHpxez5VOS+gC9Yi24/Q==", - "optional": true - }, - "bare-fs": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/bare-fs/-/bare-fs-2.3.1.tgz", - "integrity": "sha512-W/Hfxc/6VehXlsgFtbB5B4xFcsCl+pAh30cYhoFyXErf6oGrwjh8SwiPAdHgpmWonKuYpZgGywN0SXt7dgsADA==", - "dev": true, - "optional": true, - "requires": { - "bare-events": "^2.0.0", - "bare-path": "^2.0.0", - "bare-stream": "^2.0.0" - } - }, - "bare-os": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/bare-os/-/bare-os-2.4.0.tgz", - "integrity": "sha512-v8DTT08AS/G0F9xrhyLtepoo9EJBJ85FRSMbu1pQUlAf6A8T0tEEQGMVObWeqpjhSPXsE0VGlluFBJu2fdoTNg==", - "dev": true, - "optional": true - }, - "bare-path": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/bare-path/-/bare-path-2.1.3.tgz", - "integrity": "sha512-lh/eITfU8hrj9Ru5quUp0Io1kJWIk1bTjzo7JH1P5dWmQ2EL4hFUlfI8FonAhSlgIfhn63p84CDY/x+PisgcXA==", - "dev": true, - "optional": true, - "requires": { - "bare-os": "^2.1.0" - } - }, - "bare-stream": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/bare-stream/-/bare-stream-2.1.3.tgz", - "integrity": "sha512-tiDAH9H/kP+tvNO5sczyn9ZAA7utrSMobyDchsnyyXBuUe2FSQWbxhtuHB8jwpHYYevVo2UJpcmvvjrbHboUUQ==", - "dev": true, - "optional": true, - "requires": { - "streamx": "^2.18.0" - } - }, - "base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" - }, - "base64id": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", - "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==" - }, - "batch-cluster": { - "version": "13.0.0", - "resolved": "https://registry.npmjs.org/batch-cluster/-/batch-cluster-13.0.0.tgz", - "integrity": "sha512-EreW0Vi8TwovhYUHBXXRA5tthuU2ynGsZFlboyMJHCCUXYa2AjgwnE3ubBOJs2xJLcuXFJbi6c/8pH5+FVj8Og==" - }, - "bcrypt": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-5.1.1.tgz", - "integrity": "sha512-AGBHOG5hPYZ5Xl9KXzU5iKq9516yEmvCKDg3ecP5kX2aB6UqTeXZxk2ELnDgDm6BQSMlLt9rDB4LoSMx0rYwww==", - "requires": { - "@mapbox/node-pre-gyp": "^1.0.11", - "node-addon-api": "^5.0.0" - }, - "dependencies": { - "node-addon-api": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz", - "integrity": "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==" - } - } - }, - "bcrypt-pbkdf": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", - "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", - "dev": true, - "requires": { - "tweetnacl": "^0.14.3" - } - }, - "bignumber.js": { - "version": "9.1.2", - "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.1.2.tgz", - "integrity": "sha512-2/mKyZH9K85bzOEfhXDBFZTGd1CTs+5IHpeFQo9luiBG7hghdC851Pj2WAhb6E3R6b9tZj/XKhbg4fum+Kepug==" - }, - "binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==" - }, - "bl": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", - "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", - "requires": { - "buffer": "^5.5.0", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" - } - }, - "body-parser": { - "version": "1.20.3", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", - "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", - "requires": { - "bytes": "3.1.2", - "content-type": "~1.0.5", - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "on-finished": "2.4.1", - "qs": "6.13.0", - "raw-body": "2.5.2", - "type-is": "~1.6.18", - "unpipe": "1.0.0" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - } - } - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "braces": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "requires": { - "fill-range": "^7.1.1" - } - }, - "browserslist": { - "version": "4.23.0", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz", - "integrity": "sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==", - "requires": { - "caniuse-lite": "^1.0.30001587", - "electron-to-chromium": "^1.4.668", - "node-releases": "^2.0.14", - "update-browserslist-db": "^1.0.13" - } - }, - "buffer": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "requires": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" - } - }, - "buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" - }, - "buildcheck": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/buildcheck/-/buildcheck-0.0.6.tgz", - "integrity": "sha512-8f9ZJCUXyT1M35Jx7MkBgmBMo3oHTTBIPLiY9xyL0pl3T5RwcPEY8cUHr5LBNfu/fk6c2T4DJZuVM/8ZZT2D2A==", - "dev": true, - "optional": true - }, - "builtin-modules": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz", - "integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==", - "dev": true - }, - "bullmq": { - "version": "4.18.2", - "resolved": "https://registry.npmjs.org/bullmq/-/bullmq-4.18.2.tgz", - "integrity": "sha512-Cx0O98IlGiFw7UBa+zwGz+nH0Pcl1wfTvMVBlsMna3s0219hXroVovh1xPRgomyUcbyciHiugGCkW0RRNZDHYQ==", - "requires": { - "cron-parser": "^4.6.0", - "glob": "^8.0.3", - "ioredis": "^5.3.2", - "lodash": "^4.17.21", - "msgpackr": "^1.6.2", - "node-abort-controller": "^3.1.1", - "semver": "^7.5.4", - "tslib": "^2.0.0", - "uuid": "^9.0.0" - }, - "dependencies": { - "brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "requires": { - "balanced-match": "^1.0.0" - } - }, - "glob": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", - "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" - } - }, - "minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", - "requires": { - "brace-expansion": "^2.0.1" - } - } - } - }, - "busboy": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", - "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", - "requires": { - "streamsearch": "^1.1.0" - } - }, - "byline": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/byline/-/byline-5.0.0.tgz", - "integrity": "sha512-s6webAy+R4SR8XVuJWt2V2rGvhnrhxN+9S15GNuTK3wKPOXFF6RNc+8ug2XhH+2s4f+uudG4kUVYmYOQWL2g0Q==", - "dev": true - }, - "bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==" - }, - "cac": { - "version": "6.7.14", - "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", - "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", - "dev": true - }, - "call-bind": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", - "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", - "requires": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "set-function-length": "^1.2.1" - } - }, - "callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==" - }, - "camelcase-css": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", - "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", - "peer": true - }, - "caniuse-lite": { - "version": "1.0.30001618", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001618.tgz", - "integrity": "sha512-p407+D1tIkDvsEAPS22lJxLQQaG8OTBEqo0KhzfABGk0TU4juBNDSfH0hyAp/HRyx+M8L17z/ltyhxh27FTfQg==" - }, - "chai": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/chai/-/chai-5.1.1.tgz", - "integrity": "sha512-pT1ZgP8rPNqUgieVaEY+ryQr6Q4HXNg8Ei9UnLUrjN4IA7dvQC5JB+/kxVcPNDHyBcc/26CXPkbNzq3qwrOEKA==", - "dev": true, - "requires": { - "assertion-error": "^2.0.1", - "check-error": "^2.1.1", - "deep-eql": "^5.0.1", - "loupe": "^3.1.0", - "pathval": "^2.0.0" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "chardet": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", - "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==" - }, - "check-error": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.1.tgz", - "integrity": "sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==", - "dev": true - }, - "chokidar": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", - "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", - "requires": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "fsevents": "~2.3.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - } - }, - "chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==" - }, - "chrome-trace-event": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", - "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", - "dev": true - }, - "ci-info": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.0.0.tgz", - "integrity": "sha512-TdHqgGf9odd8SXNuxtUBVx8Nv+qZOejE6qyqiy5NtbYYQOeFa6zmHkxlPzmaLxWWHsU6nJmB7AETdVPi+2NBUg==", - "dev": true - }, - "cjs-module-lexer": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.1.tgz", - "integrity": "sha512-cuSVIHi9/9E/+821Qjdvngor+xpnlwnuwIyZOaLmHBVdXL+gP+I6QQB9VkO7RI77YIcTV+S1W9AreJ5eN63JBA==" - }, - "class-transformer": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/class-transformer/-/class-transformer-0.5.1.tgz", - "integrity": "sha512-SQa1Ws6hUbfC98vKGxZH3KFY0Y1lm5Zm0SY8XX9zbK7FJCyVEac3ATW0RIpwzW+oOfmHE5PMPufDG9hCfoEOMw==" - }, - "class-validator": { - "version": "0.14.1", - "resolved": "https://registry.npmjs.org/class-validator/-/class-validator-0.14.1.tgz", - "integrity": "sha512-2VEG9JICxIqTpoK1eMzZqaV+u/EiwEJkMGzTrZf6sU/fwsnOITVgYJ8yojSy6CaXtO9V0Cc6ZQZ8h8m4UBuLwQ==", - "requires": { - "@types/validator": "^13.11.8", - "libphonenumber-js": "^1.10.53", - "validator": "^13.9.0" - } - }, - "clean-regexp": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/clean-regexp/-/clean-regexp-1.0.0.tgz", - "integrity": "sha512-GfisEZEJvzKrmGWkvfhgzcz/BllN1USeqD2V6tg14OAOgaCD2Z/PUEuxnAZ/nPvmaHRG7a8y77p1T/IRQ4D1Hw==", - "dev": true, - "requires": { - "escape-string-regexp": "^1.0.5" - }, - "dependencies": { - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true - } - } - }, - "cli-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", - "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", - "requires": { - "restore-cursor": "^3.1.0" - } - }, - "cli-highlight": { - "version": "2.1.11", - "resolved": "https://registry.npmjs.org/cli-highlight/-/cli-highlight-2.1.11.tgz", - "integrity": "sha512-9KDcoEVwyUXrjcJNvHD0NFc/hiwe/WPVYIleQh2O1N2Zro5gWJZ/K+3DGn8w8P/F6FxOgzyC5bxDyHIgCSPhGg==", - "requires": { - "chalk": "^4.0.0", - "highlight.js": "^10.7.1", - "mz": "^2.4.0", - "parse5": "^5.1.1", - "parse5-htmlparser2-tree-adapter": "^6.0.0", - "yargs": "^16.0.0" - } - }, - "cli-spinners": { - "version": "2.9.1", - "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.1.tgz", - "integrity": "sha512-jHgecW0pxkonBJdrKsqxgRX9AcG+u/5k0Q7WPDfi8AogLAdwxEkyYYNWwZ5GvVFoFx2uiY1eNcSK00fh+1+FyQ==" - }, - "cli-table3": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.5.tgz", - "integrity": "sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ==", - "dev": true, - "requires": { - "@colors/colors": "1.5.0", - "string-width": "^4.2.0" - } - }, - "cli-width": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", - "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==" - }, - "client-only": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", - "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==" - }, - "cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - }, - "dependencies": { - "wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - } - } - } - }, - "clone": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==" - }, - "cluster-key-slot": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz", - "integrity": "sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==" - }, - "color": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz", - "integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==", - "requires": { - "color-convert": "^2.0.1", - "color-string": "^1.9.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - }, - "color-string": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", - "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", - "requires": { - "color-name": "^1.0.0", - "simple-swizzle": "^0.2.2" - } - }, - "color-support": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", - "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==" - }, - "commander": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", - "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==" - }, - "comment-json": { - "version": "4.2.5", - "resolved": "https://registry.npmjs.org/comment-json/-/comment-json-4.2.5.tgz", - "integrity": "sha512-bKw/r35jR3HGt5PEPm1ljsQQGyCrR8sFGNiN5L+ykDHdpO8Smxkrkla9Yi6NkQyUrb8V54PGhfMs6NrIwtxtdw==", - "dev": true, - "requires": { - "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" - } - }, - "compress-commons": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-6.0.2.tgz", - "integrity": "sha512-6FqVXeETqWPoGcfzrXb37E50NP0LXT8kAMu5ooZayhWWdgEY4lBEEcbQNXtkuKQsGduxiIcI4gOTsxTmuq/bSg==", - "requires": { - "crc-32": "^1.2.0", - "crc32-stream": "^6.0.0", - "is-stream": "^2.0.1", - "normalize-path": "^3.0.0", - "readable-stream": "^4.0.0" - }, - "dependencies": { - "buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "requires": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" - } - }, - "readable-stream": { - "version": "4.5.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz", - "integrity": "sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==", - "requires": { - "abort-controller": "^3.0.0", - "buffer": "^6.0.3", - "events": "^3.3.0", - "process": "^0.11.10", - "string_decoder": "^1.3.0" - } - } - } - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" - }, - "concat-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", - "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", - "requires": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^3.0.2", - "typedarray": "^0.0.6" - } - }, - "config-chain": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz", - "integrity": "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==", - "requires": { - "ini": "^1.3.4", - "proto-list": "~1.2.1" - } - }, - "consola": { - "version": "2.15.3", - "resolved": "https://registry.npmjs.org/consola/-/consola-2.15.3.tgz", - "integrity": "sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw==" - }, - "console-control-strings": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" - }, - "content-disposition": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", - "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", - "requires": { - "safe-buffer": "5.2.1" - } - }, - "content-type": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", - "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==" - }, - "convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==" - }, - "cookie": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz", - "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==" - }, - "cookie-parser": { - "version": "1.4.7", - "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.7.tgz", - "integrity": "sha512-nGUvgXnotP3BsjiLX2ypbQnWoGUPIIfHQNZkkC668ntrzGWEZVW70HDEB1qnNGMicPje6EttlIgzo51YSwNQGw==", - "requires": { - "cookie": "0.7.2", - "cookie-signature": "1.0.6" - }, - "dependencies": { - "cookie": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", - "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==" - } - } - }, - "cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" - }, - "core-js-compat": { - "version": "3.37.1", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.37.1.tgz", - "integrity": "sha512-9TNiImhKvQqSUkOvk/mMRZzOANTiEVC7WaBNhHcKM7x+/5E1l5NvsysR19zuDQScE8k+kfQXWRN3AtS/eOSHpg==", - "dev": true, - "requires": { - "browserslist": "^4.23.0" - } - }, - "core-util-is": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" - }, - "cors": { - "version": "2.8.5", - "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", - "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", - "requires": { - "object-assign": "^4", - "vary": "^1" - } - }, - "cosmiconfig": { - "version": "8.3.6", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", - "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", - "requires": { - "import-fresh": "^3.3.0", - "js-yaml": "^4.1.0", - "parse-json": "^5.2.0", - "path-type": "^4.0.0" - } - }, - "cpu-features": { - "version": "0.0.9", - "resolved": "https://registry.npmjs.org/cpu-features/-/cpu-features-0.0.9.tgz", - "integrity": "sha512-AKjgn2rP2yJyfbepsmLfiYcmtNn/2eUvocUyM/09yB0YDiz39HteK/5/T4Onf0pmdYDMgkBoGvRLvEguzyL7wQ==", - "dev": true, - "optional": true, - "requires": { - "buildcheck": "~0.0.6", - "nan": "^2.17.0" - } - }, - "crc-32": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz", - "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==" - }, - "crc32-stream": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-6.0.0.tgz", - "integrity": "sha512-piICUB6ei4IlTv1+653yq5+KoqfBYmj9bw6LqXoOneTMDXk5nM1qt12mFW1caG3LlJXEKW1Bp0WggEmIfQB34g==", - "requires": { - "crc-32": "^1.2.0", - "readable-stream": "^4.0.0" - }, - "dependencies": { - "buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "requires": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" - } - }, - "readable-stream": { - "version": "4.5.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz", - "integrity": "sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==", - "requires": { - "abort-controller": "^3.0.0", - "buffer": "^6.0.3", - "events": "^3.3.0", - "process": "^0.11.10", - "string_decoder": "^1.3.0" - } - } - } - }, - "create-require": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", - "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", - "optional": true, - "peer": true - }, - "cron": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/cron/-/cron-3.1.7.tgz", - "integrity": "sha512-tlBg7ARsAMQLzgwqVxy8AZl/qlTc5nibqYwtNGoCrd+cV+ugI+tvZC1oT/8dFH8W455YrywGykx/KMmAqOr7Jw==", - "requires": { - "@types/luxon": "~3.4.0", - "luxon": "~3.4.0" - }, - "dependencies": { - "luxon": { - "version": "3.4.4", - "resolved": "https://registry.npmjs.org/luxon/-/luxon-3.4.4.tgz", - "integrity": "sha512-zobTr7akeGHnv7eBOXcRgMeCP6+uyYsczwmeRCauvpvaAltgNyTbLH/+VaEAPUeWBT+1GuNmz4wC/6jtQzbbVA==" - } - } - }, - "cron-parser": { - "version": "4.9.0", - "resolved": "https://registry.npmjs.org/cron-parser/-/cron-parser-4.9.0.tgz", - "integrity": "sha512-p0SaNjrHOnQeR8/VnfGbmg9te2kfyYSQ7Sc/j/6DtPL3JQvKxmjO9TSjNFpujqV3vEYYBvNNvXSxzyksBWAx1Q==", - "requires": { - "luxon": "^3.2.1" - } - }, - "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - } - }, - "cssesc": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", - "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", - "peer": true - }, - "csstype": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", - "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", - "dev": true - }, - "dayjs": { - "version": "1.11.10", - "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.10.tgz", - "integrity": "sha512-vjAczensTgRcqDERK0SR2XMwsF/tSvnvlv6VcF2GIhg6Sx4yOIt/irsr1RDJsKiIyBzJDpCoXiWWq28MqH2cnQ==" - }, - "debounce": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/debounce/-/debounce-2.0.0.tgz", - "integrity": "sha512-xRetU6gL1VJbs85Mc4FoEGSjQxzpdxRyFhe3lmWFyy2EzydIcD4xzUvRJMD+NPDfMwKNhxa3PvsIOU32luIWeA==" - }, - "debug": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", - "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", - "requires": { - "ms": "^2.1.3" - } - }, - "deep-eql": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz", - "integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==", - "dev": true - }, - "deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true - }, - "deepmerge": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", - "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==" - }, - "defaults": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", - "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", - "requires": { - "clone": "^1.0.2" - } - }, - "define-data-property": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.3.tgz", - "integrity": "sha512-h3GBouC+RPtNX2N0hHVLo2ZwPYurq8mLmXpOLTsw71gr7lHt5VaI4vVkDUNOfiWmm48JEXe3VM7PmLX45AMmmg==", - "requires": { - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.1" - } - }, - "delegates": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" - }, - "denque": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", - "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==" - }, - "depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" - }, - "destroy": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", - "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==" - }, - "detect-libc": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz", - "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==" - }, - "diacritics": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/diacritics/-/diacritics-1.3.0.tgz", - "integrity": "sha512-wlwEkqcsaxvPJML+rDh/2iS824jbREk6DUMUKkEaSlxdYHeS43cClJtsWglvw2RfeXGm6ohKDqsXteJ5sP5enA==" - }, - "didyoumean": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", - "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", - "peer": true - }, - "diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "optional": true, - "peer": true - }, - "discontinuous-range": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/discontinuous-range/-/discontinuous-range-1.0.0.tgz", - "integrity": "sha512-c68LpLbO+7kP/b1Hr1qs8/BJ09F5khZGTxqxZuhzxpmwJKOgRFHJWIb9/KmqnqHhLdO55aOxFH/EGBvUQbL/RQ==", - "dev": true - }, - "dlv": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", - "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", - "peer": true - }, - "docker-compose": { - "version": "0.24.8", - "resolved": "https://registry.npmjs.org/docker-compose/-/docker-compose-0.24.8.tgz", - "integrity": "sha512-plizRs/Vf15H+GCVxq2EUvyPK7ei9b/cVesHvjnX4xaXjM9spHe2Ytq0BitndFgvTJ3E3NljPNUEl7BAN43iZw==", - "dev": true, - "requires": { - "yaml": "^2.2.2" - } - }, - "docker-modem": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/docker-modem/-/docker-modem-3.0.8.tgz", - "integrity": "sha512-f0ReSURdM3pcKPNS30mxOHSbaFLcknGmQjwSfmbcdOw1XWKXVhukM3NJHhr7NpY9BIyyWQb0EBo3KQvvuU5egQ==", - "dev": true, - "requires": { - "debug": "^4.1.1", - "readable-stream": "^3.5.0", - "split-ca": "^1.0.1", - "ssh2": "^1.11.0" - } - }, - "dockerode": { - "version": "3.3.5", - "resolved": "https://registry.npmjs.org/dockerode/-/dockerode-3.3.5.tgz", - "integrity": "sha512-/0YNa3ZDNeLr/tSckmD69+Gq+qVNhvKfAHNeZJBnp7EOP6RGKV8ORrJHkUn20So5wU+xxT7+1n5u8PjHbfjbSA==", - "dev": true, - "requires": { - "@balena/dockerignore": "^1.0.2", - "docker-modem": "^3.0.0", - "tar-fs": "~2.0.1" - }, - "dependencies": { - "chownr": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", - "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", - "dev": true - }, - "tar-fs": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.0.1.tgz", - "integrity": "sha512-6tzWDMeroL87uF/+lin46k+Q+46rAJ0SyPGz7OW7wTgblI273hsBqk2C1j0/xNadNLKDTUL9BukSjB7cwgmlPA==", - "dev": true, - "requires": { - "chownr": "^1.1.1", - "mkdirp-classic": "^0.5.2", - "pump": "^3.0.0", - "tar-stream": "^2.0.0" - } - }, - "tar-stream": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", - "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", - "dev": true, - "requires": { - "bl": "^4.0.3", - "end-of-stream": "^1.4.1", - "fs-constants": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^3.1.1" - } - } - } - }, - "dom-serializer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", - "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", - "requires": { - "domelementtype": "^2.3.0", - "domhandler": "^5.0.2", - "entities": "^4.2.0" - } - }, - "domelementtype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", - "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==" - }, - "domhandler": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", - "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", - "requires": { - "domelementtype": "^2.3.0" - } - }, - "domutils": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz", - "integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==", - "requires": { - "dom-serializer": "^2.0.0", - "domelementtype": "^2.3.0", - "domhandler": "^5.0.3" - } - }, - "dotenv": { - "version": "16.4.5", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", - "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==" - }, - "eastasianwidth": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" - }, - "editorconfig": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-1.0.4.tgz", - "integrity": "sha512-L9Qe08KWTlqYMVvMcTIvMAdl1cDUubzRNYL+WfA4bLDMHe4nemKkpmYzkznE1FwLKu0EEmy6obgQKzMJrg4x9Q==", - "requires": { - "@one-ini/wasm": "0.1.1", - "commander": "^10.0.0", - "minimatch": "9.0.1", - "semver": "^7.5.3" - }, - "dependencies": { - "brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "requires": { - "balanced-match": "^1.0.0" - } - }, - "commander": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", - "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==" - }, - "minimatch": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.1.tgz", - "integrity": "sha512-0jWhJpD/MdhPXwPuiRkCbfYfSKp2qnn2eOc279qI7f+osl/l+prKSrvhg157zSYvx/1nmgn2NqdT6k2Z7zSH9w==", - "requires": { - "brace-expansion": "^2.0.1" - } - } - } - }, - "ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" - }, - "electron-to-chromium": { - "version": "1.4.769", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.769.tgz", - "integrity": "sha512-bZu7p623NEA2rHTc9K1vykl57ektSPQYFFqQir8BOYf6EKOB+yIsbFB9Kpm7Cgt6tsLr9sRkqfqSZUw7LP1XxQ==" - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" - }, - "encodeurl": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", - "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==" - }, - "end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dev": true, - "requires": { - "once": "^1.4.0" - } - }, - "engine.io": { - "version": "6.5.5", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.5.5.tgz", - "integrity": "sha512-C5Pn8Wk+1vKBoHghJODM63yk8MvrO9EWZUfkAt5HAqIgPE4/8FF0PEGHXtEd40l223+cE5ABWuPzm38PHFXfMA==", - "requires": { - "@types/cookie": "^0.4.1", - "@types/cors": "^2.8.12", - "@types/node": ">=10.0.0", - "accepts": "~1.3.4", - "base64id": "2.0.0", - "cookie": "~0.4.1", - "cors": "~2.8.5", - "debug": "~4.3.1", - "engine.io-parser": "~5.2.1", - "ws": "~8.17.1" - } - }, - "engine.io-parser": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.1.tgz", - "integrity": "sha512-9JktcM3u18nU9N2Lz3bWeBgxVgOKpw7yhRaoxQA3FUDZzzw+9WlA6p4G4u0RixNkg14fH7EfEc/RhpurtiROTQ==" - }, - "enhanced-resolve": { - "version": "5.17.1", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz", - "integrity": "sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==", - "dev": true, - "requires": { - "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" - } - }, - "entities": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==" - }, - "error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "requires": { - "is-arrayish": "^0.2.1" - } - }, - "es-define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", - "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", - "requires": { - "get-intrinsic": "^1.2.4" - } - }, - "es-errors": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", - "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==" - }, - "es-module-lexer": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.3.1.tgz", - "integrity": "sha512-JUFAyicQV9mXc3YRxPnDlrfBKpqt6hUYzz9/boprUJHs4e4KVr3XwOF70doO6gwXUor6EWZJAyWAfKki84t20Q==", - "dev": true - }, - "esbuild": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", - "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", - "dev": true, - "requires": { - "@esbuild/aix-ppc64": "0.21.5", - "@esbuild/android-arm": "0.21.5", - "@esbuild/android-arm64": "0.21.5", - "@esbuild/android-x64": "0.21.5", - "@esbuild/darwin-arm64": "0.21.5", - "@esbuild/darwin-x64": "0.21.5", - "@esbuild/freebsd-arm64": "0.21.5", - "@esbuild/freebsd-x64": "0.21.5", - "@esbuild/linux-arm": "0.21.5", - "@esbuild/linux-arm64": "0.21.5", - "@esbuild/linux-ia32": "0.21.5", - "@esbuild/linux-loong64": "0.21.5", - "@esbuild/linux-mips64el": "0.21.5", - "@esbuild/linux-ppc64": "0.21.5", - "@esbuild/linux-riscv64": "0.21.5", - "@esbuild/linux-s390x": "0.21.5", - "@esbuild/linux-x64": "0.21.5", - "@esbuild/netbsd-x64": "0.21.5", - "@esbuild/openbsd-x64": "0.21.5", - "@esbuild/sunos-x64": "0.21.5", - "@esbuild/win32-arm64": "0.21.5", - "@esbuild/win32-ia32": "0.21.5", - "@esbuild/win32-x64": "0.21.5" - } - }, - "escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==" - }, - "escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" - }, - "escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true - }, - "eslint": { - "version": "9.13.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.13.0.tgz", - "integrity": "sha512-EYZK6SX6zjFHST/HRytOdA/zE72Cq/bfw45LSyuwrdvcclb/gqV8RRQxywOBEWO2+WDpva6UZa4CcDeJKzUCFA==", - "dev": true, - "requires": { - "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.11.0", - "@eslint/config-array": "^0.18.0", - "@eslint/core": "^0.7.0", - "@eslint/eslintrc": "^3.1.0", - "@eslint/js": "9.13.0", - "@eslint/plugin-kit": "^0.2.0", - "@humanfs/node": "^0.16.5", - "@humanwhocodes/module-importer": "^1.0.1", - "@humanwhocodes/retry": "^0.3.1", - "@types/estree": "^1.0.6", - "@types/json-schema": "^7.0.15", - "ajv": "^6.12.4", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^8.1.0", - "eslint-visitor-keys": "^4.1.0", - "espree": "^10.2.0", - "esquery": "^1.5.0", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^8.0.0", - "find-up": "^5.0.0", - "glob-parent": "^6.0.2", - "ignore": "^5.2.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "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.3", - "text-table": "^0.2.0" - }, - "dependencies": { - "@types/estree": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", - "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", - "dev": true - }, - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "eslint-visitor-keys": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", - "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", - "dev": true - }, - "glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "requires": { - "is-glob": "^4.0.3" - } - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - } - } - }, - "eslint-config-prettier": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz", - "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==", - "dev": true, - "requires": {} - }, - "eslint-plugin-prettier": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.2.1.tgz", - "integrity": "sha512-gH3iR3g4JfF+yYPaJYkN7jEl9QbweL/YfkoRlNnuIEHEz1vHVlCmWOS+eGGiRuzHQXdJFCOTxRgvju9b8VUmrw==", - "dev": true, - "requires": { - "prettier-linter-helpers": "^1.0.0", - "synckit": "^0.9.1" - } - }, - "eslint-plugin-unicorn": { - "version": "55.0.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-unicorn/-/eslint-plugin-unicorn-55.0.0.tgz", - "integrity": "sha512-n3AKiVpY2/uDcGrS3+QsYDkjPfaOrNrsfQxU9nt5nitd9KuvVXrfAvgCO9DYPSfap+Gqjw9EOrXIsBp5tlHZjA==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.24.5", - "@eslint-community/eslint-utils": "^4.4.0", - "ci-info": "^4.0.0", - "clean-regexp": "^1.0.0", - "core-js-compat": "^3.37.0", - "esquery": "^1.5.0", - "globals": "^15.7.0", - "indent-string": "^4.0.0", - "is-builtin-module": "^3.2.1", - "jsesc": "^3.0.2", - "pluralize": "^8.0.0", - "read-pkg-up": "^7.0.1", - "regexp-tree": "^0.1.27", - "regjsparser": "^0.10.0", - "semver": "^7.6.1", - "strip-indent": "^3.0.0" - } - }, - "eslint-scope": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.1.0.tgz", - "integrity": "sha512-14dSvlhaVhKKsa9Fx1l8A17s7ah7Ef7wCakJ10LYk6+GYmP9yDti2oq2SEwcyndt6knfcZyhyxwY3i9yL78EQw==", - "dev": true, - "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - } - }, - "eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true - }, - "espree": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-10.2.0.tgz", - "integrity": "sha512-upbkBJbckcCNBDBDXEbuhjbP68n+scUd3k/U2EkyM9nw+I/jPiL4cLF/Al06CF96wRltFda16sxDFrxsI1v0/g==", - "dev": true, - "requires": { - "acorn": "^8.12.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^4.1.0" - }, - "dependencies": { - "eslint-visitor-keys": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.1.0.tgz", - "integrity": "sha512-Q7lok0mqMUSf5a/AdAZkA5a/gHcO6snwQClVNNvFKCAVlxXucdU8pKydU5ZVZjBx5xr37vGbFFWtLQYreLzrZg==", - "dev": true - } - } - }, - "esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true - }, - "esquery": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", - "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", - "dev": true, - "requires": { - "estraverse": "^5.1.0" - } - }, - "esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "requires": { - "estraverse": "^5.2.0" - } - }, - "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true - }, - "estree-walker": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", - "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", - "dev": true, - "requires": { - "@types/estree": "^1.0.0" - } - }, - "esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true - }, - "etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==" - }, - "event-target-shim": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", - "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==" - }, - "eventemitter2": { - "version": "6.4.9", - "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-6.4.9.tgz", - "integrity": "sha512-JEPTiaOt9f04oa6NOkc4aH+nVp5I3wEjpHbIPqfgCdD5v5bUzy7xQqwcVO2aDQgOWhI28da57HksMrzK9HlRxg==" - }, - "events": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==" - }, - "exiftool-vendored": { - "version": "28.6.0", - "resolved": "https://registry.npmjs.org/exiftool-vendored/-/exiftool-vendored-28.6.0.tgz", - "integrity": "sha512-Cx8/8ov1tKEacHhsi7FNYdisIhKq/SeQfprYSpYzwBuJwkPmCV8w7tTIvUJRQX9rvopXhBA4eBf1FPXqTZW5vA==", - "requires": { - "@photostructure/tz-lookup": "^11.0.0", - "@types/luxon": "^3.4.2", - "batch-cluster": "^13.0.0", - "exiftool-vendored.exe": "12.97.0", - "exiftool-vendored.pl": "12.97.0", - "he": "^1.2.0", - "luxon": "^3.5.0" - } - }, - "exiftool-vendored.exe": { - "version": "12.97.0", - "resolved": "https://registry.npmjs.org/exiftool-vendored.exe/-/exiftool-vendored.exe-12.97.0.tgz", - "integrity": "sha512-+HxyFigEJOtwRjP7PhEslhZKuVW2V0hvmHPHtbVtNKGfAUGcfc95xNTjASQfKJvc+9ZuvzdEBPkEQmyA/ZYdIw==", - "optional": true - }, - "exiftool-vendored.pl": { - "version": "12.97.0", - "resolved": "https://registry.npmjs.org/exiftool-vendored.pl/-/exiftool-vendored.pl-12.97.0.tgz", - "integrity": "sha512-mXe9JEH3csfyPWcC7+H6IpfaokDMMr4S45n7MtiobGPdeeh+kFnf1SQ9cxg4sF403P6IKVeYYPbzgKMlpro9eQ==", - "optional": true - }, - "express": { - "version": "4.21.1", - "resolved": "https://registry.npmjs.org/express/-/express-4.21.1.tgz", - "integrity": "sha512-YSFlK1Ee0/GC8QaO91tHcDxJiE/X4FbpAyQWkxAvG6AXCuR65YzK8ua6D9hvi/TzUfZMpc+BwuM1IPw8fmQBiQ==", - "requires": { - "accepts": "~1.3.8", - "array-flatten": "1.1.1", - "body-parser": "1.20.3", - "content-disposition": "0.5.4", - "content-type": "~1.0.4", - "cookie": "0.7.1", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "2.0.0", - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "1.3.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "merge-descriptors": "1.0.3", - "methods": "~1.1.2", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "path-to-regexp": "0.1.10", - "proxy-addr": "~2.0.7", - "qs": "6.13.0", - "range-parser": "~1.2.1", - "safe-buffer": "5.2.1", - "send": "0.19.0", - "serve-static": "1.16.2", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - }, - "dependencies": { - "cookie": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", - "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==" - }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - }, - "path-to-regexp": { - "version": "0.1.10", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.10.tgz", - "integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==" - } - } - }, - "extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" - }, - "external-editor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", - "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", - "requires": { - "chardet": "^0.7.0", - "iconv-lite": "^0.4.24", - "tmp": "^0.0.33" - } - }, - "fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true - }, - "fast-diff": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", - "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", - "dev": true - }, - "fast-fifo": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz", - "integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==" - }, - "fast-glob": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", - "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", - "requires": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - } - }, - "fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true - }, - "fast-safe-stringify": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", - "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==" - }, - "fastq": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", - "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", - "requires": { - "reusify": "^1.0.4" - } - }, - "figures": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", - "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", - "requires": { - "escape-string-regexp": "^1.0.5" - }, - "dependencies": { - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==" - } - } - }, - "file-entry-cache": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", - "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", - "dev": true, - "requires": { - "flat-cache": "^4.0.0" - } - }, - "file-source": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/file-source/-/file-source-0.6.1.tgz", - "integrity": "sha512-1R1KneL7eTXmXfKxC10V/9NeGOdbsAXJ+lQ//fvvcHUgtaZcZDWNJNblxAoVOyV1cj45pOtUrR3vZTBwqcW8XA==", - "requires": { - "stream-source": "0.3" - } - }, - "fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "requires": { - "to-regex-range": "^5.0.1" - } - }, - "finalhandler": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", - "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", - "requires": { - "debug": "2.6.9", - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "statuses": "2.0.1", - "unpipe": "~1.0.0" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - } - } - }, - "find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "requires": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - } - }, - "flat-cache": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", - "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", - "dev": true, - "requires": { - "flatted": "^3.2.9", - "keyv": "^4.5.4" - } - }, - "flatted": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", - "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", - "dev": true - }, - "fluent-ffmpeg": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/fluent-ffmpeg/-/fluent-ffmpeg-2.1.3.tgz", - "integrity": "sha512-Be3narBNt2s6bsaqP6Jzq91heDgOEaDCJAXcE3qcma/EJBSy5FB4cvO31XBInuAuKBx8Kptf8dkhjK0IOru39Q==", - "requires": { - "async": "^0.2.9", - "which": "^1.1.1" - }, - "dependencies": { - "async": { - "version": "0.2.10", - "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", - "integrity": "sha512-eAkdoKxU6/LkKDBzLpT+t6Ff5EtfSF4wx1WfJiPEEV7WNLnDaRXk0oVysiEPm262roaachGexwUv94WhSgN5TQ==" - }, - "which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "requires": { - "isexe": "^2.0.0" - } - } - } - }, - "foreground-child": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", - "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", - "requires": { - "cross-spawn": "^7.0.0", - "signal-exit": "^4.0.1" - } - }, - "fork-ts-checker-webpack-plugin": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-9.0.2.tgz", - "integrity": "sha512-Uochze2R8peoN1XqlSi/rGUkDQpRogtLFocP9+PGu68zk1BDAKXfdeCdyVZpgTk8V8WFVQXdEz426VKjXLO1Gg==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.16.7", - "chalk": "^4.1.2", - "chokidar": "^3.5.3", - "cosmiconfig": "^8.2.0", - "deepmerge": "^4.2.2", - "fs-extra": "^10.0.0", - "memfs": "^3.4.1", - "minimatch": "^3.0.4", - "node-abort-controller": "^3.0.1", - "schema-utils": "^3.1.1", - "semver": "^7.3.5", - "tapable": "^2.2.1" - } - }, - "forwarded": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==" - }, - "forwarded-parse": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/forwarded-parse/-/forwarded-parse-2.1.2.tgz", - "integrity": "sha512-alTFZZQDKMporBH77856pXgzhEzaUVmLCDk+egLgIgHst3Tpndzz8MnKe+GzRJRfvVdn69HhpW7cmXzvtLvJAw==" - }, - "fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==" - }, - "fs-constants": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", - "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", - "dev": true - }, - "fs-extra": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", - "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - } - }, - "fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", - "requires": { - "minipass": "^3.0.0" - }, - "dependencies": { - "minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "requires": { - "yallist": "^4.0.0" - } - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - } - } - }, - "fs-monkey": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.5.tgz", - "integrity": "sha512-8uMbBjrhzW76TYgEV27Y5E//W2f/lTFmx78P2w19FZSxarhI/798APGQyuGCwmkNxgwGRhrLfvWyLBvNtuOmew==", - "dev": true - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" - }, - "fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "optional": true - }, - "function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==" - }, - "gauge": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", - "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", - "requires": { - "aproba": "^1.0.3 || ^2.0.0", - "color-support": "^1.1.2", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.1", - "object-assign": "^4.1.1", - "signal-exit": "^3.0.0", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1", - "wide-align": "^1.1.2" - }, - "dependencies": { - "signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" - } - } - }, - "gaxios": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-6.2.0.tgz", - "integrity": "sha512-H6+bHeoEAU5D6XNc6mPKeN5dLZqEDs9Gpk6I+SZBEzK5So58JVrHPmevNi35fRl1J9Y5TaeLW0kYx3pCJ1U2mQ==", - "requires": { - "extend": "^3.0.2", - "https-proxy-agent": "^7.0.1", - "is-stream": "^2.0.0", - "node-fetch": "^2.6.9" - }, - "dependencies": { - "agent-base": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.0.tgz", - "integrity": "sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg==", - "requires": { - "debug": "^4.3.4" - } - }, - "https-proxy-agent": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.4.tgz", - "integrity": "sha512-wlwpilI7YdjSkWaQ/7omYBMTliDcmCN8OLihO6I9B86g06lMyAoqgoDpV0XqoaPOKj+0DIdAvnsWfyAAhmimcg==", - "requires": { - "agent-base": "^7.0.2", - "debug": "4" - } - } - } - }, - "gcp-metadata": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-6.1.0.tgz", - "integrity": "sha512-Jh/AIwwgaxan+7ZUUmRLCjtchyDiqh4KjBJ5tW3plBZb5iL/BPcso8A5DlzeD9qlw0duCamnNdpFjxwaT0KyKg==", - "requires": { - "gaxios": "^6.0.0", - "json-bigint": "^1.0.0" - } - }, - "gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==" - }, - "geo-tz": { - "version": "8.1.2", - "resolved": "https://registry.npmjs.org/geo-tz/-/geo-tz-8.1.2.tgz", - "integrity": "sha512-S1udoP7MZ+CVu+7Iy/VayVNmEHTWgfJ52TjpfC2/4f+j0SB/ZXMjGrwZTqPMo6/O2m5lrGLCFCY0bkxUqiLN+g==", - "requires": { - "@turf/boolean-point-in-polygon": "^7.1.0", - "@turf/helpers": "^7.1.0", - "geobuf": "^3.0.2", - "pbf": "^3.2.1" - } - }, - "geobuf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/geobuf/-/geobuf-3.0.2.tgz", - "integrity": "sha512-ASgKwEAQQRnyNFHNvpd5uAwstbVYmiTW0Caw3fBb509tNTqXyAAPMyFs5NNihsLZhLxU1j/kjFhkhLWA9djuVg==", - "requires": { - "concat-stream": "^2.0.0", - "pbf": "^3.2.1", - "shapefile": "~0.6.6" - } - }, - "get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" - }, - "get-intrinsic": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", - "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", - "requires": { - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "hasown": "^2.0.0" - } - }, - "get-port": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/get-port/-/get-port-5.1.1.tgz", - "integrity": "sha512-g/Q1aTSDOxFpchXC4i8ZWvxA1lnPqx/JHqcpIw0/LX9T8x/GBbi6YnlN5nhaKIFkT8oFsscUKgDJYxfwfS6QsQ==", - "dev": true - }, - "get-stdin": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-8.0.0.tgz", - "integrity": "sha512-sY22aA6xchAzprjyqmSEQv4UbAAzRN0L2dQB0NlN5acTTK9Don6nhoc3eAbUnpZiCANAMfd/+40kVdKfFygohg==", - "dev": true - }, - "glob": { - "version": "10.4.2", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.2.tgz", - "integrity": "sha512-GwMlUF6PkPo3Gk21UxkCohOv0PLcIXVtKyLlpEI28R/cO/4eNOdmLk3CMW1wROV/WR/EsZOWAfBbBOqYvs88/w==", - "requires": { - "foreground-child": "^3.1.0", - "jackspeak": "^3.1.2", - "minimatch": "^9.0.4", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^1.11.1" - }, - "dependencies": { - "brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "requires": { - "balanced-match": "^1.0.0" - } - }, - "jackspeak": { - "version": "3.4.2", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.2.tgz", - "integrity": "sha512-qH3nOSj8q/8+Eg8LUPOq3C+6HWkpUioIjDsq1+D4zY91oZvpPttw8GwtF1nReRYKXl+1AORyFqtm2f5Q1SB6/Q==", - "requires": { - "@isaacs/cliui": "^8.0.2", - "@pkgjs/parseargs": "^0.11.0" - } - }, - "minimatch": { - "version": "9.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", - "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", - "requires": { - "brace-expansion": "^2.0.1" - } - } - } - }, - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "requires": { - "is-glob": "^4.0.1" - } - }, - "glob-to-regexp": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", - "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", - "dev": true - }, - "globals": { - "version": "15.11.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-15.11.0.tgz", - "integrity": "sha512-yeyNSjdbyVaWurlwCpcA6XNBrHTMIeDdj0/hnvX/OLJ9ekOXYbLsLinH/MucQyGvNnXhidTdNhTtJaffL2sMfw==", - "dev": true - }, - "globrex": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/globrex/-/globrex-0.1.2.tgz", - "integrity": "sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==", - "dev": true - }, - "gopd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", - "requires": { - "get-intrinsic": "^1.1.3" - } - }, - "graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" - }, - "graphemer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true - }, - "handlebars": { - "version": "4.7.8", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", - "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==", - "requires": { - "minimist": "^1.2.5", - "neo-async": "^2.6.2", - "source-map": "^0.6.1", - "uglify-js": "^3.1.4", - "wordwrap": "^1.0.0" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" - } - } - }, - "has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "requires": { - "function-bind": "^1.1.1" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" - }, - "has-own-prop": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-own-prop/-/has-own-prop-2.0.0.tgz", - "integrity": "sha512-Pq0h+hvsVm6dDEa8x82GnLSYHOzNDt7f0ddFa3FqcQlgzEiptPqL+XrOJNavjOzSYiYWIrgeVYYgGlLmnxwilQ==", - "dev": true - }, - "has-property-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz", - "integrity": "sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==", - "requires": { - "get-intrinsic": "^1.2.2" - } - }, - "has-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", - "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==" - }, - "has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==" - }, - "has-unicode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" - }, - "hasown": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.1.tgz", - "integrity": "sha512-1/th4MHjnwncwXsIW6QMzlvYL9kG5e/CpVvLRZe4XPa8TOUNbCELqmvhDmnkNsAjwaG4+I8gJJL0JBvTTLO9qA==", - "requires": { - "function-bind": "^1.1.2" - } - }, - "he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==" - }, - "highlight.js": { - "version": "10.7.3", - "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.3.tgz", - "integrity": "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==" - }, - "hosted-git-info": { - "version": "2.8.9", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", - "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", - "dev": true - }, - "html-escaper": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", - "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", - "dev": true - }, - "html-to-text": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/html-to-text/-/html-to-text-9.0.5.tgz", - "integrity": "sha512-qY60FjREgVZL03vJU6IfMV4GDjGBIoOyvuFdpBDIX9yTlDw0TjxVBQp+P8NvpdIXNJvfWBTNul7fsAQJq2FNpg==", - "requires": { - "@selderee/plugin-htmlparser2": "^0.11.0", - "deepmerge": "^4.3.1", - "dom-serializer": "^2.0.0", - "htmlparser2": "^8.0.2", - "selderee": "^0.11.0" - } - }, - "htmlparser2": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.2.tgz", - "integrity": "sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==", - "requires": { - "domelementtype": "^2.3.0", - "domhandler": "^5.0.3", - "domutils": "^3.0.1", - "entities": "^4.4.0" - } - }, - "http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", - "requires": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" - } - }, - "https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", - "requires": { - "agent-base": "6", - "debug": "4" - } - }, - "i18n-iso-countries": { - "version": "7.12.0", - "resolved": "https://registry.npmjs.org/i18n-iso-countries/-/i18n-iso-countries-7.12.0.tgz", - "integrity": "sha512-NDFf5j/raA5JrcPT/NcHP3RUMH7TkdkxQKAKdvDlgb+MS296WJzzqvV0Y5uwavSm7A6oYvBeSV0AxoHdDiHIiw==", - "requires": { - "diacritics": "1.3.0" - } - }, - "iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" - }, - "ignore": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", - "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", - "dev": true - }, - "import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "requires": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - } - }, - "import-in-the-middle": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.11.0.tgz", - "integrity": "sha512-5DimNQGoe0pLUHbR9qK84iWaWjjbsxiqXnw6Qz64+azRgleqv9k2kTt5fw7QsOpmaGYtuxxursnPPsnTKEx10Q==", - "requires": { - "acorn": "^8.8.2", - "acorn-import-attributes": "^1.9.5", - "cjs-module-lexer": "^1.2.2", - "module-details-from-path": "^1.0.3" - } - }, - "imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "dev": true - }, - "indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" - }, - "inquirer": { - "version": "8.2.6", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.6.tgz", - "integrity": "sha512-M1WuAmb7pn9zdFRtQYk26ZBoY043Sse0wVDdk4Bppr+JOXyQYybdtvK+l9wUibhtjdjvtoiNy8tk+EgsYIUqKg==", - "requires": { - "ansi-escapes": "^4.2.1", - "chalk": "^4.1.1", - "cli-cursor": "^3.1.0", - "cli-width": "^3.0.0", - "external-editor": "^3.0.3", - "figures": "^3.0.0", - "lodash": "^4.17.21", - "mute-stream": "0.0.8", - "ora": "^5.4.1", - "run-async": "^2.4.0", - "rxjs": "^7.5.5", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0", - "through": "^2.3.6", - "wrap-ansi": "^6.0.1" - } - }, - "ioredis": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/ioredis/-/ioredis-5.4.1.tgz", - "integrity": "sha512-2YZsvl7jopIa1gaePkeMtd9rAcSjOOjPtpcLlOeusyO+XH2SK5ZcT+UCrElPP+WVIInh2TzeI4XW9ENaSLVVHA==", - "requires": { - "@ioredis/commands": "^1.1.1", - "cluster-key-slot": "^1.1.0", - "debug": "^4.3.4", - "denque": "^2.1.0", - "lodash.defaults": "^4.2.0", - "lodash.isarguments": "^3.1.0", - "redis-errors": "^1.2.0", - "redis-parser": "^3.0.0", - "standard-as-callback": "^2.1.0" - } - }, - "ipaddr.js": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" - }, - "is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==" - }, - "is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "requires": { - "binary-extensions": "^2.0.0" - } - }, - "is-builtin-module": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-3.2.1.tgz", - "integrity": "sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==", - "dev": true, - "requires": { - "builtin-modules": "^3.3.0" - } - }, - "is-core-module": { - "version": "2.13.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.0.tgz", - "integrity": "sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==", - "requires": { - "has": "^1.0.3" - } - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==" - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" - }, - "is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "requires": { - "is-extglob": "^2.1.1" - } - }, - "is-interactive": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", - "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==" - }, - "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" - }, - "is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==" - }, - "is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==" - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" - }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" - }, - "istanbul-lib-coverage": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", - "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", - "dev": true - }, - "istanbul-lib-report": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", - "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", - "dev": true, - "requires": { - "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^4.0.0", - "supports-color": "^7.1.0" - }, - "dependencies": { - "make-dir": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", - "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", - "dev": true, - "requires": { - "semver": "^7.5.3" - } - } - } - }, - "istanbul-lib-source-maps": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-5.0.6.tgz", - "integrity": "sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A==", - "dev": true, - "requires": { - "@jridgewell/trace-mapping": "^0.3.23", - "debug": "^4.1.1", - "istanbul-lib-coverage": "^3.0.0" - } - }, - "istanbul-reports": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz", - "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==", - "dev": true, - "requires": { - "html-escaper": "^2.0.0", - "istanbul-lib-report": "^3.0.0" - } - }, - "iterare": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/iterare/-/iterare-1.2.1.tgz", - "integrity": "sha512-RKYVTCjAnRthyJes037NX/IiqeidgN1xc3j1RjFfECFp28A1GVwK9nA+i0rJPaHqSZwygLzRnFlzUuHFoWWy+Q==" - }, - "jackspeak": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", - "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", - "requires": { - "@isaacs/cliui": "^8.0.2", - "@pkgjs/parseargs": "^0.11.0" - } - }, - "jiti": { - "version": "1.21.0", - "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.0.tgz", - "integrity": "sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==", - "peer": true - }, - "joi": { - "version": "17.13.3", - "resolved": "https://registry.npmjs.org/joi/-/joi-17.13.3.tgz", - "integrity": "sha512-otDA4ldcIx+ZXsKHWmp0YizCweVRZG96J10b0FevjfuncLO1oX59THoAmHkNubYJ+9gWsYsp5k8v4ib6oDv1fA==", - "requires": { - "@hapi/hoek": "^9.3.0", - "@hapi/topo": "^5.1.0", - "@sideway/address": "^4.1.5", - "@sideway/formula": "^3.0.1", - "@sideway/pinpoint": "^2.0.0" - } - }, - "jose": { - "version": "4.15.9", - "resolved": "https://registry.npmjs.org/jose/-/jose-4.15.9.tgz", - "integrity": "sha512-1vUQX+IdDMVPj4k8kOxgUqlcK518yluMuGZwqlr44FS1ppZB/5GWh4rZG89erpOBOJjU/OBsnCVFfapsRz6nEA==" - }, - "js-beautify": { - "version": "1.15.1", - "resolved": "https://registry.npmjs.org/js-beautify/-/js-beautify-1.15.1.tgz", - "integrity": "sha512-ESjNzSlt/sWE8sciZH8kBF8BPlwXPwhR6pWKAw8bw4Bwj+iZcnKW6ONWUutJ7eObuBZQpiIb8S7OYspWrKt7rA==", - "requires": { - "config-chain": "^1.1.13", - "editorconfig": "^1.0.4", - "glob": "^10.3.3", - "js-cookie": "^3.0.5", - "nopt": "^7.2.0" - }, - "dependencies": { - "abbrev": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-2.0.0.tgz", - "integrity": "sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==" - }, - "nopt": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-7.2.0.tgz", - "integrity": "sha512-CVDtwCdhYIvnAzFoJ6NJ6dX3oga9/HyciQDnG1vQDjSLMeKLJ4A93ZqYKDrgYSr1FBY5/hMYC+2VCi24pgpkGA==", - "requires": { - "abbrev": "^2.0.0" - } - } - } - }, - "js-cookie": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.5.tgz", - "integrity": "sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==" - }, - "js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" - }, - "js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "requires": { - "argparse": "^2.0.1" - } - }, - "jsesc": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz", - "integrity": "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==", - "dev": true - }, - "json-bigint": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz", - "integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==", - "requires": { - "bignumber.js": "^9.0.0" - } - }, - "json-buffer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", - "dev": true - }, - "json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" - }, - "json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - }, - "json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", - "dev": true - }, - "json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==" - }, - "jsonc-parser": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.1.tgz", - "integrity": "sha512-AilxAyFOAcK5wA1+LeaySVBrHsGQvUFCDWXKpZjzaL0PqW+xfBOttn8GNtWKFWqneyMZj41MWF9Kl6iPWLwgOA==", - "dev": true - }, - "jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6", - "universalify": "^2.0.0" - } - }, - "keyv": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", - "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", - "dev": true, - "requires": { - "json-buffer": "3.0.1" - } - }, - "lazystream": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.1.tgz", - "integrity": "sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==", - "requires": { - "readable-stream": "^2.0.5" - }, - "dependencies": { - "readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "leac": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/leac/-/leac-0.6.0.tgz", - "integrity": "sha512-y+SqErxb8h7nE/fiEX07jsbuhrpO9lL8eca7/Y1nuWV2moNlXhyd59iDGcRf6moVyDMbmTNzL40SUyrFU/yDpg==" - }, - "levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "requires": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - } - }, - "libphonenumber-js": { - "version": "1.10.53", - "resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.10.53.tgz", - "integrity": "sha512-sDTnnqlWK4vH4AlDQuswz3n4Hx7bIQWTpIcScJX+Sp7St3LXHmfiax/ZFfyYxHmkdCvydOLSuvtAO/XpXiSySw==" - }, - "lilconfig": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", - "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", - "peer": true - }, - "lines-and-columns": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" - }, - "load-tsconfig": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/load-tsconfig/-/load-tsconfig-0.2.5.tgz", - "integrity": "sha512-IXO6OCs9yg8tMKzfPZ1YmheJbZCiEsnBdcB03l0OcfK9prKnJb96siuHCr5Fl37/yo9DnKU+TLpxzTUspw9shg==", - "dev": true - }, - "loader-runner": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", - "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", - "dev": true - }, - "locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "requires": { - "p-locate": "^5.0.0" - } - }, - "lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" - }, - "lodash.camelcase": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", - "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==" - }, - "lodash.defaults": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", - "integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==" - }, - "lodash.isarguments": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", - "integrity": "sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg==" - }, - "lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true - }, - "log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "requires": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - } - }, - "long": { - "version": "5.2.3", - "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz", - "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==" - }, - "loose-envify": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", - "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "requires": { - "js-tokens": "^3.0.0 || ^4.0.0" - } - }, - "loupe": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.1.2.tgz", - "integrity": "sha512-23I4pFZHmAemUnz8WZXbYRSKYj801VDaNv9ETuMh7IrMc7VuVVSo+Z9iLE3ni30+U48iDWfi30d3twAXBYmnCg==", - "dev": true - }, - "lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "requires": { - "yallist": "^3.0.2" - } - }, - "luxon": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/luxon/-/luxon-3.5.0.tgz", - "integrity": "sha512-rh+Zjr6DNfUYR3bPwJEnuwDdqMbxZW7LOQfUN4B54+Cl+0o5zaU9RJ6bcidfDtC1cWCZXQ+nvX8bf6bAji37QQ==" - }, - "magic-string": { - "version": "0.30.8", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.8.tgz", - "integrity": "sha512-ISQTe55T2ao7XtlAStud6qwYPZjE4GK1S/BeVPus4jrq6JuOnQ00YKQC581RWhR122W7msZV263KzVeLoqidyQ==", - "dev": true, - "requires": { - "@jridgewell/sourcemap-codec": "^1.4.15" - } - }, - "magicast": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/magicast/-/magicast-0.3.4.tgz", - "integrity": "sha512-TyDF/Pn36bBji9rWKHlZe+PZb6Mx5V8IHCSxk7X4aljM4e/vyDvZZYwHewdVaqiA0nb3ghfHU/6AUpDxWoER2Q==", - "dev": true, - "requires": { - "@babel/parser": "^7.24.4", - "@babel/types": "^7.24.0", - "source-map-js": "^1.2.0" - } - }, - "make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "requires": { - "semver": "^6.0.0" - }, - "dependencies": { - "semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" - } - } - }, - "make-error": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", - "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "optional": true, - "peer": true - }, - "marked": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/marked/-/marked-7.0.4.tgz", - "integrity": "sha512-t8eP0dXRJMtMvBojtkcsA7n48BkauktUKzfkPSCq85ZMTJ0v76Rke4DYz01omYpPTUh4p/f7HePgRo3ebG8+QQ==" - }, - "md-to-react-email": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/md-to-react-email/-/md-to-react-email-5.0.2.tgz", - "integrity": "sha512-x6kkpdzIzUhecda/yahltfEl53mH26QdWu4abUF9+S0Jgam8P//Ciro8cdhyMHnT5MQUJYrIbO6ORM2UxPiNNA==", - "requires": { - "marked": "7.0.4" - } - }, - "media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==" - }, - "memfs": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.5.3.tgz", - "integrity": "sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==", - "dev": true, - "requires": { - "fs-monkey": "^1.0.4" - } - }, - "merge-descriptors": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", - "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==" - }, - "merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true - }, - "merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==" - }, - "methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==" - }, - "micromatch": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", - "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", - "requires": { - "braces": "^3.0.3", - "picomatch": "^2.3.1" - }, - "dependencies": { - "picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==" - } - } - }, - "mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" - }, - "mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" - }, - "mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "requires": { - "mime-db": "1.52.0" - } - }, - "mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==" - }, - "min-indent": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", - "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", - "dev": true - }, - "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==" - }, - "minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==" - }, - "minizlib": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", - "requires": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" - }, - "dependencies": { - "minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "requires": { - "yallist": "^4.0.0" - } - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - } - } - }, - "mkdirp": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", - "requires": { - "minimist": "^1.2.6" - } - }, - "mkdirp-classic": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", - "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", - "dev": true - }, - "mock-fs": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/mock-fs/-/mock-fs-5.4.0.tgz", - "integrity": "sha512-3ROPnEMgBOkusBMYQUW2rnT3wZwsgfOKzJDLvx/TZ7FL1WmWvwSwn3j4aDR5fLDGtgcc1WF0Z1y0di7c9L4FKw==", - "dev": true - }, - "module-details-from-path": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/module-details-from-path/-/module-details-from-path-1.0.3.tgz", - "integrity": "sha512-ySViT69/76t8VhE1xXHK6Ch4NcDd26gx0MzKXLO+F7NOtnqH68d9zF94nT8ZWSxXh8ELOERsnJO/sWt1xZYw5A==" - }, - "moo": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/moo/-/moo-0.5.2.tgz", - "integrity": "sha512-iSAJLHYKnX41mKcJKjqvnAN9sf0LMDTXDEvFv+ffuRR9a1MIuXLjMNL6EsnDHSkKLTWNqQQ5uo61P4EbU4NU+Q==", - "dev": true - }, - "mrmime": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.0.tgz", - "integrity": "sha512-eu38+hdgojoyq63s+yTpN4XMBdt5l8HhMhc4VKLO9KM5caLIBvUm4thi7fFaxyTmCKeNnXZ5pAlBwCUnhA09uw==" - }, - "ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" - }, - "msgpackr": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/msgpackr/-/msgpackr-1.10.1.tgz", - "integrity": "sha512-r5VRLv9qouXuLiIBrLpl2d5ZvPt8svdQTl5/vMvE4nzDMyEX4sgW5yWhuBBj5UmgwOTWj8CIdSXn5sAfsHAWIQ==", - "requires": { - "msgpackr-extract": "^3.0.2" - } - }, - "msgpackr-extract": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/msgpackr-extract/-/msgpackr-extract-3.0.2.tgz", - "integrity": "sha512-SdzXp4kD/Qf8agZ9+iTu6eql0m3kWm1A2y1hkpTeVNENutaB0BwHlSvAIaMxwntmRUAUjon2V4L8Z/njd0Ct8A==", - "optional": true, - "requires": { - "@msgpackr-extract/msgpackr-extract-darwin-arm64": "3.0.2", - "@msgpackr-extract/msgpackr-extract-darwin-x64": "3.0.2", - "@msgpackr-extract/msgpackr-extract-linux-arm": "3.0.2", - "@msgpackr-extract/msgpackr-extract-linux-arm64": "3.0.2", - "@msgpackr-extract/msgpackr-extract-linux-x64": "3.0.2", - "@msgpackr-extract/msgpackr-extract-win32-x64": "3.0.2", - "node-gyp-build-optional-packages": "5.0.7" - } - }, - "multer": { - "version": "1.4.4-lts.1", - "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.4-lts.1.tgz", - "integrity": "sha512-WeSGziVj6+Z2/MwQo3GvqzgR+9Uc+qt8SwHKh3gvNPiISKfsMfG4SvCOFYlxxgkXt7yIV2i1yczehm0EOKIxIg==", - "requires": { - "append-field": "^1.0.0", - "busboy": "^1.0.0", - "concat-stream": "^1.5.2", - "mkdirp": "^0.5.4", - "object-assign": "^4.1.1", - "type-is": "^1.6.4", - "xtend": "^4.0.0" - }, - "dependencies": { - "concat-stream": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", - "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", - "requires": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^2.2.2", - "typedarray": "^0.0.6" - } - }, - "readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "mute-stream": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", - "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==" - }, - "mz": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", - "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", - "requires": { - "any-promise": "^1.0.0", - "object-assign": "^4.0.1", - "thenify-all": "^1.0.0" - } - }, - "nan": { - "version": "2.18.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.18.0.tgz", - "integrity": "sha512-W7tfG7vMOGtD30sHoZSSc/JVYiyDPEyQVso/Zz+/uQd0B0L46gtC+pHha5FFMRpil6fm/AoEcRWyOVi4+E/f8w==", - "dev": true, - "optional": true - }, - "nanoid": { - "version": "3.3.7", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", - "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==" - }, - "natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true - }, - "nearley": { - "version": "2.20.1", - "resolved": "https://registry.npmjs.org/nearley/-/nearley-2.20.1.tgz", - "integrity": "sha512-+Mc8UaAebFzgV+KpI5n7DasuuQCHA89dmwm7JXw3TV43ukfNQ9DnBH3Mdb2g/I4Fdxc26pwimBWvjIw0UAILSQ==", - "dev": true, - "requires": { - "commander": "^2.19.0", - "moo": "^0.5.0", - "railroad-diagrams": "^1.0.0", - "randexp": "0.4.6" - }, - "dependencies": { - "commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true - } - } - }, - "negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==" - }, - "neo-async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" - }, - "nest-commander": { - "version": "3.15.0", - "resolved": "https://registry.npmjs.org/nest-commander/-/nest-commander-3.15.0.tgz", - "integrity": "sha512-o9VEfFj/w2nm+hQi6fnkxL1GAFZW/KmuGcIE7/B/TX0gwm0QVy8svAF75EQm8wrDjcvWS7Cx/ArnkFn2C+iM2w==", - "requires": { - "@fig/complete-commander": "^3.0.0", - "@golevelup/nestjs-discovery": "4.0.1", - "commander": "11.1.0", - "cosmiconfig": "8.3.6", - "inquirer": "8.2.6" - }, - "dependencies": { - "@fig/complete-commander": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/@fig/complete-commander/-/complete-commander-3.2.0.tgz", - "integrity": "sha512-1Holl3XtRiANVKURZwgpjCnPuV4RsHp+XC0MhgvyAX/avQwj7F2HUItYOvGi/bXjJCkEzgBZmVfCr0HBA+q+Bw==", - "requires": { - "prettier": "^3.2.5" - } - }, - "commander": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz", - "integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==" - } - } - }, - "nestjs-cls": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/nestjs-cls/-/nestjs-cls-4.4.1.tgz", - "integrity": "sha512-4yhldwm/cJ02lQ8ZAdM8KQ7gMfjAc1z3fo5QAQgXNyN4N6X5So9BCwv+BTLRugDCkELUo3qtzQHnKhGYL/ftPg==", - "requires": {} - }, - "nestjs-otel": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/nestjs-otel/-/nestjs-otel-6.1.1.tgz", - "integrity": "sha512-hWuhDYkkaZrBXpHmi2v0jGqKa61uPqzu2YsVhww8/s+v9SaDILylR7ZdoOiygCQisgHG9rw5odP12GfsMS8cBA==", - "requires": { - "@opentelemetry/api": "^1.8.0", - "@opentelemetry/host-metrics": "^0.35.1", - "response-time": "^2.3.2" - } - }, - "next": { - "version": "14.2.3", - "resolved": "https://registry.npmjs.org/next/-/next-14.2.3.tgz", - "integrity": "sha512-dowFkFTR8v79NPJO4QsBUtxv0g9BrS/phluVpMAt2ku7H+cbcBJlopXjkWlwxrk/xGqMemr7JkGPGemPrLLX7A==", - "requires": { - "@next/env": "14.2.3", - "@next/swc-darwin-arm64": "14.2.3", - "@next/swc-darwin-x64": "14.2.3", - "@next/swc-linux-arm64-gnu": "14.2.3", - "@next/swc-linux-arm64-musl": "14.2.3", - "@next/swc-linux-x64-gnu": "14.2.3", - "@next/swc-linux-x64-musl": "14.2.3", - "@next/swc-win32-arm64-msvc": "14.2.3", - "@next/swc-win32-ia32-msvc": "14.2.3", - "@next/swc-win32-x64-msvc": "14.2.3", - "@swc/helpers": "0.5.5", - "busboy": "1.6.0", - "caniuse-lite": "^1.0.30001579", - "graceful-fs": "^4.2.11", - "postcss": "8.4.31", - "styled-jsx": "5.1.1" - }, - "dependencies": { - "postcss": { - "version": "8.4.31", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", - "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", - "requires": { - "nanoid": "^3.3.6", - "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" - } - } - } - }, - "node-abort-controller": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/node-abort-controller/-/node-abort-controller-3.1.1.tgz", - "integrity": "sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==" - }, - "node-emoji": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-1.11.0.tgz", - "integrity": "sha512-wo2DpQkQp7Sjm2A0cq+sN7EHKO6Sl0ctXeBdFZrL9T9+UywORbufTcTZxom8YqpLQt/FqNMUkOpkZrJVYSKD3A==", - "dev": true, - "requires": { - "lodash": "^4.17.21" - } - }, - "node-fetch": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", - "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", - "requires": { - "whatwg-url": "^5.0.0" - } - }, - "node-gyp-build-optional-packages": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/node-gyp-build-optional-packages/-/node-gyp-build-optional-packages-5.0.7.tgz", - "integrity": "sha512-YlCCc6Wffkx0kHkmam79GKvDQ6x+QZkMjFGrIMxgFNILFvGSbCp2fCBC55pGTT9gVaz8Na5CLmxt/urtzRv36w==", - "optional": true - }, - "node-releases": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", - "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==" - }, - "nodemailer": { - "version": "6.9.15", - "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.15.tgz", - "integrity": "sha512-AHf04ySLC6CIfuRtRiEYtGEXgRfa6INgWGluDhnxTZhHSKvrBu7lc1VVchQ0d8nPc4cFaZoPq8vkyNoZr0TpGQ==" - }, - "nopt": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", - "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", - "requires": { - "abbrev": "1" - } - }, - "normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dev": true, - "requires": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - }, - "dependencies": { - "semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true - } - } - }, - "normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" - }, - "notepack.io": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/notepack.io/-/notepack.io-3.0.1.tgz", - "integrity": "sha512-TKC/8zH5pXIAMVQio2TvVDTtPRX+DJPHDqjRbxogtFiByHyzKmy96RA0JtCQJ+WouyyL4A10xomQzgbUT+1jCg==" - }, - "npmlog": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", - "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", - "requires": { - "are-we-there-yet": "^2.0.0", - "console-control-strings": "^1.1.0", - "gauge": "^3.0.0", - "set-blocking": "^2.0.0" - } - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==" - }, - "object-hash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", - "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==" - }, - "object-inspect": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", - "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==" - }, - "obuf": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", - "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==" - }, - "oidc-token-hash": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/oidc-token-hash/-/oidc-token-hash-5.0.3.tgz", - "integrity": "sha512-IF4PcGgzAr6XXSff26Sk/+P4KZFJVuHAJZj3wgO3vX2bMdNVp/QXTP3P7CEm9V1IdG8lDLY3HhiqpsE/nOwpPw==" - }, - "on-finished": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", - "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", - "requires": { - "ee-first": "1.1.1" - } - }, - "on-headers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", - "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==" - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "requires": { - "wrappy": "1" - } - }, - "onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "requires": { - "mimic-fn": "^2.1.0" - } - }, - "openid-client": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/openid-client/-/openid-client-5.7.0.tgz", - "integrity": "sha512-4GCCGZt1i2kTHpwvaC/sCpTpQqDnBzDzuJcJMbH+y1Q5qI8U8RBvoSh28svarXszZHR5BAMXbJPX1PGPRE3VOA==", - "requires": { - "jose": "^4.15.9", - "lru-cache": "^6.0.0", - "object-hash": "^2.2.0", - "oidc-token-hash": "^5.0.3" - }, - "dependencies": { - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "requires": { - "yallist": "^4.0.0" - } - }, - "object-hash": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-2.2.0.tgz", - "integrity": "sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw==" - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - } - } - }, - "optionator": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", - "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", - "dev": true, - "requires": { - "@aashutoshrathi/word-wrap": "^1.2.3", - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0" - } - }, - "ora": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", - "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", - "requires": { - "bl": "^4.1.0", - "chalk": "^4.1.0", - "cli-cursor": "^3.1.0", - "cli-spinners": "^2.5.0", - "is-interactive": "^1.0.0", - "is-unicode-supported": "^0.1.0", - "log-symbols": "^4.1.0", - "strip-ansi": "^6.0.0", - "wcwidth": "^1.0.1" - } - }, - "os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==" - }, - "p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "requires": { - "yocto-queue": "^0.1.0" - } - }, - "p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "requires": { - "p-limit": "^3.0.2" - } - }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true - }, - "package-json-from-dist": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.0.tgz", - "integrity": "sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw==" - }, - "parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "requires": { - "callsites": "^3.0.0" - } - }, - "parse-json": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", - "requires": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" - } - }, - "parse5": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.1.tgz", - "integrity": "sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==" - }, - "parse5-htmlparser2-tree-adapter": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz", - "integrity": "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==", - "requires": { - "parse5": "^6.0.1" - }, - "dependencies": { - "parse5": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", - "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==" - } - } - }, - "parseley": { - "version": "0.12.1", - "resolved": "https://registry.npmjs.org/parseley/-/parseley-0.12.1.tgz", - "integrity": "sha512-e6qHKe3a9HWr0oMRVDTRhKce+bRO8VGQR3NyVwcjwrbhMmFCX9KszEV35+rn4AdilFAq9VPxP/Fe1wC9Qjd2lw==", - "requires": { - "leac": "^0.6.0", - "peberminta": "^0.9.0" - } - }, - "parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" - }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==" - }, - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==" - }, - "path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" - }, - "path-scurry": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", - "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", - "requires": { - "lru-cache": "^10.2.0", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" - }, - "dependencies": { - "lru-cache": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz", - "integrity": "sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==" - } - } - }, - "path-source": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/path-source/-/path-source-0.1.3.tgz", - "integrity": "sha512-dWRHm5mIw5kw0cs3QZLNmpUWty48f5+5v9nWD2dw3Y0Hf+s01Ag8iJEWV0Sm0kocE8kK27DrIowha03e1YR+Qw==", - "requires": { - "array-source": "0.0", - "file-source": "0.6" - } - }, - "path-to-regexp": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-3.3.0.tgz", - "integrity": "sha512-qyCH421YQPS2WFDxDjftfc1ZR5WKQzVzqsp4n9M2kQhVOo/ByahFoUNJfl58kOcEGfQ//7weFTDhm+ss8Ecxgw==" - }, - "path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==" - }, - "pathe": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz", - "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==", - "dev": true - }, - "pathval": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.0.tgz", - "integrity": "sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==", - "dev": true - }, - "pbf": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/pbf/-/pbf-3.2.1.tgz", - "integrity": "sha512-ClrV7pNOn7rtmoQVF4TS1vyU0WhYRnP92fzbfF75jAIwpnzdJXf8iTd4CMEqO4yUenH6NDqLiwjqlh6QgZzgLQ==", - "requires": { - "ieee754": "^1.1.12", - "resolve-protobuf-schema": "^2.1.0" - } - }, - "peberminta": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/peberminta/-/peberminta-0.9.0.tgz", - "integrity": "sha512-XIxfHpEuSJbITd1H3EeQwpcZbTLHc+VVr8ANI9t5sit565tsI4/xK3KWTUFE2e6QiangUkh3B0jihzmGnNrRsQ==" - }, - "pg": { - "version": "8.13.1", - "resolved": "https://registry.npmjs.org/pg/-/pg-8.13.1.tgz", - "integrity": "sha512-OUir1A0rPNZlX//c7ksiu7crsGZTKSOXJPgtNiHGIlC9H0lO+NC6ZDYksSgBYY/thSWhnSRBv8w1lieNNGATNQ==", - "requires": { - "pg-cloudflare": "^1.1.1", - "pg-connection-string": "^2.7.0", - "pg-pool": "^3.7.0", - "pg-protocol": "^1.7.0", - "pg-types": "^2.1.0", - "pgpass": "1.x" - } - }, - "pg-cloudflare": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.1.1.tgz", - "integrity": "sha512-xWPagP/4B6BgFO+EKz3JONXv3YDgvkbVrGw2mTo3D6tVDQRh1e7cqVGvyR3BE+eQgAvx1XhW/iEASj4/jCWl3Q==", - "optional": true - }, - "pg-connection-string": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.7.0.tgz", - "integrity": "sha512-PI2W9mv53rXJQEOb8xNR8lH7Hr+EKa6oJa38zsK0S/ky2er16ios1wLKhZyxzD7jUReiWokc9WK5nxSnC7W1TA==" - }, - "pg-int8": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz", - "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==" - }, - "pg-numeric": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pg-numeric/-/pg-numeric-1.0.2.tgz", - "integrity": "sha512-BM/Thnrw5jm2kKLE5uJkXqqExRUY/toLHda65XgFTBTFYZyopbKjBe29Ii3RbkvlsMoFwD+tHeGaCjjv0gHlyw==" - }, - "pg-pool": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.7.0.tgz", - "integrity": "sha512-ZOBQForurqh4zZWjrgSwwAtzJ7QiRX0ovFkZr2klsen3Nm0aoh33Ls0fzfv3imeH/nw/O27cjdz5kzYJfeGp/g==", - "requires": {} - }, - "pg-protocol": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.7.0.tgz", - "integrity": "sha512-hTK/mE36i8fDDhgDFjy6xNOG+LCorxLG3WO17tku+ij6sVHXh1jQUJ8hYAnRhNla4QVD2H8er/FOjc/+EgC6yQ==" - }, - "pg-types": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz", - "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==", - "requires": { - "pg-int8": "1.0.1", - "postgres-array": "~2.0.0", - "postgres-bytea": "~1.0.0", - "postgres-date": "~1.0.4", - "postgres-interval": "^1.1.0" - } - }, - "pgpass": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.5.tgz", - "integrity": "sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==", - "requires": { - "split2": "^4.1.0" - } - }, - "picocolors": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.0.tgz", - "integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==" - }, - "picomatch": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", - "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==" - }, - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", - "peer": true - }, - "pirates": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", - "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", - "peer": true - }, - "pluralize": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", - "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==", - "dev": true - }, - "pngjs": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-7.0.0.tgz", - "integrity": "sha512-LKWqWJRhstyYo9pGvgor/ivk2w94eSjE3RGVuzLGlr3NmD8bf7RcYGze1mNdEHRP6TRP6rMuDHk5t44hnTRyow==", - "dev": true - }, - "point-in-polygon-hao": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/point-in-polygon-hao/-/point-in-polygon-hao-1.1.0.tgz", - "integrity": "sha512-3hTIM2j/v9Lio+wOyur3kckD4NxruZhpowUbEgmyikW+a2Kppjtu1eN+AhnMQtoHW46zld88JiYWv6fxpsDrTQ==" - }, - "postcss": { - "version": "8.4.47", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.47.tgz", - "integrity": "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==", - "requires": { - "nanoid": "^3.3.7", - "picocolors": "^1.1.0", - "source-map-js": "^1.2.1" - } - }, - "postcss-import": { - "version": "15.1.0", - "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz", - "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==", - "peer": true, - "requires": { - "postcss-value-parser": "^4.0.0", - "read-cache": "^1.0.0", - "resolve": "^1.1.7" - } - }, - "postcss-js": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz", - "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==", - "peer": true, - "requires": { - "camelcase-css": "^2.0.1" - } - }, - "postcss-load-config": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz", - "integrity": "sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==", - "peer": true, - "requires": { - "lilconfig": "^3.0.0", - "yaml": "^2.3.4" - }, - "dependencies": { - "lilconfig": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.1.tgz", - "integrity": "sha512-O18pf7nyvHTckunPWCV1XUNXU1piu01y2b7ATJ0ppkUkk8ocqVWBrYjJBCwHDjD/ZWcfyrA0P4gKhzWGi5EINQ==", - "peer": true - } - } - }, - "postcss-nested": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.0.1.tgz", - "integrity": "sha512-mEp4xPMi5bSWiMbsgoPfcP74lsWLHkQbZc3sY+jWYd65CUwXrUaTp0fmNpa01ZcETKlIgUdFN/MpS2xZtqL9dQ==", - "peer": true, - "requires": { - "postcss-selector-parser": "^6.0.11" - } - }, - "postcss-selector-parser": { - "version": "6.0.16", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.16.tgz", - "integrity": "sha512-A0RVJrX+IUkVZbW3ClroRWurercFhieevHB38sr2+l9eUClMqome3LmEmnhlNy+5Mr2EYN6B2Kaw9wYdd+VHiw==", - "peer": true, - "requires": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - } - }, - "postcss-value-parser": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "peer": true - }, - "postgres-array": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz", - "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==" - }, - "postgres-bytea": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz", - "integrity": "sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==" - }, - "postgres-date": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz", - "integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==" - }, - "postgres-interval": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz", - "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==", - "requires": { - "xtend": "^4.0.0" - } - }, - "postgres-range": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/postgres-range/-/postgres-range-1.1.4.tgz", - "integrity": "sha512-i/hbxIE9803Alj/6ytL7UHQxRvZkI9O4Sy+J3HGc4F4oo/2eQAjTSNJ0bfxyse3bH0nuVesCk+3IRLaMtG3H6w==" - }, - "prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true - }, - "prettier": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.3.tgz", - "integrity": "sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==" - }, - "prettier-linter-helpers": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", - "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", - "dev": true, - "requires": { - "fast-diff": "^1.1.2" - } - }, - "prettier-plugin-organize-imports": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/prettier-plugin-organize-imports/-/prettier-plugin-organize-imports-4.1.0.tgz", - "integrity": "sha512-5aWRdCgv645xaa58X8lOxzZoiHAldAPChljr/MT0crXVOWTZ+Svl4hIWlz+niYSlO6ikE5UXkN1JrRvIP2ut0A==", - "dev": true, - "requires": {} - }, - "prismjs": { - "version": "1.29.0", - "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.29.0.tgz", - "integrity": "sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q==" - }, - "process": { - "version": "0.11.10", - "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", - "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==" - }, - "process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" - }, - "proper-lockfile": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/proper-lockfile/-/proper-lockfile-4.1.2.tgz", - "integrity": "sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA==", - "dev": true, - "requires": { - "graceful-fs": "^4.2.4", - "retry": "^0.12.0", - "signal-exit": "^3.0.2" - }, - "dependencies": { - "signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true - } - } - }, - "properties-reader": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/properties-reader/-/properties-reader-2.3.0.tgz", - "integrity": "sha512-z597WicA7nDZxK12kZqHr2TcvwNU1GCfA5UwfDY/HDp3hXPoPlb5rlEx9bwGTiJnc0OqbBTkU975jDToth8Gxw==", - "dev": true, - "requires": { - "mkdirp": "^1.0.4" - }, - "dependencies": { - "mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true - } - } - }, - "proto-list": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", - "integrity": "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==" - }, - "protobufjs": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.4.0.tgz", - "integrity": "sha512-mRUWCc3KUU4w1jU8sGxICXH/gNS94DvI1gxqDvBzhj1JpcsimQkYiOJfwsPUykUI5ZaspFbSgmBLER8IrQ3tqw==", - "requires": { - "@protobufjs/aspromise": "^1.1.2", - "@protobufjs/base64": "^1.1.2", - "@protobufjs/codegen": "^2.0.4", - "@protobufjs/eventemitter": "^1.1.0", - "@protobufjs/fetch": "^1.1.0", - "@protobufjs/float": "^1.0.2", - "@protobufjs/inquire": "^1.1.0", - "@protobufjs/path": "^1.1.2", - "@protobufjs/pool": "^1.1.0", - "@protobufjs/utf8": "^1.1.0", - "@types/node": ">=13.7.0", - "long": "^5.0.0" - } - }, - "protocol-buffers-schema": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/protocol-buffers-schema/-/protocol-buffers-schema-3.6.0.tgz", - "integrity": "sha512-TdDRD+/QNdrCGCE7v8340QyuXd4kIWIgapsE2+n/SaGiSSbomYl4TjHlvIoCWRpE7wFt02EpB35VVA2ImcBVqw==" - }, - "proxy-addr": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", - "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", - "requires": { - "forwarded": "0.2.0", - "ipaddr.js": "1.9.1" - } - }, - "pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "punycode": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", - "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", - "dev": true - }, - "qs": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", - "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", - "requires": { - "side-channel": "^1.0.6" - } - }, - "queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==" - }, - "queue-tick": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/queue-tick/-/queue-tick-1.0.1.tgz", - "integrity": "sha512-kJt5qhMxoszgU/62PLP1CJytzd2NKetjSRnyuj31fDd3Rlcz3fzlFdFLD1SItunPwyqEOkca6GbV612BWfaBag==" - }, - "railroad-diagrams": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/railroad-diagrams/-/railroad-diagrams-1.0.0.tgz", - "integrity": "sha512-cz93DjNeLY0idrCNOH6PviZGRN9GJhsdm9hpn1YCS879fj4W+x5IFJhhkRZcwVgMmFF7R82UA/7Oh+R8lLZg6A==", - "dev": true - }, - "randexp": { - "version": "0.4.6", - "resolved": "https://registry.npmjs.org/randexp/-/randexp-0.4.6.tgz", - "integrity": "sha512-80WNmd9DA0tmZrw9qQa62GPPWfuXJknrmVmLcxvq4uZBdYqb1wYoKTmnlGUchvVWe0XiLupYkBoXVOxz3C8DYQ==", - "dev": true, - "requires": { - "discontinuous-range": "1.0.0", - "ret": "~0.1.10" - } - }, - "randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, - "requires": { - "safe-buffer": "^5.1.0" - } - }, - "range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" - }, - "raw-body": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", - "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", - "requires": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - } - }, - "react": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", - "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", - "requires": { - "loose-envify": "^1.1.0" - } - }, - "react-dom": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", - "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", - "peer": true, - "requires": { - "loose-envify": "^1.1.0", - "scheduler": "^0.23.2" - } - }, - "react-email": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/react-email/-/react-email-3.0.1.tgz", - "integrity": "sha512-G4Bkx2ULIScy/0Z8nnWywHt0W1iTkaYCdh9rWNuQ3eVZ6B3ttTUDE9uUy3VNQ8dtQbmG0cpt8+XmImw7mMBW6Q==", - "requires": { - "@babel/core": "7.24.5", - "@babel/parser": "7.24.5", - "chalk": "4.1.2", - "chokidar": "3.6.0", - "commander": "11.1.0", - "debounce": "2.0.0", - "esbuild": "0.19.11", - "glob": "10.3.4", - "log-symbols": "4.1.0", - "mime-types": "2.1.35", - "next": "14.2.3", - "normalize-path": "3.0.0", - "ora": "5.4.1", - "socket.io": "4.7.5" - }, - "dependencies": { - "@esbuild/aix-ppc64": { - "version": "0.19.11", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.19.11.tgz", - "integrity": "sha512-FnzU0LyE3ySQk7UntJO4+qIiQgI7KoODnZg5xzXIrFJlKd2P2gwHsHY4927xj9y5PJmJSzULiUCWmv7iWnNa7g==", - "optional": true - }, - "@esbuild/android-arm": { - "version": "0.19.11", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.11.tgz", - "integrity": "sha512-5OVapq0ClabvKvQ58Bws8+wkLCV+Rxg7tUVbo9xu034Nm536QTII4YzhaFriQ7rMrorfnFKUsArD2lqKbFY4vw==", - "optional": true - }, - "@esbuild/android-arm64": { - "version": "0.19.11", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.19.11.tgz", - "integrity": "sha512-aiu7K/5JnLj//KOnOfEZ0D90obUkRzDMyqd/wNAUQ34m4YUPVhRZpnqKV9uqDGxT7cToSDnIHsGooyIczu9T+Q==", - "optional": true - }, - "@esbuild/android-x64": { - "version": "0.19.11", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.19.11.tgz", - "integrity": "sha512-eccxjlfGw43WYoY9QgB82SgGgDbibcqyDTlk3l3C0jOVHKxrjdc9CTwDUQd0vkvYg5um0OH+GpxYvp39r+IPOg==", - "optional": true - }, - "@esbuild/darwin-arm64": { - "version": "0.19.11", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.11.tgz", - "integrity": "sha512-ETp87DRWuSt9KdDVkqSoKoLFHYTrkyz2+65fj9nfXsaV3bMhTCjtQfw3y+um88vGRKRiF7erPrh/ZuIdLUIVxQ==", - "optional": true - }, - "@esbuild/darwin-x64": { - "version": "0.19.11", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.19.11.tgz", - "integrity": "sha512-fkFUiS6IUK9WYUO/+22omwetaSNl5/A8giXvQlcinLIjVkxwTLSktbF5f/kJMftM2MJp9+fXqZ5ezS7+SALp4g==", - "optional": true - }, - "@esbuild/freebsd-arm64": { - "version": "0.19.11", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.11.tgz", - "integrity": "sha512-lhoSp5K6bxKRNdXUtHoNc5HhbXVCS8V0iZmDvyWvYq9S5WSfTIHU2UGjcGt7UeS6iEYp9eeymIl5mJBn0yiuxA==", - "optional": true - }, - "@esbuild/freebsd-x64": { - "version": "0.19.11", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.19.11.tgz", - "integrity": "sha512-JkUqn44AffGXitVI6/AbQdoYAq0TEullFdqcMY/PCUZ36xJ9ZJRtQabzMA+Vi7r78+25ZIBosLTOKnUXBSi1Kw==", - "optional": true - }, - "@esbuild/linux-arm": { - "version": "0.19.11", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.19.11.tgz", - "integrity": "sha512-3CRkr9+vCV2XJbjwgzjPtO8T0SZUmRZla+UL1jw+XqHZPkPgZiyWvbDvl9rqAN8Zl7qJF0O/9ycMtjU67HN9/Q==", - "optional": true - }, - "@esbuild/linux-arm64": { - "version": "0.19.11", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.19.11.tgz", - "integrity": "sha512-LneLg3ypEeveBSMuoa0kwMpCGmpu8XQUh+mL8XXwoYZ6Be2qBnVtcDI5azSvh7vioMDhoJFZzp9GWp9IWpYoUg==", - "optional": true - }, - "@esbuild/linux-ia32": { - "version": "0.19.11", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.19.11.tgz", - "integrity": "sha512-caHy++CsD8Bgq2V5CodbJjFPEiDPq8JJmBdeyZ8GWVQMjRD0sU548nNdwPNvKjVpamYYVL40AORekgfIubwHoA==", - "optional": true - }, - "@esbuild/linux-loong64": { - "version": "0.19.11", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.19.11.tgz", - "integrity": "sha512-ppZSSLVpPrwHccvC6nQVZaSHlFsvCQyjnvirnVjbKSHuE5N24Yl8F3UwYUUR1UEPaFObGD2tSvVKbvR+uT1Nrg==", - "optional": true - }, - "@esbuild/linux-mips64el": { - "version": "0.19.11", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.19.11.tgz", - "integrity": "sha512-B5x9j0OgjG+v1dF2DkH34lr+7Gmv0kzX6/V0afF41FkPMMqaQ77pH7CrhWeR22aEeHKaeZVtZ6yFwlxOKPVFyg==", - "optional": true - }, - "@esbuild/linux-ppc64": { - "version": "0.19.11", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.19.11.tgz", - "integrity": "sha512-MHrZYLeCG8vXblMetWyttkdVRjQlQUb/oMgBNurVEnhj4YWOr4G5lmBfZjHYQHHN0g6yDmCAQRR8MUHldvvRDA==", - "optional": true - }, - "@esbuild/linux-riscv64": { - "version": "0.19.11", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.19.11.tgz", - "integrity": "sha512-f3DY++t94uVg141dozDu4CCUkYW+09rWtaWfnb3bqe4w5NqmZd6nPVBm+qbz7WaHZCoqXqHz5p6CM6qv3qnSSQ==", - "optional": true - }, - "@esbuild/linux-s390x": { - "version": "0.19.11", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.19.11.tgz", - "integrity": "sha512-A5xdUoyWJHMMlcSMcPGVLzYzpcY8QP1RtYzX5/bS4dvjBGVxdhuiYyFwp7z74ocV7WDc0n1harxmpq2ePOjI0Q==", - "optional": true - }, - "@esbuild/linux-x64": { - "version": "0.19.11", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.19.11.tgz", - "integrity": "sha512-grbyMlVCvJSfxFQUndw5mCtWs5LO1gUlwP4CDi4iJBbVpZcqLVT29FxgGuBJGSzyOxotFG4LoO5X+M1350zmPA==", - "optional": true - }, - "@esbuild/netbsd-x64": { - "version": "0.19.11", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.19.11.tgz", - "integrity": "sha512-13jvrQZJc3P230OhU8xgwUnDeuC/9egsjTkXN49b3GcS5BKvJqZn86aGM8W9pd14Kd+u7HuFBMVtrNGhh6fHEQ==", - "optional": true - }, - "@esbuild/openbsd-x64": { - "version": "0.19.11", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.19.11.tgz", - "integrity": "sha512-ysyOGZuTp6SNKPE11INDUeFVVQFrhcNDVUgSQVDzqsqX38DjhPEPATpid04LCoUr2WXhQTEZ8ct/EgJCUDpyNw==", - "optional": true - }, - "@esbuild/sunos-x64": { - "version": "0.19.11", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.19.11.tgz", - "integrity": "sha512-Hf+Sad9nVwvtxy4DXCZQqLpgmRTQqyFyhT3bZ4F2XlJCjxGmRFF0Shwn9rzhOYRB61w9VMXUkxlBy56dk9JJiQ==", - "optional": true - }, - "@esbuild/win32-arm64": { - "version": "0.19.11", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.19.11.tgz", - "integrity": "sha512-0P58Sbi0LctOMOQbpEOvOL44Ne0sqbS0XWHMvvrg6NE5jQ1xguCSSw9jQeUk2lfrXYsKDdOe6K+oZiwKPilYPQ==", - "optional": true - }, - "@esbuild/win32-ia32": { - "version": "0.19.11", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.19.11.tgz", - "integrity": "sha512-6YOrWS+sDJDmshdBIQU+Uoyh7pQKrdykdefC1avn76ss5c+RN6gut3LZA4E2cH5xUEp5/cA0+YxRaVtRAb0xBg==", - "optional": true - }, - "@esbuild/win32-x64": { - "version": "0.19.11", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.19.11.tgz", - "integrity": "sha512-vfkhltrjCAb603XaFhqhAF4LGDi2M4OrCRrFusyQ+iTLQ/o60QQXxc9cZC/FFpihBI9N1Grn6SMKVJ4KP7Fuiw==", - "optional": true - }, - "brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "requires": { - "balanced-match": "^1.0.0" - } - }, - "commander": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz", - "integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==" - }, - "esbuild": { - "version": "0.19.11", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.11.tgz", - "integrity": "sha512-HJ96Hev2hX/6i5cDVwcqiJBBtuo9+FeIJOtZ9W1kA5M6AMJRHUZlpYZ1/SbEwtO0ioNAW8rUooVpC/WehY2SfA==", - "requires": { - "@esbuild/aix-ppc64": "0.19.11", - "@esbuild/android-arm": "0.19.11", - "@esbuild/android-arm64": "0.19.11", - "@esbuild/android-x64": "0.19.11", - "@esbuild/darwin-arm64": "0.19.11", - "@esbuild/darwin-x64": "0.19.11", - "@esbuild/freebsd-arm64": "0.19.11", - "@esbuild/freebsd-x64": "0.19.11", - "@esbuild/linux-arm": "0.19.11", - "@esbuild/linux-arm64": "0.19.11", - "@esbuild/linux-ia32": "0.19.11", - "@esbuild/linux-loong64": "0.19.11", - "@esbuild/linux-mips64el": "0.19.11", - "@esbuild/linux-ppc64": "0.19.11", - "@esbuild/linux-riscv64": "0.19.11", - "@esbuild/linux-s390x": "0.19.11", - "@esbuild/linux-x64": "0.19.11", - "@esbuild/netbsd-x64": "0.19.11", - "@esbuild/openbsd-x64": "0.19.11", - "@esbuild/sunos-x64": "0.19.11", - "@esbuild/win32-arm64": "0.19.11", - "@esbuild/win32-ia32": "0.19.11", - "@esbuild/win32-x64": "0.19.11" - } - }, - "glob": { - "version": "10.3.4", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.4.tgz", - "integrity": "sha512-6LFElP3A+i/Q8XQKEvZjkEWEOTgAIALR9AO2rwT8bgPhDd1anmqDJDZ6lLddI4ehxxxR1S5RIqKe1uapMQfYaQ==", - "requires": { - "foreground-child": "^3.1.0", - "jackspeak": "^2.0.3", - "minimatch": "^9.0.1", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", - "path-scurry": "^1.10.1" - } - }, - "minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "requires": { - "brace-expansion": "^2.0.1" - } - } - } - }, - "react-promise-suspense": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/react-promise-suspense/-/react-promise-suspense-0.3.4.tgz", - "integrity": "sha512-I42jl7L3Ze6kZaq+7zXWSunBa3b1on5yfvUW6Eo/3fFOj6dZ5Bqmcd264nJbTK/gn1HjjILAjSwnZbV4RpSaNQ==", - "requires": { - "fast-deep-equal": "^2.0.1" - }, - "dependencies": { - "fast-deep-equal": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", - "integrity": "sha512-bCK/2Z4zLidyB4ReuIsvALH6w31YfAQDmXMqMx6FyfHqvBxtjC0eRumeSu4Bs3XtXwpyIywtSTrVT99BxY1f9w==" - } - } - }, - "read-cache": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", - "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", - "peer": true, - "requires": { - "pify": "^2.3.0" - } - }, - "read-pkg": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", - "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", - "dev": true, - "requires": { - "@types/normalize-package-data": "^2.4.0", - "normalize-package-data": "^2.5.0", - "parse-json": "^5.0.0", - "type-fest": "^0.6.0" - }, - "dependencies": { - "type-fest": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", - "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", - "dev": true - } - } - }, - "read-pkg-up": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", - "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", - "dev": true, - "requires": { - "find-up": "^4.1.0", - "read-pkg": "^5.2.0", - "type-fest": "^0.8.1" - }, - "dependencies": { - "find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - } - }, - "locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "requires": { - "p-locate": "^4.1.0" - } - }, - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "requires": { - "p-limit": "^2.2.0" - } - }, - "type-fest": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", - "dev": true - } - } - }, - "readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - }, - "readdir-glob": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/readdir-glob/-/readdir-glob-1.1.3.tgz", - "integrity": "sha512-v05I2k7xN8zXvPD9N+z/uhXPaj0sUFCe2rcWZIpBsqxfP7xXFQ0tipAd/wjj1YxWyWtUS5IDJpOG82JKt2EAVA==", - "requires": { - "minimatch": "^5.1.0" - }, - "dependencies": { - "brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "requires": { - "balanced-match": "^1.0.0" - } - }, - "minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", - "requires": { - "brace-expansion": "^2.0.1" - } - } - } - }, - "readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "requires": { - "picomatch": "^2.2.1" - }, - "dependencies": { - "picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==" - } - } - }, - "redis-errors": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/redis-errors/-/redis-errors-1.2.0.tgz", - "integrity": "sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w==" - }, - "redis-parser": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-3.0.0.tgz", - "integrity": "sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A==", - "requires": { - "redis-errors": "^1.0.0" - } - }, - "reflect-metadata": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.2.2.tgz", - "integrity": "sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==" - }, - "regexp-tree": { - "version": "0.1.27", - "resolved": "https://registry.npmjs.org/regexp-tree/-/regexp-tree-0.1.27.tgz", - "integrity": "sha512-iETxpjK6YoRWJG5o6hXLwvjYAoW+FEZn9os0PD/b6AP6xQwsa/Y7lCVgIixBbUPMfhu+i2LtdeAqVTgGlQarfA==", - "dev": true - }, - "regjsparser": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.10.0.tgz", - "integrity": "sha512-qx+xQGZVsy55CH0a1hiVwHmqjLryfh7wQyF5HO07XJ9f7dQMY/gPQHhlyDkIzJKC+x2fUCpCcUODUUUFrm7SHA==", - "dev": true, - "requires": { - "jsesc": "~0.5.0" - }, - "dependencies": { - "jsesc": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", - "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==", - "dev": true - } - } - }, - "repeat-string": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==", - "dev": true - }, - "require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==" - }, - "require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "dev": true - }, - "require-in-the-middle": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/require-in-the-middle/-/require-in-the-middle-7.2.0.tgz", - "integrity": "sha512-3TLx5TGyAY6AOqLBoXmHkNql0HIf2RGbuMgCDT2WO/uGVAPJs6h7Kl+bN6TIZGd9bWhWPwnDnTHGtW8Iu77sdw==", - "requires": { - "debug": "^4.1.1", - "module-details-from-path": "^1.0.3", - "resolve": "^1.22.1" - } - }, - "resolve": { - "version": "1.22.6", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.6.tgz", - "integrity": "sha512-njhxM7mV12JfufShqGy3Rz8j11RPdLy4xi15UurGJeoHLfJpVXKdh3ueuOqbYUcDZnffr6X739JBo5LzyahEsw==", - "requires": { - "is-core-module": "^2.13.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - } - }, - "resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==" - }, - "resolve-protobuf-schema": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/resolve-protobuf-schema/-/resolve-protobuf-schema-2.1.0.tgz", - "integrity": "sha512-kI5ffTiZWmJaS/huM8wZfEMer1eRd7oJQhDuxeCLe3t7N7mX3z94CN0xPxBQxFYQTSNz9T0i+v6inKqSdK8xrQ==", - "requires": { - "protocol-buffers-schema": "^3.3.1" - } - }, - "response-time": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/response-time/-/response-time-2.3.2.tgz", - "integrity": "sha512-MUIDaDQf+CVqflfTdQ5yam+aYCkXj1PY8fjlPDQ6ppxJlmgZb864pHtA750mayywNg8tx4rS7qH9JXd/OF+3gw==", - "requires": { - "depd": "~1.1.0", - "on-headers": "~1.0.1" - }, - "dependencies": { - "depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==" - } - } - }, - "restore-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", - "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", - "requires": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" - }, - "dependencies": { - "signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" - } - } - }, - "ret": { - "version": "0.1.15", - "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", - "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", - "dev": true - }, - "retry": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", - "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", - "dev": true - }, - "reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==" - }, - "rimraf": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-6.0.1.tgz", - "integrity": "sha512-9dkvaxAsk/xNXSJzMgFqqMCuFgt2+KsOFek3TMLfo8NCPfWpBmqwyNn5Y+NX56QUYfCtsyhF3ayiboEoUmJk/A==", - "dev": true, - "requires": { - "glob": "^11.0.0", - "package-json-from-dist": "^1.0.0" - }, - "dependencies": { - "brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0" - } - }, - "glob": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-11.0.0.tgz", - "integrity": "sha512-9UiX/Bl6J2yaBbxKoEBRm4Cipxgok8kQYcOPEhScPwebu2I0HoQOuYdIO6S3hLuWoZgpDpwQZMzTFxgpkyT76g==", - "dev": true, - "requires": { - "foreground-child": "^3.1.0", - "jackspeak": "^4.0.1", - "minimatch": "^10.0.0", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^2.0.0" - } - }, - "jackspeak": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.0.1.tgz", - "integrity": "sha512-cub8rahkh0Q/bw1+GxP7aeSe29hHHn2V4m29nnDlvCdlgU+3UGxkZp7Z53jLUdpX3jdTO0nJZUDl3xvbWc2Xog==", - "dev": true, - "requires": { - "@isaacs/cliui": "^8.0.2", - "@pkgjs/parseargs": "^0.11.0" - } - }, - "lru-cache": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.0.0.tgz", - "integrity": "sha512-Qv32eSV1RSCfhY3fpPE2GNZ8jgM9X7rdAfemLWqTUxwiyIC4jJ6Sy0fZ8H+oLWevO6i4/bizg7c8d8i6bxrzbA==", - "dev": true - }, - "minimatch": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.1.tgz", - "integrity": "sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==", - "dev": true, - "requires": { - "brace-expansion": "^2.0.1" - } - }, - "path-scurry": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.0.tgz", - "integrity": "sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==", - "dev": true, - "requires": { - "lru-cache": "^11.0.0", - "minipass": "^7.1.2" - } - } - } - }, - "rollup": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.22.4.tgz", - "integrity": "sha512-vD8HJ5raRcWOyymsR6Z3o6+RzfEPCnVLMFJ6vRslO1jt4LO6dUo5Qnpg7y4RkZFM2DMe3WUirkI5c16onjrc6A==", - "dev": true, - "requires": { - "@rollup/rollup-android-arm-eabi": "4.22.4", - "@rollup/rollup-android-arm64": "4.22.4", - "@rollup/rollup-darwin-arm64": "4.22.4", - "@rollup/rollup-darwin-x64": "4.22.4", - "@rollup/rollup-linux-arm-gnueabihf": "4.22.4", - "@rollup/rollup-linux-arm-musleabihf": "4.22.4", - "@rollup/rollup-linux-arm64-gnu": "4.22.4", - "@rollup/rollup-linux-arm64-musl": "4.22.4", - "@rollup/rollup-linux-powerpc64le-gnu": "4.22.4", - "@rollup/rollup-linux-riscv64-gnu": "4.22.4", - "@rollup/rollup-linux-s390x-gnu": "4.22.4", - "@rollup/rollup-linux-x64-gnu": "4.22.4", - "@rollup/rollup-linux-x64-musl": "4.22.4", - "@rollup/rollup-win32-arm64-msvc": "4.22.4", - "@rollup/rollup-win32-ia32-msvc": "4.22.4", - "@rollup/rollup-win32-x64-msvc": "4.22.4", - "@types/estree": "1.0.5", - "fsevents": "~2.3.2" - } - }, - "run-async": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", - "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==" - }, - "run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "requires": { - "queue-microtask": "^1.2.2" - } - }, - "rxjs": { - "version": "7.8.1", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", - "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", - "requires": { - "tslib": "^2.1.0" - } - }, - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" - }, - "safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - }, - "sanitize-filename": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/sanitize-filename/-/sanitize-filename-1.6.3.tgz", - "integrity": "sha512-y/52Mcy7aw3gRm7IrcGDFx/bCk4AhRh2eI9luHOQM86nZsqwiRkkq2GekHXBBD+SmPidc8i2PqtYZl+pWJ8Oeg==", - "requires": { - "truncate-utf8-bytes": "^1.0.0" - } - }, - "scheduler": { - "version": "0.23.2", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", - "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", - "peer": true, - "requires": { - "loose-envify": "^1.1.0" - } - }, - "schema-utils": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", - "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - }, - "dependencies": { - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true, - "requires": {} - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - } - } - }, - "selderee": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/selderee/-/selderee-0.11.0.tgz", - "integrity": "sha512-5TF+l7p4+OsnP8BCCvSyZiSPc4x4//p5uPwK8TCnVPJYRmU2aYKMpOXvw8zM5a5JvuuCGN1jmsMwuU2W02ukfA==", - "requires": { - "parseley": "^0.12.0" - } - }, - "semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==" - }, - "send": { - "version": "0.19.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", - "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", - "requires": { - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "mime": "1.6.0", - "ms": "2.1.3", - "on-finished": "2.4.1", - "range-parser": "~1.2.1", - "statuses": "2.0.1" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - }, - "dependencies": { - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - } - } - }, - "encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==" - } - } - }, - "serialize-javascript": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", - "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", - "dev": true, - "requires": { - "randombytes": "^2.1.0" - } - }, - "serve-static": { - "version": "1.16.2", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", - "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", - "requires": { - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.19.0" - } - }, - "set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==" - }, - "set-function-length": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.1.tgz", - "integrity": "sha512-j4t6ccc+VsKwYHso+kElc5neZpjtq9EnRICFZtWyBsLojhmeF/ZBd/elqm22WJh/BziDe/SBiOeAt0m2mfLD0g==", - "requires": { - "define-data-property": "^1.1.2", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.3", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.1" - } - }, - "setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" - }, - "sha.js": { - "version": "2.4.11", - "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", - "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", - "requires": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "shapefile": { - "version": "0.6.6", - "resolved": "https://registry.npmjs.org/shapefile/-/shapefile-0.6.6.tgz", - "integrity": "sha512-rLGSWeK2ufzCVx05wYd+xrWnOOdSV7xNUW5/XFgx3Bc02hBkpMlrd2F1dDII7/jhWzv0MSyBFh5uJIy9hLdfuw==", - "requires": { - "array-source": "0.0", - "commander": "2", - "path-source": "0.1", - "slice-source": "0.4", - "stream-source": "0.3", - "text-encoding": "^0.6.4" - }, - "dependencies": { - "commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" - } - } - }, - "sharp": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.33.5.tgz", - "integrity": "sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw==", - "requires": { - "@img/sharp-darwin-arm64": "0.33.5", - "@img/sharp-darwin-x64": "0.33.5", - "@img/sharp-libvips-darwin-arm64": "1.0.4", - "@img/sharp-libvips-darwin-x64": "1.0.4", - "@img/sharp-libvips-linux-arm": "1.0.5", - "@img/sharp-libvips-linux-arm64": "1.0.4", - "@img/sharp-libvips-linux-s390x": "1.0.4", - "@img/sharp-libvips-linux-x64": "1.0.4", - "@img/sharp-libvips-linuxmusl-arm64": "1.0.4", - "@img/sharp-libvips-linuxmusl-x64": "1.0.4", - "@img/sharp-linux-arm": "0.33.5", - "@img/sharp-linux-arm64": "0.33.5", - "@img/sharp-linux-s390x": "0.33.5", - "@img/sharp-linux-x64": "0.33.5", - "@img/sharp-linuxmusl-arm64": "0.33.5", - "@img/sharp-linuxmusl-x64": "0.33.5", - "@img/sharp-wasm32": "0.33.5", - "@img/sharp-win32-ia32": "0.33.5", - "@img/sharp-win32-x64": "0.33.5", - "color": "^4.2.3", - "detect-libc": "^2.0.3", - "semver": "^7.6.3" - } - }, - "shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "requires": { - "shebang-regex": "^3.0.0" - } - }, - "shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==" - }, - "shimmer": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/shimmer/-/shimmer-1.2.1.tgz", - "integrity": "sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw==" - }, - "side-channel": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", - "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", - "requires": { - "call-bind": "^1.0.7", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4", - "object-inspect": "^1.13.1" - } - }, - "siginfo": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", - "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", - "dev": true - }, - "signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==" - }, - "simple-swizzle": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", - "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==", - "requires": { - "is-arrayish": "^0.3.1" - }, - "dependencies": { - "is-arrayish": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", - "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==" - } - } - }, - "sirv": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/sirv/-/sirv-3.0.0.tgz", - "integrity": "sha512-BPwJGUeDaDCHihkORDchNyyTvWFhcusy1XMmhEVTQTwGeybFbp8YEmB+njbPnth1FibULBSBVwCQni25XlCUDg==", - "requires": { - "@polka/url": "^1.0.0-next.24", - "mrmime": "^2.0.0", - "totalist": "^3.0.0" - } - }, - "slice-source": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/slice-source/-/slice-source-0.4.1.tgz", - "integrity": "sha512-YiuPbxpCj4hD9Qs06hGAz/OZhQ0eDuALN0lRWJez0eD/RevzKqGdUx1IOMUnXgpr+sXZLq3g8ERwbAH0bCb8vg==" - }, - "socket.io": { - "version": "4.7.5", - "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.7.5.tgz", - "integrity": "sha512-DmeAkF6cwM9jSfmp6Dr/5/mfMwb5Z5qRrSXLpo3Fq5SqyU8CMF15jIN4ZhfSwu35ksM1qmHZDQ/DK5XTccSTvA==", - "requires": { - "accepts": "~1.3.4", - "base64id": "~2.0.0", - "cors": "~2.8.5", - "debug": "~4.3.2", - "engine.io": "~6.5.2", - "socket.io-adapter": "~2.5.2", - "socket.io-parser": "~4.2.4" - } - }, - "socket.io-adapter": { - "version": "2.5.5", - "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.5.tgz", - "integrity": "sha512-eLDQas5dzPgOWCk9GuuJC2lBqItuhKI4uxGgo9aIV7MYbk2h9Q6uULEh8WBzThoI7l+qU9Ast9fVUmkqPP9wYg==", - "requires": { - "debug": "~4.3.4", - "ws": "~8.17.1" - } - }, - "socket.io-parser": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz", - "integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==", - "requires": { - "@socket.io/component-emitter": "~3.1.0", - "debug": "~4.3.1" - } - }, - "source-map": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", - "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", - "dev": true - }, - "source-map-js": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", - "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==" - }, - "source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } - } - }, - "spdx-correct": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", - "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", - "dev": true, - "requires": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-exceptions": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.4.0.tgz", - "integrity": "sha512-hcjppoJ68fhxA/cjbN4T8N6uCUejN8yFw69ttpqtBeCbF3u13n7mb31NB9jKwGTTWWnt9IbRA/mf1FprYS8wfw==", - "dev": true - }, - "spdx-expression-parse": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", - "dev": true, - "requires": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-license-ids": { - "version": "3.0.16", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.16.tgz", - "integrity": "sha512-eWN+LnM3GR6gPu35WxNgbGl8rmY1AEmoMDvL/QD6zYmPWgywxWqJWNdLGT+ke8dKNWrcYgYjPpG5gbTfghP8rw==", - "dev": true - }, - "split-ca": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/split-ca/-/split-ca-1.0.1.tgz", - "integrity": "sha512-Q5thBSxp5t8WPTTJQS59LrGqOZqOsrhDGDVm8azCqIBjSBd7nd9o2PM+mDulQQkh8h//4U6hFZnc/mul8t5pWQ==", - "dev": true - }, - "split2": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", - "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==" - }, - "sql-formatter": { - "version": "15.4.5", - "resolved": "https://registry.npmjs.org/sql-formatter/-/sql-formatter-15.4.5.tgz", - "integrity": "sha512-dxYn0OzEmB19/9Y+yh8bqD8kJx2S/4pOTM4QLKxQDh7K6lp1Sx9MhmiF9RUJHSVjfV72KihW5R1h6Kecy6O5qA==", - "dev": true, - "requires": { - "argparse": "^2.0.1", - "get-stdin": "=8.0.0", - "nearley": "^2.20.1" - } - }, - "ssh-remote-port-forward": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/ssh-remote-port-forward/-/ssh-remote-port-forward-1.0.4.tgz", - "integrity": "sha512-x0LV1eVDwjf1gmG7TTnfqIzf+3VPRz7vrNIjX6oYLbeCrf/PeVY6hkT68Mg+q02qXxQhrLjB0jfgvhevoCRmLQ==", - "dev": true, - "requires": { - "@types/ssh2": "^0.5.48", - "ssh2": "^1.4.0" - } - }, - "ssh2": { - "version": "1.14.0", - "resolved": "https://registry.npmjs.org/ssh2/-/ssh2-1.14.0.tgz", - "integrity": "sha512-AqzD1UCqit8tbOKoj6ztDDi1ffJZ2rV2SwlgrVVrHPkV5vWqGJOVp5pmtj18PunkPJAuKQsnInyKV+/Nb2bUnA==", - "dev": true, - "requires": { - "asn1": "^0.2.6", - "bcrypt-pbkdf": "^1.0.2", - "cpu-features": "~0.0.8", - "nan": "^2.17.0" - } - }, - "stackback": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", - "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", - "dev": true - }, - "standard-as-callback": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/standard-as-callback/-/standard-as-callback-2.1.0.tgz", - "integrity": "sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A==" - }, - "statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==" - }, - "std-env": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.7.0.tgz", - "integrity": "sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg==", - "dev": true - }, - "stream-source": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/stream-source/-/stream-source-0.3.5.tgz", - "integrity": "sha512-ZuEDP9sgjiAwUVoDModftG0JtYiLUV8K4ljYD1VyUMRWtbVf92474o4kuuul43iZ8t/hRuiDAx1dIJSvirrK/g==" - }, - "streamsearch": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", - "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==" - }, - "streamx": { - "version": "2.18.0", - "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.18.0.tgz", - "integrity": "sha512-LLUC1TWdjVdn1weXGcSxyTR3T4+acB6tVGXT95y0nGbca4t4o/ng1wKAGTljm9VicuCVLvRlqFYXYy5GwgM7sQ==", - "requires": { - "bare-events": "^2.2.0", - "fast-fifo": "^1.3.2", - "queue-tick": "^1.0.1", - "text-decoder": "^1.1.0" - } - }, - "string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "requires": { - "safe-buffer": "~5.2.0" - } - }, - "string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - }, - "string-width-cjs": { - "version": "npm:string-width@4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - }, - "strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "requires": { - "ansi-regex": "^5.0.1" - } - }, - "strip-ansi-cjs": { - "version": "npm:strip-ansi@6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "requires": { - "ansi-regex": "^5.0.1" - } - }, - "strip-indent": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", - "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", - "dev": true, - "requires": { - "min-indent": "^1.0.0" - } - }, - "strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true - }, - "styled-jsx": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.1.tgz", - "integrity": "sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw==", - "requires": { - "client-only": "0.0.1" - } - }, - "sucrase": { - "version": "3.35.0", - "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz", - "integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==", - "peer": true, - "requires": { - "@jridgewell/gen-mapping": "^0.3.2", - "commander": "^4.0.0", - "glob": "^10.3.10", - "lines-and-columns": "^1.1.6", - "mz": "^2.7.0", - "pirates": "^4.0.1", - "ts-interface-checker": "^0.1.9" - } - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "requires": { - "has-flag": "^4.0.0" - } - }, - "supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==" - }, - "swagger-ui-dist": { - "version": "5.17.14", - "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-5.17.14.tgz", - "integrity": "sha512-CVbSfaLpstV65OnSjbXfVd6Sta3q3F7Cj/yYuvHMp1P90LztOLs6PfUnKEVAeiIVQt9u2SaPwv0LiH/OyMjHRw==" - }, - "symbol-observable": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-4.0.0.tgz", - "integrity": "sha512-b19dMThMV4HVFynSAM1++gBHAbk2Tc/osgLIBZMKsyqh34jb2e8Os7T6ZW/Bt3pJFdBTd2JwAnAAEQV7rSNvcQ==", - "dev": true - }, - "synckit": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.9.1.tgz", - "integrity": "sha512-7gr8p9TQP6RAHusBOSLs46F4564ZrjV8xFmw5zCmgmhGUcw2hxsShhJ6CEiHQMgPDwAQ1fWHPM0ypc4RMAig4A==", - "dev": true, - "requires": { - "@pkgr/core": "^0.1.0", - "tslib": "^2.6.2" - } - }, - "systeminformation": { - "version": "5.22.0", - "resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.22.0.tgz", - "integrity": "sha512-oAP80ymt8ssrAzjX8k3frbL7ys6AotqC35oikG6/SG15wBw+tG9nCk4oPaXIhEaAOAZ8XngxUv3ORq2IuR3r4Q==" - }, - "tailwindcss": { - "version": "3.4.6", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.6.tgz", - "integrity": "sha512-1uRHzPB+Vzu57ocybfZ4jh5Q3SdlH7XW23J5sQoM9LhE9eIOlzxer/3XPSsycvih3rboRsvt0QCmzSrqyOYUIA==", - "peer": true, - "requires": { - "@alloc/quick-lru": "^5.2.0", - "arg": "^5.0.2", - "chokidar": "^3.5.3", - "didyoumean": "^1.2.2", - "dlv": "^1.1.3", - "fast-glob": "^3.3.0", - "glob-parent": "^6.0.2", - "is-glob": "^4.0.3", - "jiti": "^1.21.0", - "lilconfig": "^2.1.0", - "micromatch": "^4.0.5", - "normalize-path": "^3.0.0", - "object-hash": "^3.0.0", - "picocolors": "^1.0.0", - "postcss": "^8.4.23", - "postcss-import": "^15.1.0", - "postcss-js": "^4.0.1", - "postcss-load-config": "^4.0.1", - "postcss-nested": "^6.0.1", - "postcss-selector-parser": "^6.0.11", - "resolve": "^1.22.2", - "sucrase": "^3.32.0" - }, - "dependencies": { - "arg": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", - "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", - "peer": true - }, - "glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "peer": true, - "requires": { - "is-glob": "^4.0.3" - } - } - } - }, - "tailwindcss-email-variants": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/tailwindcss-email-variants/-/tailwindcss-email-variants-3.0.1.tgz", - "integrity": "sha512-bRk4R2jnfaW7BBaL2kDgOdBl0SpVP/JPDE/yCkZb1n3YrPK9ZQyQGZoVX3OX06GxjMOrNO3wZACVdHJce7dm8w==", - "requires": {} - }, - "tailwindcss-mso": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/tailwindcss-mso/-/tailwindcss-mso-1.4.3.tgz", - "integrity": "sha512-8YfZ4xnIComDrhoSr8FUwm7EGz1FkxsZy07Fs4Jm/JxHrFiubdiZjyxLuHMc3S8o02+U4fjRGHPOzoVXRus10A==", - "requires": {} - }, - "tailwindcss-preset-email": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/tailwindcss-preset-email/-/tailwindcss-preset-email-1.3.2.tgz", - "integrity": "sha512-kSPNZM5+tSi+uhCb4rk1XF9Q6zp8lhoNLCa3GQqe6gKmfI/nTqY8Y+5/DYNpwqhmUPCSHULlyI/LUCaF/q8sLg==", - "requires": { - "tailwindcss-email-variants": "^3.0.0", - "tailwindcss-mso": "^1.4.3" - } - }, - "tapable": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", - "dev": true - }, - "tar": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", - "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", - "requires": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^5.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" - }, - "dependencies": { - "minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==" - }, - "mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==" - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - } - } - }, - "tar-fs": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.0.6.tgz", - "integrity": "sha512-iokBDQQkUyeXhgPYaZxmczGPhnhXZ0CmrqI+MOb/WFGS9DW5wnfrLgtjUJBvz50vQ3qfRwJ62QVoCFu8mPVu5w==", - "dev": true, - "requires": { - "bare-fs": "^2.1.1", - "bare-path": "^2.1.0", - "pump": "^3.0.0", - "tar-stream": "^3.1.5" - } - }, - "tar-stream": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-3.1.6.tgz", - "integrity": "sha512-B/UyjYwPpMBv+PaFSWAmtYjwdrlEaZQEhMIBFNC5oEG8lpiW8XjcSdmEaClj28ArfKScKHs2nshz3k2le6crsg==", - "requires": { - "b4a": "^1.6.4", - "fast-fifo": "^1.2.0", - "streamx": "^2.15.0" - } - }, - "terser": { - "version": "5.27.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.27.0.tgz", - "integrity": "sha512-bi1HRwVRskAjheeYl291n3JC4GgO/Ty4z1nVs5AAsmonJulGxpSektecnNedrwK9C7vpvVtcX3cw00VSLt7U2A==", - "dev": true, - "requires": { - "@jridgewell/source-map": "^0.3.3", - "acorn": "^8.8.2", - "commander": "^2.20.0", - "source-map-support": "~0.5.20" - }, - "dependencies": { - "commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true - } - } - }, - "terser-webpack-plugin": { - "version": "5.3.10", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz", - "integrity": "sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==", - "dev": true, - "requires": { - "@jridgewell/trace-mapping": "^0.3.20", - "jest-worker": "^27.4.5", - "schema-utils": "^3.1.1", - "serialize-javascript": "^6.0.1", - "terser": "^5.26.0" - }, - "dependencies": { - "jest-worker": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", - "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", - "dev": true, - "requires": { - "@types/node": "*", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - } - }, - "supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "test-exclude": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-7.0.1.tgz", - "integrity": "sha512-pFYqmTw68LXVjeWJMST4+borgQP2AyMNbg1BpZh9LbyhUeNkeaPF9gzfPGUAnSMV3qPYdWUwDIjjCLiSDOl7vg==", - "dev": true, - "requires": { - "@istanbuljs/schema": "^0.1.2", - "glob": "^10.4.1", - "minimatch": "^9.0.4" - }, - "dependencies": { - "brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0" - } - }, - "minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dev": true, - "requires": { - "brace-expansion": "^2.0.1" - } - } - } - }, - "testcontainers": { - "version": "10.13.2", - "resolved": "https://registry.npmjs.org/testcontainers/-/testcontainers-10.13.2.tgz", - "integrity": "sha512-LfEll+AG/1Ks3n4+IA5lpyBHLiYh/hSfI4+ERa6urwfQscbDU+M2iW1qPQrHQi+xJXQRYy4whyK1IEHdmxWa3Q==", - "dev": true, - "requires": { - "@balena/dockerignore": "^1.0.2", - "@types/dockerode": "^3.3.29", - "archiver": "^7.0.1", - "async-lock": "^1.4.1", - "byline": "^5.0.0", - "debug": "^4.3.5", - "docker-compose": "^0.24.8", - "dockerode": "^3.3.5", - "get-port": "^5.1.1", - "proper-lockfile": "^4.1.2", - "properties-reader": "^2.3.0", - "ssh-remote-port-forward": "^1.0.4", - "tar-fs": "^3.0.6", - "tmp": "^0.2.3", - "undici": "^5.28.4" - }, - "dependencies": { - "tmp": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.3.tgz", - "integrity": "sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==", - "dev": true - } - } - }, - "text-decoder": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.1.0.tgz", - "integrity": "sha512-TmLJNj6UgX8xcUZo4UDStGQtDiTzF7BzWlzn9g7UWrjkpHr5uJTK1ld16wZ3LXb2vb6jH8qU89dW5whuMdXYdw==", - "requires": { - "b4a": "^1.6.4" - } - }, - "text-encoding": { - "version": "0.6.4", - "resolved": "https://registry.npmjs.org/text-encoding/-/text-encoding-0.6.4.tgz", - "integrity": "sha512-hJnc6Qg3dWoOMkqP53F0dzRIgtmsAge09kxUIqGrEUS4qr5rWLckGYaQAVr+opBrIMRErGgy6f5aPnyPpyGRfg==" - }, - "text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true - }, - "thenify": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", - "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", - "requires": { - "any-promise": "^1.0.0" - } - }, - "thenify-all": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", - "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", - "requires": { - "thenify": ">= 3.1.0 < 4" - } - }, - "through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==" - }, - "thumbhash": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/thumbhash/-/thumbhash-0.1.1.tgz", - "integrity": "sha512-kH5pKeIIBPQXAOni2AiY/Cu/NKdkFREdpH+TLdM0g6WA7RriCv0kPLgP731ady67MhTAqrVG/4mnEeibVuCJcg==" - }, - "tinybench": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", - "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", - "dev": true - }, - "tinyexec": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.0.tgz", - "integrity": "sha512-tVGE0mVJPGb0chKhqmsoosjsS+qUnJVGJpZgsHYQcGoPlG3B51R3PouqTgEGH2Dc9jjFyOqOpix6ZHNMXp1FZg==", - "dev": true - }, - "tinypool": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.0.1.tgz", - "integrity": "sha512-URZYihUbRPcGv95En+sz6MfghfIc2OJ1sv/RmhWZLouPY0/8Vo80viwPvg3dlaS9fuq7fQMEfgRRK7BBZThBEA==", - "dev": true - }, - "tinyrainbow": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-1.2.0.tgz", - "integrity": "sha512-weEDEq7Z5eTHPDh4xjX789+fHfF+P8boiFB+0vbWzpbnbsEr/GRaohi/uMKxg8RZMXnl1ItAi/IUHWMsjDV7kQ==", - "dev": true - }, - "tinyspy": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-3.0.2.tgz", - "integrity": "sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==", - "dev": true - }, - "tmp": { - "version": "0.0.33", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", - "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", - "requires": { - "os-tmpdir": "~1.0.2" - } - }, - "to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==" - }, - "to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "requires": { - "is-number": "^7.0.0" - } - }, - "toidentifier": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==" - }, - "totalist": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz", - "integrity": "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==" - }, - "tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" - }, - "tree-kill": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", - "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", - "dev": true - }, - "truncate-utf8-bytes": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/truncate-utf8-bytes/-/truncate-utf8-bytes-1.0.2.tgz", - "integrity": "sha512-95Pu1QXQvruGEhv62XCMO3Mm90GscOCClvrIUwCM0PYOXK3kaF3l3sIHxx71ThJfcbM2O5Au6SO3AWCSEfW4mQ==", - "requires": { - "utf8-byte-length": "^1.0.1" - } - }, - "ts-api-utils": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", - "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", - "dev": true, - "requires": {} - }, - "ts-interface-checker": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", - "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", - "peer": true - }, - "ts-node": { - "version": "10.9.2", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", - "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", - "optional": true, - "peer": true, - "requires": { - "@cspotcode/source-map-support": "^0.8.0", - "@tsconfig/node10": "^1.0.7", - "@tsconfig/node12": "^1.0.7", - "@tsconfig/node14": "^1.0.0", - "@tsconfig/node16": "^1.0.2", - "acorn": "^8.4.1", - "acorn-walk": "^8.1.1", - "arg": "^4.1.0", - "create-require": "^1.1.0", - "diff": "^4.0.1", - "make-error": "^1.1.1", - "v8-compile-cache-lib": "^3.0.1", - "yn": "3.1.1" - } - }, - "tsconfck": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/tsconfck/-/tsconfck-3.1.1.tgz", - "integrity": "sha512-00eoI6WY57SvZEVjm13stEVE90VkEdJAFGgpFLTsZbJyW/LwFQ7uQxJHWpZ2hzSWgCPKc9AnBnNP+0X7o3hAmQ==", - "dev": true, - "requires": {} - }, - "tsconfig-paths": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz", - "integrity": "sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==", - "dev": true, - "requires": { - "json5": "^2.2.2", - "minimist": "^1.2.6", - "strip-bom": "^3.0.0" - }, - "dependencies": { - "strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", - "dev": true - } - } - }, - "tsconfig-paths-webpack-plugin": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/tsconfig-paths-webpack-plugin/-/tsconfig-paths-webpack-plugin-4.1.0.tgz", - "integrity": "sha512-xWFISjviPydmtmgeUAuXp4N1fky+VCtfhOkDUFIv5ea7p4wuTomI4QTrXvFBX2S4jZsmyTSrStQl+E+4w+RzxA==", - "dev": true, - "requires": { - "chalk": "^4.1.0", - "enhanced-resolve": "^5.7.0", - "tsconfig-paths": "^4.1.2" - } - }, - "tslib": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz", - "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==" - }, - "tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==", - "dev": true - }, - "type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "requires": { - "prelude-ls": "^1.2.1" - } - }, - "type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "requires": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - } - }, - "typedarray": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==" - }, - "typeorm": { - "version": "0.3.20", - "resolved": "https://registry.npmjs.org/typeorm/-/typeorm-0.3.20.tgz", - "integrity": "sha512-sJ0T08dV5eoZroaq9uPKBoNcGslHBR4E4y+EBHs//SiGbblGe7IeduP/IH4ddCcj0qp3PHwDwGnuvqEAnKlq/Q==", - "requires": { - "@sqltools/formatter": "^1.2.5", - "app-root-path": "^3.1.0", - "buffer": "^6.0.3", - "chalk": "^4.1.2", - "cli-highlight": "^2.1.11", - "dayjs": "^1.11.9", - "debug": "^4.3.4", - "dotenv": "^16.0.3", - "glob": "^10.3.10", - "mkdirp": "^2.1.3", - "reflect-metadata": "^0.2.1", - "sha.js": "^2.4.11", - "tslib": "^2.5.0", - "uuid": "^9.0.0", - "yargs": "^17.6.2" - }, - "dependencies": { - "buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "requires": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" - } - }, - "cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - } - }, - "mkdirp": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-2.1.6.tgz", - "integrity": "sha512-+hEnITedc8LAtIP9u3HJDFIdcLV2vXP33sqLLIzkv1Db1zO/1OxbvYf0Y1OC/S/Qo5dxHXepofhmxL02PsKe+A==" - }, - "wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - } - }, - "yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "requires": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - } - } - } - }, - "typescript": { - "version": "5.6.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz", - "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==", - "devOptional": true - }, - "ua-parser-js": { - "version": "1.0.39", - "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-1.0.39.tgz", - "integrity": "sha512-k24RCVWlEcjkdOxYmVJgeD/0a1TiSpqLg+ZalVGV9lsnr4yqu0w7tX/x2xX6G4zpkgQnRf89lxuZ1wsbjXM8lw==" - }, - "uglify-js": { - "version": "3.17.4", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.4.tgz", - "integrity": "sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==", - "optional": true - }, - "uid": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/uid/-/uid-2.0.2.tgz", - "integrity": "sha512-u3xV3X7uzvi5b1MncmZo3i2Aw222Zk1keqLA1YkHldREkAhAqi65wuPfe7lHx8H/Wzy+8CE7S7uS3jekIM5s8g==", - "requires": { - "@lukeed/csprng": "^1.0.0" - } - }, - "uid2": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/uid2/-/uid2-1.0.0.tgz", - "integrity": "sha512-+I6aJUv63YAcY9n4mQreLUt0d4lvwkkopDNmpomkAUz0fAkEMV9pRWxN0EjhW1YfRhcuyHg2v3mwddCDW1+LFQ==" - }, - "undici": { - "version": "5.28.4", - "resolved": "https://registry.npmjs.org/undici/-/undici-5.28.4.tgz", - "integrity": "sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g==", - "dev": true, - "requires": { - "@fastify/busboy": "^2.0.0" - } - }, - "undici-types": { - "version": "6.19.8", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", - "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==" - }, - "universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", - "dev": true - }, - "unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==" - }, - "unplugin": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/unplugin/-/unplugin-1.11.0.tgz", - "integrity": "sha512-3r7VWZ/webh0SGgJScpWl2/MRCZK5d3ZYFcNaeci/GQ7Teop7zf0Nl2pUuz7G21BwPd9pcUPOC5KmJ2L3WgC5g==", - "dev": true, - "requires": { - "acorn": "^8.11.3", - "chokidar": "^3.6.0", - "webpack-sources": "^3.2.3", - "webpack-virtual-modules": "^0.6.1" - } - }, - "unplugin-swc": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/unplugin-swc/-/unplugin-swc-1.5.1.tgz", - "integrity": "sha512-/ZLrPNjChhGx3Z95pxJ4tQgfI6rWqukgYHKflrNB4zAV1izOQuDhkTn55JWeivpBxDCoK7M/TStb2aS/14PS/g==", - "dev": true, - "requires": { - "@rollup/pluginutils": "^5.1.0", - "load-tsconfig": "^0.2.5", - "unplugin": "^1.11.0" - } - }, - "update-browserslist-db": { - "version": "1.0.13", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", - "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", - "requires": { - "escalade": "^3.1.1", - "picocolors": "^1.0.0" - } - }, - "uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, - "requires": { - "punycode": "^2.1.0" - } - }, - "utf8-byte-length": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/utf8-byte-length/-/utf8-byte-length-1.0.4.tgz", - "integrity": "sha512-4+wkEYLBbWxqTahEsWrhxepcoVOJ+1z5PGIjPZxRkytcdSUaNjIjBM7Xn8E+pdSuV7SzvWovBFA54FO0JSoqhA==" - }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" - }, - "utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==" - }, - "utimes": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/utimes/-/utimes-5.2.1.tgz", - "integrity": "sha512-6S5mCapmzcxetOD/2UEjL0GF5e4+gB07Dh8qs63xylw5ay4XuyW6iQs70FOJo/puf10LCkvhp4jYMQSDUBYEFg==", - "dev": true, - "requires": { - "@mapbox/node-pre-gyp": "^1.0.11", - "node-addon-api": "^4.3.0" - }, - "dependencies": { - "node-addon-api": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-4.3.0.tgz", - "integrity": "sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ==", - "dev": true - } - } - }, - "uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==" - }, - "v8-compile-cache-lib": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", - "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", - "optional": true, - "peer": true - }, - "validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "dev": true, - "requires": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "validator": { - "version": "13.12.0", - "resolved": "https://registry.npmjs.org/validator/-/validator-13.12.0.tgz", - "integrity": "sha512-c1Q0mCiPlgdTVVVIJIrBuxNicYE+t/7oKeI9MWLj3fh/uq2Pxh/3eeWbVZ4OcGW1TUf53At0njHw5SMdA3tmMg==" - }, - "vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==" - }, - "vite": { - "version": "5.4.7", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.7.tgz", - "integrity": "sha512-5l2zxqMEPVENgvzTuBpHer2awaetimj2BGkhBPdnwKbPNOlHsODU+oiazEZzLK7KhAnOrO+XGYJYn4ZlUhDtDQ==", - "dev": true, - "requires": { - "esbuild": "^0.21.3", - "fsevents": "~2.3.3", - "postcss": "^8.4.43", - "rollup": "^4.20.0" - } - }, - "vite-node": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-2.1.3.tgz", - "integrity": "sha512-I1JadzO+xYX887S39Do+paRePCKoiDrWRRjp9kkG5he0t7RXNvPAJPCQSJqbGN4uCrFFeS3Kj3sLqY8NMYBEdA==", - "dev": true, - "requires": { - "cac": "^6.7.14", - "debug": "^4.3.6", - "pathe": "^1.1.2", - "vite": "^5.0.0" + "engines": { + "node": "^10 || ^12 || >=14" } }, - "vite-tsconfig-paths": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/vite-tsconfig-paths/-/vite-tsconfig-paths-5.0.1.tgz", - "integrity": "sha512-yqwv+LstU7NwPeNqajZzLEBVpUFU6Dugtb2P84FXuvaoYA+/70l9MHE+GYfYAycVyPSDYZ7mjOFuYBRqlEpTig==", + "node_modules/vitest": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-2.1.8.tgz", + "integrity": "sha512-1vBKTZskHw/aosXqQUlVWWlGUxSJR8YtiyZDJAFeW2kPAeX6S3Sool0mjspO+kXLuxVWlEDDowBAeqeAQefqLQ==", "dev": true, - "requires": { - "debug": "^4.1.1", - "globrex": "^0.1.2", - "tsconfck": "^3.0.3" - } - }, - "vitest": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-2.1.3.tgz", - "integrity": "sha512-Zrxbg/WiIvUP2uEzelDNTXmEMJXuzJ1kCpbDvaKByFA9MNeO95V+7r/3ti0qzJzrxdyuUw5VduN7k+D3VmVOSA==", - "dev": true, - "requires": { - "@vitest/expect": "2.1.3", - "@vitest/mocker": "2.1.3", - "@vitest/pretty-format": "^2.1.3", - "@vitest/runner": "2.1.3", - "@vitest/snapshot": "2.1.3", - "@vitest/spy": "2.1.3", - "@vitest/utils": "2.1.3", - "chai": "^5.1.1", - "debug": "^4.3.6", - "magic-string": "^0.30.11", + "license": "MIT", + "dependencies": { + "@vitest/expect": "2.1.8", + "@vitest/mocker": "2.1.8", + "@vitest/pretty-format": "^2.1.8", + "@vitest/runner": "2.1.8", + "@vitest/snapshot": "2.1.8", + "@vitest/spy": "2.1.8", + "@vitest/utils": "2.1.8", + "chai": "^5.1.2", + "debug": "^4.3.7", + "expect-type": "^1.1.0", + "magic-string": "^0.30.12", "pathe": "^1.1.2", - "std-env": "^3.7.0", + "std-env": "^3.8.0", "tinybench": "^2.9.0", - "tinyexec": "^0.3.0", - "tinypool": "^1.0.0", + "tinyexec": "^0.3.1", + "tinypool": "^1.0.1", "tinyrainbow": "^1.2.0", "vite": "^5.0.0", - "vite-node": "2.1.3", + "vite-node": "2.1.8", "why-is-node-running": "^2.3.0" }, - "dependencies": { - "magic-string": { - "version": "0.30.12", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.12.tgz", - "integrity": "sha512-Ea8I3sQMVXr8JhN4z+H/d8zwo+tYDgHE9+5G4Wnrwhs0gaK9fXTKx0Tw5Xwsd/bCPTTZNRAdpyzvoeORe9LYpw==", - "dev": true, - "requires": { - "@jridgewell/sourcemap-codec": "^1.5.0" - } + "bin": { + "vitest": "vitest.mjs" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@edge-runtime/vm": "*", + "@types/node": "^18.0.0 || >=20.0.0", + "@vitest/browser": "2.1.8", + "@vitest/ui": "2.1.8", + "happy-dom": "*", + "jsdom": "*" + }, + "peerDependenciesMeta": { + "@edge-runtime/vm": { + "optional": true + }, + "@types/node": { + "optional": true + }, + "@vitest/browser": { + "optional": true + }, + "@vitest/ui": { + "optional": true + }, + "happy-dom": { + "optional": true + }, + "jsdom": { + "optional": true } } }, - "watchpack": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.1.tgz", - "integrity": "sha512-8wrBCMtVhqcXP2Sup1ctSkga6uc2Bx0IIvKyT7yTFier5AXHooSI+QyQQAtTb7+E0IUCCKyTFmXqdqgum2XWGg==", + "node_modules/vitest/node_modules/magic-string": { + "version": "0.30.17", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", + "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0" + } + }, + "node_modules/watchpack": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.2.tgz", + "integrity": "sha512-TnbFSbcOCcDgjZ4piURLCbJ3nJhznVh9kw6F6iokjiFPl8ONxe9A6nMDVXDiNbrSfLILs6vB07F7wLBrwPYzJw==", + "dev": true, + "license": "MIT", + "dependencies": { "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.1.2" + }, + "engines": { + "node": ">=10.13.0" } }, - "wcwidth": { + "node_modules/wcwidth": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", - "requires": { + "license": "MIT", + "dependencies": { "defaults": "^1.0.3" } }, - "webidl-conversions": { + "node_modules/webidl-conversions": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" - }, - "webpack": { - "version": "5.94.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.94.0.tgz", - "integrity": "sha512-KcsGn50VT+06JH/iunZJedYGUJS5FGjow8wb9c0v5n1Om8O1g4L6LjtfxwlXIATopoQu+vOXXa7gYisWxCoPyg==", - "dev": true, - "requires": { - "@types/estree": "^1.0.5", - "@webassemblyjs/ast": "^1.12.1", - "@webassemblyjs/wasm-edit": "^1.12.1", - "@webassemblyjs/wasm-parser": "^1.12.1", - "acorn": "^8.7.1", - "acorn-import-attributes": "^1.9.5", - "browserslist": "^4.21.10", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "license": "BSD-2-Clause" + }, + "node_modules/webpack": { + "version": "5.97.1", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.97.1.tgz", + "integrity": "sha512-EksG6gFY3L1eFMROS/7Wzgrii5mBAFe4rIr3r2BTfo7bcc+DWwFZ4OJ/miOuHJO/A85HwyI4eQ0F6IKXesO7Fg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/eslint-scope": "^3.7.7", + "@types/estree": "^1.0.6", + "@webassemblyjs/ast": "^1.14.1", + "@webassemblyjs/wasm-edit": "^1.14.1", + "@webassemblyjs/wasm-parser": "^1.14.1", + "acorn": "^8.14.0", + "browserslist": "^4.24.0", "chrome-trace-event": "^1.0.2", "enhanced-resolve": "^5.17.1", "es-module-lexer": "^1.2.1", @@ -25129,204 +15624,287 @@ "watchpack": "^2.4.1", "webpack-sources": "^3.2.3" }, - "dependencies": { - "eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - } - }, - "estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true + "bin": { + "webpack": "bin/webpack.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependenciesMeta": { + "webpack-cli": { + "optional": true } } }, - "webpack-node-externals": { + "node_modules/webpack-node-externals": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/webpack-node-externals/-/webpack-node-externals-3.0.0.tgz", "integrity": "sha512-LnL6Z3GGDPht/AigwRh2dvL9PQPFQ8skEpVrWZXLWBYmqcaojHNN0onvHzie6rq7EWKrrBfPYqNEzTJgiwEQDQ==", - "dev": true + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } }, - "webpack-sources": { + "node_modules/webpack-sources": { "version": "3.2.3", "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", - "dev": true + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.13.0" + } }, - "webpack-virtual-modules": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/webpack-virtual-modules/-/webpack-virtual-modules-0.6.1.tgz", - "integrity": "sha512-poXpCylU7ExuvZK8z+On3kX+S8o/2dQ/SVYueKA0D4WEMXROXgY8Ez50/bQEUmvoSMMrWcrJqCHuhAbsiwg7Dg==", - "dev": true + "node_modules/webpack-virtual-modules": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/webpack-virtual-modules/-/webpack-virtual-modules-0.6.2.tgz", + "integrity": "sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/webpack/node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/webpack/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } }, - "whatwg-url": { + "node_modules/whatwg-url": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "requires": { + "license": "MIT", + "dependencies": { "tr46": "~0.0.3", "webidl-conversions": "^3.0.0" } }, - "which": { + "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "requires": { + "license": "ISC", + "dependencies": { "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" } }, - "why-is-node-running": { + "node_modules/why-is-node-running": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "siginfo": "^2.0.0", "stackback": "0.0.2" + }, + "bin": { + "why-is-node-running": "cli.js" + }, + "engines": { + "node": ">=8" } }, - "wide-align": { + "node_modules/wide-align": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", - "requires": { + "license": "ISC", + "dependencies": { "string-width": "^1.0.2 || 2 || 3 || 4" } }, - "wordwrap": { + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wordwrap": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==" + "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", + "license": "MIT" }, - "wrap-ansi": { + "node_modules/wrap-ansi": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", - "requires": { + "license": "MIT", + "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" } }, - "wrap-ansi-cjs": { - "version": "npm:wrap-ansi@7.0.0", + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "requires": { + "license": "MIT", + "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "wrappy": { + "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "license": "ISC" }, - "ws": { + "node_modules/ws": { "version": "8.17.1", "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", - "requires": {} + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } }, - "xtend": { + "node_modules/xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "license": "MIT", + "engines": { + "node": ">=0.4" + } }, - "y18n": { + "node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==" + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "license": "ISC", + "engines": { + "node": ">=10" + } }, - "yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "license": "ISC" }, - "yaml": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.4.tgz", - "integrity": "sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA==" + "node_modules/yaml": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.6.1.tgz", + "integrity": "sha512-7r0XPzioN/Q9kXBro/XPnA6kznR73DHq+GXh5ON7ZozRO6aMjbmiBuKste2wslTFkC5d1dw0GooOCepZXJ2SAg==", + "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14" + } }, - "yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "requires": { - "cliui": "^7.0.2", + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "license": "MIT", + "dependencies": { + "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", - "string-width": "^4.2.0", + "string-width": "^4.2.3", "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" + "yargs-parser": "^21.1.1" }, - "dependencies": { - "yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==" - } + "engines": { + "node": ">=12" } }, - "yargs-parser": { + "node_modules/yargs-parser": { "version": "21.1.1", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==" - }, - "yn": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", - "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", - "optional": true, - "peer": true + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "license": "ISC", + "engines": { + "node": ">=12" + } }, - "yocto-queue": { + "node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, - "zip-stream": { + "node_modules/zip-stream": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-6.0.1.tgz", "integrity": "sha512-zK7YHHz4ZXpW89AHXUPbQVGKI7uvkd3hzusTdotCg1UxyaVtg0zFJSTfW/Dq5f7OBBVnq6cZIaC8Ti4hb6dtCA==", - "requires": { + "license": "MIT", + "dependencies": { "archiver-utils": "^5.0.0", "compress-commons": "^6.0.2", "readable-stream": "^4.0.0" }, - "dependencies": { - "buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "requires": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" - } - }, - "readable-stream": { - "version": "4.5.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz", - "integrity": "sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==", - "requires": { - "abort-controller": "^3.0.0", - "buffer": "^6.0.3", - "events": "^3.3.0", - "process": "^0.11.10", - "string_decoder": "^1.3.0" - } - } + "engines": { + "node": ">= 14" } } } diff --git a/server/package.json b/server/package.json index 8d3515b8daae7..074dafa5d335b 100644 --- a/server/package.json +++ b/server/package.json @@ -1,6 +1,6 @@ { "name": "immich", - "version": "1.119.1", + "version": "1.123.0", "description": "", "author": "", "private": true, @@ -41,14 +41,14 @@ "@nestjs/platform-express": "^10.2.2", "@nestjs/platform-socket.io": "^10.2.2", "@nestjs/schedule": "^4.0.0", - "@nestjs/swagger": "^7.1.8", + "@nestjs/swagger": "^8.0.0", "@nestjs/typeorm": "^10.0.0", "@nestjs/websockets": "^10.2.2", - "@opentelemetry/auto-instrumentations-node": "^0.52.0", + "@opentelemetry/auto-instrumentations-node": "^0.54.0", "@opentelemetry/context-async-hooks": "^1.24.0", - "@opentelemetry/exporter-prometheus": "^0.54.0", - "@opentelemetry/sdk-node": "^0.54.0", - "@react-email/components": "^0.0.25", + "@opentelemetry/exporter-prometheus": "^0.56.0", + "@opentelemetry/sdk-node": "^0.56.0", + "@react-email/components": "^0.0.31", "@socket.io/redis-adapter": "^8.3.0", "archiver": "^7.0.0", "async-lock": "^1.4.0", @@ -76,8 +76,8 @@ "openid-client": "^5.4.3", "pg": "^8.11.3", "picomatch": "^4.0.2", - "react": "^18.3.1", - "react-email": "^3.0.0", + "react": "^19.0.0", + "react-email": "^3.0.4", "reflect-metadata": "^0.2.0", "rxjs": "^7.8.1", "sanitize-filename": "^1.6.3", @@ -108,21 +108,21 @@ "@types/lodash": "^4.14.197", "@types/mock-fs": "^4.13.1", "@types/multer": "^1.4.7", - "@types/node": "^22.8.1", + "@types/node": "^22.10.2", "@types/nodemailer": "^6.4.14", "@types/picomatch": "^3.0.0", "@types/pngjs": "^6.0.5", - "@types/react": "^18.3.4", + "@types/react": "^19.0.0", "@types/semver": "^7.5.8", "@types/supertest": "^6.0.0", "@types/ua-parser-js": "^0.7.36", - "@typescript-eslint/eslint-plugin": "^8.0.0", - "@typescript-eslint/parser": "^8.0.0", + "@typescript-eslint/eslint-plugin": "^8.15.0", + "@typescript-eslint/parser": "^8.15.0", "@vitest/coverage-v8": "^2.0.5", - "eslint": "^9.0.0", + "eslint": "^9.14.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-prettier": "^5.1.3", - "eslint-plugin-unicorn": "^55.0.0", + "eslint-plugin-unicorn": "^56.0.1", "globals": "^15.9.0", "mock-fs": "^5.2.0", "pngjs": "^7.0.0", @@ -139,6 +139,6 @@ "vitest": "^2.0.5" }, "volta": { - "node": "22.11.0" + "node": "22.12.0" } } diff --git a/server/src/app.module.ts b/server/src/app.module.ts index 8ed9d5f6ed613..da8fa55606099 100644 --- a/server/src/app.module.ts +++ b/server/src/app.module.ts @@ -6,10 +6,12 @@ import { TypeOrmModule } from '@nestjs/typeorm'; import { ClsModule } from 'nestjs-cls'; import { OpenTelemetryModule } from 'nestjs-otel'; import { commands } from 'src/commands'; +import { IWorker } from 'src/constants'; import { controllers } from 'src/controllers'; import { entities } from 'src/entities'; import { ImmichWorker } from 'src/enum'; import { IEventRepository } from 'src/interfaces/event.interface'; +import { IJobRepository } from 'src/interfaces/job.interface'; import { ILoggerRepository } from 'src/interfaces/logger.interface'; import { ITelemetryRepository } from 'src/interfaces/telemetry.interface'; import { AuthGuard } from 'src/middleware/auth.guard'; @@ -56,29 +58,31 @@ const imports = [ TypeOrmModule.forFeature(entities), ]; -abstract class BaseModule implements OnModuleInit, OnModuleDestroy { - private get worker() { - return this.getWorker(); - } - +class BaseModule implements OnModuleInit, OnModuleDestroy { constructor( + @Inject(IWorker) private worker: ImmichWorker, @Inject(ILoggerRepository) logger: ILoggerRepository, @Inject(IEventRepository) private eventRepository: IEventRepository, + @Inject(IJobRepository) private jobRepository: IJobRepository, @Inject(ITelemetryRepository) private telemetryRepository: ITelemetryRepository, ) { logger.setAppName(this.worker); } - abstract getWorker(): ImmichWorker; - async onModuleInit() { this.telemetryRepository.setup({ repositories: repositories.map(({ useClass }) => useClass) }); + + this.jobRepository.setup({ services }); + if (this.worker === ImmichWorker.MICROSERVICES) { + this.jobRepository.startWorkers(); + } + this.eventRepository.setup({ services }); - await this.eventRepository.emit('app.bootstrap', this.worker); + await this.eventRepository.emit('app.bootstrap'); } async onModuleDestroy() { - await this.eventRepository.emit('app.shutdown', this.worker); + await this.eventRepository.emit('app.shutdown'); await teardownTelemetry(); } } @@ -86,23 +90,15 @@ abstract class BaseModule implements OnModuleInit, OnModuleDestroy { @Module({ imports: [...imports, ScheduleModule.forRoot()], controllers: [...controllers], - providers: [...common, ...middleware], + providers: [...common, ...middleware, { provide: IWorker, useValue: ImmichWorker.API }], }) -export class ApiModule extends BaseModule { - getWorker() { - return ImmichWorker.API; - } -} +export class ApiModule extends BaseModule {} @Module({ imports: [...imports], - providers: [...common, SchedulerRegistry], + providers: [...common, { provide: IWorker, useValue: ImmichWorker.MICROSERVICES }, SchedulerRegistry], }) -export class MicroservicesModule extends BaseModule { - getWorker() { - return ImmichWorker.MICROSERVICES; - } -} +export class MicroservicesModule extends BaseModule {} @Module({ imports: [...imports], diff --git a/server/src/bin/healthcheck.ts b/server/src/bin/healthcheck.ts deleted file mode 100644 index 6de58c2002fef..0000000000000 --- a/server/src/bin/healthcheck.ts +++ /dev/null @@ -1,35 +0,0 @@ -#!/usr/bin/env node -import { ImmichWorker } from 'src/enum'; -import { ConfigRepository } from 'src/repositories/config.repository'; - -const main = async () => { - const { workers, port } = new ConfigRepository().getEnv(); - if (!workers.includes(ImmichWorker.API)) { - process.exit(); - } - - const controller = new AbortController(); - const timeout = setTimeout(() => controller.abort(), 2000); - try { - const response = await fetch(`http://localhost:${port}/api/server/ping`, { - signal: controller.signal, - }); - - if (response.ok) { - const body = await response.json(); - if (body.res === 'pong') { - process.exit(); - } - } - } catch (error) { - if (error instanceof DOMException === false) { - console.error(error); - } - } finally { - clearTimeout(timeout); - } - - process.exit(1); -}; - -void main(); diff --git a/server/src/config.ts b/server/src/config.ts index 7a7a7b71acfa2..26589742003e7 100644 --- a/server/src/config.ts +++ b/server/src/config.ts @@ -36,7 +36,6 @@ export interface SystemConfig { bframes: number; refs: number; gopSize: number; - npl: number; temporalAQ: boolean; cqMode: CQMode; twoPass: boolean; @@ -53,7 +52,7 @@ export interface SystemConfig { }; machineLearning: { enabled: boolean; - url: string; + urls: string[]; clip: { enabled: boolean; modelName: string; @@ -147,9 +146,17 @@ export interface SystemConfig { }; }; }; + templates: { + email: { + welcomeTemplate: string; + albumInviteTemplate: string; + albumUpdateTemplate: string; + }; + }; server: { externalDomain: string; loginPageMessage: string; + publicUsers: boolean; }; user: { deleteDelay: number; @@ -178,7 +185,6 @@ export const defaults = Object.freeze({ bframes: -1, refs: 0, gopSize: 0, - npl: 0, temporalAQ: false, cqMode: CQMode.AUTO, twoPass: false, @@ -207,7 +213,7 @@ export const defaults = Object.freeze({ }, machineLearning: { enabled: process.env.IMMICH_MACHINE_LEARNING_ENABLED !== 'false', - url: process.env.IMMICH_MACHINE_LEARNING_URL || 'http://immich-machine-learning:3003', + urls: [process.env.IMMICH_MACHINE_LEARNING_URL || 'http://immich-machine-learning:3003'], clip: { enabled: true, modelName: 'ViT-B-32__openai', @@ -298,6 +304,7 @@ export const defaults = Object.freeze({ server: { externalDomain: '', loginPageMessage: '', + publicUsers: true, }, notifications: { smtp: { @@ -313,6 +320,13 @@ export const defaults = Object.freeze({ }, }, }, + templates: { + email: { + welcomeTemplate: '', + albumInviteTemplate: '', + albumUpdateTemplate: '', + }, + }, user: { deleteDelay: 7, }, diff --git a/server/src/constants.ts b/server/src/constants.ts index e99970723a42f..fc2442130e002 100644 --- a/server/src/constants.ts +++ b/server/src/constants.ts @@ -1,6 +1,7 @@ import { Duration } from 'luxon'; import { readFileSync } from 'node:fs'; import { SemVer } from 'semver'; +import { ExifOrientation } from 'src/enum'; export const POSTGRES_VERSION_RANGE = '>=14.0.0'; export const VECTORS_VERSION_RANGE = '>=0.2 <0.4'; @@ -13,6 +14,8 @@ export const ADDED_IN_PREFIX = 'This property was added in '; export const SALT_ROUNDS = 10; +export const IWorker = 'IWorker'; + const { version } = JSON.parse(readFileSync('./package.json', 'utf8')); export const serverVersion = new SemVer(version); @@ -79,3 +82,19 @@ export const CLIP_MODEL_INFO: Record = { 'nllb-clip-large-siglip__mrl': { dimSize: 1152 }, 'nllb-clip-large-siglip__v1': { dimSize: 1152 }, }; + +type SharpRotationData = { + angle?: number; + flip?: boolean; + flop?: boolean; +}; +export const ORIENTATION_TO_SHARP_ROTATION: Record = { + [ExifOrientation.Horizontal]: { angle: 0 }, + [ExifOrientation.MirrorHorizontal]: { angle: 0, flop: true }, + [ExifOrientation.Rotate180]: { angle: 180 }, + [ExifOrientation.MirrorVertical]: { angle: 180, flop: true }, + [ExifOrientation.MirrorHorizontalRotate270CW]: { angle: 270, flip: true }, + [ExifOrientation.Rotate90CW]: { angle: 90 }, + [ExifOrientation.MirrorHorizontalRotate90CW]: { angle: 90, flip: true }, + [ExifOrientation.Rotate270CW]: { angle: 270 }, +} as const; diff --git a/server/src/controllers/notification.controller.ts b/server/src/controllers/notification.controller.ts index 3dd72dd73a91d..27034fd63a873 100644 --- a/server/src/controllers/notification.controller.ts +++ b/server/src/controllers/notification.controller.ts @@ -1,8 +1,9 @@ -import { Body, Controller, HttpCode, HttpStatus, Post } from '@nestjs/common'; +import { Body, Controller, HttpCode, HttpStatus, Param, Post } from '@nestjs/common'; import { ApiTags } from '@nestjs/swagger'; import { AuthDto } from 'src/dtos/auth.dto'; -import { TestEmailResponseDto } from 'src/dtos/notification.dto'; +import { TemplateDto, TemplateResponseDto, TestEmailResponseDto } from 'src/dtos/notification.dto'; import { SystemConfigSmtpDto } from 'src/dtos/system-config.dto'; +import { EmailTemplate } from 'src/interfaces/notification.interface'; import { Auth, Authenticated } from 'src/middleware/auth.guard'; import { NotificationService } from 'src/services/notification.service'; @@ -17,4 +18,15 @@ export class NotificationController { sendTestEmail(@Auth() auth: AuthDto, @Body() dto: SystemConfigSmtpDto): Promise { return this.service.sendTestEmail(auth.user.id, dto); } + + @Post('templates/:name') + @HttpCode(HttpStatus.OK) + @Authenticated({ admin: true }) + getNotificationTemplate( + @Auth() auth: AuthDto, + @Param('name') name: EmailTemplate, + @Body() dto: TemplateDto, + ): Promise { + return this.service.getTemplate(name, dto.template); + } } diff --git a/server/src/controllers/person.controller.ts b/server/src/controllers/person.controller.ts index ba9a181c41015..c8faf87e6270b 100644 --- a/server/src/controllers/person.controller.ts +++ b/server/src/controllers/person.controller.ts @@ -31,8 +31,8 @@ export class PersonController { @Get() @Authenticated({ permission: Permission.PERSON_READ }) - getAllPeople(@Auth() auth: AuthDto, @Query() withHidden: PersonSearchDto): Promise { - return this.service.getAll(auth, withHidden); + getAllPeople(@Auth() auth: AuthDto, @Query() options: PersonSearchDto): Promise { + return this.service.getAll(auth, options); } @Post() diff --git a/server/src/controllers/search.controller.ts b/server/src/controllers/search.controller.ts index 9fdb2746fc1d3..367c39dae9db6 100644 --- a/server/src/controllers/search.controller.ts +++ b/server/src/controllers/search.controller.ts @@ -25,7 +25,7 @@ export class SearchController { @Post('metadata') @HttpCode(HttpStatus.OK) @Authenticated() - searchMetadata(@Auth() auth: AuthDto, @Body() dto: MetadataSearchDto): Promise { + searchAssets(@Auth() auth: AuthDto, @Body() dto: MetadataSearchDto): Promise { return this.service.searchMetadata(auth, dto); } diff --git a/server/src/controllers/user.controller.ts b/server/src/controllers/user.controller.ts index 10076098d6516..15bb1913dbc21 100644 --- a/server/src/controllers/user.controller.ts +++ b/server/src/controllers/user.controller.ts @@ -39,8 +39,8 @@ export class UserController { @Get() @Authenticated() - searchUsers(): Promise { - return this.service.search(); + searchUsers(@Auth() auth: AuthDto): Promise { + return this.service.search(auth); } @Get('me') diff --git a/server/src/cores/storage.core.spec.ts b/server/src/cores/storage.core.spec.ts index 6ff6ca61bf3d3..a6636733066d8 100644 --- a/server/src/cores/storage.core.spec.ts +++ b/server/src/cores/storage.core.spec.ts @@ -3,6 +3,8 @@ import { vitest } from 'vitest'; vitest.mock('src/constants', () => ({ APP_MEDIA_LOCATION: '/photos', + ADDED_IN_PREFIX: 'This property was added in ', + DEPRECATED_IN_PREFIX: 'This property was deprecated in ', })); describe('StorageCore', () => { diff --git a/server/src/decorators.ts b/server/src/decorators.ts index db755c5ff9c56..c2bbe19b28fd9 100644 --- a/server/src/decorators.ts +++ b/server/src/decorators.ts @@ -2,8 +2,9 @@ import { SetMetadata, applyDecorators } from '@nestjs/common'; import { ApiExtension, ApiOperation, ApiProperty, ApiTags } from '@nestjs/swagger'; import _ from 'lodash'; import { ADDED_IN_PREFIX, DEPRECATED_IN_PREFIX, LIFECYCLE_EXTENSION } from 'src/constants'; -import { MetadataKey } from 'src/enum'; +import { ImmichWorker, MetadataKey } from 'src/enum'; import { EmitEvent } from 'src/interfaces/event.interface'; +import { JobName, QueueName } from 'src/interfaces/job.interface'; import { setUnion } from 'src/utils/set'; // PostgreSQL uses a 16-bit integer to indicate the number of bound parameters. This means that the @@ -119,9 +120,17 @@ export type EventConfig = { server?: boolean; /** lower value has higher priority, defaults to 0 */ priority?: number; + /** register events for these workers, defaults to all workers */ + workers?: ImmichWorker[]; }; export const OnEvent = (config: EventConfig) => SetMetadata(MetadataKey.EVENT_CONFIG, config); +export type JobConfig = { + name: JobName; + queue: QueueName; +}; +export const OnJob = (config: JobConfig) => SetMetadata(MetadataKey.JOB_CONFIG, config); + type LifecycleRelease = 'NEXT_RELEASE' | string; type LifecycleMetadata = { addedAt?: LifecycleRelease; diff --git a/server/src/dtos/album.dto.ts b/server/src/dtos/album.dto.ts index b12847ee62537..76f4fdfc98f4a 100644 --- a/server/src/dtos/album.dto.ts +++ b/server/src/dtos/album.dto.ts @@ -7,6 +7,7 @@ import { AuthDto } from 'src/dtos/auth.dto'; import { UserResponseDto, mapUser } from 'src/dtos/user.dto'; import { AlbumEntity } from 'src/entities/album.entity'; import { AlbumUserRole, AssetOrder } from 'src/enum'; +import { getAssetDateTime } from 'src/utils/date-time'; import { Optional, ValidateBoolean, ValidateUUID } from 'src/validation'; export class AlbumInfoDto { @@ -164,8 +165,8 @@ export const mapAlbum = (entity: AlbumEntity, withAssets: boolean, auth?: AuthDt const hasSharedLink = entity.sharedLinks?.length > 0; const hasSharedUser = sharedUsers.length > 0; - let startDate = assets.at(0)?.fileCreatedAt || undefined; - let endDate = assets.at(-1)?.fileCreatedAt || undefined; + let startDate = getAssetDateTime(assets.at(0)); + let endDate = getAssetDateTime(assets.at(-1)); // Swap dates if start date is greater than end date. if (startDate && endDate && startDate > endDate) { [startDate, endDate] = [endDate, startDate]; diff --git a/server/src/dtos/asset-response.dto.ts b/server/src/dtos/asset-response.dto.ts index ed92208182ee5..a255ac103b10e 100644 --- a/server/src/dtos/asset-response.dto.ts +++ b/server/src/dtos/asset-response.dto.ts @@ -12,7 +12,6 @@ import { TagResponseDto, mapTag } from 'src/dtos/tag.dto'; import { UserResponseDto, mapUser } from 'src/dtos/user.dto'; import { AssetFaceEntity } from 'src/entities/asset-face.entity'; import { AssetEntity } from 'src/entities/asset.entity'; -import { SmartInfoEntity } from 'src/entities/smart-info.entity'; import { AssetType } from 'src/enum'; import { mimeTypes } from 'src/utils/mime-types'; @@ -45,7 +44,6 @@ export class AssetResponseDto extends SanitizedAssetResponseDto { isTrashed!: boolean; isOffline!: boolean; exifInfo?: ExifResponseDto; - smartInfo?: SmartInfoResponseDto; tags?: TagResponseDto[]; people?: PersonWithFacesResponseDto[]; unassignedFaces?: AssetFaceWithoutPersonResponseDto[]; @@ -141,7 +139,6 @@ export function mapAsset(entity: AssetEntity, options: AssetMapOptions = {}): As isTrashed: !!entity.deletedAt, duration: entity.duration ?? '0:00:00.00000', exifInfo: entity.exifInfo ? mapExif(entity.exifInfo) : undefined, - smartInfo: entity.smartInfo ? mapSmartInfo(entity.smartInfo) : undefined, livePhotoVideoId: entity.livePhotoVideoId, tags: entity.tags?.map((tag) => mapTag(tag)), people: peopleWithFaces(entity.faces), @@ -161,15 +158,3 @@ export class MemoryLaneResponseDto { assets!: AssetResponseDto[]; } - -export class SmartInfoResponseDto { - tags?: string[] | null; - objects?: string[] | null; -} - -export function mapSmartInfo(entity: SmartInfoEntity): SmartInfoResponseDto { - return { - tags: entity.tags, - objects: entity.objects, - }; -} diff --git a/server/src/dtos/notification.dto.ts b/server/src/dtos/notification.dto.ts index 34b3923580830..c1a09c801c892 100644 --- a/server/src/dtos/notification.dto.ts +++ b/server/src/dtos/notification.dto.ts @@ -1,3 +1,13 @@ +import { IsString } from 'class-validator'; + export class TestEmailResponseDto { messageId!: string; } +export class TemplateResponseDto { + name!: string; + html!: string; +} +export class TemplateDto { + @IsString() + template!: string; +} diff --git a/server/src/dtos/person.dto.ts b/server/src/dtos/person.dto.ts index 94ee52d916f65..047ef600b821d 100644 --- a/server/src/dtos/person.dto.ts +++ b/server/src/dtos/person.dto.ts @@ -67,6 +67,10 @@ export class MergePersonDto { export class PersonSearchDto { @ValidateBoolean({ optional: true }) withHidden?: boolean; + @ValidateUUID({ optional: true }) + closestPersonId?: string; + @ValidateUUID({ optional: true }) + closestAssetId?: string; /** Page number for pagination */ @ApiPropertyOptional() diff --git a/server/src/dtos/server.dto.ts b/server/src/dtos/server.dto.ts index e54048335129f..e1f94dbaa55b2 100644 --- a/server/src/dtos/server.dto.ts +++ b/server/src/dtos/server.dto.ts @@ -86,6 +86,10 @@ export class UsageByUserDto { @ApiProperty({ type: 'integer', format: 'int64' }) usage!: number; @ApiProperty({ type: 'integer', format: 'int64' }) + usagePhotos!: number; + @ApiProperty({ type: 'integer', format: 'int64' }) + usageVideos!: number; + @ApiProperty({ type: 'integer', format: 'int64' }) quotaSizeInBytes!: number | null; } @@ -99,6 +103,12 @@ export class ServerStatsResponseDto { @ApiProperty({ type: 'integer', format: 'int64' }) usage = 0; + @ApiProperty({ type: 'integer', format: 'int64' }) + usagePhotos = 0; + + @ApiProperty({ type: 'integer', format: 'int64' }) + usageVideos = 0; + @ApiProperty({ isArray: true, type: UsageByUserDto, @@ -107,7 +117,9 @@ export class ServerStatsResponseDto { { photos: 1, videos: 1, - diskUsageRaw: 1, + diskUsageRaw: 2, + usagePhotos: 1, + usageVideos: 1, }, ], }) @@ -132,6 +144,7 @@ export class ServerConfigDto { isInitialized!: boolean; isOnboarded!: boolean; externalDomain!: string; + publicUsers!: boolean; mapDarkStyleUrl!: string; mapLightStyleUrl!: string; } diff --git a/server/src/dtos/system-config.dto.ts b/server/src/dtos/system-config.dto.ts index 7e7a8e08797c4..350918254542a 100644 --- a/server/src/dtos/system-config.dto.ts +++ b/server/src/dtos/system-config.dto.ts @@ -1,6 +1,7 @@ import { ApiProperty } from '@nestjs/swagger'; -import { Type } from 'class-transformer'; +import { Exclude, Transform, Type } from 'class-transformer'; import { + ArrayMinSize, IsBoolean, IsEnum, IsInt, @@ -12,13 +13,11 @@ import { IsUrl, Max, Min, - Validate, ValidateIf, ValidateNested, - ValidatorConstraint, - ValidatorConstraintInterface, } 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, @@ -33,14 +32,7 @@ import { VideoContainer, } from 'src/enum'; import { ConcurrentQueueName, QueueName } from 'src/interfaces/job.interface'; -import { ValidateBoolean, validateCronExpression } from 'src/validation'; - -@ValidatorConstraint({ name: 'cronValidator' }) -class CronValidator implements ValidatorConstraintInterface { - validate(expression: string): boolean { - return validateCronExpression(expression); - } -} +import { IsCronExpression, ValidateBoolean } from 'src/validation'; const isLibraryScanEnabled = (config: SystemConfigLibraryScanDto) => config.enabled; const isOAuthEnabled = (config: SystemConfigOAuthDto) => config.enabled; @@ -54,7 +46,7 @@ export class DatabaseBackupConfig { @ValidateIf(isDatabaseBackupEnabled) @IsNotEmpty() - @Validate(CronValidator, { message: 'Invalid cron expression' }) + @IsCronExpression() @IsString() cronExpression!: string; @@ -134,12 +126,6 @@ export class SystemConfigFFmpegDto { @ApiProperty({ type: 'integer' }) gopSize!: number; - @IsInt() - @Min(0) - @Type(() => Number) - @ApiProperty({ type: 'integer' }) - npl!: number; - @ValidateBoolean() temporalAQ!: boolean; @@ -250,7 +236,7 @@ class SystemConfigLibraryScanDto { @ValidateIf(isLibraryScanEnabled) @IsNotEmpty() - @Validate(CronValidator, { message: 'Invalid cron expression' }) + @IsCronExpression() @IsString() cronExpression!: string; } @@ -285,9 +271,16 @@ class SystemConfigMachineLearningDto { @ValidateBoolean() enabled!: boolean; - @IsUrl({ require_tld: false, allow_underscores: true }) + @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) - url!: string; + @ApiProperty({ type: 'array', items: { type: 'string', format: 'uri' }, minItems: 1 }) + urls!: string[]; @Type(() => CLIPConfig) @ValidateNested() @@ -420,6 +413,9 @@ class SystemConfigServerDto { @IsString() loginPageMessage!: string; + + @IsBoolean() + publicUsers!: boolean; } class SystemConfigSmtpTransportDto { @@ -469,6 +465,24 @@ class SystemConfigNotificationsDto { smtp!: SystemConfigSmtpDto; } +class SystemConfigTemplateEmailsDto { + @IsString() + albumInviteTemplate!: string; + + @IsString() + welcomeTemplate!: string; + + @IsString() + albumUpdateTemplate!: string; +} + +class SystemConfigTemplatesDto { + @Type(() => SystemConfigTemplateEmailsDto) + @ValidateNested() + @IsObject() + email!: SystemConfigTemplateEmailsDto; +} + class SystemConfigStorageTemplateDto { @ValidateBoolean() enabled!: boolean; @@ -640,6 +654,11 @@ export class SystemConfigDto implements SystemConfig { @IsObject() notifications!: SystemConfigNotificationsDto; + @Type(() => SystemConfigTemplatesDto) + @ValidateNested() + @IsObject() + templates!: SystemConfigTemplatesDto; + @Type(() => SystemConfigServerDto) @ValidateNested() @IsObject() diff --git a/server/src/emails/album-invite.email.tsx b/server/src/emails/album-invite.email.tsx index 232ef5290d6db..0b3819b332b5d 100644 --- a/server/src/emails/album-invite.email.tsx +++ b/server/src/emails/album-invite.email.tsx @@ -3,6 +3,7 @@ import * as React from 'react'; import { ImmichButton } from 'src/emails/components/button.component'; import ImmichLayout from 'src/emails/components/immich.layout'; import { AlbumInviteEmailProps } from 'src/interfaces/notification.interface'; +import { replaceTemplateTags } from 'src/utils/replace-template-tags'; export const AlbumInviteEmail = ({ baseUrl, @@ -11,39 +12,64 @@ export const AlbumInviteEmail = ({ senderName, albumId, cid, -}: AlbumInviteEmailProps) => ( - - - Hey {recipientName}! - - - - {senderName} has added you to the album {albumName}. - - - {cid && ( -

- + customTemplate, +}: AlbumInviteEmailProps) => { + const variables = { + albumName, + recipientName, + senderName, + albumId, + baseUrl, + }; + + const emailContent = customTemplate ? ( + replaceTemplateTags(customTemplate, variables) + ) : ( + <> + + Hey {recipientName}! + + + + {senderName} has added you to the album {albumName}. + + + ); + + return ( + + {customTemplate && ( + +
+
+ )} + + {!customTemplate && emailContent} + + {cid && ( +
+ +
+ )} + +
+ View Album
- )} - -
- View Album -
- - - If you cannot click the button use the link below to view the album. -
- {`${baseUrl}/albums/${albumId}`} -
-
-); + + + If you cannot click the button use the link below to view the album. +
+ {`${baseUrl}/albums/${albumId}`} +
+ + ); +}; AlbumInviteEmail.PreviewProps = { baseUrl: 'https://demo.immich.app', diff --git a/server/src/emails/album-update.email.tsx b/server/src/emails/album-update.email.tsx index 0fb5ad931c9f5..9dcd858e93e03 100644 --- a/server/src/emails/album-update.email.tsx +++ b/server/src/emails/album-update.email.tsx @@ -3,47 +3,80 @@ import * as React from 'react'; import { ImmichButton } from 'src/emails/components/button.component'; import ImmichLayout from 'src/emails/components/immich.layout'; import { AlbumUpdateEmailProps } from 'src/interfaces/notification.interface'; +import { replaceTemplateTags } from 'src/utils/replace-template-tags'; -export const AlbumUpdateEmail = ({ baseUrl, albumName, recipientName, albumId, cid }: AlbumUpdateEmailProps) => ( - - - Hey {recipientName}! - - - - New media has been added to {albumName}, -
check it out! -
- - {cid && ( -
- -
- )} +export const AlbumUpdateEmail = ({ + baseUrl, + albumName, + recipientName, + albumId, + cid, + customTemplate, +}: AlbumUpdateEmailProps) => { + const usableTemplateVariables = { + albumName, + recipientName, + albumId, + baseUrl, + }; + + const emailContent = customTemplate ? ( + replaceTemplateTags(customTemplate, usableTemplateVariables) + ) : ( + <> + + Hey {recipientName}! + + + + New media has been added to {albumName}, +
check it out! +
+ + ); + + return ( + + {customTemplate && ( + +
+
+ )} -
- View Album -
+ {!customTemplate && emailContent} + + {cid && ( +
+ +
+ )} + +
+ View Album +
- - If you cannot click the button use the link below to view the album. -
- {`${baseUrl}/albums/${albumId}`} -
-
-); + + If you cannot click the button use the link below to view the album. +
+ {`${baseUrl}/albums/${albumId}`} +
+
+ ); +}; AlbumUpdateEmail.PreviewProps = { baseUrl: 'https://demo.immich.app', albumName: 'Trip to Europe', albumId: 'b63f6dae-e1c9-401b-9a85-9dbbf5612539', recipientName: 'Alan Turing', + cid: '', + customTemplate: '', } as AlbumUpdateEmailProps; export default AlbumUpdateEmail; diff --git a/server/src/emails/components/footer.template.tsx b/server/src/emails/components/footer.template.tsx index 7c41a7196d18d..c84246bf87e23 100644 --- a/server/src/emails/components/footer.template.tsx +++ b/server/src/emails/components/footer.template.tsx @@ -5,12 +5,14 @@ export const ImmichFooter = () => ( <> - - - +
+ + + +
-
+
Immich diff --git a/server/src/emails/welcome.email.tsx b/server/src/emails/welcome.email.tsx index e031ac6b97137..ced0b77698836 100644 --- a/server/src/emails/welcome.email.tsx +++ b/server/src/emails/welcome.email.tsx @@ -3,36 +3,62 @@ import * as React from 'react'; import { ImmichButton } from 'src/emails/components/button.component'; import ImmichLayout from 'src/emails/components/immich.layout'; import { WelcomeEmailProps } from 'src/interfaces/notification.interface'; +import { replaceTemplateTags } from 'src/utils/replace-template-tags'; -export const WelcomeEmail = ({ baseUrl, displayName, username, password }: WelcomeEmailProps) => ( - - - Hey {displayName}! - - - A new account has been created for you. - - - Username: {username} - {password && ( - <> -
- Password: {password} - +export const WelcomeEmail = ({ baseUrl, displayName, username, password, customTemplate }: WelcomeEmailProps) => { + const usableTemplateVariables = { + displayName, + username, + password, + baseUrl, + }; + + const emailContent = customTemplate ? ( + replaceTemplateTags(customTemplate, usableTemplateVariables) + ) : ( + <> + + Hey {displayName}! + + + A new account has been created for you. + + + Username: {username} + {password && ( + <> +
+ Password: {password} + + )} +
+ + ); + + return ( + + {customTemplate && ( + +
+
)} -
- -
- Login -
- - - If you cannot click the button use the link below to proceed with first login. -
- {baseUrl} -
-
-); + + {!customTemplate && emailContent} + +
+ Login +
+ + + If you cannot click the button use the link below to proceed with first login. +
+ {baseUrl} +
+ + ); +}; WelcomeEmail.PreviewProps = { baseUrl: 'https://demo.immich.app/auth/login', diff --git a/server/src/entities/asset.entity.ts b/server/src/entities/asset.entity.ts index 0b893134d0e0d..f9e5c5e9813d2 100644 --- a/server/src/entities/asset.entity.ts +++ b/server/src/entities/asset.entity.ts @@ -5,7 +5,6 @@ import { AssetJobStatusEntity } from 'src/entities/asset-job-status.entity'; import { ExifEntity } from 'src/entities/exif.entity'; import { LibraryEntity } from 'src/entities/library.entity'; import { SharedLinkEntity } from 'src/entities/shared-link.entity'; -import { SmartInfoEntity } from 'src/entities/smart-info.entity'; import { SmartSearchEntity } from 'src/entities/smart-search.entity'; import { StackEntity } from 'src/entities/stack.entity'; import { TagEntity } from 'src/entities/tag.entity'; @@ -143,9 +142,6 @@ export class AssetEntity { @OneToOne(() => ExifEntity, (exifEntity) => exifEntity.asset) exifInfo?: ExifEntity; - @OneToOne(() => SmartInfoEntity, (smartInfoEntity) => smartInfoEntity.asset) - smartInfo?: SmartInfoEntity; - @OneToOne(() => SmartSearchEntity, (smartSearchEntity) => smartSearchEntity.asset) smartSearch?: SmartSearchEntity; diff --git a/server/src/entities/geodata-places.entity.ts b/server/src/entities/geodata-places.entity.ts index 966a50d5c9ef3..eb32d1b99b41f 100644 --- a/server/src/entities/geodata-places.entity.ts +++ b/server/src/entities/geodata-places.entity.ts @@ -14,12 +14,41 @@ export class GeodataPlacesEntity { @Column({ type: 'float' }) latitude!: number; - // @Column({ - // generatedType: 'STORED', - // asExpression: 'll_to_earth((latitude)::double precision, (longitude)::double precision)', - // type: 'earth', - // }) - // earthCoord!: unknown; + @Column({ type: 'char', length: 2 }) + countryCode!: string; + + @Column({ type: 'varchar', length: 20, nullable: true }) + admin1Code!: string; + + @Column({ type: 'varchar', length: 80, nullable: true }) + admin2Code!: string; + + @Column({ type: 'varchar', nullable: true }) + admin1Name!: string; + + @Column({ type: 'varchar', nullable: true }) + admin2Name!: string; + + @Column({ type: 'varchar', nullable: true }) + alternateNames!: string; + + @Column({ type: 'date' }) + modificationDate!: Date; +} + +@Entity('geodata_places_tmp', { synchronize: false }) +export class GeodataPlacesTempEntity { + @PrimaryColumn({ type: 'integer' }) + id!: number; + + @Column({ type: 'varchar', length: 200 }) + name!: string; + + @Column({ type: 'float' }) + longitude!: number; + + @Column({ type: 'float' }) + latitude!: number; @Column({ type: 'char', length: 2 }) countryCode!: string; diff --git a/server/src/entities/index.ts b/server/src/entities/index.ts index 7425ee67d8a6e..75e92038acb2b 100644 --- a/server/src/entities/index.ts +++ b/server/src/entities/index.ts @@ -18,7 +18,6 @@ import { PartnerEntity } from 'src/entities/partner.entity'; import { PersonEntity } from 'src/entities/person.entity'; import { SessionEntity } from 'src/entities/session.entity'; import { SharedLinkEntity } from 'src/entities/shared-link.entity'; -import { SmartInfoEntity } from 'src/entities/smart-info.entity'; import { SmartSearchEntity } from 'src/entities/smart-search.entity'; import { StackEntity } from 'src/entities/stack.entity'; import { SystemMetadataEntity } from 'src/entities/system-metadata.entity'; @@ -46,7 +45,6 @@ export const entities = [ PartnerEntity, PersonEntity, SharedLinkEntity, - SmartInfoEntity, SmartSearchEntity, StackEntity, SystemMetadataEntity, diff --git a/server/src/entities/natural-earth-countries.entity.ts b/server/src/entities/natural-earth-countries.entity.ts index 19a12fa07b4e8..0f97132045d01 100644 --- a/server/src/entities/natural-earth-countries.entity.ts +++ b/server/src/entities/natural-earth-countries.entity.ts @@ -2,7 +2,25 @@ import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm'; @Entity('naturalearth_countries', { synchronize: false }) export class NaturalEarthCountriesEntity { - @PrimaryGeneratedColumn() + @PrimaryGeneratedColumn('identity', { generatedIdentity: 'ALWAYS' }) + id!: number; + + @Column({ type: 'varchar', length: 50 }) + admin!: string; + + @Column({ type: 'varchar', length: 3 }) + admin_a3!: string; + + @Column({ type: 'varchar', length: 50 }) + type!: string; + + @Column({ type: 'polygon' }) + coordinates!: string; +} + +@Entity('naturalearth_countries_tmp', { synchronize: false }) +export class NaturalEarthCountriesTempEntity { + @PrimaryGeneratedColumn('identity', { generatedIdentity: 'ALWAYS' }) id!: number; @Column({ type: 'varchar', length: 50 }) diff --git a/server/src/entities/smart-info.entity.ts b/server/src/entities/smart-info.entity.ts deleted file mode 100644 index 86190c174d170..0000000000000 --- a/server/src/entities/smart-info.entity.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { AssetEntity } from 'src/entities/asset.entity'; -import { Column, Entity, JoinColumn, OneToOne, PrimaryColumn } from 'typeorm'; - -@Entity('smart_info', { synchronize: false }) -export class SmartInfoEntity { - @OneToOne(() => AssetEntity, { onDelete: 'CASCADE', nullable: true }) - @JoinColumn({ name: 'assetId', referencedColumnName: 'id' }) - asset?: AssetEntity; - - @PrimaryColumn() - assetId!: string; - - @Column({ type: 'text', array: true, nullable: true }) - tags!: string[] | null; - - @Column({ type: 'text', array: true, nullable: true }) - objects!: string[] | null; -} diff --git a/server/src/enum.ts b/server/src/enum.ts index c3b3d8341babc..3440d45cee6d2 100644 --- a/server/src/enum.ts +++ b/server/src/enum.ts @@ -335,6 +335,7 @@ export enum MetadataKey { SHARED_ROUTE = 'shared_route', API_KEY_SECURITY = 'api_key', EVENT_CONFIG = 'event_config', + JOB_CONFIG = 'job_config', TELEMETRY_ENABLED = 'telemetry_enabled', } @@ -372,3 +373,14 @@ export enum ImmichTelemetry { REPO = 'repo', JOB = 'job', } + +export enum ExifOrientation { + Horizontal = 1, + MirrorHorizontal = 2, + Rotate180 = 3, + MirrorVertical = 4, + MirrorHorizontalRotate270CW = 5, + Rotate90CW = 6, + MirrorHorizontalRotate90CW = 7, + Rotate270CW = 8, +} diff --git a/server/src/interfaces/asset.interface.ts b/server/src/interfaces/asset.interface.ts index 37d3326a8abc5..b25e42ba0e9e0 100644 --- a/server/src/interfaces/asset.interface.ts +++ b/server/src/interfaces/asset.interface.ts @@ -28,9 +28,7 @@ export enum WithoutProperty { EXIF = 'exif', SMART_SEARCH = 'smart-search', DUPLICATE = 'duplicate', - OBJECT_TAGS = 'object-tags', FACES = 'faces', - PERSON = 'person', SIDECAR = 'sidecar', } @@ -94,7 +92,6 @@ export type AssetWithoutRelations = Omit< | 'library' | 'exifInfo' | 'sharedLinks' - | 'smartInfo' | 'smartSearch' | 'tags' >; @@ -149,6 +146,11 @@ export interface UpsertFileOptions { export type AssetPathEntity = Pick; +export interface DayOfYearAssets { + yearsAgo: number; + assets: AssetEntity[]; +} + export const IAssetRepository = 'IAssetRepository'; export interface IAssetRepository { @@ -159,7 +161,7 @@ export interface IAssetRepository { select?: FindOptionsSelect, ): Promise; getByIdsWithAllRelations(ids: string[]): Promise; - getByDayOfYear(ownerIds: string[], monthDay: MonthDay): Promise; + getByDayOfYear(ownerIds: string[], monthDay: MonthDay): Promise; getByChecksum(options: { ownerId: string; checksum: Buffer; libraryId?: string }): Promise; getByChecksums(userId: string, checksums: Buffer[]): Promise; getUploadAssetIdByChecksum(ownerId: string, checksum: Buffer): Promise; @@ -190,7 +192,6 @@ export interface IAssetRepository { upsertExif(exif: Partial): Promise; upsertJobStatus(...jobStatus: Partial[]): Promise; getAssetIdByCity(userId: string, options: AssetExploreFieldOptions): Promise>; - getAssetIdByTag(userId: string, options: AssetExploreFieldOptions): Promise>; getDuplicates(options: AssetBuilderOptions): Promise; getAllForUserFullSync(options: AssetFullSyncOptions): Promise; getChangedDeltaSync(options: AssetDeltaSyncOptions): Promise; diff --git a/server/src/interfaces/config.interface.ts b/server/src/interfaces/config.interface.ts index ec5397cc2cdd4..300b55f27b6fd 100644 --- a/server/src/interfaces/config.interface.ts +++ b/server/src/interfaces/config.interface.ts @@ -93,4 +93,5 @@ export interface EnvData { export interface IConfigRepository { getEnv(): EnvData; + getWorker(): ImmichWorker | undefined; } diff --git a/server/src/interfaces/cron.interface.ts b/server/src/interfaces/cron.interface.ts new file mode 100644 index 0000000000000..ceb554864a172 --- /dev/null +++ b/server/src/interfaces/cron.interface.ts @@ -0,0 +1,20 @@ +export const ICronRepository = 'ICronRepository'; + +type CronBase = { + name: string; + start?: boolean; +}; + +export type CronCreate = CronBase & { + expression: string; + onTick: () => void; +}; + +export type CronUpdate = CronBase & { + expression?: string; +}; + +export interface ICronRepository { + create(cron: CronCreate): void; + update(cron: CronUpdate): void; +} diff --git a/server/src/interfaces/event.interface.ts b/server/src/interfaces/event.interface.ts index 8b59457914a3e..9a9e23cca0018 100644 --- a/server/src/interfaces/event.interface.ts +++ b/server/src/interfaces/event.interface.ts @@ -2,21 +2,21 @@ import { ClassConstructor } from 'class-transformer'; import { SystemConfig } from 'src/config'; import { AssetResponseDto } from 'src/dtos/asset-response.dto'; import { ReleaseNotification, ServerVersionResponseDto } from 'src/dtos/server.dto'; -import { ImmichWorker } from 'src/enum'; +import { JobItem, QueueName } from 'src/interfaces/job.interface'; export const IEventRepository = 'IEventRepository'; type EventMap = { // app events - 'app.bootstrap': [ImmichWorker]; - 'app.shutdown': [ImmichWorker]; + 'app.bootstrap': []; + 'app.shutdown': []; + 'config.init': [{ newConfig: SystemConfig }]; // config events 'config.update': [ { newConfig: SystemConfig; - /** When the server starts, `oldConfig` is `undefined` */ - oldConfig?: SystemConfig; + oldConfig: SystemConfig; }, ]; 'config.validate': [{ newConfig: SystemConfig; oldConfig: SystemConfig }]; @@ -38,6 +38,8 @@ type EventMap = { 'assets.delete': [{ assetIds: string[]; userId: string }]; 'assets.restore': [{ assetIds: string[]; userId: string }]; + 'job.start': [QueueName, JobItem]; + // session events 'session.delete': [{ sessionId: string }]; @@ -86,6 +88,13 @@ export type EventItem = { server: boolean; }; +export enum BootstrapEventPriority { + // Database service should be initialized before anything else, most other services need database access + DatabaseService = -200, + // Initialise config after other bootstrap services, stop other services from using config on bootstrap + SystemConfig = 100, +} + export interface IEventRepository { setup(options: { services: ClassConstructor[] }): void; emit(event: T, ...args: ArgsOf): Promise; diff --git a/server/src/interfaces/job.interface.ts b/server/src/interfaces/job.interface.ts index 31945f97eceb5..7976f813022ff 100644 --- a/server/src/interfaces/job.interface.ts +++ b/server/src/interfaces/job.interface.ts @@ -1,3 +1,4 @@ +import { ClassConstructor } from 'class-transformer'; import { EmailImageAttachment } from 'src/interfaces/notification.interface'; export enum QueueName { @@ -238,8 +239,8 @@ export type JobItem = // Migration | { name: JobName.QUEUE_MIGRATION; data?: IBaseJob } - | { name: JobName.MIGRATE_ASSET; data?: IEntityJob } - | { name: JobName.MIGRATE_PERSON; data?: IEntityJob } + | { name: JobName.MIGRATE_ASSET; data: IEntityJob } + | { name: JobName.MIGRATE_PERSON; data: IEntityJob } // Metadata Extraction | { name: JobName.QUEUE_METADATA_EXTRACTION; data: IBaseJob } @@ -286,7 +287,7 @@ export type JobItem = | { name: JobName.LIBRARY_SYNC_FILE; data: ILibraryFileJob } | { name: JobName.LIBRARY_QUEUE_SYNC_FILES; data: IEntityJob } | { name: JobName.LIBRARY_QUEUE_SYNC_ASSETS; data: IEntityJob } - | { name: JobName.LIBRARY_SYNC_ASSET; data: IEntityJob } + | { name: JobName.LIBRARY_SYNC_ASSET; data: ILibraryAssetJob } | { name: JobName.LIBRARY_DELETE; data: IEntityJob } | { name: JobName.LIBRARY_QUEUE_SYNC_ALL; data?: IBaseJob } | { name: JobName.LIBRARY_QUEUE_CLEANUP; data: IBaseJob } @@ -305,16 +306,15 @@ export enum JobStatus { FAILED = 'failed', SKIPPED = 'skipped', } - -export type JobHandler = (data: T) => Promise; -export type JobItemHandler = (item: JobItem) => Promise; +export type Jobs = { [K in JobItem['name']]: (JobItem & { name: K })['data'] }; +export type JobOf = Jobs[T]; export const IJobRepository = 'IJobRepository'; export interface IJobRepository { - addHandler(queueName: QueueName, concurrency: number, handler: JobItemHandler): void; - addCronJob(name: string, expression: string, onTick: () => void, start?: boolean): void; - updateCronJob(name: string, expression?: string, start?: boolean): void; + setup(options: { services: ClassConstructor[] }): void; + startWorkers(): void; + run(job: JobItem): Promise; setConcurrency(queueName: QueueName, concurrency: number): void; queue(item: JobItem): Promise; queueAll(items: JobItem[]): Promise; diff --git a/server/src/interfaces/machine-learning.interface.ts b/server/src/interfaces/machine-learning.interface.ts index 5342030c8fde7..372aa0c7cde25 100644 --- a/server/src/interfaces/machine-learning.interface.ts +++ b/server/src/interfaces/machine-learning.interface.ts @@ -51,7 +51,7 @@ export type DetectedFaces = { faces: Face[] } & VisualResponse; export type MachineLearningRequest = ClipVisualRequest | ClipTextualRequest | FacialRecognitionRequest; export interface IMachineLearningRepository { - encodeImage(url: string, imagePath: string, config: ModelOptions): Promise; - encodeText(url: string, text: string, config: ModelOptions): Promise; - detectFaces(url: string, imagePath: string, config: FaceDetectionOptions): Promise; + encodeImage(urls: string[], imagePath: string, config: ModelOptions): Promise; + encodeText(urls: string[], text: string, config: ModelOptions): Promise; + detectFaces(urls: string[], imagePath: string, config: FaceDetectionOptions): Promise; } diff --git a/server/src/interfaces/media.interface.ts b/server/src/interfaces/media.interface.ts index 2bc8ccde36d8b..b90dfb483c261 100644 --- a/server/src/interfaces/media.interface.ts +++ b/server/src/interfaces/media.interface.ts @@ -1,5 +1,5 @@ import { Writable } from 'node:stream'; -import { ImageFormat, TranscodeTarget, VideoCodec } from 'src/enum'; +import { ExifOrientation, ImageFormat, TranscodeTarget, VideoCodec } from 'src/enum'; export const IMediaRepository = 'IMediaRepository'; @@ -31,6 +31,7 @@ interface DecodeImageOptions { export interface DecodeToBufferOptions extends DecodeImageOptions { size: number; + orientation?: ExifOrientation; } export type GenerateThumbnailOptions = ImageOptions & DecodeImageOptions; @@ -59,6 +60,7 @@ export interface VideoStreamInfo { frameCount: number; isHDR: boolean; bitrate: number; + pixelFormat: string; } export interface AudioStreamInfo { @@ -112,7 +114,12 @@ export interface ImageBuffer { } export interface VideoCodecSWConfig { - getCommand(target: TranscodeTarget, videoStream: VideoStreamInfo, audioStream: AudioStreamInfo): TranscodeCommand; + getCommand( + target: TranscodeTarget, + videoStream: VideoStreamInfo, + audioStream: AudioStreamInfo, + format?: VideoFormat, + ): TranscodeCommand; } export interface VideoCodecHWConfig extends VideoCodecSWConfig { @@ -123,6 +130,11 @@ export interface ProbeOptions { countFrames: boolean; } +export interface VideoInterfaces { + dri: string[]; + mali: boolean; +} + export interface IMediaRepository { // image extract(input: string, output: string): Promise; diff --git a/server/src/interfaces/notification.interface.ts b/server/src/interfaces/notification.interface.ts index ec0ecc534b6b1..b20b3c50aee8f 100644 --- a/server/src/interfaces/notification.interface.ts +++ b/server/src/interfaces/notification.interface.ts @@ -39,6 +39,7 @@ export enum EmailTemplate { interface BaseEmailProps { baseUrl: string; + customTemplate?: string; } export interface TestEmailProps extends BaseEmailProps { @@ -70,18 +71,22 @@ export type EmailRenderRequest = | { template: EmailTemplate.TEST_EMAIL; data: TestEmailProps; + customTemplate: string; } | { template: EmailTemplate.WELCOME; data: WelcomeEmailProps; + customTemplate: string; } | { template: EmailTemplate.ALBUM_INVITE; data: AlbumInviteEmailProps; + customTemplate: string; } | { template: EmailTemplate.ALBUM_UPDATE; data: AlbumUpdateEmailProps; + customTemplate: string; }; export type SendEmailResponse = { diff --git a/server/src/interfaces/person.interface.ts b/server/src/interfaces/person.interface.ts index b3e2c0990efd1..dc89f5c1b0648 100644 --- a/server/src/interfaces/person.interface.ts +++ b/server/src/interfaces/person.interface.ts @@ -10,6 +10,7 @@ export const IPersonRepository = 'IPersonRepository'; export interface PersonSearchOptions { minimumFaceCount: number; withHidden: boolean; + closestFaceAssetId?: string; } export interface PersonNameSearchOptions { diff --git a/server/src/interfaces/search.interface.ts b/server/src/interfaces/search.interface.ts index 63d74a35fb626..d59291c88339b 100644 --- a/server/src/interfaces/search.interface.ts +++ b/server/src/interfaces/search.interface.ts @@ -68,7 +68,6 @@ export interface SearchStatusOptions { export interface SearchOneToOneRelationOptions { withExif?: boolean; - withSmartInfo?: boolean; withStacked?: boolean; } @@ -171,6 +170,22 @@ export interface AssetDuplicateResult { distance: number; } +export interface GetStatesOptions { + country?: string; +} + +export interface GetCitiesOptions extends GetStatesOptions { + state?: string; +} + +export interface GetCameraModelsOptions { + make?: string; +} + +export interface GetCameraMakesOptions { + model?: string; +} + export interface ISearchRepository { searchMetadata(pagination: SearchPaginationOptions, options: AssetSearchOptions): Paginated; searchSmart(pagination: SearchPaginationOptions, options: SmartSearchOptions): Paginated; @@ -184,8 +199,8 @@ export interface ISearchRepository { getDimensionSize(): Promise; setDimensionSize(dimSize: number): Promise; getCountries(userIds: string[]): Promise>; - getStates(userIds: string[], country?: string): Promise>; - getCities(userIds: string[], country?: string, state?: string): Promise>; - getCameraMakes(userIds: string[], model?: string): Promise>; - getCameraModels(userIds: string[], make?: string): Promise>; + getStates(userIds: string[], options: GetStatesOptions): Promise>; + getCities(userIds: string[], options: GetCitiesOptions): Promise>; + getCameraMakes(userIds: string[], options: GetCameraMakesOptions): Promise>; + getCameraModels(userIds: string[], options: GetCameraModelsOptions): Promise>; } diff --git a/server/src/interfaces/user.interface.ts b/server/src/interfaces/user.interface.ts index 3353d45dce215..385a4d3d50e91 100644 --- a/server/src/interfaces/user.interface.ts +++ b/server/src/interfaces/user.interface.ts @@ -11,6 +11,8 @@ export interface UserStatsQueryResponse { photos: number; videos: number; usage: number; + usagePhotos: number; + usageVideos: number; quotaSizeInBytes: number | null; } diff --git a/server/src/middleware/auth.guard.ts b/server/src/middleware/auth.guard.ts index 2eaf4114758d7..e05dba907b4ff 100644 --- a/server/src/middleware/auth.guard.ts +++ b/server/src/middleware/auth.guard.ts @@ -49,7 +49,7 @@ export const GetLoginDetails = createParamDecorator((data, context: ExecutionCon const userAgent = UAParser(request.headers['user-agent']); return { - clientIp: request.ip, + clientIp: request.ip ?? '', isSecure: request.secure, deviceType: userAgent.browser.name || userAgent.device.type || (request.headers.devicemodel as string) || '', deviceOS: userAgent.os.name || (request.headers.devicetype as string) || '', diff --git a/server/src/middleware/file-upload.interceptor.ts b/server/src/middleware/file-upload.interceptor.ts index 075a7f504636a..108a187e67b8c 100644 --- a/server/src/middleware/file-upload.interceptor.ts +++ b/server/src/middleware/file-upload.interceptor.ts @@ -11,6 +11,7 @@ import { RouteKey } from 'src/enum'; import { ILoggerRepository } from 'src/interfaces/logger.interface'; import { AuthRequest } from 'src/middleware/auth.guard'; import { AssetMediaService, UploadFile } from 'src/services/asset-media.service'; +import { asRequest, mapToUploadFile } from 'src/utils/asset.util'; export interface UploadFiles { assetData: ImmichFile[]; @@ -35,16 +36,6 @@ export interface ImmichFile extends Express.Multer.File { checksum: Buffer; } -export function mapToUploadFile(file: ImmichFile): UploadFile { - return { - uuid: file.uuid, - checksum: file.checksum, - originalPath: file.path, - originalName: Buffer.from(file.originalname, 'latin1').toString('utf8'), - size: file.size, - }; -} - type DiskStorageCallback = (error: Error | null, result: string) => void; type ImmichMulterFile = Express.Multer.File & { uuid: string }; @@ -62,14 +53,6 @@ const callbackify = (target: (...arguments_: any[]) => T, callback: Callback< } }; -const asRequest = (request: AuthRequest, file: Express.Multer.File) => { - return { - auth: request.user || null, - fieldName: file.fieldname as UploadFieldName, - file: mapToUploadFile(file as ImmichFile), - }; -}; - @Injectable() export class FileUploadInterceptor implements NestInterceptor { private handlers: { @@ -141,6 +124,12 @@ export class FileUploadInterceptor implements NestInterceptor { private handleFile(request: AuthRequest, file: Express.Multer.File, callback: Callback>) { (file as ImmichMulterFile).uuid = randomUUID(); + + request.on('error', (error) => { + this.logger.warn('Request error while uploading file, cleaning up', error); + this.assetService.onUploadError(request, file).catch(this.logger.error); + }); + if (!this.isAssetUploadFile(file)) { this.defaultStorage._handleFile(request, file, callback); return; diff --git a/server/src/migrations/1730227312171-RemoveNplFromSystemConfig.ts b/server/src/migrations/1730227312171-RemoveNplFromSystemConfig.ts new file mode 100644 index 0000000000000..2c929191dd7e4 --- /dev/null +++ b/server/src/migrations/1730227312171-RemoveNplFromSystemConfig.ts @@ -0,0 +1,12 @@ +import { MigrationInterface, QueryRunner } from 'typeorm'; + +export class RemoveNplFromSystemConfig1730227312171 implements MigrationInterface { + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query(` + update system_metadata + set value = value #- '{ffmpeg,npl}' + where key = 'system-config' and value->'ffmpeg'->'npl' is not null`); + } + + public async down(): Promise {} +} diff --git a/server/src/migrations/1730989238718-DropSmartInfoTable.ts b/server/src/migrations/1730989238718-DropSmartInfoTable.ts new file mode 100644 index 0000000000000..a4de2652d6471 --- /dev/null +++ b/server/src/migrations/1730989238718-DropSmartInfoTable.ts @@ -0,0 +1,11 @@ +import { MigrationInterface, QueryRunner } from 'typeorm'; + +export class DropSmartInfoTable1730989238718 implements MigrationInterface { + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query(`DROP TABLE smart_info`); + } + + public async down(): Promise { + // not implemented + } +} diff --git a/server/src/migrations/1732072134943-NaturalEarthCountriesIdentityColumn.ts b/server/src/migrations/1732072134943-NaturalEarthCountriesIdentityColumn.ts new file mode 100644 index 0000000000000..3ebe8108cb13c --- /dev/null +++ b/server/src/migrations/1732072134943-NaturalEarthCountriesIdentityColumn.ts @@ -0,0 +1,29 @@ +import { MigrationInterface, QueryRunner } from 'typeorm'; + +export class NaturalEarthCountriesIdentityColumn1732072134943 implements MigrationInterface { + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE naturalearth_countries ALTER id DROP DEFAULT`); + await queryRunner.query(`DROP SEQUENCE naturalearth_countries_id_seq`); + await queryRunner.query(`ALTER TABLE naturalearth_countries ALTER id ADD GENERATED ALWAYS AS IDENTITY`); + + // same as ll_to_earth, but with explicit schema to avoid weirdness and allow it to work in expression indices + await queryRunner.query(` + CREATE FUNCTION ll_to_earth_public(latitude double precision, longitude double precision) RETURNS public.earth PARALLEL SAFE IMMUTABLE STRICT LANGUAGE SQL AS $$ + SELECT public.cube(public.cube(public.cube(public.earth()*cos(radians(latitude))*cos(radians(longitude))),public.earth()*cos(radians(latitude))*sin(radians(longitude))),public.earth()*sin(radians(latitude)))::public.earth + $$`); + + await queryRunner.query(`ALTER TABLE geodata_places DROP COLUMN "earthCoord"`); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE naturalearth_countries ALTER id DROP GENERATED`); + await queryRunner.query(`CREATE SEQUENCE naturalearth_countries_id_seq`); + await queryRunner.query( + `ALTER TABLE naturalearth_countries ALTER id SET DEFAULT nextval('naturalearth_countries_id_seq'::regclass)`, + ); + await queryRunner.query(`DROP FUNCTION ll_to_earth_public`); + await queryRunner.query( + `ALTER TABLE "geodata_places" ADD "earthCoord" earth GENERATED ALWAYS AS (ll_to_earth(latitude, longitude)) STORED`, + ); + } +} diff --git a/server/src/migrations/1733339482860-RenameMachineLearningUrlToUrls.ts b/server/src/migrations/1733339482860-RenameMachineLearningUrlToUrls.ts new file mode 100644 index 0000000000000..65bb02c8e2971 --- /dev/null +++ b/server/src/migrations/1733339482860-RenameMachineLearningUrlToUrls.ts @@ -0,0 +1,19 @@ +import { MigrationInterface, QueryRunner } from 'typeorm'; + +export class RenameMachineLearningUrlToUrls1733339482860 implements MigrationInterface { + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query(` + UPDATE system_metadata + SET value = jsonb_insert(value #- '{machineLearning,url}', '{machineLearning,urls}'::text[], jsonb_build_array(value->'machineLearning'->'url')) + WHERE key = 'system-config' AND value->'machineLearning'->'url' IS NOT NULL + `); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(` + UPDATE system_metadata + SET value = jsonb_insert(value #- '{machineLearning,urls}', '{machineLearning,url}'::text[], to_jsonb(value->'machineLearning'->'urls'->>0)) + WHERE key = 'system-config' AND value->'machineLearning'->'urls' IS NOT NULL AND jsonb_array_length(value->'machineLearning'->'urls') >= 1 + `); + } +} diff --git a/server/src/queries/asset.repository.sql b/server/src/queries/asset.repository.sql index 98edc8da1d292..4694cd20fc532 100644 --- a/server/src/queries/asset.repository.sql +++ b/server/src/queries/asset.repository.sql @@ -68,7 +68,7 @@ SELECT FROM "assets" "entity" LEFT JOIN "exif" "exifInfo" ON "exifInfo"."assetId" = "entity"."id" - LEFT JOIN "asset_files" "files" ON "files"."assetId" = "entity"."id" + INNER JOIN "asset_files" "files" ON "files"."assetId" = "entity"."id" WHERE ( "entity"."ownerId" IN ($1) @@ -84,6 +84,16 @@ WHERE FROM "entity"."localDateTime" AT TIME ZONE 'UTC' ) = $3 + AND "files"."type" = $4 + AND EXTRACT( + YEAR + FROM + CURRENT_DATE AT TIME ZONE 'UTC' + ) - EXTRACT( + YEAR + FROM + "entity"."localDateTime" AT TIME ZONE 'UTC' + ) > 0 ) AND ("entity"."deletedAt" IS NULL) ORDER BY @@ -183,9 +193,6 @@ SELECT "AssetEntity__AssetEntity_exifInfo"."bitsPerSample" AS "AssetEntity__AssetEntity_exifInfo_bitsPerSample", "AssetEntity__AssetEntity_exifInfo"."rating" AS "AssetEntity__AssetEntity_exifInfo_rating", "AssetEntity__AssetEntity_exifInfo"."fps" AS "AssetEntity__AssetEntity_exifInfo_fps", - "AssetEntity__AssetEntity_smartInfo"."assetId" AS "AssetEntity__AssetEntity_smartInfo_assetId", - "AssetEntity__AssetEntity_smartInfo"."tags" AS "AssetEntity__AssetEntity_smartInfo_tags", - "AssetEntity__AssetEntity_smartInfo"."objects" AS "AssetEntity__AssetEntity_smartInfo_objects", "AssetEntity__AssetEntity_tags"."id" AS "AssetEntity__AssetEntity_tags_id", "AssetEntity__AssetEntity_tags"."value" AS "AssetEntity__AssetEntity_tags_value", "AssetEntity__AssetEntity_tags"."createdAt" AS "AssetEntity__AssetEntity_tags_createdAt", @@ -252,7 +259,6 @@ SELECT FROM "assets" "AssetEntity" LEFT JOIN "exif" "AssetEntity__AssetEntity_exifInfo" ON "AssetEntity__AssetEntity_exifInfo"."assetId" = "AssetEntity"."id" - LEFT JOIN "smart_info" "AssetEntity__AssetEntity_smartInfo" ON "AssetEntity__AssetEntity_smartInfo"."assetId" = "AssetEntity"."id" LEFT JOIN "tag_asset" "AssetEntity_AssetEntity__AssetEntity_tags" ON "AssetEntity_AssetEntity__AssetEntity_tags"."assetsId" = "AssetEntity"."id" LEFT JOIN "tags" "AssetEntity__AssetEntity_tags" ON "AssetEntity__AssetEntity_tags"."id" = "AssetEntity_AssetEntity__AssetEntity_tags"."tagsId" LEFT JOIN "asset_faces" "AssetEntity__AssetEntity_faces" ON "AssetEntity__AssetEntity_faces"."assetId" = "AssetEntity"."id" @@ -932,36 +938,6 @@ WHERE LIMIT 12 --- AssetRepository.getAssetIdByTag -WITH - "random_tags" AS ( - SELECT - unnest(tags) AS "tag" - FROM - "smart_info" "si" - GROUP BY - tag - HAVING - count(*) >= $1 - ) -SELECT DISTINCT - ON (unnest("si"."tags")) "asset"."id" AS "data", - unnest("si"."tags") AS "value" -FROM - "assets" "asset" - INNER JOIN "smart_info" "si" ON "asset"."id" = si."assetId" - INNER JOIN "random_tags" "t" ON "si"."tags" @> ARRAY[t.tag] -WHERE - ( - "asset"."isVisible" = true - AND "asset"."type" = $2 - AND "asset"."ownerId" IN ($3) - AND "asset"."isArchived" = $4 - ) - AND ("asset"."deletedAt" IS NULL) -LIMIT - 12 - -- AssetRepository.getAllForUserFullSync SELECT "asset"."id" AS "asset_id", diff --git a/server/src/queries/person.repository.sql b/server/src/queries/person.repository.sql index 5616559d7d06d..a7e683fca1e72 100644 --- a/server/src/queries/person.repository.sql +++ b/server/src/queries/person.repository.sql @@ -20,13 +20,12 @@ SELECT "person"."isHidden" AS "person_isHidden" FROM "person" "person" - LEFT JOIN "asset_faces" "face" ON "face"."personId" = "person"."id" + INNER JOIN "asset_faces" "face" ON "face"."personId" = "person"."id" INNER JOIN "assets" "asset" ON "asset"."id" = "face"."assetId" AND ("asset"."deletedAt" IS NULL) WHERE "person"."ownerId" = $1 AND "asset"."isArchived" = false - AND "person"."thumbnailPath" != '' AND "person"."isHidden" = false GROUP BY "person"."id" @@ -257,15 +256,12 @@ SELECT ) AS "hidden" FROM "person" "person" - LEFT JOIN "asset_faces" "face" ON "face"."personId" = "person"."id" + INNER JOIN "asset_faces" "face" ON "face"."personId" = "person"."id" INNER JOIN "assets" "asset" ON "asset"."id" = "face"."assetId" AND ("asset"."deletedAt" IS NULL) WHERE "person"."ownerId" = $1 AND "asset"."isArchived" = false - AND "person"."thumbnailPath" != '' -HAVING - COUNT("face"."assetId") != 0 -- PersonRepository.getFacesByIds SELECT diff --git a/server/src/queries/search.repository.sql b/server/src/queries/search.repository.sql index cd9a84b016d0f..1084375059e52 100644 --- a/server/src/queries/search.repository.sql +++ b/server/src/queries/search.repository.sql @@ -279,13 +279,7 @@ LIMIT -- SearchRepository.searchSmart START TRANSACTION SET - LOCAL vectors.enable_prefilter = on; - -SET - LOCAL vectors.search_mode = vbase; - -SET - LOCAL vectors.hnsw_ef_search = 100; + LOCAL vectors.hnsw_ef_search = 200; SELECT "asset"."id" AS "asset_id", "asset"."deviceAssetId" AS "asset_deviceAssetId", @@ -369,7 +363,7 @@ WHERE ORDER BY "search"."embedding" <= > $6 ASC LIMIT - 101 + 201 COMMIT -- SearchRepository.searchDuplicates @@ -404,12 +398,6 @@ WHERE -- SearchRepository.searchFaces START TRANSACTION -SET - LOCAL vectors.enable_prefilter = on; - -SET - LOCAL vectors.search_mode = vbase; - SET LOCAL vectors.hnsw_ef_search = 100; WITH @@ -436,7 +424,7 @@ WITH ORDER BY "search"."embedding" <= > $1 ASC LIMIT - 100 + 64 ) SELECT res.* @@ -597,52 +585,57 @@ SELECT DISTINCT ON ("exif"."country") "exif"."country" AS "country" FROM "exif" "exif" - LEFT JOIN "assets" "asset" ON "asset"."id" = "exif"."assetId" + INNER JOIN "assets" "asset" ON "asset"."id" = "exif"."assetId" AND ("asset"."deletedAt" IS NULL) WHERE "asset"."ownerId" IN ($1) + AND "exif"."country" != '' + AND "exif"."country" IS NOT NULL -- SearchRepository.getStates SELECT DISTINCT ON ("exif"."state") "exif"."state" AS "state" FROM "exif" "exif" - LEFT JOIN "assets" "asset" ON "asset"."id" = "exif"."assetId" + INNER JOIN "assets" "asset" ON "asset"."id" = "exif"."assetId" AND ("asset"."deletedAt" IS NULL) WHERE "asset"."ownerId" IN ($1) - AND "exif"."country" = $2 + AND "exif"."state" != '' + AND "exif"."state" IS NOT NULL -- SearchRepository.getCities SELECT DISTINCT ON ("exif"."city") "exif"."city" AS "city" FROM "exif" "exif" - LEFT JOIN "assets" "asset" ON "asset"."id" = "exif"."assetId" + INNER JOIN "assets" "asset" ON "asset"."id" = "exif"."assetId" AND ("asset"."deletedAt" IS NULL) WHERE "asset"."ownerId" IN ($1) - AND "exif"."country" = $2 - AND "exif"."state" = $3 + AND "exif"."city" != '' + AND "exif"."city" IS NOT NULL -- SearchRepository.getCameraMakes SELECT DISTINCT ON ("exif"."make") "exif"."make" AS "make" FROM "exif" "exif" - LEFT JOIN "assets" "asset" ON "asset"."id" = "exif"."assetId" + INNER JOIN "assets" "asset" ON "asset"."id" = "exif"."assetId" AND ("asset"."deletedAt" IS NULL) WHERE "asset"."ownerId" IN ($1) - AND "exif"."model" = $2 + AND "exif"."make" != '' + AND "exif"."make" IS NOT NULL -- SearchRepository.getCameraModels SELECT DISTINCT ON ("exif"."model") "exif"."model" AS "model" FROM "exif" "exif" - LEFT JOIN "assets" "asset" ON "asset"."id" = "exif"."assetId" + INNER JOIN "assets" "asset" ON "asset"."id" = "exif"."assetId" AND ("asset"."deletedAt" IS NULL) WHERE "asset"."ownerId" IN ($1) - AND "exif"."make" = $2 + AND "exif"."model" != '' + AND "exif"."model" IS NOT NULL diff --git a/server/src/queries/user.repository.sql b/server/src/queries/user.repository.sql index ab0a6cc534bd0..c35dc540cef42 100644 --- a/server/src/queries/user.repository.sql +++ b/server/src/queries/user.repository.sql @@ -140,7 +140,23 @@ SELECT "assets"."libraryId" IS NULL ), 0 - ) AS "usage" + ) AS "usage", + COALESCE( + SUM("exif"."fileSizeInByte") FILTER ( + WHERE + "assets"."libraryId" IS NULL + AND "assets"."type" = 'IMAGE' + ), + 0 + ) AS "usagePhotos", + COALESCE( + SUM("exif"."fileSizeInByte") FILTER ( + WHERE + "assets"."libraryId" IS NULL + AND "assets"."type" = 'VIDEO' + ), + 0 + ) AS "usageVideos" FROM "users" "users" LEFT JOIN "assets" "assets" ON "assets"."ownerId" = "users"."id" diff --git a/server/src/repositories/asset.repository.ts b/server/src/repositories/asset.repository.ts index a50dd0f79c016..33d1e2457eb85 100644 --- a/server/src/repositories/asset.repository.ts +++ b/server/src/repositories/asset.repository.ts @@ -5,7 +5,6 @@ import { AssetFileEntity } from 'src/entities/asset-files.entity'; import { AssetJobStatusEntity } from 'src/entities/asset-job-status.entity'; import { AssetEntity } from 'src/entities/asset.entity'; import { ExifEntity } from 'src/entities/exif.entity'; -import { SmartInfoEntity } from 'src/entities/smart-info.entity'; import { AssetFileType, AssetOrder, AssetStatus, AssetType, PaginationMode } from 'src/enum'; import { AssetBuilderOptions, @@ -18,6 +17,7 @@ import { AssetUpdateAllOptions, AssetUpdateDuplicateOptions, AssetUpdateOptions, + DayOfYearAssets, IAssetRepository, LivePhotoSearchOptions, MonthDay, @@ -60,7 +60,6 @@ export class AssetRepository implements IAssetRepository { @InjectRepository(AssetFileEntity) private fileRepository: Repository, @InjectRepository(ExifEntity) private exifRepository: Repository, @InjectRepository(AssetJobStatusEntity) private jobStatusRepository: Repository, - @InjectRepository(SmartInfoEntity) private smartInfoRepository: Repository, ) {} async upsertExif(exif: Partial): Promise { @@ -76,8 +75,8 @@ export class AssetRepository implements IAssetRepository { } @GenerateSql({ params: [[DummyValue.UUID], { day: 1, month: 1 }] }) - getByDayOfYear(ownerIds: string[], { day, month }: MonthDay): Promise { - return this.repository + async getByDayOfYear(ownerIds: string[], { day, month }: MonthDay): Promise { + const assets = await this.repository .createQueryBuilder('entity') .where( `entity.ownerId IN (:...ownerIds) @@ -92,9 +91,25 @@ export class AssetRepository implements IAssetRepository { }, ) .leftJoinAndSelect('entity.exifInfo', 'exifInfo') - .leftJoinAndSelect('entity.files', 'files') + .innerJoinAndSelect('entity.files', 'files') + .andWhere('files.type = :type', { type: AssetFileType.THUMBNAIL }) + .andWhere( + `EXTRACT(YEAR FROM CURRENT_DATE AT TIME ZONE 'UTC') - EXTRACT(YEAR FROM entity.localDateTime AT TIME ZONE 'UTC') > 0`, + ) .orderBy('entity.fileCreatedAt', 'ASC') .getMany(); + + const groups: Record = {}; + const currentYear = new Date().getFullYear(); + for (const asset of assets) { + const yearsAgo = currentYear - asset.localDateTime.getFullYear(); + if (!groups[yearsAgo]) { + groups[yearsAgo] = { yearsAgo, assets: [] }; + } + groups[yearsAgo].assets.push(asset); + } + + return Object.values(groups); } @GenerateSql({ params: [[DummyValue.UUID]] }) @@ -119,7 +134,6 @@ export class AssetRepository implements IAssetRepository { where: { id: In(ids) }, relations: { exifInfo: true, - smartInfo: true, tags: true, faces: { person: true, @@ -422,22 +436,6 @@ export class AssetRepository implements IAssetRepository { break; } - case WithoutProperty.OBJECT_TAGS: { - relations = { - smartInfo: true, - }; - where = { - jobStatus: { - previewAt: Not(IsNull()), - }, - isVisible: true, - smartInfo: { - tags: IsNull(), - }, - }; - break; - } - case WithoutProperty.FACES: { relations = { faces: true, @@ -457,23 +455,6 @@ export class AssetRepository implements IAssetRepository { break; } - case WithoutProperty.PERSON: { - relations = { - faces: true, - }; - where = { - jobStatus: { - previewAt: Not(IsNull()), - }, - isVisible: true, - faces: { - assetId: Not(IsNull()), - personId: IsNull(), - }, - }; - break; - } - case WithoutProperty.SIDECAR: { where = [ { sidecarPath: IsNull(), isVisible: true }, @@ -611,35 +592,6 @@ export class AssetRepository implements IAssetRepository { return { fieldName: 'exifInfo.city', items }; } - @GenerateSql({ params: [DummyValue.UUID, { minAssetsPerField: 5, maxFields: 12 }] }) - async getAssetIdByTag( - ownerId: string, - { minAssetsPerField, maxFields }: AssetExploreFieldOptions, - ): Promise> { - const cte = this.smartInfoRepository - .createQueryBuilder('si') - .select('unnest(tags)', 'tag') - .groupBy('tag') - .having('count(*) >= :minAssetsPerField', { minAssetsPerField }); - - const items = await this.getBuilder({ - userIds: [ownerId], - exifInfo: false, - assetType: AssetType.IMAGE, - isArchived: false, - }) - .select('unnest(si.tags)', 'value') - .addSelect('asset.id', 'data') - .distinctOn(['unnest(si.tags)']) - .innerJoin('smart_info', 'si', 'asset.id = si."assetId"') - .addCommonTableExpression(cte, 'random_tags') - .innerJoin('random_tags', 't', 'si.tags @> ARRAY[t.tag]') - .limit(maxFields) - .getRawMany(); - - return { fieldName: 'smartInfo.tags', items }; - } - private getBuilder(options: AssetBuilderOptions) { const builder = this.repository.createQueryBuilder('asset').where('asset.isVisible = true'); diff --git a/server/src/repositories/config.repository.ts b/server/src/repositories/config.repository.ts index 76b0bb0c83b18..a8a1c9972b3d5 100644 --- a/server/src/repositories/config.repository.ts +++ b/server/src/repositories/config.repository.ts @@ -1,10 +1,10 @@ -import { Injectable } from '@nestjs/common'; +import { Inject, Injectable, Optional } from '@nestjs/common'; import { plainToInstance } from 'class-transformer'; import { validateSync } from 'class-validator'; import { Request, Response } from 'express'; import { CLS_ID } from 'nestjs-cls'; import { join, resolve } from 'node:path'; -import { citiesFile, excludePaths } from 'src/constants'; +import { citiesFile, excludePaths, IWorker } from 'src/constants'; import { Telemetry } from 'src/decorators'; import { EnvDto } from 'src/dtos/env.dto'; import { ImmichEnvironment, ImmichHeader, ImmichTelemetry, ImmichWorker } from 'src/enum'; @@ -228,6 +228,8 @@ let cached: EnvData | undefined; @Injectable() @Telemetry({ enabled: false }) export class ConfigRepository implements IConfigRepository { + constructor(@Inject(IWorker) @Optional() private worker?: ImmichWorker) {} + getEnv(): EnvData { if (!cached) { cached = getEnv(); @@ -235,6 +237,10 @@ export class ConfigRepository implements IConfigRepository { return cached; } + + getWorker() { + return this.worker; + } } export const clearEnvCache = () => (cached = undefined); diff --git a/server/src/repositories/cron.repository.ts b/server/src/repositories/cron.repository.ts new file mode 100644 index 0000000000000..fd7589a0343d9 --- /dev/null +++ b/server/src/repositories/cron.repository.ts @@ -0,0 +1,52 @@ +import { Inject, Injectable } from '@nestjs/common'; +import { SchedulerRegistry } from '@nestjs/schedule'; +import { CronJob, CronTime } from 'cron'; +import { CronCreate, CronUpdate, ICronRepository } from 'src/interfaces/cron.interface'; +import { ILoggerRepository } from 'src/interfaces/logger.interface'; + +@Injectable() +export class CronRepository implements ICronRepository { + constructor( + private schedulerRegistry: SchedulerRegistry, + @Inject(ILoggerRepository) private logger: ILoggerRepository, + ) { + this.logger.setContext(CronRepository.name); + } + + create({ name, expression, onTick, start = true }: CronCreate): void { + const job = new CronJob( + expression, + onTick, + // function to run onComplete + undefined, + // whether it should start directly + start, + // timezone + undefined, + // context + undefined, + // runOnInit + undefined, + // utcOffset + undefined, + // prevents memory leaking by automatically stopping when the node process finishes + true, + ); + + this.schedulerRegistry.addCronJob(name, job); + } + + update({ name, expression, start }: CronUpdate): void { + const job = this.schedulerRegistry.getCronJob(name); + if (expression) { + job.setTime(new CronTime(expression)); + } + if (start !== undefined) { + if (start) { + job.start(); + } else { + job.stop(); + } + } + } +} diff --git a/server/src/repositories/event.repository.ts b/server/src/repositories/event.repository.ts index 4451ee09c573a..7de8defe6e9b0 100644 --- a/server/src/repositories/event.repository.ts +++ b/server/src/repositories/event.repository.ts @@ -11,7 +11,8 @@ import { ClassConstructor } from 'class-transformer'; import _ from 'lodash'; import { Server, Socket } from 'socket.io'; import { EventConfig } from 'src/decorators'; -import { MetadataKey } from 'src/enum'; +import { ImmichWorker, MetadataKey } from 'src/enum'; +import { IConfigRepository } from 'src/interfaces/config.interface'; import { ArgsOf, ClientEventMap, @@ -23,6 +24,7 @@ import { ServerEvents, } from 'src/interfaces/event.interface'; import { ILoggerRepository } from 'src/interfaces/logger.interface'; +import { ConfigRepository } from 'src/repositories/config.repository'; import { AuthService } from 'src/services/auth.service'; import { handlePromiseError } from 'src/utils/misc'; @@ -50,6 +52,7 @@ export class EventRepository implements OnGatewayConnection, OnGatewayDisconnect constructor( private moduleRef: ModuleRef, + @Inject(IConfigRepository) private configRepository: ConfigRepository, @Inject(ILoggerRepository) private logger: ILoggerRepository, ) { this.logger.setContext(EventRepository.name); @@ -58,6 +61,10 @@ export class EventRepository implements OnGatewayConnection, OnGatewayDisconnect setup({ services }: { services: ClassConstructor[] }) { const reflector = this.moduleRef.get(Reflector, { strict: false }); const items: Item[] = []; + const worker = this.configRepository.getWorker(); + if (!worker) { + throw new Error('Unable to determine worker type'); + } // discovery for (const Service of services) { @@ -79,6 +86,11 @@ export class EventRepository implements OnGatewayConnection, OnGatewayDisconnect continue; } + const workers = event.workers ?? Object.values(ImmichWorker); + if (!workers.includes(worker)) { + continue; + } + items.push({ event: event.name, priority: event.priority || 0, @@ -133,7 +145,7 @@ export class EventRepository implements OnGatewayConnection, OnGatewayDisconnect await client.leave(client.nsp.name); } - private addHandler(item: EventItem): void { + private addHandler(item: Item): void { const event = item.event; if (!this.emitHandlers[event]) { @@ -143,7 +155,7 @@ export class EventRepository implements OnGatewayConnection, OnGatewayDisconnect this.emitHandlers[event].push(item); } - async emit(event: T, ...args: ArgsOf): Promise { + emit(event: T, ...args: ArgsOf): Promise { return this.onEvent({ name: event, args, server: false }); } diff --git a/server/src/repositories/index.ts b/server/src/repositories/index.ts index e487df503c824..eb6a5d6f71893 100644 --- a/server/src/repositories/index.ts +++ b/server/src/repositories/index.ts @@ -6,6 +6,7 @@ import { IKeyRepository } from 'src/interfaces/api-key.interface'; import { IAssetRepository } from 'src/interfaces/asset.interface'; import { IAuditRepository } from 'src/interfaces/audit.interface'; import { IConfigRepository } from 'src/interfaces/config.interface'; +import { ICronRepository } from 'src/interfaces/cron.interface'; import { ICryptoRepository } from 'src/interfaces/crypto.interface'; import { IDatabaseRepository } from 'src/interfaces/database.interface'; import { IEventRepository } from 'src/interfaces/event.interface'; @@ -44,6 +45,7 @@ import { ApiKeyRepository } from 'src/repositories/api-key.repository'; import { AssetRepository } from 'src/repositories/asset.repository'; import { AuditRepository } from 'src/repositories/audit.repository'; import { ConfigRepository } from 'src/repositories/config.repository'; +import { CronRepository } from 'src/repositories/cron.repository'; import { CryptoRepository } from 'src/repositories/crypto.repository'; import { DatabaseRepository } from 'src/repositories/database.repository'; import { EventRepository } from 'src/repositories/event.repository'; @@ -83,6 +85,7 @@ export const repositories = [ { provide: IAssetRepository, useClass: AssetRepository }, { provide: IAuditRepository, useClass: AuditRepository }, { provide: IConfigRepository, useClass: ConfigRepository }, + { provide: ICronRepository, useClass: CronRepository }, { provide: ICryptoRepository, useClass: CryptoRepository }, { provide: IDatabaseRepository, useClass: DatabaseRepository }, { provide: IEventRepository, useClass: EventRepository }, diff --git a/server/src/repositories/job.repository.ts b/server/src/repositories/job.repository.ts index 131dd770aa43a..c6c2947617c4f 100644 --- a/server/src/repositories/job.repository.ts +++ b/server/src/repositories/job.repository.ts @@ -1,161 +1,121 @@ import { getQueueToken } from '@nestjs/bullmq'; import { Inject, Injectable } from '@nestjs/common'; -import { ModuleRef } from '@nestjs/core'; +import { ModuleRef, Reflector } from '@nestjs/core'; import { SchedulerRegistry } from '@nestjs/schedule'; -import { Job, JobsOptions, Processor, Queue, Worker, WorkerOptions } from 'bullmq'; -import { CronJob, CronTime } from 'cron'; +import { JobsOptions, Queue, Worker } from 'bullmq'; +import { ClassConstructor } from 'class-transformer'; import { setTimeout } from 'node:timers/promises'; +import { JobConfig } from 'src/decorators'; +import { MetadataKey } from 'src/enum'; import { IConfigRepository } from 'src/interfaces/config.interface'; +import { IEventRepository } from 'src/interfaces/event.interface'; import { IEntityJob, IJobRepository, JobCounts, JobItem, JobName, + JobOf, + JobStatus, QueueCleanType, QueueName, QueueStatus, } from 'src/interfaces/job.interface'; import { ILoggerRepository } from 'src/interfaces/logger.interface'; +import { getKeyByValue, getMethodNames, ImmichStartupError } from 'src/utils/misc'; -export const JOBS_TO_QUEUE: Record = { - // misc - [JobName.ASSET_DELETION]: QueueName.BACKGROUND_TASK, - [JobName.ASSET_DELETION_CHECK]: QueueName.BACKGROUND_TASK, - [JobName.USER_DELETE_CHECK]: QueueName.BACKGROUND_TASK, - [JobName.USER_DELETION]: QueueName.BACKGROUND_TASK, - [JobName.DELETE_FILES]: QueueName.BACKGROUND_TASK, - [JobName.CLEAN_OLD_AUDIT_LOGS]: QueueName.BACKGROUND_TASK, - [JobName.CLEAN_OLD_SESSION_TOKENS]: QueueName.BACKGROUND_TASK, - [JobName.PERSON_CLEANUP]: QueueName.BACKGROUND_TASK, - [JobName.USER_SYNC_USAGE]: QueueName.BACKGROUND_TASK, - - // backups - [JobName.BACKUP_DATABASE]: QueueName.BACKUP_DATABASE, - - // conversion - [JobName.QUEUE_VIDEO_CONVERSION]: QueueName.VIDEO_CONVERSION, - [JobName.VIDEO_CONVERSION]: QueueName.VIDEO_CONVERSION, - - // thumbnails - [JobName.QUEUE_GENERATE_THUMBNAILS]: QueueName.THUMBNAIL_GENERATION, - [JobName.GENERATE_THUMBNAILS]: QueueName.THUMBNAIL_GENERATION, - [JobName.GENERATE_PERSON_THUMBNAIL]: QueueName.THUMBNAIL_GENERATION, - - // tags - [JobName.TAG_CLEANUP]: QueueName.BACKGROUND_TASK, - - // metadata - [JobName.QUEUE_METADATA_EXTRACTION]: QueueName.METADATA_EXTRACTION, - [JobName.METADATA_EXTRACTION]: QueueName.METADATA_EXTRACTION, - [JobName.LINK_LIVE_PHOTOS]: QueueName.METADATA_EXTRACTION, - - // storage template - [JobName.STORAGE_TEMPLATE_MIGRATION]: QueueName.STORAGE_TEMPLATE_MIGRATION, - [JobName.STORAGE_TEMPLATE_MIGRATION_SINGLE]: QueueName.STORAGE_TEMPLATE_MIGRATION, - - // migration - [JobName.QUEUE_MIGRATION]: QueueName.MIGRATION, - [JobName.MIGRATE_ASSET]: QueueName.MIGRATION, - [JobName.MIGRATE_PERSON]: QueueName.MIGRATION, - - // facial recognition - [JobName.QUEUE_FACE_DETECTION]: QueueName.FACE_DETECTION, - [JobName.FACE_DETECTION]: QueueName.FACE_DETECTION, - [JobName.QUEUE_FACIAL_RECOGNITION]: QueueName.FACIAL_RECOGNITION, - [JobName.FACIAL_RECOGNITION]: QueueName.FACIAL_RECOGNITION, - - // smart search - [JobName.QUEUE_SMART_SEARCH]: QueueName.SMART_SEARCH, - [JobName.SMART_SEARCH]: QueueName.SMART_SEARCH, - - // duplicate detection - [JobName.QUEUE_DUPLICATE_DETECTION]: QueueName.DUPLICATE_DETECTION, - [JobName.DUPLICATE_DETECTION]: QueueName.DUPLICATE_DETECTION, - - // XMP sidecars - [JobName.QUEUE_SIDECAR]: QueueName.SIDECAR, - [JobName.SIDECAR_DISCOVERY]: QueueName.SIDECAR, - [JobName.SIDECAR_SYNC]: QueueName.SIDECAR, - [JobName.SIDECAR_WRITE]: QueueName.SIDECAR, - - // Library management - [JobName.LIBRARY_SYNC_FILE]: QueueName.LIBRARY, - [JobName.LIBRARY_QUEUE_SYNC_FILES]: QueueName.LIBRARY, - [JobName.LIBRARY_QUEUE_SYNC_ASSETS]: QueueName.LIBRARY, - [JobName.LIBRARY_DELETE]: QueueName.LIBRARY, - [JobName.LIBRARY_SYNC_ASSET]: QueueName.LIBRARY, - [JobName.LIBRARY_QUEUE_SYNC_ALL]: QueueName.LIBRARY, - [JobName.LIBRARY_QUEUE_CLEANUP]: QueueName.LIBRARY, - - // Notification - [JobName.SEND_EMAIL]: QueueName.NOTIFICATION, - [JobName.NOTIFY_ALBUM_INVITE]: QueueName.NOTIFICATION, - [JobName.NOTIFY_ALBUM_UPDATE]: QueueName.NOTIFICATION, - [JobName.NOTIFY_SIGNUP]: QueueName.NOTIFICATION, - - // Version check - [JobName.VERSION_CHECK]: QueueName.BACKGROUND_TASK, - - // Trash - [JobName.QUEUE_TRASH_EMPTY]: QueueName.BACKGROUND_TASK, +type JobMapItem = { + jobName: JobName; + queueName: QueueName; + handler: (job: JobOf) => Promise; + label: string; }; @Injectable() export class JobRepository implements IJobRepository { private workers: Partial> = {}; + private handlers: Partial> = {}; constructor( - private moduleReference: ModuleRef, - private schedulerReqistry: SchedulerRegistry, + private moduleRef: ModuleRef, + private schedulerRegistry: SchedulerRegistry, @Inject(IConfigRepository) private configRepository: IConfigRepository, + @Inject(IEventRepository) private eventRepository: IEventRepository, @Inject(ILoggerRepository) private logger: ILoggerRepository, ) { this.logger.setContext(JobRepository.name); } - addHandler(queueName: QueueName, concurrency: number, handler: (item: JobItem) => Promise) { - const { bull } = this.configRepository.getEnv(); - const workerHandler: Processor = async (job: Job) => handler(job as JobItem); - const workerOptions: WorkerOptions = { ...bull.config, concurrency }; - this.workers[queueName] = new Worker(queueName, workerHandler, workerOptions); - } + setup({ services }: { services: ClassConstructor[] }) { + const reflector = this.moduleRef.get(Reflector, { strict: false }); + + // discovery + for (const Service of services) { + const instance = this.moduleRef.get(Service); + for (const methodName of getMethodNames(instance)) { + const handler = instance[methodName]; + const config = reflector.get(MetadataKey.JOB_CONFIG, handler); + if (!config) { + continue; + } + + const { name: jobName, queue: queueName } = config; + const label = `${Service.name}.${handler.name}`; + + // one handler per job + if (this.handlers[jobName]) { + const jobKey = getKeyByValue(JobName, jobName); + const errorMessage = `Failed to add job handler for ${label}`; + this.logger.error( + `${errorMessage}. JobName.${jobKey} is already handled by ${this.handlers[jobName].label}.`, + ); + throw new ImmichStartupError(errorMessage); + } + + this.handlers[jobName] = { + label, + jobName, + queueName, + handler: handler.bind(instance), + }; + + this.logger.verbose(`Added job handler: ${jobName} => ${label}`); + } + } - addCronJob(name: string, expression: string, onTick: () => void, start = true): void { - const job = new CronJob( - expression, - onTick, - // function to run onComplete - undefined, - // whether it should start directly - start, - // timezone - undefined, - // context - undefined, - // runOnInit - undefined, - // utcOffset - undefined, - // prevents memory leaking by automatically stopping when the node process finishes - true, - ); - - this.schedulerReqistry.addCronJob(name, job); + // no missing handlers + for (const [jobKey, jobName] of Object.entries(JobName)) { + const item = this.handlers[jobName]; + if (!item) { + const errorMessage = `Failed to find job handler for Job.${jobKey} ("${jobName}")`; + this.logger.error( + `${errorMessage}. Make sure to add the @OnJob({ name: JobName.${jobKey}, queue: QueueName.XYZ }) decorator for the new job.`, + ); + throw new ImmichStartupError(errorMessage); + } + } } - updateCronJob(name: string, expression?: string, start?: boolean): void { - const job = this.schedulerReqistry.getCronJob(name); - if (expression) { - job.setTime(new CronTime(expression)); + startWorkers() { + const { bull } = this.configRepository.getEnv(); + for (const queueName of Object.values(QueueName)) { + this.logger.debug(`Starting worker for queue: ${queueName}`); + this.workers[queueName] = new Worker( + queueName, + (job) => this.eventRepository.emit('job.start', queueName, job as JobItem), + { ...bull.config, concurrency: 1 }, + ); } - if (start !== undefined) { - if (start) { - job.start(); - } else { - job.stop(); - } + } + + async run({ name, data }: JobItem) { + const item = this.handlers[name as JobName]; + if (!item) { + this.logger.warn(`Skipping unknown job: "${name}"`); + return JobStatus.SKIPPED; } + + return item.handler(data); } setConcurrency(queueName: QueueName, concurrency: number) { @@ -204,6 +164,10 @@ export class JobRepository implements IJobRepository { ) as unknown as Promise; } + private getQueueName(name: JobName) { + return (this.handlers[name] as JobMapItem).queueName; + } + async queueAll(items: JobItem[]): Promise { if (items.length === 0) { return; @@ -212,7 +176,7 @@ export class JobRepository implements IJobRepository { const promises = []; const itemsByQueue = {} as Record; for (const item of items) { - const queueName = JOBS_TO_QUEUE[item.name]; + const queueName = this.getQueueName(item.name); const job = { name: item.name, data: item.data || {}, @@ -273,11 +237,11 @@ export class JobRepository implements IJobRepository { } private getQueue(queue: QueueName): Queue { - return this.moduleReference.get(getQueueToken(queue), { strict: false }); + return this.moduleRef.get(getQueueToken(queue), { strict: false }); } public async removeJob(jobId: string, name: JobName): Promise { - const existingJob = await this.getQueue(JOBS_TO_QUEUE[name]).getJob(jobId); + const existingJob = await this.getQueue(this.getQueueName(name)).getJob(jobId); if (!existingJob) { return; } diff --git a/server/src/repositories/machine-learning.repository.ts b/server/src/repositories/machine-learning.repository.ts index 74b17ca6a754f..56cdf30a1e48d 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 { Inject, Injectable } from '@nestjs/common'; import { readFile } from 'node:fs/promises'; import { CLIPConfig } from 'src/dtos/model-config.dto'; +import { ILoggerRepository } from 'src/interfaces/logger.interface'; import { ClipTextualResponse, ClipVisualResponse, @@ -13,33 +14,42 @@ import { ModelType, } from 'src/interfaces/machine-learning.interface'; -const errorPrefix = 'Machine learning request'; - @Injectable() export class MachineLearningRepository implements IMachineLearningRepository { - private async predict(url: string, payload: ModelPayload, config: MachineLearningRequest): Promise { - const formData = await this.getFormData(payload, config); + constructor(@Inject(ILoggerRepository) private logger: ILoggerRepository) { + this.logger.setContext(MachineLearningRepository.name); + } - const res = await fetch(new URL('/predict', url), { method: 'POST', body: formData }).catch( - (error: Error | any) => { - throw new Error(`${errorPrefix} to "${url}" failed with ${error?.cause || error}`); - }, - ); + private async predict(urls: string[], payload: ModelPayload, config: MachineLearningRequest): Promise { + const formData = await this.getFormData(payload, config); + for (const url of urls) { + try { + const response = await fetch(new URL('/predict', url), { method: 'POST', body: formData }); + if (response.ok) { + return response.json(); + } - if (res.status >= 400) { - throw new Error(`${errorPrefix} '${JSON.stringify(config)}' failed with status ${res.status}: ${res.statusText}`); + this.logger.warn( + `Machine learning request to "${url}" failed with status ${response.status}: ${response.statusText}`, + ); + } catch (error: Error | unknown) { + this.logger.warn( + `Machine learning request to "${url}" failed: ${error instanceof Error ? error.message : error}`, + ); + } } - return res.json(); + + throw new Error(`Machine learning request '${JSON.stringify(config)}' failed for all URLs`); } - async detectFaces(url: string, imagePath: string, { modelName, minScore }: FaceDetectionOptions) { + async detectFaces(urls: string[], imagePath: string, { modelName, minScore }: FaceDetectionOptions) { const request = { [ModelTask.FACIAL_RECOGNITION]: { [ModelType.DETECTION]: { modelName, options: { minScore } }, [ModelType.RECOGNITION]: { modelName }, }, }; - const response = await this.predict(url, { imagePath }, request); + const response = await this.predict(urls, { imagePath }, request); return { imageHeight: response.imageHeight, imageWidth: response.imageWidth, @@ -47,15 +57,15 @@ export class MachineLearningRepository implements IMachineLearningRepository { }; } - async encodeImage(url: string, imagePath: string, { modelName }: CLIPConfig) { + async encodeImage(urls: string[], imagePath: string, { modelName }: CLIPConfig) { const request = { [ModelTask.SEARCH]: { [ModelType.VISUAL]: { modelName } } }; - const response = await this.predict(url, { imagePath }, request); + const response = await this.predict(urls, { imagePath }, request); return response[ModelTask.SEARCH]; } - async encodeText(url: string, text: string, { modelName }: CLIPConfig) { + async encodeText(urls: string[], text: string, { modelName }: CLIPConfig) { const request = { [ModelTask.SEARCH]: { [ModelType.TEXTUAL]: { modelName } } }; - const response = await this.predict(url, { text }, request); + const response = await this.predict(urls, { text }, request); return response[ModelTask.SEARCH]; } diff --git a/server/src/repositories/map.repository.ts b/server/src/repositories/map.repository.ts index 7ad94016e8667..348736a33d4c5 100644 --- a/server/src/repositories/map.repository.ts +++ b/server/src/repositories/map.repository.ts @@ -1,14 +1,18 @@ import { Inject, Injectable } from '@nestjs/common'; import { InjectDataSource, InjectRepository } from '@nestjs/typeorm'; import { getName } from 'i18n-iso-countries'; +import { randomUUID } from 'node:crypto'; import { createReadStream, existsSync } from 'node:fs'; import { readFile } from 'node:fs/promises'; import readLine from 'node:readline'; import { citiesFile } from 'src/constants'; import { AssetEntity } from 'src/entities/asset.entity'; -import { GeodataPlacesEntity } from 'src/entities/geodata-places.entity'; -import { NaturalEarthCountriesEntity } from 'src/entities/natural-earth-countries.entity'; -import { SystemMetadataKey } from 'src/enum'; +import { GeodataPlacesEntity, GeodataPlacesTempEntity } from 'src/entities/geodata-places.entity'; +import { + NaturalEarthCountriesEntity, + NaturalEarthCountriesTempEntity, +} from 'src/entities/natural-earth-countries.entity'; +import { LogLevel, SystemMetadataKey } from 'src/enum'; import { IConfigRepository } from 'src/interfaces/config.interface'; import { ILoggerRepository } from 'src/interfaces/logger.interface'; import { @@ -20,7 +24,7 @@ import { } from 'src/interfaces/map.interface'; import { ISystemMetadataRepository } from 'src/interfaces/system-metadata.interface'; import { OptionalBetween } from 'src/utils/database'; -import { DataSource, In, IsNull, Not, QueryRunner, Repository } from 'typeorm'; +import { DataSource, In, IsNull, Not, Repository } from 'typeorm'; import { QueryDeepPartialEntity } from 'typeorm/query-builder/QueryPartialEntity.js'; @Injectable() @@ -49,8 +53,7 @@ export class MapRepository implements IMapRepository { return; } - await this.importGeodata(); - await this.importNaturalEarthCountries(); + await Promise.all([this.importGeodata(), this.importNaturalEarthCountries()]); await this.metadataRepository.set(SystemMetadataKey.REVERSE_GEOCODING_STATE, { lastUpdate: geodataDate, @@ -116,13 +119,18 @@ export class MapRepository implements IMapRepository { const response = await this.geodataPlacesRepository .createQueryBuilder('geoplaces') - .where('earth_box(ll_to_earth(:latitude, :longitude), 25000) @> "earthCoord"', point) - .orderBy('earth_distance(ll_to_earth(:latitude, :longitude), "earthCoord")') + .where( + 'earth_box(ll_to_earth_public(:latitude, :longitude), 25000) @> ll_to_earth_public(latitude, longitude)', + point, + ) + .orderBy('earth_distance(ll_to_earth_public(:latitude, :longitude), ll_to_earth_public(latitude, longitude))') .limit(1) .getOne(); if (response) { - this.logger.verbose(`Raw: ${JSON.stringify(response, null, 2)}`); + if (this.logger.isLevelEnabled(LogLevel.VERBOSE)) { + this.logger.verbose(`Raw: ${JSON.stringify(response, null, 2)}`); + } const { countryCode, name: city, admin1Name } = response; const country = getName(countryCode, 'en') ?? null; @@ -149,8 +157,9 @@ export class MapRepository implements IMapRepository { return { country: null, state: null, city: null }; } - this.logger.verbose(`Raw: ${JSON.stringify(ne_response, ['id', 'admin', 'admin_a3', 'type'], 2)}`); - + if (this.logger.isLevelEnabled(LogLevel.VERBOSE)) { + this.logger.verbose(`Raw: ${JSON.stringify(ne_response, ['id', 'admin', 'admin_a3', 'type'], 2)}`); + } const { admin_a3 } = ne_response; const country = getName(admin_a3, 'en') ?? null; const state = null; @@ -159,146 +168,119 @@ export class MapRepository implements IMapRepository { return { country, state, city }; } - private transformCoordinatesToPolygon(coordinates: number[][][]): string { - const pointsString = coordinates.map((point) => `(${point[0]},${point[1]})`).join(', '); - return `(${pointsString})`; - } - private async importNaturalEarthCountries() { - const queryRunner = this.dataSource.createQueryRunner(); - await queryRunner.connect(); - const { resourcePaths } = this.configRepository.getEnv(); + const geoJSONData = JSON.parse(await readFile(resourcePaths.geodata.naturalEarthCountriesPath, 'utf8')); + if (geoJSONData.type !== 'FeatureCollection' || !Array.isArray(geoJSONData.features)) { + this.logger.fatal('Invalid GeoJSON FeatureCollection'); + return; + } - try { - await queryRunner.startTransaction(); - await queryRunner.manager.clear(NaturalEarthCountriesEntity); - - const fileContent = await readFile(resourcePaths.geodata.naturalEarthCountriesPath, 'utf8'); - const geoJSONData = JSON.parse(fileContent); - - if (geoJSONData.type !== 'FeatureCollection' || !Array.isArray(geoJSONData.features)) { - this.logger.fatal('Invalid GeoJSON FeatureCollection'); - return; - } - - for await (const feature of geoJSONData.features) { - for (const polygon of feature.geometry.coordinates) { - const featureRecord = new NaturalEarthCountriesEntity(); - featureRecord.admin = feature.properties.ADMIN; - featureRecord.admin_a3 = feature.properties.ADM0_A3; - featureRecord.type = feature.properties.TYPE; - - if (feature.geometry.type === 'MultiPolygon') { - featureRecord.coordinates = this.transformCoordinatesToPolygon(polygon[0]); - await queryRunner.manager.save(featureRecord); - } else if (feature.geometry.type === 'Polygon') { - featureRecord.coordinates = this.transformCoordinatesToPolygon(polygon); - await queryRunner.manager.save(featureRecord); - break; - } + await this.dataSource.query('DROP TABLE IF EXISTS naturalearth_countries_tmp'); + await this.dataSource.query( + 'CREATE UNLOGGED TABLE naturalearth_countries_tmp (LIKE naturalearth_countries INCLUDING ALL EXCLUDING INDEXES)', + ); + const entities: Omit[] = []; + for (const feature of geoJSONData.features) { + for (const entry of feature.geometry.coordinates) { + const coordinates: number[][][] = feature.geometry.type === 'MultiPolygon' ? entry[0] : entry; + const featureRecord: Omit = { + admin: feature.properties.ADMIN, + admin_a3: feature.properties.ADM0_A3, + type: feature.properties.TYPE, + coordinates: `(${coordinates.map((point) => `(${point[0]},${point[1]})`).join(', ')})`, + }; + entities.push(featureRecord); + if (feature.geometry.type === 'Polygon') { + break; } } - - await queryRunner.commitTransaction(); - } catch (error) { - this.logger.fatal('Error importing natural earth country data', error); - await queryRunner.rollbackTransaction(); - throw error; - } finally { - await queryRunner.release(); } + await this.dataSource.manager.insert(NaturalEarthCountriesTempEntity, entities); + + await this.dataSource.query(`ALTER TABLE naturalearth_countries_tmp ADD PRIMARY KEY (id) WITH (FILLFACTOR = 100)`); + + await this.dataSource.transaction(async (manager) => { + await manager.query('ALTER TABLE naturalearth_countries RENAME TO naturalearth_countries_old'); + await manager.query('ALTER TABLE naturalearth_countries_tmp RENAME TO naturalearth_countries'); + await manager.query('DROP TABLE naturalearth_countries_old'); + }); } private async importGeodata() { - const queryRunner = this.dataSource.createQueryRunner(); - await queryRunner.connect(); - const { resourcePaths } = this.configRepository.getEnv(); - const admin1 = await this.loadAdmin(resourcePaths.geodata.admin1); - const admin2 = await this.loadAdmin(resourcePaths.geodata.admin2); - - try { - await queryRunner.startTransaction(); - - await queryRunner.manager.clear(GeodataPlacesEntity); - await this.loadCities500(queryRunner, admin1, admin2); - - await queryRunner.commitTransaction(); - } catch (error) { - this.logger.fatal('Error importing geodata', error); - await queryRunner.rollbackTransaction(); - throw error; - } finally { - await queryRunner.release(); - } + const [admin1, admin2] = await Promise.all([ + this.loadAdmin(resourcePaths.geodata.admin1), + this.loadAdmin(resourcePaths.geodata.admin2), + ]); + + await this.dataSource.query('DROP TABLE IF EXISTS geodata_places_tmp'); + await this.dataSource.query( + 'CREATE UNLOGGED TABLE geodata_places_tmp (LIKE geodata_places INCLUDING ALL EXCLUDING INDEXES)', + ); + await this.loadCities500(admin1, admin2); + await this.createGeodataIndices(); + + await this.dataSource.transaction(async (manager) => { + await manager.query('ALTER TABLE geodata_places RENAME TO geodata_places_old'); + await manager.query('ALTER TABLE geodata_places_tmp RENAME TO geodata_places'); + await manager.query('DROP TABLE geodata_places_old'); + }); } - private async loadGeodataToTableFromFile( - queryRunner: QueryRunner, - lineToEntityMapper: (lineSplit: string[]) => GeodataPlacesEntity, - filePath: string, - options?: { entityFilter?: (linesplit: string[]) => boolean }, - ) { - const _entityFilter = options?.entityFilter ?? (() => true); - if (!existsSync(filePath)) { - this.logger.error(`Geodata file ${filePath} not found`); - throw new Error(`Geodata file ${filePath} not found`); + private async loadCities500(admin1Map: Map, admin2Map: Map) { + const { resourcePaths } = this.configRepository.getEnv(); + const cities500 = resourcePaths.geodata.cities500; + if (!existsSync(cities500)) { + throw new Error(`Geodata file ${cities500} not found`); } - const input = createReadStream(filePath); - let bufferGeodata: QueryDeepPartialEntity[] = []; + const input = createReadStream(cities500, { highWaterMark: 512 * 1024 * 1024 }); + let bufferGeodata: QueryDeepPartialEntity[] = []; const lineReader = readLine.createInterface({ input }); + let count = 0; + let futures = []; for await (const line of lineReader) { const lineSplit = line.split('\t'); - if (!_entityFilter(lineSplit)) { + if (lineSplit[7] === 'PPLX' && lineSplit[8] !== 'AU') { continue; } - const geoData = lineToEntityMapper(lineSplit); + + const geoData = { + id: Number.parseInt(lineSplit[0]), + name: lineSplit[1], + alternateNames: lineSplit[3], + latitude: Number.parseFloat(lineSplit[4]), + longitude: Number.parseFloat(lineSplit[5]), + countryCode: lineSplit[8], + admin1Code: lineSplit[10], + admin2Code: lineSplit[11], + modificationDate: lineSplit[18], + admin1Name: admin1Map.get(`${lineSplit[8]}.${lineSplit[10]}`), + admin2Name: admin2Map.get(`${lineSplit[8]}.${lineSplit[10]}.${lineSplit[11]}`), + }; bufferGeodata.push(geoData); - if (bufferGeodata.length > 1000) { - await queryRunner.manager.upsert(GeodataPlacesEntity, bufferGeodata, ['id']); + if (bufferGeodata.length >= 5000) { + const curLength = bufferGeodata.length; + futures.push( + this.dataSource.manager.insert(GeodataPlacesTempEntity, bufferGeodata).then(() => { + count += curLength; + if (count % 10_000 === 0) { + this.logger.log(`${count} geodata records imported`); + } + }), + ); bufferGeodata = []; + // leave spare connection for other queries + if (futures.length >= 9) { + await Promise.all(futures); + futures = []; + } } } - await queryRunner.manager.upsert(GeodataPlacesEntity, bufferGeodata, ['id']); - } - private async loadCities500( - queryRunner: QueryRunner, - admin1Map: Map, - admin2Map: Map, - ) { - const { resourcePaths } = this.configRepository.getEnv(); - await this.loadGeodataToTableFromFile( - queryRunner, - (lineSplit: string[]) => - this.geodataPlacesRepository.create({ - id: Number.parseInt(lineSplit[0]), - name: lineSplit[1], - alternateNames: lineSplit[3], - latitude: Number.parseFloat(lineSplit[4]), - longitude: Number.parseFloat(lineSplit[5]), - countryCode: lineSplit[8], - admin1Code: lineSplit[10], - admin2Code: lineSplit[11], - modificationDate: lineSplit[18], - admin1Name: admin1Map.get(`${lineSplit[8]}.${lineSplit[10]}`), - admin2Name: admin2Map.get(`${lineSplit[8]}.${lineSplit[10]}.${lineSplit[11]}`), - }), - resourcePaths.geodata.cities500, - { - entityFilter: (lineSplit) => { - if (lineSplit[7] === 'PPLX') { - // Exclude populated subsections of cities that are not in Australia. - // Australia has a lot of PPLX areas, so we include them. - return lineSplit[8] === 'AU'; - } - return true; - }, - }, - ); + await this.dataSource.manager.insert(GeodataPlacesTempEntity, bufferGeodata); } private async loadAdmin(filePath: string) { @@ -307,7 +289,7 @@ export class MapRepository implements IMapRepository { throw new Error(`Geodata file ${filePath} not found`); } - const input = createReadStream(filePath); + const input = createReadStream(filePath, { highWaterMark: 512 * 1024 * 1024 }); const lineReader = readLine.createInterface({ input }); const adminMap = new Map(); @@ -318,4 +300,27 @@ export class MapRepository implements IMapRepository { return adminMap; } + + private createGeodataIndices() { + return Promise.all([ + this.dataSource.query(`ALTER TABLE geodata_places_tmp ADD PRIMARY KEY (id) WITH (FILLFACTOR = 100)`), + this.dataSource.query(` + CREATE INDEX IDX_geodata_gist_earthcoord_${randomUUID().replaceAll('-', '_')} + ON geodata_places_tmp + USING gist (ll_to_earth_public(latitude, longitude)) + WITH (fillfactor = 100)`), + this.dataSource.query(` + CREATE INDEX idx_geodata_places_name_${randomUUID().replaceAll('-', '_')} + ON geodata_places_tmp + USING gin (f_unaccent(name) gin_trgm_ops)`), + this.dataSource.query(` + CREATE INDEX idx_geodata_places_admin1_name_${randomUUID().replaceAll('-', '_')} + ON geodata_places_tmp + USING gin (f_unaccent("admin1Name") gin_trgm_ops)`), + this.dataSource.query(` + CREATE INDEX idx_geodata_places_admin2_name_${randomUUID().replaceAll('-', '_')} + ON geodata_places_tmp + USING gin (f_unaccent("admin2Name") gin_trgm_ops)`), + ]); + } } diff --git a/server/src/repositories/media.repository.ts b/server/src/repositories/media.repository.ts index d76d226f44c2b..8dcbf208c6ae8 100644 --- a/server/src/repositories/media.repository.ts +++ b/server/src/repositories/media.repository.ts @@ -5,6 +5,7 @@ import { Duration } from 'luxon'; import fs from 'node:fs/promises'; import { Writable } from 'node:stream'; import sharp from 'sharp'; +import { ORIENTATION_TO_SHARP_ROTATION } from 'src/constants'; import { Colorspace, LogLevel } from 'src/enum'; import { ILoggerRepository } from 'src/interfaces/logger.interface'; import { @@ -82,7 +83,15 @@ export class MediaRepository implements IMediaRepository { .withIccProfile(options.colorspace); if (!options.raw) { - pipeline = pipeline.rotate(); + const { angle, flip, flop } = options.orientation ? ORIENTATION_TO_SHARP_ROTATION[options.orientation] : {}; + pipeline = pipeline.rotate(angle); + if (flip) { + pipeline = pipeline.flip(); + } + + if (flop) { + pipeline = pipeline.flop(); + } } if (options.crop) { @@ -126,6 +135,7 @@ export class MediaRepository implements IMediaRepository { rotation: this.parseInt(stream.rotation), isHDR: stream.color_transfer === 'smpte2084' || stream.color_transfer === 'arib-std-b67', bitrate: this.parseInt(stream.bit_rate), + pixelFormat: stream.pix_fmt || 'yuv420p', })), audioStreams: results.streams .filter((stream) => stream.codec_type === 'audio') diff --git a/server/src/repositories/notification.repository.spec.ts b/server/src/repositories/notification.repository.spec.ts new file mode 100644 index 0000000000000..368ba3f0ce3ff --- /dev/null +++ b/server/src/repositories/notification.repository.spec.ts @@ -0,0 +1,78 @@ +import { ILoggerRepository } from 'src/interfaces/logger.interface'; +import { EmailRenderRequest, EmailTemplate } from 'src/interfaces/notification.interface'; +import { NotificationRepository } from 'src/repositories/notification.repository'; +import { Mocked } from 'vitest'; + +describe(NotificationRepository.name, () => { + let sut: NotificationRepository; + let loggerMock: Mocked; + + beforeEach(() => { + loggerMock = { + setContext: vitest.fn(), + debug: vitest.fn(), + } as unknown as Mocked; + + sut = new NotificationRepository(loggerMock); + }); + + describe('renderEmail', () => { + it('should render the email correctly for TEST_EMAIL template', async () => { + const request: EmailRenderRequest = { + template: EmailTemplate.TEST_EMAIL, + data: { displayName: 'Alen Turing', baseUrl: 'http://localhost' }, + customTemplate: '', + }; + + const result = await sut.renderEmail(request); + + expect(result.html).toContain(' { + const request: EmailRenderRequest = { + template: EmailTemplate.WELCOME, + data: { displayName: 'Alen Turing', username: 'turing', baseUrl: 'http://localhost' }, + customTemplate: '', + }; + + const result = await sut.renderEmail(request); + + expect(result.html).toContain(' { + const request: EmailRenderRequest = { + template: EmailTemplate.ALBUM_INVITE, + data: { + albumName: 'Vacation', + albumId: '123', + senderName: 'John', + recipientName: 'Jane', + baseUrl: 'http://localhost', + }, + customTemplate: '', + }; + + const result = await sut.renderEmail(request); + + expect(result.html).toContain(' { + const request: EmailRenderRequest = { + template: EmailTemplate.ALBUM_UPDATE, + data: { albumName: 'Holiday', albumId: '123', recipientName: 'Jane', baseUrl: 'http://localhost' }, + customTemplate: '', + }; + + const result = await sut.renderEmail(request); + + expect(result.html).toContain(' { + private render({ template, data, customTemplate }: EmailRenderRequest): React.FunctionComponentElement { switch (template) { case EmailTemplate.TEST_EMAIL: { - return React.createElement(TestEmail, data); + return React.createElement(TestEmail, { ...data, customTemplate }); } case EmailTemplate.WELCOME: { - return React.createElement(WelcomeEmail, data); + return React.createElement(WelcomeEmail, { ...data, customTemplate }); } case EmailTemplate.ALBUM_INVITE: { - return React.createElement(AlbumInviteEmail, data); + return React.createElement(AlbumInviteEmail, { ...data, customTemplate }); } case EmailTemplate.ALBUM_UPDATE: { - return React.createElement(AlbumUpdateEmail, data); + return React.createElement(AlbumUpdateEmail, { ...data, customTemplate }); } } } diff --git a/server/src/repositories/person.repository.ts b/server/src/repositories/person.repository.ts index 56116d7b3bf97..4229286706619 100644 --- a/server/src/repositories/person.repository.ts +++ b/server/src/repositories/person.repository.ts @@ -83,10 +83,14 @@ export class PersonRepository implements IPersonRepository { } @GenerateSql({ params: [{ take: 10, skip: 10 }, DummyValue.UUID] }) - getAllForUser(pagination: PaginationOptions, userId: string, options?: PersonSearchOptions): Paginated { + async getAllForUser( + pagination: PaginationOptions, + userId: string, + options?: PersonSearchOptions, + ): Paginated { const queryBuilder = this.personRepository .createQueryBuilder('person') - .leftJoin('person.faces', 'face') + .innerJoin('person.faces', 'face') .where('person.ownerId = :userId', { userId }) .innerJoin('face.asset', 'asset') .andWhere('asset.isArchived = false') @@ -95,13 +99,24 @@ export class PersonRepository implements IPersonRepository { .addOrderBy('COUNT(face.assetId)', 'DESC') .addOrderBy("NULLIF(person.name, '')", 'ASC', 'NULLS LAST') .addOrderBy('person.createdAt') - .andWhere("person.thumbnailPath != ''") .having("person.name != '' OR COUNT(face.assetId) >= :faces", { faces: options?.minimumFaceCount || 1 }) .groupBy('person.id'); + if (options?.closestFaceAssetId) { + const innerQueryBuilder = this.faceSearchRepository + .createQueryBuilder('face_search') + .select('embedding', 'embedding') + .where('"face_search"."faceId" = "person"."faceAssetId"'); + const faceSelectQueryBuilder = this.faceSearchRepository + .createQueryBuilder('face_search') + .select('embedding', 'embedding') + .where('"face_search"."faceId" = :faceId', { faceId: options.closestFaceAssetId }); + queryBuilder + .orderBy('(' + innerQueryBuilder.getQuery() + ') <=> (' + faceSelectQueryBuilder.getQuery() + ')') + .setParameters(faceSelectQueryBuilder.getParameters()); + } if (!options?.withHidden) { queryBuilder.andWhere('person.isHidden = false'); } - return paginatedBuilder(queryBuilder, { mode: PaginationMode.LIMIT_OFFSET, ...pagination, @@ -232,14 +247,12 @@ export class PersonRepository implements IPersonRepository { async getNumberOfPeople(userId: string): Promise { const items = await this.personRepository .createQueryBuilder('person') - .leftJoin('person.faces', 'face') + .innerJoin('person.faces', 'face') .where('person.ownerId = :userId', { userId }) .innerJoin('face.asset', 'asset') .andWhere('asset.isArchived = false') - .andWhere("person.thumbnailPath != ''") .select('COUNT(DISTINCT(person.id))', 'total') .addSelect('COUNT(DISTINCT(person.id)) FILTER (WHERE person.isHidden = true)', 'hidden') - .having('COUNT(face.assetId) != 0') .getRawOne(); if (items == undefined) { diff --git a/server/src/repositories/search.repository.ts b/server/src/repositories/search.repository.ts index b5969beecb68d..0a529f2f6ee57 100644 --- a/server/src/repositories/search.repository.ts +++ b/server/src/repositories/search.repository.ts @@ -6,7 +6,6 @@ import { AssetFaceEntity } from 'src/entities/asset-face.entity'; import { AssetEntity } from 'src/entities/asset.entity'; import { ExifEntity } from 'src/entities/exif.entity'; import { GeodataPlacesEntity } from 'src/entities/geodata-places.entity'; -import { SmartInfoEntity } from 'src/entities/smart-info.entity'; import { SmartSearchEntity } from 'src/entities/smart-search.entity'; import { AssetType, PaginationMode } from 'src/enum'; import { IConfigRepository } from 'src/interfaces/config.interface'; @@ -18,6 +17,10 @@ import { AssetSearchOptions, FaceEmbeddingSearch, FaceSearchResult, + GetCameraMakesOptions, + GetCameraModelsOptions, + GetCitiesOptions, + GetStatesOptions, ISearchRepository, SearchPaginationOptions, SmartSearchOptions, @@ -34,7 +37,6 @@ export class SearchRepository implements ISearchRepository { private assetsByCityQuery: string; constructor( - @InjectRepository(SmartInfoEntity) private repository: Repository, @InjectRepository(AssetEntity) private assetRepository: Repository, @InjectRepository(ExifEntity) private exifRepository: Repository, @InjectRepository(AssetFaceEntity) private assetFaceRepository: Repository, @@ -113,7 +115,7 @@ export class SearchRepository implements ISearchRepository { @GenerateSql({ params: [ - { page: 1, size: 100 }, + { page: 1, size: 200 }, { takenAfter: DummyValue.DATE, embedding: Array.from({ length: 512 }, Math.random), @@ -139,7 +141,10 @@ export class SearchRepository implements ISearchRepository { .orderBy('search.embedding <=> :embedding') .setParameters({ userIds, embedding: asVector(embedding) }); - await manager.query(this.getRuntimeConfig(pagination.size)); + const runtimeConfig = this.getRuntimeConfig(pagination.size); + if (runtimeConfig) { + await manager.query(runtimeConfig); + } results = await paginatedBuilder(builder, { mode: PaginationMode.LIMIT_OFFSET, skip: (pagination.page - 1) * pagination.size, @@ -198,7 +203,7 @@ export class SearchRepository implements ISearchRepository { { userIds: [DummyValue.UUID], embedding: Array.from({ length: 512 }, Math.random), - numResults: 100, + numResults: 10, maxDistance: 0.6, }, ], @@ -238,7 +243,10 @@ export class SearchRepository implements ISearchRepository { cte.addSelect(`faces.${col}`, col); } - await manager.query(this.getRuntimeConfig(numResults)); + const runtimeConfig = this.getRuntimeConfig(numResults); + if (runtimeConfig) { + await manager.query(runtimeConfig); + } results = await manager .createQueryBuilder() .select('res.*') @@ -278,7 +286,7 @@ export class SearchRepository implements ISearchRepository { @GenerateSql({ params: [[DummyValue.UUID]] }) async getAssetsByCity(userIds: string[]): Promise { const parameters = [userIds, true, false, AssetType.IMAGE]; - const rawRes = await this.repository.query(this.assetsByCityQuery, parameters); + const rawRes = await this.assetRepository.query(this.assetsByCityQuery, parameters); const items: AssetEntity[] = []; for (const res of rawRes) { @@ -338,23 +346,27 @@ export class SearchRepository implements ISearchRepository { @GenerateSql({ params: [[DummyValue.UUID]] }) async getCountries(userIds: string[]): Promise { - const results = await this.exifRepository + const query = this.exifRepository .createQueryBuilder('exif') - .leftJoin('exif.asset', 'asset') + .innerJoin('exif.asset', 'asset') .where('asset.ownerId IN (:...userIds )', { userIds }) + .andWhere(`exif.country != ''`) + .andWhere('exif.country IS NOT NULL') .select('exif.country', 'country') - .distinctOn(['exif.country']) - .getRawMany<{ country: string }>(); + .distinctOn(['exif.country']); - return results.map(({ country }) => country).filter((item) => item !== ''); + const results = await query.getRawMany<{ country: string }>(); + return results.map(({ country }) => country); } @GenerateSql({ params: [[DummyValue.UUID], DummyValue.STRING] }) - async getStates(userIds: string[], country: string | undefined): Promise { + async getStates(userIds: string[], { country }: GetStatesOptions): Promise { const query = this.exifRepository .createQueryBuilder('exif') - .leftJoin('exif.asset', 'asset') + .innerJoin('exif.asset', 'asset') .where('asset.ownerId IN (:...userIds )', { userIds }) + .andWhere(`exif.state != ''`) + .andWhere('exif.state IS NOT NULL') .select('exif.state', 'state') .distinctOn(['exif.state']); @@ -363,16 +375,17 @@ export class SearchRepository implements ISearchRepository { } const result = await query.getRawMany<{ state: string }>(); - - return result.map(({ state }) => state).filter((item) => item !== ''); + return result.map(({ state }) => state); } @GenerateSql({ params: [[DummyValue.UUID], DummyValue.STRING, DummyValue.STRING] }) - async getCities(userIds: string[], country: string | undefined, state: string | undefined): Promise { + async getCities(userIds: string[], { country, state }: GetCitiesOptions): Promise { const query = this.exifRepository .createQueryBuilder('exif') - .leftJoin('exif.asset', 'asset') + .innerJoin('exif.asset', 'asset') .where('asset.ownerId IN (:...userIds )', { userIds }) + .andWhere(`exif.city != ''`) + .andWhere('exif.city IS NOT NULL') .select('exif.city', 'city') .distinctOn(['exif.city']); @@ -385,16 +398,17 @@ export class SearchRepository implements ISearchRepository { } const results = await query.getRawMany<{ city: string }>(); - - return results.map(({ city }) => city).filter((item) => item !== ''); + return results.map(({ city }) => city); } @GenerateSql({ params: [[DummyValue.UUID], DummyValue.STRING] }) - async getCameraMakes(userIds: string[], model: string | undefined): Promise { + async getCameraMakes(userIds: string[], { model }: GetCameraMakesOptions): Promise { const query = this.exifRepository .createQueryBuilder('exif') - .leftJoin('exif.asset', 'asset') + .innerJoin('exif.asset', 'asset') .where('asset.ownerId IN (:...userIds )', { userIds }) + .andWhere(`exif.make != ''`) + .andWhere('exif.make IS NOT NULL') .select('exif.make', 'make') .distinctOn(['exif.make']); @@ -403,15 +417,17 @@ export class SearchRepository implements ISearchRepository { } const results = await query.getRawMany<{ make: string }>(); - return results.map(({ make }) => make).filter((item) => item !== ''); + return results.map(({ make }) => make); } @GenerateSql({ params: [[DummyValue.UUID], DummyValue.STRING] }) - async getCameraModels(userIds: string[], make: string | undefined): Promise { + async getCameraModels(userIds: string[], { make }: GetCameraModelsOptions): Promise { const query = this.exifRepository .createQueryBuilder('exif') - .leftJoin('exif.asset', 'asset') + .innerJoin('exif.asset', 'asset') .where('asset.ownerId IN (:...userIds )', { userIds }) + .andWhere(`exif.model != ''`) + .andWhere('exif.model IS NOT NULL') .select('exif.model', 'model') .distinctOn(['exif.model']); @@ -420,20 +436,17 @@ export class SearchRepository implements ISearchRepository { } const results = await query.getRawMany<{ model: string }>(); - return results.map(({ model }) => model).filter((item) => item !== ''); + return results.map(({ model }) => model); } - private getRuntimeConfig(numResults?: number): string { + private getRuntimeConfig(numResults?: number): string | undefined { if (this.vectorExtension === DatabaseExtension.VECTOR) { return 'SET LOCAL hnsw.ef_search = 1000;'; // mitigate post-filter recall } - let runtimeConfig = 'SET LOCAL vectors.enable_prefilter=on; SET LOCAL vectors.search_mode=vbase;'; - if (numResults) { - runtimeConfig += ` SET LOCAL vectors.hnsw_ef_search = ${numResults};`; + if (numResults && numResults !== 100) { + return `SET LOCAL vectors.hnsw_ef_search = ${Math.max(numResults, 100)};`; } - - return runtimeConfig; } } diff --git a/server/src/repositories/stack.repository.ts b/server/src/repositories/stack.repository.ts index ae1a7f70d4a3a..9e9f09c4429ca 100644 --- a/server/src/repositories/stack.repository.ts +++ b/server/src/repositories/stack.repository.ts @@ -127,6 +127,7 @@ export class StackRepository implements IStackRepository { relations: { assets: { exifInfo: true, + tags: true, }, }, order: { diff --git a/server/src/repositories/storage.repository.ts b/server/src/repositories/storage.repository.ts index e4c0c68451477..a8d3db15d813b 100644 --- a/server/src/repositories/storage.repository.ts +++ b/server/src/repositories/storage.repository.ts @@ -214,7 +214,7 @@ export class StorageRepository implements IStorageRepository { } private asGlob(pathToCrawl: string): string { - const escapedPath = escapePath(pathToCrawl); + const escapedPath = escapePath(pathToCrawl).replaceAll('"', '["]').replaceAll("'", "[']").replaceAll('`', '[`]'); const extensions = `*{${mimeTypes.getSupportedFileExtensions().join(',')}}`; return `${escapedPath}/**/${extensions}`; } diff --git a/server/src/repositories/user.repository.ts b/server/src/repositories/user.repository.ts index 6ac8536ef8a79..a2e4375701a2a 100644 --- a/server/src/repositories/user.repository.ts +++ b/server/src/repositories/user.repository.ts @@ -108,6 +108,14 @@ export class UserRepository implements IUserRepository { .addSelect(`COUNT(assets.id) FILTER (WHERE assets.type = 'IMAGE' AND assets.isVisible)`, 'photos') .addSelect(`COUNT(assets.id) FILTER (WHERE assets.type = 'VIDEO' AND assets.isVisible)`, 'videos') .addSelect('COALESCE(SUM(exif.fileSizeInByte) FILTER (WHERE assets.libraryId IS NULL), 0)', 'usage') + .addSelect( + `COALESCE(SUM(exif.fileSizeInByte) FILTER (WHERE assets.libraryId IS NULL AND assets.type = 'IMAGE'), 0)`, + 'usagePhotos', + ) + .addSelect( + `COALESCE(SUM(exif.fileSizeInByte) FILTER (WHERE assets.libraryId IS NULL AND assets.type = 'VIDEO'), 0)`, + 'usageVideos', + ) .addSelect('users.quotaSizeInBytes', 'quotaSizeInBytes') .leftJoin('users.assets', 'assets') .leftJoin('assets.exifInfo', 'exif') @@ -119,6 +127,8 @@ export class UserRepository implements IUserRepository { stat.photos = Number(stat.photos); stat.videos = Number(stat.videos); stat.usage = Number(stat.usage); + stat.usagePhotos = Number(stat.usagePhotos); + stat.usageVideos = Number(stat.usageVideos); stat.quotaSizeInBytes = stat.quotaSizeInBytes; } diff --git a/server/src/services/album.service.ts b/server/src/services/album.service.ts index 2cf83e9b99972..e57e6b168ce17 100644 --- a/server/src/services/album.service.ts +++ b/server/src/services/album.service.ts @@ -74,7 +74,7 @@ export class AlbumService extends BaseService { startDate: albumMetadata[album.id].startDate, endDate: albumMetadata[album.id].endDate, assetCount: albumMetadata[album.id].assetCount, - lastModifiedAssetTimestamp: lastModifiedAsset?.fileModifiedAt, + lastModifiedAssetTimestamp: lastModifiedAsset?.updatedAt, }; }), ); @@ -86,12 +86,14 @@ export class AlbumService extends BaseService { const withAssets = dto.withoutAssets === undefined ? true : !dto.withoutAssets; const album = await this.findOrFail(id, { withAssets }); const [albumMetadataForIds] = await this.albumRepository.getMetadataForIds([album.id]); + const lastModifiedAsset = await this.assetRepository.getLastUpdatedAssetForAlbumId(album.id); return { ...mapAlbum(album, withAssets, auth), startDate: albumMetadataForIds.startDate, endDate: albumMetadataForIds.endDate, assetCount: albumMetadataForIds.assetCount, + lastModifiedAssetTimestamp: lastModifiedAsset?.updatedAt, }; } diff --git a/server/src/services/asset-media.service.spec.ts b/server/src/services/asset-media.service.spec.ts index c269739935e01..1daeb99d0bc5b 100644 --- a/server/src/services/asset-media.service.spec.ts +++ b/server/src/services/asset-media.service.spec.ts @@ -14,6 +14,7 @@ import { IAssetRepository } from 'src/interfaces/asset.interface'; import { IJobRepository, JobName } from 'src/interfaces/job.interface'; import { IStorageRepository } from 'src/interfaces/storage.interface'; import { IUserRepository } from 'src/interfaces/user.interface'; +import { AuthRequest } from 'src/middleware/auth.guard'; import { AssetMediaService } from 'src/services/asset-media.service'; import { ImmichFileResponse } from 'src/utils/file'; import { assetStub } from 'test/fixtures/asset.stub'; @@ -97,7 +98,7 @@ const validImages = [ '.x3f', ]; -const validVideos = ['.3gp', '.avi', '.flv', '.m2ts', '.mkv', '.mov', '.mp4', '.mpg', '.mts', '.webm', '.wmv']; +const validVideos = ['.3gp', '.avi', '.flv', '.m2ts', '.mkv', '.mov', '.mp4', '.mpg', '.mts', '.vob', '.webm', '.wmv']; const uploadTests = [ { @@ -570,6 +571,7 @@ describe(AssetMediaService.name, () => { path: '/path/to/preview.jpg', cacheControl: CacheControl.PRIVATE_WITH_CACHE, contentType: 'image/jpeg', + fileName: 'asset-id_thumbnail.jpg', }), ); }); @@ -584,6 +586,7 @@ describe(AssetMediaService.name, () => { path: assetStub.image.files[0].path, cacheControl: CacheControl.PRIVATE_WITH_CACHE, contentType: 'image/jpeg', + fileName: 'asset-id_preview.jpg', }), ); }); @@ -598,6 +601,7 @@ describe(AssetMediaService.name, () => { path: assetStub.image.files[1].path, cacheControl: CacheControl.PRIVATE_WITH_CACHE, contentType: 'application/octet-stream', + fileName: 'asset-id_thumbnail.ext', }), ); }); @@ -879,4 +883,28 @@ describe(AssetMediaService.name, () => { expect(assetMock.getByChecksums).toHaveBeenCalledWith(authStub.admin.user.id, [file1, file2]); }); }); + + describe('onUploadError', () => { + it('should queue a job to delete the uploaded file', async () => { + const request = { user: authStub.user1 } as AuthRequest; + + const file = { + fieldname: UploadFieldName.ASSET_DATA, + originalname: 'image.jpg', + mimetype: 'image/jpeg', + buffer: Buffer.from(''), + size: 1000, + uuid: 'random-uuid', + checksum: Buffer.from('checksum', 'utf8'), + originalPath: 'upload/upload/user-id/ra/nd/random-uuid.jpg', + } as unknown as Express.Multer.File; + + await sut.onUploadError(request, file); + + expect(jobMock.queue).toHaveBeenCalledWith({ + name: JobName.DELETE_FILES, + data: { files: ['upload/upload/user-id/ra/nd/random-uuid.jpg'] }, + }); + }); + }); }); diff --git a/server/src/services/asset-media.service.ts b/server/src/services/asset-media.service.ts index 70f4905de31e4..e96d1fd0a6f4b 100644 --- a/server/src/services/asset-media.service.ts +++ b/server/src/services/asset-media.service.ts @@ -23,10 +23,11 @@ import { AuthDto } from 'src/dtos/auth.dto'; import { ASSET_CHECKSUM_CONSTRAINT, AssetEntity } from 'src/entities/asset.entity'; import { AssetStatus, AssetType, CacheControl, Permission, StorageFolder } from 'src/enum'; import { JobName } from 'src/interfaces/job.interface'; +import { AuthRequest } from 'src/middleware/auth.guard'; import { BaseService } from 'src/services/base.service'; import { requireUploadAccess } from 'src/utils/access'; -import { getAssetFiles, onBeforeLink } from 'src/utils/asset.util'; -import { ImmichFileResponse } from 'src/utils/file'; +import { asRequest, getAssetFiles, onBeforeLink } from 'src/utils/asset.util'; +import { getFilenameExtension, getFileNameWithoutExtension, ImmichFileResponse } from 'src/utils/file'; import { mimeTypes } from 'src/utils/mime-types'; import { fromChecksum } from 'src/utils/request'; import { QueryFailedError } from 'typeorm'; @@ -118,6 +119,14 @@ export class AssetMediaService extends BaseService { return folder; } + async onUploadError(request: AuthRequest, file: Express.Multer.File) { + const uploadFilename = this.getUploadFilename(asRequest(request, file)); + const uploadFolder = this.getUploadFolder(asRequest(request, file)); + const uploadPath = `${uploadFolder}/${uploadFilename}`; + + await this.jobRepository.queue({ name: JobName.DELETE_FILES, data: { files: [uploadPath] } }); + } + async uploadAsset( auth: AuthDto, dto: AssetMediaCreateDto, @@ -208,8 +217,12 @@ export class AssetMediaService extends BaseService { if (!filepath) { throw new NotFoundException('Asset media not found'); } + let fileName = getFileNameWithoutExtension(asset.originalFileName); + fileName += `_${size}`; + fileName += getFilenameExtension(filepath); return new ImmichFileResponse({ + fileName, path: filepath, contentType: mimeTypes.lookup(filepath), cacheControl: CacheControl.PRIVATE_WITH_CACHE, diff --git a/server/src/services/asset.service.spec.ts b/server/src/services/asset.service.spec.ts index 9063df9dc2a82..5aab5032af408 100755 --- a/server/src/services/asset.service.spec.ts +++ b/server/src/services/asset.service.spec.ts @@ -80,7 +80,20 @@ describe(AssetService.name, () => { const image4 = { ...assetStub.image, localDateTime: new Date(2009, 1, 15) }; partnerMock.getAll.mockResolvedValue([]); - assetMock.getByDayOfYear.mockResolvedValue([image1, image2, image3, image4]); + assetMock.getByDayOfYear.mockResolvedValue([ + { + yearsAgo: 1, + assets: [image1, image2], + }, + { + yearsAgo: 9, + assets: [image3], + }, + { + yearsAgo: 15, + assets: [image4], + }, + ]); await expect(sut.getMemoryLane(authStub.admin, { day: 15, month: 1 })).resolves.toEqual([ { yearsAgo: 1, title: '1 year ago', assets: [mapAsset(image1), mapAsset(image2)] }, diff --git a/server/src/services/asset.service.ts b/server/src/services/asset.service.ts index 2f31806e81444..87510371192e4 100644 --- a/server/src/services/asset.service.ts +++ b/server/src/services/asset.service.ts @@ -1,6 +1,7 @@ import { BadRequestException } from '@nestjs/common'; import _ from 'lodash'; import { DateTime, Duration } from 'luxon'; +import { OnJob } from 'src/decorators'; import { AssetResponseDto, MemoryLaneResponseDto, @@ -21,12 +22,13 @@ import { MemoryLaneDto } from 'src/dtos/search.dto'; import { AssetEntity } from 'src/entities/asset.entity'; import { AssetStatus, Permission } from 'src/enum'; import { - IAssetDeleteJob, ISidecarWriteJob, JOBS_ASSET_PAGINATION_SIZE, JobItem, JobName, + JobOf, JobStatus, + QueueName, } from 'src/interfaces/job.interface'; import { BaseService } from 'src/services/base.service'; import { getAssetFiles, getMyPartnerIds, onAfterUnlink, onBeforeLink, onBeforeUnlink } from 'src/utils/asset.util'; @@ -41,28 +43,13 @@ export class AssetService extends BaseService { }); const userIds = [auth.user.id, ...partnerIds]; - const assets = await this.assetRepository.getByDayOfYear(userIds, dto); - const assetsWithThumbnails = assets.filter(({ files }) => !!getAssetFiles(files).thumbnailFile); - const groups: Record = {}; - const currentYear = new Date().getFullYear(); - for (const asset of assetsWithThumbnails) { - const yearsAgo = currentYear - asset.localDateTime.getFullYear(); - if (!groups[yearsAgo]) { - groups[yearsAgo] = []; - } - groups[yearsAgo].push(asset); - } - - return Object.keys(groups) - .map(Number) - .sort((a, b) => a - b) - .filter((yearsAgo) => yearsAgo > 0) - .map((yearsAgo) => ({ - yearsAgo, - // TODO move this to clients - title: `${yearsAgo} year${yearsAgo > 1 ? 's' : ''} ago`, - assets: groups[yearsAgo].map((asset) => mapAsset(asset, { auth })), - })); + const groups = await this.assetRepository.getByDayOfYear(userIds, dto); + return groups.map(({ yearsAgo, assets }) => ({ + yearsAgo, + // TODO move this to clients + title: `${yearsAgo} year${yearsAgo > 1 ? 's' : ''} ago`, + assets: assets.map((asset) => mapAsset(asset, { auth })), + })); } async getStatistics(auth: AuthDto, dto: AssetStatsDto) { @@ -92,7 +79,6 @@ export class AssetService extends BaseService { { exifInfo: true, sharedLinks: true, - smartInfo: true, tags: true, owner: true, faces: { @@ -160,7 +146,6 @@ export class AssetService extends BaseService { const asset = await this.assetRepository.getById(id, { exifInfo: true, owner: true, - smartInfo: true, tags: true, faces: { person: true, @@ -186,6 +171,7 @@ export class AssetService extends BaseService { await this.assetRepository.updateAll(ids, options); } + @OnJob({ name: JobName.ASSET_DELETION_CHECK, queue: QueueName.BACKGROUND_TASK }) async handleAssetDeletionCheck(): Promise { const config = await this.getConfig({ withCache: false }); const trashedDays = config.trash.enabled ? config.trash.days : 0; @@ -211,7 +197,8 @@ export class AssetService extends BaseService { return JobStatus.SUCCESS; } - async handleAssetDeletion(job: IAssetDeleteJob): Promise { + @OnJob({ name: JobName.ASSET_DELETION, queue: QueueName.BACKGROUND_TASK }) + async handleAssetDeletion(job: JobOf): Promise { const { id, deleteOnDisk } = job; const asset = await this.assetRepository.getById(id, { diff --git a/server/src/services/audit.service.ts b/server/src/services/audit.service.ts index d891c88b3911c..3fc838e5e90ef 100644 --- a/server/src/services/audit.service.ts +++ b/server/src/services/audit.service.ts @@ -3,6 +3,7 @@ import { DateTime } from 'luxon'; import { resolve } from 'node:path'; import { AUDIT_LOG_MAX_DURATION } from 'src/constants'; import { StorageCore } from 'src/cores/storage.core'; +import { OnJob } from 'src/decorators'; import { AuditDeletesDto, AuditDeletesResponseDto, @@ -21,13 +22,14 @@ import { StorageFolder, UserPathType, } from 'src/enum'; -import { JOBS_ASSET_PAGINATION_SIZE, JobStatus } from 'src/interfaces/job.interface'; +import { JobName, JOBS_ASSET_PAGINATION_SIZE, JobStatus, QueueName } from 'src/interfaces/job.interface'; import { BaseService } from 'src/services/base.service'; import { getAssetFiles } from 'src/utils/asset.util'; import { usePagination } from 'src/utils/pagination'; @Injectable() export class AuditService extends BaseService { + @OnJob({ name: JobName.CLEAN_OLD_AUDIT_LOGS, queue: QueueName.BACKGROUND_TASK }) async handleCleanup(): Promise { await this.auditRepository.removeBefore(DateTime.now().minus(AUDIT_LOG_MAX_DURATION).toJSDate()); return JobStatus.SUCCESS; diff --git a/server/src/services/auth.service.spec.ts b/server/src/services/auth.service.spec.ts index 3701d3de56877..d34e2673f56ef 100644 --- a/server/src/services/auth.service.spec.ts +++ b/server/src/services/auth.service.spec.ts @@ -53,7 +53,7 @@ const oauthUserWithDefaultQuota = { email, name: ' ', oauthId: sub, - quotaSizeInBytes: 1_073_741_824, + quotaSizeInBytes: '1073741824', storageLabel: null, }; @@ -567,7 +567,7 @@ describe('AuthService', () => { oauthResponse, ); - expect(userMock.create).toHaveBeenCalledWith(oauthUserWithDefaultQuota); + expect(userMock.create).toHaveBeenCalledWith({ ...oauthUserWithDefaultQuota, quotaSizeInBytes: 1_073_741_824 }); }); it('should ignore an invalid storage quota', async () => { @@ -581,7 +581,7 @@ describe('AuthService', () => { oauthResponse, ); - expect(userMock.create).toHaveBeenCalledWith(oauthUserWithDefaultQuota); + expect(userMock.create).toHaveBeenCalledWith({ ...oauthUserWithDefaultQuota, quotaSizeInBytes: 1_073_741_824 }); }); it('should ignore a negative quota', async () => { @@ -595,7 +595,7 @@ describe('AuthService', () => { oauthResponse, ); - expect(userMock.create).toHaveBeenCalledWith(oauthUserWithDefaultQuota); + expect(userMock.create).toHaveBeenCalledWith({ ...oauthUserWithDefaultQuota, quotaSizeInBytes: 1_073_741_824 }); }); it('should not set quota for 0 quota', async () => { diff --git a/server/src/services/auth.service.ts b/server/src/services/auth.service.ts index b0094ae9edba9..0d44fa0562235 100644 --- a/server/src/services/auth.service.ts +++ b/server/src/services/auth.service.ts @@ -1,5 +1,5 @@ import { BadRequestException, ForbiddenException, Injectable, UnauthorizedException } from '@nestjs/common'; -import { isNumber, isString } from 'class-validator'; +import { isString } from 'class-validator'; import cookieParser from 'cookie'; import { DateTime } from 'luxon'; import { IncomingHttpHeaders } from 'node:http'; @@ -226,7 +226,7 @@ export class AuthService extends BaseService { const storageQuota = this.getClaim(profile, { key: storageQuotaClaim, default: defaultStorageQuota, - isValid: (value: unknown) => isNumber(value) && value >= 0, + isValid: (value: unknown) => Number(value) >= 0, }); const userName = profile.name ?? `${profile.given_name || ''} ${profile.family_name || ''}`; diff --git a/server/src/services/backup.service.spec.ts b/server/src/services/backup.service.spec.ts index 8f006d0d6ba0b..41ba7c2153e1e 100644 --- a/server/src/services/backup.service.spec.ts +++ b/server/src/services/backup.service.spec.ts @@ -2,8 +2,10 @@ import { PassThrough } from 'node:stream'; import { defaults, SystemConfig } from 'src/config'; import { StorageCore } from 'src/cores/storage.core'; import { ImmichWorker, StorageFolder } from 'src/enum'; +import { IConfigRepository } from 'src/interfaces/config.interface'; +import { ICronRepository } from 'src/interfaces/cron.interface'; import { IDatabaseRepository } from 'src/interfaces/database.interface'; -import { IJobRepository, JobStatus } from 'src/interfaces/job.interface'; +import { JobStatus } from 'src/interfaces/job.interface'; import { IProcessRepository } from 'src/interfaces/process.interface'; import { IStorageRepository } from 'src/interfaces/storage.interface'; import { ISystemMetadataRepository } from 'src/interfaces/system-metadata.interface'; @@ -16,13 +18,14 @@ describe(BackupService.name, () => { let sut: BackupService; let databaseMock: Mocked; - let jobMock: Mocked; + let configMock: Mocked; + let cronMock: Mocked; let processMock: Mocked; let storageMock: Mocked; let systemMock: Mocked; beforeEach(() => { - ({ sut, databaseMock, jobMock, processMock, storageMock, systemMock } = newTestService(BackupService)); + ({ sut, cronMock, configMock, databaseMock, processMock, storageMock, systemMock } = newTestService(BackupService)); }); it('should work', () => { @@ -32,35 +35,32 @@ describe(BackupService.name, () => { describe('onBootstrapEvent', () => { it('should init cron job and handle config changes', async () => { databaseMock.tryLock.mockResolvedValue(true); - systemMock.get.mockResolvedValue(systemConfigStub.backupEnabled); - await sut.onBootstrap(ImmichWorker.API); + await sut.onConfigInit({ newConfig: systemConfigStub.backupEnabled as SystemConfig }); - expect(jobMock.addCronJob).toHaveBeenCalled(); - expect(systemMock.get).toHaveBeenCalled(); + expect(cronMock.create).toHaveBeenCalled(); }); it('should not initialize backup database cron job when lock is taken', async () => { - systemMock.get.mockResolvedValue(systemConfigStub.backupEnabled); databaseMock.tryLock.mockResolvedValue(false); - await sut.onBootstrap(ImmichWorker.API); + await sut.onConfigInit({ newConfig: systemConfigStub.backupEnabled as SystemConfig }); - expect(jobMock.addCronJob).not.toHaveBeenCalled(); + expect(cronMock.create).not.toHaveBeenCalled(); }); it('should not initialise backup database job when running on microservices', async () => { - await sut.onBootstrap(ImmichWorker.MICROSERVICES); + configMock.getWorker.mockReturnValue(ImmichWorker.MICROSERVICES); + await sut.onConfigInit({ newConfig: systemConfigStub.backupEnabled as SystemConfig }); - expect(jobMock.addCronJob).not.toHaveBeenCalled(); + expect(cronMock.create).not.toHaveBeenCalled(); }); }); describe('onConfigUpdateEvent', () => { beforeEach(async () => { - systemMock.get.mockResolvedValue(defaults); databaseMock.tryLock.mockResolvedValue(true); - await sut.onBootstrap(ImmichWorker.API); + await sut.onConfigInit({ newConfig: defaults }); }); it('should update cron job if backup is enabled', () => { @@ -76,40 +76,15 @@ describe(BackupService.name, () => { } as SystemConfig, }); - expect(jobMock.updateCronJob).toHaveBeenCalledWith('backupDatabase', '0 1 * * *', true); - expect(jobMock.updateCronJob).toHaveBeenCalled(); - }); - - it('should do nothing if oldConfig is not provided', () => { - sut.onConfigUpdate({ newConfig: systemConfigStub.backupEnabled as SystemConfig }); - expect(jobMock.updateCronJob).not.toHaveBeenCalled(); + expect(cronMock.update).toHaveBeenCalledWith({ name: 'backupDatabase', expression: '0 1 * * *', start: true }); + expect(cronMock.update).toHaveBeenCalled(); }); it('should do nothing if instance does not have the backup database lock', async () => { databaseMock.tryLock.mockResolvedValue(false); - await sut.onBootstrap(ImmichWorker.API); + await sut.onConfigInit({ newConfig: defaults }); sut.onConfigUpdate({ newConfig: systemConfigStub.backupEnabled as SystemConfig, oldConfig: defaults }); - expect(jobMock.updateCronJob).not.toHaveBeenCalled(); - }); - }); - - describe('onConfigValidateEvent', () => { - it('should allow a valid cron expression', () => { - expect(() => - sut.onConfigValidate({ - newConfig: { backup: { database: { cronExpression: '0 0 * * *' } } } as SystemConfig, - oldConfig: {} as SystemConfig, - }), - ).not.toThrow(expect.stringContaining('Invalid cron expression')); - }); - - it('should fail for an invalid cron expression', () => { - expect(() => - sut.onConfigValidate({ - newConfig: { backup: { database: { cronExpression: 'foo' } } } as SystemConfig, - oldConfig: {} as SystemConfig, - }), - ).toThrow(/Invalid cron expression.*/); + expect(cronMock.update).not.toHaveBeenCalled(); }); }); @@ -171,6 +146,7 @@ describe(BackupService.name, () => { storageMock.readdir.mockResolvedValue([]); processMock.spawn.mockReturnValue(mockSpawn(0, 'data', '')); storageMock.rename.mockResolvedValue(); + storageMock.unlink.mockResolvedValue(); systemMock.get.mockResolvedValue(systemConfigStub.backupEnabled); storageMock.createWriteStream.mockReturnValue(new PassThrough()); }); @@ -213,5 +189,42 @@ describe(BackupService.name, () => { const result = await sut.handleBackupDatabase(); expect(result).toBe(JobStatus.FAILED); }); + it('should ignore unlink failing and still return failed job status', async () => { + processMock.spawn.mockReturnValueOnce(mockSpawn(1, '', 'error')); + storageMock.unlink.mockRejectedValue(new Error('error')); + const result = await sut.handleBackupDatabase(); + expect(storageMock.unlink).toHaveBeenCalled(); + expect(result).toBe(JobStatus.FAILED); + }); + it.each` + postgresVersion | expectedVersion + ${'14.10'} | ${14} + ${'14.10.3'} | ${14} + ${'14.10 (Debian 14.10-1.pgdg120+1)'} | ${14} + ${'15.3.3'} | ${15} + ${'16.4.2'} | ${16} + ${'17.15.1'} | ${17} + `( + `should use pg_dumpall $expectedVersion with postgres version $postgresVersion`, + async ({ postgresVersion, expectedVersion }) => { + databaseMock.getPostgresVersion.mockResolvedValue(postgresVersion); + await sut.handleBackupDatabase(); + expect(processMock.spawn).toHaveBeenCalledWith( + `/usr/lib/postgresql/${expectedVersion}/bin/pg_dumpall`, + expect.any(Array), + expect.any(Object), + ); + }, + ); + it.each` + postgresVersion + ${'13.99.99'} + ${'18.0.0'} + `(`should fail if postgres version $postgresVersion is not supported`, async ({ postgresVersion }) => { + databaseMock.getPostgresVersion.mockResolvedValue(postgresVersion); + const result = await sut.handleBackupDatabase(); + expect(processMock.spawn).not.toHaveBeenCalled(); + expect(result).toBe(JobStatus.FAILED); + }); }); }); diff --git a/server/src/services/backup.service.ts b/server/src/services/backup.service.ts index ba2ab816cd7a4..b3bc1dd8d16e3 100644 --- a/server/src/services/backup.service.ts +++ b/server/src/services/backup.service.ts @@ -1,55 +1,48 @@ import { Injectable } from '@nestjs/common'; import { default as path } from 'node:path'; +import semver from 'semver'; import { StorageCore } from 'src/cores/storage.core'; -import { OnEvent } from 'src/decorators'; +import { OnEvent, OnJob } from 'src/decorators'; import { ImmichWorker, StorageFolder } from 'src/enum'; import { DatabaseLock } from 'src/interfaces/database.interface'; import { ArgOf } from 'src/interfaces/event.interface'; -import { JobName, JobStatus } from 'src/interfaces/job.interface'; +import { JobName, JobStatus, QueueName } from 'src/interfaces/job.interface'; import { BaseService } from 'src/services/base.service'; import { handlePromiseError } from 'src/utils/misc'; -import { validateCronExpression } from 'src/validation'; @Injectable() export class BackupService extends BaseService { private backupLock = false; - @OnEvent({ name: 'app.bootstrap' }) - async onBootstrap(workerType: ImmichWorker) { - if (workerType !== ImmichWorker.API) { - return; - } - const { + @OnEvent({ name: 'config.init', workers: [ImmichWorker.MICROSERVICES] }) + async onConfigInit({ + newConfig: { backup: { database }, - } = await this.getConfig({ withCache: true }); - + }, + }: ArgOf<'config.init'>) { this.backupLock = await this.databaseRepository.tryLock(DatabaseLock.BackupDatabase); if (this.backupLock) { - this.jobRepository.addCronJob( - 'backupDatabase', - database.cronExpression, - () => handlePromiseError(this.jobRepository.queue({ name: JobName.BACKUP_DATABASE }), this.logger), - database.enabled, - ); + this.cronRepository.create({ + name: 'backupDatabase', + expression: database.cronExpression, + onTick: () => handlePromiseError(this.jobRepository.queue({ name: JobName.BACKUP_DATABASE }), this.logger), + start: database.enabled, + }); } } @OnEvent({ name: 'config.update', server: true }) - onConfigUpdate({ newConfig: { backup }, oldConfig }: ArgOf<'config.update'>) { - if (!oldConfig || !this.backupLock) { + onConfigUpdate({ newConfig: { backup } }: ArgOf<'config.update'>) { + if (!this.backupLock) { return; } - this.jobRepository.updateCronJob('backupDatabase', backup.database.cronExpression, backup.database.enabled); - } - - @OnEvent({ name: 'config.validate' }) - onConfigValidate({ newConfig }: ArgOf<'config.validate'>) { - const { database } = newConfig.backup; - if (!validateCronExpression(database.cronExpression)) { - throw new Error(`Invalid cron expression ${database.cronExpression}`); - } + this.cronRepository.update({ + name: 'backupDatabase', + expression: backup.database.cronExpression, + start: backup.database.enabled, + }); } async cleanupDatabaseBackups() { @@ -75,6 +68,7 @@ export class BackupService extends BaseService { this.logger.debug(`Database Backup Cleanup Finished, deleted ${toDelete.length} backups`); } + @OnJob({ name: JobName.BACKUP_DATABASE, queue: QueueName.BACKUP_DATABASE }) async handleBackupDatabase(): Promise { this.logger.debug(`Database Backup Started`); @@ -83,19 +77,53 @@ export class BackupService extends BaseService { } = this.configRepository.getEnv(); const isUrlConnection = config.connectionType === 'url'; - const databaseParams = isUrlConnection ? [config.url] : ['-U', config.username, '-h', config.host]; + + const databaseParams = isUrlConnection + ? ['--dbname', config.url] + : [ + '--username', + config.username, + '--host', + config.host, + '--port', + `${config.port}`, + '--database', + config.database, + ]; + + databaseParams.push('--clean', '--if-exists'); + const backupFilePath = path.join( StorageCore.getBaseFolder(StorageFolder.BACKUPS), `immich-db-backup-${Date.now()}.sql.gz.tmp`, ); + const databaseVersion = await this.databaseRepository.getPostgresVersion(); + const databaseSemver = semver.coerce(databaseVersion); + const databaseMajorVersion = databaseSemver?.major; + + if (!databaseMajorVersion || !databaseSemver || !semver.satisfies(databaseSemver, '>=14.0.0 <18.0.0')) { + this.logger.error(`Database Backup Failure: Unsupported PostgreSQL version: ${databaseVersion}`); + return JobStatus.FAILED; + } + + this.logger.log(`Database Backup Starting. Database Version: ${databaseMajorVersion}`); + try { await new Promise((resolve, reject) => { - const pgdump = this.processRepository.spawn(`pg_dumpall`, [...databaseParams, '--clean', '--if-exists'], { - env: { PATH: process.env.PATH, PGPASSWORD: isUrlConnection ? undefined : config.password }, - }); - - const gzip = this.processRepository.spawn(`gzip`, []); + const pgdump = this.processRepository.spawn( + `/usr/lib/postgresql/${databaseMajorVersion}/bin/pg_dumpall`, + databaseParams, + { + env: { + PATH: process.env.PATH, + PGPASSWORD: isUrlConnection ? undefined : config.password, + }, + }, + ); + + // NOTE: `--rsyncable` is only supported in GNU gzip + const gzip = this.processRepository.spawn(`gzip`, ['--rsyncable']); pgdump.stdout.pipe(gzip.stdin); const fileStream = this.storageRepository.createWriteStream(backupFilePath); @@ -147,10 +175,13 @@ export class BackupService extends BaseService { await this.storageRepository.rename(backupFilePath, backupFilePath.replace('.tmp', '')); } catch (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)); return JobStatus.FAILED; } - this.logger.debug(`Database Backup Success`); + this.logger.log(`Database Backup Success`); await this.cleanupDatabaseBackups(); return JobStatus.SUCCESS; } diff --git a/server/src/services/base.service.ts b/server/src/services/base.service.ts index a312050f08386..3630d69c1804f 100644 --- a/server/src/services/base.service.ts +++ b/server/src/services/base.service.ts @@ -12,6 +12,7 @@ import { IKeyRepository } from 'src/interfaces/api-key.interface'; import { IAssetRepository } from 'src/interfaces/asset.interface'; import { IAuditRepository } from 'src/interfaces/audit.interface'; import { IConfigRepository } from 'src/interfaces/config.interface'; +import { ICronRepository } from 'src/interfaces/cron.interface'; import { ICryptoRepository } from 'src/interfaces/crypto.interface'; import { IDatabaseRepository } from 'src/interfaces/database.interface'; import { IEventRepository } from 'src/interfaces/event.interface'; @@ -57,6 +58,7 @@ export class BaseService { @Inject(IAlbumUserRepository) protected albumUserRepository: IAlbumUserRepository, @Inject(IAssetRepository) protected assetRepository: IAssetRepository, @Inject(IConfigRepository) protected configRepository: IConfigRepository, + @Inject(ICronRepository) protected cronRepository: ICronRepository, @Inject(ICryptoRepository) protected cryptoRepository: ICryptoRepository, @Inject(IDatabaseRepository) protected databaseRepository: IDatabaseRepository, @Inject(IEventRepository) protected eventRepository: IEventRepository, @@ -101,6 +103,10 @@ export class BaseService { ); } + get worker() { + return this.configRepository.getWorker(); + } + private get configRepos() { return { configRepo: this.configRepository, diff --git a/server/src/services/database.service.ts b/server/src/services/database.service.ts index 363266c6aef6a..b1a270abd8dc7 100644 --- a/server/src/services/database.service.ts +++ b/server/src/services/database.service.ts @@ -9,6 +9,7 @@ import { VectorExtension, VectorIndex, } from 'src/interfaces/database.interface'; +import { BootstrapEventPriority } from 'src/interfaces/event.interface'; import { BaseService } from 'src/services/base.service'; type CreateFailedArgs = { name: string; extension: string; otherName: string }; @@ -64,7 +65,7 @@ const RETRY_DURATION = Duration.fromObject({ seconds: 5 }); export class DatabaseService extends BaseService { private reconnection?: NodeJS.Timeout; - @OnEvent({ name: 'app.bootstrap', priority: -200 }) + @OnEvent({ name: 'app.bootstrap', priority: BootstrapEventPriority.DatabaseService }) async onBootstrap() { const version = await this.databaseRepository.getPostgresVersion(); const current = semver.coerce(version); diff --git a/server/src/services/duplicate.service.spec.ts b/server/src/services/duplicate.service.spec.ts index 095d53dde6570..75af1ef6f1f49 100644 --- a/server/src/services/duplicate.service.spec.ts +++ b/server/src/services/duplicate.service.spec.ts @@ -31,11 +31,23 @@ describe(SearchService.name, () => { describe('getDuplicates', () => { it('should get duplicates', async () => { - assetMock.getDuplicates.mockResolvedValue([assetStub.hasDupe]); + assetMock.getDuplicates.mockResolvedValue([assetStub.hasDupe, assetStub.hasDupe]); await expect(sut.getDuplicates(authStub.admin)).resolves.toEqual([ - { duplicateId: assetStub.hasDupe.duplicateId, assets: [expect.objectContaining({ id: assetStub.hasDupe.id })] }, + { + duplicateId: assetStub.hasDupe.duplicateId, + assets: [ + expect.objectContaining({ id: assetStub.hasDupe.id }), + expect.objectContaining({ id: assetStub.hasDupe.id }), + ], + }, ]); }); + + it('should update assets with duplicateId', async () => { + assetMock.getDuplicates.mockResolvedValue([assetStub.hasDupe]); + await expect(sut.getDuplicates(authStub.admin)).resolves.toEqual([]); + expect(assetMock.updateAll).toHaveBeenCalledWith([assetStub.hasDupe.id], { duplicateId: null }); + }); }); describe('handleQueueSearchDuplicates', () => { diff --git a/server/src/services/duplicate.service.ts b/server/src/services/duplicate.service.ts index e76b80b04391c..0d91df5790d4b 100644 --- a/server/src/services/duplicate.service.ts +++ b/server/src/services/duplicate.service.ts @@ -1,10 +1,11 @@ import { Injectable } from '@nestjs/common'; +import { OnJob } from 'src/decorators'; import { mapAsset } from 'src/dtos/asset-response.dto'; import { AuthDto } from 'src/dtos/auth.dto'; import { DuplicateResponseDto, mapDuplicateResponse } from 'src/dtos/duplicate.dto'; import { AssetEntity } from 'src/entities/asset.entity'; import { WithoutProperty } from 'src/interfaces/asset.interface'; -import { IBaseJob, IEntityJob, JOBS_ASSET_PAGINATION_SIZE, JobName, JobStatus } from 'src/interfaces/job.interface'; +import { JOBS_ASSET_PAGINATION_SIZE, JobName, JobOf, JobStatus, QueueName } from 'src/interfaces/job.interface'; import { AssetDuplicateResult } from 'src/interfaces/search.interface'; import { BaseService } from 'src/services/base.service'; import { getAssetFiles } from 'src/utils/asset.util'; @@ -15,11 +16,28 @@ import { usePagination } from 'src/utils/pagination'; export class DuplicateService extends BaseService { async getDuplicates(auth: AuthDto): Promise { const res = await this.assetRepository.getDuplicates({ userIds: [auth.user.id] }); - - return mapDuplicateResponse(res.map((a) => mapAsset(a, { auth, withStack: true }))); + const uniqueAssetIds: string[] = []; + const duplicates = mapDuplicateResponse(res.map((a) => mapAsset(a, { auth, withStack: true }))).filter( + (duplicate) => { + if (duplicate.assets.length === 1) { + uniqueAssetIds.push(duplicate.assets[0].id); + return false; + } + return true; + }, + ); + if (uniqueAssetIds.length > 0) { + try { + await this.assetRepository.updateAll(uniqueAssetIds, { duplicateId: null }); + } catch (error: any) { + this.logger.error(`Failed to remove duplicateId from assets: ${error.message}`); + } + } + return duplicates; } - async handleQueueSearchDuplicates({ force }: IBaseJob): Promise { + @OnJob({ name: JobName.QUEUE_DUPLICATE_DETECTION, queue: QueueName.DUPLICATE_DETECTION }) + async handleQueueSearchDuplicates({ force }: JobOf): Promise { const { machineLearning } = await this.getConfig({ withCache: false }); if (!isDuplicateDetectionEnabled(machineLearning)) { return JobStatus.SKIPPED; @@ -40,7 +58,8 @@ export class DuplicateService extends BaseService { return JobStatus.SUCCESS; } - async handleSearchDuplicates({ id }: IEntityJob): Promise { + @OnJob({ name: JobName.DUPLICATE_DETECTION, queue: QueueName.DUPLICATE_DETECTION }) + async handleSearchDuplicates({ id }: JobOf): Promise { const { machineLearning } = await this.getConfig({ withCache: true }); if (!isDuplicateDetectionEnabled(machineLearning)) { return JobStatus.SKIPPED; diff --git a/server/src/services/index.ts b/server/src/services/index.ts index 89c6afd7f4c1c..0dd8bdae666a6 100644 --- a/server/src/services/index.ts +++ b/server/src/services/index.ts @@ -17,7 +17,6 @@ import { MapService } from 'src/services/map.service'; import { MediaService } from 'src/services/media.service'; import { MemoryService } from 'src/services/memory.service'; import { MetadataService } from 'src/services/metadata.service'; -import { MicroservicesService } from 'src/services/microservices.service'; import { NotificationService } from 'src/services/notification.service'; import { PartnerService } from 'src/services/partner.service'; import { PersonService } from 'src/services/person.service'; @@ -60,7 +59,6 @@ export const services = [ MediaService, MemoryService, MetadataService, - MicroservicesService, NotificationService, PartnerService, PersonService, diff --git a/server/src/services/job.service.spec.ts b/server/src/services/job.service.spec.ts index 8e42693dc028a..a23b05073c215 100644 --- a/server/src/services/job.service.spec.ts +++ b/server/src/services/job.service.spec.ts @@ -1,38 +1,28 @@ import { BadRequestException } from '@nestjs/common'; -import { defaults } from 'src/config'; +import { defaults, SystemConfig } from 'src/config'; import { ImmichWorker } from 'src/enum'; import { IAssetRepository } from 'src/interfaces/asset.interface'; -import { - IJobRepository, - JobCommand, - JobHandler, - JobItem, - JobName, - JobStatus, - QueueName, -} from 'src/interfaces/job.interface'; -import { ISystemMetadataRepository } from 'src/interfaces/system-metadata.interface'; +import { IConfigRepository } from 'src/interfaces/config.interface'; +import { IJobRepository, JobCommand, JobItem, JobName, JobStatus, QueueName } from 'src/interfaces/job.interface'; +import { ILoggerRepository } from 'src/interfaces/logger.interface'; +import { ITelemetryRepository } from 'src/interfaces/telemetry.interface'; import { JobService } from 'src/services/job.service'; import { assetStub } from 'test/fixtures/asset.stub'; import { newTestService } from 'test/utils'; -import { Mocked, vitest } from 'vitest'; - -const makeMockHandlers = (status: JobStatus) => { - const mock = vitest.fn().mockResolvedValue(status); - return Object.fromEntries(Object.values(JobName).map((jobName) => [jobName, mock])) as unknown as Record< - JobName, - JobHandler - >; -}; +import { Mocked } from 'vitest'; describe(JobService.name, () => { let sut: JobService; let assetMock: Mocked; + let configMock: Mocked; let jobMock: Mocked; - let systemMock: Mocked; + let loggerMock: Mocked; + let telemetryMock: Mocked; beforeEach(() => { - ({ sut, assetMock, jobMock, systemMock } = newTestService(JobService)); + ({ sut, assetMock, configMock, jobMock, loggerMock, telemetryMock } = newTestService(JobService, {})); + + configMock.getWorker.mockReturnValue(ImmichWorker.MICROSERVICES); }); it('should work', () => { @@ -41,8 +31,7 @@ describe(JobService.name, () => { describe('onConfigUpdate', () => { it('should update concurrency', () => { - sut.onBootstrap(ImmichWorker.MICROSERVICES); - sut.onConfigUpdate({ oldConfig: defaults, newConfig: defaults }); + sut.onConfigUpdate({ newConfig: defaults, oldConfig: {} as SystemConfig }); expect(jobMock.setConcurrency).toHaveBeenCalledTimes(15); expect(jobMock.setConcurrency).toHaveBeenNthCalledWith(5, QueueName.FACIAL_RECOGNITION, 1); @@ -225,11 +214,19 @@ describe(JobService.name, () => { }); }); - describe('init', () => { - it('should register a handler for each queue', async () => { - await sut.init(makeMockHandlers(JobStatus.SUCCESS)); - expect(systemMock.get).toHaveBeenCalled(); - expect(jobMock.addHandler).toHaveBeenCalledTimes(Object.keys(QueueName).length); + describe('onJobStart', () => { + it('should process a successful job', async () => { + jobMock.run.mockResolvedValue(JobStatus.SUCCESS); + + await sut.onJobStart(QueueName.BACKGROUND_TASK, { + name: JobName.DELETE_FILES, + data: { files: ['path/to/file'] }, + }); + + expect(telemetryMock.jobs.addToGauge).toHaveBeenCalledWith('immich.queues.background_task.active', 1); + expect(telemetryMock.jobs.addToGauge).toHaveBeenCalledWith('immich.queues.background_task.active', -1); + expect(telemetryMock.jobs.addToCounter).toHaveBeenCalledWith('immich.jobs.delete_files.success', 1); + expect(loggerMock.error).not.toHaveBeenCalled(); }); const tests: Array<{ item: JobItem; jobs: JobName[] }> = [ @@ -297,8 +294,9 @@ describe(JobService.name, () => { } } - await sut.init(makeMockHandlers(JobStatus.SUCCESS)); - await jobMock.addHandler.mock.calls[0][2](item); + jobMock.run.mockResolvedValue(JobStatus.SUCCESS); + + await sut.onJobStart(QueueName.BACKGROUND_TASK, item); if (jobs.length > 1) { expect(jobMock.queueAll).toHaveBeenCalledWith( @@ -313,8 +311,9 @@ describe(JobService.name, () => { }); it(`should not queue any jobs when ${item.name} fails`, async () => { - await sut.init(makeMockHandlers(JobStatus.FAILED)); - await jobMock.addHandler.mock.calls[0][2](item); + jobMock.run.mockResolvedValue(JobStatus.FAILED); + + await sut.onJobStart(QueueName.BACKGROUND_TASK, item); expect(jobMock.queueAll).not.toHaveBeenCalled(); }); diff --git a/server/src/services/job.service.ts b/server/src/services/job.service.ts index 15046a0ef538a..2faed0a51666a 100644 --- a/server/src/services/job.service.ts +++ b/server/src/services/job.service.ts @@ -4,11 +4,10 @@ import { OnEvent } from 'src/decorators'; import { mapAsset } from 'src/dtos/asset-response.dto'; import { AllJobStatusResponseDto, JobCommandDto, JobCreateDto, JobStatusDto } from 'src/dtos/job.dto'; import { AssetType, ImmichWorker, ManualJobName } from 'src/enum'; -import { ArgOf } from 'src/interfaces/event.interface'; +import { ArgOf, ArgsOf } from 'src/interfaces/event.interface'; import { ConcurrentQueueName, JobCommand, - JobHandler, JobItem, JobName, JobStatus, @@ -39,19 +38,8 @@ const asJobItem = (dto: JobCreateDto): JobItem => { @Injectable() export class JobService extends BaseService { - private isMicroservices = false; - - @OnEvent({ name: 'app.bootstrap' }) - onBootstrap(app: ArgOf<'app.bootstrap'>) { - this.isMicroservices = app === ImmichWorker.MICROSERVICES; - } - - @OnEvent({ name: 'config.update', server: true }) - onConfigUpdate({ newConfig: config, oldConfig }: ArgOf<'config.update'>) { - if (!oldConfig || !this.isMicroservices) { - return; - } - + @OnEvent({ name: 'config.init', workers: [ImmichWorker.MICROSERVICES] }) + onConfigInit({ newConfig: config }: ArgOf<'config.init'>) { this.logger.debug(`Updating queue concurrency settings`); for (const queueName of Object.values(QueueName)) { let concurrency = 1; @@ -63,6 +51,11 @@ export class JobService extends BaseService { } } + @OnEvent({ name: 'config.update', server: true }) + onConfigUpdate({ newConfig: config }: ArgOf<'config.update'>) { + this.onConfigInit({ newConfig: config }); + } + async create(dto: JobCreateDto): Promise { await this.jobRepository.queue(asJobItem(dto)); } @@ -171,47 +164,31 @@ export class JobService extends BaseService { return this.jobRepository.queue({ name: JobName.LIBRARY_QUEUE_SYNC_ALL, data: { force } }); } + case QueueName.BACKUP_DATABASE: { + return this.jobRepository.queue({ name: JobName.BACKUP_DATABASE, data: { force } }); + } + default: { throw new BadRequestException(`Invalid job name: ${name}`); } } } - async init(jobHandlers: Record) { - const config = await this.getConfig({ withCache: false }); - for (const queueName of Object.values(QueueName)) { - let concurrency = 1; - - if (this.isConcurrentQueue(queueName)) { - concurrency = config.job[queueName].concurrency; + @OnEvent({ name: 'job.start' }) + async onJobStart(...[queueName, job]: ArgsOf<'job.start'>) { + const queueMetric = `immich.queues.${snakeCase(queueName)}.active`; + this.telemetryRepository.jobs.addToGauge(queueMetric, 1); + try { + const status = await this.jobRepository.run(job); + const jobMetric = `immich.jobs.${job.name.replaceAll('-', '_')}.${status}`; + this.telemetryRepository.jobs.addToCounter(jobMetric, 1); + if (status === JobStatus.SUCCESS || status == JobStatus.SKIPPED) { + await this.onDone(job); } - - this.logger.debug(`Registering ${queueName} with a concurrency of ${concurrency}`); - this.jobRepository.addHandler(queueName, concurrency, async (item: JobItem): Promise => { - const { name, data } = item; - - const handler = jobHandlers[name]; - if (!handler) { - this.logger.warn(`Skipping unknown job: "${name}"`); - return; - } - - const queueMetric = `immich.queues.${snakeCase(queueName)}.active`; - this.telemetryRepository.jobs.addToGauge(queueMetric, 1); - - try { - const status = await handler(data); - const jobMetric = `immich.jobs.${name.replaceAll('-', '_')}.${status}`; - this.telemetryRepository.jobs.addToCounter(jobMetric, 1); - if (status === JobStatus.SUCCESS || status == JobStatus.SKIPPED) { - await this.onDone(item); - } - } catch (error: Error | any) { - this.logger.error(`Unable to run job handler (${queueName}/${name}): ${error}`, error?.stack, data); - } finally { - this.telemetryRepository.jobs.addToGauge(queueMetric, -1); - } - }); + } catch (error: Error | any) { + this.logger.error(`Unable to run job handler (${queueName}/${job.name}): ${error}`, error?.stack, job.data); + } finally { + this.telemetryRepository.jobs.addToGauge(queueMetric, -1); } } diff --git a/server/src/services/library.service.spec.ts b/server/src/services/library.service.spec.ts index a3b270218ef48..9b944045ab738 100644 --- a/server/src/services/library.service.spec.ts +++ b/server/src/services/library.service.spec.ts @@ -5,6 +5,8 @@ import { mapLibrary } from 'src/dtos/library.dto'; import { UserEntity } from 'src/entities/user.entity'; import { AssetType, ImmichWorker } from 'src/enum'; import { IAssetRepository } from 'src/interfaces/asset.interface'; +import { IConfigRepository } from 'src/interfaces/config.interface'; +import { ICronRepository } from 'src/interfaces/cron.interface'; import { IDatabaseRepository } from 'src/interfaces/database.interface'; import { IJobRepository, @@ -16,7 +18,6 @@ import { } from 'src/interfaces/job.interface'; import { ILibraryRepository } from 'src/interfaces/library.interface'; import { IStorageRepository } from 'src/interfaces/storage.interface'; -import { ISystemMetadataRepository } from 'src/interfaces/system-metadata.interface'; import { LibraryService } from 'src/services/library.service'; import { assetStub } from 'test/fixtures/asset.stub'; import { authStub } from 'test/fixtures/auth.stub'; @@ -35,30 +36,30 @@ describe(LibraryService.name, () => { let sut: LibraryService; let assetMock: Mocked; + let configMock: Mocked; + let cronMock: Mocked; let databaseMock: Mocked; let jobMock: Mocked; let libraryMock: Mocked; let storageMock: Mocked; - let systemMock: Mocked; beforeEach(() => { - ({ sut, assetMock, databaseMock, jobMock, libraryMock, storageMock, systemMock } = newTestService(LibraryService)); + ({ sut, assetMock, configMock, cronMock, databaseMock, jobMock, libraryMock, storageMock } = + newTestService(LibraryService)); databaseMock.tryLock.mockResolvedValue(true); + configMock.getWorker.mockReturnValue(ImmichWorker.MICROSERVICES); }); it('should work', () => { expect(sut).toBeDefined(); }); - describe('onBootstrapEvent', () => { + describe('onConfigInit', () => { it('should init cron job and handle config changes', async () => { - systemMock.get.mockResolvedValue(systemConfigStub.libraryScan); + await sut.onConfigInit({ newConfig: defaults }); - await sut.onBootstrap(ImmichWorker.MICROSERVICES); - - expect(jobMock.addCronJob).toHaveBeenCalled(); - expect(systemMock.get).toHaveBeenCalled(); + expect(cronMock.create).toHaveBeenCalled(); await sut.onConfigUpdate({ oldConfig: defaults, @@ -73,7 +74,7 @@ describe(LibraryService.name, () => { } as SystemConfig, }); - expect(jobMock.updateCronJob).toHaveBeenCalledWith('libraryScan', '0 1 * * *', true); + expect(cronMock.update).toHaveBeenCalledWith({ name: 'libraryScan', expression: '0 1 * * *', start: true }); }); it('should initialize watcher for all external libraries', async () => { @@ -82,7 +83,6 @@ describe(LibraryService.name, () => { libraryStub.externalLibraryWithImportPaths2, ]); - systemMock.get.mockResolvedValue(systemConfigStub.libraryWatchEnabled); libraryMock.get.mockImplementation((id) => Promise.resolve( [libraryStub.externalLibraryWithImportPaths1, libraryStub.externalLibraryWithImportPaths2].find( @@ -91,7 +91,7 @@ describe(LibraryService.name, () => { ), ); - await sut.onBootstrap(ImmichWorker.MICROSERVICES); + await sut.onConfigInit({ newConfig: systemConfigStub.libraryWatchEnabled as SystemConfig }); expect(storageMock.watch.mock.calls).toEqual( expect.arrayContaining([ @@ -102,113 +102,71 @@ describe(LibraryService.name, () => { }); it('should not initialize watcher when watching is disabled', async () => { - systemMock.get.mockResolvedValue(systemConfigStub.libraryWatchDisabled); - - await sut.onBootstrap(ImmichWorker.MICROSERVICES); + await sut.onConfigInit({ newConfig: systemConfigStub.libraryWatchDisabled as SystemConfig }); expect(storageMock.watch).not.toHaveBeenCalled(); }); it('should not initialize watcher when lock is taken', async () => { - systemMock.get.mockResolvedValue(systemConfigStub.libraryWatchEnabled); databaseMock.tryLock.mockResolvedValue(false); - await sut.onBootstrap(ImmichWorker.MICROSERVICES); + await sut.onConfigInit({ newConfig: systemConfigStub.libraryWatchEnabled as SystemConfig }); expect(storageMock.watch).not.toHaveBeenCalled(); }); it('should not initialize library scan cron job when lock is taken', async () => { - systemMock.get.mockResolvedValue(systemConfigStub.libraryWatchEnabled); databaseMock.tryLock.mockResolvedValue(false); - await sut.onBootstrap(ImmichWorker.MICROSERVICES); - - expect(jobMock.addCronJob).not.toHaveBeenCalled(); - }); - - it('should not initialize watcher or library scan job when running on api', async () => { - await sut.onBootstrap(ImmichWorker.API); + await sut.onConfigInit({ newConfig: systemConfigStub.libraryWatchEnabled as SystemConfig }); - expect(jobMock.addCronJob).not.toHaveBeenCalled(); + expect(cronMock.create).not.toHaveBeenCalled(); }); }); describe('onConfigUpdateEvent', () => { beforeEach(async () => { - systemMock.get.mockResolvedValue(defaults); databaseMock.tryLock.mockResolvedValue(true); - await sut.onBootstrap(ImmichWorker.MICROSERVICES); - }); - - it('should do nothing if oldConfig is not provided', async () => { - await sut.onConfigUpdate({ newConfig: systemConfigStub.libraryScan as SystemConfig }); - expect(jobMock.updateCronJob).not.toHaveBeenCalled(); + await sut.onConfigInit({ newConfig: defaults }); }); it('should do nothing if instance does not have the watch lock', async () => { databaseMock.tryLock.mockResolvedValue(false); - await sut.onBootstrap(ImmichWorker.MICROSERVICES); + await sut.onConfigInit({ newConfig: defaults }); await sut.onConfigUpdate({ newConfig: systemConfigStub.libraryScan as SystemConfig, oldConfig: defaults }); - expect(jobMock.updateCronJob).not.toHaveBeenCalled(); + expect(cronMock.update).not.toHaveBeenCalled(); }); it('should update cron job and enable watching', async () => { libraryMock.getAll.mockResolvedValue([]); await sut.onConfigUpdate({ - newConfig: { - library: { ...systemConfigStub.libraryScan.library, ...systemConfigStub.libraryWatchEnabled.library }, - } as SystemConfig, + newConfig: systemConfigStub.libraryScanAndWatch as SystemConfig, oldConfig: defaults, }); - expect(jobMock.updateCronJob).toHaveBeenCalledWith( - 'libraryScan', - systemConfigStub.libraryScan.library.scan.cronExpression, - systemConfigStub.libraryScan.library.scan.enabled, - ); + expect(cronMock.update).toHaveBeenCalledWith({ + name: 'libraryScan', + expression: systemConfigStub.libraryScan.library.scan.cronExpression, + start: systemConfigStub.libraryScan.library.scan.enabled, + }); }); it('should update cron job and disable watching', async () => { libraryMock.getAll.mockResolvedValue([]); await sut.onConfigUpdate({ - newConfig: { - library: { ...systemConfigStub.libraryScan.library, ...systemConfigStub.libraryWatchEnabled.library }, - } as SystemConfig, + newConfig: systemConfigStub.libraryScanAndWatch as SystemConfig, oldConfig: defaults, }); await sut.onConfigUpdate({ - newConfig: { - library: { ...systemConfigStub.libraryScan.library, ...systemConfigStub.libraryWatchDisabled.library }, - } as SystemConfig, + newConfig: systemConfigStub.libraryScan as SystemConfig, oldConfig: defaults, }); - expect(jobMock.updateCronJob).toHaveBeenCalledWith( - 'libraryScan', - systemConfigStub.libraryScan.library.scan.cronExpression, - systemConfigStub.libraryScan.library.scan.enabled, - ); - }); - }); - - describe('onConfigValidateEvent', () => { - it('should allow a valid cron expression', () => { - expect(() => - sut.onConfigValidate({ - newConfig: { library: { scan: { cronExpression: '0 0 * * *' } } } as SystemConfig, - oldConfig: {} as SystemConfig, - }), - ).not.toThrow(expect.stringContaining('Invalid cron expression')); - }); - - it('should fail for an invalid cron expression', () => { - expect(() => - sut.onConfigValidate({ - newConfig: { library: { scan: { cronExpression: 'foo' } } } as SystemConfig, - oldConfig: {} as SystemConfig, - }), - ).toThrow(/Invalid cron expression.*/); + expect(cronMock.update).toHaveBeenCalledWith({ + name: 'libraryScan', + expression: systemConfigStub.libraryScan.library.scan.cronExpression, + start: systemConfigStub.libraryScan.library.scan.enabled, + }); }); }); @@ -456,7 +414,6 @@ describe(LibraryService.name, () => { localDateTime: expect.any(Date), type: AssetType.IMAGE, originalFileName: 'photo.jpg', - sidecarPath: null, isExternal: true, }, ], @@ -465,57 +422,9 @@ describe(LibraryService.name, () => { expect(jobMock.queue.mock.calls).toEqual([ [ { - name: JobName.METADATA_EXTRACTION, + name: JobName.SIDECAR_DISCOVERY, data: { id: assetStub.image.id, - source: 'upload', - }, - }, - ], - ]); - }); - - it('should import a new asset with sidecar', async () => { - const mockLibraryJob: ILibraryFileJob = { - id: libraryStub.externalLibrary1.id, - ownerId: mockUser.id, - assetPath: '/data/user1/photo.jpg', - }; - - assetMock.getByLibraryIdAndOriginalPath.mockResolvedValue(null); - assetMock.create.mockResolvedValue(assetStub.image); - storageMock.checkFileExists.mockResolvedValue(true); - libraryMock.get.mockResolvedValue(libraryStub.externalLibrary1); - - await expect(sut.handleSyncFile(mockLibraryJob)).resolves.toBe(JobStatus.SUCCESS); - - expect(assetMock.create.mock.calls).toEqual([ - [ - { - ownerId: mockUser.id, - libraryId: libraryStub.externalLibrary1.id, - checksum: expect.any(Buffer), - originalPath: '/data/user1/photo.jpg', - deviceAssetId: expect.any(String), - deviceId: 'Library Import', - fileCreatedAt: expect.any(Date), - fileModifiedAt: expect.any(Date), - localDateTime: expect.any(Date), - type: AssetType.IMAGE, - originalFileName: 'photo.jpg', - sidecarPath: '/data/user1/photo.jpg.xmp', - isExternal: true, - }, - ], - ]); - - expect(jobMock.queue.mock.calls).toEqual([ - [ - { - name: JobName.METADATA_EXTRACTION, - data: { - id: assetStub.image.id, - source: 'upload', }, }, ], @@ -549,7 +458,6 @@ describe(LibraryService.name, () => { localDateTime: expect.any(Date), type: AssetType.VIDEO, originalFileName: 'video.mp4', - sidecarPath: null, isExternal: true, }, ], @@ -558,10 +466,9 @@ describe(LibraryService.name, () => { expect(jobMock.queue.mock.calls).toEqual([ [ { - name: JobName.METADATA_EXTRACTION, + name: JobName.SIDECAR_DISCOVERY, data: { id: assetStub.image.id, - source: 'upload', }, }, ], @@ -703,12 +610,10 @@ describe(LibraryService.name, () => { libraryMock.get.mockResolvedValue(libraryStub.externalLibraryWithImportPaths1); libraryMock.getAll.mockResolvedValue([libraryStub.externalLibraryWithImportPaths1]); - systemMock.get.mockResolvedValue(systemConfigStub.libraryWatchEnabled); - const mockClose = vitest.fn(); storageMock.watch.mockImplementation(makeMockWatcher({ close: mockClose })); - await sut.onBootstrap(ImmichWorker.MICROSERVICES); + await sut.onConfigInit({ newConfig: systemConfigStub.libraryWatchEnabled as SystemConfig }); await sut.delete(libraryStub.externalLibraryWithImportPaths1.id); expect(mockClose).toHaveBeenCalled(); @@ -837,12 +742,11 @@ describe(LibraryService.name, () => { }); it('should create watched with import paths', async () => { - systemMock.get.mockResolvedValue(systemConfigStub.libraryWatchEnabled); libraryMock.create.mockResolvedValue(libraryStub.externalLibraryWithImportPaths1); libraryMock.get.mockResolvedValue(libraryStub.externalLibraryWithImportPaths1); libraryMock.getAll.mockResolvedValue([]); - await sut.onBootstrap(ImmichWorker.MICROSERVICES); + await sut.onConfigInit({ newConfig: systemConfigStub.libraryWatchEnabled as SystemConfig }); await sut.create({ ownerId: authStub.admin.user.id, importPaths: libraryStub.externalLibraryWithImportPaths1.importPaths, @@ -902,10 +806,9 @@ describe(LibraryService.name, () => { describe('update', () => { beforeEach(async () => { - systemMock.get.mockResolvedValue(systemConfigStub.libraryWatchEnabled); libraryMock.getAll.mockResolvedValue([]); - await sut.onBootstrap(ImmichWorker.MICROSERVICES); + await sut.onConfigInit({ newConfig: systemConfigStub.libraryWatchEnabled as SystemConfig }); }); it('should throw an error if an import path is invalid', async () => { @@ -944,9 +847,7 @@ describe(LibraryService.name, () => { describe('watching disabled', () => { beforeEach(async () => { - systemMock.get.mockResolvedValue(systemConfigStub.libraryWatchDisabled); - - await sut.onBootstrap(ImmichWorker.MICROSERVICES); + await sut.onConfigInit({ newConfig: systemConfigStub.libraryWatchDisabled as SystemConfig }); }); it('should not watch library', async () => { @@ -960,9 +861,8 @@ describe(LibraryService.name, () => { describe('watching enabled', () => { beforeEach(async () => { - systemMock.get.mockResolvedValue(systemConfigStub.libraryWatchEnabled); libraryMock.getAll.mockResolvedValue([]); - await sut.onBootstrap(ImmichWorker.MICROSERVICES); + await sut.onConfigInit({ newConfig: systemConfigStub.libraryWatchEnabled as SystemConfig }); }); it('should watch library', async () => { @@ -1114,7 +1014,6 @@ describe(LibraryService.name, () => { libraryStub.externalLibraryWithImportPaths2, ]); - systemMock.get.mockResolvedValue(systemConfigStub.libraryWatchEnabled); libraryMock.get.mockResolvedValue(libraryStub.externalLibrary1); libraryMock.get.mockImplementation((id) => @@ -1128,7 +1027,7 @@ describe(LibraryService.name, () => { const mockClose = vitest.fn(); storageMock.watch.mockImplementation(makeMockWatcher({ close: mockClose })); - await sut.onBootstrap(ImmichWorker.MICROSERVICES); + await sut.onConfigInit({ newConfig: systemConfigStub.libraryWatchEnabled as SystemConfig }); await sut.onShutdown(); expect(mockClose).toHaveBeenCalledTimes(2); diff --git a/server/src/services/library.service.ts b/server/src/services/library.service.ts index 6c329e80ec140..0deddc894195b 100644 --- a/server/src/services/library.service.ts +++ b/server/src/services/library.service.ts @@ -3,7 +3,7 @@ import { R_OK } from 'node:constants'; import path, { basename, isAbsolute, parse } from 'node:path'; import picomatch from 'picomatch'; import { StorageCore } from 'src/cores/storage.core'; -import { OnEvent } from 'src/decorators'; +import { OnEvent, OnJob } from 'src/decorators'; import { CreateLibraryDto, LibraryResponseDto, @@ -19,19 +19,11 @@ import { LibraryEntity } from 'src/entities/library.entity'; import { AssetType, ImmichWorker } from 'src/enum'; import { DatabaseLock } from 'src/interfaces/database.interface'; import { ArgOf } from 'src/interfaces/event.interface'; -import { - IEntityJob, - ILibraryAssetJob, - ILibraryFileJob, - JobName, - JOBS_LIBRARY_PAGINATION_SIZE, - JobStatus, -} from 'src/interfaces/job.interface'; +import { JobName, JobOf, JOBS_LIBRARY_PAGINATION_SIZE, JobStatus, QueueName } from 'src/interfaces/job.interface'; import { BaseService } from 'src/services/base.service'; import { mimeTypes } from 'src/utils/mime-types'; import { handlePromiseError } from 'src/utils/misc'; import { usePagination } from 'src/utils/pagination'; -import { validateCronExpression } from 'src/validation'; @Injectable() export class LibraryService extends BaseService { @@ -39,28 +31,25 @@ export class LibraryService extends BaseService { private lock = false; private watchers: Record Promise> = {}; - @OnEvent({ name: 'app.bootstrap' }) - async onBootstrap(workerType: ImmichWorker) { - if (workerType !== ImmichWorker.MICROSERVICES) { - return; - } - - const config = await this.getConfig({ withCache: false }); - - const { watch, scan } = config.library; - + @OnEvent({ name: 'config.init', workers: [ImmichWorker.MICROSERVICES] }) + async onConfigInit({ + newConfig: { + library: { watch, scan }, + }, + }: ArgOf<'config.init'>) { // This ensures that library watching only occurs in one microservice this.lock = await this.databaseRepository.tryLock(DatabaseLock.Library); this.watchLibraries = this.lock && watch.enabled; if (this.lock) { - this.jobRepository.addCronJob( - 'libraryScan', - scan.cronExpression, - () => handlePromiseError(this.jobRepository.queue({ name: JobName.LIBRARY_QUEUE_SYNC_ALL }), this.logger), - scan.enabled, - ); + this.cronRepository.create({ + name: 'libraryScan', + expression: scan.cronExpression, + onTick: () => + handlePromiseError(this.jobRepository.queue({ name: JobName.LIBRARY_QUEUE_SYNC_ALL }), this.logger), + start: scan.enabled, + }); } if (this.watchLibraries) { @@ -69,12 +58,16 @@ export class LibraryService extends BaseService { } @OnEvent({ name: 'config.update', server: true }) - async onConfigUpdate({ newConfig: { library }, oldConfig }: ArgOf<'config.update'>) { - if (!oldConfig || !this.lock) { + async onConfigUpdate({ newConfig: { library } }: ArgOf<'config.update'>) { + if (!this.lock) { return; } - this.jobRepository.updateCronJob('libraryScan', library.scan.cronExpression, library.scan.enabled); + this.cronRepository.update({ + name: 'libraryScan', + expression: library.scan.cronExpression, + start: library.scan.enabled, + }); if (library.watch.enabled !== this.watchLibraries) { // Watch configuration changed, update accordingly @@ -83,14 +76,6 @@ export class LibraryService extends BaseService { } } - @OnEvent({ name: 'config.validate' }) - onConfigValidate({ newConfig }: ArgOf<'config.validate'>) { - const { scan } = newConfig.library; - if (!validateCronExpression(scan.cronExpression)) { - throw new Error(`Invalid cron expression ${scan.cronExpression}`); - } - } - private async watch(id: string): Promise { if (!this.watchLibraries) { return false; @@ -223,6 +208,7 @@ export class LibraryService extends BaseService { return libraries.map((library) => mapLibrary(library)); } + @OnJob({ name: JobName.LIBRARY_QUEUE_CLEANUP, queue: QueueName.LIBRARY }) async handleQueueCleanup(): Promise { this.logger.debug('Cleaning up any pending library deletions'); const pendingDeletion = await this.libraryRepository.getAllDeleted(); @@ -340,7 +326,8 @@ export class LibraryService extends BaseService { await this.jobRepository.queue({ name: JobName.LIBRARY_DELETE, data: { id } }); } - async handleDeleteLibrary(job: IEntityJob): Promise { + @OnJob({ name: JobName.LIBRARY_DELETE, queue: QueueName.LIBRARY }) + async handleDeleteLibrary(job: JobOf): Promise { const libraryId = job.id; const assetPagination = usePagination(JOBS_LIBRARY_PAGINATION_SIZE, (pagination) => @@ -374,7 +361,8 @@ export class LibraryService extends BaseService { return JobStatus.SUCCESS; } - async handleSyncFile(job: ILibraryFileJob): Promise { + @OnJob({ name: JobName.LIBRARY_SYNC_FILE, queue: QueueName.LIBRARY }) + async handleSyncFile(job: JobOf): Promise { // Only needs to handle new assets const assetPath = path.normalize(job.assetPath); @@ -408,12 +396,6 @@ export class LibraryService extends BaseService { const pathHash = this.cryptoRepository.hashSha1(`path:${assetPath}`); - // TODO: doesn't xmp replace the file extension? Will need investigation - let sidecarPath: string | null = null; - if (await this.storageRepository.checkFileExists(`${assetPath}.xmp`, R_OK)) { - sidecarPath = `${assetPath}.xmp`; - } - const assetType = mimeTypes.isVideo(assetPath) ? AssetType.VIDEO : AssetType.IMAGE; const mtime = stat.mtime; @@ -430,8 +412,6 @@ export class LibraryService extends BaseService { localDateTime: mtime, type: assetType, originalFileName: parse(assetPath).base, - - sidecarPath, isExternal: true, }); @@ -443,7 +423,11 @@ export class LibraryService extends BaseService { async queuePostSyncJobs(asset: AssetEntity) { this.logger.debug(`Queueing metadata extraction for: ${asset.originalPath}`); - await this.jobRepository.queue({ name: JobName.METADATA_EXTRACTION, data: { id: asset.id, source: 'upload' } }); + // We queue a sidecar discovery which, in turn, queues metadata extraction + await this.jobRepository.queue({ + name: JobName.SIDECAR_DISCOVERY, + data: { id: asset.id }, + }); } async queueScan(id: string) { @@ -458,6 +442,7 @@ export class LibraryService extends BaseService { await this.jobRepository.queue({ name: JobName.LIBRARY_QUEUE_SYNC_ASSETS, data: { id } }); } + @OnJob({ name: JobName.LIBRARY_QUEUE_SYNC_ALL, queue: QueueName.LIBRARY }) async handleQueueSyncAll(): Promise { this.logger.debug(`Refreshing all external libraries`); @@ -483,7 +468,8 @@ export class LibraryService extends BaseService { return JobStatus.SUCCESS; } - async handleSyncAsset(job: ILibraryAssetJob): Promise { + @OnJob({ name: JobName.LIBRARY_SYNC_ASSET, queue: QueueName.LIBRARY }) + async handleSyncAsset(job: JobOf): Promise { const asset = await this.assetRepository.getById(job.id); if (!asset) { return JobStatus.SKIPPED; @@ -538,7 +524,8 @@ export class LibraryService extends BaseService { return JobStatus.SUCCESS; } - async handleQueueSyncFiles(job: IEntityJob): Promise { + @OnJob({ name: JobName.LIBRARY_QUEUE_SYNC_FILES, queue: QueueName.LIBRARY }) + async handleQueueSyncFiles(job: JobOf): Promise { const library = await this.libraryRepository.get(job.id); if (!library) { this.logger.debug(`Library ${job.id} not found, skipping refresh`); @@ -589,7 +576,8 @@ export class LibraryService extends BaseService { return JobStatus.SUCCESS; } - async handleQueueSyncAssets(job: IEntityJob): Promise { + @OnJob({ name: JobName.LIBRARY_QUEUE_SYNC_ASSETS, queue: QueueName.LIBRARY }) + async handleQueueSyncAssets(job: JobOf): Promise { const library = await this.libraryRepository.get(job.id); if (!library) { return JobStatus.SKIPPED; diff --git a/server/src/services/media.service.spec.ts b/server/src/services/media.service.spec.ts index 65166f42936a3..36a9045677460 100644 --- a/server/src/services/media.service.spec.ts +++ b/server/src/services/media.service.spec.ts @@ -1,4 +1,3 @@ -import type { Stats } from 'node:fs'; import { SystemConfig } from 'src/config'; import { AssetEntity } from 'src/entities/asset.entity'; import { ExifEntity } from 'src/entities/exif.entity'; @@ -9,7 +8,6 @@ import { AudioCodec, Colorspace, ImageFormat, - ToneMapping, TranscodeHWAccel, TranscodePolicy, VideoCodec, @@ -304,7 +302,7 @@ describe(MediaService.name, () => { it('should skip video thumbnail generation if no video stream', async () => { mediaMock.probe.mockResolvedValue(probeStub.noVideoStreams); assetMock.getById.mockResolvedValue(assetStub.video); - await expect(sut.handleGenerateThumbnails({ id: assetStub.video.id })).rejects.toBeInstanceOf(Error); + await expect(sut.handleGenerateThumbnails({ id: assetStub.video.id })).rejects.toThrowError(); expect(mediaMock.generateThumbnail).not.toHaveBeenCalled(); expect(assetMock.update).not.toHaveBeenCalledWith(); }); @@ -410,7 +408,7 @@ describe(MediaService.name, () => { '-frames:v 1', '-update 1', '-v verbose', - String.raw`-vf fps=12:eof_action=pass:round=down,thumbnail=12,select=gt(scene\,0.1)-eq(prev_selected_n\,n)+isnan(prev_selected_n)+gt(n\,20),trim=end_frame=2,reverse,scale=-2:1440:flags=lanczos+accurate_rnd+full_chroma_int:out_color_matrix=bt601:out_range=pc,format=yuv420p`, + String.raw`-vf fps=12:eof_action=pass:round=down,thumbnail=12,select=gt(scene\,0.1)-eq(prev_selected_n\,n)+isnan(prev_selected_n)+gt(n\,20),trim=end_frame=2,reverse,scale=-2:1440:flags=lanczos+accurate_rnd+full_chroma_int:out_range=pc`, ], twoPass: false, }), @@ -445,7 +443,7 @@ describe(MediaService.name, () => { '-frames:v 1', '-update 1', '-v verbose', - String.raw`-vf fps=12:eof_action=pass:round=down,thumbnail=12,select=gt(scene\,0.1)-eq(prev_selected_n\,n)+isnan(prev_selected_n)+gt(n\,20),trim=end_frame=2,reverse,zscale=t=linear:npl=100,tonemap=hable:desat=0,zscale=p=709:t=601:m=470bg:range=pc,format=yuv420p`, + String.raw`-vf fps=12:eof_action=pass:round=down,thumbnail=12,select=gt(scene\,0.1)-eq(prev_selected_n\,n)+isnan(prev_selected_n)+gt(n\,20),trim=end_frame=2,reverse,tonemapx=tonemap=hable:desat=0:p=bt709:t=bt709:m=bt709:r=pc:peak=100:format=yuv420p`, ], twoPass: false, }), @@ -482,12 +480,28 @@ describe(MediaService.name, () => { '-frames:v 1', '-update 1', '-v verbose', - String.raw`-vf fps=12:eof_action=pass:round=down,thumbnail=12,select=gt(scene\,0.1)-eq(prev_selected_n\,n)+isnan(prev_selected_n)+gt(n\,20),trim=end_frame=2,reverse,zscale=t=linear:npl=100,tonemap=hable:desat=0,zscale=p=709:t=601:m=470bg:range=pc,format=yuv420p`, + String.raw`-vf fps=12:eof_action=pass:round=down,thumbnail=12,select=gt(scene\,0.1)-eq(prev_selected_n\,n)+isnan(prev_selected_n)+gt(n\,20),trim=end_frame=2,reverse,tonemapx=tonemap=hable:desat=0:p=bt709:t=bt709:m=bt709:r=pc:peak=100:format=yuv420p`, ], twoPass: false, }), ); }); + it('should not skip intra frames for MTS file', async () => { + mediaMock.probe.mockResolvedValue(probeStub.videoStreamMTS); + assetMock.getById.mockResolvedValue(assetStub.video); + await sut.handleGenerateThumbnails({ id: assetStub.video.id }); + + expect(mediaMock.transcode).toHaveBeenCalledWith( + '/original/path.ext', + 'upload/thumbs/user-id/as/se/asset-id-preview.jpeg', + expect.objectContaining({ + inputOptions: ['-sws_flags accurate_rnd+full_chroma_int'], + outputOptions: expect.any(Array), + progress: expect.any(Object), + twoPass: false, + }), + ); + }); it('should use scaling divisible by 2 even when using quick sync', async () => { mediaMock.probe.mockResolvedValue(probeStub.videoStream2160p); @@ -755,6 +769,7 @@ describe(MediaService.name, () => { describe('handleVideoConversion', () => { beforeEach(() => { assetMock.getByIds.mockResolvedValue([assetStub.video]); + sut.videoInterfaces = { dri: ['renderD128'], mali: true }; }); it('should skip transcoding if asset not found', async () => { @@ -811,7 +826,7 @@ describe(MediaService.name, () => { systemMock.get.mockResolvedValue({ ffmpeg: { transcode: 'foo' } } as never as SystemConfig); assetMock.getByIds.mockResolvedValue([assetStub.video]); - await expect(sut.handleVideoConversion({ id: assetStub.video.id })).rejects.toBeDefined(); + await expect(sut.handleVideoConversion({ id: assetStub.video.id })).rejects.toThrowError(); expect(mediaMock.transcode).not.toHaveBeenCalled(); }); @@ -1064,7 +1079,7 @@ describe(MediaService.name, () => { mediaMock.probe.mockResolvedValue(probeStub.videoStream2160p); systemMock.get.mockResolvedValue({ ffmpeg: { transcode: 'invalid' as any } }); - await expect(sut.handleVideoConversion({ id: assetStub.video.id })).rejects.toThrow(); + await expect(sut.handleVideoConversion({ id: assetStub.video.id })).rejects.toThrowError(); expect(mediaMock.transcode).not.toHaveBeenCalled(); }); @@ -1328,7 +1343,7 @@ describe(MediaService.name, () => { '-map 0:0', '-map 0:1', '-v verbose', - '-vf scale=-2:720,format=yuv420p', + '-vf scale=-2:720', '-preset 12', '-crf 23', ]), @@ -1419,7 +1434,7 @@ describe(MediaService.name, () => { mediaMock.probe.mockResolvedValue(probeStub.matroskaContainer); systemMock.get.mockResolvedValue({ ffmpeg: { accel: TranscodeHWAccel.NVENC, targetVideoCodec: VideoCodec.VP9 } }); assetMock.getByIds.mockResolvedValue([assetStub.video]); - await expect(sut.handleVideoConversion({ id: assetStub.video.id })).resolves.toBe(JobStatus.FAILED); + await expect(sut.handleVideoConversion({ id: assetStub.video.id })).rejects.toThrowError(); expect(mediaMock.transcode).not.toHaveBeenCalled(); }); @@ -1427,7 +1442,7 @@ describe(MediaService.name, () => { mediaMock.probe.mockResolvedValue(probeStub.matroskaContainer); systemMock.get.mockResolvedValue({ ffmpeg: { accel: 'invalid' as any } }); assetMock.getByIds.mockResolvedValue([assetStub.video]); - await expect(sut.handleVideoConversion({ id: assetStub.video.id })).resolves.toBe(JobStatus.FAILED); + await expect(sut.handleVideoConversion({ id: assetStub.video.id })).rejects.toThrowError(); expect(mediaMock.transcode).not.toHaveBeenCalled(); }); @@ -1454,7 +1469,7 @@ describe(MediaService.name, () => { '-map 0:1', '-g 256', '-v verbose', - '-vf format=nv12,hwupload_cuda,scale_cuda=-2:720', + '-vf hwupload_cuda,scale_cuda=-2:720:format=nv12', '-preset p1', '-cq:v 23', ]), @@ -1586,7 +1601,7 @@ describe(MediaService.name, () => { inputOptions: expect.arrayContaining(['-hwaccel cuda', '-hwaccel_output_format cuda']), outputOptions: expect.arrayContaining([ expect.stringContaining( - 'tonemap_cuda=desat=0:matrix=bt709:primaries=bt709:range=pc:tonemap=hable:transfer=bt709:format=nv12', + 'tonemap_cuda=desat=0:matrix=bt709:primaries=bt709:range=pc:tonemap=hable:tonemap_mode=lum:transfer=bt709:peak=100:format=nv12', ), ]), twoPass: false, @@ -1594,8 +1609,25 @@ describe(MediaService.name, () => { ); }); + it('should set format to nv12 for nvenc if input is not yuv420p', async () => { + mediaMock.probe.mockResolvedValue(probeStub.videoStream10Bit); + systemMock.get.mockResolvedValue({ + ffmpeg: { accel: TranscodeHWAccel.NVENC, accelDecode: true }, + }); + assetMock.getByIds.mockResolvedValue([assetStub.video]); + await sut.handleVideoConversion({ id: assetStub.video.id }); + expect(mediaMock.transcode).toHaveBeenCalledWith( + '/original/path.ext', + 'upload/encoded-video/user-id/as/se/asset-id.mp4', + expect.objectContaining({ + inputOptions: expect.arrayContaining(['-hwaccel cuda', '-hwaccel_output_format cuda']), + outputOptions: expect.arrayContaining([expect.stringContaining('format=nv12')]), + twoPass: false, + }), + ); + }); + it('should set options for qsv', async () => { - storageMock.readdir.mockResolvedValue(['renderD128']); mediaMock.probe.mockResolvedValue(probeStub.matroskaContainer); systemMock.get.mockResolvedValue({ ffmpeg: { accel: TranscodeHWAccel.QSV, maxBitrate: '10000k' } }); assetMock.getByIds.mockResolvedValue([assetStub.video]); @@ -1604,7 +1636,10 @@ describe(MediaService.name, () => { '/original/path.ext', 'upload/encoded-video/user-id/as/se/asset-id.mp4', expect.objectContaining({ - inputOptions: expect.arrayContaining(['-init_hw_device qsv=hw', '-filter_hw_device hw']), + inputOptions: expect.arrayContaining([ + '-init_hw_device qsv=hw,child_device=/dev/dri/renderD128', + '-filter_hw_device hw', + ]), outputOptions: expect.arrayContaining([ `-c:v h264_qsv`, '-c:a copy', @@ -1616,7 +1651,7 @@ describe(MediaService.name, () => { '-refs 5', '-g 256', '-v verbose', - '-vf format=nv12,hwupload=extra_hw_frames=64,scale_qsv=-1:720:mode=hq', + '-vf hwupload=extra_hw_frames=64,scale_qsv=-1:720:mode=hq:format=nv12', '-preset 7', '-global_quality:v 23', '-maxrate 10000k', @@ -1628,7 +1663,6 @@ describe(MediaService.name, () => { }); it('should set options for qsv with custom dri node', async () => { - storageMock.readdir.mockResolvedValue(['renderD128']); mediaMock.probe.mockResolvedValue(probeStub.matroskaContainer); systemMock.get.mockResolvedValue({ ffmpeg: { @@ -1654,7 +1688,6 @@ describe(MediaService.name, () => { }); it('should omit preset for qsv if invalid', async () => { - storageMock.readdir.mockResolvedValue(['renderD128']); mediaMock.probe.mockResolvedValue(probeStub.matroskaContainer); systemMock.get.mockResolvedValue({ ffmpeg: { accel: TranscodeHWAccel.QSV, preset: 'invalid' } }); assetMock.getByIds.mockResolvedValue([assetStub.video]); @@ -1663,7 +1696,10 @@ describe(MediaService.name, () => { '/original/path.ext', 'upload/encoded-video/user-id/as/se/asset-id.mp4', expect.objectContaining({ - inputOptions: expect.arrayContaining(['-init_hw_device qsv=hw', '-filter_hw_device hw']), + inputOptions: expect.arrayContaining([ + '-init_hw_device qsv=hw,child_device=/dev/dri/renderD128', + '-filter_hw_device hw', + ]), outputOptions: expect.not.arrayContaining([expect.stringContaining('-preset')]), twoPass: false, }), @@ -1671,7 +1707,6 @@ describe(MediaService.name, () => { }); it('should set low power mode for qsv if target video codec is vp9', async () => { - storageMock.readdir.mockResolvedValue(['renderD128']); mediaMock.probe.mockResolvedValue(probeStub.matroskaContainer); systemMock.get.mockResolvedValue({ ffmpeg: { accel: TranscodeHWAccel.QSV, targetVideoCodec: VideoCodec.VP9 } }); assetMock.getByIds.mockResolvedValue([assetStub.video]); @@ -1680,7 +1715,10 @@ describe(MediaService.name, () => { '/original/path.ext', 'upload/encoded-video/user-id/as/se/asset-id.mp4', expect.objectContaining({ - inputOptions: expect.arrayContaining(['-init_hw_device qsv=hw', '-filter_hw_device hw']), + inputOptions: expect.arrayContaining([ + '-init_hw_device qsv=hw,child_device=/dev/dri/renderD128', + '-filter_hw_device hw', + ]), outputOptions: expect.arrayContaining(['-low_power 1']), twoPass: false, }), @@ -1688,17 +1726,37 @@ describe(MediaService.name, () => { }); it('should fail for qsv if no hw devices', async () => { - storageMock.readdir.mockRejectedValue(new Error('Could not read directory')); + sut.videoInterfaces = { dri: [], mali: false }; mediaMock.probe.mockResolvedValue(probeStub.matroskaContainer); systemMock.get.mockResolvedValue({ ffmpeg: { accel: TranscodeHWAccel.QSV } }); assetMock.getByIds.mockResolvedValue([assetStub.video]); - await expect(sut.handleVideoConversion({ id: assetStub.video.id })).resolves.toBe(JobStatus.FAILED); + + await expect(sut.handleVideoConversion({ id: assetStub.video.id })).rejects.toThrowError(); + expect(mediaMock.transcode).not.toHaveBeenCalled(); - expect(loggerMock.debug).toHaveBeenCalledWith('No devices found in /dev/dri.'); + }); + + it('should prefer higher index renderD* device for qsv', async () => { + sut.videoInterfaces = { dri: ['card1', 'renderD129', 'card0', 'renderD128'], mali: false }; + mediaMock.probe.mockResolvedValue(probeStub.matroskaContainer); + systemMock.get.mockResolvedValue({ ffmpeg: { accel: TranscodeHWAccel.QSV } }); + assetMock.getByIds.mockResolvedValue([assetStub.video]); + await sut.handleVideoConversion({ id: assetStub.video.id }); + expect(mediaMock.transcode).toHaveBeenCalledWith( + '/original/path.ext', + 'upload/encoded-video/user-id/as/se/asset-id.mp4', + expect.objectContaining({ + inputOptions: expect.arrayContaining([ + '-init_hw_device qsv=hw,child_device=/dev/dri/renderD129', + '-filter_hw_device hw', + ]), + outputOptions: expect.arrayContaining([`-c:v h264_qsv`]), + twoPass: false, + }), + ); }); it('should use hardware decoding for qsv if enabled', async () => { - storageMock.readdir.mockResolvedValue(['renderD128']); mediaMock.probe.mockResolvedValue(probeStub.matroskaContainer); systemMock.get.mockResolvedValue({ ffmpeg: { accel: TranscodeHWAccel.QSV, accelDecode: true }, @@ -1717,6 +1775,7 @@ describe(MediaService.name, () => { '-async_depth 4', '-noautorotate', '-threads 1', + '-qsv_device /dev/dri/renderD128', ]), outputOptions: expect.arrayContaining([ expect.stringContaining('scale_qsv=-1:720:async_depth=4:mode=hq:format=nv12'), @@ -1727,7 +1786,6 @@ describe(MediaService.name, () => { }); it('should use hardware tone-mapping for qsv if hardware decoding is enabled and should tone map', async () => { - storageMock.readdir.mockResolvedValue(['renderD128']); mediaMock.probe.mockResolvedValue(probeStub.videoStreamHDR); systemMock.get.mockResolvedValue({ ffmpeg: { accel: TranscodeHWAccel.QSV, accelDecode: true }, @@ -1748,7 +1806,7 @@ describe(MediaService.name, () => { ]), outputOptions: expect.arrayContaining([ expect.stringContaining( - 'hwmap=derive_device=opencl,tonemap_opencl=desat=0:format=nv12:matrix=bt709:primaries=bt709:range=pc:tonemap=hable:transfer=bt709,hwmap=derive_device=qsv:reverse=1,format=qsv', + 'hwmap=derive_device=opencl,tonemap_opencl=desat=0:format=nv12:matrix=bt709:primaries=bt709:transfer=bt709:range=pc:tonemap=hable:tonemap_mode=lum:peak=100,hwmap=derive_device=qsv:reverse=1,format=qsv', ), ]), twoPass: false, @@ -1757,7 +1815,7 @@ describe(MediaService.name, () => { }); it('should use preferred device for qsv when hardware decoding', async () => { - storageMock.readdir.mockResolvedValue(['renderD128', 'renderD129', 'renderD130']); + sut.videoInterfaces = { dri: ['renderD128', 'renderD129', 'renderD130'], mali: false }; mediaMock.probe.mockResolvedValue(probeStub.matroskaContainer); systemMock.get.mockResolvedValue({ ffmpeg: { accel: TranscodeHWAccel.QSV, accelDecode: true, preferredHwDevice: 'renderD129' }, @@ -1776,8 +1834,32 @@ describe(MediaService.name, () => { ); }); + it('should set format to nv12 for qsv if input is not yuv420p', async () => { + mediaMock.probe.mockResolvedValue(probeStub.videoStream10Bit); + systemMock.get.mockResolvedValue({ + ffmpeg: { accel: TranscodeHWAccel.QSV, accelDecode: true }, + }); + assetMock.getByIds.mockResolvedValue([assetStub.video]); + + await sut.handleVideoConversion({ id: assetStub.video.id }); + + expect(mediaMock.transcode).toHaveBeenCalledWith( + '/original/path.ext', + 'upload/encoded-video/user-id/as/se/asset-id.mp4', + expect.objectContaining({ + inputOptions: expect.arrayContaining([ + '-hwaccel qsv', + '-hwaccel_output_format qsv', + '-async_depth 4', + '-threads 1', + ]), + outputOptions: expect.arrayContaining([expect.stringContaining('format=nv12')]), + twoPass: false, + }), + ); + }); + it('should set options for vaapi', async () => { - storageMock.readdir.mockResolvedValue(['renderD128']); mediaMock.probe.mockResolvedValue(probeStub.matroskaContainer); systemMock.get.mockResolvedValue({ ffmpeg: { accel: TranscodeHWAccel.VAAPI } }); assetMock.getByIds.mockResolvedValue([assetStub.video]); @@ -1799,7 +1881,7 @@ describe(MediaService.name, () => { '-map 0:1', '-g 256', '-v verbose', - '-vf format=nv12,hwupload,scale_vaapi=-2:720:mode=hq:out_range=pc', + '-vf hwupload=extra_hw_frames=64,scale_vaapi=-2:720:mode=hq:out_range=pc:format=nv12', '-compression_level 7', '-rc_mode 1', ]), @@ -1809,7 +1891,6 @@ describe(MediaService.name, () => { }); it('should set vbr options for vaapi when max bitrate is enabled', async () => { - storageMock.readdir.mockResolvedValue(['renderD128']); mediaMock.probe.mockResolvedValue(probeStub.matroskaContainer); systemMock.get.mockResolvedValue({ ffmpeg: { accel: TranscodeHWAccel.VAAPI, maxBitrate: '10000k' } }); assetMock.getByIds.mockResolvedValue([assetStub.video]); @@ -1835,7 +1916,6 @@ describe(MediaService.name, () => { }); it('should set cq options for vaapi when max bitrate is disabled', async () => { - storageMock.readdir.mockResolvedValue(['renderD128']); mediaMock.probe.mockResolvedValue(probeStub.matroskaContainer); systemMock.get.mockResolvedValue({ ffmpeg: { accel: TranscodeHWAccel.VAAPI } }); assetMock.getByIds.mockResolvedValue([assetStub.video]); @@ -1861,7 +1941,6 @@ describe(MediaService.name, () => { }); it('should omit preset for vaapi if invalid', async () => { - storageMock.readdir.mockResolvedValue(['renderD128']); mediaMock.probe.mockResolvedValue(probeStub.matroskaContainer); systemMock.get.mockResolvedValue({ ffmpeg: { accel: TranscodeHWAccel.VAAPI, preset: 'invalid' } }); assetMock.getByIds.mockResolvedValue([assetStub.video]); @@ -1880,8 +1959,8 @@ describe(MediaService.name, () => { ); }); - it('should prefer gpu for vaapi if available', async () => { - storageMock.readdir.mockResolvedValue(['renderD129', 'card1', 'card0', 'renderD128']); + it('should prefer higher index renderD* device for vaapi', async () => { + sut.videoInterfaces = { dri: ['card1', 'renderD129', 'card0', 'renderD128'], mali: false }; mediaMock.probe.mockResolvedValue(probeStub.matroskaContainer); systemMock.get.mockResolvedValue({ ffmpeg: { accel: TranscodeHWAccel.VAAPI } }); assetMock.getByIds.mockResolvedValue([assetStub.video]); @@ -1891,27 +1970,7 @@ describe(MediaService.name, () => { 'upload/encoded-video/user-id/as/se/asset-id.mp4', expect.objectContaining({ inputOptions: expect.arrayContaining([ - '-init_hw_device vaapi=accel:/dev/dri/card1', - '-filter_hw_device accel', - ]), - outputOptions: expect.arrayContaining([`-c:v h264_vaapi`]), - twoPass: false, - }), - ); - }); - - it('should prefer higher index gpu node', async () => { - storageMock.readdir.mockResolvedValue(['renderD129', 'renderD130', 'renderD128']); - mediaMock.probe.mockResolvedValue(probeStub.matroskaContainer); - systemMock.get.mockResolvedValue({ ffmpeg: { accel: TranscodeHWAccel.VAAPI } }); - assetMock.getByIds.mockResolvedValue([assetStub.video]); - await sut.handleVideoConversion({ id: assetStub.video.id }); - expect(mediaMock.transcode).toHaveBeenCalledWith( - '/original/path.ext', - 'upload/encoded-video/user-id/as/se/asset-id.mp4', - expect.objectContaining({ - inputOptions: expect.arrayContaining([ - '-init_hw_device vaapi=accel:/dev/dri/renderD130', + '-init_hw_device vaapi=accel:/dev/dri/renderD129', '-filter_hw_device accel', ]), outputOptions: expect.arrayContaining([`-c:v h264_vaapi`]), @@ -1921,7 +1980,7 @@ describe(MediaService.name, () => { }); it('should select specific gpu node if selected', async () => { - storageMock.readdir.mockResolvedValue(['renderD129', 'card1', 'card0', 'renderD128']); + sut.videoInterfaces = { dri: ['renderD129', 'card1', 'card0', 'renderD128'], mali: false }; mediaMock.probe.mockResolvedValue(probeStub.matroskaContainer); systemMock.get.mockResolvedValue({ ffmpeg: { accel: TranscodeHWAccel.VAAPI, preferredHwDevice: '/dev/dri/renderD128' }, @@ -1943,7 +2002,6 @@ describe(MediaService.name, () => { }); it('should use hardware decoding for vaapi if enabled', async () => { - storageMock.readdir.mockResolvedValue(['renderD128']); mediaMock.probe.mockResolvedValue(probeStub.matroskaContainer); systemMock.get.mockResolvedValue({ ffmpeg: { accel: TranscodeHWAccel.VAAPI, accelDecode: true }, @@ -1961,6 +2019,7 @@ describe(MediaService.name, () => { '-hwaccel_output_format vaapi', '-noautorotate', '-threads 1', + '-hwaccel_device /dev/dri/renderD128', ]), outputOptions: expect.arrayContaining([ expect.stringContaining('scale_vaapi=-2:720:mode=hq:out_range=pc:format=nv12'), @@ -1970,8 +2029,7 @@ describe(MediaService.name, () => { ); }); - it('should use hardware tone-mapping for qsv if hardware decoding is enabled and should tone map', async () => { - storageMock.readdir.mockResolvedValue(['renderD128']); + it('should use hardware tone-mapping for vaapi if hardware decoding is enabled and should tone map', async () => { mediaMock.probe.mockResolvedValue(probeStub.videoStreamHDR); systemMock.get.mockResolvedValue({ ffmpeg: { accel: TranscodeHWAccel.VAAPI, accelDecode: true }, @@ -1987,7 +2045,7 @@ describe(MediaService.name, () => { inputOptions: expect.arrayContaining(['-hwaccel vaapi', '-hwaccel_output_format vaapi', '-threads 1']), outputOptions: expect.arrayContaining([ expect.stringContaining( - 'hwmap=derive_device=opencl,tonemap_opencl=desat=0:format=nv12:matrix=bt709:primaries=bt709:range=pc:tonemap=hable:transfer=bt709,hwmap=derive_device=vaapi:reverse=1,format=vaapi', + 'hwmap=derive_device=opencl,tonemap_opencl=desat=0:format=nv12:matrix=bt709:primaries=bt709:transfer=bt709:range=pc:tonemap=hable:tonemap_mode=lum:peak=100,hwmap=derive_device=vaapi:reverse=1,format=vaapi', ), ]), twoPass: false, @@ -1995,8 +2053,28 @@ describe(MediaService.name, () => { ); }); + it('should set format to nv12 for vaapi if input is not yuv420p', async () => { + mediaMock.probe.mockResolvedValue(probeStub.videoStream10Bit); + systemMock.get.mockResolvedValue({ + ffmpeg: { accel: TranscodeHWAccel.VAAPI, accelDecode: true }, + }); + assetMock.getByIds.mockResolvedValue([assetStub.video]); + + await sut.handleVideoConversion({ id: assetStub.video.id }); + + expect(mediaMock.transcode).toHaveBeenCalledWith( + '/original/path.ext', + 'upload/encoded-video/user-id/as/se/asset-id.mp4', + expect.objectContaining({ + inputOptions: expect.arrayContaining(['-hwaccel vaapi', '-hwaccel_output_format vaapi', '-threads 1']), + outputOptions: expect.arrayContaining([expect.stringContaining('format=nv12')]), + twoPass: false, + }), + ); + }); + it('should use preferred device for vaapi when hardware decoding', async () => { - storageMock.readdir.mockResolvedValue(['renderD128', 'renderD129', 'renderD130']); + sut.videoInterfaces = { dri: ['renderD128', 'renderD129', 'renderD130'], mali: false }; mediaMock.probe.mockResolvedValue(probeStub.matroskaContainer); systemMock.get.mockResolvedValue({ ffmpeg: { accel: TranscodeHWAccel.VAAPI, accelDecode: true, preferredHwDevice: 'renderD129' }, @@ -2015,8 +2093,47 @@ describe(MediaService.name, () => { ); }); - it('should fallback to sw transcoding if hw transcoding fails', async () => { - storageMock.readdir.mockResolvedValue(['renderD128']); + it('should fallback to hw encoding and sw decoding if hw transcoding fails and hw decoding is enabled', async () => { + mediaMock.probe.mockResolvedValue(probeStub.matroskaContainer); + systemMock.get.mockResolvedValue({ ffmpeg: { accel: TranscodeHWAccel.VAAPI, accelDecode: true } }); + assetMock.getByIds.mockResolvedValue([assetStub.video]); + mediaMock.transcode.mockRejectedValueOnce(new Error('error')); + await sut.handleVideoConversion({ id: assetStub.video.id }); + expect(mediaMock.transcode).toHaveBeenCalledTimes(2); + expect(mediaMock.transcode).toHaveBeenLastCalledWith( + '/original/path.ext', + 'upload/encoded-video/user-id/as/se/asset-id.mp4', + expect.objectContaining({ + inputOptions: expect.arrayContaining([ + '-init_hw_device vaapi=accel:/dev/dri/renderD128', + '-filter_hw_device accel', + ]), + outputOptions: expect.arrayContaining([`-c:v h264_vaapi`]), + twoPass: false, + }), + ); + }); + + it('should fallback to sw decoding if fallback to sw decoding + hw encoding fails', async () => { + mediaMock.probe.mockResolvedValue(probeStub.matroskaContainer); + systemMock.get.mockResolvedValue({ ffmpeg: { accel: TranscodeHWAccel.VAAPI, accelDecode: true } }); + assetMock.getByIds.mockResolvedValue([assetStub.video]); + mediaMock.transcode.mockRejectedValueOnce(new Error('error')); + mediaMock.transcode.mockRejectedValueOnce(new Error('error')); + await sut.handleVideoConversion({ id: assetStub.video.id }); + expect(mediaMock.transcode).toHaveBeenCalledTimes(3); + expect(mediaMock.transcode).toHaveBeenLastCalledWith( + '/original/path.ext', + 'upload/encoded-video/user-id/as/se/asset-id.mp4', + expect.objectContaining({ + inputOptions: expect.any(Array), + outputOptions: expect.arrayContaining(['-c:v h264']), + twoPass: false, + }), + ); + }); + + it('should fallback to sw transcoding if hw transcoding fails and hw decoding is disabled', async () => { mediaMock.probe.mockResolvedValue(probeStub.matroskaContainer); systemMock.get.mockResolvedValue({ ffmpeg: { accel: TranscodeHWAccel.VAAPI } }); assetMock.getByIds.mockResolvedValue([assetStub.video]); @@ -2035,17 +2152,15 @@ describe(MediaService.name, () => { }); it('should fail for vaapi if no hw devices', async () => { - storageMock.readdir.mockResolvedValue([]); + sut.videoInterfaces = { dri: [], mali: true }; mediaMock.probe.mockResolvedValue(probeStub.matroskaContainer); systemMock.get.mockResolvedValue({ ffmpeg: { accel: TranscodeHWAccel.VAAPI } }); assetMock.getByIds.mockResolvedValue([assetStub.video]); - await expect(sut.handleVideoConversion({ id: assetStub.video.id })).resolves.toBe(JobStatus.FAILED); + await expect(sut.handleVideoConversion({ id: assetStub.video.id })).rejects.toThrowError(); expect(mediaMock.transcode).not.toHaveBeenCalled(); }); it('should set options for rkmpp', async () => { - storageMock.readdir.mockResolvedValue(['renderD128']); - storageMock.stat.mockResolvedValue({ isFile: () => true, isCharacterDevice: () => true } as Stats); mediaMock.probe.mockResolvedValue(probeStub.matroskaContainer); systemMock.get.mockResolvedValue({ ffmpeg: { accel: TranscodeHWAccel.RKMPP, accelDecode: true } }); assetMock.getByIds.mockResolvedValue([assetStub.video]); @@ -2069,7 +2184,7 @@ describe(MediaService.name, () => { '-map 0:1', '-g 256', '-v verbose', - '-vf scale_rkrga=-2:720:format=nv12:afbc=1', + '-vf scale_rkrga=-2:720:format=nv12:afbc=1:async_depth=4', '-level 51', '-rc_mode CQP', '-qp_init 23', @@ -2080,8 +2195,6 @@ describe(MediaService.name, () => { }); it('should set vbr options for rkmpp when max bitrate is enabled', async () => { - storageMock.readdir.mockResolvedValue(['renderD128']); - storageMock.stat.mockResolvedValue({ isFile: () => true, isCharacterDevice: () => true } as Stats); mediaMock.probe.mockResolvedValue(probeStub.videoStreamVp9); systemMock.get.mockResolvedValue({ ffmpeg: { @@ -2105,8 +2218,6 @@ describe(MediaService.name, () => { }); it('should set cqp options for rkmpp when max bitrate is disabled', async () => { - storageMock.readdir.mockResolvedValue(['renderD128']); - storageMock.stat.mockResolvedValue({ isFile: () => true, isCharacterDevice: () => true } as Stats); mediaMock.probe.mockResolvedValue(probeStub.matroskaContainer); systemMock.get.mockResolvedValue({ ffmpeg: { accel: TranscodeHWAccel.RKMPP, accelDecode: true, crf: 30, maxBitrate: '0' }, @@ -2125,8 +2236,6 @@ describe(MediaService.name, () => { }); it('should set OpenCL tonemapping options for rkmpp when OpenCL is available', async () => { - storageMock.readdir.mockResolvedValue(['renderD128']); - storageMock.stat.mockResolvedValue({ isFile: () => true, isCharacterDevice: () => true } as Stats); mediaMock.probe.mockResolvedValue(probeStub.videoStreamHDR); systemMock.get.mockResolvedValue({ ffmpeg: { accel: TranscodeHWAccel.RKMPP, accelDecode: true, crf: 30, maxBitrate: '0' }, @@ -2140,7 +2249,7 @@ describe(MediaService.name, () => { inputOptions: expect.arrayContaining(['-hwaccel rkmpp', '-hwaccel_output_format drm_prime', '-afbc rga']), outputOptions: expect.arrayContaining([ expect.stringContaining( - 'scale_rkrga=-2:720:format=p010:afbc=1,hwmap=derive_device=opencl:mode=read,tonemap_opencl=format=nv12:r=pc:p=bt709:t=bt709:m=bt709:tonemap=hable:desat=0,hwmap=derive_device=rkmpp:mode=write:reverse=1,format=drm_prime', + 'scale_rkrga=-2:720:format=p010:afbc=1:async_depth=4,hwmap=derive_device=opencl:mode=read,tonemap_opencl=format=nv12:r=pc:p=bt709:t=bt709:m=bt709:tonemap=hable:desat=0:tonemap_mode=lum:peak=100,hwmap=derive_device=rkmpp:mode=write:reverse=1,format=drm_prime', ), ]), twoPass: false, @@ -2148,9 +2257,28 @@ describe(MediaService.name, () => { ); }); + it('should set hardware decoding options for rkmpp when hardware decoding is enabled with no OpenCL on non-HDR file', async () => { + sut.videoInterfaces = { dri: ['renderD128'], mali: false }; + mediaMock.probe.mockResolvedValue(probeStub.noAudioStreams); + systemMock.get.mockResolvedValue({ + ffmpeg: { accel: TranscodeHWAccel.RKMPP, accelDecode: true, crf: 30, maxBitrate: '0' }, + }); + assetMock.getByIds.mockResolvedValue([assetStub.video]); + await sut.handleVideoConversion({ id: assetStub.video.id }); + expect(mediaMock.transcode).toHaveBeenCalledWith( + '/original/path.ext', + 'upload/encoded-video/user-id/as/se/asset-id.mp4', + expect.objectContaining({ + inputOptions: expect.arrayContaining(['-hwaccel rkmpp', '-hwaccel_output_format drm_prime', '-afbc rga']), + outputOptions: expect.arrayContaining([ + expect.stringContaining('scale_rkrga=-2:720:format=nv12:afbc=1:async_depth=4'), + ]), + twoPass: false, + }), + ); + }); + it('should use software decoding and tone-mapping if hardware decoding is disabled', async () => { - storageMock.readdir.mockResolvedValue(['renderD128']); - storageMock.stat.mockResolvedValue({ isFile: () => true, isCharacterDevice: () => true } as Stats); mediaMock.probe.mockResolvedValue(probeStub.videoStreamHDR); systemMock.get.mockResolvedValue({ ffmpeg: { accel: TranscodeHWAccel.RKMPP, accelDecode: false, crf: 30, maxBitrate: '0' }, @@ -2164,7 +2292,7 @@ describe(MediaService.name, () => { inputOptions: [], outputOptions: expect.arrayContaining([ expect.stringContaining( - 'zscale=t=linear:npl=100,tonemap=hable:desat=0,zscale=p=709:t=709:m=709:range=pc,format=yuv420p', + 'tonemapx=tonemap=hable:desat=0:p=bt709:t=bt709:m=bt709:r=pc:peak=100:format=yuv420p', ), ]), twoPass: false, @@ -2172,9 +2300,8 @@ describe(MediaService.name, () => { ); }); - it('should use software decoding and tone-mapping if opencl is not available', async () => { - storageMock.readdir.mockResolvedValue(['renderD128']); - storageMock.stat.mockResolvedValue({ isFile: () => false, isCharacterDevice: () => false } as Stats); + it('should use software tone-mapping if opencl is not available', async () => { + sut.videoInterfaces = { dri: ['renderD128'], mali: false }; mediaMock.probe.mockResolvedValue(probeStub.videoStreamHDR); systemMock.get.mockResolvedValue({ ffmpeg: { accel: TranscodeHWAccel.RKMPP, accelDecode: true, crf: 30, maxBitrate: '0' }, @@ -2185,10 +2312,10 @@ describe(MediaService.name, () => { '/original/path.ext', 'upload/encoded-video/user-id/as/se/asset-id.mp4', expect.objectContaining({ - inputOptions: [], + inputOptions: expect.any(Array), outputOptions: expect.arrayContaining([ expect.stringContaining( - 'zscale=t=linear:npl=100,tonemap=hable:desat=0,zscale=p=709:t=709:m=709:range=pc,format=yuv420p', + 'tonemapx=tonemap=hable:desat=0:p=bt709:t=bt709:m=bt709:r=pc:peak=100:format=yuv420p', ), ]), twoPass: false, @@ -2209,7 +2336,7 @@ describe(MediaService.name, () => { outputOptions: expect.arrayContaining([ '-c:v h264', '-c:a copy', - '-vf zscale=t=linear:npl=100,tonemap=hable:desat=0,zscale=p=709:t=709:m=709:range=pc,format=yuv420p', + '-vf tonemapx=tonemap=hable:desat=0:p=bt709:t=bt709:m=bt709:r=pc:peak=100:format=yuv420p', ]), twoPass: false, }), @@ -2229,16 +2356,16 @@ describe(MediaService.name, () => { outputOptions: expect.arrayContaining([ '-c:v h264', '-c:a copy', - '-vf zscale=t=linear:npl=100,tonemap=hable:desat=0,zscale=p=709:t=709:m=709:range=pc,format=yuv420p', + '-vf tonemapx=tonemap=hable:desat=0:p=bt709:t=bt709:m=bt709:r=pc:peak=100:format=yuv420p', ]), twoPass: false, }), ); }); - it('should set npl to 250 for reinhard and mobius tone-mapping algorithms', async () => { - mediaMock.probe.mockResolvedValue(probeStub.videoStreamHDR); - systemMock.get.mockResolvedValue({ ffmpeg: { tonemap: ToneMapping.MOBIUS } }); + it('should transcode when policy is required and video is not yuv420p', async () => { + mediaMock.probe.mockResolvedValue(probeStub.videoStream10Bit); + systemMock.get.mockResolvedValue({ ffmpeg: { transcode: TranscodePolicy.REQUIRED } }); assetMock.getByIds.mockResolvedValue([assetStub.video]); await sut.handleVideoConversion({ id: assetStub.video.id }); expect(mediaMock.transcode).toHaveBeenCalledWith( @@ -2246,11 +2373,7 @@ describe(MediaService.name, () => { 'upload/encoded-video/user-id/as/se/asset-id.mp4', expect.objectContaining({ inputOptions: expect.any(Array), - outputOptions: expect.arrayContaining([ - '-c:v h264', - '-c:a copy', - '-vf zscale=t=linear:npl=250,tonemap=mobius:desat=0,zscale=p=709:t=709:m=709:range=pc,format=yuv420p', - ]), + outputOptions: expect.arrayContaining(['-c:v h264', '-c:a copy', '-vf format=yuv420p']), twoPass: false, }), ); diff --git a/server/src/services/media.service.ts b/server/src/services/media.service.ts index 8393f5dc76282..7036bd32e831c 100644 --- a/server/src/services/media.service.ts +++ b/server/src/services/media.service.ts @@ -1,6 +1,7 @@ import { Injectable } from '@nestjs/common'; import { dirname } from 'node:path'; import { StorageCore } from 'src/cores/storage.core'; +import { OnEvent, OnJob } from 'src/decorators'; import { SystemConfigFFmpegDto } from 'src/dtos/system-config.dto'; import { AssetEntity } from 'src/entities/asset.entity'; import { @@ -19,15 +20,14 @@ import { } from 'src/enum'; import { UpsertFileOptions, WithoutProperty } from 'src/interfaces/asset.interface'; import { - IBaseJob, - IEntityJob, JOBS_ASSET_PAGINATION_SIZE, JobItem, JobName, + JobOf, JobStatus, QueueName, } from 'src/interfaces/job.interface'; -import { AudioStreamInfo, TranscodeCommand, VideoFormat, VideoStreamInfo } from 'src/interfaces/media.interface'; +import { AudioStreamInfo, VideoFormat, VideoInterfaces, VideoStreamInfo } from 'src/interfaces/media.interface'; import { BaseService } from 'src/services/base.service'; import { getAssetFiles } from 'src/utils/asset.util'; import { BaseConfig, ThumbnailConfig } from 'src/utils/media'; @@ -36,10 +36,16 @@ import { usePagination } from 'src/utils/pagination'; @Injectable() export class MediaService extends BaseService { - private maliOpenCL?: boolean; - private devices?: string[]; + videoInterfaces: VideoInterfaces = { dri: [], mali: false }; - async handleQueueGenerateThumbnails({ force }: IBaseJob): Promise { + @OnEvent({ name: 'app.bootstrap' }) + async onBootstrap() { + const [dri, mali] = await Promise.all([this.getDevices(), this.hasMaliOpenCL()]); + this.videoInterfaces = { dri, mali }; + } + + @OnJob({ name: JobName.QUEUE_GENERATE_THUMBNAILS, queue: QueueName.THUMBNAIL_GENERATION }) + async handleQueueGenerateThumbnails({ force }: JobOf): Promise { const assetPagination = usePagination(JOBS_ASSET_PAGINATION_SIZE, (pagination) => { return force ? this.assetRepository.getAll(pagination, { @@ -90,6 +96,7 @@ export class MediaService extends BaseService { return JobStatus.SUCCESS; } + @OnJob({ name: JobName.QUEUE_MIGRATION, queue: QueueName.MIGRATION }) async handleQueueMigration(): Promise { const assetPagination = usePagination(JOBS_ASSET_PAGINATION_SIZE, (pagination) => this.assetRepository.getAll(pagination), @@ -120,7 +127,8 @@ export class MediaService extends BaseService { return JobStatus.SUCCESS; } - async handleAssetMigration({ id }: IEntityJob): Promise { + @OnJob({ name: JobName.MIGRATE_ASSET, queue: QueueName.MIGRATION }) + async handleAssetMigration({ id }: JobOf): Promise { const { image } = await this.getConfig({ withCache: true }); const [asset] = await this.assetRepository.getByIds([id], { files: true }); if (!asset) { @@ -134,7 +142,8 @@ export class MediaService extends BaseService { return JobStatus.SUCCESS; } - async handleGenerateThumbnails({ id }: IEntityJob): Promise { + @OnJob({ name: JobName.GENERATE_THUMBNAILS, queue: QueueName.THUMBNAIL_GENERATION }) + async handleGenerateThumbnails({ id }: JobOf): Promise { const asset = await this.assetRepository.getById(id, { exifInfo: true, files: true }); if (!asset) { this.logger.warn(`Thumbnail generation failed for asset ${id}: not found`); @@ -210,7 +219,8 @@ export class MediaService extends BaseService { const colorspace = this.isSRGB(asset) ? Colorspace.SRGB : image.colorspace; const processInvalidImages = process.env.IMMICH_PROCESS_INVALID_IMAGES === 'true'; - const decodeOptions = { colorspace, processInvalidImages, size: image.preview.size }; + const orientation = useExtracted && asset.exifInfo?.orientation ? Number(asset.exifInfo.orientation) : undefined; + const decodeOptions = { colorspace, processInvalidImages, size: image.preview.size, orientation }; const { data, info } = await this.mediaRepository.decodeImage(inputPath, decodeOptions); const options = { colorspace, processInvalidImages, raw: info }; @@ -234,7 +244,7 @@ export class MediaService extends BaseService { const thumbnailPath = StorageCore.getImagePath(asset, AssetPathType.THUMBNAIL, image.thumbnail.format); this.storageCore.ensureFolders(previewPath); - const { audioStreams, videoStreams } = await this.mediaRepository.probe(asset.originalPath); + const { format, audioStreams, videoStreams } = await this.mediaRepository.probe(asset.originalPath); const mainVideoStream = this.getMainStream(videoStreams); if (!mainVideoStream) { throw new Error(`No video streams found for asset ${asset.id}`); @@ -243,9 +253,14 @@ export class MediaService extends BaseService { const previewConfig = ThumbnailConfig.create({ ...ffmpeg, targetResolution: image.preview.size.toString() }); const thumbnailConfig = ThumbnailConfig.create({ ...ffmpeg, targetResolution: image.thumbnail.size.toString() }); + const previewOptions = previewConfig.getCommand(TranscodeTarget.VIDEO, mainVideoStream, mainAudioStream, format); + const thumbnailOptions = thumbnailConfig.getCommand( + TranscodeTarget.VIDEO, + mainVideoStream, + mainAudioStream, + format, + ); - const previewOptions = previewConfig.getCommand(TranscodeTarget.VIDEO, mainVideoStream, mainAudioStream); - const thumbnailOptions = thumbnailConfig.getCommand(TranscodeTarget.VIDEO, mainVideoStream, mainAudioStream); await this.mediaRepository.transcode(asset.originalPath, previewPath, previewOptions); await this.mediaRepository.transcode(asset.originalPath, thumbnailPath, thumbnailOptions); @@ -257,7 +272,8 @@ export class MediaService extends BaseService { return { previewPath, thumbnailPath, thumbhash }; } - async handleQueueVideoConversion(job: IBaseJob): Promise { + @OnJob({ name: JobName.QUEUE_VIDEO_CONVERSION, queue: QueueName.VIDEO_CONVERSION }) + async handleQueueVideoConversion(job: JobOf): Promise { const { force } = job; const assetPagination = usePagination(JOBS_ASSET_PAGINATION_SIZE, (pagination) => { @@ -275,7 +291,8 @@ export class MediaService extends BaseService { return JobStatus.SUCCESS; } - async handleVideoConversion({ id }: IEntityJob): Promise { + @OnJob({ name: JobName.VIDEO_CONVERSION, queue: QueueName.VIDEO_CONVERSION }) + async handleVideoConversion({ id }: JobOf): Promise { const [asset] = await this.assetRepository.getByIds([id]); if (!asset || asset.type !== AssetType.VIDEO) { return JobStatus.FAILED; @@ -288,19 +305,19 @@ export class MediaService extends BaseService { const { videoStreams, audioStreams, format } = await this.mediaRepository.probe(input, { countFrames: this.logger.isLevelEnabled(LogLevel.DEBUG), // makes frame count more reliable for progress logs }); - const mainVideoStream = this.getMainStream(videoStreams); - const mainAudioStream = this.getMainStream(audioStreams); - if (!mainVideoStream || !format.formatName) { + const videoStream = this.getMainStream(videoStreams); + const audioStream = this.getMainStream(audioStreams); + if (!videoStream || !format.formatName) { return JobStatus.FAILED; } - if (!mainVideoStream.height || !mainVideoStream.width) { + if (!videoStream.height || !videoStream.width) { this.logger.warn(`Skipped transcoding for asset ${asset.id}: no video streams found`); return JobStatus.FAILED; } - const { ffmpeg } = await this.getConfig({ withCache: true }); - const target = this.getTranscodeTarget(ffmpeg, mainVideoStream, mainAudioStream); + let { ffmpeg } = await this.getConfig({ withCache: true }); + const target = this.getTranscodeTarget(ffmpeg, videoStream, audioStream); if (target === TranscodeTarget.NONE && !this.isRemuxRequired(ffmpeg, format)) { if (asset.encodedVideoPath) { this.logger.log(`Transcoded video exists for asset ${asset.id}, but is no longer required. Deleting...`); @@ -313,19 +330,13 @@ export class MediaService extends BaseService { return JobStatus.SKIPPED; } - let command: TranscodeCommand; - try { - const config = BaseConfig.create(ffmpeg, await this.getDevices(), await this.hasMaliOpenCL()); - command = config.getCommand(target, mainVideoStream, mainAudioStream); - } catch (error) { - this.logger.error(`An error occurred while configuring transcoding options: ${error}`); - return JobStatus.FAILED; - } - + const command = BaseConfig.create(ffmpeg, this.videoInterfaces).getCommand(target, videoStream, audioStream); if (ffmpeg.accel === TranscodeHWAccel.DISABLED) { - this.logger.log(`Encoding video ${asset.id} without hardware acceleration`); + this.logger.log(`Transcoding video ${asset.id} without hardware acceleration`); } else { - this.logger.log(`Encoding video ${asset.id} with ${ffmpeg.accel.toUpperCase()} acceleration`); + this.logger.log( + `Transcoding video ${asset.id} with ${ffmpeg.accel.toUpperCase()}-accelerated encoding and${ffmpeg.accelDecode ? '' : ' software'} decoding`, + ); } try { @@ -335,10 +346,26 @@ export class MediaService extends BaseService { if (ffmpeg.accel === TranscodeHWAccel.DISABLED) { return JobStatus.FAILED; } - this.logger.error(`Retrying with ${ffmpeg.accel.toUpperCase()} acceleration disabled`); - const config = BaseConfig.create({ ...ffmpeg, accel: TranscodeHWAccel.DISABLED }); - command = config.getCommand(target, mainVideoStream, mainAudioStream); - await this.mediaRepository.transcode(input, output, command); + + let partialFallbackSuccess = false; + if (ffmpeg.accelDecode) { + try { + this.logger.error(`Retrying with ${ffmpeg.accel.toUpperCase()}-accelerated encoding and software decoding`); + ffmpeg = { ...ffmpeg, accelDecode: false }; + const command = BaseConfig.create(ffmpeg, this.videoInterfaces).getCommand(target, videoStream, audioStream); + await this.mediaRepository.transcode(input, output, command); + partialFallbackSuccess = true; + } catch (error: any) { + this.logger.error(`Error occurred during transcoding: ${error.message}`); + } + } + + if (!partialFallbackSuccess) { + this.logger.error(`Retrying with ${ffmpeg.accel.toUpperCase()} acceleration disabled`); + ffmpeg = { ...ffmpeg, accel: TranscodeHWAccel.DISABLED }; + const command = BaseConfig.create(ffmpeg, this.videoInterfaces).getCommand(target, videoStream, audioStream); + await this.mediaRepository.transcode(input, output, command); + } } this.logger.log(`Successfully encoded ${asset.id}`); @@ -407,7 +434,7 @@ export class MediaService extends BaseService { const isLargerThanTargetBitrate = stream.bitrate > this.parseBitrateToBps(ffmpegConfig.maxBitrate); const isTargetVideoCodec = ffmpegConfig.acceptedVideoCodecs.includes(stream.codecName as VideoCodec); - const isRequired = !isTargetVideoCodec || stream.isHDR; + const isRequired = !isTargetVideoCodec || !stream.pixelFormat.endsWith('420p'); switch (ffmpegConfig.transcode) { case TranscodePolicy.DISABLED: { @@ -477,30 +504,24 @@ export class MediaService extends BaseService { } private async getDevices() { - if (!this.devices) { - try { - this.devices = await this.storageRepository.readdir('/dev/dri'); - } catch { - this.logger.debug('No devices found in /dev/dri.'); - this.devices = []; - } + try { + return await this.storageRepository.readdir('/dev/dri'); + } catch { + this.logger.debug('No devices found in /dev/dri.'); + return []; } - - return this.devices; } private async hasMaliOpenCL() { - if (this.maliOpenCL === undefined) { - try { - const maliIcdStat = await this.storageRepository.stat('/etc/OpenCL/vendors/mali.icd'); - const maliDeviceStat = await this.storageRepository.stat('/dev/mali0'); - this.maliOpenCL = maliIcdStat.isFile() && maliDeviceStat.isCharacterDevice(); - } catch { - this.logger.debug('OpenCL not available for transcoding, so RKMPP acceleration will use CPU decoding'); - this.maliOpenCL = false; - } + try { + const [maliIcdStat, maliDeviceStat] = await Promise.all([ + this.storageRepository.stat('/etc/OpenCL/vendors/mali.icd'), + this.storageRepository.stat('/dev/mali0'), + ]); + return maliIcdStat.isFile() && maliDeviceStat.isCharacterDevice(); + } catch { + this.logger.debug('OpenCL not available for transcoding, so RKMPP acceleration will use CPU tonemapping'); + return false; } - - return this.maliOpenCL; } } diff --git a/server/src/services/metadata.service.spec.ts b/server/src/services/metadata.service.spec.ts index cc6eae6e3b511..390f18b777b56 100644 --- a/server/src/services/metadata.service.spec.ts +++ b/server/src/services/metadata.service.spec.ts @@ -3,9 +3,10 @@ import { randomBytes } from 'node:crypto'; import { Stats } from 'node:fs'; import { constants } from 'node:fs/promises'; import { ExifEntity } from 'src/entities/exif.entity'; -import { AssetType, ImmichWorker, SourceType } from 'src/enum'; +import { AssetType, ExifOrientation, ImmichWorker, SourceType } from 'src/enum'; import { IAlbumRepository } from 'src/interfaces/album.interface'; import { IAssetRepository, WithoutProperty } from 'src/interfaces/asset.interface'; +import { IConfigRepository } from 'src/interfaces/config.interface'; import { ICryptoRepository } from 'src/interfaces/crypto.interface'; import { IEventRepository } from 'src/interfaces/event.interface'; import { IJobRepository, JobName, JobStatus } from 'src/interfaces/job.interface'; @@ -17,7 +18,7 @@ import { IStorageRepository } from 'src/interfaces/storage.interface'; import { ISystemMetadataRepository } from 'src/interfaces/system-metadata.interface'; import { ITagRepository } from 'src/interfaces/tag.interface'; import { IUserRepository } from 'src/interfaces/user.interface'; -import { MetadataService, Orientation } from 'src/services/metadata.service'; +import { MetadataService } from 'src/services/metadata.service'; import { assetStub } from 'test/fixtures/asset.stub'; import { fileStub } from 'test/fixtures/file.stub'; import { probeStub } from 'test/fixtures/media.stub'; @@ -32,6 +33,7 @@ describe(MetadataService.name, () => { let albumMock: Mocked; let assetMock: Mocked; + let configMock: Mocked; let cryptoMock: Mocked; let eventMock: Mocked; let jobMock: Mocked; @@ -55,6 +57,7 @@ describe(MetadataService.name, () => { sut, albumMock, assetMock, + configMock, cryptoMock, eventMock, jobMock, @@ -70,6 +73,8 @@ describe(MetadataService.name, () => { mockReadTags(); + configMock.getWorker.mockReturnValue(ImmichWorker.MICROSERVICES); + delete process.env.TZ; }); @@ -83,22 +88,12 @@ describe(MetadataService.name, () => { describe('onBootstrapEvent', () => { it('should pause and resume queue during init', async () => { - await sut.onBootstrap(ImmichWorker.MICROSERVICES); + await sut.onBootstrap(); expect(jobMock.pause).toHaveBeenCalledTimes(1); expect(mapMock.init).toHaveBeenCalledTimes(1); expect(jobMock.resume).toHaveBeenCalledTimes(1); }); - - it('should return if reverse geocoding is disabled', async () => { - systemMock.get.mockResolvedValue({ reverseGeocoding: { enabled: false } }); - - await sut.onBootstrap(ImmichWorker.MICROSERVICES); - - expect(jobMock.pause).not.toHaveBeenCalled(); - expect(mapMock.init).not.toHaveBeenCalled(); - expect(jobMock.resume).not.toHaveBeenCalled(); - }); }); describe('handleLivePhotoLinking', () => { @@ -535,7 +530,7 @@ describe(MetadataService.name, () => { expect(assetMock.getByIds).toHaveBeenCalledWith([assetStub.video.id], { faces: { person: false } }); expect(assetMock.upsertExif).toHaveBeenCalledWith( - expect.objectContaining({ orientation: Orientation.Rotate270CW.toString() }), + expect.objectContaining({ orientation: ExifOrientation.Rotate270CW.toString() }), ); }); diff --git a/server/src/services/metadata.service.ts b/server/src/services/metadata.service.ts index a45bcd4252533..e0566c84b72d2 100644 --- a/server/src/services/metadata.service.ts +++ b/server/src/services/metadata.service.ts @@ -7,24 +7,16 @@ import { constants } from 'node:fs/promises'; import path from 'node:path'; import { SystemConfig } from 'src/config'; import { StorageCore } from 'src/cores/storage.core'; -import { OnEvent } from 'src/decorators'; +import { OnEvent, OnJob } from 'src/decorators'; import { AssetFaceEntity } from 'src/entities/asset-face.entity'; import { AssetEntity } from 'src/entities/asset.entity'; import { ExifEntity } from 'src/entities/exif.entity'; import { PersonEntity } from 'src/entities/person.entity'; -import { AssetType, ImmichWorker, SourceType } from 'src/enum'; +import { AssetType, ExifOrientation, ImmichWorker, SourceType } from 'src/enum'; import { WithoutProperty } from 'src/interfaces/asset.interface'; import { DatabaseLock } from 'src/interfaces/database.interface'; import { ArgOf } from 'src/interfaces/event.interface'; -import { - IBaseJob, - IEntityJob, - ISidecarWriteJob, - JobName, - JOBS_ASSET_PAGINATION_SIZE, - JobStatus, - QueueName, -} from 'src/interfaces/job.interface'; +import { JobName, JobOf, JOBS_ASSET_PAGINATION_SIZE, JobStatus, QueueName } from 'src/interfaces/job.interface'; import { ReverseGeocodeResult } from 'src/interfaces/map.interface'; import { ImmichTags } from 'src/interfaces/metadata.interface'; import { BaseService } from 'src/services/base.service'; @@ -44,17 +36,6 @@ const EXIF_DATE_TAGS: Array = [ 'DateTimeCreated', ]; -export enum Orientation { - Horizontal = 1, - MirrorHorizontal = 2, - Rotate180 = 3, - MirrorVertical = 4, - MirrorHorizontalRotate270CW = 5, - Rotate90CW = 6, - MirrorHorizontalRotate90CW = 7, - Rotate270CW = 8, -} - const validate = (value: T): NonNullable | null => { // handle lists of numbers if (Array.isArray(value)) { @@ -87,13 +68,10 @@ const validateRange = (value: number | undefined, min: number, max: number): Non @Injectable() export class MetadataService extends BaseService { - @OnEvent({ name: 'app.bootstrap' }) - async onBootstrap(app: ArgOf<'app.bootstrap'>) { - if (app !== ImmichWorker.MICROSERVICES) { - return; - } - const config = await this.getConfig({ withCache: false }); - await this.init(config); + @OnEvent({ name: 'app.bootstrap', workers: [ImmichWorker.MICROSERVICES] }) + async onBootstrap() { + this.logger.log('Bootstrapping metadata service'); + await this.init(); } @OnEvent({ name: 'app.shutdown' }) @@ -101,17 +79,8 @@ export class MetadataService extends BaseService { await this.metadataRepository.teardown(); } - @OnEvent({ name: 'config.update' }) - async onConfigUpdate({ newConfig }: ArgOf<'config.update'>) { - await this.init(newConfig); - } - - private async init({ reverseGeocoding }: SystemConfig) { - const { enabled } = reverseGeocoding; - - if (!enabled) { - return; - } + private async init() { + this.logger.log('Initializing metadata service'); try { await this.jobRepository.pause(QueueName.METADATA_EXTRACTION); @@ -124,7 +93,8 @@ export class MetadataService extends BaseService { } } - async handleLivePhotoLinking(job: IEntityJob): Promise { + @OnJob({ name: JobName.LINK_LIVE_PHOTOS, queue: QueueName.METADATA_EXTRACTION }) + async handleLivePhotoLinking(job: JobOf): Promise { const { id } = job; const [asset] = await this.assetRepository.getByIds([id], { exifInfo: true }); if (!asset?.exifInfo) { @@ -159,7 +129,8 @@ export class MetadataService extends BaseService { return JobStatus.SUCCESS; } - async handleQueueMetadataExtraction(job: IBaseJob): Promise { + @OnJob({ name: JobName.QUEUE_METADATA_EXTRACTION, queue: QueueName.METADATA_EXTRACTION }) + async handleQueueMetadataExtraction(job: JobOf): Promise { const { force } = job; const assetPagination = usePagination(JOBS_ASSET_PAGINATION_SIZE, (pagination) => { return force @@ -176,7 +147,8 @@ export class MetadataService extends BaseService { return JobStatus.SUCCESS; } - async handleMetadataExtraction({ id }: IEntityJob): Promise { + @OnJob({ name: JobName.METADATA_EXTRACTION, queue: QueueName.METADATA_EXTRACTION }) + async handleMetadataExtraction({ id }: JobOf): Promise { const { metadata, reverseGeocoding } = await this.getConfig({ withCache: true }); const [asset] = await this.assetRepository.getByIds([id], { faces: { person: false } }); if (!asset) { @@ -192,6 +164,8 @@ export class MetadataService extends BaseService { const { dateTimeOriginal, localDateTime, timeZone, modifyDate } = this.getDates(asset, exifTags); const { latitude, longitude, country, state, city } = await this.getGeo(exifTags, reverseGeocoding); + const { width, height } = this.getImageDimensions(exifTags); + const exifData: Partial = { assetId: asset.id, @@ -209,8 +183,8 @@ export class MetadataService extends BaseService { // image/file fileSizeInByte: stats.size, - exifImageHeight: validate(exifTags.ImageHeight), - exifImageWidth: validate(exifTags.ImageWidth), + exifImageHeight: validate(height), + exifImageWidth: validate(width), orientation: validate(exifTags.Orientation)?.toString() ?? null, projectionType: exifTags.ProjectionType ? String(exifTags.ProjectionType).toUpperCase() : null, bitsPerSample: this.getBitsPerSample(exifTags), @@ -260,7 +234,8 @@ export class MetadataService extends BaseService { return JobStatus.SUCCESS; } - async handleQueueSidecar(job: IBaseJob): Promise { + @OnJob({ name: JobName.QUEUE_SIDECAR, queue: QueueName.SIDECAR }) + async handleQueueSidecar(job: JobOf): Promise { const { force } = job; const assetPagination = usePagination(JOBS_ASSET_PAGINATION_SIZE, (pagination) => { return force @@ -280,11 +255,13 @@ export class MetadataService extends BaseService { return JobStatus.SUCCESS; } - handleSidecarSync({ id }: IEntityJob): Promise { + @OnJob({ name: JobName.SIDECAR_SYNC, queue: QueueName.SIDECAR }) + handleSidecarSync({ id }: JobOf): Promise { return this.processSidecar(id, true); } - handleSidecarDiscovery({ id }: IEntityJob): Promise { + @OnJob({ name: JobName.SIDECAR_DISCOVERY, queue: QueueName.SIDECAR }) + handleSidecarDiscovery({ id }: JobOf): Promise { return this.processSidecar(id, false); } @@ -298,7 +275,8 @@ export class MetadataService extends BaseService { await this.jobRepository.queue({ name: JobName.SIDECAR_WRITE, data: { id: assetId, tags: true } }); } - async handleSidecarWrite(job: ISidecarWriteJob): Promise { + @OnJob({ name: JobName.SIDECAR_WRITE, queue: QueueName.SIDECAR }) + async handleSidecarWrite(job: JobOf): Promise { const { id, description, dateTimeOriginal, latitude, longitude, rating, tags } = job; const [asset] = await this.assetRepository.getByIds([id], { tags: true }); if (!asset) { @@ -334,6 +312,19 @@ export class MetadataService extends BaseService { return JobStatus.SUCCESS; } + private getImageDimensions(exifTags: ImmichTags): { width?: number; height?: number } { + /* + * The "true" values for width and height are a bit hidden, depending on the camera model and file format. + * For RAW images in the CR2 or RAF format, the "ImageSize" value seems to be correct, + * but ImageWidth and ImageHeight are not correct (they contain the dimensions of the preview image). + */ + let [width, height] = exifTags.ImageSize?.split('x').map((dim) => Number.parseInt(dim) || undefined) || []; + if (!width || !height) { + [width, height] = [exifTags.ImageWidth, exifTags.ImageHeight]; + } + return { width, height }; + } + private async getExifTags(asset: AssetEntity): Promise { const mediaTags = await this.metadataRepository.readTags(asset.originalPath); const sidecarTags = asset.sidecarPath ? await this.metadataRepository.readTags(asset.sidecarPath) : {}; @@ -671,19 +662,19 @@ export class MetadataService extends BaseService { if (videoStreams[0]) { switch (videoStreams[0].rotation) { case -90: { - tags.Orientation = Orientation.Rotate90CW; + tags.Orientation = ExifOrientation.Rotate90CW; break; } case 0: { - tags.Orientation = Orientation.Horizontal; + tags.Orientation = ExifOrientation.Horizontal; break; } case 90: { - tags.Orientation = Orientation.Rotate270CW; + tags.Orientation = ExifOrientation.Rotate270CW; break; } case 180: { - tags.Orientation = Orientation.Rotate180; + tags.Orientation = ExifOrientation.Rotate180; break; } } @@ -707,7 +698,7 @@ export class MetadataService extends BaseService { return JobStatus.FAILED; } - if (!isSync && (!asset.isVisible || asset.sidecarPath)) { + if (!isSync && (!asset.isVisible || asset.sidecarPath) && !asset.isExternal) { return JobStatus.FAILED; } @@ -729,6 +720,13 @@ export class MetadataService extends BaseService { sidecarPath = sidecarPathWithoutExt; } + if (asset.isExternal) { + if (sidecarPath !== asset.sidecarPath) { + await this.assetRepository.update({ id: asset.id, sidecarPath }); + } + return JobStatus.SUCCESS; + } + if (sidecarPath) { await this.assetRepository.update({ id: asset.id, sidecarPath }); return JobStatus.SUCCESS; diff --git a/server/src/services/microservices.service.ts b/server/src/services/microservices.service.ts deleted file mode 100644 index c60007780938f..0000000000000 --- a/server/src/services/microservices.service.ts +++ /dev/null @@ -1,106 +0,0 @@ -import { Injectable } from '@nestjs/common'; -import { OnEvent } from 'src/decorators'; -import { ImmichWorker } from 'src/enum'; -import { ArgOf } from 'src/interfaces/event.interface'; -import { IDeleteFilesJob, JobName } from 'src/interfaces/job.interface'; -import { AssetService } from 'src/services/asset.service'; -import { AuditService } from 'src/services/audit.service'; -import { BackupService } from 'src/services/backup.service'; -import { DuplicateService } from 'src/services/duplicate.service'; -import { JobService } from 'src/services/job.service'; -import { LibraryService } from 'src/services/library.service'; -import { MediaService } from 'src/services/media.service'; -import { MetadataService } from 'src/services/metadata.service'; -import { NotificationService } from 'src/services/notification.service'; -import { PersonService } from 'src/services/person.service'; -import { SessionService } from 'src/services/session.service'; -import { SmartInfoService } from 'src/services/smart-info.service'; -import { StorageTemplateService } from 'src/services/storage-template.service'; -import { StorageService } from 'src/services/storage.service'; -import { TagService } from 'src/services/tag.service'; -import { TrashService } from 'src/services/trash.service'; -import { UserService } from 'src/services/user.service'; -import { VersionService } from 'src/services/version.service'; - -@Injectable() -export class MicroservicesService { - constructor( - private auditService: AuditService, - private assetService: AssetService, - private backupService: BackupService, - private jobService: JobService, - private libraryService: LibraryService, - private mediaService: MediaService, - private metadataService: MetadataService, - private notificationService: NotificationService, - private personService: PersonService, - private smartInfoService: SmartInfoService, - private sessionService: SessionService, - private storageTemplateService: StorageTemplateService, - private storageService: StorageService, - private tagService: TagService, - private trashService: TrashService, - private userService: UserService, - private duplicateService: DuplicateService, - private versionService: VersionService, - ) {} - - @OnEvent({ name: 'app.bootstrap' }) - async onBootstrap(app: ArgOf<'app.bootstrap'>) { - if (app !== ImmichWorker.MICROSERVICES) { - return; - } - - await this.jobService.init({ - [JobName.ASSET_DELETION]: (data) => this.assetService.handleAssetDeletion(data), - [JobName.ASSET_DELETION_CHECK]: () => this.assetService.handleAssetDeletionCheck(), - [JobName.BACKUP_DATABASE]: () => this.backupService.handleBackupDatabase(), - [JobName.DELETE_FILES]: (data: IDeleteFilesJob) => this.storageService.handleDeleteFiles(data), - [JobName.CLEAN_OLD_AUDIT_LOGS]: () => this.auditService.handleCleanup(), - [JobName.CLEAN_OLD_SESSION_TOKENS]: () => this.sessionService.handleCleanup(), - [JobName.USER_DELETE_CHECK]: () => this.userService.handleUserDeleteCheck(), - [JobName.USER_DELETION]: (data) => this.userService.handleUserDelete(data), - [JobName.USER_SYNC_USAGE]: () => this.userService.handleUserSyncUsage(), - [JobName.QUEUE_SMART_SEARCH]: (data) => this.smartInfoService.handleQueueEncodeClip(data), - [JobName.SMART_SEARCH]: (data) => this.smartInfoService.handleEncodeClip(data), - [JobName.QUEUE_DUPLICATE_DETECTION]: (data) => this.duplicateService.handleQueueSearchDuplicates(data), - [JobName.DUPLICATE_DETECTION]: (data) => this.duplicateService.handleSearchDuplicates(data), - [JobName.STORAGE_TEMPLATE_MIGRATION]: () => this.storageTemplateService.handleMigration(), - [JobName.STORAGE_TEMPLATE_MIGRATION_SINGLE]: (data) => this.storageTemplateService.handleMigrationSingle(data), - [JobName.QUEUE_MIGRATION]: () => this.mediaService.handleQueueMigration(), - [JobName.MIGRATE_ASSET]: (data) => this.mediaService.handleAssetMigration(data), - [JobName.MIGRATE_PERSON]: (data) => this.personService.handlePersonMigration(data), - [JobName.QUEUE_GENERATE_THUMBNAILS]: (data) => this.mediaService.handleQueueGenerateThumbnails(data), - [JobName.GENERATE_THUMBNAILS]: (data) => this.mediaService.handleGenerateThumbnails(data), - [JobName.QUEUE_VIDEO_CONVERSION]: (data) => this.mediaService.handleQueueVideoConversion(data), - [JobName.VIDEO_CONVERSION]: (data) => this.mediaService.handleVideoConversion(data), - [JobName.QUEUE_METADATA_EXTRACTION]: (data) => this.metadataService.handleQueueMetadataExtraction(data), - [JobName.METADATA_EXTRACTION]: (data) => this.metadataService.handleMetadataExtraction(data), - [JobName.LINK_LIVE_PHOTOS]: (data) => this.metadataService.handleLivePhotoLinking(data), - [JobName.QUEUE_FACE_DETECTION]: (data) => this.personService.handleQueueDetectFaces(data), - [JobName.FACE_DETECTION]: (data) => this.personService.handleDetectFaces(data), - [JobName.QUEUE_FACIAL_RECOGNITION]: (data) => this.personService.handleQueueRecognizeFaces(data), - [JobName.FACIAL_RECOGNITION]: (data) => this.personService.handleRecognizeFaces(data), - [JobName.GENERATE_PERSON_THUMBNAIL]: (data) => this.personService.handleGeneratePersonThumbnail(data), - [JobName.PERSON_CLEANUP]: () => this.personService.handlePersonCleanup(), - [JobName.QUEUE_SIDECAR]: (data) => this.metadataService.handleQueueSidecar(data), - [JobName.SIDECAR_DISCOVERY]: (data) => this.metadataService.handleSidecarDiscovery(data), - [JobName.SIDECAR_SYNC]: (data) => this.metadataService.handleSidecarSync(data), - [JobName.SIDECAR_WRITE]: (data) => this.metadataService.handleSidecarWrite(data), - [JobName.LIBRARY_QUEUE_SYNC_ALL]: () => this.libraryService.handleQueueSyncAll(), - [JobName.LIBRARY_QUEUE_SYNC_FILES]: (data) => this.libraryService.handleQueueSyncFiles(data), //Queues all files paths on disk - [JobName.LIBRARY_SYNC_FILE]: (data) => this.libraryService.handleSyncFile(data), //Handles a single path on disk //Watcher calls for new files - [JobName.LIBRARY_QUEUE_SYNC_ASSETS]: (data) => this.libraryService.handleQueueSyncAssets(data), //Queues all library assets - [JobName.LIBRARY_SYNC_ASSET]: (data) => this.libraryService.handleSyncAsset(data), //Handles all library assets // Watcher calls for unlink and changed - [JobName.LIBRARY_DELETE]: (data) => this.libraryService.handleDeleteLibrary(data), - [JobName.LIBRARY_QUEUE_CLEANUP]: () => this.libraryService.handleQueueCleanup(), - [JobName.SEND_EMAIL]: (data) => this.notificationService.handleSendEmail(data), - [JobName.NOTIFY_ALBUM_INVITE]: (data) => this.notificationService.handleAlbumInvite(data), - [JobName.NOTIFY_ALBUM_UPDATE]: (data) => this.notificationService.handleAlbumUpdate(data), - [JobName.NOTIFY_SIGNUP]: (data) => this.notificationService.handleUserSignup(data), - [JobName.TAG_CLEANUP]: () => this.tagService.handleTagCleanup(), - [JobName.VERSION_CHECK]: () => this.versionService.handleVersionCheck(), - [JobName.QUEUE_TRASH_EMPTY]: () => this.trashService.handleQueueEmptyTrash(), - }); - } -} diff --git a/server/src/services/notification.service.spec.ts b/server/src/services/notification.service.spec.ts index d07d06443aee1..76da12bbd6abb 100644 --- a/server/src/services/notification.service.spec.ts +++ b/server/src/services/notification.service.spec.ts @@ -77,7 +77,7 @@ describe(NotificationService.name, () => { describe('onConfigUpdate', () => { it('should emit client and server events', () => { - const update = { newConfig: defaults }; + const update = { oldConfig: defaults, newConfig: defaults }; expect(sut.onConfigUpdate(update)).toBeUndefined(); expect(eventMock.clientBroadcast).toHaveBeenCalledWith('on_config_update'); expect(eventMock.serverSend).toHaveBeenCalledWith('config.update', update); diff --git a/server/src/services/notification.service.ts b/server/src/services/notification.service.ts index c3c7727468240..37b265c6ae741 100644 --- a/server/src/services/notification.service.ts +++ b/server/src/services/notification.service.ts @@ -1,17 +1,16 @@ import { BadRequestException, Injectable } from '@nestjs/common'; -import { OnEvent } from 'src/decorators'; +import { OnEvent, OnJob } from 'src/decorators'; import { SystemConfigSmtpDto } from 'src/dtos/system-config.dto'; import { AlbumEntity } from 'src/entities/album.entity'; import { ArgOf } from 'src/interfaces/event.interface'; import { - IEmailJob, IEntityJob, - INotifyAlbumInviteJob, INotifyAlbumUpdateJob, - INotifySignupJob, JobItem, JobName, + JobOf, JobStatus, + QueueName, } from 'src/interfaces/job.interface'; import { EmailImageAttachment, EmailTemplate } from 'src/interfaces/notification.interface'; import { BaseService } from 'src/services/base.service'; @@ -141,7 +140,7 @@ export class NotificationService extends BaseService { setTimeout(() => this.eventRepository.clientSend('on_session_delete', sessionId, sessionId), 500); } - async sendTestEmail(id: string, dto: SystemConfigSmtpDto) { + async sendTestEmail(id: string, dto: SystemConfigSmtpDto, tempTemplate?: string) { const user = await this.userRepository.get(id, { withDeleted: false }); if (!user) { throw new Error('User not found'); @@ -161,8 +160,8 @@ export class NotificationService extends BaseService { baseUrl: getExternalDomain(server, port), displayName: user.name, }, + customTemplate: tempTemplate!, }); - const { messageId } = await this.notificationRepository.sendEmail({ to: user.email, subject: 'Test email from Immich', @@ -176,13 +175,77 @@ export class NotificationService extends BaseService { return { messageId }; } - async handleUserSignup({ id, tempPassword }: INotifySignupJob) { + async getTemplate(name: EmailTemplate, customTemplate: string) { + const { server, templates } = await this.getConfig({ withCache: false }); + const { port } = this.configRepository.getEnv(); + + let templateResponse = ''; + + switch (name) { + case EmailTemplate.WELCOME: { + const { html: _welcomeHtml } = await this.notificationRepository.renderEmail({ + template: EmailTemplate.WELCOME, + data: { + baseUrl: getExternalDomain(server, port), + 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.notificationRepository.renderEmail({ + template: EmailTemplate.ALBUM_UPDATE, + data: { + baseUrl: getExternalDomain(server, port), + 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.notificationRepository.renderEmail({ + template: EmailTemplate.ALBUM_INVITE, + data: { + baseUrl: getExternalDomain(server, port), + 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.NOTIFY_SIGNUP, queue: QueueName.NOTIFICATION }) + async handleUserSignup({ id, tempPassword }: JobOf) { const user = await this.userRepository.get(id, { withDeleted: false }); if (!user) { return JobStatus.SKIPPED; } - const { server } = await this.getConfig({ withCache: true }); + const { server, templates } = await this.getConfig({ withCache: true }); const { port } = this.configRepository.getEnv(); const { html, text } = await this.notificationRepository.renderEmail({ template: EmailTemplate.WELCOME, @@ -192,6 +255,7 @@ export class NotificationService extends BaseService { username: user.email, password: tempPassword, }, + customTemplate: templates.email.welcomeTemplate, }); await this.jobRepository.queue({ @@ -207,7 +271,8 @@ export class NotificationService extends BaseService { return JobStatus.SUCCESS; } - async handleAlbumInvite({ id, recipientId }: INotifyAlbumInviteJob) { + @OnJob({ name: JobName.NOTIFY_ALBUM_INVITE, queue: QueueName.NOTIFICATION }) + async handleAlbumInvite({ id, recipientId }: JobOf) { const album = await this.albumRepository.getById(id, { withAssets: false }); if (!album) { return JobStatus.SKIPPED; @@ -226,7 +291,7 @@ export class NotificationService extends BaseService { const attachment = await this.getAlbumThumbnailAttachment(album); - const { server } = await this.getConfig({ withCache: false }); + const { server, templates } = await this.getConfig({ withCache: false }); const { port } = this.configRepository.getEnv(); const { html, text } = await this.notificationRepository.renderEmail({ template: EmailTemplate.ALBUM_INVITE, @@ -238,6 +303,7 @@ export class NotificationService extends BaseService { recipientName: recipient.name, cid: attachment ? attachment.cid : undefined, }, + customTemplate: templates.email.albumInviteTemplate, }); await this.jobRepository.queue({ @@ -254,7 +320,8 @@ export class NotificationService extends BaseService { return JobStatus.SUCCESS; } - async handleAlbumUpdate({ id, recipientIds }: INotifyAlbumUpdateJob) { + @OnJob({ name: JobName.NOTIFY_ALBUM_UPDATE, queue: QueueName.NOTIFICATION }) + async handleAlbumUpdate({ id, recipientIds }: JobOf) { const album = await this.albumRepository.getById(id, { withAssets: false }); if (!album) { @@ -271,7 +338,7 @@ export class NotificationService extends BaseService { ); const attachment = await this.getAlbumThumbnailAttachment(album); - const { server } = await this.getConfig({ withCache: false }); + const { server, templates } = await this.getConfig({ withCache: false }); const { port } = this.configRepository.getEnv(); for (const recipient of recipients) { @@ -295,6 +362,7 @@ export class NotificationService extends BaseService { recipientName: recipient.name, cid: attachment ? attachment.cid : undefined, }, + customTemplate: templates.email.albumUpdateTemplate, }); await this.jobRepository.queue({ @@ -312,7 +380,8 @@ export class NotificationService extends BaseService { return JobStatus.SUCCESS; } - async handleSendEmail(data: IEmailJob): Promise { + @OnJob({ name: JobName.SEND_EMAIL, queue: QueueName.NOTIFICATION }) + async handleSendEmail(data: JobOf): Promise { const { notifications } = await this.getConfig({ withCache: false }); if (!notifications.smtp.enabled) { return JobStatus.SKIPPED; diff --git a/server/src/services/person.service.spec.ts b/server/src/services/person.service.spec.ts index da4656be021a8..3b749c0ab65cc 100644 --- a/server/src/services/person.service.spec.ts +++ b/server/src/services/person.service.spec.ts @@ -717,7 +717,7 @@ describe(PersonService.name, () => { assetMock.getByIds.mockResolvedValue([assetStub.image]); await sut.handleDetectFaces({ id: assetStub.image.id }); expect(machineLearningMock.detectFaces).toHaveBeenCalledWith( - 'http://immich-machine-learning:3003', + ['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 e5f016d8ef24d..bdec6f88e8e7b 100644 --- a/server/src/services/person.service.ts +++ b/server/src/services/person.service.ts @@ -1,6 +1,7 @@ import { BadRequestException, Injectable, NotFoundException } from '@nestjs/common'; import { FACE_THUMBNAIL_SIZE } from 'src/constants'; import { StorageCore } from 'src/cores/storage.core'; +import { OnJob } from 'src/decorators'; import { BulkIdErrorReason, BulkIdResponseDto } from 'src/dtos/asset-ids.response.dto'; import { AuthDto } from 'src/dtos/auth.dto'; import { @@ -33,13 +34,10 @@ import { } from 'src/enum'; import { WithoutProperty } from 'src/interfaces/asset.interface'; import { - IBaseJob, - IDeferrableJob, - IEntityJob, - INightlyJob, JOBS_ASSET_PAGINATION_SIZE, JobItem, JobName, + JobOf, JobStatus, QueueName, } from 'src/interfaces/job.interface'; @@ -57,16 +55,25 @@ import { IsNull } from 'typeorm'; @Injectable() export class PersonService extends BaseService { async getAll(auth: AuthDto, dto: PersonSearchDto): Promise { - const { withHidden = false, page, size } = dto; + const { withHidden = false, closestAssetId, closestPersonId, page, size } = dto; + let closestFaceAssetId = closestAssetId; const pagination = { take: size, skip: (page - 1) * size, }; + if (closestPersonId) { + const person = await this.personRepository.getById(closestPersonId); + if (!person?.faceAssetId) { + throw new NotFoundException('Person not found'); + } + closestFaceAssetId = person.faceAssetId; + } const { machineLearning } = await this.getConfig({ withCache: false }); const { items, hasNextPage } = await this.personRepository.getAllForUser(pagination, auth.user.id, { minimumFaceCount: machineLearning.facialRecognition.minFaces, withHidden, + closestFaceAssetId, }); const { total, hidden } = await this.personRepository.getNumberOfPeople(auth.user.id); @@ -231,13 +238,15 @@ export class PersonService extends BaseService { this.logger.debug(`Deleted ${people.length} people`); } + @OnJob({ name: JobName.PERSON_CLEANUP, queue: QueueName.BACKGROUND_TASK }) async handlePersonCleanup(): Promise { const people = await this.personRepository.getAllWithoutFaces(); await this.delete(people); return JobStatus.SUCCESS; } - async handleQueueDetectFaces({ force }: IBaseJob): Promise { + @OnJob({ name: JobName.QUEUE_FACE_DETECTION, queue: QueueName.FACE_DETECTION }) + async handleQueueDetectFaces({ force }: JobOf): Promise { const { machineLearning } = await this.getConfig({ withCache: false }); if (!isFacialRecognitionEnabled(machineLearning)) { return JobStatus.SKIPPED; @@ -272,7 +281,8 @@ export class PersonService extends BaseService { return JobStatus.SUCCESS; } - async handleDetectFaces({ id }: IEntityJob): Promise { + @OnJob({ name: JobName.FACE_DETECTION, queue: QueueName.FACE_DETECTION }) + async handleDetectFaces({ id }: JobOf): Promise { const { machineLearning } = await this.getConfig({ withCache: true }); if (!isFacialRecognitionEnabled(machineLearning)) { return JobStatus.SKIPPED; @@ -296,7 +306,7 @@ export class PersonService extends BaseService { } const { imageHeight, imageWidth, faces } = await this.machineLearningRepository.detectFaces( - machineLearning.url, + machineLearning.urls, previewFile.path, machineLearning.facialRecognition, ); @@ -376,7 +386,8 @@ export class PersonService extends BaseService { return intersection / union; } - async handleQueueRecognizeFaces({ force, nightly }: INightlyJob): Promise { + @OnJob({ name: JobName.QUEUE_FACIAL_RECOGNITION, queue: QueueName.FACIAL_RECOGNITION }) + async handleQueueRecognizeFaces({ force, nightly }: JobOf): Promise { const { machineLearning } = await this.getConfig({ withCache: false }); if (!isFacialRecognitionEnabled(machineLearning)) { return JobStatus.SKIPPED; @@ -426,7 +437,8 @@ export class PersonService extends BaseService { return JobStatus.SUCCESS; } - async handleRecognizeFaces({ id, deferred }: IDeferrableJob): Promise { + @OnJob({ name: JobName.FACIAL_RECOGNITION, queue: QueueName.FACIAL_RECOGNITION }) + async handleRecognizeFaces({ id, deferred }: JobOf): Promise { const { machineLearning } = await this.getConfig({ withCache: true }); if (!isFacialRecognitionEnabled(machineLearning)) { return JobStatus.SKIPPED; @@ -509,7 +521,8 @@ export class PersonService extends BaseService { return JobStatus.SUCCESS; } - async handlePersonMigration({ id }: IEntityJob): Promise { + @OnJob({ name: JobName.MIGRATE_PERSON, queue: QueueName.MIGRATION }) + async handlePersonMigration({ id }: JobOf): Promise { const person = await this.personRepository.getById(id); if (!person) { return JobStatus.FAILED; @@ -520,7 +533,8 @@ export class PersonService extends BaseService { return JobStatus.SUCCESS; } - async handleGeneratePersonThumbnail(data: IEntityJob): Promise { + @OnJob({ name: JobName.GENERATE_PERSON_THUMBNAIL, queue: QueueName.THUMBNAIL_GENERATION }) + async handleGeneratePersonThumbnail(data: JobOf): Promise { const { machineLearning, metadata, image } = await this.getConfig({ withCache: true }); if (!isFacialRecognitionEnabled(machineLearning) && !isFaceImportEnabled(metadata)) { return JobStatus.SKIPPED; diff --git a/server/src/services/search.service.spec.ts b/server/src/services/search.service.spec.ts index e0b03f31aee3b..3933526167339 100644 --- a/server/src/services/search.service.spec.ts +++ b/server/src/services/search.service.spec.ts @@ -47,14 +47,9 @@ describe(SearchService.name, () => { fieldName: 'exifInfo.city', items: [{ value: 'Paris', data: assetStub.image.id }], }); - assetMock.getAssetIdByTag.mockResolvedValue({ - fieldName: 'smartInfo.tags', - items: [{ value: 'train', data: assetStub.imageFrom2015.id }], - }); assetMock.getByIdsWithAllRelations.mockResolvedValue([assetStub.image, assetStub.imageFrom2015]); const expectedResponse = [ { fieldName: 'exifInfo.city', items: [{ value: 'Paris', data: mapAsset(assetStub.image) }] }, - { fieldName: 'smartInfo.tags', items: [{ value: 'train', data: mapAsset(assetStub.imageFrom2015) }] }, ]; const result = await sut.getExploreData(authStub.user1); @@ -64,20 +59,84 @@ describe(SearchService.name, () => { }); describe('getSearchSuggestions', () => { - it('should return search suggestions (including null)', async () => { - searchMock.getCountries.mockResolvedValue(['USA', null]); + it('should return search suggestions for country', async () => { + searchMock.getCountries.mockResolvedValue(['USA']); + await expect( + sut.getSearchSuggestions(authStub.user1, { includeNull: false, type: SearchSuggestionType.COUNTRY }), + ).resolves.toEqual(['USA']); + expect(searchMock.getCountries).toHaveBeenCalledWith([authStub.user1.user.id]); + }); + + it('should return search suggestions for country (including null)', async () => { + searchMock.getCountries.mockResolvedValue(['USA']); await expect( sut.getSearchSuggestions(authStub.user1, { includeNull: true, type: SearchSuggestionType.COUNTRY }), ).resolves.toEqual(['USA', null]); expect(searchMock.getCountries).toHaveBeenCalledWith([authStub.user1.user.id]); }); - it('should return search suggestions (without null)', async () => { - searchMock.getCountries.mockResolvedValue(['USA', null]); + it('should return search suggestions for state', async () => { + searchMock.getStates.mockResolvedValue(['California']); await expect( - sut.getSearchSuggestions(authStub.user1, { includeNull: false, type: SearchSuggestionType.COUNTRY }), - ).resolves.toEqual(['USA']); - expect(searchMock.getCountries).toHaveBeenCalledWith([authStub.user1.user.id]); + sut.getSearchSuggestions(authStub.user1, { includeNull: false, type: SearchSuggestionType.STATE }), + ).resolves.toEqual(['California']); + expect(searchMock.getStates).toHaveBeenCalledWith([authStub.user1.user.id], expect.anything()); + }); + + it('should return search suggestions for state (including null)', async () => { + searchMock.getStates.mockResolvedValue(['California']); + await expect( + sut.getSearchSuggestions(authStub.user1, { includeNull: true, type: SearchSuggestionType.STATE }), + ).resolves.toEqual(['California', null]); + expect(searchMock.getStates).toHaveBeenCalledWith([authStub.user1.user.id], expect.anything()); + }); + + it('should return search suggestions for city', async () => { + searchMock.getCities.mockResolvedValue(['Denver']); + await expect( + sut.getSearchSuggestions(authStub.user1, { includeNull: false, type: SearchSuggestionType.CITY }), + ).resolves.toEqual(['Denver']); + expect(searchMock.getCities).toHaveBeenCalledWith([authStub.user1.user.id], expect.anything()); + }); + + it('should return search suggestions for city (including null)', async () => { + searchMock.getCities.mockResolvedValue(['Denver']); + await expect( + sut.getSearchSuggestions(authStub.user1, { includeNull: true, type: SearchSuggestionType.CITY }), + ).resolves.toEqual(['Denver', null]); + expect(searchMock.getCities).toHaveBeenCalledWith([authStub.user1.user.id], expect.anything()); + }); + + it('should return search suggestions for camera make', async () => { + searchMock.getCameraMakes.mockResolvedValue(['Nikon']); + await expect( + sut.getSearchSuggestions(authStub.user1, { includeNull: false, type: SearchSuggestionType.CAMERA_MAKE }), + ).resolves.toEqual(['Nikon']); + expect(searchMock.getCameraMakes).toHaveBeenCalledWith([authStub.user1.user.id], expect.anything()); + }); + + it('should return search suggestions for camera make (including null)', async () => { + searchMock.getCameraMakes.mockResolvedValue(['Nikon']); + await expect( + sut.getSearchSuggestions(authStub.user1, { includeNull: true, type: SearchSuggestionType.CAMERA_MAKE }), + ).resolves.toEqual(['Nikon', null]); + expect(searchMock.getCameraMakes).toHaveBeenCalledWith([authStub.user1.user.id], expect.anything()); + }); + + it('should return search suggestions for camera model', async () => { + searchMock.getCameraModels.mockResolvedValue(['Fujifilm X100VI']); + await expect( + sut.getSearchSuggestions(authStub.user1, { includeNull: false, type: SearchSuggestionType.CAMERA_MODEL }), + ).resolves.toEqual(['Fujifilm X100VI']); + expect(searchMock.getCameraModels).toHaveBeenCalledWith([authStub.user1.user.id], expect.anything()); + }); + + it('should return search suggestions for camera model (including null)', async () => { + searchMock.getCameraModels.mockResolvedValue(['Fujifilm X100VI']); + await expect( + sut.getSearchSuggestions(authStub.user1, { includeNull: true, type: SearchSuggestionType.CAMERA_MODEL }), + ).resolves.toEqual(['Fujifilm X100VI', null]); + expect(searchMock.getCameraModels).toHaveBeenCalledWith([authStub.user1.user.id], expect.anything()); }); }); }); diff --git a/server/src/services/search.service.ts b/server/src/services/search.service.ts index 03ffbe97db14e..7fc947a8b533c 100644 --- a/server/src/services/search.service.ts +++ b/server/src/services/search.service.ts @@ -34,10 +34,8 @@ export class SearchService extends BaseService { async getExploreData(auth: AuthDto): Promise[]> { const options = { maxFields: 12, minAssetsPerField: 5 }; - const results = await Promise.all([ - this.assetRepository.getAssetIdByCity(auth.user.id, options), - this.assetRepository.getAssetIdByTag(auth.user.id, options), - ]); + const result = await this.assetRepository.getAssetIdByCity(auth.user.id, options); + const results = [result]; const assetIds = new Set(results.flatMap((field) => field.items.map((item) => item.data))); const assets = await this.assetRepository.getByIdsWithAllRelations([...assetIds]); const assetMap = new Map(assets.map((asset) => [asset.id, mapAsset(asset)])); @@ -88,7 +86,7 @@ export class SearchService extends BaseService { const userIds = await this.getUserIdsToSearch(auth); const embedding = await this.machineLearningRepository.encodeText( - machineLearning.url, + machineLearning.urls, dto.query, machineLearning.clip, ); @@ -110,8 +108,11 @@ export class SearchService extends BaseService { async getSearchSuggestions(auth: AuthDto, dto: SearchSuggestionRequestDto) { const userIds = await this.getUserIdsToSearch(auth); - const results = await this.getSuggestions(userIds, dto); - return results.filter((result) => (dto.includeNull ? true : result !== null)); + const suggestions = await this.getSuggestions(userIds, dto); + if (dto.includeNull) { + suggestions.push(null); + } + return suggestions; } private getSuggestions(userIds: string[], dto: SearchSuggestionRequestDto) { @@ -120,19 +121,19 @@ export class SearchService extends BaseService { return this.searchRepository.getCountries(userIds); } case SearchSuggestionType.STATE: { - return this.searchRepository.getStates(userIds, dto.country); + return this.searchRepository.getStates(userIds, dto); } case SearchSuggestionType.CITY: { - return this.searchRepository.getCities(userIds, dto.country, dto.state); + return this.searchRepository.getCities(userIds, dto); } case SearchSuggestionType.CAMERA_MAKE: { - return this.searchRepository.getCameraMakes(userIds, dto.model); + return this.searchRepository.getCameraMakes(userIds, dto); } case SearchSuggestionType.CAMERA_MODEL: { - return this.searchRepository.getCameraModels(userIds, dto.make); + return this.searchRepository.getCameraModels(userIds, dto); } default: { - return []; + return [] as (string | null)[]; } } } diff --git a/server/src/services/server.service.spec.ts b/server/src/services/server.service.spec.ts index ab6eb3b1a4f05..3f7fafcebf1dd 100644 --- a/server/src/services/server.service.spec.ts +++ b/server/src/services/server.service.spec.ts @@ -169,6 +169,7 @@ describe(ServerService.name, () => { isInitialized: undefined, isOnboarded: false, externalDomain: '', + publicUsers: true, mapDarkStyleUrl: 'https://tiles.immich.cloud/v1/style/dark.json', mapLightStyleUrl: 'https://tiles.immich.cloud/v1/style/light.json', }); @@ -185,6 +186,8 @@ describe(ServerService.name, () => { photos: 10, videos: 11, usage: 12_345, + usagePhotos: 1, + usageVideos: 11_345, quotaSizeInBytes: 0, }, { @@ -193,6 +196,8 @@ describe(ServerService.name, () => { photos: 10, videos: 20, usage: 123_456, + usagePhotos: 100, + usageVideos: 23_456, quotaSizeInBytes: 0, }, { @@ -201,6 +206,8 @@ describe(ServerService.name, () => { photos: 100, videos: 0, usage: 987_654, + usagePhotos: 900, + usageVideos: 87_654, quotaSizeInBytes: 0, }, ]); @@ -209,11 +216,15 @@ describe(ServerService.name, () => { photos: 120, videos: 31, usage: 1_123_455, + usagePhotos: 1001, + usageVideos: 122_455, usageByUser: [ { photos: 10, quotaSizeInBytes: 0, usage: 12_345, + usagePhotos: 1, + usageVideos: 11_345, userName: '1 User', userId: 'user1', videos: 11, @@ -222,6 +233,8 @@ describe(ServerService.name, () => { photos: 10, quotaSizeInBytes: 0, usage: 123_456, + usagePhotos: 100, + usageVideos: 23_456, userName: '2 User', userId: 'user2', videos: 20, @@ -230,6 +243,8 @@ describe(ServerService.name, () => { photos: 100, quotaSizeInBytes: 0, usage: 987_654, + usagePhotos: 900, + usageVideos: 87_654, userName: '3 User', userId: 'user3', videos: 0, diff --git a/server/src/services/server.service.ts b/server/src/services/server.service.ts index 3fc319a2fd938..e9dd908a7c3ac 100644 --- a/server/src/services/server.service.ts +++ b/server/src/services/server.service.ts @@ -110,6 +110,7 @@ export class ServerService extends BaseService { isInitialized, isOnboarded: onboarding?.isOnboarded || false, externalDomain: config.server.externalDomain, + publicUsers: config.server.publicUsers, mapDarkStyleUrl: config.map.darkStyle, mapLightStyleUrl: config.map.lightStyle, }; @@ -126,11 +127,16 @@ export class ServerService extends BaseService { usage.photos = user.photos; usage.videos = user.videos; usage.usage = user.usage; + usage.usagePhotos = user.usagePhotos; + usage.usageVideos = user.usageVideos; usage.quotaSizeInBytes = user.quotaSizeInBytes; serverStats.photos += usage.photos; serverStats.videos += usage.videos; serverStats.usage += usage.usage; + serverStats.usagePhotos += usage.usagePhotos; + serverStats.usageVideos += usage.usageVideos; + serverStats.usageByUser.push(usage); } diff --git a/server/src/services/session.service.ts b/server/src/services/session.service.ts index 2e27942c663a1..68df7828ad784 100644 --- a/server/src/services/session.service.ts +++ b/server/src/services/session.service.ts @@ -1,14 +1,16 @@ import { Injectable } from '@nestjs/common'; import { DateTime } from 'luxon'; +import { OnJob } from 'src/decorators'; import { AuthDto } from 'src/dtos/auth.dto'; import { SessionResponseDto, mapSession } from 'src/dtos/session.dto'; import { Permission } from 'src/enum'; -import { JobStatus } from 'src/interfaces/job.interface'; +import { JobName, JobStatus, QueueName } from 'src/interfaces/job.interface'; import { BaseService } from 'src/services/base.service'; @Injectable() export class SessionService extends BaseService { - async handleCleanup() { + @OnJob({ name: JobName.CLEAN_OLD_SESSION_TOKENS, queue: QueueName.BACKGROUND_TASK }) + async handleCleanup(): Promise { const sessions = await this.sessionRepository.search({ updatedBefore: DateTime.now().minus({ days: 90 }).toJSDate(), }); diff --git a/server/src/services/smart-info.service.spec.ts b/server/src/services/smart-info.service.spec.ts index f53822a9e2251..0b0ee6b20f30b 100644 --- a/server/src/services/smart-info.service.spec.ts +++ b/server/src/services/smart-info.service.spec.ts @@ -1,6 +1,7 @@ import { SystemConfig } from 'src/config'; import { ImmichWorker } from 'src/enum'; import { IAssetRepository, WithoutProperty } from 'src/interfaces/asset.interface'; +import { IConfigRepository } from 'src/interfaces/config.interface'; import { IDatabaseRepository } from 'src/interfaces/database.interface'; import { IJobRepository, JobName, JobStatus } from 'src/interfaces/job.interface'; import { IMachineLearningRepository } from 'src/interfaces/machine-learning.interface'; @@ -22,12 +23,14 @@ describe(SmartInfoService.name, () => { let machineLearningMock: Mocked; let searchMock: Mocked; let systemMock: Mocked; + let configMock: Mocked; beforeEach(() => { - ({ sut, assetMock, databaseMock, jobMock, machineLearningMock, searchMock, systemMock } = + ({ sut, assetMock, databaseMock, jobMock, machineLearningMock, searchMock, systemMock, configMock } = newTestService(SmartInfoService)); assetMock.getByIds.mockResolvedValue([assetStub.image]); + configMock.getWorker.mockReturnValue(ImmichWorker.MICROSERVICES); }); it('should work', () => { @@ -63,26 +66,10 @@ describe(SmartInfoService.name, () => { }); }); - describe('onBootstrapEvent', () => { - it('should return if not microservices', async () => { - await sut.onBootstrap(ImmichWorker.API); - - expect(systemMock.get).not.toHaveBeenCalled(); - expect(searchMock.getDimensionSize).not.toHaveBeenCalled(); - expect(searchMock.setDimensionSize).not.toHaveBeenCalled(); - expect(searchMock.deleteAllSearchEmbeddings).not.toHaveBeenCalled(); - expect(jobMock.getQueueStatus).not.toHaveBeenCalled(); - expect(jobMock.pause).not.toHaveBeenCalled(); - expect(jobMock.waitForQueueCompletion).not.toHaveBeenCalled(); - expect(jobMock.resume).not.toHaveBeenCalled(); - }); - + describe('onConfigInit', () => { it('should return if machine learning is disabled', async () => { - systemMock.get.mockResolvedValue(systemConfigStub.machineLearningDisabled); - - await sut.onBootstrap(ImmichWorker.MICROSERVICES); + await sut.onConfigInit({ newConfig: systemConfigStub.machineLearningDisabled as SystemConfig }); - expect(systemMock.get).toHaveBeenCalledTimes(1); expect(searchMock.getDimensionSize).not.toHaveBeenCalled(); expect(searchMock.setDimensionSize).not.toHaveBeenCalled(); expect(searchMock.deleteAllSearchEmbeddings).not.toHaveBeenCalled(); @@ -95,9 +82,8 @@ describe(SmartInfoService.name, () => { it('should return if model and DB dimension size are equal', async () => { searchMock.getDimensionSize.mockResolvedValue(512); - await sut.onBootstrap(ImmichWorker.MICROSERVICES); + await sut.onConfigInit({ newConfig: systemConfigStub.machineLearningEnabled as SystemConfig }); - expect(systemMock.get).toHaveBeenCalledTimes(1); expect(searchMock.getDimensionSize).toHaveBeenCalledTimes(1); expect(searchMock.setDimensionSize).not.toHaveBeenCalled(); expect(searchMock.deleteAllSearchEmbeddings).not.toHaveBeenCalled(); @@ -111,9 +97,8 @@ describe(SmartInfoService.name, () => { searchMock.getDimensionSize.mockResolvedValue(768); jobMock.getQueueStatus.mockResolvedValue({ isActive: false, isPaused: false }); - await sut.onBootstrap(ImmichWorker.MICROSERVICES); + await sut.onConfigInit({ newConfig: systemConfigStub.machineLearningEnabled as SystemConfig }); - expect(systemMock.get).toHaveBeenCalledTimes(1); expect(searchMock.getDimensionSize).toHaveBeenCalledTimes(1); expect(searchMock.setDimensionSize).toHaveBeenCalledWith(512); expect(jobMock.getQueueStatus).toHaveBeenCalledTimes(1); @@ -126,9 +111,8 @@ describe(SmartInfoService.name, () => { searchMock.getDimensionSize.mockResolvedValue(768); jobMock.getQueueStatus.mockResolvedValue({ isActive: false, isPaused: true }); - await sut.onBootstrap(ImmichWorker.MICROSERVICES); + await sut.onConfigInit({ newConfig: systemConfigStub.machineLearningEnabled as SystemConfig }); - expect(systemMock.get).toHaveBeenCalledTimes(1); expect(searchMock.getDimensionSize).toHaveBeenCalledTimes(1); expect(searchMock.setDimensionSize).toHaveBeenCalledWith(512); expect(jobMock.getQueueStatus).toHaveBeenCalledTimes(1); @@ -305,7 +289,7 @@ describe(SmartInfoService.name, () => { expect(await sut.handleEncodeClip({ id: assetStub.image.id })).toEqual(JobStatus.SUCCESS); expect(machineLearningMock.encodeImage).toHaveBeenCalledWith( - 'http://immich-machine-learning:3003', + ['http://immich-machine-learning:3003'], '/uploads/user-id/thumbs/path.jpg', expect.objectContaining({ modelName: 'ViT-B-32__openai' }), ); @@ -338,7 +322,7 @@ describe(SmartInfoService.name, () => { expect(databaseMock.wait).toHaveBeenCalledWith(512); expect(machineLearningMock.encodeImage).toHaveBeenCalledWith( - 'http://immich-machine-learning:3003', + ['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 778f40c931618..8fef961fe1f32 100644 --- a/server/src/services/smart-info.service.ts +++ b/server/src/services/smart-info.service.ts @@ -1,18 +1,11 @@ import { Injectable } from '@nestjs/common'; import { SystemConfig } from 'src/config'; -import { OnEvent } from 'src/decorators'; +import { OnEvent, OnJob } from 'src/decorators'; import { ImmichWorker } from 'src/enum'; import { WithoutProperty } from 'src/interfaces/asset.interface'; import { DatabaseLock } from 'src/interfaces/database.interface'; import { ArgOf } from 'src/interfaces/event.interface'; -import { - IBaseJob, - IEntityJob, - JOBS_ASSET_PAGINATION_SIZE, - JobName, - JobStatus, - QueueName, -} from 'src/interfaces/job.interface'; +import { JOBS_ASSET_PAGINATION_SIZE, JobName, JobOf, JobStatus, QueueName } from 'src/interfaces/job.interface'; import { BaseService } from 'src/services/base.service'; import { getAssetFiles } from 'src/utils/asset.util'; import { getCLIPModelInfo, isSmartSearchEnabled } from 'src/utils/misc'; @@ -20,17 +13,12 @@ import { usePagination } from 'src/utils/pagination'; @Injectable() export class SmartInfoService extends BaseService { - @OnEvent({ name: 'app.bootstrap' }) - async onBootstrap(app: ArgOf<'app.bootstrap'>) { - if (app !== ImmichWorker.MICROSERVICES) { - return; - } - - const config = await this.getConfig({ withCache: false }); - await this.init(config); + @OnEvent({ name: 'config.init', workers: [ImmichWorker.MICROSERVICES] }) + async onConfigInit({ newConfig }: ArgOf<'config.init'>) { + await this.init(newConfig); } - @OnEvent({ name: 'config.update' }) + @OnEvent({ name: 'config.update', workers: [ImmichWorker.MICROSERVICES], server: true }) async onConfigUpdate({ oldConfig, newConfig }: ArgOf<'config.update'>) { await this.init(newConfig, oldConfig); } @@ -86,7 +74,8 @@ export class SmartInfoService extends BaseService { }); } - async handleQueueEncodeClip({ force }: IBaseJob): Promise { + @OnJob({ name: JobName.QUEUE_SMART_SEARCH, queue: QueueName.SMART_SEARCH }) + async handleQueueEncodeClip({ force }: JobOf): Promise { const { machineLearning } = await this.getConfig({ withCache: false }); if (!isSmartSearchEnabled(machineLearning)) { return JobStatus.SKIPPED; @@ -111,7 +100,8 @@ export class SmartInfoService extends BaseService { return JobStatus.SUCCESS; } - async handleEncodeClip({ id }: IEntityJob): Promise { + @OnJob({ name: JobName.SMART_SEARCH, queue: QueueName.SMART_SEARCH }) + async handleEncodeClip({ id }: JobOf): Promise { const { machineLearning } = await this.getConfig({ withCache: true }); if (!isSmartSearchEnabled(machineLearning)) { return JobStatus.SKIPPED; @@ -132,7 +122,7 @@ export class SmartInfoService extends BaseService { } const embedding = await this.machineLearningRepository.encodeImage( - machineLearning.url, + machineLearning.urls, previewFile.path, machineLearning.clip, ); diff --git a/server/src/services/storage-template.service.spec.ts b/server/src/services/storage-template.service.spec.ts index fd063bd50d419..728e891d05379 100644 --- a/server/src/services/storage-template.service.spec.ts +++ b/server/src/services/storage-template.service.spec.ts @@ -38,7 +38,7 @@ describe(StorageTemplateService.name, () => { systemMock.get.mockResolvedValue({ storageTemplate: { enabled: true } }); - sut.onConfigUpdate({ newConfig: defaults }); + sut.onConfigInit({ newConfig: defaults }); }); describe('onConfigValidate', () => { @@ -171,7 +171,7 @@ describe(StorageTemplateService.name, () => { const config = structuredClone(defaults); config.storageTemplate.template = '{{y}}/{{#if album}}{{album}}{{else}}other/{{MM}}{{/if}}/{{filename}}'; - sut.onConfigUpdate({ oldConfig: defaults, newConfig: config }); + sut.onConfigInit({ newConfig: config }); userMock.get.mockResolvedValue(user); assetMock.getByIds.mockResolvedValueOnce([asset]); @@ -192,7 +192,7 @@ describe(StorageTemplateService.name, () => { const user = userStub.user1; const config = structuredClone(defaults); config.storageTemplate.template = '{{y}}/{{#if album}}{{album}}{{else}}other//{{MM}}{{/if}}/{{filename}}'; - sut.onConfigUpdate({ oldConfig: defaults, newConfig: config }); + sut.onConfigInit({ newConfig: config }); userMock.get.mockResolvedValue(user); assetMock.getByIds.mockResolvedValueOnce([asset]); diff --git a/server/src/services/storage-template.service.ts b/server/src/services/storage-template.service.ts index d2394356609b8..e8e4bd12a5569 100644 --- a/server/src/services/storage-template.service.ts +++ b/server/src/services/storage-template.service.ts @@ -4,13 +4,13 @@ import { DateTime } from 'luxon'; import path from 'node:path'; import sanitize from 'sanitize-filename'; import { StorageCore } from 'src/cores/storage.core'; -import { OnEvent } from 'src/decorators'; +import { OnEvent, OnJob } from 'src/decorators'; import { SystemConfigTemplateStorageOptionDto } from 'src/dtos/system-config.dto'; import { AssetEntity } from 'src/entities/asset.entity'; import { AssetPathType, AssetType, StorageFolder } from 'src/enum'; import { DatabaseLock } from 'src/interfaces/database.interface'; import { ArgOf } from 'src/interfaces/event.interface'; -import { IEntityJob, JOBS_ASSET_PAGINATION_SIZE, JobStatus } from 'src/interfaces/job.interface'; +import { JobName, JobOf, JOBS_ASSET_PAGINATION_SIZE, JobStatus, QueueName } from 'src/interfaces/job.interface'; import { BaseService } from 'src/services/base.service'; import { getLivePhotoMotionFilename } from 'src/utils/file'; import { usePagination } from 'src/utils/pagination'; @@ -74,8 +74,8 @@ export class StorageTemplateService extends BaseService { return this._template; } - @OnEvent({ name: 'config.update', server: true }) - onConfigUpdate({ newConfig }: ArgOf<'config.update'>) { + @OnEvent({ name: 'config.init' }) + onConfigInit({ newConfig }: ArgOf<'config.init'>) { const template = newConfig.storageTemplate.template; if (!this._template || template !== this.template.raw) { this.logger.debug(`Compiling new storage template: ${template}`); @@ -83,6 +83,11 @@ export class StorageTemplateService extends BaseService { } } + @OnEvent({ name: 'config.update', server: true }) + onConfigUpdate({ newConfig }: ArgOf<'config.update'>) { + this.onConfigInit({ newConfig }); + } + @OnEvent({ name: 'config.validate' }) onConfigValidate({ newConfig }: ArgOf<'config.validate'>) { try { @@ -108,7 +113,8 @@ export class StorageTemplateService extends BaseService { return { ...storageTokens, presetOptions: storagePresets }; } - async handleMigrationSingle({ id }: IEntityJob): Promise { + @OnJob({ name: JobName.STORAGE_TEMPLATE_MIGRATION_SINGLE, queue: QueueName.STORAGE_TEMPLATE_MIGRATION }) + async handleMigrationSingle({ id }: JobOf): Promise { const config = await this.getConfig({ withCache: true }); const storageTemplateEnabled = config.storageTemplate.enabled; if (!storageTemplateEnabled) { @@ -137,6 +143,7 @@ export class StorageTemplateService extends BaseService { return JobStatus.SUCCESS; } + @OnJob({ name: JobName.STORAGE_TEMPLATE_MIGRATION, queue: QueueName.STORAGE_TEMPLATE_MIGRATION }) async handleMigration(): Promise { this.logger.log('Starting storage template migration'); const { storageTemplate } = await this.getConfig({ withCache: true }); diff --git a/server/src/services/storage.service.spec.ts b/server/src/services/storage.service.spec.ts index dd9bb9969d071..dd97a063aeda5 100644 --- a/server/src/services/storage.service.spec.ts +++ b/server/src/services/storage.service.spec.ts @@ -3,7 +3,8 @@ import { IConfigRepository } from 'src/interfaces/config.interface'; import { ILoggerRepository } from 'src/interfaces/logger.interface'; import { IStorageRepository } from 'src/interfaces/storage.interface'; import { ISystemMetadataRepository } from 'src/interfaces/system-metadata.interface'; -import { ImmichStartupError, StorageService } from 'src/services/storage.service'; +import { StorageService } from 'src/services/storage.service'; +import { ImmichStartupError } from 'src/utils/misc'; import { mockEnvData } from 'test/repositories/config.repository.mock'; import { newTestService } from 'test/utils'; import { Mocked } from 'vitest'; diff --git a/server/src/services/storage.service.ts b/server/src/services/storage.service.ts index 3b6a16fb41911..ce26df486977e 100644 --- a/server/src/services/storage.service.ts +++ b/server/src/services/storage.service.ts @@ -1,15 +1,13 @@ import { Injectable } from '@nestjs/common'; import { join } from 'node:path'; import { StorageCore } from 'src/cores/storage.core'; -import { OnEvent } from 'src/decorators'; +import { OnEvent, OnJob } from 'src/decorators'; import { SystemFlags } from 'src/entities/system-metadata.entity'; import { StorageFolder, SystemMetadataKey } from 'src/enum'; import { DatabaseLock } from 'src/interfaces/database.interface'; -import { IDeleteFilesJob, JobStatus } from 'src/interfaces/job.interface'; +import { JobName, JobOf, JobStatus, QueueName } from 'src/interfaces/job.interface'; import { BaseService } from 'src/services/base.service'; - -export class ImmichStartupError extends Error {} -export const isStartUpError = (error: unknown): error is ImmichStartupError => error instanceof ImmichStartupError; +import { ImmichStartupError } from 'src/utils/misc'; const docsMessage = `Please see https://immich.app/docs/administration/system-integrity#folder-checks for more information.`; @@ -66,7 +64,8 @@ export class StorageService extends BaseService { }); } - async handleDeleteFiles(job: IDeleteFilesJob) { + @OnJob({ name: JobName.DELETE_FILES, queue: QueueName.BACKGROUND_TASK }) + async handleDeleteFiles(job: JobOf): Promise { const { files } = job; // TODO: one job per file diff --git a/server/src/services/system-config.service.spec.ts b/server/src/services/system-config.service.spec.ts index 2ad7c78ca22e0..2a20f329330ae 100644 --- a/server/src/services/system-config.service.spec.ts +++ b/server/src/services/system-config.service.spec.ts @@ -65,7 +65,6 @@ const updatedConfig = Object.freeze({ bframes: -1, refs: 0, gopSize: 0, - npl: 0, temporalAQ: false, cqMode: CQMode.AUTO, twoPass: false, @@ -86,7 +85,7 @@ const updatedConfig = Object.freeze({ }, machineLearning: { enabled: true, - url: 'http://immich-machine-learning:3003', + urls: ['http://immich-machine-learning:3003'], clip: { enabled: true, modelName: 'ViT-B-32__openai', @@ -134,6 +133,7 @@ const updatedConfig = Object.freeze({ server: { externalDomain: '', loginPageMessage: '', + publicUsers: true, }, storageTemplate: { enabled: false, @@ -190,6 +190,13 @@ const updatedConfig = Object.freeze({ }, }, }, + templates: { + email: { + albumInviteTemplate: '', + welcomeTemplate: '', + albumUpdateTemplate: '', + }, + }, }); describe(SystemConfigService.name, () => { @@ -262,6 +269,29 @@ describe(SystemConfigService.name, () => { }); }); + it('should accept valid cron expressions', async () => { + configMock.getEnv.mockReturnValue(mockEnvData({ configFile: 'immich-config.json' })); + systemMock.readFile.mockResolvedValue(JSON.stringify({ library: { scan: { cronExpression: '0 0 * * *' } } })); + + await expect(sut.getSystemConfig()).resolves.toMatchObject({ + library: { + scan: { + enabled: true, + cronExpression: '0 0 * * *', + }, + }, + }); + }); + + it('should reject invalid cron expressions', async () => { + configMock.getEnv.mockReturnValue(mockEnvData({ configFile: 'immich-config.json' })); + systemMock.readFile.mockResolvedValue(JSON.stringify({ library: { scan: { cronExpression: 'foo' } } })); + + await expect(sut.getSystemConfig()).rejects.toThrow( + 'library.scan.cronExpression has failed the following constraints: cronValidator', + ); + }); + it('should log errors with the config file', async () => { configMock.getEnv.mockReturnValue(mockEnvData({ configFile: 'immich-config.json' })); @@ -307,11 +337,11 @@ describe(SystemConfigService.name, () => { it('should allow underscores in the machine learning url', async () => { configMock.getEnv.mockReturnValue(mockEnvData({ configFile: 'immich-config.json' })); - const partialConfig = { machineLearning: { url: 'immich_machine_learning' } }; + const partialConfig = { machineLearning: { urls: ['immich_machine_learning'] } }; systemMock.readFile.mockResolvedValue(JSON.stringify(partialConfig)); const config = await sut.getSystemConfig(); - expect(config.machineLearning.url).toEqual('immich_machine_learning'); + expect(config.machineLearning.urls).toEqual(['immich_machine_learning']); }); const externalDomainTests = [ diff --git a/server/src/services/system-config.service.ts b/server/src/services/system-config.service.ts index 8f19b221733a5..b5ae42e0989d1 100644 --- a/server/src/services/system-config.service.ts +++ b/server/src/services/system-config.service.ts @@ -4,17 +4,17 @@ import _ from 'lodash'; import { defaults } from 'src/config'; import { OnEvent } from 'src/decorators'; import { SystemConfigDto, mapConfig } from 'src/dtos/system-config.dto'; -import { ArgOf } from 'src/interfaces/event.interface'; +import { ArgOf, BootstrapEventPriority } from 'src/interfaces/event.interface'; import { BaseService } from 'src/services/base.service'; import { clearConfigCache } from 'src/utils/config'; import { toPlainObject } from 'src/utils/object'; @Injectable() export class SystemConfigService extends BaseService { - @OnEvent({ name: 'app.bootstrap', priority: -100 }) + @OnEvent({ name: 'app.bootstrap', priority: BootstrapEventPriority.SystemConfig }) async onBootstrap() { const config = await this.getConfig({ withCache: false }); - await this.eventRepository.emit('config.update', { newConfig: config }); + await this.eventRepository.emit('config.init', { newConfig: config }); } async getSystemConfig(): Promise { @@ -26,14 +26,18 @@ export class SystemConfigService extends BaseService { return mapConfig(defaults); } - @OnEvent({ name: 'config.update', server: true }) - onConfigUpdate({ newConfig: { logging } }: ArgOf<'config.update'>) { + @OnEvent({ name: 'config.init' }) + onConfigInit({ newConfig: { logging } }: ArgOf<'config.init'>) { 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)'}`); - // TODO only do this if the event is a socket.io event + } + + @OnEvent({ name: 'config.update', server: true }) + onConfigUpdate({ newConfig }: ArgOf<'config.update'>) { + this.onConfigInit({ newConfig }); clearConfigCache(); } diff --git a/server/src/services/tag.service.ts b/server/src/services/tag.service.ts index 5534d74efa63e..2aca400cc71e2 100644 --- a/server/src/services/tag.service.ts +++ b/server/src/services/tag.service.ts @@ -1,4 +1,5 @@ import { BadRequestException, Injectable } from '@nestjs/common'; +import { OnJob } from 'src/decorators'; import { BulkIdResponseDto, BulkIdsDto } from 'src/dtos/asset-ids.response.dto'; import { AuthDto } from 'src/dtos/auth.dto'; import { @@ -12,7 +13,7 @@ import { } from 'src/dtos/tag.dto'; import { TagEntity } from 'src/entities/tag.entity'; import { Permission } from 'src/enum'; -import { JobStatus } from 'src/interfaces/job.interface'; +import { JobName, JobStatus, QueueName } from 'src/interfaces/job.interface'; import { AssetTagItem } from 'src/interfaces/tag.interface'; import { BaseService } from 'src/services/base.service'; import { addAssets, removeAssets } from 'src/utils/asset.util'; @@ -131,6 +132,7 @@ export class TagService extends BaseService { return results; } + @OnJob({ name: JobName.TAG_CLEANUP, queue: QueueName.BACKGROUND_TASK }) async handleTagCleanup() { await this.tagRepository.deleteEmptyTags(); return JobStatus.SUCCESS; diff --git a/server/src/services/trash.service.ts b/server/src/services/trash.service.ts index 91c359392eecd..621dee0f8176d 100644 --- a/server/src/services/trash.service.ts +++ b/server/src/services/trash.service.ts @@ -1,9 +1,9 @@ -import { OnEvent } from 'src/decorators'; +import { OnEvent, OnJob } from 'src/decorators'; import { BulkIdsDto } from 'src/dtos/asset-ids.response.dto'; import { AuthDto } from 'src/dtos/auth.dto'; import { TrashResponseDto } from 'src/dtos/trash.dto'; import { Permission } from 'src/enum'; -import { JOBS_ASSET_PAGINATION_SIZE, JobName, JobStatus } from 'src/interfaces/job.interface'; +import { JOBS_ASSET_PAGINATION_SIZE, JobName, JobStatus, QueueName } from 'src/interfaces/job.interface'; import { BaseService } from 'src/services/base.service'; import { usePagination } from 'src/utils/pagination'; @@ -44,6 +44,7 @@ export class TrashService extends BaseService { await this.jobRepository.queue({ name: JobName.QUEUE_TRASH_EMPTY, data: {} }); } + @OnJob({ name: JobName.QUEUE_TRASH_EMPTY, queue: QueueName.BACKGROUND_TASK }) async handleQueueEmptyTrash() { let count = 0; const assetPagination = usePagination(JOBS_ASSET_PAGINATION_SIZE, (pagination) => diff --git a/server/src/services/user.service.spec.ts b/server/src/services/user.service.spec.ts index 767d8d895453a..08b663046bc31 100644 --- a/server/src/services/user.service.spec.ts +++ b/server/src/services/user.service.spec.ts @@ -38,9 +38,9 @@ describe(UserService.name, () => { }); describe('getAll', () => { - it('should get all users', async () => { + it('admin should get all users', async () => { userMock.getList.mockResolvedValue([userStub.admin]); - await expect(sut.search()).resolves.toEqual([ + await expect(sut.search(authStub.admin)).resolves.toEqual([ expect.objectContaining({ id: authStub.admin.user.id, email: authStub.admin.user.email, @@ -48,6 +48,29 @@ describe(UserService.name, () => { ]); expect(userMock.getList).toHaveBeenCalledWith({ withDeleted: false }); }); + + it('non-admin should get all users when publicUsers enabled', async () => { + userMock.getList.mockResolvedValue([userStub.user1]); + await expect(sut.search(authStub.user1)).resolves.toEqual([ + expect.objectContaining({ + id: authStub.user1.user.id, + email: authStub.user1.user.email, + }), + ]); + expect(userMock.getList).toHaveBeenCalledWith({ withDeleted: false }); + }); + + it('non-admin user should only receive itself when publicUsers is disabled', async () => { + userMock.getList.mockResolvedValue([userStub.user1]); + systemMock.get.mockResolvedValue(systemConfigStub.publicUsersDisabled); + await expect(sut.search(authStub.user1)).resolves.toEqual([ + expect.objectContaining({ + id: authStub.user1.user.id, + email: authStub.user1.user.email, + }), + ]); + expect(userMock.getList).not.toHaveBeenCalledWith({ withDeleted: false }); + }); }); describe('get', () => { diff --git a/server/src/services/user.service.ts b/server/src/services/user.service.ts index f67d04cbd3405..f4ae42b5edd05 100644 --- a/server/src/services/user.service.ts +++ b/server/src/services/user.service.ts @@ -2,6 +2,7 @@ import { BadRequestException, Injectable, NotFoundException } from '@nestjs/comm import { DateTime } from 'luxon'; import { SALT_ROUNDS } from 'src/constants'; import { StorageCore } from 'src/cores/storage.core'; +import { OnJob } from 'src/decorators'; import { AuthDto } from 'src/dtos/auth.dto'; import { LicenseKeyDto, LicenseResponseDto } from 'src/dtos/license.dto'; import { UserPreferencesResponseDto, UserPreferencesUpdateDto, mapPreferences } from 'src/dtos/user-preferences.dto'; @@ -10,7 +11,7 @@ import { UserAdminResponseDto, UserResponseDto, UserUpdateMeDto, mapUser, mapUse import { UserMetadataEntity } from 'src/entities/user-metadata.entity'; import { UserEntity } from 'src/entities/user.entity'; import { CacheControl, StorageFolder, UserMetadataKey } from 'src/enum'; -import { IEntityJob, JobName, JobStatus } from 'src/interfaces/job.interface'; +import { JobName, JobOf, JobStatus, QueueName } from 'src/interfaces/job.interface'; import { UserFindOptions } from 'src/interfaces/user.interface'; import { BaseService } from 'src/services/base.service'; import { ImmichFileResponse } from 'src/utils/file'; @@ -18,8 +19,14 @@ import { getPreferences, getPreferencesPartial, mergePreferences } from 'src/uti @Injectable() export class UserService extends BaseService { - async search(): Promise { - const users = await this.userRepository.getList({ withDeleted: false }); + async search(auth: AuthDto): Promise { + const config = await this.getConfig({ withCache: false }); + + let users: UserEntity[] = [auth.user]; + if (auth.user.isAdmin || config.server.publicUsers) { + users = await this.userRepository.getList({ withDeleted: false }); + } + return users.map((user) => mapUser(user)); } @@ -163,11 +170,13 @@ export class UserService extends BaseService { return licenseData; } + @OnJob({ name: JobName.USER_SYNC_USAGE, queue: QueueName.BACKGROUND_TASK }) async handleUserSyncUsage(): Promise { await this.userRepository.syncUsage(); return JobStatus.SUCCESS; } + @OnJob({ name: JobName.USER_DELETE_CHECK, queue: QueueName.BACKGROUND_TASK }) async handleUserDeleteCheck(): Promise { const users = await this.userRepository.getDeletedUsers(); const config = await this.getConfig({ withCache: false }); @@ -181,7 +190,8 @@ export class UserService extends BaseService { return JobStatus.SUCCESS; } - async handleUserDelete({ id, force }: IEntityJob): Promise { + @OnJob({ name: JobName.USER_DELETION, queue: QueueName.BACKGROUND_TASK }) + async handleUserDelete({ id, force }: JobOf): Promise { const config = await this.getConfig({ withCache: false }); const user = await this.userRepository.get(id, { withDeleted: true }); if (!user) { diff --git a/server/src/services/version.service.ts b/server/src/services/version.service.ts index 231ced1a950af..ff4fa3c6bf636 100644 --- a/server/src/services/version.service.ts +++ b/server/src/services/version.service.ts @@ -2,13 +2,13 @@ import { Injectable } from '@nestjs/common'; import { DateTime } from 'luxon'; import semver, { SemVer } from 'semver'; import { serverVersion } from 'src/constants'; -import { OnEvent } from 'src/decorators'; +import { OnEvent, OnJob } from 'src/decorators'; import { ReleaseNotification, ServerVersionResponseDto } from 'src/dtos/server.dto'; import { VersionCheckMetadata } from 'src/entities/system-metadata.entity'; import { ImmichEnvironment, SystemMetadataKey } from 'src/enum'; import { DatabaseLock } from 'src/interfaces/database.interface'; import { ArgOf } from 'src/interfaces/event.interface'; -import { JobName, JobStatus } from 'src/interfaces/job.interface'; +import { JobName, JobStatus, QueueName } from 'src/interfaces/job.interface'; import { BaseService } from 'src/services/base.service'; const asNotification = ({ checkedAt, releaseVersion }: VersionCheckMetadata): ReleaseNotification => { @@ -48,6 +48,7 @@ export class VersionService extends BaseService { await this.jobRepository.queue({ name: JobName.VERSION_CHECK, data: {} }); } + @OnJob({ name: JobName.VERSION_CHECK, queue: QueueName.BACKGROUND_TASK }) async handleVersionCheck(): Promise { try { this.logger.debug('Running version check'); diff --git a/server/src/utils/asset.util.ts b/server/src/utils/asset.util.ts index 44c291e139766..f8bed5485f8b1 100644 --- a/server/src/utils/asset.util.ts +++ b/server/src/utils/asset.util.ts @@ -1,6 +1,7 @@ import { BadRequestException } from '@nestjs/common'; import { StorageCore } from 'src/cores/storage.core'; import { BulkIdErrorReason, BulkIdResponseDto } from 'src/dtos/asset-ids.response.dto'; +import { UploadFieldName } from 'src/dtos/asset-media.dto'; import { AuthDto } from 'src/dtos/auth.dto'; import { AssetFileEntity } from 'src/entities/asset-files.entity'; import { AssetFileType, AssetType, Permission } from 'src/enum'; @@ -8,6 +9,9 @@ import { IAccessRepository } from 'src/interfaces/access.interface'; import { IAssetRepository } from 'src/interfaces/asset.interface'; import { IEventRepository } from 'src/interfaces/event.interface'; import { IPartnerRepository } from 'src/interfaces/partner.interface'; +import { AuthRequest } from 'src/middleware/auth.guard'; +import { ImmichFile } from 'src/middleware/file-upload.interceptor'; +import { UploadFile } from 'src/services/asset-media.service'; import { checkAccess } from 'src/utils/access'; export interface IBulkAsset { @@ -181,3 +185,21 @@ export const onAfterUnlink = async ( await assetRepository.update({ id: livePhotoVideoId, isVisible: true }); await eventRepository.emit('asset.show', { assetId: livePhotoVideoId, userId }); }; + +export function mapToUploadFile(file: ImmichFile): UploadFile { + return { + uuid: file.uuid, + checksum: file.checksum, + originalPath: file.path, + originalName: Buffer.from(file.originalname, 'latin1').toString('utf8'), + size: file.size, + }; +} + +export const asRequest = (request: AuthRequest, file: Express.Multer.File) => { + return { + auth: request.user || null, + fieldName: file.fieldname as UploadFieldName, + file: mapToUploadFile(file as ImmichFile), + }; +}; diff --git a/server/src/utils/database.ts b/server/src/utils/database.ts index 55e4fcb0e555b..ad2198b38c571 100644 --- a/server/src/utils/database.ts +++ b/server/src/utils/database.ts @@ -90,7 +90,6 @@ export function searchAssetBuilder( isNotInAlbum, withFaces, withPeople, - withSmartInfo, personIds, withStacked, trashedAfter, @@ -123,10 +122,6 @@ export function searchAssetBuilder( builder.leftJoinAndSelect('faces.person', 'person'); } - if (withSmartInfo) { - builder.leftJoinAndSelect(`${builder.alias}.smartInfo`, 'smartInfo'); - } - if (personIds && personIds.length > 0) { const cte = builder .createQueryBuilder() diff --git a/server/src/utils/date-time.ts b/server/src/utils/date-time.ts new file mode 100644 index 0000000000000..e1578cbb19ad2 --- /dev/null +++ b/server/src/utils/date-time.ts @@ -0,0 +1,5 @@ +import { AssetEntity } from 'src/entities/asset.entity'; + +export const getAssetDateTime = (asset: AssetEntity | undefined) => { + return asset?.exifInfo?.dateTimeOriginal || asset?.fileCreatedAt; +}; diff --git a/server/src/utils/file.ts b/server/src/utils/file.ts index 3b26c3e1ba1e8..869e4d78765ea 100644 --- a/server/src/utils/file.ts +++ b/server/src/utils/file.ts @@ -24,6 +24,7 @@ export class ImmichFileResponse { public readonly path!: string; public readonly contentType!: string; public readonly cacheControl!: CacheControl; + public readonly fileName?: string; constructor(response: ImmichFileResponse) { Object.assign(this, response); @@ -56,6 +57,9 @@ export const sendFile = async ( } res.header('Content-Type', file.contentType); + if (file.fileName) { + res.header('Content-Disposition', `inline; filename*=UTF-8''${encodeURIComponent(file.fileName)}`); + } const options: SendFileOptions = { dotfiles: 'allow' }; if (!isAbsolute(file.path)) { diff --git a/server/src/utils/logger.ts b/server/src/utils/logger.ts index 2e33a7bcb557a..cf66404d69657 100644 --- a/server/src/utils/logger.ts +++ b/server/src/utils/logger.ts @@ -16,7 +16,7 @@ export const logGlobalError = (logger: ILoggerRepository, error: Error) => { } if (error instanceof Error) { - logger.error(`Unknown error: ${error}`); + logger.error(`Unknown error: ${error}`, error?.stack); return; } }; diff --git a/server/src/utils/media.ts b/server/src/utils/media.ts index 03d57296d83b8..678e8cb15a48e 100644 --- a/server/src/utils/media.ts +++ b/server/src/utils/media.ts @@ -6,6 +6,8 @@ import { TranscodeCommand, VideoCodecHWConfig, VideoCodecSWConfig, + VideoFormat, + VideoInterfaces, VideoStreamInfo, } from 'src/interfaces/media.interface'; @@ -13,11 +15,11 @@ export class BaseConfig implements VideoCodecSWConfig { readonly presets = ['veryslow', 'slower', 'slow', 'medium', 'fast', 'faster', 'veryfast', 'superfast', 'ultrafast']; protected constructor(protected config: SystemConfigFFmpegDto) {} - static create(config: SystemConfigFFmpegDto, devices: string[] = [], hasMaliOpenCL = false): VideoCodecSWConfig { + static create(config: SystemConfigFFmpegDto, interfaces: VideoInterfaces): VideoCodecSWConfig { if (config.accel === TranscodeHWAccel.DISABLED) { return this.getSWCodecConfig(config); } - return this.getHWCodecConfig(config, devices, hasMaliOpenCL); + return this.getHWCodecConfig(config, interfaces); } private static getSWCodecConfig(config: SystemConfigFFmpegDto) { @@ -40,28 +42,31 @@ export class BaseConfig implements VideoCodecSWConfig { } } - private static getHWCodecConfig(config: SystemConfigFFmpegDto, devices: string[] = [], hasMaliOpenCL = false) { + private static getHWCodecConfig(config: SystemConfigFFmpegDto, interfaces: VideoInterfaces) { let handler: VideoCodecHWConfig; switch (config.accel) { case TranscodeHWAccel.NVENC: { - handler = config.accelDecode ? new NvencHwDecodeConfig(config) : new NvencSwDecodeConfig(config); + handler = config.accelDecode + ? new NvencHwDecodeConfig(config, interfaces) + : new NvencSwDecodeConfig(config, interfaces); break; } case TranscodeHWAccel.QSV: { - handler = config.accelDecode ? new QsvHwDecodeConfig(config, devices) : new QsvSwDecodeConfig(config, devices); + handler = config.accelDecode + ? new QsvHwDecodeConfig(config, interfaces) + : new QsvSwDecodeConfig(config, interfaces); break; } case TranscodeHWAccel.VAAPI: { handler = config.accelDecode - ? new VaapiHwDecodeConfig(config, devices) - : new VaapiSwDecodeConfig(config, devices); + ? new VaapiHwDecodeConfig(config, interfaces) + : new VaapiSwDecodeConfig(config, interfaces); break; } case TranscodeHWAccel.RKMPP: { - handler = - config.accelDecode && hasMaliOpenCL - ? new RkmppHwDecodeConfig(config, devices) - : new RkmppSwDecodeConfig(config, devices); + handler = config.accelDecode + ? new RkmppHwDecodeConfig(config, interfaces) + : new RkmppSwDecodeConfig(config, interfaces); break; } default: { @@ -77,9 +82,14 @@ export class BaseConfig implements VideoCodecSWConfig { return handler; } - getCommand(target: TranscodeTarget, videoStream: VideoStreamInfo, audioStream?: AudioStreamInfo) { + getCommand( + target: TranscodeTarget, + videoStream: VideoStreamInfo, + audioStream?: AudioStreamInfo, + format?: VideoFormat, + ) { const options = { - inputOptions: this.getBaseInputOptions(videoStream), + inputOptions: this.getBaseInputOptions(videoStream, format), outputOptions: [...this.getBaseOutputOptions(target, videoStream, audioStream), '-v verbose'], twoPass: this.eligibleForTwoPass(), progress: { frameCount: videoStream.frameCount, percentInterval: 5 }, @@ -101,7 +111,7 @@ export class BaseConfig implements VideoCodecSWConfig { } // eslint-disable-next-line @typescript-eslint/no-unused-vars - getBaseInputOptions(videoStream: VideoStreamInfo): string[] { + getBaseInputOptions(videoStream: VideoStreamInfo, format?: VideoFormat): string[] { return this.getInputThreadOptions(); } @@ -149,7 +159,11 @@ export class BaseConfig implements VideoCodecSWConfig { options.push(`scale=${this.getScaling(videoStream)}`); } - options.push(...this.getToneMapping(videoStream), 'format=yuv420p'); + options.push(...this.getToneMapping(videoStream)); + if (options.length === 0 && !videoStream.pixelFormat.endsWith('420p')) { + options.push(`format=yuv420p`); + } + return options; } @@ -271,33 +285,20 @@ export class BaseConfig implements VideoCodecSWConfig { getColors() { return { - primaries: '709', - transfer: '709', - matrix: '709', + primaries: 'bt709', + transfer: 'bt709', + matrix: 'bt709', }; } - getNPL() { - if (this.config.npl <= 0) { - // since hable already outputs a darker image, we use a lower npl value for it - return this.config.tonemap === ToneMapping.HABLE ? 100 : 250; - } else { - return this.config.npl; - } - } - getToneMapping(videoStream: VideoStreamInfo) { if (!this.shouldToneMap(videoStream)) { return []; } - const colors = this.getColors(); - - return [ - `zscale=t=linear:npl=${this.getNPL()}`, - `tonemap=${this.config.tonemap}:desat=0`, - `zscale=p=${colors.primaries}:t=${colors.transfer}:m=${colors.matrix}:range=pc`, - ]; + const { primaries, transfer, matrix } = this.getColors(); + const options = `tonemapx=tonemap=${this.config.tonemap}:desat=0:p=${primaries}:t=${transfer}:m=${matrix}:r=pc:peak=100:format=yuv420p`; + return [options]; } getAudioCodec(): string { @@ -326,14 +327,16 @@ export class BaseConfig implements VideoCodecSWConfig { } export class BaseHWConfig extends BaseConfig implements VideoCodecHWConfig { - protected devices: string[]; + protected device: string; + protected interfaces: VideoInterfaces; constructor( protected config: SystemConfigFFmpegDto, - devices: string[] = [], + interfaces: VideoInterfaces, ) { super(config); - this.devices = this.validateDevices(devices); + this.interfaces = interfaces; + this.device = this.getDevice(interfaces); } getSupportedCodecs() { @@ -341,18 +344,29 @@ export class BaseHWConfig extends BaseConfig implements VideoCodecHWConfig { } validateDevices(devices: string[]) { - return devices - .filter((device) => device.startsWith('renderD') || device.startsWith('card')) - .sort((a, b) => { - // order GPU devices first - if (a.startsWith('card') && b.startsWith('renderD')) { - return -1; - } - if (a.startsWith('renderD') && b.startsWith('card')) { - return 1; - } - return -a.localeCompare(b); - }); + if (devices.length === 0) { + throw new Error('No /dev/dri devices found. If using Docker, make sure at least one /dev/dri device is mounted'); + } + + return devices.filter(function (device) { + return device.startsWith('renderD') || device.startsWith('card'); + }); + } + + getDevice({ dri }: VideoInterfaces) { + if (this.config.preferredHwDevice === 'auto') { + // eslint-disable-next-line unicorn/no-array-reduce + return `/dev/dri/${this.validateDevices(dri).reduce(function (a, b) { + return a.localeCompare(b) < 0 ? b : a; + })}`; + } + + const deviceName = this.config.preferredHwDevice.replace('/dev/dri/', ''); + if (!dri.includes(deviceName)) { + throw new Error(`Device '${deviceName}' does not exist. If using Docker, make sure this device is mounted`); + } + + return `/dev/dri/${deviceName}`; } getVideoCodec(): string { @@ -365,20 +379,6 @@ export class BaseHWConfig extends BaseConfig implements VideoCodecHWConfig { } return this.config.gopSize; } - - getPreferredHardwareDevice(): string | undefined { - const device = this.config.preferredHwDevice; - if (device === 'auto') { - return; - } - - const deviceName = device.replace('/dev/dri/', ''); - if (!this.devices.includes(deviceName)) { - throw new Error(`Device '${device}' does not exist`); - } - - return `/dev/dri/${deviceName}`; - } } export class ThumbnailConfig extends BaseConfig { @@ -386,8 +386,11 @@ export class ThumbnailConfig extends BaseConfig { return new ThumbnailConfig(config); } - getBaseInputOptions(): string[] { - return ['-skip_frame nointra', '-sws_flags accurate_rnd+full_chroma_int']; + 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']; } getBaseOutputOptions() { @@ -395,19 +398,14 @@ export class ThumbnailConfig extends BaseConfig { } getFilterOptions(videoStream: VideoStreamInfo): string[] { - const options = [ + return [ 'fps=12:eof_action=pass:round=down', 'thumbnail=12', String.raw`select=gt(scene\,0.1)-eq(prev_selected_n\,n)+isnan(prev_selected_n)+gt(n\,20)`, 'trim=end_frame=2', 'reverse', + ...super.getFilterOptions(videoStream), ]; - if (this.shouldScale(videoStream)) { - options.push(`scale=${this.getScaling(videoStream)}`); - } - - options.push(...this.getToneMapping(videoStream), 'format=yuv420p'); - return options; } getPresetOptions() { @@ -423,19 +421,7 @@ export class ThumbnailConfig extends BaseConfig { } getScaling(videoStream: VideoStreamInfo) { - let options = super.getScaling(videoStream) + ':flags=lanczos+accurate_rnd+full_chroma_int'; - if (!this.shouldToneMap(videoStream)) { - options += ':out_color_matrix=bt601:out_range=pc'; - } - return options; - } - - getColors() { - return { - primaries: '709', - transfer: '601', - matrix: '470bg', - }; + return super.getScaling(videoStream) + ':flags=lanczos+accurate_rnd+full_chroma_int:out_range=pc'; } } @@ -531,12 +517,16 @@ export class AV1Config extends BaseConfig { } export class NvencSwDecodeConfig extends BaseHWConfig { + getDevice() { + return '0'; + } + getSupportedCodecs() { return [VideoCodec.H264, VideoCodec.HEVC, VideoCodec.AV1]; } getBaseInputOptions() { - return ['-init_hw_device cuda=cuda:0', '-filter_hw_device cuda']; + return [`-init_hw_device cuda=cuda:${this.device}`, '-filter_hw_device cuda']; } getBaseOutputOptions(target: TranscodeTarget, videoStream: VideoStreamInfo, audioStream?: AudioStreamInfo) { @@ -559,9 +549,9 @@ export class NvencSwDecodeConfig extends BaseHWConfig { getFilterOptions(videoStream: VideoStreamInfo) { const options = this.getToneMapping(videoStream); - options.push('format=nv12', 'hwupload_cuda'); + options.push('hwupload_cuda'); if (this.shouldScale(videoStream)) { - options.push(`scale_cuda=${this.getScaling(videoStream)}`); + options.push(`scale_cuda=${this.getScaling(videoStream)}:format=nv12`); } return options; @@ -622,6 +612,8 @@ export class NvencHwDecodeConfig extends NvencSwDecodeConfig { options.push(...this.getToneMapping(videoStream)); if (options.length > 0) { options[options.length - 1] += ':format=nv12'; + } else if (!videoStream.pixelFormat.endsWith('420p')) { + options.push('format=nv12'); } return options; } @@ -631,14 +623,16 @@ export class NvencHwDecodeConfig extends NvencSwDecodeConfig { return []; } - const colors = this.getColors(); + const { matrix, primaries, transfer } = this.getColors(); const tonemapOptions = [ 'desat=0', - `matrix=${colors.matrix}`, - `primaries=${colors.primaries}`, + `matrix=${matrix}`, + `primaries=${primaries}`, 'range=pc', `tonemap=${this.config.tonemap}`, - `transfer=${colors.transfer}`, + 'tonemap_mode=lum', + `transfer=${transfer}`, + 'peak=100', ]; return [`tonemap_cuda=${tonemapOptions.join(':')}`]; @@ -651,29 +645,11 @@ export class NvencHwDecodeConfig extends NvencSwDecodeConfig { getOutputThreadOptions() { return []; } - - getColors() { - return { - primaries: 'bt709', - transfer: 'bt709', - matrix: 'bt709', - }; - } } export class QsvSwDecodeConfig extends BaseHWConfig { getBaseInputOptions() { - if (this.devices.length === 0) { - throw new Error('No QSV device found'); - } - - let qsvString = ''; - const hwDevice = this.getPreferredHardwareDevice(); - if (hwDevice) { - qsvString = `,child_device=${hwDevice}`; - } - - return [`-init_hw_device qsv=hw${qsvString}`, '-filter_hw_device hw']; + return [`-init_hw_device qsv=hw,child_device=${this.device}`, '-filter_hw_device hw']; } getBaseOutputOptions(target: TranscodeTarget, videoStream: VideoStreamInfo, audioStream?: AudioStreamInfo) { @@ -687,9 +663,9 @@ export class QsvSwDecodeConfig extends BaseHWConfig { getFilterOptions(videoStream: VideoStreamInfo) { const options = this.getToneMapping(videoStream); - options.push('format=nv12', 'hwupload=extra_hw_frames=64'); + options.push('hwupload=extra_hw_frames=64'); if (this.shouldScale(videoStream)) { - options.push(`scale_qsv=${this.getScaling(videoStream)}:mode=hq`); + options.push(`scale_qsv=${this.getScaling(videoStream)}:mode=hq:format=nv12`); } return options; } @@ -743,36 +719,30 @@ export class QsvSwDecodeConfig extends BaseHWConfig { export class QsvHwDecodeConfig extends QsvSwDecodeConfig { getBaseInputOptions() { - if (this.devices.length === 0) { - throw new Error('No QSV device found'); - } - - const options = [ + return [ '-hwaccel qsv', '-hwaccel_output_format qsv', '-async_depth 4', '-noautorotate', + `-qsv_device ${this.device}`, ...this.getInputThreadOptions(), ]; - const hwDevice = this.getPreferredHardwareDevice(); - if (hwDevice) { - options.push(`-qsv_device ${hwDevice}`); - } - - return options; } getFilterOptions(videoStream: VideoStreamInfo) { const options = []; - if (this.shouldScale(videoStream) || !this.shouldToneMap(videoStream)) { + const tonemapOptions = this.getToneMapping(videoStream); + if (this.shouldScale(videoStream) || tonemapOptions.length === 0) { let scaling = `scale_qsv=${this.getScaling(videoStream)}:async_depth=4:mode=hq`; - if (!this.shouldToneMap(videoStream)) { + if (tonemapOptions.length === 0) { scaling += ':format=nv12'; } options.push(scaling); } - - options.push(...this.getToneMapping(videoStream)); + options.push(...tonemapOptions); + if (options.length === 0 && !videoStream.pixelFormat.endsWith('420p')) { + options.push('format=nv12'); + } return options; } @@ -781,15 +751,17 @@ export class QsvHwDecodeConfig extends QsvSwDecodeConfig { return []; } - const colors = this.getColors(); + const { matrix, primaries, transfer } = this.getColors(); const tonemapOptions = [ 'desat=0', 'format=nv12', - `matrix=${colors.matrix}`, - `primaries=${colors.primaries}`, + `matrix=${matrix}`, + `primaries=${primaries}`, + `transfer=${transfer}`, 'range=pc', `tonemap=${this.config.tonemap}`, - `transfer=${colors.transfer}`, + 'tonemap_mode=lum', + 'peak=100', ]; return [ @@ -802,35 +774,18 @@ export class QsvHwDecodeConfig extends QsvSwDecodeConfig { getInputThreadOptions() { return [`-threads 1`]; } - - getColors() { - return { - primaries: 'bt709', - transfer: 'bt709', - matrix: 'bt709', - }; - } } export class VaapiSwDecodeConfig extends BaseHWConfig { getBaseInputOptions() { - if (this.devices.length === 0) { - throw new Error('No VAAPI device found'); - } - - let hwDevice = this.getPreferredHardwareDevice(); - if (!hwDevice) { - hwDevice = `/dev/dri/${this.devices[0]}`; - } - - return [`-init_hw_device vaapi=accel:${hwDevice}`, '-filter_hw_device accel']; + return [`-init_hw_device vaapi=accel:${this.device}`, '-filter_hw_device accel']; } getFilterOptions(videoStream: VideoStreamInfo) { const options = this.getToneMapping(videoStream); - options.push('format=nv12', 'hwupload'); + options.push('hwupload=extra_hw_frames=64'); if (this.shouldScale(videoStream)) { - options.push(`scale_vaapi=${this.getScaling(videoStream)}:mode=hq:out_range=pc`); + options.push(`scale_vaapi=${this.getScaling(videoStream)}:mode=hq:out_range=pc:format=nv12`); } return options; @@ -881,35 +836,29 @@ export class VaapiSwDecodeConfig extends BaseHWConfig { export class VaapiHwDecodeConfig extends VaapiSwDecodeConfig { getBaseInputOptions() { - if (this.devices.length === 0) { - throw new Error('No VAAPI device found'); - } - - const options = [ + return [ '-hwaccel vaapi', '-hwaccel_output_format vaapi', '-noautorotate', + `-hwaccel_device ${this.device}`, ...this.getInputThreadOptions(), ]; - const hwDevice = this.getPreferredHardwareDevice(); - if (hwDevice) { - options.push(`-hwaccel_device ${hwDevice}`); - } - - return options; } getFilterOptions(videoStream: VideoStreamInfo) { const options = []; - if (this.shouldScale(videoStream) || !this.shouldToneMap(videoStream)) { + const tonemapOptions = this.getToneMapping(videoStream); + if (this.shouldScale(videoStream) || tonemapOptions.length === 0) { let scaling = `scale_vaapi=${this.getScaling(videoStream)}:mode=hq:out_range=pc`; - if (!this.shouldToneMap(videoStream)) { + if (tonemapOptions.length === 0) { scaling += ':format=nv12'; } options.push(scaling); } - - options.push(...this.getToneMapping(videoStream)); + options.push(...tonemapOptions); + if (options.length === 0 && !videoStream.pixelFormat.endsWith('420p')) { + options.push('format=nv12'); + } return options; } @@ -918,15 +867,17 @@ export class VaapiHwDecodeConfig extends VaapiSwDecodeConfig { return []; } - const colors = this.getColors(); + const { matrix, primaries, transfer } = this.getColors(); const tonemapOptions = [ 'desat=0', 'format=nv12', - `matrix=${colors.matrix}`, - `primaries=${colors.primaries}`, + `matrix=${matrix}`, + `primaries=${primaries}`, + `transfer=${transfer}`, 'range=pc', `tonemap=${this.config.tonemap}`, - `transfer=${colors.transfer}`, + 'tonemap_mode=lum', + 'peak=100', ]; return [ @@ -939,32 +890,14 @@ export class VaapiHwDecodeConfig extends VaapiSwDecodeConfig { getInputThreadOptions() { return [`-threads 1`]; } - - getColors() { - return { - primaries: 'bt709', - transfer: 'bt709', - matrix: 'bt709', - }; - } } export class RkmppSwDecodeConfig extends BaseHWConfig { - constructor( - protected config: SystemConfigFFmpegDto, - devices: string[] = [], - ) { - super(config, devices); - } - eligibleForTwoPass(): boolean { return false; } getBaseInputOptions(): string[] { - if (this.devices.length === 0) { - throw new Error('No RKMPP device found'); - } return []; } @@ -1005,34 +938,33 @@ export class RkmppSwDecodeConfig extends BaseHWConfig { export class RkmppHwDecodeConfig extends RkmppSwDecodeConfig { getBaseInputOptions() { - if (this.devices.length === 0) { - throw new Error('No RKMPP device found'); - } - return ['-hwaccel rkmpp', '-hwaccel_output_format drm_prime', '-afbc rga', '-noautorotate']; } getFilterOptions(videoStream: VideoStreamInfo) { if (this.shouldToneMap(videoStream)) { - const colors = this.getColors(); + const { primaries, transfer, matrix } = this.getColors(); + if (this.interfaces.mali) { + return [ + // use RKMPP for scaling, OpenCL for tone mapping + `scale_rkrga=${this.getScaling(videoStream)}:format=p010:afbc=1:async_depth=4`, + 'hwmap=derive_device=opencl:mode=read', + `tonemap_opencl=format=nv12:r=pc:p=${primaries}:t=${transfer}:m=${matrix}:tonemap=${this.config.tonemap}:desat=0:tonemap_mode=lum:peak=100`, + 'hwmap=derive_device=rkmpp:mode=write:reverse=1', + 'format=drm_prime', + ]; + } return [ - `scale_rkrga=${this.getScaling(videoStream)}:format=p010:afbc=1`, - 'hwmap=derive_device=opencl:mode=read', - `tonemap_opencl=format=nv12:r=pc:p=${colors.primaries}:t=${colors.transfer}:m=${colors.matrix}:tonemap=${this.config.tonemap}:desat=0`, - 'hwmap=derive_device=rkmpp:mode=write:reverse=1', - 'format=drm_prime', + // use RKMPP for scaling, CPU for tone mapping (only works on RK3588, which supports 10-bit output) + `scale_rkrga=${this.getScaling(videoStream)}:format=p010:afbc=1:async_depth=4`, + 'hwdownload', + 'format=p010', + `tonemapx=tonemap=${this.config.tonemap}:desat=0:p=${primaries}:t=${transfer}:m=${matrix}:r=pc:peak=100:format=yuv420p`, + 'hwupload', ]; } else if (this.shouldScale(videoStream)) { - return [`scale_rkrga=${this.getScaling(videoStream)}:format=nv12:afbc=1`]; + return [`scale_rkrga=${this.getScaling(videoStream)}:format=nv12:afbc=1:async_depth=4`]; } return []; } - - getColors() { - return { - primaries: 'bt709', - transfer: 'bt709', - matrix: 'bt709', - }; - } } diff --git a/server/src/utils/mime-types.spec.ts b/server/src/utils/mime-types.spec.ts index 50fe760a04b82..05cd8566c8554 100644 --- a/server/src/utils/mime-types.spec.ts +++ b/server/src/utils/mime-types.spec.ts @@ -92,6 +92,7 @@ describe('mimeTypes', () => { { mimetype: 'video/x-matroska', extension: '.mkv' }, { mimetype: 'video/x-ms-wmv', extension: '.wmv' }, { mimetype: 'video/x-msvideo', extension: '.avi' }, + { mimetype: 'video/mpeg', extension: '.vob' }, ]) { it(`should map ${extension} to ${mimetype}`, () => { expect({ ...mimeTypes.image, ...mimeTypes.video }[extension]).toContain(mimetype); diff --git a/server/src/utils/mime-types.ts b/server/src/utils/mime-types.ts index cbf6e5b489069..165eb44a4f514 100644 --- a/server/src/utils/mime-types.ts +++ b/server/src/utils/mime-types.ts @@ -74,6 +74,7 @@ const video: Record = { '.mpeg': ['video/mpeg'], '.mpg': ['video/mpeg'], '.mts': ['video/mp2t'], + '.vob': ['video/mpeg'], '.webm': ['video/webm'], '.wmv': ['video/x-ms-wmv'], }; diff --git a/server/src/utils/misc.ts b/server/src/utils/misc.ts index 6e435e68a8dc7..6a64923a3bf7b 100644 --- a/server/src/utils/misc.ts +++ b/server/src/utils/misc.ts @@ -15,6 +15,32 @@ import { CLIP_MODEL_INFO, serverVersion } from 'src/constants'; import { ImmichCookie, ImmichHeader, MetadataKey } from 'src/enum'; import { ILoggerRepository } from 'src/interfaces/logger.interface'; +export class ImmichStartupError extends Error {} +export const isStartUpError = (error: unknown): error is ImmichStartupError => error instanceof ImmichStartupError; + +export const getKeyByValue = (object: Record, value: unknown) => + Object.keys(object).find((key) => object[key] === value); + +export const getMethodNames = (instance: any) => { + const ctx = Object.getPrototypeOf(instance); + const methods: string[] = []; + for (const property of Object.getOwnPropertyNames(ctx)) { + const descriptor = Object.getOwnPropertyDescriptor(ctx, property); + if (!descriptor || descriptor.get || descriptor.set) { + continue; + } + + const handler = instance[property]; + if (typeof handler !== 'function') { + continue; + } + + methods.push(property); + } + + return methods; +}; + export const getExternalDomain = (server: SystemConfig['server'], port: number) => server.externalDomain || `http://localhost:${port}`; diff --git a/server/src/utils/replace-template-tags.ts b/server/src/utils/replace-template-tags.ts new file mode 100644 index 0000000000000..70333d7dfff5b --- /dev/null +++ b/server/src/utils/replace-template-tags.ts @@ -0,0 +1,5 @@ +export const replaceTemplateTags = (template: string, variables: Record) => { + return template.replaceAll(/{(.*?)}/g, (_, key) => { + return variables[key] || `{${key}}`; + }); +}; diff --git a/server/src/validation.ts b/server/src/validation.ts index 180d53ed5688b..177e439919b92 100644 --- a/server/src/validation.ts +++ b/server/src/validation.ts @@ -16,9 +16,12 @@ import { IsOptional, IsString, IsUUID, + Validate, ValidateBy, ValidateIf, ValidationOptions, + ValidatorConstraint, + ValidatorConstraintInterface, buildMessage, isDateString, } from 'class-validator'; @@ -156,16 +159,20 @@ export const ValidateBoolean = (options?: BooleanOptions) => { return applyDecorators(...decorators); }; -export function validateCronExpression(expression: string) { - try { - new CronJob(expression, () => {}); - } catch { - return false; +@ValidatorConstraint({ name: 'cronValidator' }) +class CronValidator implements ValidatorConstraintInterface { + validate(expression: string): boolean { + try { + new CronJob(expression, () => {}); + return true; + } catch { + return false; + } } - - return true; } +export const IsCronExpression = () => Validate(CronValidator, { message: 'Invalid cron expression' }); + type IValue = { value: unknown }; export const toEmail = ({ value }: IValue) => (typeof value === 'string' ? value.toLowerCase() : value); diff --git a/server/src/workers/api.ts b/server/src/workers/api.ts index bc8eb22b20589..5196e7595ccea 100644 --- a/server/src/workers/api.ts +++ b/server/src/workers/api.ts @@ -13,8 +13,7 @@ import { WebSocketAdapter } from 'src/middleware/websocket.adapter'; import { ConfigRepository } from 'src/repositories/config.repository'; import { bootstrapTelemetry } from 'src/repositories/telemetry.repository'; import { ApiService } from 'src/services/api.service'; -import { isStartUpError } from 'src/services/storage.service'; -import { useSwagger } from 'src/utils/misc'; +import { isStartUpError, useSwagger } from 'src/utils/misc'; async function bootstrap() { process.title = 'immich-api'; diff --git a/server/src/workers/microservices.ts b/server/src/workers/microservices.ts index bd1e65d6ccf48..0fa056d5d43ea 100644 --- a/server/src/workers/microservices.ts +++ b/server/src/workers/microservices.ts @@ -7,7 +7,7 @@ import { ILoggerRepository } from 'src/interfaces/logger.interface'; import { WebSocketAdapter } from 'src/middleware/websocket.adapter'; import { ConfigRepository } from 'src/repositories/config.repository'; import { bootstrapTelemetry } from 'src/repositories/telemetry.repository'; -import { isStartUpError } from 'src/services/storage.service'; +import { isStartUpError } from 'src/utils/misc'; export async function bootstrap() { const { telemetry } = new ConfigRepository().getEnv(); diff --git a/server/test/fixtures/media.stub.ts b/server/test/fixtures/media.stub.ts index cdcdfd4d5e5d9..de11c23f0a961 100644 --- a/server/test/fixtures/media.stub.ts +++ b/server/test/fixtures/media.stub.ts @@ -17,6 +17,7 @@ const probeStubDefaultVideoStream: VideoStreamInfo[] = [ rotation: 0, isHDR: false, bitrate: 0, + pixelFormat: 'yuv420p', }, ]; @@ -43,6 +44,7 @@ export const probeStub = { rotation: 0, isHDR: false, bitrate: 0, + pixelFormat: 'yuv420p', }, { index: 1, @@ -53,6 +55,7 @@ export const probeStub = { rotation: 0, isHDR: false, bitrate: 0, + pixelFormat: 'yuv420p', }, ], }), @@ -68,6 +71,7 @@ export const probeStub = { rotation: 0, isHDR: false, bitrate: 0, + pixelFormat: 'yuv420p', }, ], }), @@ -83,6 +87,7 @@ export const probeStub = { rotation: 0, isHDR: false, bitrate: 0, + pixelFormat: 'yuv420p', }, ], }), @@ -90,6 +95,13 @@ export const probeStub = { ...probeStubDefault, videoStreams: [{ ...probeStubDefaultVideoStream[0], bitrate: 40_000_000 }], }), + videoStreamMTS: Object.freeze({ + ...probeStubDefault, + format: { + ...probeStubDefaultFormat, + formatName: 'mpegts', + }, + }), videoStreamHDR: Object.freeze({ ...probeStubDefault, videoStreams: [ @@ -102,6 +114,23 @@ export const probeStub = { rotation: 0, isHDR: true, bitrate: 0, + pixelFormat: 'yuv420p10le', + }, + ], + }), + videoStream10Bit: Object.freeze({ + ...probeStubDefault, + videoStreams: [ + { + index: 0, + height: 480, + width: 480, + codecName: 'h264', + frameCount: 100, + rotation: 0, + isHDR: false, + bitrate: 0, + pixelFormat: 'yuv420p10le', }, ], }), @@ -117,6 +146,7 @@ export const probeStub = { rotation: 90, isHDR: false, bitrate: 0, + pixelFormat: 'yuv420p', }, ], }), @@ -132,6 +162,7 @@ export const probeStub = { rotation: 0, isHDR: false, bitrate: 0, + pixelFormat: 'yuv420p', }, ], }), @@ -147,6 +178,7 @@ export const probeStub = { rotation: 0, isHDR: false, bitrate: 0, + pixelFormat: 'yuv420p', }, ], }), diff --git a/server/test/fixtures/shared-link.stub.ts b/server/test/fixtures/shared-link.stub.ts index e446a6180b65a..a8b8e02d742b6 100644 --- a/server/test/fixtures/shared-link.stub.ts +++ b/server/test/fixtures/shared-link.stub.ts @@ -62,10 +62,6 @@ const assetResponse: AssetResponseDto = { updatedAt: today, isFavorite: false, isArchived: false, - smartInfo: { - tags: [], - objects: ['a', 'b', 'c'], - }, duration: '0:00:00.00000', exifInfo: assetInfo, livePhotoVideoId: null, @@ -205,12 +201,6 @@ export const sharedLinkStub = { isArchived: false, isExternal: false, isOffline: false, - smartInfo: { - assetId: 'id_1', - tags: [], - objects: ['a', 'b', 'c'], - asset: null as any, - }, files: [], thumbhash: null, encodedVideoPath: '', diff --git a/server/test/fixtures/system-config.stub.ts b/server/test/fixtures/system-config.stub.ts index 9c6822d52f34d..ed8cc8694ac9e 100644 --- a/server/test/fixtures/system-config.stub.ts +++ b/server/test/fixtures/system-config.stub.ts @@ -54,6 +54,9 @@ export const systemConfigStub = { }, libraryWatchEnabled: { library: { + scan: { + enabled: false, + }, watch: { enabled: true, }, @@ -61,6 +64,9 @@ export const systemConfigStub = { }, libraryWatchDisabled: { library: { + scan: { + enabled: false, + }, watch: { enabled: false, }, @@ -72,6 +78,20 @@ export const systemConfigStub = { enabled: true, cronExpression: '0 0 * * *', }, + watch: { + enabled: false, + }, + }, + }, + libraryScanAndWatch: { + library: { + scan: { + enabled: true, + cronExpression: '0 0 * * *', + }, + watch: { + enabled: true, + }, }, }, backupEnabled: { @@ -88,4 +108,18 @@ export const systemConfigStub = { enabled: false, }, }, + machineLearningEnabled: { + machineLearning: { + enabled: true, + clip: { + modelName: 'ViT-B-16__openai', + enabled: true, + }, + }, + }, + publicUsersDisabled: { + server: { + publicUsers: false, + }, + }, } satisfies Record>; diff --git a/server/test/repositories/asset.repository.mock.ts b/server/test/repositories/asset.repository.mock.ts index 982273ff69b96..928a7956c5f0c 100644 --- a/server/test/repositories/asset.repository.mock.ts +++ b/server/test/repositories/asset.repository.mock.ts @@ -33,7 +33,6 @@ export const newAssetRepositoryMock = (): Mocked => { getTimeBucket: vitest.fn(), getTimeBuckets: vitest.fn(), getAssetIdByCity: vitest.fn(), - getAssetIdByTag: vitest.fn(), getAllForUserFullSync: vitest.fn(), getChangedDeltaSync: vitest.fn(), getDuplicates: vitest.fn(), diff --git a/server/test/repositories/config.repository.mock.ts b/server/test/repositories/config.repository.mock.ts index 55a890fa4a663..df26f7f72565f 100644 --- a/server/test/repositories/config.repository.mock.ts +++ b/server/test/repositories/config.repository.mock.ts @@ -96,5 +96,6 @@ export const mockEnvData = (config: Partial) => ({ ...envData, ...confi export const newConfigRepositoryMock = (): Mocked => { return { getEnv: vitest.fn().mockReturnValue(mockEnvData({})), + getWorker: vitest.fn().mockReturnValue(ImmichWorker.API), }; }; diff --git a/server/test/repositories/cron.repository.mock.ts b/server/test/repositories/cron.repository.mock.ts new file mode 100644 index 0000000000000..2b0784e8ac27e --- /dev/null +++ b/server/test/repositories/cron.repository.mock.ts @@ -0,0 +1,9 @@ +import { ICronRepository } from 'src/interfaces/cron.interface'; +import { Mocked, vitest } from 'vitest'; + +export const newCronRepositoryMock = (): Mocked => { + return { + create: vitest.fn(), + update: vitest.fn(), + }; +}; diff --git a/server/test/repositories/job.repository.mock.ts b/server/test/repositories/job.repository.mock.ts index cfa1826dd8809..e9557af59bae7 100644 --- a/server/test/repositories/job.repository.mock.ts +++ b/server/test/repositories/job.repository.mock.ts @@ -3,9 +3,9 @@ import { Mocked, vitest } from 'vitest'; export const newJobRepositoryMock = (): Mocked => { return { - addHandler: vitest.fn(), - addCronJob: vitest.fn(), - updateCronJob: vitest.fn(), + setup: vitest.fn(), + startWorkers: vitest.fn(), + run: vitest.fn(), setConcurrency: vitest.fn(), empty: vitest.fn(), pause: vitest.fn(), diff --git a/server/test/utils.ts b/server/test/utils.ts index 09c86d1afb242..7f5b75020c7bc 100644 --- a/server/test/utils.ts +++ b/server/test/utils.ts @@ -1,6 +1,7 @@ import { ChildProcessWithoutNullStreams } from 'node:child_process'; import { Writable } from 'node:stream'; import { PNG } from 'pngjs'; +import { ImmichWorker } from 'src/enum'; import { IMetadataRepository } from 'src/interfaces/metadata.interface'; import { BaseService } from 'src/services/base.service'; import { newAccessRepositoryMock } from 'test/repositories/access.repository.mock'; @@ -11,6 +12,7 @@ import { newKeyRepositoryMock } from 'test/repositories/api-key.repository.mock' import { newAssetRepositoryMock } from 'test/repositories/asset.repository.mock'; import { newAuditRepositoryMock } from 'test/repositories/audit.repository.mock'; import { newConfigRepositoryMock } from 'test/repositories/config.repository.mock'; +import { newCronRepositoryMock } from 'test/repositories/cron.repository.mock'; import { newCryptoRepositoryMock } from 'test/repositories/crypto.repository.mock'; import { newDatabaseRepositoryMock } from 'test/repositories/database.repository.mock'; import { newEventRepositoryMock } from 'test/repositories/event.repository.mock'; @@ -44,8 +46,9 @@ import { newViewRepositoryMock } from 'test/repositories/view.repository.mock'; import { Readable } from 'typeorm/platform/PlatformTools'; import { Mocked, vitest } from 'vitest'; -type RepositoryOverrides = { - metadataRepository: IMetadataRepository; +type Overrides = { + worker?: ImmichWorker; + metadataRepository?: IMetadataRepository; }; type BaseServiceArgs = ConstructorParameters; type Constructor> = { @@ -54,12 +57,13 @@ type Constructor> = { export const newTestService = ( Service: Constructor, - overrides?: RepositoryOverrides, + overrides?: Overrides, ) => { const { metadataRepository } = overrides || {}; const accessMock = newAccessRepositoryMock(); const loggerMock = newLoggerRepositoryMock(); + const cronMock = newCronRepositoryMock(); const cryptoMock = newCryptoRepositoryMock(); const activityMock = newActivityRepositoryMock(); const auditMock = newAuditRepositoryMock(); @@ -106,6 +110,7 @@ export const newTestService = ( albumUserMock, assetMock, configMock, + cronMock, cryptoMock, databaseMock, eventMock, @@ -142,6 +147,7 @@ export const newTestService = ( sut, accessMock, loggerMock, + cronMock, cryptoMock, activityMock, auditMock, diff --git a/web/.nvmrc b/web/.nvmrc index 7af24b7ddbde0..1d9b7831ba9d9 100644 --- a/web/.nvmrc +++ b/web/.nvmrc @@ -1 +1 @@ -22.11.0 +22.12.0 diff --git a/web/Dockerfile b/web/Dockerfile index 674fafcda9238..bf6aa5af5c2b7 100644 --- a/web/Dockerfile +++ b/web/Dockerfile @@ -1,4 +1,4 @@ -FROM node:22.10.0-alpine3.20@sha256:fc95a044b87e95507c60c1f8c829e5d98ddf46401034932499db370c494ef0ff +FROM node:22.12.0-alpine3.20@sha256:96cc8323e25c8cc6ddcb8b965e135cfd57846e8003ec0d7bcec16c5fd5f6d39f RUN apk add --no-cache tini USER node diff --git a/web/eslint.config.mjs b/web/eslint.config.mjs index f1ba46355f73a..f3cf9d7f10b72 100644 --- a/web/eslint.config.mjs +++ b/web/eslint.config.mjs @@ -33,6 +33,7 @@ export default [ 'eslint.config.mjs', 'postcss.config.cjs', 'tailwind.config.js', + 'coverage', ], }, ...compat.extends( diff --git a/web/package-lock.json b/web/package-lock.json index 5185a235dbce9..799808fc679e9 100644 --- a/web/package-lock.json +++ b/web/package-lock.json @@ -1,12 +1,12 @@ { "name": "immich-web", - "version": "1.119.1", + "version": "1.123.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "immich-web", - "version": "1.119.1", + "version": "1.123.0", "license": "GNU Affero General Public License version 3", "dependencies": { "@formatjs/icu-messageformat-parser": "^2.7.8", @@ -23,9 +23,9 @@ "justified-layout": "^4.1.0", "lodash-es": "^4.17.21", "luxon": "^3.4.4", - "socket.io-client": "^4.7.4", + "socket.io-client": "~4.7.5", "svelte-gestures": "^5.0.4", - "svelte-i18n": "^4.0.0", + "svelte-i18n": "^4.0.1", "svelte-local-storage-store": "^0.6.4", "svelte-maplibre": "^0.9.13", "thumbhash": "^0.1.1" @@ -35,26 +35,26 @@ "@eslint/js": "^9.8.0", "@faker-js/faker": "^9.0.0", "@socket.io/component-emitter": "^3.1.0", - "@sveltejs/adapter-static": "^3.0.1", - "@sveltejs/enhanced-img": "^0.3.0", - "@sveltejs/kit": "^2.5.18", - "@sveltejs/vite-plugin-svelte": "^3.1.2", + "@sveltejs/adapter-static": "^3.0.5", + "@sveltejs/enhanced-img": "^0.4.0", + "@sveltejs/kit": "^2.12.0", + "@sveltejs/vite-plugin-svelte": "^4.0.0", "@testing-library/jest-dom": "^6.4.2", - "@testing-library/svelte": "^5.2.0", + "@testing-library/svelte": "^5.2.4", "@testing-library/user-event": "^14.5.2", "@types/dom-to-image": "^2.6.7", "@types/justified-layout": "^4.1.4", "@types/lodash-es": "^4.17.12", "@types/luxon": "^3.4.2", - "@typescript-eslint/eslint-plugin": "^8.0.0", - "@typescript-eslint/parser": "^8.0.0", + "@typescript-eslint/eslint-plugin": "^8.15.0", + "@typescript-eslint/parser": "^8.15.0", "@vitest/coverage-v8": "^2.0.5", "autoprefixer": "^10.4.17", "dotenv": "^16.4.5", - "eslint": "^9.0.0", + "eslint": "^9.14.0", "eslint-config-prettier": "^9.1.0", - "eslint-plugin-svelte": "^2.43.0", - "eslint-plugin-unicorn": "^55.0.0", + "eslint-plugin-svelte": "^2.45.1", + "eslint-plugin-unicorn": "^56.0.1", "factory.ts": "^1.4.1", "globals": "^15.9.0", "postcss": "^8.4.35", @@ -63,24 +63,24 @@ "prettier-plugin-sort-json": "^4.0.0", "prettier-plugin-svelte": "^3.2.6", "rollup-plugin-visualizer": "^5.12.0", - "svelte": "^4.2.19", - "svelte-check": "^4.0.0", + "svelte": "^5.1.5", + "svelte-check": "^4.0.9", "tailwindcss": "^3.4.1", "tslib": "^2.6.2", "typescript": "^5.5.0", - "vite": "^5.1.4", + "vite": "^5.4.4", "vitest": "^2.0.5" } }, "../open-api/typescript-sdk": { "name": "@immich/sdk", - "version": "1.119.1", + "version": "1.123.0", "license": "GNU Affero General Public License version 3", "dependencies": { "@oazapfts/runtime": "^1.0.2" }, "devDependencies": { - "@types/node": "^22.8.0", + "@types/node": "^22.10.2", "typescript": "^5.3.3" } }, @@ -138,19 +138,21 @@ } }, "node_modules/@babel/helper-string-parser": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz", - "integrity": "sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", + "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz", - "integrity": "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", + "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } @@ -170,12 +172,13 @@ } }, "node_modules/@babel/parser": { - "version": "7.25.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.3.tgz", - "integrity": "sha512-iLTJKDbJ4hMvFPgQwwsVoxtHyWpKKPBrxkANrSYewDPaPpT5py5yeVkgPIJ7XYXhndxJpaA3PyALSXQ7u8e/Dw==", + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.2.tgz", + "integrity": "sha512-DWMCZH9WA4Maitz2q21SRKHo9QXZxkDsbNZoVD62gusNtNBBqDg9i7uOhASfTfIGNzW+O+r7+jAlM8dwphcJKQ==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/types": "^7.25.2" + "@babel/types": "^7.26.0" }, "bin": { "parser": "bin/babel-parser.js" @@ -197,14 +200,14 @@ } }, "node_modules/@babel/types": { - "version": "7.25.2", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.2.tgz", - "integrity": "sha512-YTnYtra7W9e6/oAZEHj0bJehPRUlLH9/fbpT5LfB0NhQXyALCRkRs3zH9v07IYhkgpqX6Z78FnuccZr/l4Fs4Q==", + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.0.tgz", + "integrity": "sha512-Z/yiTPj+lDVnF7lWeKCIJzaIkI0vYO87dMpZ4bg4TDrFe4XXLFWL1TbXU27gBP3QccxV9mZICCrnjnYlJjXHOA==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-string-parser": "^7.24.8", - "@babel/helper-validator-identifier": "^7.24.7", - "to-fast-properties": "^2.0.0" + "@babel/helper-string-parser": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -633,9 +636,9 @@ } }, "node_modules/@eslint-community/regexpp": { - "version": "4.11.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.0.tgz", - "integrity": "sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A==", + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", + "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", "dev": true, "license": "MIT", "engines": { @@ -668,9 +671,9 @@ } }, "node_modules/@eslint/eslintrc": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.1.0.tgz", - "integrity": "sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.2.0.tgz", + "integrity": "sha512-grOjVNN8P3hjJn/eIETF1wwd12DdnwFDoyceUJLYYdkpbwq3nLi+4fqrTAONx7XDALqlL220wC/RHSC/QTI/0w==", "dev": true, "license": "MIT", "dependencies": { @@ -692,9 +695,9 @@ } }, "node_modules/@eslint/eslintrc/node_modules/eslint-visitor-keys": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz", - "integrity": "sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", + "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", "dev": true, "license": "Apache-2.0", "engines": { @@ -705,15 +708,15 @@ } }, "node_modules/@eslint/eslintrc/node_modules/espree": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-10.1.0.tgz", - "integrity": "sha512-M1M6CpiE6ffoigIOWYO9UDP8TMUw9kqb21tf+08IgDYjCsOvCuDt4jQcZmoYxx+w7zlKw9/N0KXfto+I8/FrXA==", + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.3.0.tgz", + "integrity": "sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==", "dev": true, "license": "BSD-2-Clause", "dependencies": { - "acorn": "^8.12.0", + "acorn": "^8.14.0", "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^4.0.0" + "eslint-visitor-keys": "^4.2.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -736,9 +739,9 @@ } }, "node_modules/@eslint/js": { - "version": "9.13.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.13.0.tgz", - "integrity": "sha512-IFLyoY4d72Z5y/6o/BazFBezupzI/taV8sGumxTAVw3lXG9A6md1Dc34T9s1FoD/an9pJH8RHbAxsaEbBed9lA==", + "version": "9.15.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.15.0.tgz", + "integrity": "sha512-tMTqrY+EzbXmKJR5ToI8lxu7jaN5EdmrBFJpQk5JmSlyLsx6o4t27r883K5xsLuCYCpfKBCGswMSWXsM+jB7lg==", "dev": true, "license": "MIT", "engines": { @@ -756,9 +759,9 @@ } }, "node_modules/@eslint/plugin-kit": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.0.tgz", - "integrity": "sha512-vH9PiIMMwvhCx31Af3HiGzsVNULDbyVkHXwlemn/B0TFj/00ho3y55efXrUZTfQipxoHC5u4xq6zblww1zm1Ig==", + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.3.tgz", + "integrity": "sha512-2b/g5hRmpbb1o4GnTZax9N9m0FXzz9OV42ZzI4rDDMDuHUqigAiQCEWChBWCY4ztAGVRjoWT19v0yMmc5/L5kA==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -769,9 +772,9 @@ } }, "node_modules/@faker-js/faker": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/@faker-js/faker/-/faker-9.0.3.tgz", - "integrity": "sha512-lWrrK4QNlFSU+13PL9jMbMKLJYXDFu3tQfayBsMXX7KL/GiQeqfB1CzHkqD5UHBUtPAuPo6XwGbMFNdVMZObRA==", + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/@faker-js/faker/-/faker-9.2.0.tgz", + "integrity": "sha512-ulqQu4KMr1/sTFIYvqSdegHT8NIkt66tFAkugGnHA+1WAfEn6hMzNR+svjXGFRVLnapxvej67Z/LwchFrnLBUg==", "dev": true, "funding": [ { @@ -786,59 +789,59 @@ } }, "node_modules/@formatjs/ecma402-abstract": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/@formatjs/ecma402-abstract/-/ecma402-abstract-2.2.1.tgz", - "integrity": "sha512-O4ywpkdJybrjFc9zyL8qK5aklleIAi5O4nYhBVJaOFtCkNrnU+lKFeJOFC48zpsZQmR8Aok2V79hGpHnzbmFpg==", + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/@formatjs/ecma402-abstract/-/ecma402-abstract-2.2.3.tgz", + "integrity": "sha512-aElGmleuReGnk2wtYOzYFmNWYoiWWmf1pPPCYg0oiIQSJj0mjc4eUfzUXaSOJ4S8WzI/cLqnCTWjqz904FT2OQ==", "license": "MIT", "dependencies": { - "@formatjs/fast-memoize": "2.2.2", - "@formatjs/intl-localematcher": "0.5.6", + "@formatjs/fast-memoize": "2.2.3", + "@formatjs/intl-localematcher": "0.5.7", "tslib": "2" } }, "node_modules/@formatjs/fast-memoize": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/@formatjs/fast-memoize/-/fast-memoize-2.2.2.tgz", - "integrity": "sha512-mzxZcS0g1pOzwZTslJOBTmLzDXseMLLvnh25ymRilCm8QLMObsQ7x/rj9GNrH0iUhZMlFisVOD6J1n6WQqpKPQ==", + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/@formatjs/fast-memoize/-/fast-memoize-2.2.3.tgz", + "integrity": "sha512-3jeJ+HyOfu8osl3GNSL4vVHUuWFXR03Iz9jjgI7RwjG6ysu/Ymdr0JRCPHfF5yGbTE6JCrd63EpvX1/WybYRbA==", "license": "MIT", "dependencies": { "tslib": "2" } }, "node_modules/@formatjs/icu-messageformat-parser": { - "version": "2.9.1", - "resolved": "https://registry.npmjs.org/@formatjs/icu-messageformat-parser/-/icu-messageformat-parser-2.9.1.tgz", - "integrity": "sha512-7AYk4tjnLi5wBkxst2w7qFj38JLMJoqzj7BhdEl7oTlsWMlqwgx4p9oMmmvpXWTSDGNwOKBRc1SfwMh5MOHeNg==", + "version": "2.9.3", + "resolved": "https://registry.npmjs.org/@formatjs/icu-messageformat-parser/-/icu-messageformat-parser-2.9.3.tgz", + "integrity": "sha512-9L99QsH14XjOCIp4TmbT8wxuffJxGK8uLNO1zNhLtcZaVXvv626N0s4A2qgRCKG3dfYWx9psvGlFmvyVBa6u/w==", "license": "MIT", "dependencies": { - "@formatjs/ecma402-abstract": "2.2.1", - "@formatjs/icu-skeleton-parser": "1.8.5", + "@formatjs/ecma402-abstract": "2.2.3", + "@formatjs/icu-skeleton-parser": "1.8.7", "tslib": "2" } }, "node_modules/@formatjs/icu-skeleton-parser": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@formatjs/icu-skeleton-parser/-/icu-skeleton-parser-1.8.5.tgz", - "integrity": "sha512-zRZ/e3B5qY2+JCLs7puTzWS1Jb+t/K+8Jur/gEZpA2EjWeLDE17nsx8thyo9P48Mno7UmafnPupV2NCJXX17Dg==", + "version": "1.8.7", + "resolved": "https://registry.npmjs.org/@formatjs/icu-skeleton-parser/-/icu-skeleton-parser-1.8.7.tgz", + "integrity": "sha512-fI+6SmS2g7h3srfAKSWa5dwreU5zNEfon2uFo99OToiLF6yxGE+WikvFSbsvMAYkscucvVmTYNlWlaDPp0n5HA==", "license": "MIT", "dependencies": { - "@formatjs/ecma402-abstract": "2.2.1", + "@formatjs/ecma402-abstract": "2.2.3", "tslib": "2" } }, "node_modules/@formatjs/intl-localematcher": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/@formatjs/intl-localematcher/-/intl-localematcher-0.5.6.tgz", - "integrity": "sha512-roz1+Ba5e23AHX6KUAWmLEyTRZegM5YDuxuvkHCyK3RJddf/UXB2f+s7pOMm9ktfPGla0g+mQXOn5vsuYirnaA==", + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/@formatjs/intl-localematcher/-/intl-localematcher-0.5.7.tgz", + "integrity": "sha512-GGFtfHGQVFe/niOZp24Kal5b2i36eE2bNL0xi9Sg/yd0TR8aLjcteApZdHmismP5QQax1cMnZM9yWySUUjJteA==", "license": "MIT", "dependencies": { "tslib": "2" } }, "node_modules/@humanfs/core": { - "version": "0.19.0", - "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.0.tgz", - "integrity": "sha512-2cbWIHbZVEweE853g8jymffCA+NCMiuqeECeBBLm8dg2oFdjuGJhgN4UAbI+6v0CKbbhvtXA4qV8YR5Ji86nmw==", + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", + "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", "dev": true, "license": "Apache-2.0", "engines": { @@ -846,13 +849,13 @@ } }, "node_modules/@humanfs/node": { - "version": "0.16.5", - "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.5.tgz", - "integrity": "sha512-KSPA4umqSG4LHYRodq31VDwKAvaTF4xmVlzM8Aeh4PlU1JQ3IG0wiA8C25d3RQ9nJyM3mBHyI53K06VVL/oFFg==", + "version": "0.16.6", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.6.tgz", + "integrity": "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@humanfs/core": "^0.19.0", + "@humanfs/core": "^0.19.1", "@humanwhocodes/retry": "^0.3.0" }, "engines": { @@ -1635,30 +1638,30 @@ } }, "node_modules/@photo-sphere-viewer/core": { - "version": "5.11.0", - "resolved": "https://registry.npmjs.org/@photo-sphere-viewer/core/-/core-5.11.0.tgz", - "integrity": "sha512-SjEVBBMNj5v3aSLglpTd88q+cyDw0Lke7mK3kN3p+KsQK8X0OG7GsbtI7sGj81zSCbHmV3c0DgUaXMv+xdGFaw==", + "version": "5.11.1", + "resolved": "https://registry.npmjs.org/@photo-sphere-viewer/core/-/core-5.11.1.tgz", + "integrity": "sha512-bxWnoQGYjXfmHGee4OSkoYLZmdgqvJWMn7wmpK0V0Vf46Fqu+TJ4Yt8+dY2PgpM89HoKzNr15Dzt6jqOfjkFxQ==", "license": "MIT", "dependencies": { "three": "^0.169.0" } }, "node_modules/@photo-sphere-viewer/equirectangular-video-adapter": { - "version": "5.11.0", - "resolved": "https://registry.npmjs.org/@photo-sphere-viewer/equirectangular-video-adapter/-/equirectangular-video-adapter-5.11.0.tgz", - "integrity": "sha512-xs5+vT5jYjBtEsguuJe6CVJNGxtwopb3+Zs4z/VJg0oNm2mTZF2TQu2RkSlRJZTE6a/IfZ7Zv1fJcN3Yiv7AVg==", + "version": "5.11.1", + "resolved": "https://registry.npmjs.org/@photo-sphere-viewer/equirectangular-video-adapter/-/equirectangular-video-adapter-5.11.1.tgz", + "integrity": "sha512-fkWuVeArtZSWd0z282/J82YSc+oernQaE/cpo0soVaStaNbS1V35iSnPlaBKw40qX6tucJWYw15QwM8xgPC2IQ==", "license": "MIT", "peerDependencies": { - "@photo-sphere-viewer/core": "5.11.0" + "@photo-sphere-viewer/core": "5.11.1" } }, "node_modules/@photo-sphere-viewer/video-plugin": { - "version": "5.11.0", - "resolved": "https://registry.npmjs.org/@photo-sphere-viewer/video-plugin/-/video-plugin-5.11.0.tgz", - "integrity": "sha512-6ApAKvwDRgVZOk4N/3SJ14IFpQ6V0QDDtknXxLI5JqU1yAvBcyb7goa5XDbyTWXYUaPKH06Fz+8UruWRzCsBXw==", + "version": "5.11.1", + "resolved": "https://registry.npmjs.org/@photo-sphere-viewer/video-plugin/-/video-plugin-5.11.1.tgz", + "integrity": "sha512-02spWwv9bjyI6inNdZsczX/qdMICVV9B8lWX/J4iNBaiUCHqPKmk8CeZbRyC/Uh3OHSusSJHyW0FDEOf6qjjww==", "license": "MIT", "peerDependencies": { - "@photo-sphere-viewer/core": "5.11.0" + "@photo-sphere-viewer/core": "5.11.1" } }, "node_modules/@pkgjs/parseargs": { @@ -1706,9 +1709,9 @@ "dev": true }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.21.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.21.1.tgz", - "integrity": "sha512-2thheikVEuU7ZxFXubPDOtspKn1x0yqaYQwvALVtEcvFhMifPADBrgRPyHV0TF3b+9BgvgjgagVyvA/UqPZHmg==", + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.28.1.tgz", + "integrity": "sha512-2aZp8AES04KI2dy3Ss6/MDjXbwBzj+i0GqKtWXgw2/Ma6E4jJvujryO6gJAghIRVz7Vwr9Gtl/8na3nDUKpraQ==", "cpu": [ "arm" ], @@ -1720,9 +1723,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.21.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.21.1.tgz", - "integrity": "sha512-t1lLYn4V9WgnIFHXy1d2Di/7gyzBWS8G5pQSXdZqfrdCGTwi1VasRMSS81DTYb+avDs/Zz4A6dzERki5oRYz1g==", + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.28.1.tgz", + "integrity": "sha512-EbkK285O+1YMrg57xVA+Dp0tDBRB93/BZKph9XhMjezf6F4TpYjaUSuPt5J0fZXlSag0LmZAsTmdGGqPp4pQFA==", "cpu": [ "arm64" ], @@ -1734,9 +1737,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.21.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.21.1.tgz", - "integrity": "sha512-AH/wNWSEEHvs6t4iJ3RANxW5ZCK3fUnmf0gyMxWCesY1AlUj8jY7GC+rQE4wd3gwmZ9XDOpL0kcFnCjtN7FXlA==", + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.28.1.tgz", + "integrity": "sha512-prduvrMKU6NzMq6nxzQw445zXgaDBbMQvmKSJaxpaZ5R1QDM8w+eGxo6Y/jhT/cLoCvnZI42oEqf9KQNYz1fqQ==", "cpu": [ "arm64" ], @@ -1748,9 +1751,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.21.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.21.1.tgz", - "integrity": "sha512-dO0BIz/+5ZdkLZrVgQrDdW7m2RkrLwYTh2YMFG9IpBtlC1x1NPNSXkfczhZieOlOLEqgXOFH3wYHB7PmBtf+Bg==", + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.28.1.tgz", + "integrity": "sha512-WsvbOunsUk0wccO/TV4o7IKgloJ942hVFK1CLatwv6TJspcCZb9umQkPdvB7FihmdxgaKR5JyxDjWpCOp4uZlQ==", "cpu": [ "x64" ], @@ -1761,10 +1764,38 @@ "darwin" ] }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.28.1.tgz", + "integrity": "sha512-HTDPdY1caUcU4qK23FeeGxCdJF64cKkqajU0iBnTVxS8F7H/7BewvYoG+va1KPSL63kQ1PGNyiwKOfReavzvNA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.28.1.tgz", + "integrity": "sha512-m/uYasxkUevcFTeRSM9TeLyPe2QDuqtjkeoTpP9SW0XxUWfcYrGDMkO/m2tTw+4NMAF9P2fU3Mw4ahNvo7QmsQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.21.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.21.1.tgz", - "integrity": "sha512-sWWgdQ1fq+XKrlda8PsMCfut8caFwZBmhYeoehJ05FdI0YZXk6ZyUjWLrIgbR/VgiGycrFKMMgp7eJ69HOF2pQ==", + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.28.1.tgz", + "integrity": "sha512-QAg11ZIt6mcmzpNE6JZBpKfJaKkqTm1A9+y9O+frdZJEuhQxiugM05gnCWiANHj4RmbgeVJpTdmKRmH/a+0QbA==", "cpu": [ "arm" ], @@ -1776,9 +1807,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.21.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.21.1.tgz", - "integrity": "sha512-9OIiSuj5EsYQlmwhmFRA0LRO0dRRjdCVZA3hnmZe1rEwRk11Jy3ECGGq3a7RrVEZ0/pCsYWx8jG3IvcrJ6RCew==", + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.28.1.tgz", + "integrity": "sha512-dRP9PEBfolq1dmMcFqbEPSd9VlRuVWEGSmbxVEfiq2cs2jlZAl0YNxFzAQS2OrQmsLBLAATDMb3Z6MFv5vOcXg==", "cpu": [ "arm" ], @@ -1790,9 +1821,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.21.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.21.1.tgz", - "integrity": "sha512-0kuAkRK4MeIUbzQYu63NrJmfoUVicajoRAL1bpwdYIYRcs57iyIV9NLcuyDyDXE2GiZCL4uhKSYAnyWpjZkWow==", + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.28.1.tgz", + "integrity": "sha512-uGr8khxO+CKT4XU8ZUH1TTEUtlktK6Kgtv0+6bIFSeiSlnGJHG1tSFSjm41uQ9sAO/5ULx9mWOz70jYLyv1QkA==", "cpu": [ "arm64" ], @@ -1804,9 +1835,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.21.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.21.1.tgz", - "integrity": "sha512-/6dYC9fZtfEY0vozpc5bx1RP4VrtEOhNQGb0HwvYNwXD1BBbwQ5cKIbUVVU7G2d5WRE90NfB922elN8ASXAJEA==", + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.28.1.tgz", + "integrity": "sha512-QF54q8MYGAqMLrX2t7tNpi01nvq5RI59UBNx+3+37zoKX5KViPo/gk2QLhsuqok05sSCRluj0D00LzCwBikb0A==", "cpu": [ "arm64" ], @@ -1817,10 +1848,24 @@ "linux" ] }, + "node_modules/@rollup/rollup-linux-loongarch64-gnu": { + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.28.1.tgz", + "integrity": "sha512-vPul4uodvWvLhRco2w0GcyZcdyBfpfDRgNKU+p35AWEbJ/HPs1tOUrkSueVbBS0RQHAf/A+nNtDpvw95PeVKOA==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.21.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.21.1.tgz", - "integrity": "sha512-ltUWy+sHeAh3YZ91NUsV4Xg3uBXAlscQe8ZOXRCVAKLsivGuJsrkawYPUEyCV3DYa9urgJugMLn8Z3Z/6CeyRQ==", + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.28.1.tgz", + "integrity": "sha512-pTnTdBuC2+pt1Rmm2SV7JWRqzhYpEILML4PKODqLz+C7Ou2apEV52h19CR7es+u04KlqplggmN9sqZlekg3R1A==", "cpu": [ "ppc64" ], @@ -1832,9 +1877,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.21.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.21.1.tgz", - "integrity": "sha512-BggMndzI7Tlv4/abrgLwa/dxNEMn2gC61DCLrTzw8LkpSKel4o+O+gtjbnkevZ18SKkeN3ihRGPuBxjaetWzWg==", + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.28.1.tgz", + "integrity": "sha512-vWXy1Nfg7TPBSuAncfInmAI/WZDd5vOklyLJDdIRKABcZWojNDY0NJwruY2AcnCLnRJKSaBgf/GiJfauu8cQZA==", "cpu": [ "riscv64" ], @@ -1846,9 +1891,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.21.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.21.1.tgz", - "integrity": "sha512-z/9rtlGd/OMv+gb1mNSjElasMf9yXusAxnRDrBaYB+eS1shFm6/4/xDH1SAISO5729fFKUkJ88TkGPRUh8WSAA==", + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.28.1.tgz", + "integrity": "sha512-/yqC2Y53oZjb0yz8PVuGOQQNOTwxcizudunl/tFs1aLvObTclTwZ0JhXF2XcPT/zuaymemCDSuuUPXJJyqeDOg==", "cpu": [ "s390x" ], @@ -1860,9 +1905,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.21.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.21.1.tgz", - "integrity": "sha512-kXQVcWqDcDKw0S2E0TmhlTLlUgAmMVqPrJZR+KpH/1ZaZhLSl23GZpQVmawBQGVhyP5WXIsIQ/zqbDBBYmxm5w==", + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.28.1.tgz", + "integrity": "sha512-fzgeABz7rrAlKYB0y2kSEiURrI0691CSL0+KXwKwhxvj92VULEDQLpBYLHpF49MSiPG4sq5CK3qHMnb9tlCjBw==", "cpu": [ "x64" ], @@ -1874,9 +1919,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.21.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.21.1.tgz", - "integrity": "sha512-CbFv/WMQsSdl+bpX6rVbzR4kAjSSBuDgCqb1l4J68UYsQNalz5wOqLGYj4ZI0thGpyX5kc+LLZ9CL+kpqDovZA==", + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.28.1.tgz", + "integrity": "sha512-xQTDVzSGiMlSshpJCtudbWyRfLaNiVPXt1WgdWTwWz9n0U12cI2ZVtWe/Jgwyv/6wjL7b66uu61Vg0POWVfz4g==", "cpu": [ "x64" ], @@ -1888,9 +1933,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.21.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.21.1.tgz", - "integrity": "sha512-3Q3brDgA86gHXWHklrwdREKIrIbxC0ZgU8lwpj0eEKGBQH+31uPqr0P2v11pn0tSIxHvcdOWxa4j+YvLNx1i6g==", + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.28.1.tgz", + "integrity": "sha512-wSXmDRVupJstFP7elGMgv+2HqXelQhuNf+IS4V+nUpNVi/GUiBgDmfwD0UGN3pcAnWsgKG3I52wMOBnk1VHr/A==", "cpu": [ "arm64" ], @@ -1902,9 +1947,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.21.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.21.1.tgz", - "integrity": "sha512-tNg+jJcKR3Uwe4L0/wY3Ro0H+u3nrb04+tcq1GSYzBEmKLeOQF2emk1whxlzNqb6MMrQ2JOcQEpuuiPLyRcSIw==", + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.28.1.tgz", + "integrity": "sha512-ZkyTJ/9vkgrE/Rk9vhMXhf8l9D+eAhbAVbsGsXKy2ohmJaWg0LPQLnIxRdRp/bKyr8tXuPlXhIoGlEB5XpJnGA==", "cpu": [ "ia32" ], @@ -1916,9 +1961,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.21.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.21.1.tgz", - "integrity": "sha512-xGiIH95H1zU7naUyTKEyOA/I0aexNMUdO9qRv0bLKN3qu25bBdrxZHqA3PTJ24YNN/GdMzG4xkDcd/GvjuhfLg==", + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.28.1.tgz", + "integrity": "sha512-ZvK2jBafvttJjoIdKm/Q/Bh7IJ1Ose9IBOwpOXcOvW3ikGTQGmKDgxTC6oCAzW6PynbkKP8+um1du81XJHZ0JA==", "cpu": [ "x64" ], @@ -1945,25 +1990,26 @@ } }, "node_modules/@sveltejs/enhanced-img": { - "version": "0.3.10", - "resolved": "https://registry.npmjs.org/@sveltejs/enhanced-img/-/enhanced-img-0.3.10.tgz", - "integrity": "sha512-1JxjthN6yb1md3rSFbHRDBi/Jj2R9EjE06vh9zbWgYxm5d4UUphTzNICJTis8bkIDQilbAokrkaQtfRpKSE7qg==", + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@sveltejs/enhanced-img/-/enhanced-img-0.4.1.tgz", + "integrity": "sha512-Z0xwQWM7tfdlNYuaFsAsbjEosEZb961yP7hlvZBLlh3+Rv4tI3BboD6bUkmInj+cC66p/5rybgvEtxX5LILSuw==", "dev": true, "license": "MIT", "dependencies": { "magic-string": "^0.30.5", "svelte-parse-markup": "^0.1.5", - "vite-imagetools": "^7.0.1" + "vite-imagetools": "^7.0.1", + "zimmerframe": "^1.1.2" }, "peerDependencies": { - "svelte": "^4.0.0 || ^5.0.0-next.0", + "svelte": "^5.0.0", "vite": ">= 5.0.0" } }, "node_modules/@sveltejs/kit": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/@sveltejs/kit/-/kit-2.7.3.tgz", - "integrity": "sha512-Vx7nq5MJ86I8qXYsVidC5PX6xm+uxt8DydvOdmJoyOK7LvGP18OFEG359yY+aa51t6pENvqZAMqAREQQx1OI2Q==", + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/@sveltejs/kit/-/kit-2.13.0.tgz", + "integrity": "sha512-6t6ne00vZx/TjD6s0Jvwt8wRLKBwbSAN1nhlOzcLUSTYX1hTp4eCBaTPB5Yz/lu+tYcvz4YPEEuPv3yfsNp2gw==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -1971,7 +2017,7 @@ "@types/cookie": "^0.6.0", "cookie": "^0.6.0", "devalue": "^5.1.0", - "esm-env": "^1.0.0", + "esm-env": "^1.2.1", "import-meta-resolve": "^4.1.0", "kleur": "^4.1.5", "magic-string": "^0.30.5", @@ -1988,49 +2034,48 @@ "node": ">=18.13" }, "peerDependencies": { - "@sveltejs/vite-plugin-svelte": "^3.0.0 || ^4.0.0-next.1", + "@sveltejs/vite-plugin-svelte": "^3.0.0 || ^4.0.0-next.1 || ^5.0.0", "svelte": "^4.0.0 || ^5.0.0-next.0", - "vite": "^5.0.3" + "vite": "^5.0.3 || ^6.0.0" } }, "node_modules/@sveltejs/vite-plugin-svelte": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte/-/vite-plugin-svelte-3.1.2.tgz", - "integrity": "sha512-Txsm1tJvtiYeLUVRNqxZGKR/mI+CzuIQuc2gn+YCs9rMTowpNZ2Nqt53JdL8KF9bLhAf2ruR/dr9eZCwdTriRA==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte/-/vite-plugin-svelte-4.0.1.tgz", + "integrity": "sha512-prXoAE/GleD2C4pKgHa9vkdjpzdYwCSw/kmjw6adIyu0vk5YKCfqIztkLg10m+kOYnzZu3bb0NaPTxlWre2a9Q==", "dev": true, "license": "MIT", "dependencies": { - "@sveltejs/vite-plugin-svelte-inspector": "^2.1.0", - "debug": "^4.3.4", + "@sveltejs/vite-plugin-svelte-inspector": "^3.0.0-next.0||^3.0.0", + "debug": "^4.3.7", "deepmerge": "^4.3.1", "kleur": "^4.1.5", - "magic-string": "^0.30.10", - "svelte-hmr": "^0.16.0", - "vitefu": "^0.2.5" + "magic-string": "^0.30.12", + "vitefu": "^1.0.3" }, "engines": { - "node": "^18.0.0 || >=20" + "node": "^18.0.0 || ^20.0.0 || >=22" }, "peerDependencies": { - "svelte": "^4.0.0 || ^5.0.0-next.0", + "svelte": "^5.0.0-next.96 || ^5.0.0", "vite": "^5.0.0" } }, "node_modules/@sveltejs/vite-plugin-svelte-inspector": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte-inspector/-/vite-plugin-svelte-inspector-2.1.0.tgz", - "integrity": "sha512-9QX28IymvBlSCqsCll5t0kQVxipsfhFFL+L2t3nTWfXnddYwxBuAEtTtlaVQpRz9c37BhJjltSeY4AJSC03SSg==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte-inspector/-/vite-plugin-svelte-inspector-3.0.1.tgz", + "integrity": "sha512-2CKypmj1sM4GE7HjllT7UKmo4Q6L5xFRd7VMGEWhYnZ+wc6AUVU01IBd7yUi6WnFndEwWoMNOd6e8UjoN0nbvQ==", "dev": true, "license": "MIT", "dependencies": { - "debug": "^4.3.4" + "debug": "^4.3.7" }, "engines": { - "node": "^18.0.0 || >=20" + "node": "^18.0.0 || ^20.0.0 || >=22" }, "peerDependencies": { - "@sveltejs/vite-plugin-svelte": "^3.0.0", - "svelte": "^4.0.0 || ^5.0.0-next.0", + "@sveltejs/vite-plugin-svelte": "^4.0.0-next.0||^4.0.0", + "svelte": "^5.0.0-next.96 || ^5.0.0", "vite": "^5.0.0" } }, @@ -2125,9 +2170,9 @@ } }, "node_modules/@testing-library/jest-dom": { - "version": "6.6.2", - "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-6.6.2.tgz", - "integrity": "sha512-P6GJD4yqc9jZLbe98j/EkyQDTPgqftohZF5FBkHY5BUERZmcf4HeO2k0XaefEg329ux2p21i1A1DmyQ1kKw2Jw==", + "version": "6.6.3", + "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-6.6.3.tgz", + "integrity": "sha512-IteBhl4XqYNkM54f4ejhLRJiZNqcSCoXUOG2CPK7qbD322KjQozM4kHQOfkG2oln9b9HTYqs+Sae8vBATubxxA==", "dev": true, "license": "MIT", "dependencies": { @@ -2230,7 +2275,6 @@ "resolved": "https://registry.npmjs.org/@testing-library/svelte/-/svelte-5.2.4.tgz", "integrity": "sha512-EFdy73+lULQgMJ1WolAymrxWWrPv9DWyDuDFKKlUip2PA/EXuHptzfYOKWljccFWDKhhGOu3dqNmoc2f/h/Ecg==", "dev": true, - "license": "MIT", "dependencies": { "@testing-library/dom": "^10.0.0" }, @@ -2283,9 +2327,10 @@ "dev": true }, "node_modules/@types/estree": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", - "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==" + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", + "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", + "license": "MIT" }, "node_modules/@types/geojson": { "version": "7946.0.14", @@ -2385,17 +2430,17 @@ } }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.11.0.tgz", - "integrity": "sha512-KhGn2LjW1PJT2A/GfDpiyOfS4a8xHQv2myUagTM5+zsormOmBlYsnQ6pobJ8XxJmh6hnHwa2Mbe3fPrDJoDhbA==", + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.15.0.tgz", + "integrity": "sha512-+zkm9AR1Ds9uLWN3fkoeXgFppaQ+uEVtfOV62dDmsy9QCNqlRHWNEck4yarvRNrvRcHQLGfqBNui3cimoz8XAg==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.11.0", - "@typescript-eslint/type-utils": "8.11.0", - "@typescript-eslint/utils": "8.11.0", - "@typescript-eslint/visitor-keys": "8.11.0", + "@typescript-eslint/scope-manager": "8.15.0", + "@typescript-eslint/type-utils": "8.15.0", + "@typescript-eslint/utils": "8.15.0", + "@typescript-eslint/visitor-keys": "8.15.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", @@ -2419,16 +2464,16 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.11.0.tgz", - "integrity": "sha512-lmt73NeHdy1Q/2ul295Qy3uninSqi6wQI18XwSpm8w0ZbQXUpjCAWP1Vlv/obudoBiIjJVjlztjQ+d/Md98Yxg==", + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.15.0.tgz", + "integrity": "sha512-7n59qFpghG4uazrF9qtGKBZXn7Oz4sOMm8dwNWDQY96Xlm2oX67eipqcblDj+oY1lLCbf1oltMZFpUso66Kl1A==", "dev": true, "license": "BSD-2-Clause", "dependencies": { - "@typescript-eslint/scope-manager": "8.11.0", - "@typescript-eslint/types": "8.11.0", - "@typescript-eslint/typescript-estree": "8.11.0", - "@typescript-eslint/visitor-keys": "8.11.0", + "@typescript-eslint/scope-manager": "8.15.0", + "@typescript-eslint/types": "8.15.0", + "@typescript-eslint/typescript-estree": "8.15.0", + "@typescript-eslint/visitor-keys": "8.15.0", "debug": "^4.3.4" }, "engines": { @@ -2448,14 +2493,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.11.0.tgz", - "integrity": "sha512-Uholz7tWhXmA4r6epo+vaeV7yjdKy5QFCERMjs1kMVsLRKIrSdM6o21W2He9ftp5PP6aWOVpD5zvrvuHZC0bMQ==", + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.15.0.tgz", + "integrity": "sha512-QRGy8ADi4J7ii95xz4UoiymmmMd/zuy9azCaamnZ3FM8T5fZcex8UfJcjkiEZjJSztKfEBe3dZ5T/5RHAmw2mA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.11.0", - "@typescript-eslint/visitor-keys": "8.11.0" + "@typescript-eslint/types": "8.15.0", + "@typescript-eslint/visitor-keys": "8.15.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2466,14 +2511,14 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.11.0.tgz", - "integrity": "sha512-ItiMfJS6pQU0NIKAaybBKkuVzo6IdnAhPFZA/2Mba/uBjuPQPet/8+zh5GtLHwmuFRShZx+8lhIs7/QeDHflOg==", + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.15.0.tgz", + "integrity": "sha512-UU6uwXDoI3JGSXmcdnP5d8Fffa2KayOhUUqr/AiBnG1Gl7+7ut/oyagVeSkh7bxQ0zSXV9ptRh/4N15nkCqnpw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "8.11.0", - "@typescript-eslint/utils": "8.11.0", + "@typescript-eslint/typescript-estree": "8.15.0", + "@typescript-eslint/utils": "8.15.0", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" }, @@ -2484,6 +2529,9 @@ "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0" + }, "peerDependenciesMeta": { "typescript": { "optional": true @@ -2491,9 +2539,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.11.0.tgz", - "integrity": "sha512-tn6sNMHf6EBAYMvmPUaKaVeYvhUsrE6x+bXQTxjQRp360h1giATU0WvgeEys1spbvb5R+VpNOZ+XJmjD8wOUHw==", + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.15.0.tgz", + "integrity": "sha512-n3Gt8Y/KyJNe0S3yDCD2RVKrHBC4gTUcLTebVBXacPy091E6tNspFLKRXlk3hwT4G55nfr1n2AdFqi/XMxzmPQ==", "dev": true, "license": "MIT", "engines": { @@ -2505,14 +2553,14 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.11.0.tgz", - "integrity": "sha512-yHC3s1z1RCHoCz5t06gf7jH24rr3vns08XXhfEqzYpd6Hll3z/3g23JRi0jM8A47UFKNc3u/y5KIMx8Ynbjohg==", + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.15.0.tgz", + "integrity": "sha512-1eMp2JgNec/niZsR7ioFBlsh/Fk0oJbhaqO0jRyQBMgkz7RrFfkqF9lYYmBoGBaSiLnu8TAPQTwoTUiSTUW9dg==", "dev": true, "license": "BSD-2-Clause", "dependencies": { - "@typescript-eslint/types": "8.11.0", - "@typescript-eslint/visitor-keys": "8.11.0", + "@typescript-eslint/types": "8.15.0", + "@typescript-eslint/visitor-keys": "8.15.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -2560,16 +2608,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.11.0.tgz", - "integrity": "sha512-CYiX6WZcbXNJV7UNB4PLDIBtSdRmRI/nb0FMyqHPTQD1rMjA0foPLaPUV39C/MxkTd/QKSeX+Gb34PPsDVC35g==", + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.15.0.tgz", + "integrity": "sha512-k82RI9yGhr0QM3Dnq+egEpz9qB6Un+WLYhmoNcvl8ltMEededhh7otBVVIDDsEEttauwdY/hQoSsOv13lxrFzQ==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.11.0", - "@typescript-eslint/types": "8.11.0", - "@typescript-eslint/typescript-estree": "8.11.0" + "@typescript-eslint/scope-manager": "8.15.0", + "@typescript-eslint/types": "8.15.0", + "@typescript-eslint/typescript-estree": "8.15.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2580,17 +2628,22 @@ }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.11.0.tgz", - "integrity": "sha512-EaewX6lxSjRJnc+99+dqzTeoDZUfyrA52d2/HRrkI830kgovWsmIiTfmr0NZorzqic7ga+1bS60lRBUgR3n/Bw==", + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.15.0.tgz", + "integrity": "sha512-h8vYOulWec9LhpwfAdZf2bjr8xIp0KNKnpgqSz0qqYYKAW/QZKw3ktRndbiAtUz4acH4QLQavwZBYCc0wulA/Q==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.11.0", - "eslint-visitor-keys": "^3.4.3" + "@typescript-eslint/types": "8.15.0", + "eslint-visitor-keys": "^4.2.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2600,23 +2653,36 @@ "url": "https://opencollective.com/typescript-eslint" } }, + "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", + "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, "node_modules/@vitest/coverage-v8": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-2.1.3.tgz", - "integrity": "sha512-2OJ3c7UPoFSmBZwqD2VEkUw6A/tzPF0LmW0ZZhhB8PFxuc+9IBG/FaSM+RLEenc7ljzFvGN+G0nGQoZnh7sy2A==", + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-2.1.5.tgz", + "integrity": "sha512-/RoopB7XGW7UEkUndRXF87A9CwkoZAJW01pj8/3pgmDVsjMH2IKy6H1A38po9tmUlwhSyYs0az82rbKd9Yaynw==", "dev": true, "license": "MIT", "dependencies": { "@ampproject/remapping": "^2.3.0", "@bcoe/v8-coverage": "^0.2.3", - "debug": "^4.3.6", + "debug": "^4.3.7", "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.11", - "magicast": "^0.3.4", - "std-env": "^3.7.0", + "magic-string": "^0.30.12", + "magicast": "^0.3.5", + "std-env": "^3.8.0", "test-exclude": "^7.0.1", "tinyrainbow": "^1.2.0" }, @@ -2624,8 +2690,8 @@ "url": "https://opencollective.com/vitest" }, "peerDependencies": { - "@vitest/browser": "2.1.3", - "vitest": "2.1.3" + "@vitest/browser": "2.1.5", + "vitest": "2.1.5" }, "peerDependenciesMeta": { "@vitest/browser": { @@ -2634,15 +2700,15 @@ } }, "node_modules/@vitest/expect": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-2.1.3.tgz", - "integrity": "sha512-SNBoPubeCJhZ48agjXruCI57DvxcsivVDdWz+SSsmjTT4QN/DfHk3zB/xKsJqMs26bLZ/pNRLnCf0j679i0uWQ==", + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-2.1.5.tgz", + "integrity": "sha512-nZSBTW1XIdpZvEJyoP/Sy8fUg0b8od7ZpGDkTUcfJ7wz/VoZAFzFfLyxVxGFhUjJzhYqSbIpfMtl/+k/dpWa3Q==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/spy": "2.1.3", - "@vitest/utils": "2.1.3", - "chai": "^5.1.1", + "@vitest/spy": "2.1.5", + "@vitest/utils": "2.1.5", + "chai": "^5.1.2", "tinyrainbow": "^1.2.0" }, "funding": { @@ -2650,22 +2716,21 @@ } }, "node_modules/@vitest/mocker": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-2.1.3.tgz", - "integrity": "sha512-eSpdY/eJDuOvuTA3ASzCjdithHa+GIF1L4PqtEELl6Qa3XafdMLBpBlZCIUCX2J+Q6sNmjmxtosAG62fK4BlqQ==", + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-2.1.5.tgz", + "integrity": "sha512-XYW6l3UuBmitWqSUXTNXcVBUCRytDogBsWuNXQijc00dtnU/9OqpXWp4OJroVrad/gLIomAq9aW8yWDBtMthhQ==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/spy": "2.1.3", + "@vitest/spy": "2.1.5", "estree-walker": "^3.0.3", - "magic-string": "^0.30.11" + "magic-string": "^0.30.12" }, "funding": { "url": "https://opencollective.com/vitest" }, "peerDependencies": { - "@vitest/spy": "2.1.3", - "msw": "^2.3.5", + "msw": "^2.4.9", "vite": "^5.0.0" }, "peerDependenciesMeta": { @@ -2678,9 +2743,9 @@ } }, "node_modules/@vitest/pretty-format": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-2.1.3.tgz", - "integrity": "sha512-XH1XdtoLZCpqV59KRbPrIhFCOO0hErxrQCMcvnQete3Vibb9UeIOX02uFPfVn3Z9ZXsq78etlfyhnkmIZSzIwQ==", + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-2.1.5.tgz", + "integrity": "sha512-4ZOwtk2bqG5Y6xRGHcveZVr+6txkH7M2e+nPFd6guSoN638v/1XQ0K06eOpi0ptVU/2tW/pIU4IoPotY/GZ9fw==", "dev": true, "license": "MIT", "dependencies": { @@ -2691,13 +2756,13 @@ } }, "node_modules/@vitest/runner": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-2.1.3.tgz", - "integrity": "sha512-JGzpWqmFJ4fq5ZKHtVO3Xuy1iF2rHGV4d/pdzgkYHm1+gOzNZtqjvyiaDGJytRyMU54qkxpNzCx+PErzJ1/JqQ==", + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-2.1.5.tgz", + "integrity": "sha512-pKHKy3uaUdh7X6p1pxOkgkVAFW7r2I818vHDthYLvUyjRfkKOU6P45PztOch4DZarWQne+VOaIMwA/erSSpB9g==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/utils": "2.1.3", + "@vitest/utils": "2.1.5", "pathe": "^1.1.2" }, "funding": { @@ -2705,14 +2770,14 @@ } }, "node_modules/@vitest/snapshot": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-2.1.3.tgz", - "integrity": "sha512-qWC2mWc7VAXmjAkEKxrScWHWFyCQx/cmiZtuGqMi+WwqQJ2iURsVY4ZfAK6dVo6K2smKRU6l3BPwqEBvhnpQGg==", + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-2.1.5.tgz", + "integrity": "sha512-zmYw47mhfdfnYbuhkQvkkzYroXUumrwWDGlMjpdUr4jBd3HZiV2w7CQHj+z7AAS4VOtWxI4Zt4bWt4/sKcoIjg==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "2.1.3", - "magic-string": "^0.30.11", + "@vitest/pretty-format": "2.1.5", + "magic-string": "^0.30.12", "pathe": "^1.1.2" }, "funding": { @@ -2720,27 +2785,27 @@ } }, "node_modules/@vitest/spy": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-2.1.3.tgz", - "integrity": "sha512-Nb2UzbcUswzeSP7JksMDaqsI43Sj5+Kry6ry6jQJT4b5gAK+NS9NED6mDb8FlMRCX8m5guaHCDZmqYMMWRy5nQ==", + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-2.1.5.tgz", + "integrity": "sha512-aWZF3P0r3w6DiYTVskOYuhBc7EMc3jvn1TkBg8ttylFFRqNN2XGD7V5a4aQdk6QiUzZQ4klNBSpCLJgWNdIiNw==", "dev": true, "license": "MIT", "dependencies": { - "tinyspy": "^3.0.0" + "tinyspy": "^3.0.2" }, "funding": { "url": "https://opencollective.com/vitest" } }, "node_modules/@vitest/utils": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-2.1.3.tgz", - "integrity": "sha512-xpiVfDSg1RrYT0tX6czgerkpcKFmFOF/gCr30+Mve5V2kewCy4Prn1/NDMSRwaSmT7PRaOF83wu+bEtsY1wrvA==", + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-2.1.5.tgz", + "integrity": "sha512-yfj6Yrp0Vesw2cwJbP+cl04OC+IHFsuQsrsJBL9pyGeQXE56v1UAOQco+SR55Vf1nQzfV0QJg1Qum7AaWUwwYg==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "2.1.3", - "loupe": "^3.1.1", + "@vitest/pretty-format": "2.1.5", + "loupe": "^3.1.2", "tinyrainbow": "^1.2.0" }, "funding": { @@ -2797,6 +2862,15 @@ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, + "node_modules/acorn-typescript": { + "version": "1.4.13", + "resolved": "https://registry.npmjs.org/acorn-typescript/-/acorn-typescript-1.4.13.tgz", + "integrity": "sha512-xsc9Xv0xlVfwp2o7sQ+GCQ1PgbkdcpWdTzrwXxO3xDMTAywVS3oXVOcOHuRjAPkS4P9b+yc/qNF15460v+jp4Q==", + "license": "MIT", + "peerDependencies": { + "acorn": ">=8.9.0" + } + }, "node_modules/agent-base": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.0.tgz", @@ -2883,6 +2957,7 @@ "version": "5.3.0", "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", + "dev": true, "dependencies": { "dequal": "^2.0.3" } @@ -2960,11 +3035,12 @@ } }, "node_modules/axobject-query": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.0.0.tgz", - "integrity": "sha512-+60uv1hiVFhHZeO+Lz0RYzsVHy5Wr1ayX0mwda9KPDVLNJgZ1T9Ny7VmFbLDzxsH0D87I86vgj3gFrjTJUYznw==", - "dependencies": { - "dequal": "^2.0.3" + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz", + "integrity": "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==", + "license": "Apache-2.0", + "engines": { + "node": ">= 0.4" } }, "node_modules/balanced-match": { @@ -2993,21 +3069,22 @@ } }, "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dev": true, + "license": "MIT", "dependencies": { - "fill-range": "^7.0.1" + "fill-range": "^7.1.1" }, "engines": { "node": ">=8" } }, "node_modules/browserslist": { - "version": "4.23.3", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.3.tgz", - "integrity": "sha512-btwCFJVjI4YWDNfau8RhZ+B1Q/VLoUITrm3RlP6y1tYGWIOa+InuYiRGXUBXo8nA1qKmHMyLB/iVQg5TT4eFoA==", + "version": "4.24.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.3.tgz", + "integrity": "sha512-1CPmv8iobE2fyRMV97dAcMVegvvWKxmq94hkLiAkUGwKVTyDLw33K+ZxiFrREKmmps4rIw6grcCFCnTMSZ/YiA==", "dev": true, "funding": [ { @@ -3025,10 +3102,10 @@ ], "license": "MIT", "dependencies": { - "caniuse-lite": "^1.0.30001646", - "electron-to-chromium": "^1.5.4", - "node-releases": "^2.0.18", - "update-browserslist-db": "^1.1.0" + "caniuse-lite": "^1.0.30001688", + "electron-to-chromium": "^1.5.73", + "node-releases": "^2.0.19", + "update-browserslist-db": "^1.1.1" }, "bin": { "browserslist": "cli.js" @@ -3101,9 +3178,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001651", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001651.tgz", - "integrity": "sha512-9Cf+Xv1jJNe1xPZLGuUXLNkE1BoDkqRqYyFJ9TDYSqhduqA4hu4oR9HluGoWYQC/aj8WHjsGVV+bwkh0+tegRg==", + "version": "1.0.30001689", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001689.tgz", + "integrity": "sha512-CmeR2VBycfa+5/jOfnp/NpWPGd06nf1XYiefUvhXFfZE4GkRc9jv+eGPS4nT558WS/8lYCzV8SlANCIPvbWP1g==", "dev": true, "funding": [ { @@ -3122,9 +3199,9 @@ "license": "CC-BY-4.0" }, "node_modules/chai": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/chai/-/chai-5.1.1.tgz", - "integrity": "sha512-pT1ZgP8rPNqUgieVaEY+ryQr6Q4HXNg8Ei9UnLUrjN4IA7dvQC5JB+/kxVcPNDHyBcc/26CXPkbNzq3qwrOEKA==", + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/chai/-/chai-5.1.2.tgz", + "integrity": "sha512-aGtmf24DW6MLHHG5gCx4zaI3uBq3KRtxeVs0DjFH6Z0rDNbsvTxFASFvdj79pxjxZ8/5u3PIiN3IwEIQkiiuPw==", "dev": true, "license": "MIT", "dependencies": { @@ -3163,16 +3240,11 @@ } }, "node_modules/chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], + "license": "MIT", "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", @@ -3185,6 +3257,9 @@ "engines": { "node": ">= 8.10.0" }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, "optionalDependencies": { "fsevents": "~2.3.2" } @@ -3271,18 +3346,6 @@ "node": ">=6" } }, - "node_modules/code-red": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/code-red/-/code-red-1.0.4.tgz", - "integrity": "sha512-7qJWqItLA8/VPVlKJlFXU+NBlo/qyfs39aJcuMT/2ere32ZqvF5OSxgdM5xOfJJ7O429gg2HM47y8v9P+9wrNw==", - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.4.15", - "@types/estree": "^1.0.1", - "acorn": "^8.10.0", - "estree-walker": "^3.0.3", - "periscopic": "^3.1.0" - } - }, "node_modules/color": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz", @@ -3378,12 +3441,13 @@ } }, "node_modules/core-js-compat": { - "version": "3.37.1", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.37.1.tgz", - "integrity": "sha512-9TNiImhKvQqSUkOvk/mMRZzOANTiEVC7WaBNhHcKM7x+/5E1l5NvsysR19zuDQScE8k+kfQXWRN3AtS/eOSHpg==", + "version": "3.39.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.39.0.tgz", + "integrity": "sha512-VgEUx3VwlExr5no0tXlBt+silBvhTryPwCXRI2Id1PN8WTKu7MreethvddqOubrYxkFdv/RnYrqlv1sFNAUelw==", "dev": true, + "license": "MIT", "dependencies": { - "browserslist": "^4.23.0" + "browserslist": "^4.24.2" }, "funding": { "type": "opencollective", @@ -3391,10 +3455,11 @@ } }, "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "dev": true, + "license": "MIT", "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -3404,18 +3469,6 @@ "node": ">= 8" } }, - "node_modules/css-tree": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz", - "integrity": "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==", - "dependencies": { - "mdn-data": "2.0.30", - "source-map-js": "^1.0.1" - }, - "engines": { - "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" - } - }, "node_modules/css.escape": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz", @@ -3505,11 +3558,12 @@ } }, "node_modules/debug": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", - "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "license": "MIT", "dependencies": { - "ms": "2.1.2" + "ms": "^2.1.3" }, "engines": { "node": ">=6.0" @@ -3643,9 +3697,9 @@ "dev": true }, "node_modules/electron-to-chromium": { - "version": "1.5.6", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.6.tgz", - "integrity": "sha512-jwXWsM5RPf6j9dPYzaorcBSUg6AiqocPEyMpkchkvntaH9HGfOOMZwxMJjDY/XEs3T5dM7uyH1VhRMkqUU9qVw==", + "version": "1.5.74", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.74.tgz", + "integrity": "sha512-ck3//9RC+6oss/1Bh9tiAVFy5vfSKbRHAFh7Z3/eTRkEqJeWgymloShB17Vg3Z4nmDNp35vAd1BZ6CMW4Wt6Iw==", "dev": true, "license": "ISC" }, @@ -3656,22 +3710,23 @@ "dev": true }, "node_modules/engine.io-client": { - "version": "6.6.1", - "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.6.1.tgz", - "integrity": "sha512-aYuoak7I+R83M/BBPIOs2to51BmFIpC1wZe6zZzMrT2llVsHy5cvcmdsJgP2Qz6smHu+sD9oexiSUAVd8OfBPw==", + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.5.4.tgz", + "integrity": "sha512-GeZeeRjpD2qf49cZQ0Wvh/8NJNfeXkXXcoGh+F77oEAgo9gUHwT1fCRxSNU+YEEaysOJTnsFHmM5oAcPy4ntvQ==", "license": "MIT", "dependencies": { "@socket.io/component-emitter": "~3.1.0", "debug": "~4.3.1", "engine.io-parser": "~5.2.1", "ws": "~8.17.1", - "xmlhttprequest-ssl": "~2.1.1" + "xmlhttprequest-ssl": "~2.0.0" } }, "node_modules/engine.io-parser": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.1.tgz", - "integrity": "sha512-9JktcM3u18nU9N2Lz3bWeBgxVgOKpw7yhRaoxQA3FUDZzzw+9WlA6p4G4u0RixNkg14fH7EfEc/RhpurtiROTQ==", + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.3.tgz", + "integrity": "sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==", + "license": "MIT", "engines": { "node": ">=10.0.0" } @@ -3699,6 +3754,13 @@ "is-arrayish": "^0.2.1" } }, + "node_modules/es-module-lexer": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.5.4.tgz", + "integrity": "sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==", + "dev": true, + "license": "MIT" + }, "node_modules/es5-ext": { "version": "0.10.64", "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.64.tgz", @@ -3787,9 +3849,9 @@ } }, "node_modules/escalade": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", - "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", "dev": true, "license": "MIT", "engines": { @@ -3806,22 +3868,22 @@ } }, "node_modules/eslint": { - "version": "9.13.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.13.0.tgz", - "integrity": "sha512-EYZK6SX6zjFHST/HRytOdA/zE72Cq/bfw45LSyuwrdvcclb/gqV8RRQxywOBEWO2+WDpva6UZa4CcDeJKzUCFA==", + "version": "9.14.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.14.0.tgz", + "integrity": "sha512-c2FHsVBr87lnUtjP4Yhvk4yEhKrQavGafRA/Se1ouse8PfbfC/Qh9Mxa00yWsZRlqeUB9raXip0aiiUZkgnr9g==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.11.0", + "@eslint-community/regexpp": "^4.12.1", "@eslint/config-array": "^0.18.0", "@eslint/core": "^0.7.0", "@eslint/eslintrc": "^3.1.0", - "@eslint/js": "9.13.0", + "@eslint/js": "9.14.0", "@eslint/plugin-kit": "^0.2.0", - "@humanfs/node": "^0.16.5", + "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", - "@humanwhocodes/retry": "^0.3.1", + "@humanwhocodes/retry": "^0.4.0", "@types/estree": "^1.0.6", "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", @@ -3829,9 +3891,9 @@ "cross-spawn": "^7.0.2", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^8.1.0", - "eslint-visitor-keys": "^4.1.0", - "espree": "^10.2.0", + "eslint-scope": "^8.2.0", + "eslint-visitor-keys": "^4.2.0", + "espree": "^10.3.0", "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", @@ -3930,19 +3992,19 @@ } }, "node_modules/eslint-plugin-unicorn": { - "version": "55.0.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-unicorn/-/eslint-plugin-unicorn-55.0.0.tgz", - "integrity": "sha512-n3AKiVpY2/uDcGrS3+QsYDkjPfaOrNrsfQxU9nt5nitd9KuvVXrfAvgCO9DYPSfap+Gqjw9EOrXIsBp5tlHZjA==", + "version": "56.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-unicorn/-/eslint-plugin-unicorn-56.0.1.tgz", + "integrity": "sha512-FwVV0Uwf8XPfVnKSGpMg7NtlZh0G0gBarCaFcMUOoqPxXryxdYxTRRv4kH6B9TFCVIrjRXG+emcxIk2ayZilog==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-validator-identifier": "^7.24.5", + "@babel/helper-validator-identifier": "^7.24.7", "@eslint-community/eslint-utils": "^4.4.0", "ci-info": "^4.0.0", "clean-regexp": "^1.0.0", - "core-js-compat": "^3.37.0", - "esquery": "^1.5.0", - "globals": "^15.7.0", + "core-js-compat": "^3.38.1", + "esquery": "^1.6.0", + "globals": "^15.9.0", "indent-string": "^4.0.0", "is-builtin-module": "^3.2.1", "jsesc": "^3.0.2", @@ -3950,7 +4012,7 @@ "read-pkg-up": "^7.0.1", "regexp-tree": "^0.1.27", "regjsparser": "^0.10.0", - "semver": "^7.6.1", + "semver": "^7.6.3", "strip-indent": "^3.0.0" }, "engines": { @@ -4004,12 +4066,29 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/eslint/node_modules/@types/estree": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", - "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", + "node_modules/eslint/node_modules/@eslint/js": { + "version": "9.14.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.14.0.tgz", + "integrity": "sha512-pFoEtFWCPyDOl+C6Ift+wC7Ro89otjigCf5vcuWqWgqNSQbRrpjSvdeE6ofLz4dHmyxD5f7gIdGT4+p36L6Twg==", "dev": true, - "license": "MIT" + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/eslint/node_modules/@humanwhocodes/retry": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.1.tgz", + "integrity": "sha512-c7hNEllBlenFTHBky65mhq8WD2kbN9Q6gk0bTk8lSBvc554jpXSkST1iePudpt7+A/AQvuHs9EMqjHDXMY1lrA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } }, "node_modules/eslint/node_modules/ansi-styles": { "version": "4.3.0", @@ -4149,10 +4228,10 @@ } }, "node_modules/esm-env": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/esm-env/-/esm-env-1.0.0.tgz", - "integrity": "sha512-Cf6VksWPsTuW01vU9Mk/3vRue91Zevka5SjyNf3nEpokFRuqt/KjUQoGAwq9qMmhpLTHmXzSIrFRw8zxWzmFBA==", - "dev": true + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/esm-env/-/esm-env-1.2.1.tgz", + "integrity": "sha512-U9JedYYjCnadUlXk7e1Kr+aENQhtUaoaV9+gZm1T8LC/YBAPJx3NSPIAurFOC0U5vrdSevnUJS2/wUVxGwPhng==", + "license": "MIT" }, "node_modules/esniff": { "version": "2.0.1", @@ -4186,10 +4265,11 @@ } }, "node_modules/esquery": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", - "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "estraverse": "^5.1.0" }, @@ -4197,6 +4277,16 @@ "node": ">=0.10" } }, + "node_modules/esrap": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/esrap/-/esrap-1.2.2.tgz", + "integrity": "sha512-F2pSJklxx1BlQIQgooczXCPHmcWpn6EsP5oo73LQfonG9fIlIENQ8vMmfGXeojP9MrkzUNAfyU5vdFlR9shHAw==", + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.4.15", + "@types/estree": "^1.0.1" + } + }, "node_modules/esrecurse": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", @@ -4222,6 +4312,7 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "dev": true, "dependencies": { "@types/estree": "^1.0.0" } @@ -4244,6 +4335,16 @@ "es5-ext": "~0.10.14" } }, + "node_modules/expect-type": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.1.0.tgz", + "integrity": "sha512-bFi65yM+xZgk+u/KRIpekdSYkTB5W1pEf0Lt8Q8Msh7b+eQ7LXVtIB1Bkm4fvclDEL1b2CZkMhv2mOeF8tMdkA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/ext": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/ext/-/ext-1.7.0.tgz", @@ -4352,10 +4453,11 @@ } }, "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dev": true, + "license": "MIT", "dependencies": { "to-regex-range": "^5.0.1" }, @@ -4445,12 +4547,6 @@ "url": "https://github.com/sponsors/rawify" } }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true - }, "node_modules/fsevents": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", @@ -4509,6 +4605,27 @@ "resolved": "https://registry.npmjs.org/gl-matrix/-/gl-matrix-3.4.3.tgz", "integrity": "sha512-wcCp8vu8FT22BnvKVPjXa/ICBWRq/zjFfdofZy1WSpQZpphblv12/bOQLBC1rMM7SGOFS9ltVmKOHil5+Ml7gA==" }, + "node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "dev": true, + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/glob-parent": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", @@ -4521,6 +4638,32 @@ "node": ">=10.13.0" } }, + "node_modules/glob/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/glob/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/global-prefix": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz", @@ -4546,9 +4689,9 @@ } }, "node_modules/globals": { - "version": "15.11.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-15.11.0.tgz", - "integrity": "sha512-yeyNSjdbyVaWurlwCpcA6XNBrHTMIeDdj0/hnvX/OLJ9ekOXYbLsLinH/MucQyGvNnXhidTdNhTtJaffL2sMfw==", + "version": "15.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-15.12.0.tgz", + "integrity": "sha512-1+gLErljJFhbOVyaetcwJiJ4+eLe45S2E7P5UiZ9xGfeq3ATQf5DOv9G7MH3gGbKQLkzmNh2DxfZwLdw+j6oTQ==", "dev": true, "license": "MIT", "engines": { @@ -4786,22 +4929,6 @@ "node": ">=8" } }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "dev": true, - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, "node_modules/ini": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", @@ -4816,14 +4943,14 @@ } }, "node_modules/intl-messageformat": { - "version": "10.7.3", - "resolved": "https://registry.npmjs.org/intl-messageformat/-/intl-messageformat-10.7.3.tgz", - "integrity": "sha512-AAo/3oyh7ROfPhDuh7DxTTydh97OC+lv7h1Eq5LuHWuLsUMKOhtzTYuyXlUReuwZ9vANDHo4CS1bGRrn7TZRtg==", + "version": "10.7.6", + "resolved": "https://registry.npmjs.org/intl-messageformat/-/intl-messageformat-10.7.6.tgz", + "integrity": "sha512-IsMU/hqyy3FJwNJ0hxDfY2heJ7MteSuFvcnCebxRp67di4Fhx1gKKE+qS0bBwUF8yXkX9SsPUhLeX/B6h5SKUA==", "license": "BSD-3-Clause", "dependencies": { - "@formatjs/ecma402-abstract": "2.2.1", - "@formatjs/fast-memoize": "2.2.2", - "@formatjs/icu-messageformat-parser": "2.9.1", + "@formatjs/ecma402-abstract": "2.2.3", + "@formatjs/fast-memoize": "2.2.3", + "@formatjs/icu-messageformat-parser": "2.9.3", "tslib": "2" } }, @@ -4930,6 +5057,7 @@ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.12.0" } @@ -4959,11 +5087,12 @@ "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==" }, "node_modules/is-reference": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-3.0.2.tgz", - "integrity": "sha512-v3rht/LgVcsdZa3O2Nqs+NMowLOxeOm7Ay9+/ARQ2F+qEoANRcqrjAZKGN0v8ymUetZGgkp26LTnGT7H0Qo9Pg==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-3.0.3.tgz", + "integrity": "sha512-ixkJoqQvAP88E6wLydLGGqCJsrFUnqoH6HnaczB8XmDH1oaWU+xxdptvikTgaEhtZ53Ky6YXiBuUI2WXLMCwjw==", + "license": "MIT", "dependencies": { - "@types/estree": "*" + "@types/estree": "^1.0.6" } }, "node_modules/is-wsl": { @@ -5078,10 +5207,11 @@ } }, "node_modules/jiti": { - "version": "1.21.0", - "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.0.tgz", - "integrity": "sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==", + "version": "1.21.6", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.6.tgz", + "integrity": "sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==", "dev": true, + "license": "MIT", "bin": { "jiti": "bin/jiti.js" } @@ -5329,22 +5459,23 @@ } }, "node_modules/magic-string": { - "version": "0.30.11", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.11.tgz", - "integrity": "sha512-+Wri9p0QHMy+545hKww7YAu5NyzF8iomPL/RQazugQ9+Ez4Ic3mERMd8ZTX5rfK944j+560ZJi8iAwgak1Ac7A==", + "version": "0.30.12", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.12.tgz", + "integrity": "sha512-Ea8I3sQMVXr8JhN4z+H/d8zwo+tYDgHE9+5G4Wnrwhs0gaK9fXTKx0Tw5Xwsd/bCPTTZNRAdpyzvoeORe9LYpw==", "license": "MIT", "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0" } }, "node_modules/magicast": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/magicast/-/magicast-0.3.4.tgz", - "integrity": "sha512-TyDF/Pn36bBji9rWKHlZe+PZb6Mx5V8IHCSxk7X4aljM4e/vyDvZZYwHewdVaqiA0nb3ghfHU/6AUpDxWoER2Q==", + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/magicast/-/magicast-0.3.5.tgz", + "integrity": "sha512-L0WhttDl+2BOsybvEOLK7fW3UA0OQ0IQ2d6Zl2x/a6vVRs3bAY0ECOSHHeL5jD+SbOpOCUEi0y1DgHEn9Qn1AQ==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/parser": "^7.24.4", - "@babel/types": "^7.24.0", + "@babel/parser": "^7.25.4", + "@babel/types": "^7.25.4", "source-map-js": "^1.2.0" } }, @@ -5475,11 +5606,6 @@ "url": "https://github.com/maplibre/maplibre-gl-js?sponsor=1" } }, - "node_modules/mdn-data": { - "version": "2.0.30", - "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz", - "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==" - }, "node_modules/memoizee": { "version": "0.4.17", "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.17.tgz", @@ -5508,12 +5634,13 @@ } }, "node_modules/micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "dev": true, + "license": "MIT", "dependencies": { - "braces": "^3.0.2", + "braces": "^3.0.3", "picomatch": "^2.3.1" }, "engines": { @@ -5601,9 +5728,10 @@ } }, "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" }, "node_modules/murmurhash-js": { "version": "1.0.0", @@ -5622,9 +5750,9 @@ } }, "node_modules/nanoid": { - "version": "3.3.7", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", - "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "version": "3.3.8", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz", + "integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==", "dev": true, "funding": [ { @@ -5632,6 +5760,7 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "bin": { "nanoid": "bin/nanoid.cjs" }, @@ -5656,9 +5785,9 @@ "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==" }, "node_modules/node-releases": { - "version": "2.0.18", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz", - "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==", + "version": "2.0.19", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", + "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==", "dev": true, "license": "MIT" }, @@ -5727,15 +5856,6 @@ "node": ">= 6" } }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, - "dependencies": { - "wrappy": "1" - } - }, "node_modules/open": { "version": "8.4.2", "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", @@ -5868,15 +5988,6 @@ "node": ">=8" } }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", @@ -5943,20 +6054,10 @@ "pbf": "bin/pbf" } }, - "node_modules/periscopic": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/periscopic/-/periscopic-3.1.0.tgz", - "integrity": "sha512-vKiQ8RRtkl9P+r/+oefh25C3fhybptkHKCZSPlcXiJux2tJF55GnEj3BVn4A5gKfq9NWWXXrxkHBwVPUfH0opw==", - "dependencies": { - "@types/estree": "^1.0.0", - "estree-walker": "^3.0.0", - "is-reference": "^3.0.0" - } - }, "node_modules/picocolors": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.0.tgz", - "integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", "dev": true, "license": "ISC" }, @@ -6009,9 +6110,9 @@ } }, "node_modules/postcss": { - "version": "8.4.47", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.47.tgz", - "integrity": "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==", + "version": "8.4.49", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.49.tgz", + "integrity": "sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==", "dev": true, "funding": [ { @@ -6030,7 +6131,7 @@ "license": "MIT", "dependencies": { "nanoid": "^3.3.7", - "picocolors": "^1.1.0", + "picocolors": "^1.1.1", "source-map-js": "^1.2.1" }, "engines": { @@ -6103,20 +6204,27 @@ } }, "node_modules/postcss-nested": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.0.1.tgz", - "integrity": "sha512-mEp4xPMi5bSWiMbsgoPfcP74lsWLHkQbZc3sY+jWYd65CUwXrUaTp0fmNpa01ZcETKlIgUdFN/MpS2xZtqL9dQ==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz", + "integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==", "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", "dependencies": { - "postcss-selector-parser": "^6.0.11" + "postcss-selector-parser": "^6.1.1" }, "engines": { "node": ">=12.0" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, "peerDependencies": { "postcss": "^8.2.14" } @@ -6165,9 +6273,9 @@ } }, "node_modules/postcss-selector-parser": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.0.tgz", - "integrity": "sha512-UMz42UD0UY0EApS0ZL9o1XnLhSTtvvvLe5Dc2H2O56fvRZi+KulDyf5ctDhhtYJBGKStV2FL1fy6253cmLgqVQ==", + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", + "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", "dev": true, "license": "MIT", "dependencies": { @@ -6244,9 +6352,9 @@ } }, "node_modules/prettier-plugin-svelte": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/prettier-plugin-svelte/-/prettier-plugin-svelte-3.2.7.tgz", - "integrity": "sha512-/Dswx/ea0lV34If1eDcG3nulQ63YNr5KPDfMsjbdtpSWOxKKJ7nAc2qlVuYwEvCr4raIuredNoR7K4JCkmTGaQ==", + "version": "3.2.8", + "resolved": "https://registry.npmjs.org/prettier-plugin-svelte/-/prettier-plugin-svelte-3.2.8.tgz", + "integrity": "sha512-PAHmmU5cGZdnhW4mWhmvxuG2PVbbHIxUuPOdUKvfE+d4Qt2d29iU5VWrPdsaW5YqVEE0nqhlvN4eoKmVMpIF3Q==", "dev": true, "license": "MIT", "peerDependencies": { @@ -6531,10 +6639,11 @@ "peer": true }, "node_modules/resolve": { - "version": "1.22.6", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.6.tgz", - "integrity": "sha512-njhxM7mV12JfufShqGy3Rz8j11RPdLy4xi15UurGJeoHLfJpVXKdh3ueuOqbYUcDZnffr6X739JBo5LzyahEsw==", + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", "dev": true, + "license": "MIT", "dependencies": { "is-core-module": "^2.13.0", "path-parse": "^1.0.7", @@ -6566,13 +6675,13 @@ } }, "node_modules/rollup": { - "version": "4.21.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.21.1.tgz", - "integrity": "sha512-ZnYyKvscThhgd3M5+Qt3pmhO4jIRR5RGzaSovB6Q7rGNrK5cUncrtLmcTTJVSdcKXyZjW8X8MB0JMSuH9bcAJg==", + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.28.1.tgz", + "integrity": "sha512-61fXYl/qNVinKmGSTHAZ6Yy8I3YIJC/r2m9feHo6SwVAVcLT5MPwOUFe7EuURA/4m0NR8lXG4BBXuo/IZEsjMg==", "dev": true, "license": "MIT", "dependencies": { - "@types/estree": "1.0.5" + "@types/estree": "1.0.6" }, "bin": { "rollup": "dist/bin/rollup" @@ -6582,22 +6691,25 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.21.1", - "@rollup/rollup-android-arm64": "4.21.1", - "@rollup/rollup-darwin-arm64": "4.21.1", - "@rollup/rollup-darwin-x64": "4.21.1", - "@rollup/rollup-linux-arm-gnueabihf": "4.21.1", - "@rollup/rollup-linux-arm-musleabihf": "4.21.1", - "@rollup/rollup-linux-arm64-gnu": "4.21.1", - "@rollup/rollup-linux-arm64-musl": "4.21.1", - "@rollup/rollup-linux-powerpc64le-gnu": "4.21.1", - "@rollup/rollup-linux-riscv64-gnu": "4.21.1", - "@rollup/rollup-linux-s390x-gnu": "4.21.1", - "@rollup/rollup-linux-x64-gnu": "4.21.1", - "@rollup/rollup-linux-x64-musl": "4.21.1", - "@rollup/rollup-win32-arm64-msvc": "4.21.1", - "@rollup/rollup-win32-ia32-msvc": "4.21.1", - "@rollup/rollup-win32-x64-msvc": "4.21.1", + "@rollup/rollup-android-arm-eabi": "4.28.1", + "@rollup/rollup-android-arm64": "4.28.1", + "@rollup/rollup-darwin-arm64": "4.28.1", + "@rollup/rollup-darwin-x64": "4.28.1", + "@rollup/rollup-freebsd-arm64": "4.28.1", + "@rollup/rollup-freebsd-x64": "4.28.1", + "@rollup/rollup-linux-arm-gnueabihf": "4.28.1", + "@rollup/rollup-linux-arm-musleabihf": "4.28.1", + "@rollup/rollup-linux-arm64-gnu": "4.28.1", + "@rollup/rollup-linux-arm64-musl": "4.28.1", + "@rollup/rollup-linux-loongarch64-gnu": "4.28.1", + "@rollup/rollup-linux-powerpc64le-gnu": "4.28.1", + "@rollup/rollup-linux-riscv64-gnu": "4.28.1", + "@rollup/rollup-linux-s390x-gnu": "4.28.1", + "@rollup/rollup-linux-x64-gnu": "4.28.1", + "@rollup/rollup-linux-x64-musl": "4.28.1", + "@rollup/rollup-win32-arm64-msvc": "4.28.1", + "@rollup/rollup-win32-ia32-msvc": "4.28.1", + "@rollup/rollup-win32-x64-msvc": "4.28.1", "fsevents": "~2.3.2" } }, @@ -6860,14 +6972,14 @@ } }, "node_modules/socket.io-client": { - "version": "4.8.1", - "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.8.1.tgz", - "integrity": "sha512-hJVXfu3E28NmzGk8o1sHhN3om52tRvwYeidbj7xKy2eIIse5IoKX3USlS6Tqt3BHAtflLIkCQBkzVrEEfWUyYQ==", + "version": "4.7.5", + "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.7.5.tgz", + "integrity": "sha512-sJ/tqHOCe7Z50JCBCXrsY3I2k03iOiUe+tj1OmKeD2lXPiGH/RUCdTZFoqVyN7l1MnpIzPrGtLcijffmeouNlQ==", "license": "MIT", "dependencies": { "@socket.io/component-emitter": "~3.1.0", "debug": "~4.3.2", - "engine.io-client": "~6.6.1", + "engine.io-client": "~6.5.2", "socket.io-parser": "~4.2.4" }, "engines": { @@ -6930,6 +7042,7 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" @@ -7018,10 +7131,11 @@ "dev": true }, "node_modules/std-env": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.7.0.tgz", - "integrity": "sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg==", - "dev": true + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.8.0.tgz", + "integrity": "sha512-Bc3YwwCB+OzldMxOXJIIvC6cPRWr/LxOp48CdQTOkPyk/t4JWWJbrilwBd7RJzKV8QW7tJkcgAmeuLLJugl5/w==", + "dev": true, + "license": "MIT" }, "node_modules/string-width": { "version": "4.2.3", @@ -7102,14 +7216,15 @@ } }, "node_modules/sucrase": { - "version": "3.34.0", - "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.34.0.tgz", - "integrity": "sha512-70/LQEZ07TEcxiU2dz51FKaE6hCTWC6vr7FOk3Gr0U60C3shtAN+H+BFr9XlYe5xqf3RA8nrc+VIwzCfnxuXJw==", + "version": "3.35.0", + "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz", + "integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==", "dev": true, + "license": "MIT", "dependencies": { "@jridgewell/gen-mapping": "^0.3.2", "commander": "^4.0.0", - "glob": "7.1.6", + "glob": "^10.3.10", "lines-and-columns": "^1.1.6", "mz": "^2.7.0", "pirates": "^4.0.1", @@ -7120,27 +7235,7 @@ "sucrase-node": "bin/sucrase-node" }, "engines": { - "node": ">=8" - } - }, - "node_modules/sucrase/node_modules/glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": ">=16 || 14 >=14.17" } }, "node_modules/supercluster": { @@ -7176,34 +7271,33 @@ } }, "node_modules/svelte": { - "version": "4.2.19", - "resolved": "https://registry.npmjs.org/svelte/-/svelte-4.2.19.tgz", - "integrity": "sha512-IY1rnGr6izd10B0A8LqsBfmlT5OILVuZ7XsI0vdGPEvuonFV7NYEUK4dAkm9Zg2q0Um92kYjTpS1CAP3Nh/KWw==", + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/svelte/-/svelte-5.2.1.tgz", + "integrity": "sha512-WzyA7VUVlDTLPt+m71bLD5BXasavqvAo68DelxWaPo8dNEZ3tmeq3DSJPsWqnG37cG2hfn7HaD3x882qF+7UOw==", "license": "MIT", "dependencies": { - "@ampproject/remapping": "^2.2.1", - "@jridgewell/sourcemap-codec": "^1.4.15", - "@jridgewell/trace-mapping": "^0.3.18", - "@types/estree": "^1.0.1", - "acorn": "^8.9.0", - "aria-query": "^5.3.0", - "axobject-query": "^4.0.0", - "code-red": "^1.0.3", - "css-tree": "^2.3.1", - "estree-walker": "^3.0.3", - "is-reference": "^3.0.1", + "@ampproject/remapping": "^2.3.0", + "@jridgewell/sourcemap-codec": "^1.5.0", + "@types/estree": "^1.0.5", + "acorn": "^8.12.1", + "acorn-typescript": "^1.4.13", + "aria-query": "^5.3.1", + "axobject-query": "^4.1.0", + "esm-env": "^1.0.0", + "esrap": "^1.2.2", + "is-reference": "^3.0.3", "locate-character": "^3.0.0", - "magic-string": "^0.30.4", - "periscopic": "^3.1.0" + "magic-string": "^0.30.11", + "zimmerframe": "^1.1.2" }, "engines": { - "node": ">=16" + "node": ">=18" } }, "node_modules/svelte-check": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/svelte-check/-/svelte-check-4.0.5.tgz", - "integrity": "sha512-icBTBZ3ibBaywbXUat3cK6hB5Du+Kq9Z8CRuyLmm64XIe2/r+lQcbuBx/IQgsbrC+kT2jQ0weVpZSSRIPwB6jQ==", + "version": "4.0.9", + "resolved": "https://registry.npmjs.org/svelte-check/-/svelte-check-4.0.9.tgz", + "integrity": "sha512-SVNCz2L+9ZELGli7G0n3B3QE5kdf0u27RtKr2ZivWQhcWIXatZxwM4VrQ6AiA2k9zKp2mk5AxkEhdjbpjv7rEw==", "dev": true, "license": "MIT", "dependencies": { @@ -7318,18 +7412,6 @@ "integrity": "sha512-kElJnoZrQtlkXE0O/RcKioz9NP0Sxx05j31ohyosNkydo6NOEsZB85mhoaCxOQNjxN+QPumYWfmIUsznYFjihA==", "license": "MIT" }, - "node_modules/svelte-hmr": { - "version": "0.16.0", - "resolved": "https://registry.npmjs.org/svelte-hmr/-/svelte-hmr-0.16.0.tgz", - "integrity": "sha512-Gyc7cOS3VJzLlfj7wKS0ZnzDVdv3Pn2IuVeJPk9m2skfhcu5bq3wtIZyQGggr7/Iim5rH5cncyQft/kRLupcnA==", - "dev": true, - "engines": { - "node": "^12.20 || ^14.13.1 || >= 16" - }, - "peerDependencies": { - "svelte": "^3.19.0 || ^4.0.0" - } - }, "node_modules/svelte-i18n": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/svelte-i18n/-/svelte-i18n-4.0.1.tgz", @@ -7821,6 +7903,15 @@ "svelte": "^3.0.0 || ^4.0.0 || ^5.0.0-next.1" } }, + "node_modules/svelte/node_modules/aria-query": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz", + "integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==", + "license": "Apache-2.0", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/symbol-tree": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", @@ -7830,34 +7921,34 @@ "peer": true }, "node_modules/tailwindcss": { - "version": "3.4.14", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.14.tgz", - "integrity": "sha512-IcSvOcTRcUtQQ7ILQL5quRDg7Xs93PdJEk1ZLbhhvJc7uj/OAhYOnruEiwnGgBvUtaUAJ8/mhSw1o8L2jCiENA==", + "version": "3.4.15", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.15.tgz", + "integrity": "sha512-r4MeXnfBmSOuKUWmXe6h2CcyfzJCEk4F0pptO5jlnYSIViUkVmsawj80N5h2lO3gwcmSb4n3PuN+e+GC1Guylw==", "dev": true, "license": "MIT", "dependencies": { "@alloc/quick-lru": "^5.2.0", "arg": "^5.0.2", - "chokidar": "^3.5.3", + "chokidar": "^3.6.0", "didyoumean": "^1.2.2", "dlv": "^1.1.3", - "fast-glob": "^3.3.0", + "fast-glob": "^3.3.2", "glob-parent": "^6.0.2", "is-glob": "^4.0.3", - "jiti": "^1.21.0", + "jiti": "^1.21.6", "lilconfig": "^2.1.0", - "micromatch": "^4.0.5", + "micromatch": "^4.0.8", "normalize-path": "^3.0.0", "object-hash": "^3.0.0", - "picocolors": "^1.0.0", - "postcss": "^8.4.23", + "picocolors": "^1.1.1", + "postcss": "^8.4.47", "postcss-import": "^15.1.0", "postcss-js": "^4.0.1", - "postcss-load-config": "^4.0.1", - "postcss-nested": "^6.0.1", - "postcss-selector-parser": "^6.0.11", - "resolve": "^1.22.2", - "sucrase": "^3.32.0" + "postcss-load-config": "^4.0.2", + "postcss-nested": "^6.2.0", + "postcss-selector-parser": "^6.1.2", + "resolve": "^1.22.8", + "sucrase": "^3.35.0" }, "bin": { "tailwind": "lib/cli.js", @@ -7917,9 +8008,9 @@ } }, "node_modules/tailwindcss/node_modules/yaml": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.6.0.tgz", - "integrity": "sha512-a6ae//JvKDEra2kdi1qzCyrJW/WZCgFi8ydDV+eXExl95t+5R+ijnqHJbz9tmMh8FUjx3iv2fCQ4dclAQlO2UQ==", + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.6.1.tgz", + "integrity": "sha512-7r0XPzioN/Q9kXBro/XPnA6kznR73DHq+GXh5ON7ZozRO6aMjbmiBuKste2wslTFkC5d1dw0GooOCepZXJ2SAg==", "dev": true, "license": "ISC", "bin": { @@ -7952,26 +8043,6 @@ "balanced-match": "^1.0.0" } }, - "node_modules/test-exclude/node_modules/glob": { - "version": "10.4.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", - "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", - "dev": true, - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^3.1.2", - "minimatch": "^9.0.4", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^1.11.1" - }, - "bin": { - "glob": "dist/esm/bin.mjs" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/test-exclude/node_modules/minimatch": { "version": "9.0.5", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", @@ -7991,7 +8062,8 @@ "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/thenify": { "version": "3.3.1", @@ -8051,17 +8123,18 @@ "license": "MIT" }, "node_modules/tinyexec": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.0.tgz", - "integrity": "sha512-tVGE0mVJPGb0chKhqmsoosjsS+qUnJVGJpZgsHYQcGoPlG3B51R3PouqTgEGH2Dc9jjFyOqOpix6ZHNMXp1FZg==", + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.1.tgz", + "integrity": "sha512-WiCJLEECkO18gwqIp6+hJg0//p23HXp4S+gGtAKu3mI2F2/sXC4FvHvXvB0zJVVaTPhx1/tOwdbRsa1sOBIKqQ==", "dev": true, "license": "MIT" }, "node_modules/tinypool": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.0.0.tgz", - "integrity": "sha512-KIKExllK7jp3uvrNtvRBYBWBOAXSX8ZvoaD8T+7KB/QHIuoJW3Pmr60zucywjAlMb5TeXUkcs/MWeWLu0qvuAQ==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.0.1.tgz", + "integrity": "sha512-URZYihUbRPcGv95En+sz6MfghfIc2OJ1sv/RmhWZLouPY0/8Vo80viwPvg3dlaS9fuq7fQMEfgRRK7BBZThBEA==", "dev": true, + "license": "MIT", "engines": { "node": "^18.0.0 || >=20.0.0" } @@ -8090,20 +8163,12 @@ "node": ">=14.0.0" } }, - "node_modules/to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", - "dev": true, - "engines": { - "node": ">=4" - } - }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, + "license": "MIT", "dependencies": { "is-number": "^7.0.0" }, @@ -8170,9 +8235,9 @@ "dev": true }, "node_modules/tslib": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.0.tgz", - "integrity": "sha512-jWVzBLplnCmoaTr13V9dYbiQ99wvZRd0vNWaDRg+aVYRcjDF3nDksxFDE/+fkXnKhpnUUkmx5pK/v8mCtLVqZA==", + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", "license": "0BSD" }, "node_modules/type": { @@ -8257,9 +8322,9 @@ } }, "node_modules/update-browserslist-db": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz", - "integrity": "sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz", + "integrity": "sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==", "dev": true, "funding": [ { @@ -8277,8 +8342,8 @@ ], "license": "MIT", "dependencies": { - "escalade": "^3.1.2", - "picocolors": "^1.0.1" + "escalade": "^3.2.0", + "picocolors": "^1.1.0" }, "bin": { "update-browserslist-db": "cli.js" @@ -8325,9 +8390,9 @@ } }, "node_modules/vite": { - "version": "5.4.10", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.10.tgz", - "integrity": "sha512-1hvaPshuPUtxeQ0hsVH3Mud0ZanOLwVTneA1EgbAM5LhaZEqyPWGRQ7BtaMvUrTDeEaC8pxtj6a6jku3x4z6SQ==", + "version": "5.4.11", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.11.tgz", + "integrity": "sha512-c7jFQRklXua0mTzneGW9QVyxFjUgwcihC4bXEtujIo2ouWCe1Ajt/amn2PCxYnhYfd5k09JX3SB7OYWFKYqj8Q==", "dev": true, "license": "MIT", "dependencies": { @@ -8398,14 +8463,15 @@ } }, "node_modules/vite-node": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-2.1.3.tgz", - "integrity": "sha512-I1JadzO+xYX887S39Do+paRePCKoiDrWRRjp9kkG5he0t7RXNvPAJPCQSJqbGN4uCrFFeS3Kj3sLqY8NMYBEdA==", + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-2.1.5.tgz", + "integrity": "sha512-rd0QIgx74q4S1Rd56XIiL2cYEdyWn13cunYBIuqh9mpmQr7gGS0IxXoP8R6OaZtNQQLyXSWbd4rXKYUbhFpK5w==", "dev": true, "license": "MIT", "dependencies": { "cac": "^6.7.14", - "debug": "^4.3.6", + "debug": "^4.3.7", + "es-module-lexer": "^1.5.4", "pathe": "^1.1.2", "vite": "^5.0.0" }, @@ -8420,12 +8486,17 @@ } }, "node_modules/vitefu": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/vitefu/-/vitefu-0.2.5.tgz", - "integrity": "sha512-SgHtMLoqaeeGnd2evZ849ZbACbnwQCIwRH57t18FxcXoZop0uQu0uzlIhJBlF/eWVzuce0sHeqPcDo+evVcg8Q==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/vitefu/-/vitefu-1.0.3.tgz", + "integrity": "sha512-iKKfOMBHob2WxEJbqbJjHAkmYgvFDPhuqrO82om83S8RLk+17FtyMBfcyeH8GqD0ihShtkMW/zzJgiA51hCNCQ==", "dev": true, + "license": "MIT", + "workspaces": [ + "tests/deps/*", + "tests/projects/*" + ], "peerDependencies": { - "vite": "^3.0.0 || ^4.0.0 || ^5.0.0" + "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0-beta.0" }, "peerDependenciesMeta": { "vite": { @@ -8434,30 +8505,31 @@ } }, "node_modules/vitest": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-2.1.3.tgz", - "integrity": "sha512-Zrxbg/WiIvUP2uEzelDNTXmEMJXuzJ1kCpbDvaKByFA9MNeO95V+7r/3ti0qzJzrxdyuUw5VduN7k+D3VmVOSA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vitest/expect": "2.1.3", - "@vitest/mocker": "2.1.3", - "@vitest/pretty-format": "^2.1.3", - "@vitest/runner": "2.1.3", - "@vitest/snapshot": "2.1.3", - "@vitest/spy": "2.1.3", - "@vitest/utils": "2.1.3", - "chai": "^5.1.1", - "debug": "^4.3.6", - "magic-string": "^0.30.11", + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-2.1.5.tgz", + "integrity": "sha512-P4ljsdpuzRTPI/kbND2sDZ4VmieerR2c9szEZpjc+98Z9ebvnXmM5+0tHEKqYZumXqlvnmfWsjeFOjXVriDG7A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/expect": "2.1.5", + "@vitest/mocker": "2.1.5", + "@vitest/pretty-format": "^2.1.5", + "@vitest/runner": "2.1.5", + "@vitest/snapshot": "2.1.5", + "@vitest/spy": "2.1.5", + "@vitest/utils": "2.1.5", + "chai": "^5.1.2", + "debug": "^4.3.7", + "expect-type": "^1.1.0", + "magic-string": "^0.30.12", "pathe": "^1.1.2", - "std-env": "^3.7.0", + "std-env": "^3.8.0", "tinybench": "^2.9.0", - "tinyexec": "^0.3.0", - "tinypool": "^1.0.0", + "tinyexec": "^0.3.1", + "tinypool": "^1.0.1", "tinyrainbow": "^1.2.0", "vite": "^5.0.0", - "vite-node": "2.1.3", + "vite-node": "2.1.5", "why-is-node-running": "^2.3.0" }, "bin": { @@ -8472,8 +8544,8 @@ "peerDependencies": { "@edge-runtime/vm": "*", "@types/node": "^18.0.0 || >=20.0.0", - "@vitest/browser": "2.1.3", - "@vitest/ui": "2.1.3", + "@vitest/browser": "2.1.5", + "@vitest/ui": "2.1.5", "happy-dom": "*", "jsdom": "*" }, @@ -8710,12 +8782,6 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true - }, "node_modules/ws": { "version": "8.17.1", "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", @@ -8757,9 +8823,9 @@ "peer": true }, "node_modules/xmlhttprequest-ssl": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.1.1.tgz", - "integrity": "sha512-ptjR8YSJIXoA3Mbv5po7RtSYHO6mZr8s7i5VGmEk7QY2pQWyT1o0N+W1gKbOyJPUCGXGnuw0wqe8f0L6Y0ny7g==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.0.0.tgz", + "integrity": "sha512-QKxVRxiRACQcVuQEYFsI1hhkrMlrXHPegbbd1yn9UHOmRxY+si12nQYzri3vbzt8VdTTRviqcKxcyllFas5z2A==", "engines": { "node": ">=0.4.0" } @@ -8820,6 +8886,12 @@ "funding": { "url": "https://github.com/sponsors/sindresorhus" } + }, + "node_modules/zimmerframe": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/zimmerframe/-/zimmerframe-1.1.2.tgz", + "integrity": "sha512-rAbqEGa8ovJy4pyBxZM70hg4pE6gDgaQ0Sl9M3enG3I0d6H4XSAM3GeNGLKnsBpuijUow064sf7ww1nutC5/3w==", + "license": "MIT" } } } diff --git a/web/package.json b/web/package.json index 103f4535f9f2c..2d42de1a8e86a 100644 --- a/web/package.json +++ b/web/package.json @@ -1,6 +1,6 @@ { "name": "immich-web", - "version": "1.119.1", + "version": "1.123.0", "license": "GNU Affero General Public License version 3", "scripts": { "dev": "vite dev --host 0.0.0.0 --port 3000", @@ -8,7 +8,7 @@ "build:stats": "BUILD_STATS=true vite build", "package": "svelte-kit package", "preview": "vite preview", - "check:svelte": "svelte-check --no-tsconfig --fail-on-warnings", + "check:svelte": "svelte-check --no-tsconfig --fail-on-warnings --compiler-warnings 'reactive_declaration_non_reactive_property:ignore'", "check:typescript": "tsc --noEmit", "check:watch": "npm run check:svelte -- --watch", "check:code": "npm run format && npm run lint && npm run check:svelte && npm run check:typescript", @@ -27,26 +27,26 @@ "@eslint/js": "^9.8.0", "@faker-js/faker": "^9.0.0", "@socket.io/component-emitter": "^3.1.0", - "@sveltejs/adapter-static": "^3.0.1", - "@sveltejs/enhanced-img": "^0.3.0", - "@sveltejs/kit": "^2.5.18", - "@sveltejs/vite-plugin-svelte": "^3.1.2", + "@sveltejs/adapter-static": "^3.0.5", + "@sveltejs/enhanced-img": "^0.4.0", + "@sveltejs/kit": "^2.12.0", + "@sveltejs/vite-plugin-svelte": "^4.0.0", "@testing-library/jest-dom": "^6.4.2", - "@testing-library/svelte": "^5.2.0", + "@testing-library/svelte": "^5.2.4", "@testing-library/user-event": "^14.5.2", "@types/dom-to-image": "^2.6.7", "@types/justified-layout": "^4.1.4", "@types/lodash-es": "^4.17.12", "@types/luxon": "^3.4.2", - "@typescript-eslint/eslint-plugin": "^8.0.0", - "@typescript-eslint/parser": "^8.0.0", + "@typescript-eslint/eslint-plugin": "^8.15.0", + "@typescript-eslint/parser": "^8.15.0", "@vitest/coverage-v8": "^2.0.5", "autoprefixer": "^10.4.17", "dotenv": "^16.4.5", - "eslint": "^9.0.0", + "eslint": "^9.14.0", "eslint-config-prettier": "^9.1.0", - "eslint-plugin-svelte": "^2.43.0", - "eslint-plugin-unicorn": "^55.0.0", + "eslint-plugin-svelte": "^2.45.1", + "eslint-plugin-unicorn": "^56.0.1", "factory.ts": "^1.4.1", "globals": "^15.9.0", "postcss": "^8.4.35", @@ -55,12 +55,12 @@ "prettier-plugin-sort-json": "^4.0.0", "prettier-plugin-svelte": "^3.2.6", "rollup-plugin-visualizer": "^5.12.0", - "svelte": "^4.2.19", - "svelte-check": "^4.0.0", + "svelte": "^5.1.5", + "svelte-check": "^4.0.9", "tailwindcss": "^3.4.1", "tslib": "^2.6.2", "typescript": "^5.5.0", - "vite": "^5.1.4", + "vite": "^5.4.4", "vitest": "^2.0.5" }, "type": "module", @@ -79,14 +79,14 @@ "justified-layout": "^4.1.0", "lodash-es": "^4.17.21", "luxon": "^3.4.4", - "socket.io-client": "^4.7.4", + "socket.io-client": "~4.7.5", "svelte-gestures": "^5.0.4", - "svelte-i18n": "^4.0.0", + "svelte-i18n": "^4.0.1", "svelte-local-storage-store": "^0.6.4", "svelte-maplibre": "^0.9.13", "thumbhash": "^0.1.1" }, "volta": { - "node": "22.11.0" + "node": "22.12.0" } } diff --git a/web/src/app.d.ts b/web/src/app.d.ts index ccec3f33d6ef0..d0d25443c9373 100644 --- a/web/src/app.d.ts +++ b/web/src/app.d.ts @@ -28,7 +28,7 @@ interface Element { requestFullscreen?(options?: FullscreenOptions): Promise; } -import type en from '$lib/en.json'; +import type en from '$i18n/en.json'; import 'svelte-i18n'; type NestedKeys = K extends keyof T & string diff --git a/web/src/lib/__mocks__/animate.mock.ts b/web/src/lib/__mocks__/animate.mock.ts new file mode 100644 index 0000000000000..5f0d367d86446 --- /dev/null +++ b/web/src/lib/__mocks__/animate.mock.ts @@ -0,0 +1,17 @@ +import { tick } from 'svelte'; +import { vi } from 'vitest'; + +export const getAnimateMock = () => + vi.fn().mockImplementation(() => { + let onfinish: (() => void) | null = null; + void tick().then(() => onfinish?.()); + + return { + set onfinish(fn: () => void) { + onfinish = fn; + }, + cancel() { + onfinish = null; + }, + }; + }); diff --git a/web/src/lib/__mocks__/visual-viewport.mock.ts b/web/src/lib/__mocks__/visual-viewport.mock.ts new file mode 100644 index 0000000000000..23903d56cd0e7 --- /dev/null +++ b/web/src/lib/__mocks__/visual-viewport.mock.ts @@ -0,0 +1,9 @@ +export const getVisualViewportMock = () => ({ + height: window.innerHeight, + width: window.innerWidth, + scale: 1, + offsetLeft: 0, + offsetTop: 0, + addEventListener: vi.fn(), + removeEventListener: vi.fn(), +}); diff --git a/web/src/lib/actions/__test__/focus-trap-test.svelte b/web/src/lib/actions/__test__/focus-trap-test.svelte index 207c880cd9d8f..e1cb6fa4fba79 100644 --- a/web/src/lib/actions/__test__/focus-trap-test.svelte +++ b/web/src/lib/actions/__test__/focus-trap-test.svelte @@ -1,16 +1,20 @@ - + {#if show}
text - +
diff --git a/web/src/lib/actions/autogrow.ts b/web/src/lib/actions/autogrow.ts index ff80454ef3e84..0e6dec8e8180c 100644 --- a/web/src/lib/actions/autogrow.ts +++ b/web/src/lib/actions/autogrow.ts @@ -1,7 +1,19 @@ -export const autoGrowHeight = (textarea: HTMLTextAreaElement, height = 'auto') => { - if (!textarea) { - return; - } - textarea.style.height = height; - textarea.style.height = `${textarea.scrollHeight}px`; +import { tick } from 'svelte'; +import type { Action } from 'svelte/action'; + +type Parameters = { + height?: string; + value: string; // added to enable reactivity +}; + +export const autoGrowHeight: Action = (textarea, { height = 'auto' }) => { + const update = () => { + void tick().then(() => { + textarea.style.height = height; + textarea.style.height = `${textarea.scrollHeight}px`; + }); + }; + + update(); + return { update }; }; diff --git a/web/src/lib/actions/context-menu-navigation.ts b/web/src/lib/actions/context-menu-navigation.ts index 3b45e7fe527f0..89b7b76d24f4f 100644 --- a/web/src/lib/actions/context-menu-navigation.ts +++ b/web/src/lib/actions/context-menu-navigation.ts @@ -10,7 +10,7 @@ interface Options { /** * The container element that with direct children that should be navigated. */ - container: HTMLElement; + container?: HTMLElement; /** * Indicates if the dropdown is open. */ @@ -52,7 +52,11 @@ export const contextMenuNavigation: Action = (node, option await tick(); } - const children = Array.from(container?.children).filter((child) => child.tagName !== 'HR') as HTMLElement[]; + if (!container) { + return; + } + + const children = Array.from(container.children).filter((child) => child.tagName !== 'HR') as HTMLElement[]; if (children.length === 0) { return; } diff --git a/web/src/lib/actions/list-navigation.ts b/web/src/lib/actions/list-navigation.ts index 8f8ed62ed009e..cd4214f700570 100644 --- a/web/src/lib/actions/list-navigation.ts +++ b/web/src/lib/actions/list-navigation.ts @@ -6,8 +6,15 @@ import type { Action } from 'svelte/action'; * @param node Element which listens for keyboard events * @param container Element containing the list of elements */ -export const listNavigation: Action = (node, container: HTMLElement) => { +export const listNavigation: Action = ( + node: HTMLElement, + container?: HTMLElement, +) => { const moveFocus = (direction: 'up' | 'down') => { + if (!container) { + return; + } + const children = Array.from(container?.children); if (children.length === 0) { return; diff --git a/web/src/lib/actions/scroll-memory.ts b/web/src/lib/actions/scroll-memory.ts new file mode 100644 index 0000000000000..1c19fdd8ab2d0 --- /dev/null +++ b/web/src/lib/actions/scroll-memory.ts @@ -0,0 +1,87 @@ +import { navigating } from '$app/stores'; +import { AppRoute, SessionStorageKey } from '$lib/constants'; +import { handlePromiseError } from '$lib/utils'; + +interface Options { + /** + * {@link AppRoute} for subpages that scroll state should be kept while visiting. + * + * This must be kept the same in all subpages of this route for the scroll memory clearer to work. + */ + routeStartsWith: AppRoute; + /** + * Function to clear additional data/state before scrolling (ex infinite scroll). + */ + beforeClear?: () => void; +} + +interface PageOptions extends Options { + /** + * Function to save additional data/state before scrolling (ex infinite scroll). + */ + beforeSave?: () => void; + /** + * Function to load additional data/state before scrolling (ex infinite scroll). + */ + beforeScroll?: () => Promise; +} + +/** + * @param node The scroll slot element, typically from {@link UserPageLayout} + */ +export function scrollMemory( + node: HTMLElement, + { routeStartsWith, beforeSave, beforeClear, beforeScroll }: PageOptions, +) { + const unsubscribeNavigating = navigating.subscribe((navigation) => { + const existingScroll = sessionStorage.getItem(SessionStorageKey.SCROLL_POSITION); + if (navigation?.to && !existingScroll) { + // Save current scroll information when going into a subpage. + if (navigation.to.url.pathname.startsWith(routeStartsWith)) { + beforeSave?.(); + sessionStorage.setItem(SessionStorageKey.SCROLL_POSITION, node.scrollTop.toString()); + } else { + beforeClear?.(); + sessionStorage.removeItem(SessionStorageKey.SCROLL_POSITION); + } + } + }); + + handlePromiseError( + (async () => { + await beforeScroll?.(); + + const newScroll = sessionStorage.getItem(SessionStorageKey.SCROLL_POSITION); + if (newScroll) { + node.scroll({ + top: Number.parseFloat(newScroll), + behavior: 'instant', + }); + } + beforeClear?.(); + sessionStorage.removeItem(SessionStorageKey.SCROLL_POSITION); + })(), + ); + + return { + destroy() { + unsubscribeNavigating(); + }, + }; +} + +export function scrollMemoryClearer(_node: HTMLElement, { routeStartsWith, beforeClear }: Options) { + const unsubscribeNavigating = navigating.subscribe((navigation) => { + // Forget scroll position from main page if going somewhere else. + if (navigation?.to && !navigation?.to.url.pathname.startsWith(routeStartsWith)) { + beforeClear?.(); + sessionStorage.removeItem(SessionStorageKey.SCROLL_POSITION); + } + }); + + return { + destroy() { + unsubscribeNavigating(); + }, + }; +} diff --git a/web/src/lib/actions/use-actions.ts b/web/src/lib/actions/use-actions.ts new file mode 100644 index 0000000000000..762cfdccf775b --- /dev/null +++ b/web/src/lib/actions/use-actions.ts @@ -0,0 +1,67 @@ +/** + * @license Apache-2.0 + * https://github.com/hperrin/svelte-material-ui/blob/master/packages/common/src/internal/useActions.ts + */ + +export type SvelteActionReturnType

= { + update?: (newParams?: P) => void; + destroy?: () => void; +} | void; + +export type SvelteHTMLActionType

= (node: HTMLElement, params?: P) => SvelteActionReturnType

; + +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export type HTMLActionEntry

= SvelteHTMLActionType

| [SvelteHTMLActionType

, P]; + +export type HTMLActionArray = HTMLActionEntry[]; + +export type SvelteSVGActionType

= (node: SVGElement, params?: P) => SvelteActionReturnType

; + +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export type SVGActionEntry

= SvelteSVGActionType

| [SvelteSVGActionType

, P]; + +export type SVGActionArray = SVGActionEntry[]; + +export type ActionArray = HTMLActionArray | SVGActionArray; + +export function useActions(node: HTMLElement | SVGElement, actions: ActionArray) { + const actionReturns: SvelteActionReturnType[] = []; + + if (actions) { + for (const actionEntry of actions) { + const action = Array.isArray(actionEntry) ? actionEntry[0] : actionEntry; + if (Array.isArray(actionEntry) && actionEntry.length > 1) { + actionReturns.push(action(node as HTMLElement & SVGElement, actionEntry[1])); + } else { + actionReturns.push(action(node as HTMLElement & SVGElement)); + } + } + } + + return { + update(actions: ActionArray) { + if ((actions?.length || 0) != actionReturns.length) { + throw new Error('You must not change the length of an actions array.'); + } + + if (actions) { + for (const [i, returnEntry] of actionReturns.entries()) { + if (returnEntry && returnEntry.update) { + const actionEntry = actions[i]; + if (Array.isArray(actionEntry) && actionEntry.length > 1) { + returnEntry.update(actionEntry[1]); + } else { + returnEntry.update(); + } + } + } + } + }, + + destroy() { + for (const returnEntry of actionReturns) { + returnEntry?.destroy?.(); + } + }, + }; +} diff --git a/web/src/lib/components/admin-page/delete-confirm-dialogue.svelte b/web/src/lib/components/admin-page/delete-confirm-dialogue.svelte index a2fbbe787a1e9..6eb603263ecec 100644 --- a/web/src/lib/components/admin-page/delete-confirm-dialogue.svelte +++ b/web/src/lib/components/admin-page/delete-confirm-dialogue.svelte @@ -7,13 +7,17 @@ import { deleteUserAdmin, type UserResponseDto } from '@immich/sdk'; import { t } from 'svelte-i18n'; - export let user: UserResponseDto; - export let onSuccess: () => void; - export let onFail: () => void; - export let onCancel: () => void; + interface Props { + user: UserResponseDto; + onSuccess: () => void; + onFail: () => void; + onCancel: () => void; + } - let forceDelete = false; - let deleteButtonDisabled = false; + let { user, onSuccess, onFail, onCancel }: Props = $props(); + + let forceDelete = $state(false); + let deleteButtonDisabled = $state(false); let userIdInput: string = ''; const handleDeleteUser = async () => { @@ -47,12 +51,14 @@ {onCancel} disabled={deleteButtonDisabled} > - + {#snippet promptSnippet()}

{#if forceDelete}

- - {message} + + {#snippet children({ message })} + {message} + {/snippet}

{:else} @@ -60,9 +66,10 @@ - {message} + {#snippet children({ message })} + {message} + {/snippet}

{/if} @@ -73,7 +80,7 @@ label={$t('admin.user_delete_immediately_checkbox')} labelClass="text-sm dark:text-immich-dark-fg" bind:checked={forceDelete} - on:change={() => { + onchange={() => { deleteButtonDisabled = forceDelete; }} /> @@ -92,9 +99,9 @@ aria-describedby="confirm-user-desc" name="confirm-user-id" type="text" - on:input={handleConfirm} + oninput={handleConfirm} /> {/if}
- + {/snippet} diff --git a/web/src/lib/components/admin-page/jobs/job-tile-button.svelte b/web/src/lib/components/admin-page/jobs/job-tile-button.svelte index 69d3706230de9..f71d8a3e447af 100644 --- a/web/src/lib/components/admin-page/jobs/job-tile-button.svelte +++ b/web/src/lib/components/admin-page/jobs/job-tile-button.svelte @@ -1,10 +1,18 @@ -
- + {@render children?.()}
diff --git a/web/src/lib/components/admin-page/jobs/job-tile.svelte b/web/src/lib/components/admin-page/jobs/job-tile.svelte index b0af3a710f36f..0e39647c75974 100644 --- a/web/src/lib/components/admin-page/jobs/job-tile.svelte +++ b/web/src/lib/components/admin-page/jobs/job-tile.svelte @@ -14,27 +14,42 @@ mdiPlay, mdiSelectionSearch, } from '@mdi/js'; - import { type ComponentType } from 'svelte'; + import { type Component } from 'svelte'; import { t } from 'svelte-i18n'; import JobTileButton from './job-tile-button.svelte'; import JobTileStatus from './job-tile-status.svelte'; - export let title: string; - export let subtitle: string | undefined; - export let description: ComponentType | undefined; - export let jobCounts: JobCountsDto; - export let queueStatus: QueueStatusDto; - export let icon: string; - export let disabled = false; + interface Props { + title: string; + subtitle: string | undefined; + description: Component | undefined; + jobCounts: JobCountsDto; + queueStatus: QueueStatusDto; + icon: string; + disabled?: boolean; + allText: string | undefined; + refreshText: string | undefined; + missingText: string; + onCommand: (command: JobCommandDto) => void; + } - export let allText: string | undefined; - export let refreshText: string | undefined; - export let missingText: string; - export let onCommand: (command: JobCommandDto) => void; + let { + title, + subtitle, + description, + jobCounts, + queueStatus, + icon, + disabled = false, + allText, + refreshText, + missingText, + onCommand, + }: Props = $props(); - $: waitingCount = jobCounts.waiting + jobCounts.paused + jobCounts.delayed; - $: isIdle = !queueStatus.isActive && !queueStatus.isPaused; - $: multipleButtons = allText || refreshText; + let waitingCount = $derived(jobCounts.waiting + jobCounts.paused + jobCounts.delayed); + let isIdle = $derived(!queueStatus.isActive && !queueStatus.isPaused); + let multipleButtons = $derived(allText || refreshText); const commonClasses = 'flex place-items-center justify-between w-full py-2 sm:py-4 pr-4 pl-6'; @@ -67,7 +82,7 @@ title={$t('clear_message')} size="12" padding="1" - on:click={() => onCommand({ command: JobCommand.ClearFailed, force: false })} + onclick={() => onCommand({ command: JobCommand.ClearFailed, force: false })} />
@@ -87,8 +102,9 @@ {/if} {#if description} + {@const SvelteComponent = description}
- +
{/if} @@ -118,7 +134,7 @@ onCommand({ command: JobCommand.Start, force: false })} + onClick={() => onCommand({ command: JobCommand.Start, force: false })} > {$t('disabled').toUpperCase()} @@ -127,20 +143,20 @@ {#if !disabled && !isIdle} {#if waitingCount > 0} - onCommand({ command: JobCommand.Empty, force: false })}> + onCommand({ command: JobCommand.Empty, force: false })}> {$t('clear').toUpperCase()} {/if} {#if queueStatus.isPaused} {@const size = waitingCount > 0 ? '24' : '48'} - onCommand({ command: JobCommand.Resume, force: false })}> + onCommand({ command: JobCommand.Resume, force: false })}> {$t('resume').toUpperCase()} {:else} - onCommand({ command: JobCommand.Pause, force: false })}> + onCommand({ command: JobCommand.Pause, force: false })}> {$t('pause').toUpperCase()} @@ -149,25 +165,25 @@ {#if !disabled && multipleButtons && isIdle} {#if allText} - onCommand({ command: JobCommand.Start, force: true })}> + onCommand({ command: JobCommand.Start, force: true })}> {allText} {/if} {#if refreshText} - onCommand({ command: JobCommand.Start, force: undefined })}> + onCommand({ command: JobCommand.Start, force: undefined })}> {refreshText} {/if} - onCommand({ command: JobCommand.Start, force: false })}> + onCommand({ command: JobCommand.Start, force: false })}> {missingText} {/if} {#if !disabled && !multipleButtons && isIdle} - onCommand({ command: JobCommand.Start, force: false })}> + onCommand({ command: JobCommand.Start, force: false })}> {$t('start').toUpperCase()} diff --git a/web/src/lib/components/admin-page/jobs/jobs-panel.svelte b/web/src/lib/components/admin-page/jobs/jobs-panel.svelte index 8702a1e933fa4..9b4f3ffdd646a 100644 --- a/web/src/lib/components/admin-page/jobs/jobs-panel.svelte +++ b/web/src/lib/components/admin-page/jobs/jobs-panel.svelte @@ -19,18 +19,22 @@ mdiTagFaces, mdiVideo, } from '@mdi/js'; - import type { ComponentType } from 'svelte'; + import type { Component } from 'svelte'; import JobTile from './job-tile.svelte'; import StorageMigrationDescription from './storage-migration-description.svelte'; import { dialogController } from '$lib/components/shared-components/dialog/dialog'; import { t } from 'svelte-i18n'; - export let jobs: AllJobStatusResponseDto; + interface Props { + jobs: AllJobStatusResponseDto; + } + + let { jobs = $bindable() }: Props = $props(); interface JobDetails { title: string; subtitle?: string; - description?: ComponentType; + description?: Component; allText?: string; refreshText?: string; missingText: string; @@ -56,7 +60,7 @@ await handleCommand(jobId, dto); }; - $: jobDetails = >>{ + let jobDetails: Partial> = { [JobName.ThumbnailGeneration]: { icon: mdiFileJpgBox, title: $getJobName(JobName.ThumbnailGeneration), @@ -141,7 +145,8 @@ missingText: $t('missing'), }, }; - $: jobList = Object.entries(jobDetails) as [JobName, JobDetails][]; + + let jobList = Object.entries(jobDetails) as [JobName, JobDetails][]; async function handleCommand(jobId: JobName, jobCommand: JobCommandDto) { const title = jobDetails[jobId]?.title; diff --git a/web/src/lib/components/admin-page/jobs/storage-migration-description.svelte b/web/src/lib/components/admin-page/jobs/storage-migration-description.svelte index 8a74d2c5ad0be..b47df1daaec86 100644 --- a/web/src/lib/components/admin-page/jobs/storage-migration-description.svelte +++ b/web/src/lib/components/admin-page/jobs/storage-migration-description.svelte @@ -7,12 +7,13 @@ - - {message} - + {#snippet children({ message })} + + {message} + + {/snippet} diff --git a/web/src/lib/components/admin-page/restore-dialogue.svelte b/web/src/lib/components/admin-page/restore-dialogue.svelte index 25afbc6d4b9b6..a72ada2ca5d88 100644 --- a/web/src/lib/components/admin-page/restore-dialogue.svelte +++ b/web/src/lib/components/admin-page/restore-dialogue.svelte @@ -5,10 +5,14 @@ import { restoreUserAdmin, type UserResponseDto } from '@immich/sdk'; import { t } from 'svelte-i18n'; - export let user: UserResponseDto; - export let onSuccess: () => void; - export let onFail: () => void; - export let onCancel: () => void; + interface Props { + user: UserResponseDto; + onSuccess: () => void; + onFail: () => void; + onCancel: () => void; + } + + let { user, onSuccess, onFail, onCancel }: Props = $props(); const handleRestoreUser = async () => { try { @@ -32,11 +36,13 @@ onConfirm={handleRestoreUser} {onCancel} > - + {#snippet promptSnippet()}

- - {message} + + {#snippet children({ message })} + {message} + {/snippet}

-
+ {/snippet} diff --git a/web/src/lib/components/admin-page/server-stats/server-stats-panel.svelte b/web/src/lib/components/admin-page/server-stats/server-stats-panel.svelte index 35afc0962d414..bb288511accf7 100644 --- a/web/src/lib/components/admin-page/server-stats/server-stats-panel.svelte +++ b/web/src/lib/components/admin-page/server-stats/server-stats-panel.svelte @@ -7,14 +7,22 @@ import StatsCard from './stats-card.svelte'; import { t } from 'svelte-i18n'; - export let stats: ServerStatsResponseDto = { - photos: 0, - videos: 0, - usage: 0, - usageByUser: [], - }; + interface Props { + stats?: ServerStatsResponseDto; + } + + let { + stats = { + photos: 0, + videos: 0, + usage: 0, + usagePhotos: 0, + usageVideos: 0, + usageByUser: [], + }, + }: Props = $props(); - $: zeros = (value: number) => { + const zeros = (value: number) => { const maxLength = 13; const valueLength = value.toString().length; const zeroLength = maxLength - valueLength; @@ -23,7 +31,7 @@ }; const TiB = 1024 ** 4; - $: [statsUsage, statsUsageUnit] = getBytesWithUnit(stats.usage, stats.usage > TiB ? 2 : 0); + let [statsUsage, statsUsageUnit] = $derived(getBytesWithUnit(stats.usage, stats.usage > TiB ? 2 : 0));
@@ -99,8 +107,12 @@ class="flex h-[50px] w-full place-items-center text-center odd:bg-immich-gray even:bg-immich-bg odd:dark:bg-immich-dark-gray/75 even:dark:bg-immich-dark-gray/50" > {user.userName} - {user.photos.toLocaleString($locale)} - {user.videos.toLocaleString($locale)} + {user.photos.toLocaleString($locale)} ({getByteUnitString(user.usagePhotos, $locale, 0)}) + {user.videos.toLocaleString($locale)} ({getByteUnitString(user.usageVideos, $locale, 0)}) {getByteUnitString(user.usage, $locale, 0)} {#if user.quotaSizeInBytes} diff --git a/web/src/lib/components/admin-page/server-stats/stats-card.svelte b/web/src/lib/components/admin-page/server-stats/stats-card.svelte index 31baa0afdd780..14d32c055f23a 100644 --- a/web/src/lib/components/admin-page/server-stats/stats-card.svelte +++ b/web/src/lib/components/admin-page/server-stats/stats-card.svelte @@ -2,18 +2,22 @@ import Icon from '$lib/components/elements/icon.svelte'; import { ByteUnit } from '$lib/utils/byte-units'; - export let icon: string; - export let title: string; - export let value: number; - export let unit: ByteUnit | undefined = undefined; + interface Props { + icon: string; + title: string; + value: number; + unit?: ByteUnit | undefined; + } - $: zeros = () => { + let { icon, title, value, unit = undefined }: Props = $props(); + + const zeros = $derived(() => { const maxLength = 13; const valueLength = value.toString().length; const zeroLength = maxLength - valueLength; return '0'.repeat(zeroLength); - }; + });
diff --git a/web/src/lib/components/admin-page/settings/admin-settings.svelte b/web/src/lib/components/admin-page/settings/admin-settings.svelte index 19a8580d6bb90..199db0b57112a 100644 --- a/web/src/lib/components/admin-page/settings/admin-settings.svelte +++ b/web/src/lib/components/admin-page/settings/admin-settings.svelte @@ -1,5 +1,3 @@ - - {#if savedConfig && defaultConfig} - + {@render children({ savedConfig, defaultConfig })} {/if} diff --git a/web/src/lib/components/admin-page/settings/auth/auth-settings.svelte b/web/src/lib/components/admin-page/settings/auth/auth-settings.svelte index 9b0e4b32706b5..5380a7628634f 100644 --- a/web/src/lib/components/admin-page/settings/auth/auth-settings.svelte +++ b/web/src/lib/components/admin-page/settings/auth/auth-settings.svelte @@ -2,9 +2,7 @@ import ConfirmDialog from '$lib/components/shared-components/dialog/confirm-dialog.svelte'; import SettingAccordion from '$lib/components/shared-components/settings/setting-accordion.svelte'; import SettingButtonsRow from '$lib/components/shared-components/settings/setting-buttons-row.svelte'; - import SettingInputField, { - SettingInputFieldType, - } from '$lib/components/shared-components/settings/setting-input-field.svelte'; + import SettingInputField from '$lib/components/shared-components/settings/setting-input-field.svelte'; import SettingSwitch from '$lib/components/shared-components/settings/setting-switch.svelte'; import { type SystemConfigDto } from '@immich/sdk'; import { isEqual } from 'lodash-es'; @@ -12,21 +10,26 @@ import type { SettingsResetEvent, SettingsSaveEvent } from '../admin-settings'; import { t } from 'svelte-i18n'; import FormatMessage from '$lib/components/i18n/format-message.svelte'; + import { SettingInputFieldType } from '$lib/constants'; - export let savedConfig: SystemConfigDto; - export let defaultConfig: SystemConfigDto; - export let config: SystemConfigDto; // this is the config that is being edited - export let disabled = false; - export let onReset: SettingsResetEvent; - export let onSave: SettingsSaveEvent; + interface Props { + savedConfig: SystemConfigDto; + defaultConfig: SystemConfigDto; + config: SystemConfigDto; + disabled?: boolean; + onReset: SettingsResetEvent; + onSave: SettingsSaveEvent; + } - let isConfirmOpen = false; + let { savedConfig, defaultConfig, config = $bindable(), disabled = false, onReset, onSave }: Props = $props(); + + let isConfirmOpen = $state(false); const handleToggleOverride = () => { // click runs before bind const previouslyEnabled = config.oauth.mobileOverrideEnabled; if (!previouslyEnabled && !config.oauth.mobileRedirectUri) { - config.oauth.mobileRedirectUri = window.location.origin + '/api/oauth/mobile-redirect'; + config.oauth.mobileRedirectUri = globalThis.location.origin + '/api/oauth/mobile-redirect'; } }; @@ -48,29 +51,31 @@ onCancel={() => (isConfirmOpen = false)} onConfirm={() => handleSave(true)} > - + {#snippet promptSnippet()}

{$t('admin.authentication_settings_disable_all')}

- - - {message} - + + {#snippet children({ message })} + + {message} + + {/snippet}

-
+ {/snippet} {/if}
-
+ e.preventDefault()}>

- - - {message} - + + {#snippet children({ message })} + + {message} + + {/snippet}

@@ -147,7 +154,7 @@ handleToggleOverride()} + onToggle={() => handleToggleOverride()} bind:checked={config.oauth.mobileOverrideEnabled} /> diff --git a/web/src/lib/components/admin-page/settings/backup-settings/backup-settings.svelte b/web/src/lib/components/admin-page/settings/backup-settings/backup-settings.svelte index 05543f112465e..3ec477e29c645 100644 --- a/web/src/lib/components/admin-page/settings/backup-settings/backup-settings.svelte +++ b/web/src/lib/components/admin-page/settings/backup-settings/backup-settings.svelte @@ -3,33 +3,40 @@ import { isEqual } from 'lodash-es'; import { fade } from 'svelte/transition'; import type { SettingsResetEvent, SettingsSaveEvent } from '../admin-settings'; - import SettingInputField, { - SettingInputFieldType, - } from '$lib/components/shared-components/settings/setting-input-field.svelte'; + import SettingInputField from '$lib/components/shared-components/settings/setting-input-field.svelte'; import SettingSwitch from '$lib/components/shared-components/settings/setting-switch.svelte'; import SettingButtonsRow from '$lib/components/shared-components/settings/setting-buttons-row.svelte'; import SettingSelect from '$lib/components/shared-components/settings/setting-select.svelte'; import { t } from 'svelte-i18n'; import FormatMessage from '$lib/components/i18n/format-message.svelte'; + import { SettingInputFieldType } from '$lib/constants'; - export let savedConfig: SystemConfigDto; - export let defaultConfig: SystemConfigDto; - export let config: SystemConfigDto; // this is the config that is being edited - export let disabled = false; - export let onReset: SettingsResetEvent; - export let onSave: SettingsSaveEvent; + interface Props { + savedConfig: SystemConfigDto; + defaultConfig: SystemConfigDto; + config: SystemConfigDto; + disabled?: boolean; + onReset: SettingsResetEvent; + onSave: SettingsSaveEvent; + } - $: cronExpressionOptions = [ + let { savedConfig, defaultConfig, config = $bindable(), disabled = false, onReset, onSave }: Props = $props(); + + let cronExpressionOptions = $derived([ { text: $t('interval.night_at_midnight'), value: '0 0 * * *' }, { text: $t('interval.night_at_twoam'), value: '0 02 * * *' }, { text: $t('interval.day_at_onepm'), value: '0 13 * * *' }, { text: $t('interval.hours', { values: { hours: 6 } }), value: '0 */6 * * *' }, - ]; + ]); + + const onsubmit = (event: Event) => { + event.preventDefault(); + };
- +
- + {#snippet descriptionSnippet()}

- - - {message} -
-
+ + {#snippet children({ message })} + + {message} +
+
+ {/snippet}

-
+ {/snippet} { + event.preventDefault(); + };
- +

- - {#if tag === 'h264-link'} - - {message} - - {:else if tag === 'hevc-link'} - - {message} - - {:else if tag === 'vp9-link'} - - {message} - - {/if} + + {#snippet children({ tag, message })} + {#if tag === 'h264-link'} + + {message} + + {:else if tag === 'hevc-link'} + + {message} + + {:else if tag === 'vp9-link'} + + {message} + + {/if} + {/snippet}

@@ -60,7 +69,7 @@ inputType={SettingInputFieldType.NUMBER} {disabled} label={$t('admin.transcoding_constant_rate_factor')} - desc={$t('admin.transcoding_constant_rate_factor_description')} + description={$t('admin.transcoding_constant_rate_factor_description')} bind:value={config.ffmpeg.crf} required={true} isEdited={config.ffmpeg.crf !== savedConfig.ffmpeg.crf} @@ -186,7 +195,7 @@ inputType={SettingInputFieldType.TEXT} {disabled} label={$t('admin.transcoding_max_bitrate')} - desc={$t('admin.transcoding_max_bitrate_description')} + description={$t('admin.transcoding_max_bitrate_description')} bind:value={config.ffmpeg.maxBitrate} isEdited={config.ffmpeg.maxBitrate !== savedConfig.ffmpeg.maxBitrate} /> @@ -195,7 +204,7 @@ inputType={SettingInputFieldType.NUMBER} {disabled} label={$t('admin.transcoding_threads')} - desc={$t('admin.transcoding_threads_description')} + description={$t('admin.transcoding_threads_description')} bind:value={config.ffmpeg.threads} isEdited={config.ffmpeg.threads !== savedConfig.ffmpeg.threads} /> @@ -329,7 +338,7 @@
- - { + event.preventDefault(); + };
- +
{ + event.preventDefault(); + };
- + {#each jobNames as jobName}
{#if isSystemConfigJobDto(jobName)} @@ -46,7 +53,7 @@ inputType={SettingInputFieldType.NUMBER} {disabled} label={$t('admin.job_concurrency', { values: { job: $getJobName(jobName) } })} - desc="" + description="" bind:value={config.job[jobName].concurrency} required={true} isEdited={!(config.job[jobName].concurrency == savedConfig.job[jobName].concurrency)} @@ -55,7 +62,7 @@ { + event.preventDefault(); + };
- +
-
- - -
+ - + {#snippet descriptionSnippet()}

- - - {message} - + + {#snippet children({ message })} + + {message} + + {/snippet}

-
+ {/snippet}
diff --git a/web/src/lib/components/admin-page/settings/logging-settings/logging-settings.svelte b/web/src/lib/components/admin-page/settings/logging-settings/logging-settings.svelte index 6e71ba926c79f..29a1c65162359 100644 --- a/web/src/lib/components/admin-page/settings/logging-settings/logging-settings.svelte +++ b/web/src/lib/components/admin-page/settings/logging-settings/logging-settings.svelte @@ -8,17 +8,25 @@ import SettingSelect from '$lib/components/shared-components/settings/setting-select.svelte'; import { t } from 'svelte-i18n'; - export let savedConfig: SystemConfigDto; - export let defaultConfig: SystemConfigDto; - export let config: SystemConfigDto; // this is the config that is being edited - export let disabled = false; - export let onReset: SettingsResetEvent; - export let onSave: SettingsSaveEvent; + interface Props { + savedConfig: SystemConfigDto; + defaultConfig: SystemConfigDto; + config: SystemConfigDto; + disabled?: boolean; + onReset: SettingsResetEvent; + onSave: SettingsSaveEvent; + } + + let { savedConfig, defaultConfig, config = $bindable(), disabled = false, onReset, onSave }: Props = $props(); + + const onsubmit = (event: Event) => { + event.preventDefault(); + };
- +
{ + event.preventDefault(); + };
- +
- +
+ {#each config.machineLearning.urls as _, i} + {#snippet removeButton()} + {#if config.machineLearning.urls.length > 1} + config.machineLearning.urls.splice(i, 1)} + icon={mdiMinusCircle} + /> + {/if} + {/snippet} + + + {/each} +
+ +
-

- - {message} - -

+ {#snippet descriptionSnippet()} +

+ + {#snippet children({ message })} + {message} + {/snippet} + +

+ {/snippet}
@@ -100,7 +141,7 @@ step="0.0005" min={0.001} max={0.1} - desc={$t('admin.machine_learning_max_detection_distance_description')} + description={$t('admin.machine_learning_max_detection_distance_description')} disabled={disabled || !$featureFlags.duplicateDetection} isEdited={config.machineLearning.duplicateDetection.maxDistance !== savedConfig.machineLearning.duplicateDetection.maxDistance} @@ -142,7 +183,7 @@ { + event.preventDefault(); + };
- +
@@ -38,7 +45,7 @@ - + {#snippet subtitleSnippet()}

- - - {message} - + + {#snippet children({ message })} + + {message} + + {/snippet}

-
+ {/snippet}
{ + event.preventDefault(); + };
- +
{ + event.preventDefault(); + };
- +
{ if (isSending) { @@ -65,11 +69,15 @@ isSending = false; } }; + + const onsubmit = (event: Event) => { + event.preventDefault(); + };
- +
@@ -85,7 +93,7 @@ inputType={SettingInputFieldType.TEXT} required label={$t('host')} - desc={$t('admin.notification_email_host_description')} + description={$t('admin.notification_email_host_description')} disabled={disabled || !config.notifications.smtp.enabled} bind:value={config.notifications.smtp.transport.host} isEdited={config.notifications.smtp.transport.host !== savedConfig.notifications.smtp.transport.host} @@ -95,7 +103,7 @@ inputType={SettingInputFieldType.NUMBER} required label={$t('port')} - desc={$t('admin.notification_email_port_description')} + description={$t('admin.notification_email_port_description')} disabled={disabled || !config.notifications.smtp.enabled} bind:value={config.notifications.smtp.transport.port} isEdited={config.notifications.smtp.transport.port !== savedConfig.notifications.smtp.transport.port} @@ -104,7 +112,7 @@
-
- - onReset({ ...options, configKeys: ['notifications'] })} - onSave={() => onSave({ notifications: config.notifications })} - showResetToDefault={!isEqual(savedConfig, defaultConfig)} - {disabled} - />
+ + + onReset({ ...options, configKeys: ['notifications', 'templates'] })} + onSave={() => onSave({ notifications: config.notifications, templates: config.templates })} + showResetToDefault={!isEqual(savedConfig, defaultConfig)} + {disabled} + />
diff --git a/web/src/lib/components/admin-page/settings/server/server-settings.svelte b/web/src/lib/components/admin-page/settings/server/server-settings.svelte index f021c99f24a1c..b9134d1e5072a 100644 --- a/web/src/lib/components/admin-page/settings/server/server-settings.svelte +++ b/web/src/lib/components/admin-page/settings/server/server-settings.svelte @@ -3,28 +3,36 @@ import { isEqual } from 'lodash-es'; import { fade } from 'svelte/transition'; import type { SettingsResetEvent, SettingsSaveEvent } from '../admin-settings'; - import SettingInputField, { - SettingInputFieldType, - } from '$lib/components/shared-components/settings/setting-input-field.svelte'; + import SettingInputField from '$lib/components/shared-components/settings/setting-input-field.svelte'; import SettingButtonsRow from '$lib/components/shared-components/settings/setting-buttons-row.svelte'; + import SettingSwitch from '$lib/components/shared-components/settings/setting-switch.svelte'; import { t } from 'svelte-i18n'; + import { SettingInputFieldType } from '$lib/constants'; - export let savedConfig: SystemConfigDto; - export let defaultConfig: SystemConfigDto; - export let config: SystemConfigDto; // this is the config that is being edited - export let disabled = false; - export let onReset: SettingsResetEvent; - export let onSave: SettingsSaveEvent; + interface Props { + savedConfig: SystemConfigDto; + defaultConfig: SystemConfigDto; + config: SystemConfigDto; + disabled?: boolean; + onReset: SettingsResetEvent; + onSave: SettingsSaveEvent; + } + + let { savedConfig, defaultConfig, config = $bindable(), disabled = false, onReset, onSave }: Props = $props(); + + const onsubmit = (event: Event) => { + event.preventDefault(); + };
-
+
@@ -32,11 +40,18 @@ + +
onReset({ ...options, configKeys: ['server'] })} diff --git a/web/src/lib/components/admin-page/settings/storage-template/storage-template-settings.svelte b/web/src/lib/components/admin-page/settings/storage-template/storage-template-settings.svelte index 4ebf4ed118d89..74d240a4a6a8a 100644 --- a/web/src/lib/components/admin-page/settings/storage-template/storage-template-settings.svelte +++ b/web/src/lib/components/admin-page/settings/storage-template/storage-template-settings.svelte @@ -1,6 +1,9 @@

- - {#if tag === 'template-link'} - - {message} - - {:else if tag === 'implications-link'} - - {message} - - {/if} + + {#snippet children({ tag, message })} + {#if tag === 'template-link'} + + {message} + + {:else if tag === 'implications-link'} + + {message} + + {/if} + {/snippet}

@@ -164,19 +186,18 @@ - {message} + {#snippet children({ message })} + {message} + {/snippet}

- - {message} + + {#snippet children({ message })} + {message} + {/snippet}

@@ -186,24 +207,30 @@ >/{parsedTemplate()}.jpg

- +
- - + {#if templateOptions} + + + {/if}
+
- - {message} - + {#snippet children({ message })} + + {message} + + {/snippet}

@@ -247,7 +275,7 @@ {/if} {#if minified} - + {@render children?.()} {:else} onReset({ ...options, configKeys: ['storageTemplate'] })} diff --git a/web/src/lib/components/admin-page/settings/storage-template/supported-datetime-panel.svelte b/web/src/lib/components/admin-page/settings/storage-template/supported-datetime-panel.svelte index 10f22c18057f3..379e366df60f1 100644 --- a/web/src/lib/components/admin-page/settings/storage-template/supported-datetime-panel.svelte +++ b/web/src/lib/components/admin-page/settings/storage-template/supported-datetime-panel.svelte @@ -4,7 +4,11 @@ import { DateTime } from 'luxon'; import { t } from 'svelte-i18n'; - export let options: SystemConfigTemplateStorageOptionDto; + interface Props { + options: SystemConfigTemplateStorageOptionDto; + } + + let { options }: Props = $props(); const getLuxonExample = (format: string) => { return DateTime.fromISO('2022-09-04T20:03:05.250Z', { locale: $locale }).toFormat(format); diff --git a/web/src/lib/components/admin-page/settings/template-settings/template-settings.svelte b/web/src/lib/components/admin-page/settings/template-settings/template-settings.svelte new file mode 100644 index 0000000000000..c27df817c2914 --- /dev/null +++ b/web/src/lib/components/admin-page/settings/template-settings/template-settings.svelte @@ -0,0 +1,131 @@ + + +
+
+ +
+ +
+

+ + {$t('admin.template_email_if_empty')} + +

+
+ {#if loadingPreview} + + {/if} + + {#each templateConfigs as { label, templateKey, descriptionTags, templateName }} + +
+ +
+ {/each} +
+
+
+ + {#if htmlPreview} + +
+ +
+
+ {/if} + +
+
diff --git a/web/src/lib/components/admin-page/settings/theme/theme-settings.svelte b/web/src/lib/components/admin-page/settings/theme/theme-settings.svelte index 84a12e05c9674..79b5f838e3d0b 100644 --- a/web/src/lib/components/admin-page/settings/theme/theme-settings.svelte +++ b/web/src/lib/components/admin-page/settings/theme/theme-settings.svelte @@ -7,24 +7,31 @@ import SettingButtonsRow from '$lib/components/shared-components/settings/setting-buttons-row.svelte'; import { t } from 'svelte-i18n'; - export let savedConfig: SystemConfigDto; - export let defaultConfig: SystemConfigDto; - export let config: SystemConfigDto; // this is the config that is being edited - export let disabled = false; - export let onReset: SettingsResetEvent; - export let onSave: SettingsSaveEvent; + interface Props { + savedConfig: SystemConfigDto; + defaultConfig: SystemConfigDto; + config: SystemConfigDto; + disabled?: boolean; + onReset: SettingsResetEvent; + onSave: SettingsSaveEvent; + } + + let { savedConfig, defaultConfig, config = $bindable(), disabled = false, onReset, onSave }: Props = $props(); + + const onsubmit = (event: Event) => { + event.preventDefault(); + };
-
+
diff --git a/web/src/lib/components/admin-page/settings/trash-settings/trash-settings.svelte b/web/src/lib/components/admin-page/settings/trash-settings/trash-settings.svelte index 8f287d48e04ed..05979bf9f037d 100644 --- a/web/src/lib/components/admin-page/settings/trash-settings/trash-settings.svelte +++ b/web/src/lib/components/admin-page/settings/trash-settings/trash-settings.svelte @@ -4,23 +4,30 @@ import { fade } from 'svelte/transition'; import type { SettingsResetEvent, SettingsSaveEvent } from '../admin-settings'; import SettingSwitch from '$lib/components/shared-components/settings/setting-switch.svelte'; - import SettingInputField, { - SettingInputFieldType, - } from '$lib/components/shared-components/settings/setting-input-field.svelte'; + import SettingInputField from '$lib/components/shared-components/settings/setting-input-field.svelte'; import SettingButtonsRow from '$lib/components/shared-components/settings/setting-buttons-row.svelte'; import { t } from 'svelte-i18n'; + import { SettingInputFieldType } from '$lib/constants'; - export let savedConfig: SystemConfigDto; - export let defaultConfig: SystemConfigDto; - export let config: SystemConfigDto; // this is the config that is being edited - export let disabled = false; - export let onReset: SettingsResetEvent; - export let onSave: SettingsSaveEvent; + interface Props { + savedConfig: SystemConfigDto; + defaultConfig: SystemConfigDto; + config: SystemConfigDto; + disabled?: boolean; + onReset: SettingsResetEvent; + onSave: SettingsSaveEvent; + } + + let { savedConfig, defaultConfig, config = $bindable(), disabled = false, onReset, onSave }: Props = $props(); + + const onsubmit = (event: Event) => { + event.preventDefault(); + };
- +
@@ -29,7 +36,7 @@
- + e.preventDefault()}>
diff --git a/web/src/lib/components/album-page/__tests__/album-card.spec.ts b/web/src/lib/components/album-page/__tests__/album-card.spec.ts index 8da9fbfd4591f..9e396bec3ecc8 100644 --- a/web/src/lib/components/album-page/__tests__/album-card.spec.ts +++ b/web/src/lib/components/album-page/__tests__/album-card.spec.ts @@ -1,14 +1,15 @@ import { sdkMock } from '$lib/__mocks__/sdk.mock'; import { albumFactory } from '@test-data/factories/album-factory'; import '@testing-library/jest-dom'; -import { fireEvent, render, waitFor, type RenderResult } from '@testing-library/svelte'; +import { render, waitFor, type RenderResult } from '@testing-library/svelte'; +import userEvent from '@testing-library/user-event'; import { init, register, waitLocale } from 'svelte-i18n'; import AlbumCard from '../album-card.svelte'; const onShowContextMenu = vi.fn(); describe('AlbumCard component', () => { - let sut: RenderResult; + let sut: RenderResult; beforeAll(async () => { await init({ fallbackLocale: 'en-US' }); @@ -110,13 +111,9 @@ describe('AlbumCard component', () => { toJSON: () => ({}), }); - await fireEvent( - contextMenuButton, - new MouseEvent('click', { - clientX: 123, - clientY: 456, - }), - ); + const user = userEvent.setup(); + await user.click(contextMenuButton); + expect(onShowContextMenu).toHaveBeenCalledTimes(1); expect(onShowContextMenu).toHaveBeenCalledWith(expect.objectContaining({ x: 123, y: 456 })); }); diff --git a/web/src/lib/components/album-page/album-card-group.svelte b/web/src/lib/components/album-page/album-card-group.svelte index f899cebd8c430..ae2b27efac1da 100644 --- a/web/src/lib/components/album-page/album-card-group.svelte +++ b/web/src/lib/components/album-page/album-card-group.svelte @@ -11,28 +11,43 @@ import Icon from '$lib/components/elements/icon.svelte'; import { t } from 'svelte-i18n'; - export let albums: AlbumResponseDto[]; - export let group: AlbumGroup | undefined = undefined; - export let showOwner = false; - export let showDateRange = false; - export let showItemCount = false; - export let onShowContextMenu: ((position: ContextMenuPosition, album: AlbumResponseDto) => unknown) | undefined = - undefined; + interface Props { + albums: AlbumResponseDto[]; + group?: AlbumGroup | undefined; + showOwner?: boolean; + showDateRange?: boolean; + showItemCount?: boolean; + onShowContextMenu?: ((position: ContextMenuPosition, album: AlbumResponseDto) => unknown) | undefined; + } - $: isCollapsed = !!group && isAlbumGroupCollapsed($albumViewSettings, group.id); + let { + albums, + group = undefined, + showOwner = false, + showDateRange = false, + showItemCount = false, + onShowContextMenu = undefined, + }: Props = $props(); + + let isCollapsed = $derived(!!group && isAlbumGroupCollapsed($albumViewSettings, group.id)); const showContextMenu = (position: ContextMenuPosition, album: AlbumResponseDto) => { onShowContextMenu?.(position, album); }; - $: iconRotation = isCollapsed ? 'rotate-0' : 'rotate-90'; + let iconRotation = $derived(isCollapsed ? 'rotate-0' : 'rotate-90'); + + const oncontextmenu = (event: MouseEvent, album: AlbumResponseDto) => { + event.preventDefault(); + showContextMenu({ x: event.x, y: event.y }, album); + }; {#if group}
{/if} diff --git a/web/src/lib/components/album-page/album-cover.svelte b/web/src/lib/components/album-page/album-cover.svelte index d0444f35990e2..3f71bbe632c9f 100644 --- a/web/src/lib/components/album-page/album-cover.svelte +++ b/web/src/lib/components/album-page/album-cover.svelte @@ -5,13 +5,18 @@ import AssetCover from '$lib/components/sharedlinks-page/covers/asset-cover.svelte'; import { t } from 'svelte-i18n'; - export let album: AlbumResponseDto; - export let preload = false; - let className = ''; - export { className as class }; + interface Props { + album: AlbumResponseDto; + preload?: boolean; + class?: string; + } - $: alt = album.albumName || $t('unnamed_album'); - $: thumbnailUrl = album.albumThumbnailAssetId ? getAssetThumbnailUrl({ id: album.albumThumbnailAssetId }) : null; + let { album, preload = false, class: className = '' }: Props = $props(); + + let alt = $derived(album.albumName || $t('unnamed_album')); + let thumbnailUrl = $derived( + album.albumThumbnailAssetId ? getAssetThumbnailUrl({ id: album.albumThumbnailAssetId }) : null, + ); {#if thumbnailUrl} diff --git a/web/src/lib/components/album-page/album-description.svelte b/web/src/lib/components/album-page/album-description.svelte index b3ad688a30512..46b424f93ae0d 100644 --- a/web/src/lib/components/album-page/album-description.svelte +++ b/web/src/lib/components/album-page/album-description.svelte @@ -4,9 +4,13 @@ import AutogrowTextarea from '$lib/components/shared-components/autogrow-textarea.svelte'; import { t } from 'svelte-i18n'; - export let id: string; - export let description: string; - export let isOwned: boolean; + interface Props { + id: string; + description: string; + isOwned: boolean; + } + + let { id, description = $bindable(), isOwned }: Props = $props(); const handleUpdateDescription = async (newDescription: string) => { try { diff --git a/web/src/lib/components/album-page/album-options.svelte b/web/src/lib/components/album-page/album-options.svelte index 3ec1842757201..884de8c2a2b83 100644 --- a/web/src/lib/components/album-page/album-options.svelte +++ b/web/src/lib/components/album-page/album-options.svelte @@ -23,24 +23,38 @@ import { notificationController, NotificationType } from '../shared-components/notification/notification'; import MenuOption from '$lib/components/shared-components/context-menu/menu-option.svelte'; - export let album: AlbumResponseDto; - export let order: AssetOrder | undefined; - export let user: UserResponseDto; // Declare user as a prop - export let onChangeOrder: (order: AssetOrder) => void; - export let onClose: () => void; - export let onToggleEnabledActivity: () => void; - export let onShowSelectSharedUser: () => void; - export let onRemove: (userId: string) => void; - export let onRefreshAlbum: () => void; + interface Props { + album: AlbumResponseDto; + order: AssetOrder | undefined; + user: UserResponseDto; + onChangeOrder: (order: AssetOrder) => void; + onClose: () => void; + onToggleEnabledActivity: () => void; + onShowSelectSharedUser: () => void; + onRemove: (userId: string) => void; + onRefreshAlbum: () => void; + } - let selectedRemoveUser: UserResponseDto | null = null; + let { + album, + order, + user, + onChangeOrder, + onClose, + onToggleEnabledActivity, + onShowSelectSharedUser, + onRemove, + onRefreshAlbum, + }: Props = $props(); + + let selectedRemoveUser: UserResponseDto | null = $state(null); const options: Record = { [AssetOrder.Asc]: { icon: mdiArrowUpThin, title: $t('oldest_first') }, [AssetOrder.Desc]: { icon: mdiArrowDownThin, title: $t('newest_first') }, }; - $: selectedOption = order ? options[order] : options[AssetOrder.Desc]; + let selectedOption = $derived(order ? options[order] : options[AssetOrder.Desc]); const handleToggle = async (returnedOption: RenderedOption): Promise => { if (selectedOption === returnedOption) { @@ -125,7 +139,7 @@
{$t('people').toUpperCase()}
-
- createAlbumAndRedirect()}> + createAlbumAndRedirect()}>
@@ -179,7 +164,7 @@