Compare commits
184 Commits
v1.120.2
...
feat/docke
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
23373f39cb | ||
|
|
34ce61d03a | ||
|
|
0250a7a23a | ||
|
|
b91f39d1af | ||
|
|
139090715e | ||
|
|
05cea0fc69 | ||
|
|
2255f3e966 | ||
|
|
2be1cb7de2 | ||
|
|
227eb4b0a6 | ||
|
|
23461e98fb | ||
|
|
ef0070c3fd | ||
|
|
6b08e82cf7 | ||
|
|
b88f98bf66 | ||
|
|
c3be74c450 | ||
|
|
4bc2aa5451 | ||
|
|
6080e6e827 | ||
|
|
d5906c2efe | ||
|
|
b3821c50d7 | ||
|
|
1cec3af98c | ||
|
|
da70a1e457 | ||
|
|
a14735846c | ||
|
|
79a780e8d9 | ||
|
|
556c59f12f | ||
|
|
8e724c3c27 | ||
|
|
207bb527bb | ||
|
|
b034cb1861 | ||
|
|
6a855f6331 | ||
|
|
a03f4f5610 | ||
|
|
e0fc8734bf | ||
|
|
0d060ebb32 | ||
|
|
f58b2572e6 | ||
|
|
fd34a914a6 | ||
|
|
b81470a383 | ||
|
|
6f3b6365e5 | ||
|
|
2948b9ed29 | ||
|
|
a2dd9622a3 | ||
|
|
c7b44bef81 | ||
|
|
95f300f8d2 | ||
|
|
9503bf479b | ||
|
|
364b717fde | ||
|
|
f180ae70f9 | ||
|
|
4edeed9739 | ||
|
|
e52774553f | ||
|
|
12e55f5bf0 | ||
|
|
8945a5d862 | ||
|
|
6b0f9ec46c | ||
|
|
fe554c3a5b | ||
|
|
dd9feeec45 | ||
|
|
cc111a1fcb | ||
|
|
b5022d80d6 | ||
|
|
525840b040 | ||
|
|
bccf2f60b2 | ||
|
|
39732f3371 | ||
|
|
40a0bf6ad5 | ||
|
|
6abe696d0b | ||
|
|
59d6af54c7 | ||
|
|
58d63d9f1c | ||
|
|
11be85feb3 | ||
|
|
c52f1bae81 | ||
|
|
0c03753642 | ||
|
|
71b48b11e6 | ||
|
|
3053d84e49 | ||
|
|
e40c7c51ee | ||
|
|
11f585d0ad | ||
|
|
5814a1b223 | ||
|
|
bcc438eafb | ||
|
|
7cae25c28b | ||
|
|
f6909a3b11 | ||
|
|
70b4647a21 | ||
|
|
345f918784 | ||
|
|
9eff1c4b34 | ||
|
|
25ca3b1124 | ||
|
|
60c783bbe9 | ||
|
|
1ba622adc9 | ||
|
|
e4b76e8efe | ||
|
|
03eb5903fe | ||
|
|
04b311bd93 | ||
|
|
e99edc47b7 | ||
|
|
5e955a1b03 | ||
|
|
e2b36476e7 | ||
|
|
c02e3e2a2e | ||
|
|
97c1eb7289 | ||
|
|
07096bdcee | ||
|
|
d36477381a | ||
|
|
4380ecf7bb | ||
|
|
37220a342a | ||
|
|
5e662e4a93 | ||
|
|
bb0242ae0a | ||
|
|
055f1fc72f | ||
|
|
3c38851d50 | ||
|
|
5060ee95c2 | ||
|
|
292182fa7f | ||
|
|
4bf1b84cc2 | ||
|
|
411878c0aa | ||
|
|
ba9b9353bc | ||
|
|
52247c3650 | ||
|
|
ba71fd42da | ||
|
|
1bb6926b5e | ||
|
|
4eb7758f56 | ||
|
|
56d2309122 | ||
|
|
3d61548d7d | ||
|
|
b4c96a09fb | ||
|
|
21f14be949 | ||
|
|
5417e34fb6 | ||
|
|
b6ec79cbdd | ||
|
|
25488b3138 | ||
|
|
361d83c729 | ||
|
|
d277096d58 | ||
|
|
51de108d43 | ||
|
|
ca37a13b25 | ||
|
|
447ff6fcb3 | ||
|
|
b9e98d2706 | ||
|
|
c33b918d74 | ||
|
|
454836b551 | ||
|
|
6d492985a2 | ||
|
|
1c82804f63 | ||
|
|
1935b88d13 | ||
|
|
e8da6604c9 | ||
|
|
45ba0cc3ac | ||
|
|
689c6aa276 | ||
|
|
6ec94f94f1 | ||
|
|
9a9d40c193 | ||
|
|
9e1e9b1fbf | ||
|
|
ed8a3101a8 | ||
|
|
876893c823 | ||
|
|
c6e1dbec5c | ||
|
|
f40269bc3e | ||
|
|
95297cd024 | ||
|
|
b6937c5e03 | ||
|
|
98c9ae1f7d | ||
|
|
1d8673eb3b | ||
|
|
026482099a | ||
|
|
c17c174149 | ||
|
|
cfba7f7701 | ||
|
|
ad510dd6fd | ||
|
|
a3712e40bd | ||
|
|
34fae31fd4 | ||
|
|
f8bbc6eabe | ||
|
|
69e50d0d27 | ||
|
|
3a2e30e30e | ||
|
|
53940f7d42 | ||
|
|
b66c53bef3 | ||
|
|
1737013e66 | ||
|
|
bcd17c2ebe | ||
|
|
b031a8cac1 | ||
|
|
41f138d3c8 | ||
|
|
6b5defc27b | ||
|
|
2604940f09 | ||
|
|
32f908baf1 | ||
|
|
944ea7dbcd | ||
|
|
4b5657c21e | ||
|
|
f5c4af73aa | ||
|
|
24ae4ecff1 | ||
|
|
64a7baec8c | ||
|
|
caf6c0996d | ||
|
|
6729782c3f | ||
|
|
a60209db3e | ||
|
|
d1169e3b2f | ||
|
|
df972ef711 | ||
|
|
33263cf9f3 | ||
|
|
1b5811d992 | ||
|
|
1fa0122eda | ||
|
|
d1085e8a02 | ||
|
|
d6a70bc7e5 | ||
|
|
d3fe238eef | ||
|
|
35f24270fe | ||
|
|
1f1a4ab1a3 | ||
|
|
0b3742cf13 | ||
|
|
9203a61709 | ||
|
|
11403abfbc | ||
|
|
5a2af558fb | ||
|
|
de993289ad | ||
|
|
c58bd307ce | ||
|
|
333ca8827e | ||
|
|
3dad19883d | ||
|
|
4ca27a3e7f | ||
|
|
b0bb11f9e0 | ||
|
|
ecb8349085 | ||
|
|
e1feba2198 | ||
|
|
53a7ac3868 | ||
|
|
f2e950d89c | ||
|
|
8ba2c99b08 | ||
|
|
93346496fc | ||
|
|
a9525de356 |
2
.devcontainer/Dockerfile
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
ARG BASEIMAGE=mcr.microsoft.com/devcontainers/typescript-node:22@sha256:9791f4aa527774bc370c6bd2f6705ce5a686f1e6f204badd8dfaacce28c631ae
|
||||||
|
FROM ${BASEIMAGE}
|
||||||
20
.devcontainer/devcontainer.json
Normal file
@@ -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"
|
||||||
|
}
|
||||||
|
|
||||||
4
.github/workflows/cli.yml
vendored
@@ -59,7 +59,7 @@ jobs:
|
|||||||
uses: docker/setup-qemu-action@v3.2.0
|
uses: docker/setup-qemu-action@v3.2.0
|
||||||
|
|
||||||
- name: Set up Docker Buildx
|
- 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
|
- name: Login to GitHub Container Registry
|
||||||
uses: docker/login-action@v3
|
uses: docker/login-action@v3
|
||||||
@@ -88,7 +88,7 @@ jobs:
|
|||||||
type=raw,value=latest,enable=${{ github.event_name == 'release' }}
|
type=raw,value=latest,enable=${{ github.event_name == 'release' }}
|
||||||
|
|
||||||
- name: Build and push image
|
- name: Build and push image
|
||||||
uses: docker/build-push-action@v6.9.0
|
uses: docker/build-push-action@v6.10.0
|
||||||
with:
|
with:
|
||||||
file: cli/Dockerfile
|
file: cli/Dockerfile
|
||||||
platforms: linux/amd64,linux/arm64
|
platforms: linux/amd64,linux/arm64
|
||||||
|
|||||||
8
.github/workflows/docker.yml
vendored
@@ -125,7 +125,7 @@ jobs:
|
|||||||
uses: docker/setup-qemu-action@v3.2.0
|
uses: docker/setup-qemu-action@v3.2.0
|
||||||
|
|
||||||
- name: Set up Docker Buildx
|
- 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
|
- name: Login to Docker Hub
|
||||||
# Only push to Docker Hub when making a release
|
# Only push to Docker Hub when making a release
|
||||||
@@ -174,7 +174,7 @@ jobs:
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
- name: Build and push image
|
- name: Build and push image
|
||||||
uses: docker/build-push-action@v6.9.0
|
uses: docker/build-push-action@v6.10.0
|
||||||
with:
|
with:
|
||||||
context: ${{ env.context }}
|
context: ${{ env.context }}
|
||||||
file: ${{ env.file }}
|
file: ${{ env.file }}
|
||||||
@@ -216,7 +216,7 @@ jobs:
|
|||||||
uses: docker/setup-qemu-action@v3.2.0
|
uses: docker/setup-qemu-action@v3.2.0
|
||||||
|
|
||||||
- name: Set up Docker Buildx
|
- 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
|
- name: Login to Docker Hub
|
||||||
# Only push to Docker Hub when making a release
|
# Only push to Docker Hub when making a release
|
||||||
@@ -265,7 +265,7 @@ jobs:
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
- name: Build and push image
|
- name: Build and push image
|
||||||
uses: docker/build-push-action@v6.9.0
|
uses: docker/build-push-action@v6.10.0
|
||||||
with:
|
with:
|
||||||
context: ${{ env.context }}
|
context: ${{ env.context }}
|
||||||
file: ${{ env.file }}
|
file: ${{ env.file }}
|
||||||
|
|||||||
1
.github/workflows/pr-label-validation.yml
vendored
@@ -19,3 +19,4 @@ jobs:
|
|||||||
use_regex: true
|
use_regex: true
|
||||||
labels: "changelog:.*"
|
labels: "changelog:.*"
|
||||||
add_comment: true
|
add_comment: true
|
||||||
|
message: "Label error. Requires {{errorString}} {{count}} of: {{ provided }}. Found: {{ applied }}. A maintainer will add the required label."
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: PR Conventional Commit Validation
|
- name: PR Conventional Commit Validation
|
||||||
uses: ytanikin/PRConventionalCommits@1.2.0
|
uses: ytanikin/PRConventionalCommits@1.3.0
|
||||||
with:
|
with:
|
||||||
task_types: '["feat","fix","docs","test","ci","refactor","perf","chore","revert"]'
|
task_types: '["feat","fix","docs","test","ci","refactor","perf","chore","revert"]'
|
||||||
add_label: 'false'
|
add_label: 'false'
|
||||||
|
|||||||
2
.vscode/settings.json
vendored
@@ -41,4 +41,4 @@
|
|||||||
"explorer.fileNesting.patterns": {
|
"explorer.fileNesting.patterns": {
|
||||||
"*.ts": "${capture}.spec.ts,${capture}.mock.ts"
|
"*.ts": "${capture}.spec.ts,${capture}.mock.ts"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
18
Makefile
@@ -39,7 +39,7 @@ attach-server:
|
|||||||
renovate:
|
renovate:
|
||||||
LOG_LEVEL=debug npx renovate --platform=local --repository-cache=reset
|
LOG_LEVEL=debug npx renovate --platform=local --repository-cache=reset
|
||||||
|
|
||||||
MODULES = e2e server web cli sdk
|
MODULES = e2e server web cli sdk docs
|
||||||
|
|
||||||
audit-%:
|
audit-%:
|
||||||
npm --prefix $(subst sdk,open-api/typescript-sdk,$*) audit fix
|
npm --prefix $(subst sdk,open-api/typescript-sdk,$*) audit fix
|
||||||
@@ -48,11 +48,9 @@ install-%:
|
|||||||
build-cli: build-sdk
|
build-cli: build-sdk
|
||||||
build-web: build-sdk
|
build-web: build-sdk
|
||||||
build-%: install-%
|
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
|
||||||
&& npm --prefix $(subst sdk,open-api/typescript-sdk,$*) run build || true
|
|
||||||
format-%:
|
format-%:
|
||||||
npm --prefix $(subst sdk,open-api/typescript-sdk,$*) run | grep 'format:fix' >/dev/null \
|
npm --prefix $* run format:fix
|
||||||
&& npm --prefix $(subst sdk,open-api/typescript-sdk,$*) run format:fix || true
|
|
||||||
lint-%:
|
lint-%:
|
||||||
npm --prefix $* run lint:fix
|
npm --prefix $* run lint:fix
|
||||||
check-%:
|
check-%:
|
||||||
@@ -79,14 +77,14 @@ test-medium:
|
|||||||
test-medium-dev:
|
test-medium-dev:
|
||||||
docker exec -it immich_server /bin/sh -c "npm run test:medium"
|
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) ;
|
install-all: $(foreach M,$(MODULES),install-$M) ;
|
||||||
check-all: $(foreach M,$(MODULES),check-$M) ;
|
check-all: $(foreach M,$(filter-out sdk cli docs,$(MODULES)),check-$M) ;
|
||||||
lint-all: $(foreach M,$(MODULES),lint-$M) ;
|
lint-all: $(foreach M,$(filter-out sdk docs,$(MODULES)),lint-$M) ;
|
||||||
format-all: $(foreach M,$(MODULES),format-$M) ;
|
format-all: $(foreach M,$(filter-out sdk,$(MODULES)),format-$M) ;
|
||||||
audit-all: $(foreach M,$(MODULES),audit-$M) ;
|
audit-all: $(foreach M,$(MODULES),audit-$M) ;
|
||||||
hygiene-all: lint-all format-all check-all sql audit-all;
|
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:
|
clean:
|
||||||
find . -name "node_modules" -type d -prune -exec rm -rf '{}' +
|
find . -name "node_modules" -type d -prune -exec rm -rf '{}' +
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
22.11.0
|
22.12.0
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
FROM node:22.11.0-alpine3.20@sha256:dc8ba2f61dd86c44e43eb25a7812ad03c5b1b224a19fc6f77e1eb9e5669f0b82 AS core
|
FROM node:22.12.0-alpine3.20@sha256:96cc8323e25c8cc6ddcb8b965e135cfd57846e8003ec0d7bcec16c5fd5f6d39f AS core
|
||||||
|
|
||||||
WORKDIR /usr/src/open-api/typescript-sdk
|
WORKDIR /usr/src/open-api/typescript-sdk
|
||||||
COPY open-api/typescript-sdk/package*.json open-api/typescript-sdk/tsconfig*.json ./
|
COPY open-api/typescript-sdk/package*.json open-api/typescript-sdk/tsconfig*.json ./
|
||||||
|
|||||||
510
cli/package-lock.json
generated
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@immich/cli",
|
"name": "@immich/cli",
|
||||||
"version": "2.2.31",
|
"version": "2.2.37",
|
||||||
"description": "Command Line Interface (CLI) for Immich",
|
"description": "Command Line Interface (CLI) for Immich",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"exports": "./dist/index.js",
|
"exports": "./dist/index.js",
|
||||||
@@ -20,17 +20,17 @@
|
|||||||
"@types/cli-progress": "^3.11.0",
|
"@types/cli-progress": "^3.11.0",
|
||||||
"@types/lodash-es": "^4.17.12",
|
"@types/lodash-es": "^4.17.12",
|
||||||
"@types/mock-fs": "^4.13.1",
|
"@types/mock-fs": "^4.13.1",
|
||||||
"@types/node": "^22.9.0",
|
"@types/node": "^22.10.2",
|
||||||
"@typescript-eslint/eslint-plugin": "^8.0.0",
|
"@typescript-eslint/eslint-plugin": "^8.15.0",
|
||||||
"@typescript-eslint/parser": "^8.0.0",
|
"@typescript-eslint/parser": "^8.15.0",
|
||||||
"@vitest/coverage-v8": "^2.0.5",
|
"@vitest/coverage-v8": "^2.0.5",
|
||||||
"byte-size": "^9.0.0",
|
"byte-size": "^9.0.0",
|
||||||
"cli-progress": "^3.12.0",
|
"cli-progress": "^3.12.0",
|
||||||
"commander": "^12.0.0",
|
"commander": "^12.0.0",
|
||||||
"eslint": "^9.0.0",
|
"eslint": "^9.14.0",
|
||||||
"eslint-config-prettier": "^9.1.0",
|
"eslint-config-prettier": "^9.1.0",
|
||||||
"eslint-plugin-prettier": "^5.1.3",
|
"eslint-plugin-prettier": "^5.1.3",
|
||||||
"eslint-plugin-unicorn": "^55.0.0",
|
"eslint-plugin-unicorn": "^56.0.1",
|
||||||
"globals": "^15.9.0",
|
"globals": "^15.9.0",
|
||||||
"mock-fs": "^5.2.0",
|
"mock-fs": "^5.2.0",
|
||||||
"prettier": "^3.2.5",
|
"prettier": "^3.2.5",
|
||||||
@@ -67,6 +67,6 @@
|
|||||||
"lodash-es": "^4.17.21"
|
"lodash-es": "^4.17.21"
|
||||||
},
|
},
|
||||||
"volta": {
|
"volta": {
|
||||||
"node": "22.11.0"
|
"node": "22.12.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import {
|
import {
|
||||||
Action,
|
Action,
|
||||||
|
AssetBulkUploadCheckItem,
|
||||||
AssetBulkUploadCheckResult,
|
AssetBulkUploadCheckResult,
|
||||||
AssetMediaResponseDto,
|
AssetMediaResponseDto,
|
||||||
AssetMediaStatus,
|
AssetMediaStatus,
|
||||||
@@ -11,7 +12,7 @@ import {
|
|||||||
getSupportedMediaTypes,
|
getSupportedMediaTypes,
|
||||||
} from '@immich/sdk';
|
} from '@immich/sdk';
|
||||||
import byteSize from 'byte-size';
|
import byteSize from 'byte-size';
|
||||||
import { Presets, SingleBar } from 'cli-progress';
|
import { MultiBar, Presets, SingleBar } from 'cli-progress';
|
||||||
import { chunk } from 'lodash-es';
|
import { chunk } from 'lodash-es';
|
||||||
import { Stats, createReadStream } from 'node:fs';
|
import { Stats, createReadStream } from 'node:fs';
|
||||||
import { stat, unlink } from 'node:fs/promises';
|
import { stat, unlink } from 'node:fs/promises';
|
||||||
@@ -90,23 +91,23 @@ export const checkForDuplicates = async (files: string[], { concurrency, skipHas
|
|||||||
return { newFiles: files, duplicates: [] };
|
return { newFiles: files, duplicates: [] };
|
||||||
}
|
}
|
||||||
|
|
||||||
const progressBar = new SingleBar(
|
const multiBar = new MultiBar(
|
||||||
{ format: 'Checking files | {bar} | {percentage}% | ETA: {eta}s | {value}/{total} assets' },
|
{ format: '{message} | {bar} | {percentage}% | ETA: {eta}s | {value}/{total} assets' },
|
||||||
Presets.shades_classic,
|
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 newFiles: string[] = [];
|
||||||
const duplicates: Asset[] = [];
|
const duplicates: Asset[] = [];
|
||||||
|
|
||||||
const queue = new Queue<string[], AssetBulkUploadCheckResults>(
|
const checkBulkUploadQueue = new Queue<AssetBulkUploadCheckItem[], void>(
|
||||||
async (filepaths: string[]) => {
|
async (assets: AssetBulkUploadCheckItem[]) => {
|
||||||
const dto = await Promise.all(
|
const response = await checkBulkUpload({ assetBulkUploadCheckDto: { assets } });
|
||||||
filepaths.map(async (filepath) => ({ id: filepath, checksum: await sha1(filepath) })),
|
|
||||||
);
|
|
||||||
const response = await checkBulkUpload({ assetBulkUploadCheckDto: { assets: dto } });
|
|
||||||
const results = response.results as AssetBulkUploadCheckResults;
|
const results = response.results as AssetBulkUploadCheckResults;
|
||||||
|
|
||||||
for (const { id: filepath, assetId, action } of results) {
|
for (const { id: filepath, assetId, action } of results) {
|
||||||
if (action === Action.Accept) {
|
if (action === Action.Accept) {
|
||||||
newFiles.push(filepath);
|
newFiles.push(filepath);
|
||||||
@@ -115,19 +116,46 @@ export const checkForDuplicates = async (files: string[], { concurrency, skipHas
|
|||||||
duplicates.push({ id: assetId as string, filepath });
|
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<string, AssetBulkUploadCheckItem[]>(
|
||||||
|
async (filepath: string): Promise<AssetBulkUploadCheckItem[]> => {
|
||||||
|
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;
|
return results;
|
||||||
},
|
},
|
||||||
{ concurrency, retry: 3 },
|
{ concurrency, retry: 3 },
|
||||||
);
|
);
|
||||||
|
|
||||||
for (const items of chunk(files, concurrency)) {
|
for (const item of files) {
|
||||||
await queue.push(items);
|
void queue.push(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
await queue.drained();
|
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)}`);
|
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 },
|
{ concurrency, retry: 3 },
|
||||||
);
|
);
|
||||||
|
|
||||||
for (const filepath of files) {
|
for (const item of files) {
|
||||||
await queue.push(filepath);
|
void queue.push(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
await queue.drained();
|
await queue.drained();
|
||||||
|
|||||||
@@ -72,8 +72,8 @@ export class Queue<T, R> {
|
|||||||
* @returns Promise<void> - The returned Promise will be resolved when all tasks in the queue have been processed by a worker.
|
* @returns Promise<void> - 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`.
|
* This promise could be ignored as it will not lead to a `unhandledRejection`.
|
||||||
*/
|
*/
|
||||||
async drained(): Promise<void> {
|
drained(): Promise<void> {
|
||||||
await this.queue.drain();
|
return this.queue.drained();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -2,37 +2,37 @@
|
|||||||
# Manual edits may be lost in future updates.
|
# Manual edits may be lost in future updates.
|
||||||
|
|
||||||
provider "registry.opentofu.org/cloudflare/cloudflare" {
|
provider "registry.opentofu.org/cloudflare/cloudflare" {
|
||||||
version = "4.45.0"
|
version = "4.48.0"
|
||||||
constraints = "4.45.0"
|
constraints = "4.48.0"
|
||||||
hashes = [
|
hashes = [
|
||||||
"h1:/CGpnYMkLRDmqn4iAsh/jg7ELZ6QExUw03VdjKZyK5M=",
|
"h1:0IKUOR32xEI1suS5QCOjfxjQ2mRd058btXk8hVnaOJ4=",
|
||||||
"h1:82C/ryqwQvxhBINYOOyF5ZzPW/k4zJ/RYT13eCdPgEc=",
|
"h1:3YG6vu/bFPcYOeLdSUZhiAWiWKaFlOAR34z2o8cbE9k=",
|
||||||
"h1:8Wu1D7ZwbLGdHakLRAzoAJ5VqZ8I14qzkPv1OGNfIlg=",
|
"h1:FvGy06/i9AMtVkSIUnCrXNv5xF6jqBqMH8oPVLyeeAg=",
|
||||||
"h1:CVq0CAibeueOuiNk0UQtwZvMLMof33n1BgskFPOymrk=",
|
"h1:GXH7nIF0ocMqebbA41+fSGIYfM+VAM/PvTe7fJr8UrQ=",
|
||||||
"h1:FSS5Kq+L+CX1zARy8PhaF8edBFNgsLtds4Uo8MwJiK8=",
|
"h1:H0ll0ph4404vFE868W3qJ3zhOyy4jbXrOMtdkViEZsU=",
|
||||||
"h1:L4qsorLII7f8xSFmv6JOoWfLWDunWQEpK964Bxk7mtM=",
|
"h1:SX42e3k73IcFcrQlZ2e/Veqt2tvCMy6fwlo5yNUktCE=",
|
||||||
"h1:StO3PV5PDskSCnhoHhWHOPxu6hbzJUQggfLgOSkvhwg=",
|
"h1:Uu/gjBc99GefdPdSrlBwU75DWU0ZcwGcrd3ZFyTeL0s=",
|
||||||
"h1:Tjo+Er9ets5YrTRIdP9LBmi4p89nL/W+A7r8a1MM9nI=",
|
"h1:VZw0uN41PWRmNlhg7Ze0Eh7cdoklX1oZbfNAXNYnU1I=",
|
||||||
"h1:XIwT+AWvks1LTytePM9zls+O8ItxoqCfPOgHwuH9ivQ=",
|
"h1:cMdV7ql6PsFa4qtb0EoZSctvTaTqV7yplBSDwcLRCLc=",
|
||||||
"h1:aOXn/zuM1+5GGy/SSRx8q4EYCSTFE9Tr0twHPIf5/KE=",
|
"h1:ePGvSurmlqOCkD761vkhRmz7bsK36/EnIvx2Xy8TdXo=",
|
||||||
"h1:lb+YcuZ4guYd8zE51vgSnDsRAD9IV00Z15l1i1X52s8=",
|
"h1:fOYufF+1bzw2N3aHLpkLB6E8VbZ4ysXDODYQOlwhwd4=",
|
||||||
"h1:pYwNXGjfXA2rUEmotGMLWgmavT9D2rdHnV3TpuIK3ko=",
|
"h1:qe8RbnWq0T4xhqjn9QcbO6YW5YDx47P+eJ0NUMIfwCc=",
|
||||||
"h1:q1qrnPq6KkljwBrugCwzb7f0SVP4Lzkfh+EOLARY9V8=",
|
"h1:tRD2av6PafHDP/b9jDQsG5/aX+lHeKxpbIEHYYLBVUc=",
|
||||||
"h1:v9sL4cZLTV5Gu2004DDyy7209gT0JmudBCAD0WCr/JE=",
|
"h1:zyl6Gvx/CFpwYW8pFFDesfO8Lxv+a6CopyAsIMhp54s=",
|
||||||
"zh:00be2a6adc76615a368491c7a026098103b6286deb31e3cfb037365dd39f095f",
|
"zh:04c0a49c2b23140b2f21cfd0d52f9798d70d3bdae3831613e156aabe519bbc6c",
|
||||||
"zh:05bd072e6119f7a5abff05c6064001f745473119a956586cf77ae843cf55d666",
|
"zh:185f21b4834ba63e8df1f84aa34639d8a7e126429a4007bb5f9ad82f2602a997",
|
||||||
"zh:228bbe61345c4e8e0bc6b698b4b9652abff65662ee72ede2aecb4c3efb91b243",
|
"zh:234724f52cb4c0c3f7313d3b2697caef26d921d134f26ae14801e7afac522f7b",
|
||||||
"zh:2948aeefe71ba041c94082cf931ecc95510d93af0a61d0a287880f5b9d24b11a",
|
"zh:38a56fcd1b3e40706af995611c977816543b53f1e55fe2720944aae2b6828fcb",
|
||||||
"zh:5dfc2c5e95843ca54957212ee3ecb7ff06f2cf60bfd6ca278b5249fd70ac18f5",
|
"zh:419938f5430fc78eff933470aefbf94a460a478f867cf7761a3dea177b4eb153",
|
||||||
"zh:69922cb45559b0b0544b9c2d31ed2d0fac9121faa75bc2f523484785b45d8e2b",
|
"zh:4b46d92bfde1deab7de7ba1a6bbf4ba7c711e4fd925341ddf09d4cc28dae03d8",
|
||||||
|
"zh:537acd4a31c752f1bae305ba7190f60b71ad1a459f22d464f3f914336c9e919f",
|
||||||
|
"zh:5ff36b005aad07697dd0b30d4f0c35dbcdc30dc52b41722552060792fa87ce04",
|
||||||
|
"zh:635c5ee419daea098060f794d9d7d999275301181e49562c4e4c08f043076937",
|
||||||
|
"zh:859277c330d61f91abe9e799389467ca11b77131bf34bedbef52f8da68b2bb49",
|
||||||
"zh:890df766e9b839623b1f0437355032a3c006226a6c200cd911e15ee1a9014e9f",
|
"zh:890df766e9b839623b1f0437355032a3c006226a6c200cd911e15ee1a9014e9f",
|
||||||
"zh:9d83a0cbf72327286f7dbd63cd4af89059c648163fe6ed21b1df768e0518d445",
|
"zh:927dfdb8d9aef37ead03fceaa29e87ba076a3dd24e19b6cefdbb0efe9987ff8c",
|
||||||
"zh:a8e1982945822c7d7aaa6ba8602c7247d1a3fad15d612f30eb323491a637bf8d",
|
"zh:bbf2226f07f6b1e721877328e69ded4b64f9c196634d2e2429e3cfabbe41e532",
|
||||||
"zh:c6d41ebd69ddb23e3dad49a0ebf1da5a9c7d8706a4f55d953115d371f407928b",
|
"zh:daeed873d6f38604232b46ee4a5830c85d195b967f8dbcafe2fcffa98daf9c5f",
|
||||||
"zh:d03e5442b12846c2737f099d30cd23d9f85a0c6d65437ccb44819f9a6c4e1d7f",
|
"zh:f8f2fc4646c1ba44085612fa7f4dbb7cbcead43b4e661f2b98ddfb4f68afc758",
|
||||||
"zh:d446f2e1186b35037aea03b0e27d8b032d2f069f194f84b3f0e2907b3a79a955",
|
|
||||||
"zh:e4d7549a4c856524e01f3dd4d69f57119ea205f7a0fa38dcfe154475b4ae9258",
|
|
||||||
"zh:e64b8915cb9686f85e77115bd674f2faf4f29880688067d7d0f1376566fdb3b0",
|
|
||||||
"zh:f046efdc55e6385cdd69baaa06a929bef9fe6809d373b0d2d6c7df8f8c23eddc",
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ terraform {
|
|||||||
required_providers {
|
required_providers {
|
||||||
cloudflare = {
|
cloudflare = {
|
||||||
source = "cloudflare/cloudflare"
|
source = "cloudflare/cloudflare"
|
||||||
version = "4.45.0"
|
version = "4.48.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,37 +2,37 @@
|
|||||||
# Manual edits may be lost in future updates.
|
# Manual edits may be lost in future updates.
|
||||||
|
|
||||||
provider "registry.opentofu.org/cloudflare/cloudflare" {
|
provider "registry.opentofu.org/cloudflare/cloudflare" {
|
||||||
version = "4.45.0"
|
version = "4.48.0"
|
||||||
constraints = "4.45.0"
|
constraints = "4.48.0"
|
||||||
hashes = [
|
hashes = [
|
||||||
"h1:/CGpnYMkLRDmqn4iAsh/jg7ELZ6QExUw03VdjKZyK5M=",
|
"h1:0IKUOR32xEI1suS5QCOjfxjQ2mRd058btXk8hVnaOJ4=",
|
||||||
"h1:82C/ryqwQvxhBINYOOyF5ZzPW/k4zJ/RYT13eCdPgEc=",
|
"h1:3YG6vu/bFPcYOeLdSUZhiAWiWKaFlOAR34z2o8cbE9k=",
|
||||||
"h1:8Wu1D7ZwbLGdHakLRAzoAJ5VqZ8I14qzkPv1OGNfIlg=",
|
"h1:FvGy06/i9AMtVkSIUnCrXNv5xF6jqBqMH8oPVLyeeAg=",
|
||||||
"h1:CVq0CAibeueOuiNk0UQtwZvMLMof33n1BgskFPOymrk=",
|
"h1:GXH7nIF0ocMqebbA41+fSGIYfM+VAM/PvTe7fJr8UrQ=",
|
||||||
"h1:FSS5Kq+L+CX1zARy8PhaF8edBFNgsLtds4Uo8MwJiK8=",
|
"h1:H0ll0ph4404vFE868W3qJ3zhOyy4jbXrOMtdkViEZsU=",
|
||||||
"h1:L4qsorLII7f8xSFmv6JOoWfLWDunWQEpK964Bxk7mtM=",
|
"h1:SX42e3k73IcFcrQlZ2e/Veqt2tvCMy6fwlo5yNUktCE=",
|
||||||
"h1:StO3PV5PDskSCnhoHhWHOPxu6hbzJUQggfLgOSkvhwg=",
|
"h1:Uu/gjBc99GefdPdSrlBwU75DWU0ZcwGcrd3ZFyTeL0s=",
|
||||||
"h1:Tjo+Er9ets5YrTRIdP9LBmi4p89nL/W+A7r8a1MM9nI=",
|
"h1:VZw0uN41PWRmNlhg7Ze0Eh7cdoklX1oZbfNAXNYnU1I=",
|
||||||
"h1:XIwT+AWvks1LTytePM9zls+O8ItxoqCfPOgHwuH9ivQ=",
|
"h1:cMdV7ql6PsFa4qtb0EoZSctvTaTqV7yplBSDwcLRCLc=",
|
||||||
"h1:aOXn/zuM1+5GGy/SSRx8q4EYCSTFE9Tr0twHPIf5/KE=",
|
"h1:ePGvSurmlqOCkD761vkhRmz7bsK36/EnIvx2Xy8TdXo=",
|
||||||
"h1:lb+YcuZ4guYd8zE51vgSnDsRAD9IV00Z15l1i1X52s8=",
|
"h1:fOYufF+1bzw2N3aHLpkLB6E8VbZ4ysXDODYQOlwhwd4=",
|
||||||
"h1:pYwNXGjfXA2rUEmotGMLWgmavT9D2rdHnV3TpuIK3ko=",
|
"h1:qe8RbnWq0T4xhqjn9QcbO6YW5YDx47P+eJ0NUMIfwCc=",
|
||||||
"h1:q1qrnPq6KkljwBrugCwzb7f0SVP4Lzkfh+EOLARY9V8=",
|
"h1:tRD2av6PafHDP/b9jDQsG5/aX+lHeKxpbIEHYYLBVUc=",
|
||||||
"h1:v9sL4cZLTV5Gu2004DDyy7209gT0JmudBCAD0WCr/JE=",
|
"h1:zyl6Gvx/CFpwYW8pFFDesfO8Lxv+a6CopyAsIMhp54s=",
|
||||||
"zh:00be2a6adc76615a368491c7a026098103b6286deb31e3cfb037365dd39f095f",
|
"zh:04c0a49c2b23140b2f21cfd0d52f9798d70d3bdae3831613e156aabe519bbc6c",
|
||||||
"zh:05bd072e6119f7a5abff05c6064001f745473119a956586cf77ae843cf55d666",
|
"zh:185f21b4834ba63e8df1f84aa34639d8a7e126429a4007bb5f9ad82f2602a997",
|
||||||
"zh:228bbe61345c4e8e0bc6b698b4b9652abff65662ee72ede2aecb4c3efb91b243",
|
"zh:234724f52cb4c0c3f7313d3b2697caef26d921d134f26ae14801e7afac522f7b",
|
||||||
"zh:2948aeefe71ba041c94082cf931ecc95510d93af0a61d0a287880f5b9d24b11a",
|
"zh:38a56fcd1b3e40706af995611c977816543b53f1e55fe2720944aae2b6828fcb",
|
||||||
"zh:5dfc2c5e95843ca54957212ee3ecb7ff06f2cf60bfd6ca278b5249fd70ac18f5",
|
"zh:419938f5430fc78eff933470aefbf94a460a478f867cf7761a3dea177b4eb153",
|
||||||
"zh:69922cb45559b0b0544b9c2d31ed2d0fac9121faa75bc2f523484785b45d8e2b",
|
"zh:4b46d92bfde1deab7de7ba1a6bbf4ba7c711e4fd925341ddf09d4cc28dae03d8",
|
||||||
|
"zh:537acd4a31c752f1bae305ba7190f60b71ad1a459f22d464f3f914336c9e919f",
|
||||||
|
"zh:5ff36b005aad07697dd0b30d4f0c35dbcdc30dc52b41722552060792fa87ce04",
|
||||||
|
"zh:635c5ee419daea098060f794d9d7d999275301181e49562c4e4c08f043076937",
|
||||||
|
"zh:859277c330d61f91abe9e799389467ca11b77131bf34bedbef52f8da68b2bb49",
|
||||||
"zh:890df766e9b839623b1f0437355032a3c006226a6c200cd911e15ee1a9014e9f",
|
"zh:890df766e9b839623b1f0437355032a3c006226a6c200cd911e15ee1a9014e9f",
|
||||||
"zh:9d83a0cbf72327286f7dbd63cd4af89059c648163fe6ed21b1df768e0518d445",
|
"zh:927dfdb8d9aef37ead03fceaa29e87ba076a3dd24e19b6cefdbb0efe9987ff8c",
|
||||||
"zh:a8e1982945822c7d7aaa6ba8602c7247d1a3fad15d612f30eb323491a637bf8d",
|
"zh:bbf2226f07f6b1e721877328e69ded4b64f9c196634d2e2429e3cfabbe41e532",
|
||||||
"zh:c6d41ebd69ddb23e3dad49a0ebf1da5a9c7d8706a4f55d953115d371f407928b",
|
"zh:daeed873d6f38604232b46ee4a5830c85d195b967f8dbcafe2fcffa98daf9c5f",
|
||||||
"zh:d03e5442b12846c2737f099d30cd23d9f85a0c6d65437ccb44819f9a6c4e1d7f",
|
"zh:f8f2fc4646c1ba44085612fa7f4dbb7cbcead43b4e661f2b98ddfb4f68afc758",
|
||||||
"zh:d446f2e1186b35037aea03b0e27d8b032d2f069f194f84b3f0e2907b3a79a955",
|
|
||||||
"zh:e4d7549a4c856524e01f3dd4d69f57119ea205f7a0fa38dcfe154475b4ae9258",
|
|
||||||
"zh:e64b8915cb9686f85e77115bd674f2faf4f29880688067d7d0f1376566fdb3b0",
|
|
||||||
"zh:f046efdc55e6385cdd69baaa06a929bef9fe6809d373b0d2d6c7df8f8c23eddc",
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ terraform {
|
|||||||
required_providers {
|
required_providers {
|
||||||
cloudflare = {
|
cloudflare = {
|
||||||
source = "cloudflare/cloudflare"
|
source = "cloudflare/cloudflare"
|
||||||
version = "4.45.0"
|
version = "4.48.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
10
docker/.gitignore
vendored
@@ -1 +1,9 @@
|
|||||||
.env
|
.DS_Store
|
||||||
|
node_modules
|
||||||
|
/build
|
||||||
|
/.svelte-kit
|
||||||
|
/dist
|
||||||
|
/package
|
||||||
|
.env
|
||||||
|
.env.*
|
||||||
|
!.env.example
|
||||||
|
|||||||
1
docker/.npmrc
Normal file
@@ -0,0 +1 @@
|
|||||||
|
engine-strict=true
|
||||||
1
docker/.nvmrc
Normal file
@@ -0,0 +1 @@
|
|||||||
|
22.11.0
|
||||||
14
docker/.prettierignore
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
.DS_Store
|
||||||
|
node_modules
|
||||||
|
/build
|
||||||
|
/package
|
||||||
|
/coverage
|
||||||
|
.env
|
||||||
|
.env.*
|
||||||
|
!.env.example
|
||||||
|
*.md
|
||||||
|
|
||||||
|
# Ignore files for PNPM, NPM and YARN
|
||||||
|
pnpm-lock.yaml
|
||||||
|
package-lock.json
|
||||||
|
yarn.lock
|
||||||
9
docker/.prettierrc
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"jsonRecursiveSort": true,
|
||||||
|
"organizeImportsSkipDestructiveCodeActions": true,
|
||||||
|
"plugins": ["prettier-plugin-organize-imports", "prettier-plugin-sort-json"],
|
||||||
|
"printWidth": 120,
|
||||||
|
"semi": true,
|
||||||
|
"singleQuote": true,
|
||||||
|
"trailingComma": "all"
|
||||||
|
}
|
||||||
@@ -47,6 +47,7 @@ services:
|
|||||||
ports:
|
ports:
|
||||||
- 9230:9230
|
- 9230:9230
|
||||||
- 9231:9231
|
- 9231:9231
|
||||||
|
- 2283:2283
|
||||||
depends_on:
|
depends_on:
|
||||||
- redis
|
- redis
|
||||||
- database
|
- database
|
||||||
@@ -56,13 +57,15 @@ services:
|
|||||||
immich-web:
|
immich-web:
|
||||||
container_name: immich_web
|
container_name: immich_web
|
||||||
image: immich-web-dev:latest
|
image: immich-web-dev:latest
|
||||||
|
# Needed for rootless docker setup, see https://github.com/moby/moby/issues/45919
|
||||||
|
# user: 0:0
|
||||||
build:
|
build:
|
||||||
context: ../web
|
context: ../web
|
||||||
command: ['/usr/src/app/bin/immich-web']
|
command: ['/usr/src/app/bin/immich-web']
|
||||||
env_file:
|
env_file:
|
||||||
- .env
|
- .env
|
||||||
ports:
|
ports:
|
||||||
- 2283:3000
|
- 3000:3000
|
||||||
- 24678:24678
|
- 24678:24678
|
||||||
volumes:
|
volumes:
|
||||||
- ../web:/usr/src/app
|
- ../web:/usr/src/app
|
||||||
@@ -103,7 +106,7 @@ services:
|
|||||||
|
|
||||||
redis:
|
redis:
|
||||||
container_name: immich_redis
|
container_name: immich_redis
|
||||||
image: redis:6.2-alpine@sha256:2ba50e1ac3a0ea17b736ce9db2b0a9f6f8b85d4c27d5f5accc6a416d8f42c6d5
|
image: redis:6.2-alpine@sha256:eaba718fecd1196d88533de7ba49bf903ad33664a92debb24660a922ecd9cac8
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: redis-cli ping || exit 1
|
test: redis-cli ping || exit 1
|
||||||
|
|
||||||
@@ -122,26 +125,23 @@ services:
|
|||||||
ports:
|
ports:
|
||||||
- 5432:5432
|
- 5432:5432
|
||||||
healthcheck:
|
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
|
interval: 5m
|
||||||
start_interval: 30s
|
start_interval: 30s
|
||||||
start_period: 5m
|
start_period: 5m
|
||||||
command:
|
command: >-
|
||||||
[
|
postgres
|
||||||
'postgres',
|
-c shared_preload_libraries=vectors.so
|
||||||
'-c',
|
-c 'search_path="$$user", public, vectors'
|
||||||
'shared_preload_libraries=vectors.so',
|
-c logging_collector=on
|
||||||
'-c',
|
-c max_wal_size=2GB
|
||||||
'search_path="$$user", public, vectors',
|
-c shared_buffers=512MB
|
||||||
'-c',
|
-c wal_compression=on
|
||||||
'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
|
# set IMMICH_TELEMETRY_INCLUDE=all in .env to enable metrics
|
||||||
# immich-prometheus:
|
# immich-prometheus:
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ services:
|
|||||||
|
|
||||||
redis:
|
redis:
|
||||||
container_name: immich_redis
|
container_name: immich_redis
|
||||||
image: redis:6.2-alpine@sha256:2ba50e1ac3a0ea17b736ce9db2b0a9f6f8b85d4c27d5f5accc6a416d8f42c6d5
|
image: redis:6.2-alpine@sha256:eaba718fecd1196d88533de7ba49bf903ad33664a92debb24660a922ecd9cac8
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: redis-cli ping || exit 1
|
test: redis-cli ping || exit 1
|
||||||
restart: always
|
restart: always
|
||||||
@@ -67,26 +67,23 @@ services:
|
|||||||
ports:
|
ports:
|
||||||
- 5432:5432
|
- 5432:5432
|
||||||
healthcheck:
|
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
|
interval: 5m
|
||||||
start_interval: 30s
|
start_interval: 30s
|
||||||
start_period: 5m
|
start_period: 5m
|
||||||
command:
|
command: >-
|
||||||
[
|
postgres
|
||||||
'postgres',
|
-c shared_preload_libraries=vectors.so
|
||||||
'-c',
|
-c 'search_path="$$user", public, vectors'
|
||||||
'shared_preload_libraries=vectors.so',
|
-c logging_collector=on
|
||||||
'-c',
|
-c max_wal_size=2GB
|
||||||
'search_path="$$user", public, vectors',
|
-c shared_buffers=512MB
|
||||||
'-c',
|
-c wal_compression=on
|
||||||
'logging_collector=on',
|
|
||||||
'-c',
|
|
||||||
'max_wal_size=2GB',
|
|
||||||
'-c',
|
|
||||||
'shared_buffers=512MB',
|
|
||||||
'-c',
|
|
||||||
'wal_compression=on',
|
|
||||||
]
|
|
||||||
restart: always
|
restart: always
|
||||||
|
|
||||||
# set IMMICH_TELEMETRY_INCLUDE=all in .env to enable metrics
|
# set IMMICH_TELEMETRY_INCLUDE=all in .env to enable metrics
|
||||||
@@ -94,7 +91,7 @@ services:
|
|||||||
container_name: immich_prometheus
|
container_name: immich_prometheus
|
||||||
ports:
|
ports:
|
||||||
- 9090:9090
|
- 9090:9090
|
||||||
image: prom/prometheus@sha256:378f4e03703557d1c6419e6caccf922f96e6d88a530f7431d66a4c4f4b1000fe
|
image: prom/prometheus@sha256:565ee86501224ebbb98fc10b332fa54440b100469924003359edf49cbce374bd
|
||||||
volumes:
|
volumes:
|
||||||
- ./prometheus.yml:/etc/prometheus/prometheus.yml
|
- ./prometheus.yml:/etc/prometheus/prometheus.yml
|
||||||
- prometheus-data:/prometheus
|
- prometheus-data:/prometheus
|
||||||
@@ -106,7 +103,7 @@ services:
|
|||||||
command: ['./run.sh', '-disable-reporting']
|
command: ['./run.sh', '-disable-reporting']
|
||||||
ports:
|
ports:
|
||||||
- 3000:3000
|
- 3000:3000
|
||||||
image: grafana/grafana:11.3.0-ubuntu@sha256:51587e148ac0214d7938e7f3fe8512182e4eb6141892a3ffb88bba1901b49285
|
image: grafana/grafana:11.4.0-ubuntu@sha256:afccec22ba0e4815cca1d2bf3836e414322390dc78d77f1851976ffa8d61051c
|
||||||
volumes:
|
volumes:
|
||||||
- grafana-data:/var/lib/grafana
|
- grafana-data:/var/lib/grafana
|
||||||
|
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ services:
|
|||||||
|
|
||||||
redis:
|
redis:
|
||||||
container_name: immich_redis
|
container_name: immich_redis
|
||||||
image: docker.io/redis:6.2-alpine@sha256:2ba50e1ac3a0ea17b736ce9db2b0a9f6f8b85d4c27d5f5accc6a416d8f42c6d5
|
image: docker.io/redis:6.2-alpine@sha256:eaba718fecd1196d88533de7ba49bf903ad33664a92debb24660a922ecd9cac8
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: redis-cli ping || exit 1
|
test: redis-cli ping || exit 1
|
||||||
restart: always
|
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
|
# 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
|
- ${DB_DATA_LOCATION}:/var/lib/postgresql/data
|
||||||
healthcheck:
|
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
|
interval: 5m
|
||||||
start_interval: 30s
|
start_interval: 30s
|
||||||
start_period: 5m
|
start_period: 5m
|
||||||
command:
|
command: >-
|
||||||
[
|
postgres
|
||||||
'postgres',
|
-c shared_preload_libraries=vectors.so
|
||||||
'-c',
|
-c 'search_path="$$user", public, vectors'
|
||||||
'shared_preload_libraries=vectors.so',
|
-c logging_collector=on
|
||||||
'-c',
|
-c max_wal_size=2GB
|
||||||
'search_path="$$user", public, vectors',
|
-c shared_buffers=512MB
|
||||||
'-c',
|
-c wal_compression=on
|
||||||
'logging_collector=on',
|
|
||||||
'-c',
|
|
||||||
'max_wal_size=2GB',
|
|
||||||
'-c',
|
|
||||||
'shared_buffers=512MB',
|
|
||||||
'-c',
|
|
||||||
'wal_compression=on',
|
|
||||||
]
|
|
||||||
restart: always
|
restart: always
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
|
|||||||
86
docker/eslint.config.mjs
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
import { FlatCompat } from '@eslint/eslintrc';
|
||||||
|
import js from '@eslint/js';
|
||||||
|
import typescriptEslint from '@typescript-eslint/eslint-plugin';
|
||||||
|
import tsParser from '@typescript-eslint/parser';
|
||||||
|
import globals from 'globals';
|
||||||
|
import path from 'node:path';
|
||||||
|
import { fileURLToPath } from 'node:url';
|
||||||
|
|
||||||
|
const __filename = fileURLToPath(import.meta.url);
|
||||||
|
const __dirname = path.dirname(__filename);
|
||||||
|
const compat = new FlatCompat({
|
||||||
|
baseDirectory: __dirname,
|
||||||
|
recommendedConfig: js.configs.recommended,
|
||||||
|
allConfig: js.configs.all,
|
||||||
|
});
|
||||||
|
|
||||||
|
export default [
|
||||||
|
{
|
||||||
|
ignores: [
|
||||||
|
'**/.DS_Store',
|
||||||
|
'**/node_modules',
|
||||||
|
'dist',
|
||||||
|
'lib/docker-compose/types.ts',
|
||||||
|
'build',
|
||||||
|
'package',
|
||||||
|
'**/.env',
|
||||||
|
'**/.env.*',
|
||||||
|
'!**/.env.example',
|
||||||
|
'**/pnpm-lock.yaml',
|
||||||
|
'**/package-lock.json',
|
||||||
|
'**/yarn.lock',
|
||||||
|
'eslint.config.mjs',
|
||||||
|
'vite.config.js',
|
||||||
|
'coverage',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
...compat.extends('eslint:recommended', 'plugin:@typescript-eslint/recommended', 'plugin:unicorn/recommended'),
|
||||||
|
{
|
||||||
|
ignores: ['src/**'],
|
||||||
|
plugins: {
|
||||||
|
'@typescript-eslint': typescriptEslint,
|
||||||
|
},
|
||||||
|
|
||||||
|
languageOptions: {
|
||||||
|
globals: {
|
||||||
|
...globals.browser,
|
||||||
|
...globals.node,
|
||||||
|
NodeJS: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
parser: tsParser,
|
||||||
|
ecmaVersion: 2022,
|
||||||
|
sourceType: 'module',
|
||||||
|
|
||||||
|
parserOptions: {
|
||||||
|
tsconfigRootDir: __dirname,
|
||||||
|
project: ['./tsconfig.json'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
rules: {
|
||||||
|
'@typescript-eslint/no-unused-vars': [
|
||||||
|
'warn',
|
||||||
|
{
|
||||||
|
argsIgnorePattern: '^_$',
|
||||||
|
varsIgnorePattern: '^_$',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
|
||||||
|
curly: 2,
|
||||||
|
'unicorn/no-useless-undefined': 'off',
|
||||||
|
'unicorn/prefer-spread': 'off',
|
||||||
|
'unicorn/no-null': 'off',
|
||||||
|
'unicorn/prevent-abbreviations': 'off',
|
||||||
|
'unicorn/no-nested-ternary': 'off',
|
||||||
|
'unicorn/consistent-function-scoping': 'off',
|
||||||
|
'unicorn/prefer-top-level-await': 'off',
|
||||||
|
'unicorn/import-style': 'off',
|
||||||
|
'@typescript-eslint/await-thenable': 'error',
|
||||||
|
'@typescript-eslint/no-floating-promises': 'error',
|
||||||
|
'@typescript-eslint/no-misused-promises': 'error',
|
||||||
|
'@typescript-eslint/require-await': 'error',
|
||||||
|
'object-shorthand': ['error', 'always'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
87
docker/lib/build.ts
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
import { dump as dumpYaml } from 'js-yaml';
|
||||||
|
import { ComposeBuilder, ServiceBuilder } from 'lib/docker-compose/builder';
|
||||||
|
import { ContainerName, GeneratorOptions, ServiceName } from 'lib/types';
|
||||||
|
import { asQueryParams, getImmichEnvironment, getImmichVolumes, isExternalPostgres, isIoRedis } from 'lib/utils';
|
||||||
|
|
||||||
|
const RELEASE_VERSION = 'v1.122.0';
|
||||||
|
const postgresHealthCheck = [
|
||||||
|
'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\n`,
|
||||||
|
].join(' ');
|
||||||
|
const postgresCommand = [
|
||||||
|
`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`,
|
||||||
|
].join(' ');
|
||||||
|
|
||||||
|
const build = (options: GeneratorOptions) => {
|
||||||
|
const healthchecksEnabled = options.healthchecks ?? true;
|
||||||
|
const containerNames = options.containerNames ?? true;
|
||||||
|
|
||||||
|
const immichService = ServiceBuilder.create(ServiceName.ImmichServer)
|
||||||
|
.setImage(`ghcr.io/immich-app/immich-server:${RELEASE_VERSION}`)
|
||||||
|
.setContainerName(containerNames && ContainerName.ImmichServer)
|
||||||
|
.setRestartPolicy('always')
|
||||||
|
.setHealthcheck(healthchecksEnabled)
|
||||||
|
.setEnvironment(getImmichEnvironment(options))
|
||||||
|
.addExposedPort(2283)
|
||||||
|
.addVolumes(getImmichVolumes(options));
|
||||||
|
|
||||||
|
const machineLearningEnabled = options.machineLearning;
|
||||||
|
const modelCacheVolume = 'model-cache';
|
||||||
|
const machineLearningService =
|
||||||
|
machineLearningEnabled &&
|
||||||
|
ServiceBuilder.create(ServiceName.ImmichMachineLearning)
|
||||||
|
.setImage(`ghcr.io/immich-app/immich-machine-learning:${RELEASE_VERSION}-cuda`)
|
||||||
|
.setContainerName(containerNames && ContainerName.ImmichMachineLearning)
|
||||||
|
.setRestartPolicy('always')
|
||||||
|
.setHealthcheck(healthchecksEnabled)
|
||||||
|
.addVolume(`${modelCacheVolume}:/cache`);
|
||||||
|
|
||||||
|
const redisService = isIoRedis(options)
|
||||||
|
? false
|
||||||
|
: ServiceBuilder.create(ServiceName.Redis)
|
||||||
|
.setImage('docker.io/redis:6.2-alpine')
|
||||||
|
.setContainerName(containerNames && ContainerName.Redis)
|
||||||
|
.setRestartPolicy('always')
|
||||||
|
.setHealthcheck(healthchecksEnabled && 'redis-cli ping || exit 1');
|
||||||
|
|
||||||
|
const postgresService = isExternalPostgres(options)
|
||||||
|
? false
|
||||||
|
: ServiceBuilder.create(ServiceName.Postgres)
|
||||||
|
.setImage('docker.io/tensorchord/pgvecto-rs:pg14-v0.2.0')
|
||||||
|
.setContainerName(containerNames && ContainerName.Postgres)
|
||||||
|
.setRestartPolicy('always')
|
||||||
|
.setEnvironment({
|
||||||
|
POSTGRES_PASSWORD: options.postgresPassword,
|
||||||
|
POSTGRES_USER: options.postgresUser,
|
||||||
|
POSTGRES_DB: options.postgresDatabase,
|
||||||
|
POSTGRES_INITDB_ARGS: '--data-checksums',
|
||||||
|
})
|
||||||
|
.setHealthcheck(healthchecksEnabled && postgresHealthCheck)
|
||||||
|
.setCommand(postgresCommand)
|
||||||
|
.addVolume(`${options.postgresDataLocation}:/var/lib/postgresql/data`);
|
||||||
|
|
||||||
|
const domain = 'https://get.immich.app';
|
||||||
|
const url = `${domain}/compose?${asQueryParams(options)}`;
|
||||||
|
|
||||||
|
return ComposeBuilder.create('immich')
|
||||||
|
.addComment(`This docker compose file was originally generated at https://get.immich.app/compose`)
|
||||||
|
.addComment(url)
|
||||||
|
.addComment(`${dumpYaml({ options }, { indent: 2 })}`)
|
||||||
|
.addService(immichService.addDependsOn(redisService).addDependsOn(postgresService))
|
||||||
|
.addService(machineLearningService)
|
||||||
|
.addService(redisService)
|
||||||
|
.addService(postgresService)
|
||||||
|
.addVolume(modelCacheVolume, machineLearningEnabled && {});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const buildSpec = (options: GeneratorOptions) => build(options).asSpec();
|
||||||
|
export const buildYaml = (options: GeneratorOptions) => build(options).asYaml();
|
||||||
208
docker/lib/docker-compose/builder.ts
Normal file
@@ -0,0 +1,208 @@
|
|||||||
|
import { dump as dumpYaml } from 'js-yaml';
|
||||||
|
import {
|
||||||
|
Command,
|
||||||
|
ComposeSpecification,
|
||||||
|
DefinitionsService,
|
||||||
|
DefinitionsVolume,
|
||||||
|
ListOfStrings,
|
||||||
|
} from 'lib/docker-compose/types';
|
||||||
|
|
||||||
|
type ServiceNameAccessor = { getName: () => string };
|
||||||
|
type ServiceBuildAccessor = { build: () => DefinitionsService };
|
||||||
|
|
||||||
|
const withNewLines = (yaml: string) =>
|
||||||
|
yaml.replaceAll(/(?<leading>[^:]\n)(?<key>[ ]{0,2}\S+:)$/gm, '$<leading>\n$<key>');
|
||||||
|
|
||||||
|
export class ComposeBuilder {
|
||||||
|
private spec: ComposeSpecification = {};
|
||||||
|
private comments: string[] = [];
|
||||||
|
|
||||||
|
private constructor(projectName?: string) {
|
||||||
|
if (projectName) {
|
||||||
|
this.setProjectName(projectName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static create(projectName?: string) {
|
||||||
|
return new ComposeBuilder(projectName);
|
||||||
|
}
|
||||||
|
|
||||||
|
setProjectName(name: string) {
|
||||||
|
this.spec.name = name;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
addComment(comment: string) {
|
||||||
|
this.comments.push(comment + '\n');
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
addService(spec: false | (ServiceNameAccessor & ServiceBuildAccessor)) {
|
||||||
|
if (!spec) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.spec.services) {
|
||||||
|
this.spec.services = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
this.spec.services[spec.getName()] = spec.build();
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
addVolume(name: string, volume: false | DefinitionsVolume) {
|
||||||
|
if (volume === false) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.spec.volumes) {
|
||||||
|
this.spec.volumes = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
this.spec.volumes[name] = volume;
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
asSpec() {
|
||||||
|
return this.spec;
|
||||||
|
}
|
||||||
|
|
||||||
|
asYaml() {
|
||||||
|
let prefix = '';
|
||||||
|
if (this.comments.length > 0) {
|
||||||
|
const comments =
|
||||||
|
this.comments
|
||||||
|
.flatMap((comment) => comment.split('\n'))
|
||||||
|
.join('\n')
|
||||||
|
.trim()
|
||||||
|
.split('\n')
|
||||||
|
.map((comment) => `# ${comment}`)
|
||||||
|
.join('\n') + '\n\n';
|
||||||
|
|
||||||
|
prefix += comments;
|
||||||
|
}
|
||||||
|
|
||||||
|
const spec = withNewLines(dumpYaml(this.spec, { indent: 2, lineWidth: 140 })).trim();
|
||||||
|
|
||||||
|
return prefix + spec;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class ServiceBuilder {
|
||||||
|
private spec: DefinitionsService = {};
|
||||||
|
|
||||||
|
private constructor(private name: string) {}
|
||||||
|
|
||||||
|
static create(name: string) {
|
||||||
|
return new ServiceBuilder(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
getName() {
|
||||||
|
return this.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
setImage(image: string) {
|
||||||
|
this.spec.image = image;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
setContainerName(name: false | string) {
|
||||||
|
if (name === false) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.spec.container_name = name;
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
addExposedPort(port: number | { internal: number; external: number }) {
|
||||||
|
if (typeof port === 'number') {
|
||||||
|
port = { internal: port, external: port };
|
||||||
|
}
|
||||||
|
|
||||||
|
const { internal, external } = port;
|
||||||
|
|
||||||
|
if (!this.spec.ports) {
|
||||||
|
this.spec.ports = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
this.spec.ports.push(`${external}:${internal}`);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
addDependsOn(service: false | string | ServiceNameAccessor) {
|
||||||
|
if (service === false) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
let serviceName = service as string;
|
||||||
|
if ('getName' in (service as ServiceNameAccessor)) {
|
||||||
|
serviceName = (service as ServiceNameAccessor).getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.spec.depends_on) {
|
||||||
|
this.spec.depends_on = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
(this.spec.depends_on as ListOfStrings).push(serviceName);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
setRestartPolicy(restart: string) {
|
||||||
|
this.spec.restart = restart;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
setEnvironment(env: Record<string, string | number | undefined>) {
|
||||||
|
this.spec.environment = env;
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
setHealthcheck(test: boolean | string) {
|
||||||
|
if (test === true) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (test === false) {
|
||||||
|
this.spec.healthcheck = { disable: true };
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.spec.healthcheck = { test };
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
setCommand(command: Command) {
|
||||||
|
this.spec.command = command;
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
addVolume(volume: string) {
|
||||||
|
if (!this.spec.volumes) {
|
||||||
|
this.spec.volumes = [];
|
||||||
|
}
|
||||||
|
this.spec.volumes.push(volume);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
addVolumes(volumes: string[]) {
|
||||||
|
for (const volume of volumes) {
|
||||||
|
this.addVolume(volume);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
build() {
|
||||||
|
return this.spec;
|
||||||
|
}
|
||||||
|
}
|
||||||
937
docker/lib/docker-compose/types.ts
Normal file
@@ -0,0 +1,937 @@
|
|||||||
|
export type DefinitionsInclude =
|
||||||
|
| string
|
||||||
|
| {
|
||||||
|
path?: StringOrList;
|
||||||
|
env_file?: StringOrList;
|
||||||
|
project_directory?: string;
|
||||||
|
};
|
||||||
|
export type StringOrList = string | ListOfStrings;
|
||||||
|
export type ListOfStrings = string[];
|
||||||
|
export type DefinitionsDevelopment = {
|
||||||
|
watch?: {
|
||||||
|
ignore?: string[];
|
||||||
|
path: string;
|
||||||
|
action: 'rebuild' | 'sync' | 'sync+restart';
|
||||||
|
target?: string;
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
}[];
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
} & Development;
|
||||||
|
export type Development = {
|
||||||
|
watch?: {
|
||||||
|
ignore?: string[];
|
||||||
|
path: string;
|
||||||
|
action: 'rebuild' | 'sync' | 'sync+restart';
|
||||||
|
target?: string;
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
}[];
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
} | null;
|
||||||
|
export type DefinitionsDeployment = {
|
||||||
|
mode?: string;
|
||||||
|
endpoint_mode?: string;
|
||||||
|
replicas?: number | string;
|
||||||
|
labels?: ListOrDict;
|
||||||
|
rollback_config?: {
|
||||||
|
parallelism?: number | string;
|
||||||
|
delay?: string;
|
||||||
|
failure_action?: string;
|
||||||
|
monitor?: string;
|
||||||
|
max_failure_ratio?: number | string;
|
||||||
|
order?: 'start-first' | 'stop-first';
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
};
|
||||||
|
update_config?: {
|
||||||
|
parallelism?: number | string;
|
||||||
|
delay?: string;
|
||||||
|
failure_action?: string;
|
||||||
|
monitor?: string;
|
||||||
|
max_failure_ratio?: number | string;
|
||||||
|
order?: 'start-first' | 'stop-first';
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
};
|
||||||
|
resources?: {
|
||||||
|
limits?: {
|
||||||
|
cpus?: number | string;
|
||||||
|
memory?: string;
|
||||||
|
pids?: number | string;
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
};
|
||||||
|
reservations?: {
|
||||||
|
cpus?: number | string;
|
||||||
|
memory?: string;
|
||||||
|
generic_resources?: DefinitionsGenericResources;
|
||||||
|
devices?: DefinitionsDevices;
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
};
|
||||||
|
restart_policy?: {
|
||||||
|
condition?: string;
|
||||||
|
delay?: string;
|
||||||
|
max_attempts?: number | string;
|
||||||
|
window?: string;
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
};
|
||||||
|
placement?: {
|
||||||
|
constraints?: string[];
|
||||||
|
preferences?: {
|
||||||
|
spread?: string;
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
}[];
|
||||||
|
max_replicas_per_node?: number | string;
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
} & Deployment;
|
||||||
|
export type ListOrDict =
|
||||||
|
| {
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` ".+".
|
||||||
|
*/
|
||||||
|
[k: string]: undefined | string | number | boolean | null;
|
||||||
|
}
|
||||||
|
| string[];
|
||||||
|
export type DefinitionsGenericResources = {
|
||||||
|
discrete_resource_spec?: {
|
||||||
|
kind?: string;
|
||||||
|
value?: number | string;
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
}[];
|
||||||
|
export type DefinitionsDevices = {
|
||||||
|
capabilities: ListOfStrings;
|
||||||
|
count?: string | number;
|
||||||
|
device_ids?: ListOfStrings;
|
||||||
|
driver?: string;
|
||||||
|
options?: ListOrDict;
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
}[];
|
||||||
|
export type Deployment = {
|
||||||
|
mode?: string;
|
||||||
|
endpoint_mode?: string;
|
||||||
|
replicas?: number | string;
|
||||||
|
labels?: ListOrDict;
|
||||||
|
rollback_config?: {
|
||||||
|
parallelism?: number | string;
|
||||||
|
delay?: string;
|
||||||
|
failure_action?: string;
|
||||||
|
monitor?: string;
|
||||||
|
max_failure_ratio?: number | string;
|
||||||
|
order?: 'start-first' | 'stop-first';
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
};
|
||||||
|
update_config?: {
|
||||||
|
parallelism?: number | string;
|
||||||
|
delay?: string;
|
||||||
|
failure_action?: string;
|
||||||
|
monitor?: string;
|
||||||
|
max_failure_ratio?: number | string;
|
||||||
|
order?: 'start-first' | 'stop-first';
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
};
|
||||||
|
resources?: {
|
||||||
|
limits?: {
|
||||||
|
cpus?: number | string;
|
||||||
|
memory?: string;
|
||||||
|
pids?: number | string;
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
};
|
||||||
|
reservations?: {
|
||||||
|
cpus?: number | string;
|
||||||
|
memory?: string;
|
||||||
|
generic_resources?: DefinitionsGenericResources;
|
||||||
|
devices?: DefinitionsDevices;
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
};
|
||||||
|
restart_policy?: {
|
||||||
|
condition?: string;
|
||||||
|
delay?: string;
|
||||||
|
max_attempts?: number | string;
|
||||||
|
window?: string;
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
};
|
||||||
|
placement?: {
|
||||||
|
constraints?: string[];
|
||||||
|
preferences?: {
|
||||||
|
spread?: string;
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
}[];
|
||||||
|
max_replicas_per_node?: number | string;
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
} | null;
|
||||||
|
export type ExtraHosts = {} | string[];
|
||||||
|
export type ServiceConfigOrSecret = (
|
||||||
|
| string
|
||||||
|
| {
|
||||||
|
source?: string;
|
||||||
|
target?: string;
|
||||||
|
uid?: string;
|
||||||
|
gid?: string;
|
||||||
|
mode?: number | string;
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
}
|
||||||
|
)[];
|
||||||
|
export type Command = null | string | string[];
|
||||||
|
export type EnvFile =
|
||||||
|
| string
|
||||||
|
| (
|
||||||
|
| string
|
||||||
|
| {
|
||||||
|
path: string;
|
||||||
|
format?: string;
|
||||||
|
required?: boolean | string;
|
||||||
|
}
|
||||||
|
)[];
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `PropertiesNetworks`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^[a-zA-Z0-9._-]+$".
|
||||||
|
*/
|
||||||
|
export type DefinitionsNetwork = {
|
||||||
|
name?: string;
|
||||||
|
driver?: string;
|
||||||
|
driver_opts?: {
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^.+$".
|
||||||
|
*/
|
||||||
|
[k: string]: string | number;
|
||||||
|
};
|
||||||
|
ipam?: {
|
||||||
|
driver?: string;
|
||||||
|
config?: {
|
||||||
|
subnet?: string;
|
||||||
|
ip_range?: string;
|
||||||
|
gateway?: string;
|
||||||
|
aux_addresses?: {
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^.+$".
|
||||||
|
*/
|
||||||
|
[k: string]: string;
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
}[];
|
||||||
|
options?: {
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^.+$".
|
||||||
|
*/
|
||||||
|
[k: string]: string;
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
};
|
||||||
|
external?:
|
||||||
|
| boolean
|
||||||
|
| string
|
||||||
|
| {
|
||||||
|
name?: string;
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
};
|
||||||
|
internal?: boolean | string;
|
||||||
|
enable_ipv6?: boolean | string;
|
||||||
|
attachable?: boolean | string;
|
||||||
|
labels?: ListOrDict;
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
} & Network;
|
||||||
|
export type Network = {
|
||||||
|
name?: string;
|
||||||
|
driver?: string;
|
||||||
|
driver_opts?: {
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^.+$".
|
||||||
|
*/
|
||||||
|
[k: string]: string | number;
|
||||||
|
};
|
||||||
|
ipam?: {
|
||||||
|
driver?: string;
|
||||||
|
config?: {
|
||||||
|
subnet?: string;
|
||||||
|
ip_range?: string;
|
||||||
|
gateway?: string;
|
||||||
|
aux_addresses?: {
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^.+$".
|
||||||
|
*/
|
||||||
|
[k: string]: string;
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
}[];
|
||||||
|
options?: {
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^.+$".
|
||||||
|
*/
|
||||||
|
[k: string]: string;
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
};
|
||||||
|
external?:
|
||||||
|
| boolean
|
||||||
|
| string
|
||||||
|
| {
|
||||||
|
name?: string;
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
};
|
||||||
|
internal?: boolean | string;
|
||||||
|
enable_ipv6?: boolean | string;
|
||||||
|
attachable?: boolean | string;
|
||||||
|
labels?: ListOrDict;
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
} | null;
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `PropertiesVolumes`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^[a-zA-Z0-9._-]+$".
|
||||||
|
*/
|
||||||
|
export type DefinitionsVolume = {
|
||||||
|
name?: string;
|
||||||
|
driver?: string;
|
||||||
|
driver_opts?: {
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^.+$".
|
||||||
|
*/
|
||||||
|
[k: string]: string | number;
|
||||||
|
};
|
||||||
|
external?:
|
||||||
|
| boolean
|
||||||
|
| string
|
||||||
|
| {
|
||||||
|
name?: string;
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
};
|
||||||
|
labels?: ListOrDict;
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
} & Volume;
|
||||||
|
export type Volume = {
|
||||||
|
name?: string;
|
||||||
|
driver?: string;
|
||||||
|
driver_opts?: {
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^.+$".
|
||||||
|
*/
|
||||||
|
[k: string]: string | number;
|
||||||
|
};
|
||||||
|
external?:
|
||||||
|
| boolean
|
||||||
|
| string
|
||||||
|
| {
|
||||||
|
name?: string;
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
};
|
||||||
|
labels?: ListOrDict;
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
} | null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Compose file is a YAML file defining a multi-containers based application.
|
||||||
|
*/
|
||||||
|
export interface ComposeSpecification {
|
||||||
|
/**
|
||||||
|
* declared for backward compatibility, ignored.
|
||||||
|
*/
|
||||||
|
version?: string;
|
||||||
|
/**
|
||||||
|
* define the Compose project name, until user defines one explicitly.
|
||||||
|
*/
|
||||||
|
name?: string;
|
||||||
|
/**
|
||||||
|
* compose sub-projects to be included.
|
||||||
|
*/
|
||||||
|
include?: DefinitionsInclude[];
|
||||||
|
services?: PropertiesServices;
|
||||||
|
networks?: PropertiesNetworks;
|
||||||
|
volumes?: PropertiesVolumes;
|
||||||
|
secrets?: PropertiesSecrets;
|
||||||
|
configs?: PropertiesConfigs;
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `ComposeSpecification`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
}
|
||||||
|
export interface PropertiesServices {
|
||||||
|
[k: string]: DefinitionsService;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `PropertiesServices`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^[a-zA-Z0-9._-]+$".
|
||||||
|
*/
|
||||||
|
export interface DefinitionsService {
|
||||||
|
develop?: DefinitionsDevelopment;
|
||||||
|
deploy?: DefinitionsDeployment;
|
||||||
|
annotations?: ListOrDict;
|
||||||
|
attach?: boolean | string;
|
||||||
|
build?:
|
||||||
|
| string
|
||||||
|
| {
|
||||||
|
context?: string;
|
||||||
|
dockerfile?: string;
|
||||||
|
dockerfile_inline?: string;
|
||||||
|
entitlements?: string[];
|
||||||
|
args?: ListOrDict;
|
||||||
|
ssh?: ListOrDict;
|
||||||
|
labels?: ListOrDict;
|
||||||
|
cache_from?: string[];
|
||||||
|
cache_to?: string[];
|
||||||
|
no_cache?: boolean | string;
|
||||||
|
additional_contexts?: ListOrDict;
|
||||||
|
network?: string;
|
||||||
|
pull?: boolean | string;
|
||||||
|
target?: string;
|
||||||
|
shm_size?: number | string;
|
||||||
|
extra_hosts?: ExtraHosts;
|
||||||
|
isolation?: string;
|
||||||
|
privileged?: boolean | string;
|
||||||
|
secrets?: ServiceConfigOrSecret;
|
||||||
|
tags?: string[];
|
||||||
|
ulimits?: Ulimits;
|
||||||
|
platforms?: string[];
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
};
|
||||||
|
blkio_config?: {
|
||||||
|
device_read_bps?: BlkioLimit[];
|
||||||
|
device_read_iops?: BlkioLimit[];
|
||||||
|
device_write_bps?: BlkioLimit[];
|
||||||
|
device_write_iops?: BlkioLimit[];
|
||||||
|
weight?: number | string;
|
||||||
|
weight_device?: BlkioWeight[];
|
||||||
|
};
|
||||||
|
cap_add?: string[];
|
||||||
|
cap_drop?: string[];
|
||||||
|
cgroup?: 'host' | 'private';
|
||||||
|
cgroup_parent?: string;
|
||||||
|
command?: Command;
|
||||||
|
configs?: ServiceConfigOrSecret;
|
||||||
|
container_name?: string;
|
||||||
|
cpu_count?: string | number;
|
||||||
|
cpu_percent?: string | number;
|
||||||
|
cpu_shares?: number | string;
|
||||||
|
cpu_quota?: number | string;
|
||||||
|
cpu_period?: number | string;
|
||||||
|
cpu_rt_period?: number | string;
|
||||||
|
cpu_rt_runtime?: number | string;
|
||||||
|
cpus?: number | string;
|
||||||
|
cpuset?: string;
|
||||||
|
credential_spec?: {
|
||||||
|
config?: string;
|
||||||
|
file?: string;
|
||||||
|
registry?: string;
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
};
|
||||||
|
depends_on?:
|
||||||
|
| ListOfStrings
|
||||||
|
| {
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^[a-zA-Z0-9._-]+$".
|
||||||
|
*/
|
||||||
|
[k: string]: {
|
||||||
|
restart?: boolean | string;
|
||||||
|
required?: boolean;
|
||||||
|
condition: 'service_started' | 'service_healthy' | 'service_completed_successfully';
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
device_cgroup_rules?: ListOfStrings;
|
||||||
|
devices?: (
|
||||||
|
| string
|
||||||
|
| {
|
||||||
|
source: string;
|
||||||
|
target?: string;
|
||||||
|
permissions?: string;
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
}
|
||||||
|
)[];
|
||||||
|
dns?: StringOrList;
|
||||||
|
dns_opt?: string[];
|
||||||
|
dns_search?: StringOrList;
|
||||||
|
domainname?: string;
|
||||||
|
entrypoint?: Command;
|
||||||
|
env_file?: EnvFile;
|
||||||
|
environment?: ListOrDict;
|
||||||
|
expose?: (string | number)[];
|
||||||
|
extends?:
|
||||||
|
| string
|
||||||
|
| {
|
||||||
|
service: string;
|
||||||
|
file?: string;
|
||||||
|
};
|
||||||
|
external_links?: string[];
|
||||||
|
extra_hosts?: ExtraHosts;
|
||||||
|
group_add?: (string | number)[];
|
||||||
|
healthcheck?: DefinitionsHealthcheck;
|
||||||
|
hostname?: string;
|
||||||
|
image?: string;
|
||||||
|
init?: boolean | string;
|
||||||
|
ipc?: string;
|
||||||
|
isolation?: string;
|
||||||
|
labels?: ListOrDict;
|
||||||
|
links?: string[];
|
||||||
|
logging?: {
|
||||||
|
driver?: string;
|
||||||
|
options?: {
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^.+$".
|
||||||
|
*/
|
||||||
|
[k: string]: string | number | null;
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
};
|
||||||
|
mac_address?: string;
|
||||||
|
mem_limit?: number | string;
|
||||||
|
mem_reservation?: string | number;
|
||||||
|
mem_swappiness?: number | string;
|
||||||
|
memswap_limit?: number | string;
|
||||||
|
network_mode?: string;
|
||||||
|
networks?:
|
||||||
|
| ListOfStrings
|
||||||
|
| {
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^[a-zA-Z0-9._-]+$".
|
||||||
|
*/
|
||||||
|
[k: string]: {
|
||||||
|
aliases?: ListOfStrings;
|
||||||
|
ipv4_address?: string;
|
||||||
|
ipv6_address?: string;
|
||||||
|
link_local_ips?: ListOfStrings;
|
||||||
|
mac_address?: string;
|
||||||
|
driver_opts?: {
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^.+$".
|
||||||
|
*/
|
||||||
|
[k: string]: string | number;
|
||||||
|
};
|
||||||
|
priority?: number;
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
} | null;
|
||||||
|
};
|
||||||
|
oom_kill_disable?: boolean | string;
|
||||||
|
oom_score_adj?: string | number;
|
||||||
|
pid?: string | null;
|
||||||
|
pids_limit?: number | string;
|
||||||
|
platform?: string;
|
||||||
|
ports?: (
|
||||||
|
| number
|
||||||
|
| string
|
||||||
|
| {
|
||||||
|
name?: string;
|
||||||
|
mode?: string;
|
||||||
|
host_ip?: string;
|
||||||
|
target?: number | string;
|
||||||
|
published?: string | number;
|
||||||
|
protocol?: string;
|
||||||
|
app_protocol?: string;
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
}
|
||||||
|
)[];
|
||||||
|
post_start?: DefinitionsServiceHook[];
|
||||||
|
pre_stop?: DefinitionsServiceHook[];
|
||||||
|
privileged?: boolean | string;
|
||||||
|
profiles?: ListOfStrings;
|
||||||
|
pull_policy?: 'always' | 'never' | 'if_not_present' | 'build' | 'missing';
|
||||||
|
read_only?: boolean | string;
|
||||||
|
restart?: string;
|
||||||
|
runtime?: string;
|
||||||
|
scale?: number | string;
|
||||||
|
security_opt?: string[];
|
||||||
|
shm_size?: number | string;
|
||||||
|
secrets?: ServiceConfigOrSecret;
|
||||||
|
sysctls?: ListOrDict;
|
||||||
|
stdin_open?: boolean | string;
|
||||||
|
stop_grace_period?: string;
|
||||||
|
stop_signal?: string;
|
||||||
|
storage_opt?: {
|
||||||
|
[k: string]: unknown;
|
||||||
|
};
|
||||||
|
tmpfs?: StringOrList;
|
||||||
|
tty?: boolean | string;
|
||||||
|
ulimits?: Ulimits;
|
||||||
|
user?: string;
|
||||||
|
uts?: string;
|
||||||
|
userns_mode?: string;
|
||||||
|
volumes?: (
|
||||||
|
| string
|
||||||
|
| {
|
||||||
|
type: string;
|
||||||
|
source?: string;
|
||||||
|
target?: string;
|
||||||
|
read_only?: boolean | string;
|
||||||
|
consistency?: string;
|
||||||
|
bind?: {
|
||||||
|
propagation?: string;
|
||||||
|
create_host_path?: boolean | string;
|
||||||
|
selinux?: 'z' | 'Z';
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
};
|
||||||
|
volume?: {
|
||||||
|
nocopy?: boolean | string;
|
||||||
|
subpath?: string;
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
};
|
||||||
|
tmpfs?: {
|
||||||
|
size?: number | string;
|
||||||
|
mode?: number | string;
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
}
|
||||||
|
)[];
|
||||||
|
volumes_from?: string[];
|
||||||
|
working_dir?: string;
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `DefinitionsService`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
}
|
||||||
|
export interface Ulimits {
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `Ulimits`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^[a-z]+$".
|
||||||
|
*/
|
||||||
|
[k: string]:
|
||||||
|
| (number | string)
|
||||||
|
| {
|
||||||
|
hard: number | string;
|
||||||
|
soft: number | string;
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
export interface BlkioLimit {
|
||||||
|
path?: string;
|
||||||
|
rate?: number | string;
|
||||||
|
}
|
||||||
|
export interface BlkioWeight {
|
||||||
|
path?: string;
|
||||||
|
weight?: number | string;
|
||||||
|
}
|
||||||
|
export interface DefinitionsHealthcheck {
|
||||||
|
disable?: boolean | string;
|
||||||
|
interval?: string;
|
||||||
|
retries?: number | string;
|
||||||
|
test?: string | string[];
|
||||||
|
timeout?: string;
|
||||||
|
start_period?: string;
|
||||||
|
start_interval?: string;
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `DefinitionsHealthcheck`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
}
|
||||||
|
export interface DefinitionsServiceHook {
|
||||||
|
command?: Command;
|
||||||
|
user?: string;
|
||||||
|
privileged?: boolean | string;
|
||||||
|
working_dir?: string;
|
||||||
|
environment?: ListOrDict;
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `DefinitionsServiceHook`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
}
|
||||||
|
export interface PropertiesNetworks {
|
||||||
|
[k: string]: DefinitionsNetwork;
|
||||||
|
}
|
||||||
|
export interface PropertiesVolumes {
|
||||||
|
[k: string]: DefinitionsVolume;
|
||||||
|
}
|
||||||
|
export interface PropertiesSecrets {
|
||||||
|
[k: string]: DefinitionsSecret;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `PropertiesSecrets`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^[a-zA-Z0-9._-]+$".
|
||||||
|
*/
|
||||||
|
export interface DefinitionsSecret {
|
||||||
|
name?: string;
|
||||||
|
environment?: string;
|
||||||
|
file?: string;
|
||||||
|
external?:
|
||||||
|
| boolean
|
||||||
|
| string
|
||||||
|
| {
|
||||||
|
name?: string;
|
||||||
|
[k: string]: unknown;
|
||||||
|
};
|
||||||
|
labels?: ListOrDict;
|
||||||
|
driver?: string;
|
||||||
|
driver_opts?: {
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^.+$".
|
||||||
|
*/
|
||||||
|
[k: string]: string | number;
|
||||||
|
};
|
||||||
|
template_driver?: string;
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `DefinitionsSecret`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
}
|
||||||
|
export interface PropertiesConfigs {
|
||||||
|
[k: string]: DefinitionsConfig;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `PropertiesConfigs`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^[a-zA-Z0-9._-]+$".
|
||||||
|
*/
|
||||||
|
export interface DefinitionsConfig {
|
||||||
|
name?: string;
|
||||||
|
content?: string;
|
||||||
|
environment?: string;
|
||||||
|
file?: string;
|
||||||
|
external?:
|
||||||
|
| boolean
|
||||||
|
| string
|
||||||
|
| {
|
||||||
|
name?: string;
|
||||||
|
[k: string]: unknown;
|
||||||
|
};
|
||||||
|
labels?: ListOrDict;
|
||||||
|
template_driver?: string;
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `DefinitionsConfig`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
}
|
||||||
2
docker/lib/index.ts
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
export * from 'lib/build';
|
||||||
|
export * from 'lib/types';
|
||||||
57
docker/lib/types.ts
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
export enum ServiceName {
|
||||||
|
ImmichServer = 'immich-server',
|
||||||
|
ImmichMachineLearning = 'immich-machine-learning',
|
||||||
|
Postgres = 'immich-postgres',
|
||||||
|
Redis = 'immich-redis',
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum ContainerName {
|
||||||
|
ImmichServer = 'immich-server',
|
||||||
|
ImmichMachineLearning = 'immich-machine-learning',
|
||||||
|
Postgres = 'immich-postgres',
|
||||||
|
Redis = 'immich-redis',
|
||||||
|
}
|
||||||
|
|
||||||
|
export type BaseOptions = {
|
||||||
|
releaseVersion: string;
|
||||||
|
healthchecks?: boolean;
|
||||||
|
machineLearning: boolean;
|
||||||
|
containerNames?: boolean;
|
||||||
|
serverTimeZone?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type GeneratorOptions = (BaseOptions & FolderOptions & PostgresOptions) & RedisOptions;
|
||||||
|
|
||||||
|
export type FolderOptions = {
|
||||||
|
baseLocation: string;
|
||||||
|
encodedVideoLocation?: string;
|
||||||
|
libraryLocation?: string;
|
||||||
|
uploadLocation?: string;
|
||||||
|
profileLocation?: string;
|
||||||
|
thumbnailsLocation?: string;
|
||||||
|
backupsLocation?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type PostgresOptions = InternalPostgresOptions | ExternalPostgresOptions;
|
||||||
|
export type InternalPostgresOptions = {
|
||||||
|
postgresUser: string;
|
||||||
|
postgresPassword: string;
|
||||||
|
postgresDatabase: string;
|
||||||
|
postgresDataLocation: string;
|
||||||
|
};
|
||||||
|
export type ExternalPostgresOptions = { postgresUrl: string; postgresVectorExtension?: VectorExtension };
|
||||||
|
|
||||||
|
export type RedisOptions = ExternalRedisOptions | IoRedisOptions | { redis: true };
|
||||||
|
export type ExternalRedisOptions = {
|
||||||
|
redisHost: string;
|
||||||
|
redisPort: number;
|
||||||
|
redisDbIndex?: number;
|
||||||
|
redisUsername?: string;
|
||||||
|
redisPassword?: string;
|
||||||
|
redisSocket?: string;
|
||||||
|
};
|
||||||
|
export type IoRedisOptions = { redisUrl: string };
|
||||||
|
|
||||||
|
export type VectorExtension = 'pgvector' | 'pgvecto.rs';
|
||||||
|
|
||||||
|
export type HardwareAccelerationPlatform = 'nvenc' | 'quicksync' | 'rkmpp' | 'vappi' | 'vaapi-wsl';
|
||||||
84
docker/lib/utils.ts
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
import {
|
||||||
|
ExternalPostgresOptions,
|
||||||
|
ExternalRedisOptions,
|
||||||
|
GeneratorOptions,
|
||||||
|
IoRedisOptions,
|
||||||
|
PostgresOptions,
|
||||||
|
RedisOptions,
|
||||||
|
ServiceName,
|
||||||
|
} from 'lib/types';
|
||||||
|
|
||||||
|
export const isExternalPostgres = (options: PostgresOptions): options is ExternalPostgresOptions =>
|
||||||
|
'postgresUrl' in options;
|
||||||
|
|
||||||
|
export const isIoRedis = (options: RedisOptions): options is IoRedisOptions => 'redisUrl' in options;
|
||||||
|
export const isExternalRedis = (options: RedisOptions): options is ExternalRedisOptions => 'redisHost' in options;
|
||||||
|
|
||||||
|
export const asQueryParams = (values: Record<string, string | number | boolean | undefined>) => {
|
||||||
|
return new URLSearchParams(
|
||||||
|
Object.entries(values)
|
||||||
|
.filter(Boolean)
|
||||||
|
.map(([key, value]) => [key, String(value)]),
|
||||||
|
).toString();
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getImmichVolumes = (options: GeneratorOptions) => {
|
||||||
|
const {
|
||||||
|
baseLocation,
|
||||||
|
encodedVideoLocation,
|
||||||
|
uploadLocation,
|
||||||
|
backupsLocation,
|
||||||
|
profileLocation,
|
||||||
|
libraryLocation,
|
||||||
|
thumbnailsLocation,
|
||||||
|
} = options;
|
||||||
|
|
||||||
|
const internalBaseLocation = '/usr/src/app/upload';
|
||||||
|
|
||||||
|
const volumes = [`${baseLocation}:${internalBaseLocation}`];
|
||||||
|
|
||||||
|
for (const { override, folder } of [
|
||||||
|
{ override: encodedVideoLocation, folder: 'encoded-video' },
|
||||||
|
{ override: libraryLocation, folder: 'library' },
|
||||||
|
{ override: uploadLocation, folder: 'upload' },
|
||||||
|
{ override: profileLocation, folder: 'profile' },
|
||||||
|
{ override: thumbnailsLocation, folder: 'thumbs' },
|
||||||
|
{ override: backupsLocation, folder: 'backups' },
|
||||||
|
]) {
|
||||||
|
if (override) {
|
||||||
|
volumes.push(`${override}:${internalBaseLocation}/${folder}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
volumes.push(`/etc/localtime:/etc/localtime:ro`);
|
||||||
|
|
||||||
|
return volumes;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getImmichEnvironment = (options: GeneratorOptions) => {
|
||||||
|
const env: Record<string, string | number | undefined> = {};
|
||||||
|
if (isExternalPostgres(options)) {
|
||||||
|
env.DB_URL = options.postgresUrl;
|
||||||
|
env.DB_VECTOR_EXTENSION = options.postgresVectorExtension;
|
||||||
|
} else {
|
||||||
|
const { postgresUser, postgresPassword, postgresDatabase } = options;
|
||||||
|
env.DB_URL = `postgres://${postgresUser}:${postgresPassword}@${ServiceName.Postgres}:5432/${postgresDatabase}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isIoRedis(options)) {
|
||||||
|
env.REDIS_URL = options.redisUrl;
|
||||||
|
} else if (isExternalRedis(options)) {
|
||||||
|
env.REDIS_HOSTNAME = options.redisHost;
|
||||||
|
env.REDIS_PORT = options.redisPort;
|
||||||
|
env.REDIS_DBINDEX = options.redisDbIndex;
|
||||||
|
env.REDIS_USERNAME = options.redisUsername;
|
||||||
|
env.REDIS_PASSWORD = options.redisPassword;
|
||||||
|
env.REDIS_SOCKET = options.redisSocket;
|
||||||
|
} else {
|
||||||
|
env.REDIS_HOSTNAME = ServiceName.Redis;
|
||||||
|
}
|
||||||
|
|
||||||
|
env.TZ = options.serverTimeZone;
|
||||||
|
|
||||||
|
return env;
|
||||||
|
};
|
||||||
4555
docker/package-lock.json
generated
Normal file
38
docker/package.json
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
{
|
||||||
|
"name": "immich-docker",
|
||||||
|
"version": "0.0.0",
|
||||||
|
"description": "A docker-compose generator for Immich",
|
||||||
|
"main": "index.js",
|
||||||
|
"scripts": {
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1",
|
||||||
|
"build": "vite build",
|
||||||
|
"generate": "npx tsx src/index.ts",
|
||||||
|
"lint": "eslint . --max-warnings 0",
|
||||||
|
"lint:fix": "npm run lint -- --fix",
|
||||||
|
"format": "prettier --check .",
|
||||||
|
"format:fix": "prettier --write ."
|
||||||
|
},
|
||||||
|
"type": "module",
|
||||||
|
"exports": "./dist/immich-docker.js",
|
||||||
|
"author": "team@immich.app",
|
||||||
|
"private": true,
|
||||||
|
"license": "GNU Affero General Public License version 3",
|
||||||
|
"dependencies": {
|
||||||
|
"js-yaml": "^4.1.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@eslint/eslintrc": "^3.2.0",
|
||||||
|
"@eslint/js": "^9.16.0",
|
||||||
|
"@types/js-yaml": "^4.0.9",
|
||||||
|
"@types/node": "^22.10.2",
|
||||||
|
"@typescript-eslint/eslint-plugin": "^8.18.0",
|
||||||
|
"@typescript-eslint/parser": "^8.18.0",
|
||||||
|
"eslint-plugin-unicorn": "^56.0.1",
|
||||||
|
"globals": "^15.13.0",
|
||||||
|
"json-schema-to-ts": "^3.1.1",
|
||||||
|
"prettier-plugin-organize-imports": "^4.1.0",
|
||||||
|
"prettier-plugin-sort-json": "^4.0.0",
|
||||||
|
"vite": "^6.0.3",
|
||||||
|
"vitest": "^2.1.8"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
global:
|
global:
|
||||||
scrape_interval: 15s
|
scrape_interval: 15s
|
||||||
evaluation_interval: 15s
|
evaluation_interval: 15s
|
||||||
|
|
||||||
scrape_configs:
|
scrape_configs:
|
||||||
|
|||||||
60
docker/src/index.ts
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
import { mkdirSync, writeFileSync } from 'node:fs';
|
||||||
|
import { buildYaml } from '../lib/index';
|
||||||
|
import { GeneratorOptions } from '../lib/types';
|
||||||
|
|
||||||
|
const main = () => {
|
||||||
|
const commonOptions = {
|
||||||
|
releaseVersion: 'v1.122.0',
|
||||||
|
baseLocation: '/home/immich/library',
|
||||||
|
serverTimeZone: 'America/New_York',
|
||||||
|
healthchecks: true,
|
||||||
|
machineLearning: true,
|
||||||
|
containerNames: true,
|
||||||
|
// hardwareAcceleration: 'nvenc',
|
||||||
|
};
|
||||||
|
|
||||||
|
const postgresOptions = {
|
||||||
|
postgresUser: 'postgres',
|
||||||
|
postgresPassword: 'postgres',
|
||||||
|
postgresDatabase: 'immich',
|
||||||
|
postgresDataLocation: '/home/immich/database',
|
||||||
|
};
|
||||||
|
|
||||||
|
const defaultOptions: GeneratorOptions = { ...commonOptions, ...postgresOptions, redis: true };
|
||||||
|
|
||||||
|
const samples: Array<{ name: string; options: GeneratorOptions }> = [
|
||||||
|
{ name: 'defaults', options: defaultOptions },
|
||||||
|
{ name: 'no-names', options: { ...defaultOptions, containerNames: false } },
|
||||||
|
{ name: 'no-healthchecks', options: { ...defaultOptions, healthchecks: false } },
|
||||||
|
{ name: 'external-ioredis', options: { ...defaultOptions, redisUrl: 'ioredis://<base64>' } },
|
||||||
|
{ name: 'external-redis', options: { ...defaultOptions, redisHost: '192.168.0.5', redisPort: 1234 } },
|
||||||
|
{
|
||||||
|
name: 'external-postgres',
|
||||||
|
options: {
|
||||||
|
...defaultOptions,
|
||||||
|
postgresUrl: 'postgres://immich:immich@localhost:5432/immich',
|
||||||
|
postgresVectorExtension: 'pgvector',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'split-storage',
|
||||||
|
options: {
|
||||||
|
...defaultOptions,
|
||||||
|
thumbnailsLocation: '/home/fast/thumbs',
|
||||||
|
encodedVideoLocation: '/home/fast/encoded-videos',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
// TODO replace with vitest test files/scripts
|
||||||
|
mkdirSync('./examples', { recursive: true });
|
||||||
|
for (const { name, options } of samples) {
|
||||||
|
const spec = buildYaml(options);
|
||||||
|
|
||||||
|
const filename = `./examples/docker-compose.${name}.yaml`;
|
||||||
|
writeFileSync(filename, spec);
|
||||||
|
console.log(`Wrote ${filename}`);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
main();
|
||||||
19
docker/tsconfig.json
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"allowJs": true,
|
||||||
|
"baseUrl": "./",
|
||||||
|
"checkJs": true,
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"forceConsistentCasingInFileNames": true,
|
||||||
|
"module": "es2020",
|
||||||
|
"moduleResolution": "bundler",
|
||||||
|
"outDir": "./dist",
|
||||||
|
"resolveJsonModule": true,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"sourceMap": true,
|
||||||
|
"strict": true,
|
||||||
|
"target": "es2022",
|
||||||
|
"types": []
|
||||||
|
},
|
||||||
|
"include": ["lib"]
|
||||||
|
}
|
||||||
25
docker/tsconfig.src.json
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"allowSyntheticDefaultImports": true,
|
||||||
|
"baseUrl": "./",
|
||||||
|
"declaration": true,
|
||||||
|
"emitDecoratorMetadata": true,
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"experimentalDecorators": true,
|
||||||
|
"forceConsistentCasingInFileNames": true,
|
||||||
|
"incremental": true,
|
||||||
|
"jsx": "react",
|
||||||
|
"lib": ["dom", "es2023"],
|
||||||
|
"module": "node16",
|
||||||
|
"moduleResolution": "node16",
|
||||||
|
"outDir": "./dist",
|
||||||
|
"preserveWatchOutput": true,
|
||||||
|
"removeComments": true,
|
||||||
|
"resolveJsonModule": true,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"sourceMap": true,
|
||||||
|
"strict": true,
|
||||||
|
"target": "es2022"
|
||||||
|
},
|
||||||
|
"include": ["src", "lib"]
|
||||||
|
}
|
||||||
20
docker/vite.config.js
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
import { resolve } from 'node:path';
|
||||||
|
import { defineConfig } from 'vite';
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
resolve: {
|
||||||
|
alias: {
|
||||||
|
lib: resolve('lib'),
|
||||||
|
src: resolve('src'),
|
||||||
|
test: resolve('test'),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
build: {
|
||||||
|
lib: {
|
||||||
|
entry: resolve(__dirname, 'lib/index.ts'),
|
||||||
|
name: 'immich-docker',
|
||||||
|
// the proper extensions will be added
|
||||||
|
fileName: 'immich-docker',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
@@ -1 +1 @@
|
|||||||
22.11.0
|
22.12.0
|
||||||
|
|||||||
@@ -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?
|
### 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.
|
It is recommended to read about [Storage Template](https://immich.app/docs/administration/storage-template) before activation.
|
||||||
|
|
||||||
### Can I add my existing photo library?
|
### 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?
|
### 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?
|
### 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?
|
### 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?
|
### 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?
|
### 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?
|
### 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.
|
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.
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
<summary>docker-compose.yml</summary>
|
<summary>docker-compose.yml</summary>
|
||||||
@@ -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.
|
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 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 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.
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
## Database
|
## Database
|
||||||
|
|
||||||
### Why am I getting database ownership errors?
|
### 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.
|
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?
|
### 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.
|
A result of `on` means that checksums are enabled.
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
@@ -419,7 +429,7 @@ docker exec -it immich_postgres psql --dbname=immich --username=<DB_USERNAME> --
|
|||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
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.
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
<summary>Check for database corruption</summary>
|
<summary>Check for database corruption</summary>
|
||||||
|
|||||||
@@ -58,19 +58,24 @@ docker compose up -d # Start remainder of Immich apps
|
|||||||
<TabItem value="Windows system (PowerShell)" label="Windows system (PowerShell)">
|
<TabItem value="Windows system (PowerShell)" label="Windows system (PowerShell)">
|
||||||
|
|
||||||
```powershell title='Backup'
|
```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'
|
```powershell title='Restore'
|
||||||
docker compose down -v # CAUTION! Deletes all Immich data to start from scratch
|
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
|
## 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
|
# 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 pull # Update to latest version of Immich (if desired)
|
||||||
docker compose create # Create Docker containers for Immich apps without running them
|
docker compose create # Create Docker containers for Immich apps without running them
|
||||||
docker start immich_postgres # Start Postgres server
|
docker start immich_postgres # Start Postgres server
|
||||||
sleep 10 # Wait for Postgres server to start up
|
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
|
# 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
|
docker compose up -d # Start remainder of Immich apps
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -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:
|
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:
|
||||||
|
|
||||||
<img src={require('./img/user-notifications-settings.png').default} width="80%" title="User notification settings" />
|
<img src={require('./img/user-notifications-settings.png').default} width="80%" title="User notification settings" />
|
||||||
|
|
||||||
|
## 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.
|
||||||
|
|
||||||
|
<img src={require('./img/user-notifications-templates.png').default} width="80%" title="User notification templates" />
|
||||||
|
|||||||
BIN
docs/docs/administration/img/user-notifications-templates.png
Normal file
|
After Width: | Height: | Size: 195 KiB |
@@ -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)
|
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
|
## Server Settings
|
||||||
|
|
||||||
### External Domain
|
### External Domain
|
||||||
@@ -205,4 +209,68 @@ When this option is enabled the `immich-server` will periodically make requests
|
|||||||
|
|
||||||
## Video Transcoding Settings
|
## 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).
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
# PR Checklist
|
# 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:
|
When contributing code through a pull request, please check the following:
|
||||||
|
|
||||||
## Web Checks
|
## 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 lint` (linting via ESLint)
|
||||||
- [ ] `npm run format` (formatting via Prettier)
|
- [ ] `npm run format` (formatting via Prettier)
|
||||||
- [ ] `npm run check:svelte` (Type checking via SvelteKit)
|
- [ ] `npm run check:svelte` (Type checking via SvelteKit)
|
||||||
|
- [ ] `npm run check:typescript` (check typescript)
|
||||||
- [ ] `npm test` (unit tests)
|
- [ ] `npm test` (unit tests)
|
||||||
|
|
||||||
## Documentation
|
## Documentation
|
||||||
|
|||||||
@@ -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.
|
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.
|
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
|
#### Connect web to a remote backend
|
||||||
|
|
||||||
|
|||||||
BIN
docs/docs/features/img/mobile-upload-open-photo.png
Normal file
|
After Width: | Height: | Size: 379 KiB |
BIN
docs/docs/features/img/mobile-upload-selected-photos.png
Normal file
|
After Width: | Height: | Size: 2.1 MiB |
@@ -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 MobileAppDownload from '/docs/partials/_mobile-app-download.md';
|
||||||
import MobileAppLogin from '/docs/partials/_mobile-app-login.md';
|
import MobileAppLogin from '/docs/partials/_mobile-app-login.md';
|
||||||
import MobileAppBackup from '/docs/partials/_mobile-app-backup.md';
|
import MobileAppBackup from '/docs/partials/_mobile-app-backup.md';
|
||||||
|
import { cloudDonePath, cloudOffPath } from '@site/src/components/svg-paths';
|
||||||
|
|
||||||
# Mobile App
|
# 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).
|
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 **<ins>Settings -> Photo Grid</ins>** 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. <Icon path={mdiCloudOffOutline} size={1} /> - Local-only asset; not synced to the server
|
||||||
|
2. <Icon path={mdiCloudCheckOutline} size={1} /> - 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 **<ins>Library -> On this device</ins>**. To selectively upload photos from these albums, simply select the local-only photos and tap on "Upload" button in the dynamic bottom menu.
|
||||||
|
|
||||||
|
<img
|
||||||
|
src={require('./img/mobile-upload-open-photo.png').default}
|
||||||
|
width="50%"
|
||||||
|
title="Upload button on local asset preview"
|
||||||
|
/>
|
||||||
|
<img
|
||||||
|
src={require('./img/mobile-upload-selected-photos.png').default}
|
||||||
|
width="40%"
|
||||||
|
title="Upload button after photos selection"
|
||||||
|
/>
|
||||||
|
|
||||||
## Album Sync
|
## 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.
|
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.
|
||||||
|
|||||||
@@ -98,6 +98,10 @@ SELECT * FROM "move_history";
|
|||||||
SELECT * FROM "users";
|
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
|
## System Config
|
||||||
|
|
||||||
```sql title="Custom settings"
|
```sql title="Custom settings"
|
||||||
|
|||||||
@@ -1,18 +1,20 @@
|
|||||||
# Remote Machine Learning
|
# 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):
|
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.
|
||||||
|
|
||||||
- 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`.
|
|
||||||
|
|
||||||
:::info
|
:::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
|
:::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
|
```yaml
|
||||||
@@ -37,8 +39,26 @@ volumes:
|
|||||||
model-cache:
|
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`
|
||||||
|
|
||||||
:::caution
|
:::info
|
||||||
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.
|
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.
|
||||||
|
|
||||||
|
:::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.
|
||||||
:::
|
:::
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ The default configuration looks like this:
|
|||||||
},
|
},
|
||||||
"machineLearning": {
|
"machineLearning": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"url": "http://immich-machine-learning:3003",
|
"urls": ["http://immich-machine-learning:3003"],
|
||||||
"clip": {
|
"clip": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"modelName": "ViT-B-32__openai"
|
"modelName": "ViT-B-32__openai"
|
||||||
|
|||||||
@@ -7,10 +7,9 @@ import ExampleEnv from '!!raw-loader!../../../docker/example.env';
|
|||||||
|
|
||||||
# Docker Compose [Recommended]
|
# Docker Compose [Recommended]
|
||||||
|
|
||||||
Docker Compose is the recommended method to run Immich in production. Below are the steps to deploy Immich with Docker Compose.
|
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.
|
|
||||||
|
|
||||||
### 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.
|
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
|
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"
|
```bash title="Get docker-compose.yml file"
|
||||||
wget -O docker-compose.yml https://github.com/immich-app/immich/releases/latest/download/docker-compose.yml
|
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
|
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"
|
```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
|
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
|
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
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
<summary>
|
<summary>
|
||||||
@@ -54,31 +52,37 @@ Optionally, you can enable hardware acceleration for machine learning and transc
|
|||||||
<CodeBlock language="bash">{ExampleEnv}</CodeBlock>
|
<CodeBlock language="bash">{ExampleEnv}</CodeBlock>
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
- Populate custom database information if necessary.
|
- Populate `UPLOAD_LOCATION` with your preferred location for storing backup assets. It should be a new directory on the server with enough free space.
|
||||||
- Populate `UPLOAD_LOCATION` with your preferred location for storing backup assets.
|
|
||||||
- Consider changing `DB_PASSWORD` to a custom value. Postgres is not publically exposed, so this password is only used for local authentication.
|
- 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.
|
- Set your timezone by uncommenting the `TZ=` line.
|
||||||
|
- Populate custom database information if necessary.
|
||||||
|
|
||||||
### Step 3 - Start the containers
|
:::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).
|
||||||
|
:::
|
||||||
|
|
||||||
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`.
|
## 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 this command:
|
||||||
|
|
||||||
```bash title="Start the containers using docker compose command"
|
```bash title="Start the containers using docker compose command"
|
||||||
docker compose up -d
|
docker compose up -d
|
||||||
```
|
```
|
||||||
|
|
||||||
:::info Docker version
|
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`).
|
||||||
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].
|
|
||||||
|
|
||||||
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:
|
:::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 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:
|
||||||
|
|
||||||
```
|
```
|
||||||
The Compose file './docker-compose.yml' is invalid because:
|
The Compose file './docker-compose.yml' is invalid because:
|
||||||
'name' does not match any of the regexes: '^x-'
|
'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
|
:::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]).
|
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
|
:::danger Breaking Changes
|
||||||
It is important to follow breaking updates to avoid problems. You can see versions that had breaking changes [here][breaking].
|
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.
|
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
|
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
|
:::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].
|
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
|
[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
|
[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
|
[releases]: https://github.com/immich-app/immich/releases
|
||||||
[docker-repo]: https://docs.docker.com/engine/install/ubuntu/#install-using-the-repository
|
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 8.7 KiB After Width: | Height: | Size: 9.4 KiB |
|
Before Width: | Height: | Size: 86 KiB After Width: | Height: | Size: 127 KiB |
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 35 KiB |
|
Before Width: | Height: | Size: 79 KiB After Width: | Height: | Size: 128 KiB |
|
Before Width: | Height: | Size: 6.0 KiB After Width: | Height: | Size: 23 KiB |
|
Before Width: | Height: | Size: 4.0 KiB After Width: | Height: | Size: 5.5 KiB |
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 63 KiB |
|
Before Width: | Height: | Size: 6.2 KiB After Width: | Height: | Size: 24 KiB |
|
Before Width: | Height: | Size: 9.9 KiB After Width: | Height: | Size: 12 KiB |
BIN
docs/docs/install/img/truenas10.png
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
docs/docs/install/img/truenas11.png
Normal file
|
After Width: | Height: | Size: 4.9 KiB |
BIN
docs/docs/install/img/truenas12.png
Normal file
|
After Width: | Height: | Size: 19 KiB |
@@ -8,30 +8,43 @@ Hardware and software requirements for Immich:
|
|||||||
|
|
||||||
## Software
|
## Software
|
||||||
|
|
||||||
- [Docker](https://docs.docker.com/engine/install/)
|
Immich requires [**Docker**](https://docs.docker.com/get-started/get-docker/) with the **Docker Compose plugin**:
|
||||||
- [Docker Compose](https://docs.docker.com/compose/install/)
|
|
||||||
|
- **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
|
:::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
|
## Hardware
|
||||||
|
|
||||||
- **OS**: Recommended Linux operating system (Ubuntu, Debian, etc).
|
- **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/).
|
- Non-Linux OSes tend to provide a poor Docker experience and are strongly discouraged.
|
||||||
- macOS is supported with [Docker Desktop on Mac](https://docs.docker.com/desktop/install/mac-install/).
|
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.
|
- **RAM**: Minimum 4GB, recommended 6GB.
|
||||||
- **CPU**: Minimum 2 cores, recommended 4 cores.
|
- **CPU**: Minimum 2 cores, recommended 4 cores.
|
||||||
- **Storage**: Recommended Unix-compatible filesystem (EXT4, ZFS, APFS, etc.) with support for user/group ownership and permissions.
|
- **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.
|
- 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
|
### Special requirements for Windows users
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
<summary>Database storage on Windows systems</summary>
|
<summary>Database storage on Windows systems</summary>
|
||||||
|
|
||||||
The Immich Postgres database (`DB_DATA_LOCATION`) must be located on a filesystem that supports user/group
|
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.
|
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`).
|
It will not work in WSL (Windows Subsystem for Linux) when using a mounted host directory (commonly under `/mnt`).
|
||||||
|
|||||||
@@ -7,7 +7,9 @@ sidebar_position: 80
|
|||||||
:::note
|
:::note
|
||||||
This is a community contribution and not officially supported by the Immich team, but included here for convenience.
|
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.
|
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.
|
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.
|
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.
|
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 can configure environment variables at any time after deploying the application.
|
You may also configure environment variables at any time after deploying the application.
|
||||||
|
|
||||||
You can allow SCALE to create the datasets Immich requires automatically during app installation.
|
### Setting up Storage Datasets
|
||||||
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**.
|
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.
|
||||||
You can organize these as one parent with seven child datasets, for example `mnt/tank/immich/library`, `mnt/tank/immich/pgBackup`, and so on.
|
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.
|
||||||
|
|
||||||
|
<img
|
||||||
|
src={require('./img/truenas12.png').default}
|
||||||
|
width="30%"
|
||||||
|
alt="Immich App Widget"
|
||||||
|
className="border rounded-xl"
|
||||||
|
/>
|
||||||
|
|
||||||
:::info Permissions
|
:::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 **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
|
## Installing the Immich Application
|
||||||
@@ -47,6 +57,8 @@ className="border rounded-xl"
|
|||||||
|
|
||||||
Click on the widget to open the **Immich** application details screen.
|
Click on the widget to open the **Immich** application details screen.
|
||||||
|
|
||||||
|
<br/><br/>
|
||||||
|
|
||||||
<img
|
<img
|
||||||
src={require('./img/truenas02.png').default}
|
src={require('./img/truenas02.png').default}
|
||||||
width="100%"
|
width="100%"
|
||||||
@@ -56,9 +68,13 @@ className="border rounded-xl"
|
|||||||
|
|
||||||
Click **Install** to open the Immich application configuration screen.
|
Click **Install** to open the Immich application configuration screen.
|
||||||
|
|
||||||
|
<br/><br/>
|
||||||
|
|
||||||
Application configuration settings are presented in several sections, each explained below.
|
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.
|
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
|
||||||
|
|
||||||
<img
|
<img
|
||||||
src={require('./img/truenas03.png').default}
|
src={require('./img/truenas03.png').default}
|
||||||
width="100%"
|
width="100%"
|
||||||
@@ -66,21 +82,123 @@ alt="Install Immich Screen"
|
|||||||
className="border rounded-xl"
|
className="border rounded-xl"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
Accept the default values in **Application Name** and **Version**.
|
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 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.
|
||||||
|
|
||||||
|
### Immich Configuration
|
||||||
|
|
||||||
|
<img
|
||||||
|
src={require('./img/truenas05.png').default}
|
||||||
|
width="40%"
|
||||||
|
alt="Configuration Settings"
|
||||||
|
className="border rounded-xl"
|
||||||
|
/>
|
||||||
|
|
||||||
Accept the default value in **Timezone** or change to match your local timezone.
|
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.
|
**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**.
|
Untick **Enable Machine Learning** if you will not use face recognition, image search, and smart duplicate detection.
|
||||||
|
|
||||||
|
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).
|
||||||
|
|
||||||
|
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`.
|
||||||
|
|
||||||
|
The **Redis Password** should be set to a custom value using only the characters `A-Za-z0-9`.
|
||||||
|
|
||||||
|
Accept the **Log Level** default of **Log**.
|
||||||
|
|
||||||
|
Leave **Hugging Face Endpoint** blank. (This is for downloading ML models from a different source.)
|
||||||
|
|
||||||
|
Leave **Additional Environment Variables** blank or see [Environment Variables](#environment-variables) to set before installing.
|
||||||
|
|
||||||
|
### Network Configuration
|
||||||
|
|
||||||
|
<img
|
||||||
|
src={require('./img/truenas06.png').default}
|
||||||
|
width="40%"
|
||||||
|
alt="Networking Settings"
|
||||||
|
className="border rounded-xl"
|
||||||
|
/>
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
Regardless of version, to avoid port conflicts, don't use [ports on this list](https://www.truenas.com/docs/references/defaultports/).
|
||||||
|
:::
|
||||||
|
|
||||||
|
### Storage Configuration
|
||||||
|
|
||||||
Immich requires seven storage datasets.
|
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 defaults in Resources or change the CPU and memory limits to suit your use case.
|
<img
|
||||||
|
src={require('./img/truenas07.png').default}
|
||||||
|
width="20%"
|
||||||
|
alt="Configure Storage ixVolumes"
|
||||||
|
className="border rounded-xl"
|
||||||
|
/>
|
||||||
|
|
||||||
Click **Install**.
|
:::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)
|
||||||
|
:::
|
||||||
|
|
||||||
|
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`.
|
||||||
|
|
||||||
|
<img
|
||||||
|
src={require('./img/truenas08.png').default}
|
||||||
|
width="40%"
|
||||||
|
alt="Configure Storage Host Paths"
|
||||||
|
className="border rounded-xl"
|
||||||
|
/>
|
||||||
|
The image above has example values.
|
||||||
|
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
### Additional Storage [(External Libraries)](/docs/features/libraries)
|
||||||
|
|
||||||
|
<img
|
||||||
|
src={require('./img/truenas10.png').default}
|
||||||
|
width="40%"
|
||||||
|
alt="Configure Storage Host Paths"
|
||||||
|
className="border rounded-xl"
|
||||||
|
/>
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
<!-- A section for Labels would go here but I don't know what they do. -->
|
||||||
|
|
||||||
|
### Resources Configuration
|
||||||
|
|
||||||
|
<img
|
||||||
|
src={require('./img/truenas09.png').default}
|
||||||
|
width="40%"
|
||||||
|
alt="Resource Limits"
|
||||||
|
className="border rounded-xl"
|
||||||
|
/>
|
||||||
|
|
||||||
|
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.
|
The system opens the **Installed Applications** screen with the Immich app in the **Deploying** state.
|
||||||
When the installation completes it changes to **Running**.
|
When the installation completes it changes to **Running**.
|
||||||
|
|
||||||
@@ -97,102 +215,41 @@ Click **Web Portal** on the **Application Info** widget to open the Immich web i
|
|||||||
For more information on how to use the application once installed, please refer to the [Post Install](/docs/install/post-install.mdx) guide.
|
For more information on how to use the application once installed, please refer to the [Post Install](/docs/install/post-install.mdx) guide.
|
||||||
:::
|
:::
|
||||||
|
|
||||||
## Editing Environment Variables
|
## Edit App Settings
|
||||||
|
|
||||||
Go to the **Installed Applications** screen and select Immich from the list of installed applications.
|
- 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.
|
- 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.
|
- Change any settings you would like to change.
|
||||||
You cannot edit **Storage Configuration** paths after the initial app install.
|
- 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.
|
||||||
|
|
||||||
Click **Update** to save changes.
|
## Environment Variables
|
||||||
TrueNAS automatically updates, recreates, and redeploys the Immich container with the updated 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**.
|
||||||
|
|
||||||
|
<img
|
||||||
|
src={require('./img/truenas11.png').default}
|
||||||
|
width="40%"
|
||||||
|
alt="Environment Variables"
|
||||||
|
className="border rounded-xl"
|
||||||
|
/>
|
||||||
|
|
||||||
|
:::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`.
|
||||||
|
:::
|
||||||
|
|
||||||
## Updating the App
|
## Updating the App
|
||||||
|
|
||||||
When updates become available, SCALE alerts and provides easy updates.
|
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.
|
To update the app to the latest version:
|
||||||
|
|
||||||
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.
|
- 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.
|
||||||
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.
|
- This opens an update window with some options
|
||||||
|
- You may select an Image update too.
|
||||||
## Understanding Immich Settings in TrueNAS SCALE
|
- You may view the Changelog.
|
||||||
|
- Click **Upgrade** to begin the process and open a counter dialog that shows the upgrade progress.
|
||||||
Accept the default value or enter a name in **Application Name** field.
|
- 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.
|
||||||
In most cases use the default name, but if adding a second deployment of the application you must change this name.
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
### Immich Configuration Settings
|
|
||||||
|
|
||||||
You can accept the defaults in the **Immich Configuration** settings, or enter the settings you want to use.
|
|
||||||
|
|
||||||
<img
|
|
||||||
src={require('./img/truenas05.png').default}
|
|
||||||
width="100%"
|
|
||||||
alt="Configuration Settings"
|
|
||||||
className="border rounded-xl"
|
|
||||||
/>
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
You can enter a **Public Login Message** to display on the login page, or leave it blank.
|
|
||||||
|
|
||||||
### Networking Settings
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
<img
|
|
||||||
src={require('./img/truenas06.png').default}
|
|
||||||
width="100%"
|
|
||||||
alt="Networking Settings"
|
|
||||||
className="border rounded-xl"
|
|
||||||
/>
|
|
||||||
|
|
||||||
### Storage Settings
|
|
||||||
|
|
||||||
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).
|
|
||||||
|
|
||||||
<img
|
|
||||||
src={require('./img/truenas07.png').default}
|
|
||||||
width="100%"
|
|
||||||
alt="Configure Storage ixVolumes"
|
|
||||||
className="border rounded-xl"
|
|
||||||
/>
|
|
||||||
|
|
||||||
Select **Host Path (Path that already exists on the system)** to browse to and select the datasets.
|
|
||||||
|
|
||||||
<img
|
|
||||||
src={require('./img/truenas08.png').default}
|
|
||||||
width="100%"
|
|
||||||
alt="Configure Storage Host Paths"
|
|
||||||
className="border rounded-xl"
|
|
||||||
/>
|
|
||||||
|
|
||||||
### Resource Configuration 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.
|
|
||||||
|
|
||||||
<img
|
|
||||||
src={require('./img/truenas09.png').default}
|
|
||||||
width="100%"
|
|
||||||
alt="Resource Limits"
|
|
||||||
className="border rounded-xl"
|
|
||||||
/>
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|||||||
@@ -14,13 +14,7 @@ Check the [requirements page](/docs/install/requirements) to get started.
|
|||||||
|
|
||||||
## Install and Launch via Docker Compose
|
## Install and Launch via Docker Compose
|
||||||
|
|
||||||
Follow the [Docker Compose (Recommended)](/docs/install/docker-compose) instructions
|
Follow the [Docker Compose (Recommended)](/docs/install/docker-compose) instructions to install the server.
|
||||||
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".
|
|
||||||
|
|
||||||
## Try the Web UI
|
## 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
|
The backup time differs depending on how many photos are on your mobile device. Large uploads may
|
||||||
take quite a while.
|
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.
|
You can select the **Jobs** tab to see Immich processing your photos.
|
||||||
|
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|
||||||
<img src={require('./img/backup-header.png').default} width='50%' title='Backup button' />
|
<img src={require('./img/backup-header.png').default} width='50%' title='Backup button' />
|
||||||
|
|
||||||
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.
|
||||||
|
|
||||||
<img src={require('./img/album-selection.png').default} width='50%' title='Backup button' />
|
<img src={require('./img/album-selection.png').default} width='50%' title='Backup button' />
|
||||||
|
|
||||||
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.
|
||||||
|
|||||||
6
docs/package-lock.json
generated
@@ -8,8 +8,8 @@
|
|||||||
"name": "documentation",
|
"name": "documentation",
|
||||||
"version": "0.0.0",
|
"version": "0.0.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@docusaurus/core": "^3.2.1",
|
"@docusaurus/core": "~3.5.2",
|
||||||
"@docusaurus/preset-classic": "^3.2.1",
|
"@docusaurus/preset-classic": "~3.5.2",
|
||||||
"@mdi/js": "^7.3.67",
|
"@mdi/js": "^7.3.67",
|
||||||
"@mdi/react": "^1.6.1",
|
"@mdi/react": "^1.6.1",
|
||||||
"@mdx-js/react": "^3.0.0",
|
"@mdx-js/react": "^3.0.0",
|
||||||
@@ -27,7 +27,7 @@
|
|||||||
"url": "^0.11.0"
|
"url": "^0.11.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@docusaurus/module-type-aliases": "^3.1.0",
|
"@docusaurus/module-type-aliases": "~3.5.2",
|
||||||
"@tsconfig/docusaurus": "^2.0.2",
|
"@tsconfig/docusaurus": "^2.0.2",
|
||||||
"prettier": "^3.2.4",
|
"prettier": "^3.2.4",
|
||||||
"typescript": "^5.1.6"
|
"typescript": "^5.1.6"
|
||||||
|
|||||||
@@ -16,8 +16,8 @@
|
|||||||
"write-heading-ids": "docusaurus write-heading-ids"
|
"write-heading-ids": "docusaurus write-heading-ids"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@docusaurus/core": "^3.2.1",
|
"@docusaurus/core": "~3.5.2",
|
||||||
"@docusaurus/preset-classic": "^3.2.1",
|
"@docusaurus/preset-classic": "~3.5.2",
|
||||||
"@mdi/js": "^7.3.67",
|
"@mdi/js": "^7.3.67",
|
||||||
"@mdi/react": "^1.6.1",
|
"@mdi/react": "^1.6.1",
|
||||||
"@mdx-js/react": "^3.0.0",
|
"@mdx-js/react": "^3.0.0",
|
||||||
@@ -35,8 +35,7 @@
|
|||||||
"url": "^0.11.0"
|
"url": "^0.11.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@docusaurus/module-type-aliases": "^3.1.0",
|
"@docusaurus/module-type-aliases": "~3.5.2",
|
||||||
"@tsconfig/docusaurus": "^2.0.2",
|
|
||||||
"prettier": "^3.2.4",
|
"prettier": "^3.2.4",
|
||||||
"typescript": "^5.1.6"
|
"typescript": "^5.1.6"
|
||||||
},
|
},
|
||||||
@@ -56,6 +55,6 @@
|
|||||||
"node": ">=20"
|
"node": ">=20"
|
||||||
},
|
},
|
||||||
"volta": {
|
"volta": {
|
||||||
"node": "22.11.0"
|
"node": "22.12.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -89,6 +89,11 @@ const projects: CommunityProjectProps[] = [
|
|||||||
'Share your Immich photos and albums in a safe way without exposing your Immich instance to the public.',
|
'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',
|
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 {
|
function CommunityProject({ title, description, url }: CommunityProjectProps): JSX.Element {
|
||||||
|
|||||||
24
docs/static/archived-versions.json
vendored
@@ -1,4 +1,28 @@
|
|||||||
[
|
[
|
||||||
|
{
|
||||||
|
"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",
|
"label": "v1.120.2",
|
||||||
"url": "https://v1.120.2.archive.immich.app"
|
"url": "https://v1.120.2.archive.immich.app"
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
22.11.0
|
22.12.0
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ services:
|
|||||||
- 2285:2285
|
- 2285:2285
|
||||||
|
|
||||||
redis:
|
redis:
|
||||||
image: redis:6.2-alpine@sha256:2ba50e1ac3a0ea17b736ce9db2b0a9f6f8b85d4c27d5f5accc6a416d8f42c6d5
|
image: redis:6.2-alpine@sha256:eaba718fecd1196d88533de7ba49bf903ad33664a92debb24660a922ecd9cac8
|
||||||
|
|
||||||
database:
|
database:
|
||||||
image: tensorchord/pgvecto-rs:pg14-v0.2.0@sha256:90724186f0a3517cf6914295b5ab410db9ce23190a2d9d0b9dd6463e3fa298f0
|
image: tensorchord/pgvecto-rs:pg14-v0.2.0@sha256:90724186f0a3517cf6914295b5ab410db9ce23190a2d9d0b9dd6463e3fa298f0
|
||||||
|
|||||||
749
e2e/package-lock.json
generated
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "immich-e2e",
|
"name": "immich-e2e",
|
||||||
"version": "1.120.2",
|
"version": "1.123.0",
|
||||||
"description": "",
|
"description": "",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
@@ -25,18 +25,18 @@
|
|||||||
"@immich/sdk": "file:../open-api/typescript-sdk",
|
"@immich/sdk": "file:../open-api/typescript-sdk",
|
||||||
"@playwright/test": "^1.44.1",
|
"@playwright/test": "^1.44.1",
|
||||||
"@types/luxon": "^3.4.2",
|
"@types/luxon": "^3.4.2",
|
||||||
"@types/node": "^22.9.0",
|
"@types/node": "^22.10.2",
|
||||||
"@types/oidc-provider": "^8.5.1",
|
"@types/oidc-provider": "^8.5.1",
|
||||||
"@types/pg": "^8.11.0",
|
"@types/pg": "^8.11.0",
|
||||||
"@types/pngjs": "^6.0.4",
|
"@types/pngjs": "^6.0.4",
|
||||||
"@types/supertest": "^6.0.2",
|
"@types/supertest": "^6.0.2",
|
||||||
"@typescript-eslint/eslint-plugin": "^8.0.0",
|
"@typescript-eslint/eslint-plugin": "^8.15.0",
|
||||||
"@typescript-eslint/parser": "^8.0.0",
|
"@typescript-eslint/parser": "^8.15.0",
|
||||||
"@vitest/coverage-v8": "^2.0.5",
|
"@vitest/coverage-v8": "^2.0.5",
|
||||||
"eslint": "^9.0.0",
|
"eslint": "^9.14.0",
|
||||||
"eslint-config-prettier": "^9.1.0",
|
"eslint-config-prettier": "^9.1.0",
|
||||||
"eslint-plugin-prettier": "^5.1.3",
|
"eslint-plugin-prettier": "^5.1.3",
|
||||||
"eslint-plugin-unicorn": "^55.0.0",
|
"eslint-plugin-unicorn": "^56.0.1",
|
||||||
"exiftool-vendored": "^28.3.1",
|
"exiftool-vendored": "^28.3.1",
|
||||||
"globals": "^15.9.0",
|
"globals": "^15.9.0",
|
||||||
"jose": "^5.6.3",
|
"jose": "^5.6.3",
|
||||||
@@ -53,6 +53,6 @@
|
|||||||
"vitest": "^2.0.5"
|
"vitest": "^2.0.5"
|
||||||
},
|
},
|
||||||
"volta": {
|
"volta": {
|
||||||
"node": "22.11.0"
|
"node": "22.12.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -141,6 +141,7 @@ describe('/albums', () => {
|
|||||||
expect(body).toEqual({
|
expect(body).toEqual({
|
||||||
...user1Albums[0],
|
...user1Albums[0],
|
||||||
assets: [expect.objectContaining({ isFavorite: false })],
|
assets: [expect.objectContaining({ isFavorite: false })],
|
||||||
|
lastModifiedAssetTimestamp: expect.any(String),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -297,6 +298,7 @@ describe('/albums', () => {
|
|||||||
expect(body).toEqual({
|
expect(body).toEqual({
|
||||||
...user1Albums[0],
|
...user1Albums[0],
|
||||||
assets: [expect.objectContaining({ id: user1Albums[0].assets[0].id })],
|
assets: [expect.objectContaining({ id: user1Albums[0].assets[0].id })],
|
||||||
|
lastModifiedAssetTimestamp: expect.any(String),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -327,6 +329,7 @@ describe('/albums', () => {
|
|||||||
expect(body).toEqual({
|
expect(body).toEqual({
|
||||||
...user1Albums[0],
|
...user1Albums[0],
|
||||||
assets: [expect.objectContaining({ id: user1Albums[0].assets[0].id })],
|
assets: [expect.objectContaining({ id: user1Albums[0].assets[0].id })],
|
||||||
|
lastModifiedAssetTimestamp: expect.any(String),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -340,6 +343,7 @@ describe('/albums', () => {
|
|||||||
...user1Albums[0],
|
...user1Albums[0],
|
||||||
assets: [],
|
assets: [],
|
||||||
assetCount: 1,
|
assetCount: 1,
|
||||||
|
lastModifiedAssetTimestamp: expect.any(String),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { LibraryResponseDto, LoginResponseDto, getAllLibraries, scanLibrary } from '@immich/sdk';
|
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 { Socket } from 'socket.io-client';
|
||||||
import { userDto, uuidDto } from 'src/fixtures';
|
import { userDto, uuidDto } from 'src/fixtures';
|
||||||
import { errorDto } from 'src/responses';
|
import { errorDto } from 'src/responses';
|
||||||
@@ -299,7 +299,7 @@ describe('/libraries', () => {
|
|||||||
|
|
||||||
await utils.waitForQueueFinish(admin.accessToken, 'library');
|
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`,
|
originalPath: `${testAssetDirInternal}/temp/directoryA/assetA.png`,
|
||||||
});
|
});
|
||||||
expect(assets.count).toBe(1);
|
expect(assets.count).toBe(1);
|
||||||
@@ -320,7 +320,7 @@ describe('/libraries', () => {
|
|||||||
|
|
||||||
await utils.waitForQueueFinish(admin.accessToken, 'library');
|
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.count).toBe(1);
|
||||||
expect(assets.items[0].originalPath.includes('directoryB'));
|
expect(assets.items[0].originalPath.includes('directoryB'));
|
||||||
@@ -340,7 +340,7 @@ describe('/libraries', () => {
|
|||||||
|
|
||||||
await utils.waitForQueueFinish(admin.accessToken, 'library');
|
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.count).toBe(2);
|
||||||
expect(assets.items.find((asset) => asset.originalPath.includes('directoryA'))).toBeDefined();
|
expect(assets.items.find((asset) => asset.originalPath.includes('directoryA'))).toBeDefined();
|
||||||
@@ -365,7 +365,7 @@ describe('/libraries', () => {
|
|||||||
|
|
||||||
await utils.waitForQueueFinish(admin.accessToken, 'library');
|
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.count).toBe(2);
|
||||||
expect(assets.items.find((asset) => asset.originalPath.includes('folder, a'))).toBeDefined();
|
expect(assets.items.find((asset) => asset.originalPath.includes('folder, a'))).toBeDefined();
|
||||||
@@ -393,7 +393,7 @@ describe('/libraries', () => {
|
|||||||
|
|
||||||
await utils.waitForQueueFinish(admin.accessToken, 'library');
|
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.count).toBe(2);
|
||||||
expect(assets.items.find((asset) => asset.originalPath.includes('folder{ a'))).toBeDefined();
|
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`);
|
utils.removeImageFile(`${testAssetDir}/temp/folder} b/assetB.png`);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should reimport a modified file', async () => {
|
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, {
|
const library = await utils.createLibrary(admin.accessToken, {
|
||||||
ownerId: admin.userId,
|
ownerId: admin.userId,
|
||||||
importPaths: [`${testAssetDirInternal}/temp`],
|
importPaths: [`${testAssetDirInternal}/temp/folder${char}1`, `${testAssetDirInternal}/temp/folder${char}2`],
|
||||||
});
|
});
|
||||||
|
|
||||||
utils.createImageFile(`${testAssetDir}/temp/directoryA/assetB.jpg`);
|
utils.createImageFile(`${testAssetDir}/temp/folder${char}1/asset1.png`);
|
||||||
await utimes(`${testAssetDir}/temp/directoryA/assetB.jpg`, 447_775_200_000);
|
utils.createImageFile(`${testAssetDir}/temp/folder${char}2/asset2.png`);
|
||||||
|
|
||||||
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_001);
|
|
||||||
|
|
||||||
const { status } = await request(app)
|
const { status } = await request(app)
|
||||||
.post(`/libraries/${library.id}/scan`)
|
.post(`/libraries/${library.id}/scan`)
|
||||||
.set('Authorization', `Bearer ${admin.accessToken}`)
|
.set('Authorization', `Bearer ${admin.accessToken}`)
|
||||||
.send({ refreshModifiedFiles: true });
|
.send();
|
||||||
expect(status).toBe(204);
|
expect(status).toBe(204);
|
||||||
|
|
||||||
await utils.waitForQueueFinish(admin.accessToken, 'library');
|
await utils.waitForQueueFinish(admin.accessToken, 'library');
|
||||||
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 });
|
||||||
libraryId: library.id,
|
|
||||||
model: 'NIKON D750',
|
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/reimport`],
|
||||||
});
|
});
|
||||||
expect(assets.count).toBe(1);
|
|
||||||
|
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/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();
|
||||||
|
expect(status).toBe(204);
|
||||||
|
|
||||||
|
await utils.waitForQueueFinish(admin.accessToken, 'library');
|
||||||
|
await utils.waitForQueueFinish(admin.accessToken, 'sidecar');
|
||||||
|
await utils.waitForQueueFinish(admin.accessToken, 'metadataExtraction');
|
||||||
|
|
||||||
|
const { assets } = await utils.searchAssets(admin.accessToken, {
|
||||||
|
libraryId: library.id,
|
||||||
|
});
|
||||||
|
|
||||||
|
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 () => {
|
it('should not reimport unmodified files', async () => {
|
||||||
const library = await utils.createLibrary(admin.accessToken, {
|
const library = await utils.createLibrary(admin.accessToken, {
|
||||||
ownerId: admin.userId,
|
ownerId: admin.userId,
|
||||||
importPaths: [`${testAssetDirInternal}/temp`],
|
importPaths: [`${testAssetDirInternal}/temp/reimport`],
|
||||||
});
|
});
|
||||||
|
|
||||||
utils.createImageFile(`${testAssetDir}/temp/directoryA/assetB.jpg`);
|
utils.createImageFile(`${testAssetDir}/temp/reimport/asset.jpg`);
|
||||||
await utimes(`${testAssetDir}/temp/directoryA/assetB.jpg`, 447_775_200_000);
|
await utimes(`${testAssetDir}/temp/reimport/asset.jpg`, 447_775_200_000);
|
||||||
|
|
||||||
await scan(admin.accessToken, library.id);
|
await scan(admin.accessToken, library.id);
|
||||||
await utils.waitForQueueFinish(admin.accessToken, 'library');
|
await utils.waitForQueueFinish(admin.accessToken, 'library');
|
||||||
|
|
||||||
cpSync(`${testAssetDir}/albums/nature/tanners_ridge.jpg`, `${testAssetDir}/temp/directoryA/assetB.jpg`);
|
cpSync(`${testAssetDir}/albums/nature/tanners_ridge.jpg`, `${testAssetDir}/temp/reimport/asset.jpg`);
|
||||||
await utimes(`${testAssetDir}/temp/directoryA/assetB.jpg`, 447_775_200_000);
|
await utimes(`${testAssetDir}/temp/reimport/asset.jpg`, 447_775_200_000);
|
||||||
|
|
||||||
const { status } = await request(app)
|
const { status } = await request(app)
|
||||||
.post(`/libraries/${library.id}/scan`)
|
.post(`/libraries/${library.id}/scan`)
|
||||||
.set('Authorization', `Bearer ${admin.accessToken}`)
|
.set('Authorization', `Bearer ${admin.accessToken}`)
|
||||||
.send({ refreshModifiedFiles: true });
|
.send();
|
||||||
expect(status).toBe(204);
|
expect(status).toBe(204);
|
||||||
|
|
||||||
await utils.waitForQueueFinish(admin.accessToken, 'library');
|
await utils.waitForQueueFinish(admin.accessToken, 'library');
|
||||||
|
await utils.waitForQueueFinish(admin.accessToken, 'sidecar');
|
||||||
await utils.waitForQueueFinish(admin.accessToken, 'metadataExtraction');
|
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,
|
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 () => {
|
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 scan(admin.accessToken, library.id);
|
||||||
await utils.waitForQueueFinish(admin.accessToken, 'library');
|
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.count).toBe(1);
|
||||||
|
|
||||||
utils.removeImageFile(`${testAssetDir}/temp/offline/offline.png`);
|
utils.removeImageFile(`${testAssetDir}/temp/offline/offline.png`);
|
||||||
@@ -495,7 +584,7 @@ describe('/libraries', () => {
|
|||||||
expect(trashedAsset.originalPath).toBe(`${testAssetDirInternal}/temp/offline/offline.png`);
|
expect(trashedAsset.originalPath).toBe(`${testAssetDirInternal}/temp/offline/offline.png`);
|
||||||
expect(trashedAsset.isOffline).toEqual(true);
|
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([]);
|
expect(newAssets.items).toEqual([]);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -510,7 +599,7 @@ describe('/libraries', () => {
|
|||||||
await scan(admin.accessToken, library.id);
|
await scan(admin.accessToken, library.id);
|
||||||
await utils.waitForQueueFinish(admin.accessToken, 'library');
|
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.count).toBe(1);
|
||||||
|
|
||||||
utils.createDirectory(`${testAssetDir}/temp/another-path/`);
|
utils.createDirectory(`${testAssetDir}/temp/another-path/`);
|
||||||
@@ -532,7 +621,7 @@ describe('/libraries', () => {
|
|||||||
expect(trashedAsset.originalPath).toBe(`${testAssetDirInternal}/temp/offline/offline.png`);
|
expect(trashedAsset.originalPath).toBe(`${testAssetDirInternal}/temp/offline/offline.png`);
|
||||||
expect(trashedAsset.isOffline).toBe(true);
|
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(newAssets.items).toEqual([]);
|
||||||
|
|
||||||
@@ -549,7 +638,7 @@ describe('/libraries', () => {
|
|||||||
await scan(admin.accessToken, library.id);
|
await scan(admin.accessToken, library.id);
|
||||||
await utils.waitForQueueFinish(admin.accessToken, 'library');
|
await utils.waitForQueueFinish(admin.accessToken, 'library');
|
||||||
|
|
||||||
const { assets } = await utils.metadataSearch(admin.accessToken, {
|
const { assets } = await utils.searchAssets(admin.accessToken, {
|
||||||
libraryId: library.id,
|
libraryId: library.id,
|
||||||
originalFileName: 'assetB.png',
|
originalFileName: 'assetB.png',
|
||||||
});
|
});
|
||||||
@@ -568,7 +657,7 @@ describe('/libraries', () => {
|
|||||||
expect(trashedAsset.originalPath).toBe(`${testAssetDirInternal}/temp/directoryB/assetB.png`);
|
expect(trashedAsset.originalPath).toBe(`${testAssetDirInternal}/temp/directoryB/assetB.png`);
|
||||||
expect(trashedAsset.isOffline).toBe(true);
|
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(newAssets.items).toEqual([
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
@@ -586,7 +675,7 @@ describe('/libraries', () => {
|
|||||||
await scan(admin.accessToken, library.id);
|
await scan(admin.accessToken, library.id);
|
||||||
await utils.waitForQueueFinish(admin.accessToken, 'library');
|
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);
|
expect(assetsBefore.count).toBeGreaterThan(1);
|
||||||
|
|
||||||
const { status } = await request(app)
|
const { status } = await request(app)
|
||||||
@@ -597,10 +686,302 @@ describe('/libraries', () => {
|
|||||||
|
|
||||||
await utils.waitForQueueFinish(admin.accessToken, 'library');
|
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);
|
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', () => {
|
describe('POST /libraries/:id/validate', () => {
|
||||||
|
|||||||
@@ -98,6 +98,7 @@ describe('/search', () => {
|
|||||||
{ latitude: 31.634_16, longitude: -7.999_94 }, // marrakesh
|
{ latitude: 31.634_16, longitude: -7.999_94 }, // marrakesh
|
||||||
{ latitude: 38.523_735_4, longitude: -78.488_619_4 }, // tanners ridge
|
{ latitude: 38.523_735_4, longitude: -78.488_619_4 }, // tanners ridge
|
||||||
{ latitude: 59.938_63, longitude: 30.314_13 }, // st. petersburg
|
{ latitude: 59.938_63, longitude: 30.314_13 }, // st. petersburg
|
||||||
|
{ latitude: 0, longitude: 0 }, // null island
|
||||||
];
|
];
|
||||||
|
|
||||||
const updates = coordinates.map((dto, i) =>
|
const updates = coordinates.map((dto, i) =>
|
||||||
@@ -532,7 +533,7 @@ describe('/search', () => {
|
|||||||
expect(body).toEqual(errorDto.unauthorized);
|
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)
|
const { status, body } = await request(app)
|
||||||
.get('/search/suggestions?type=country&includeNull=true')
|
.get('/search/suggestions?type=country&includeNull=true')
|
||||||
.set('Authorization', `Bearer ${admin.accessToken}`);
|
.set('Authorization', `Bearer ${admin.accessToken}`);
|
||||||
@@ -555,7 +556,29 @@ describe('/search', () => {
|
|||||||
expect(status).toBe(200);
|
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)
|
const { status, body } = await request(app)
|
||||||
.get('/search/suggestions?type=state&includeNull=true')
|
.get('/search/suggestions?type=state&includeNull=true')
|
||||||
.set('Authorization', `Bearer ${admin.accessToken}`);
|
.set('Authorization', `Bearer ${admin.accessToken}`);
|
||||||
@@ -579,7 +602,30 @@ describe('/search', () => {
|
|||||||
expect(status).toBe(200);
|
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)
|
const { status, body } = await request(app)
|
||||||
.get('/search/suggestions?type=city&includeNull=true')
|
.get('/search/suggestions?type=city&includeNull=true')
|
||||||
.set('Authorization', `Bearer ${admin.accessToken}`);
|
.set('Authorization', `Bearer ${admin.accessToken}`);
|
||||||
@@ -604,7 +650,31 @@ describe('/search', () => {
|
|||||||
expect(status).toBe(200);
|
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)
|
const { status, body } = await request(app)
|
||||||
.get('/search/suggestions?type=camera-make&includeNull=true')
|
.get('/search/suggestions?type=camera-make&includeNull=true')
|
||||||
.set('Authorization', `Bearer ${admin.accessToken}`);
|
.set('Authorization', `Bearer ${admin.accessToken}`);
|
||||||
@@ -621,7 +691,23 @@ describe('/search', () => {
|
|||||||
expect(status).toBe(200);
|
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)
|
const { status, body } = await request(app)
|
||||||
.get('/search/suggestions?type=camera-model&includeNull=true')
|
.get('/search/suggestions?type=camera-model&includeNull=true')
|
||||||
.set('Authorization', `Bearer ${admin.accessToken}`);
|
.set('Authorization', `Bearer ${admin.accessToken}`);
|
||||||
@@ -642,5 +728,26 @@ describe('/search', () => {
|
|||||||
]);
|
]);
|
||||||
expect(status).toBe(200);
|
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);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -133,6 +133,7 @@ describe('/server', () => {
|
|||||||
userDeleteDelay: 7,
|
userDeleteDelay: 7,
|
||||||
isInitialized: true,
|
isInitialized: true,
|
||||||
externalDomain: '',
|
externalDomain: '',
|
||||||
|
publicUsers: true,
|
||||||
isOnboarded: false,
|
isOnboarded: false,
|
||||||
mapDarkStyleUrl: 'https://tiles.immich.cloud/v1/style/dark.json',
|
mapDarkStyleUrl: 'https://tiles.immich.cloud/v1/style/dark.json',
|
||||||
mapLightStyleUrl: 'https://tiles.immich.cloud/v1/style/light.json',
|
mapLightStyleUrl: 'https://tiles.immich.cloud/v1/style/light.json',
|
||||||
@@ -163,11 +164,15 @@ describe('/server', () => {
|
|||||||
expect(body).toEqual({
|
expect(body).toEqual({
|
||||||
photos: 0,
|
photos: 0,
|
||||||
usage: 0,
|
usage: 0,
|
||||||
|
usagePhotos: 0,
|
||||||
|
usageVideos: 0,
|
||||||
usageByUser: [
|
usageByUser: [
|
||||||
{
|
{
|
||||||
quotaSizeInBytes: null,
|
quotaSizeInBytes: null,
|
||||||
photos: 0,
|
photos: 0,
|
||||||
usage: 0,
|
usage: 0,
|
||||||
|
usagePhotos: 0,
|
||||||
|
usageVideos: 0,
|
||||||
userName: 'Immich Admin',
|
userName: 'Immich Admin',
|
||||||
userId: admin.userId,
|
userId: admin.userId,
|
||||||
videos: 0,
|
videos: 0,
|
||||||
@@ -176,6 +181,8 @@ describe('/server', () => {
|
|||||||
quotaSizeInBytes: null,
|
quotaSizeInBytes: null,
|
||||||
photos: 0,
|
photos: 0,
|
||||||
usage: 0,
|
usage: 0,
|
||||||
|
usagePhotos: 0,
|
||||||
|
usageVideos: 0,
|
||||||
userName: 'User 1',
|
userName: 'User 1',
|
||||||
userId: nonAdmin.userId,
|
userId: nonAdmin.userId,
|
||||||
videos: 0,
|
videos: 0,
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ describe('/trash', () => {
|
|||||||
await scan(admin.accessToken, library.id);
|
await scan(admin.accessToken, library.id);
|
||||||
await utils.waitForQueueFinish(admin.accessToken, 'library');
|
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);
|
expect(assets.items.length).toBe(1);
|
||||||
const asset = assets.items[0];
|
const asset = assets.items[0];
|
||||||
|
|
||||||
@@ -148,7 +148,7 @@ describe('/trash', () => {
|
|||||||
await scan(admin.accessToken, library.id);
|
await scan(admin.accessToken, library.id);
|
||||||
await utils.waitForQueueFinish(admin.accessToken, 'library');
|
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.count).toBe(1);
|
||||||
const assetId = assets.items[0].id;
|
const assetId = assets.items[0].id;
|
||||||
|
|
||||||
@@ -206,7 +206,7 @@ describe('/trash', () => {
|
|||||||
await scan(admin.accessToken, library.id);
|
await scan(admin.accessToken, library.id);
|
||||||
await utils.waitForQueueFinish(admin.accessToken, 'library');
|
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.count).toBe(1);
|
||||||
const assetId = assets.items[0].id;
|
const assetId = assets.items[0].id;
|
||||||
|
|
||||||
|
|||||||
@@ -103,7 +103,7 @@ describe(`immich upload`, () => {
|
|||||||
describe(`immich upload /path/to/file.jpg`, () => {
|
describe(`immich upload /path/to/file.jpg`, () => {
|
||||||
it('should upload a single file', async () => {
|
it('should upload a single file', async () => {
|
||||||
const { stderr, stdout, exitCode } = await immichCli(['upload', `${testAssetDir}/albums/nature/silver_fir.jpg`]);
|
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(stdout.split('\n')).toEqual(
|
||||||
expect.arrayContaining([expect.stringContaining('Successfully uploaded 1 new asset')]),
|
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 expectedCount = Object.entries(files).filter((entry) => entry[1]).length;
|
||||||
|
|
||||||
const { stderr, stdout, exitCode } = await immichCli(['upload', ...commandLine]);
|
const { stderr, stdout, exitCode } = await immichCli(['upload', ...commandLine]);
|
||||||
expect(stderr).toBe('');
|
expect(stderr).toContain('{message}');
|
||||||
expect(stdout.split('\n')).toEqual(
|
expect(stdout.split('\n')).toEqual(
|
||||||
expect.arrayContaining([expect.stringContaining(`Successfully uploaded ${expectedCount} new asset`)]),
|
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]);
|
cpSync(`${testAssetDir}/albums/nature/silver_fir.jpg`, testPaths[1]);
|
||||||
|
|
||||||
const { stderr, stdout, exitCode } = await immichCli(['upload', ...testPaths]);
|
const { stderr, stdout, exitCode } = await immichCli(['upload', ...testPaths]);
|
||||||
expect(stderr).toBe('');
|
expect(stderr).toContain('{message}');
|
||||||
expect(stdout.split('\n')).toEqual(
|
expect(stdout.split('\n')).toEqual(
|
||||||
expect.arrayContaining([expect.stringContaining('Successfully uploaded 2 new assets')]),
|
expect.arrayContaining([expect.stringContaining('Successfully uploaded 2 new assets')]),
|
||||||
);
|
);
|
||||||
@@ -169,7 +169,7 @@ describe(`immich upload`, () => {
|
|||||||
|
|
||||||
it('should skip a duplicate file', async () => {
|
it('should skip a duplicate file', async () => {
|
||||||
const first = await immichCli(['upload', `${testAssetDir}/albums/nature/silver_fir.jpg`]);
|
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(first.stdout.split('\n')).toEqual(
|
||||||
expect.arrayContaining([expect.stringContaining('Successfully uploaded 1 new asset')]),
|
expect.arrayContaining([expect.stringContaining('Successfully uploaded 1 new asset')]),
|
||||||
);
|
);
|
||||||
@@ -179,7 +179,7 @@ describe(`immich upload`, () => {
|
|||||||
expect(assets.total).toBe(1);
|
expect(assets.total).toBe(1);
|
||||||
|
|
||||||
const second = await immichCli(['upload', `${testAssetDir}/albums/nature/silver_fir.jpg`]);
|
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(second.stdout.split('\n')).toEqual(
|
||||||
expect.arrayContaining([
|
expect.arrayContaining([
|
||||||
expect.stringContaining('Found 0 new files and 1 duplicate'),
|
expect.stringContaining('Found 0 new files and 1 duplicate'),
|
||||||
@@ -205,7 +205,7 @@ describe(`immich upload`, () => {
|
|||||||
`${testAssetDir}/albums/nature/silver_fir.jpg`,
|
`${testAssetDir}/albums/nature/silver_fir.jpg`,
|
||||||
'--dry-run',
|
'--dry-run',
|
||||||
]);
|
]);
|
||||||
expect(stderr).toBe('');
|
expect(stderr).toContain('{message}');
|
||||||
expect(stdout.split('\n')).toEqual(
|
expect(stdout.split('\n')).toEqual(
|
||||||
expect.arrayContaining([expect.stringContaining('Would have uploaded 1 asset')]),
|
expect.arrayContaining([expect.stringContaining('Would have uploaded 1 asset')]),
|
||||||
);
|
);
|
||||||
@@ -217,7 +217,7 @@ describe(`immich upload`, () => {
|
|||||||
|
|
||||||
it('dry run should handle duplicates', async () => {
|
it('dry run should handle duplicates', async () => {
|
||||||
const first = await immichCli(['upload', `${testAssetDir}/albums/nature/silver_fir.jpg`]);
|
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(first.stdout.split('\n')).toEqual(
|
||||||
expect.arrayContaining([expect.stringContaining('Successfully uploaded 1 new asset')]),
|
expect.arrayContaining([expect.stringContaining('Successfully uploaded 1 new asset')]),
|
||||||
);
|
);
|
||||||
@@ -227,7 +227,7 @@ describe(`immich upload`, () => {
|
|||||||
expect(assets.total).toBe(1);
|
expect(assets.total).toBe(1);
|
||||||
|
|
||||||
const second = await immichCli(['upload', `${testAssetDir}/albums/nature/`, '--dry-run']);
|
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(second.stdout.split('\n')).toEqual(
|
||||||
expect.arrayContaining([
|
expect.arrayContaining([
|
||||||
expect.stringContaining('Found 8 new files and 1 duplicate'),
|
expect.stringContaining('Found 8 new files and 1 duplicate'),
|
||||||
@@ -241,7 +241,7 @@ describe(`immich upload`, () => {
|
|||||||
describe('immich upload --recursive', () => {
|
describe('immich upload --recursive', () => {
|
||||||
it('should upload a folder recursively', async () => {
|
it('should upload a folder recursively', async () => {
|
||||||
const { stderr, stdout, exitCode } = await immichCli(['upload', `${testAssetDir}/albums/nature/`, '--recursive']);
|
const { stderr, stdout, exitCode } = await immichCli(['upload', `${testAssetDir}/albums/nature/`, '--recursive']);
|
||||||
expect(stderr).toBe('');
|
expect(stderr).toContain('{message}');
|
||||||
expect(stdout.split('\n')).toEqual(
|
expect(stdout.split('\n')).toEqual(
|
||||||
expect.arrayContaining([expect.stringContaining('Successfully uploaded 9 new assets')]),
|
expect.arrayContaining([expect.stringContaining('Successfully uploaded 9 new assets')]),
|
||||||
);
|
);
|
||||||
@@ -267,7 +267,7 @@ describe(`immich upload`, () => {
|
|||||||
expect.stringContaining('Successfully updated 9 assets'),
|
expect.stringContaining('Successfully updated 9 assets'),
|
||||||
]),
|
]),
|
||||||
);
|
);
|
||||||
expect(stderr).toBe('');
|
expect(stderr).toContain('{message}');
|
||||||
expect(exitCode).toBe(0);
|
expect(exitCode).toBe(0);
|
||||||
|
|
||||||
const assets = await getAssetStatistics({}, { headers: asKeyAuth(key) });
|
const assets = await getAssetStatistics({}, { headers: asKeyAuth(key) });
|
||||||
@@ -283,7 +283,7 @@ describe(`immich upload`, () => {
|
|||||||
expect(response1.stdout.split('\n')).toEqual(
|
expect(response1.stdout.split('\n')).toEqual(
|
||||||
expect.arrayContaining([expect.stringContaining('Successfully uploaded 9 new assets')]),
|
expect.arrayContaining([expect.stringContaining('Successfully uploaded 9 new assets')]),
|
||||||
);
|
);
|
||||||
expect(response1.stderr).toBe('');
|
expect(response1.stderr).toContain('{message}');
|
||||||
expect(response1.exitCode).toBe(0);
|
expect(response1.exitCode).toBe(0);
|
||||||
|
|
||||||
const assets1 = await getAssetStatistics({}, { headers: asKeyAuth(key) });
|
const assets1 = await getAssetStatistics({}, { headers: asKeyAuth(key) });
|
||||||
@@ -299,7 +299,7 @@ describe(`immich upload`, () => {
|
|||||||
expect.stringContaining('Successfully updated 9 assets'),
|
expect.stringContaining('Successfully updated 9 assets'),
|
||||||
]),
|
]),
|
||||||
);
|
);
|
||||||
expect(response2.stderr).toBe('');
|
expect(response2.stderr).toContain('{message}');
|
||||||
expect(response2.exitCode).toBe(0);
|
expect(response2.exitCode).toBe(0);
|
||||||
|
|
||||||
const assets2 = await getAssetStatistics({}, { headers: asKeyAuth(key) });
|
const assets2 = await getAssetStatistics({}, { headers: asKeyAuth(key) });
|
||||||
@@ -325,7 +325,7 @@ describe(`immich upload`, () => {
|
|||||||
expect.stringContaining('Would have updated albums of 9 assets'),
|
expect.stringContaining('Would have updated albums of 9 assets'),
|
||||||
]),
|
]),
|
||||||
);
|
);
|
||||||
expect(stderr).toBe('');
|
expect(stderr).toContain('{message}');
|
||||||
expect(exitCode).toBe(0);
|
expect(exitCode).toBe(0);
|
||||||
|
|
||||||
const assets = await getAssetStatistics({}, { headers: asKeyAuth(key) });
|
const assets = await getAssetStatistics({}, { headers: asKeyAuth(key) });
|
||||||
@@ -351,7 +351,7 @@ describe(`immich upload`, () => {
|
|||||||
expect.stringContaining('Successfully updated 9 assets'),
|
expect.stringContaining('Successfully updated 9 assets'),
|
||||||
]),
|
]),
|
||||||
);
|
);
|
||||||
expect(stderr).toBe('');
|
expect(stderr).toContain('{message}');
|
||||||
expect(exitCode).toBe(0);
|
expect(exitCode).toBe(0);
|
||||||
|
|
||||||
const assets = await getAssetStatistics({}, { headers: asKeyAuth(key) });
|
const assets = await getAssetStatistics({}, { headers: asKeyAuth(key) });
|
||||||
@@ -377,7 +377,7 @@ describe(`immich upload`, () => {
|
|||||||
expect.stringContaining('Would have updated albums of 9 assets'),
|
expect.stringContaining('Would have updated albums of 9 assets'),
|
||||||
]),
|
]),
|
||||||
);
|
);
|
||||||
expect(stderr).toBe('');
|
expect(stderr).toContain('{message}');
|
||||||
expect(exitCode).toBe(0);
|
expect(exitCode).toBe(0);
|
||||||
|
|
||||||
const assets = await getAssetStatistics({}, { headers: asKeyAuth(key) });
|
const assets = await getAssetStatistics({}, { headers: asKeyAuth(key) });
|
||||||
@@ -408,7 +408,7 @@ describe(`immich upload`, () => {
|
|||||||
expect.stringContaining('Deleting assets that have been uploaded'),
|
expect.stringContaining('Deleting assets that have been uploaded'),
|
||||||
]),
|
]),
|
||||||
);
|
);
|
||||||
expect(stderr).toBe('');
|
expect(stderr).toContain('{message}');
|
||||||
expect(exitCode).toBe(0);
|
expect(exitCode).toBe(0);
|
||||||
|
|
||||||
const assets = await getAssetStatistics({}, { headers: asKeyAuth(key) });
|
const assets = await getAssetStatistics({}, { headers: asKeyAuth(key) });
|
||||||
@@ -434,7 +434,7 @@ describe(`immich upload`, () => {
|
|||||||
expect.stringContaining('Would have deleted 9 local assets'),
|
expect.stringContaining('Would have deleted 9 local assets'),
|
||||||
]),
|
]),
|
||||||
);
|
);
|
||||||
expect(stderr).toBe('');
|
expect(stderr).toContain('{message}');
|
||||||
expect(exitCode).toBe(0);
|
expect(exitCode).toBe(0);
|
||||||
|
|
||||||
const assets = await getAssetStatistics({}, { headers: asKeyAuth(key) });
|
const assets = await getAssetStatistics({}, { headers: asKeyAuth(key) });
|
||||||
@@ -493,7 +493,7 @@ describe(`immich upload`, () => {
|
|||||||
'2',
|
'2',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
expect(stderr).toBe('');
|
expect(stderr).toContain('{message}');
|
||||||
expect(stdout.split('\n')).toEqual(
|
expect(stdout.split('\n')).toEqual(
|
||||||
expect.arrayContaining([
|
expect.arrayContaining([
|
||||||
'Found 9 new files and 0 duplicates',
|
'Found 9 new files and 0 duplicates',
|
||||||
@@ -534,7 +534,7 @@ describe(`immich upload`, () => {
|
|||||||
'silver_fir.jpg',
|
'silver_fir.jpg',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
expect(stderr).toBe('');
|
expect(stderr).toContain('{message}');
|
||||||
expect(stdout.split('\n')).toEqual(
|
expect(stdout.split('\n')).toEqual(
|
||||||
expect.arrayContaining([
|
expect.arrayContaining([
|
||||||
'Found 8 new files and 0 duplicates',
|
'Found 8 new files and 0 duplicates',
|
||||||
@@ -555,7 +555,7 @@ describe(`immich upload`, () => {
|
|||||||
'!(*_*_*).jpg',
|
'!(*_*_*).jpg',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
expect(stderr).toBe('');
|
expect(stderr).toContain('{message}');
|
||||||
expect(stdout.split('\n')).toEqual(
|
expect(stdout.split('\n')).toEqual(
|
||||||
expect.arrayContaining([
|
expect.arrayContaining([
|
||||||
'Found 1 new files and 0 duplicates',
|
'Found 1 new files and 0 duplicates',
|
||||||
@@ -577,7 +577,7 @@ describe(`immich upload`, () => {
|
|||||||
'--dry-run',
|
'--dry-run',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
expect(stderr).toBe('');
|
expect(stderr).toContain('{message}');
|
||||||
expect(stdout.split('\n')).toEqual(
|
expect(stdout.split('\n')).toEqual(
|
||||||
expect.arrayContaining([
|
expect.arrayContaining([
|
||||||
'Found 8 new files and 0 duplicates',
|
'Found 8 new files and 0 duplicates',
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import {
|
|||||||
PersonCreateDto,
|
PersonCreateDto,
|
||||||
SharedLinkCreateDto,
|
SharedLinkCreateDto,
|
||||||
UserAdminCreateDto,
|
UserAdminCreateDto,
|
||||||
|
UserPreferencesUpdateDto,
|
||||||
ValidateLibraryDto,
|
ValidateLibraryDto,
|
||||||
checkExistingAssets,
|
checkExistingAssets,
|
||||||
createAlbum,
|
createAlbum,
|
||||||
@@ -19,19 +20,23 @@ import {
|
|||||||
createPartner,
|
createPartner,
|
||||||
createPerson,
|
createPerson,
|
||||||
createSharedLink,
|
createSharedLink,
|
||||||
|
createStack,
|
||||||
createUserAdmin,
|
createUserAdmin,
|
||||||
deleteAssets,
|
deleteAssets,
|
||||||
getAllJobsStatus,
|
getAllJobsStatus,
|
||||||
getAssetInfo,
|
getAssetInfo,
|
||||||
getConfigDefaults,
|
getConfigDefaults,
|
||||||
login,
|
login,
|
||||||
searchMetadata,
|
searchAssets,
|
||||||
setBaseUrl,
|
setBaseUrl,
|
||||||
signUpAdmin,
|
signUpAdmin,
|
||||||
|
tagAssets,
|
||||||
updateAdminOnboarding,
|
updateAdminOnboarding,
|
||||||
updateAlbumUser,
|
updateAlbumUser,
|
||||||
updateAssets,
|
updateAssets,
|
||||||
updateConfig,
|
updateConfig,
|
||||||
|
updateMyPreferences,
|
||||||
|
upsertTags,
|
||||||
validate,
|
validate,
|
||||||
} from '@immich/sdk';
|
} from '@immich/sdk';
|
||||||
import { BrowserContext } from '@playwright/test';
|
import { BrowserContext } from '@playwright/test';
|
||||||
@@ -400,8 +405,8 @@ export const utils = {
|
|||||||
checkExistingAssets: (accessToken: string, checkExistingAssetsDto: CheckExistingAssetsDto) =>
|
checkExistingAssets: (accessToken: string, checkExistingAssetsDto: CheckExistingAssetsDto) =>
|
||||||
checkExistingAssets({ checkExistingAssetsDto }, { headers: asBearerAuth(accessToken) }),
|
checkExistingAssets({ checkExistingAssetsDto }, { headers: asBearerAuth(accessToken) }),
|
||||||
|
|
||||||
metadataSearch: async (accessToken: string, dto: MetadataSearchDto) => {
|
searchAssets: async (accessToken: string, dto: MetadataSearchDto) => {
|
||||||
return searchMetadata({ metadataSearchDto: dto }, { headers: asBearerAuth(accessToken) });
|
return searchAssets({ metadataSearchDto: dto }, { headers: asBearerAuth(accessToken) });
|
||||||
},
|
},
|
||||||
|
|
||||||
archiveAssets: (accessToken: string, ids: string[]) =>
|
archiveAssets: (accessToken: string, ids: string[]) =>
|
||||||
@@ -444,6 +449,18 @@ export const utils = {
|
|||||||
|
|
||||||
createPartner: (accessToken: string, id: string) => createPartner({ id }, { headers: asBearerAuth(accessToken) }),
|
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') =>
|
setAuthCookies: async (context: BrowserContext, accessToken: string, domain = '127.0.0.1') =>
|
||||||
await context.addCookies([
|
await context.addCookies([
|
||||||
{
|
{
|
||||||
|
|||||||
66
e2e/src/web/specs/asset-viewer/stack.e2e-spec.ts
Normal file
@@ -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');
|
||||||
|
});
|
||||||
|
});
|
||||||
58
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 <link>Server Command</link>.",
|
||||||
|
"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. <link>Crontab Guru</link>",
|
||||||
|
"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"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
116
i18n/ar.json
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"about": "حول",
|
"about": "تحديث",
|
||||||
"account": "الحساب",
|
"account": "الحساب",
|
||||||
"account_settings": "إعدادات الحساب",
|
"account_settings": "إعدادات الحساب",
|
||||||
"acknowledge": "أُدرك ذلك",
|
"acknowledge": "أُدرك ذلك",
|
||||||
@@ -34,6 +34,11 @@
|
|||||||
"authentication_settings_disable_all": "هل أنت متأكد أنك تريد تعطيل جميع وسائل تسجيل الدخول؟ سيتم تعطيل تسجيل الدخول بالكامل.",
|
"authentication_settings_disable_all": "هل أنت متأكد أنك تريد تعطيل جميع وسائل تسجيل الدخول؟ سيتم تعطيل تسجيل الدخول بالكامل.",
|
||||||
"authentication_settings_reenable": "لإعادة التفعيل، استخدم <link>أمر الخادم</link>.",
|
"authentication_settings_reenable": "لإعادة التفعيل، استخدم <link>أمر الخادم</link>.",
|
||||||
"background_task_job": "المهام الخلفية",
|
"background_task_job": "المهام الخلفية",
|
||||||
|
"backup_database": "قاعدة البيانات الاحتياطية",
|
||||||
|
"backup_database_enable_description": "تمكين النسخ الاحتياطي لقاعدة البيانات",
|
||||||
|
"backup_keep_last_amount": "مقدار النسخ الاحتياطية السابقة للاحتفاظ بها",
|
||||||
|
"backup_settings": "إعدادات النسخ الاحتياطي",
|
||||||
|
"backup_settings_description": "إدارة إعدادات النسخ الاحتياطي لقاعدة البيانات",
|
||||||
"check_all": "اختر الكل",
|
"check_all": "اختر الكل",
|
||||||
"cleared_jobs": "تم إخلاء مهام: {job}",
|
"cleared_jobs": "تم إخلاء مهام: {job}",
|
||||||
"config_set_by_file": "الإعدادات حاليًا معينة عن طريق ملف الاعدادات",
|
"config_set_by_file": "الإعدادات حاليًا معينة عن طريق ملف الاعدادات",
|
||||||
@@ -43,9 +48,10 @@
|
|||||||
"confirm_reprocess_all_faces": "هل أنت متأكد أنك تريد إعادة معالجة جميع الوجوه؟ سيخلي هذا كل الأشخاص الذين سَميتَهم.",
|
"confirm_reprocess_all_faces": "هل أنت متأكد أنك تريد إعادة معالجة جميع الوجوه؟ سيخلي هذا كل الأشخاص الذين سَميتَهم.",
|
||||||
"confirm_user_password_reset": "هل أنت متأكد أنك تريد إعادة تعيين كلمة مرور {user}؟",
|
"confirm_user_password_reset": "هل أنت متأكد أنك تريد إعادة تعيين كلمة مرور {user}؟",
|
||||||
"create_job": "إنشاء وظيفة",
|
"create_job": "إنشاء وظيفة",
|
||||||
"crontab_guru": "",
|
"cron_expression": "تعبير Cron",
|
||||||
|
"cron_expression_description": "اضبط الفاصل الزمني للفحص باستخدام تنسيق cron. لمزيد من المعلومات يُرجى الرجوع إلى <link>Crontab Guru</link> على سبيل المثال",
|
||||||
|
"cron_expression_presets": "الإعدادات المسبقة لتعبير Cron",
|
||||||
"disable_login": "تعطيل تسجيل الدخول",
|
"disable_login": "تعطيل تسجيل الدخول",
|
||||||
"disabled": "",
|
|
||||||
"duplicate_detection_job_description": "بدء التعلم الآلي على المحتوى للعثور على الصور المتشابهة. يعتمد على البحث الذكي",
|
"duplicate_detection_job_description": "بدء التعلم الآلي على المحتوى للعثور على الصور المتشابهة. يعتمد على البحث الذكي",
|
||||||
"exclusion_pattern_description": "تتيح لك أنماط الاستبعاد تجاهل الملفات والمجلدات عند فحص مكتبتك. يعد هذا مفيدًا إذا كان لديك مجلدات تحتوي على ملفات لا تريد استيرادها، مثل ملفات RAW.",
|
"exclusion_pattern_description": "تتيح لك أنماط الاستبعاد تجاهل الملفات والمجلدات عند فحص مكتبتك. يعد هذا مفيدًا إذا كان لديك مجلدات تحتوي على ملفات لا تريد استيرادها، مثل ملفات RAW.",
|
||||||
"external_library_created_at": "مكتبة خارجية (أُنشئت في {date})",
|
"external_library_created_at": "مكتبة خارجية (أُنشئت في {date})",
|
||||||
@@ -63,22 +69,15 @@
|
|||||||
"image_prefer_wide_gamut": "تفضيل نطاق الألوان الواسع",
|
"image_prefer_wide_gamut": "تفضيل نطاق الألوان الواسع",
|
||||||
"image_prefer_wide_gamut_setting_description": "استخدم Display P3 للصور المصغرة. يحافظ هذا على حيوية الصور ذات مساحات الألوان الواسعة بشكل أفضل، ولكن قد تظهر الصور بشكل مختلف على الأجهزة القديمة ذات إصدار متصفح قديم. يتم الاحتفاظ بصور sRGB بتنسيق sRGB لتجنب تغيرات اللون.",
|
"image_prefer_wide_gamut_setting_description": "استخدم Display P3 للصور المصغرة. يحافظ هذا على حيوية الصور ذات مساحات الألوان الواسعة بشكل أفضل، ولكن قد تظهر الصور بشكل مختلف على الأجهزة القديمة ذات إصدار متصفح قديم. يتم الاحتفاظ بصور sRGB بتنسيق sRGB لتجنب تغيرات اللون.",
|
||||||
"image_preview_description": "صورة متوسطة الحجم مع بيانات وصفية مجردة، تُستخدم عند عرض أصل واحد وللتعلم الآلي",
|
"image_preview_description": "صورة متوسطة الحجم مع بيانات وصفية مجردة، تُستخدم عند عرض أصل واحد وللتعلم الآلي",
|
||||||
"image_preview_format": "تنسيق المعاينة",
|
|
||||||
"image_preview_quality_description": "جودة المعاينة من 1 إلى 100. كلما كانت القيمة أعلى كان ذلك أفضل، ولكنها تنتج ملفات أكبر وقد تقلل من استجابة التطبيق. قد يؤثر ضبط قيمة منخفضة على جودة التعلم الآلي.",
|
"image_preview_quality_description": "جودة المعاينة من 1 إلى 100. كلما كانت القيمة أعلى كان ذلك أفضل، ولكنها تنتج ملفات أكبر وقد تقلل من استجابة التطبيق. قد يؤثر ضبط قيمة منخفضة على جودة التعلم الآلي.",
|
||||||
"image_preview_resolution": "معاينة الدقّة",
|
|
||||||
"image_preview_resolution_description": "يُستخدم عند عرض صورة واحدة وللتعلم الآلي. ستحافظ الدقاتُ العالية على المزيد من التفاصيل ولكنها ستستغرق وقتًا أطول للترميز، ولها أحجام ملفات أكبر، ويمكن أن تقلل من استجابة التطبيق.",
|
|
||||||
"image_preview_title": "إعدادات المعاينة",
|
"image_preview_title": "إعدادات المعاينة",
|
||||||
"image_quality": "الجودة",
|
"image_quality": "الجودة",
|
||||||
"image_quality_description": "جودة الصورة من 1-100. الأعلى هو الأفضل من حيث الجودة ولكنه ينتج ملفات أكبر، ويؤثر هذا الخيار على صور المعاينة والصور المصغرة.",
|
|
||||||
"image_resolution": "الدقة",
|
"image_resolution": "الدقة",
|
||||||
"image_resolution_description": "يمكن للدقة العالية الحفاظ على مزيد من التفاصيل ولكنها تستغرق وقتًا أطول للترميز، وتحتوي على أحجام ملفات أكبر ويمكن أن تقلل من استجابة التطبيق.",
|
"image_resolution_description": "يمكن للدقة العالية الحفاظ على مزيد من التفاصيل ولكنها تستغرق وقتًا أطول للترميز، وتحتوي على أحجام ملفات أكبر ويمكن أن تقلل من استجابة التطبيق.",
|
||||||
"image_settings": "إعدادات الصور",
|
"image_settings": "إعدادات الصور",
|
||||||
"image_settings_description": "إدارة جودة ودقة الصور التي تم إنشاؤها",
|
"image_settings_description": "إدارة جودة ودقة الصور التي تم إنشاؤها",
|
||||||
"image_thumbnail_description": "صورة مصغرة صغيرة مع بيانات وصفية مجردة، تُستخدم عند عرض مجموعات من الصور مثل الجدول الزمني الرئيسي",
|
"image_thumbnail_description": "صورة مصغرة صغيرة مع بيانات وصفية مجردة، تُستخدم عند عرض مجموعات من الصور مثل الجدول الزمني الرئيسي",
|
||||||
"image_thumbnail_format": "تنسيق الصور المصغّرة",
|
|
||||||
"image_thumbnail_quality_description": "تتراوح جودة الصورة المصغرة من 1 إلى 100. كلما كانت الجودة أعلى كان ذلك أفضل، ولكنها تنتج ملفات أكبر وقد تقلل من استجابة التطبيق.",
|
"image_thumbnail_quality_description": "تتراوح جودة الصورة المصغرة من 1 إلى 100. كلما كانت الجودة أعلى كان ذلك أفضل، ولكنها تنتج ملفات أكبر وقد تقلل من استجابة التطبيق.",
|
||||||
"image_thumbnail_resolution": "دقة الصور المصغّرة",
|
|
||||||
"image_thumbnail_resolution_description": "يُستخدم عند عرض مجموعات من الصور (المخطط الزمني الرئيسي، عرض الألبوم، وما إلى ذلك). ستحافظ الدقاتُ العالية على المزيد من التفاصيل ولكنها ستستغرق وقتًا أطول للترميز، ولها أحجام ملفات أكبر، ويمكن أن تقلل من استجابة التطبيق.",
|
|
||||||
"image_thumbnail_title": "إعدادات الصورة المصغرة",
|
"image_thumbnail_title": "إعدادات الصورة المصغرة",
|
||||||
"job_concurrency": "تزامن {job}",
|
"job_concurrency": "تزامن {job}",
|
||||||
"job_created": "تم إنشاء الوظيفة",
|
"job_created": "تم إنشاء الوظيفة",
|
||||||
@@ -89,9 +88,6 @@
|
|||||||
"jobs_delayed": "{jobCount, plural, other {# مؤجلة}}",
|
"jobs_delayed": "{jobCount, plural, other {# مؤجلة}}",
|
||||||
"jobs_failed": "{jobCount, plural, other {# فشلت}}",
|
"jobs_failed": "{jobCount, plural, other {# فشلت}}",
|
||||||
"library_created": "تم إنشاء المكتبة: {library}",
|
"library_created": "تم إنشاء المكتبة: {library}",
|
||||||
"library_cron_expression": "تعبير Cron",
|
|
||||||
"library_cron_expression_description": "\"اضبط فواصلَ زمنِ الفحص باستخدام صيغة cron. للمزيد من المعلومات، يرجى الرجوع إلى <link>Crontab Guru</link>\"",
|
|
||||||
"library_cron_expression_presets": "إعدادات مسبقة لتعبير Cron",
|
|
||||||
"library_deleted": "تم حذف المكتبة",
|
"library_deleted": "تم حذف المكتبة",
|
||||||
"library_import_path_description": "حدد مجلدًا للاستيراد. سيتم فحص هذا المجلد، بما في ذلك المجلدات الفرعية، بحثًا عن الصور ومقاطع الفيديو.",
|
"library_import_path_description": "حدد مجلدًا للاستيراد. سيتم فحص هذا المجلد، بما في ذلك المجلدات الفرعية، بحثًا عن الصور ومقاطع الفيديو.",
|
||||||
"library_scanning": "الفحص الدوري",
|
"library_scanning": "الفحص الدوري",
|
||||||
@@ -215,7 +211,6 @@
|
|||||||
"refreshing_all_libraries": "تحديث كافة المكتبات",
|
"refreshing_all_libraries": "تحديث كافة المكتبات",
|
||||||
"registration": "تسجيل المدير",
|
"registration": "تسجيل المدير",
|
||||||
"registration_description": "بما أنك أول مستخدم في النظام، سيتم تعيينك كمسؤول وستكون مسؤولًا عن المهام الإدارية، وسيتم إنشاء مستخدمين إضافيين بواسطتك.",
|
"registration_description": "بما أنك أول مستخدم في النظام، سيتم تعيينك كمسؤول وستكون مسؤولًا عن المهام الإدارية، وسيتم إنشاء مستخدمين إضافيين بواسطتك.",
|
||||||
"removing_deleted_files": "إزالة الملفات غير المتصلة",
|
|
||||||
"repair_all": "إصلاح الكل",
|
"repair_all": "إصلاح الكل",
|
||||||
"repair_matched_items": "تمت مطابقة {count, plural, one {# عنصر} other {# عناصر}}",
|
"repair_matched_items": "تمت مطابقة {count, plural, one {# عنصر} other {# عناصر}}",
|
||||||
"repaired_items": "تم إصلاح {count, plural, one {# عنصر} other {# عناصر}}",
|
"repaired_items": "تم إصلاح {count, plural, one {# عنصر} other {# عناصر}}",
|
||||||
@@ -223,12 +218,12 @@
|
|||||||
"reset_settings_to_default": "إعادة ضبط الإعدادات إلى الوضع الافتراضي",
|
"reset_settings_to_default": "إعادة ضبط الإعدادات إلى الوضع الافتراضي",
|
||||||
"reset_settings_to_recent_saved": "إعادة ضبط الإعدادات إلى الإعدادات المحفوظة مؤخرًا",
|
"reset_settings_to_recent_saved": "إعادة ضبط الإعدادات إلى الإعدادات المحفوظة مؤخرًا",
|
||||||
"scanning_library": "مسح المكتبة",
|
"scanning_library": "مسح المكتبة",
|
||||||
"scanning_library_for_changed_files": "فحص المكتبة لاكتشاف الملفات التي تم تغييرها",
|
|
||||||
"scanning_library_for_new_files": "فحص المكتبة للبحث عن ملفات جديدة",
|
|
||||||
"search_jobs": "البحث عن وظائف...",
|
"search_jobs": "البحث عن وظائف...",
|
||||||
"send_welcome_email": "إرسال بريد ترحيبي",
|
"send_welcome_email": "إرسال بريد ترحيبي",
|
||||||
"server_external_domain_settings": "إسم النطاق الخارجي",
|
"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": "يتم إدراج جميع المستخدمين (الاسم والبريد الإلكتروني) عند إضافة مستخدم إلى الألبومات المشتركة. عند تعطيل هذه الميزة، ستكون قائمة المستخدمين متاحة فقط لمستخدمي الإدارة.",
|
||||||
"server_settings": "إعدادات الخادم",
|
"server_settings": "إعدادات الخادم",
|
||||||
"server_settings_description": "إدارة إعدادات الخادم",
|
"server_settings_description": "إدارة إعدادات الخادم",
|
||||||
"server_welcome_message": "الرسالة الترحيبية",
|
"server_welcome_message": "الرسالة الترحيبية",
|
||||||
@@ -261,7 +256,6 @@
|
|||||||
"these_files_matched_by_checksum": "تتم مطابقة هذه الملفات من خلال المجاميع الاختبارية الخاصة بهم",
|
"these_files_matched_by_checksum": "تتم مطابقة هذه الملفات من خلال المجاميع الاختبارية الخاصة بهم",
|
||||||
"thumbnail_generation_job": "إنشاء الصور المصغرة",
|
"thumbnail_generation_job": "إنشاء الصور المصغرة",
|
||||||
"thumbnail_generation_job_description": "إنشاء صور مصغرة كبيرة وصغيرة وغير واضحة لكل أصل، بالإضافة إلى صور مصغرة لكل شخص",
|
"thumbnail_generation_job_description": "إنشاء صور مصغرة كبيرة وصغيرة وغير واضحة لكل أصل، بالإضافة إلى صور مصغرة لكل شخص",
|
||||||
"transcode_policy_description": "",
|
|
||||||
"transcoding_acceleration_api": "واجهة برمجة التطبيقات للتسريع",
|
"transcoding_acceleration_api": "واجهة برمجة التطبيقات للتسريع",
|
||||||
"transcoding_acceleration_api_description": "الواجهة البرمجية التي ستتفاعل مع جهازك لتسريع التحويل. هذا الإعداد هو \"أفضل محاولة\": سيعود إلى التحويل البرمجي في حالة الفشل. قد لا يعمل VP9 اعتمادًا على عتادك.",
|
"transcoding_acceleration_api_description": "الواجهة البرمجية التي ستتفاعل مع جهازك لتسريع التحويل. هذا الإعداد هو \"أفضل محاولة\": سيعود إلى التحويل البرمجي في حالة الفشل. قد لا يعمل VP9 اعتمادًا على عتادك.",
|
||||||
"transcoding_acceleration_nvenc": "NVENC (يتطلب GPU من NVIDIA)",
|
"transcoding_acceleration_nvenc": "NVENC (يتطلب GPU من NVIDIA)",
|
||||||
@@ -313,8 +307,6 @@
|
|||||||
"transcoding_threads_description": "تؤدي القيم الأعلى إلى تشفير أسرع، ولكنها تترك مساحة أقل للخادم لمعالجة المهام الأخرى أثناء النشاط. يجب ألا تزيد هذه القيمة عن عدد مراكز وحدة المعالجة المركزية. يزيد من الإستغلال إذا تم ضبطه على 0.",
|
"transcoding_threads_description": "تؤدي القيم الأعلى إلى تشفير أسرع، ولكنها تترك مساحة أقل للخادم لمعالجة المهام الأخرى أثناء النشاط. يجب ألا تزيد هذه القيمة عن عدد مراكز وحدة المعالجة المركزية. يزيد من الإستغلال إذا تم ضبطه على 0.",
|
||||||
"transcoding_tone_mapping": "رسم الخرائط النغمية",
|
"transcoding_tone_mapping": "رسم الخرائط النغمية",
|
||||||
"transcoding_tone_mapping_description": "تحاول الحفاظ على مظهر مقاطع الفيديو HDR عند تحويلها إلى SDR. يقدم كل خوارزمية تنازلات مختلفة بين اللون والتفاصيل والسطوع. Hable تحافظ على التفاصيل، Mobius تحافظ على الألوان، و Reinhard تحافظ على السطوع.",
|
"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": "سياسة الترميز",
|
||||||
"transcoding_transcode_policy_description": "سياسة تحديد متى يجب ترميز الفيديو. سيتم دائمًا ترميز مقاطع الفيديو HDR (ما لم يتم تعطيل الترميز).",
|
"transcoding_transcode_policy_description": "سياسة تحديد متى يجب ترميز الفيديو. سيتم دائمًا ترميز مقاطع الفيديو HDR (ما لم يتم تعطيل الترميز).",
|
||||||
"transcoding_two_pass_encoding": "الترميز بمرورين",
|
"transcoding_two_pass_encoding": "الترميز بمرورين",
|
||||||
@@ -395,7 +387,6 @@
|
|||||||
"archive_or_unarchive_photo": "أرشفة الصورة أو إلغاء أرشفتها",
|
"archive_or_unarchive_photo": "أرشفة الصورة أو إلغاء أرشفتها",
|
||||||
"archive_size": "حجم الأرشيف",
|
"archive_size": "حجم الأرشيف",
|
||||||
"archive_size_description": "تكوين حجم الأرشيف للتنزيلات (بالجيجابايت)",
|
"archive_size_description": "تكوين حجم الأرشيف للتنزيلات (بالجيجابايت)",
|
||||||
"archived": "",
|
|
||||||
"archived_count": "{count, plural, other {الأرشيف #}}",
|
"archived_count": "{count, plural, other {الأرشيف #}}",
|
||||||
"are_these_the_same_person": "هل هؤلاء هم نفس الشخص؟",
|
"are_these_the_same_person": "هل هؤلاء هم نفس الشخص؟",
|
||||||
"are_you_sure_to_do_this": "هل انت متأكد من أنك تريد أن تفعل هذا؟",
|
"are_you_sure_to_do_this": "هل انت متأكد من أنك تريد أن تفعل هذا؟",
|
||||||
@@ -445,10 +436,6 @@
|
|||||||
"cannot_merge_people": "لا يمكن دمج الأشخاص",
|
"cannot_merge_people": "لا يمكن دمج الأشخاص",
|
||||||
"cannot_undo_this_action": "لا يمكنك التراجع عن هذا الإجراء!",
|
"cannot_undo_this_action": "لا يمكنك التراجع عن هذا الإجراء!",
|
||||||
"cannot_update_the_description": "لا يمكن تحديث الوصف",
|
"cannot_update_the_description": "لا يمكن تحديث الوصف",
|
||||||
"cant_apply_changes": "",
|
|
||||||
"cant_get_faces": "",
|
|
||||||
"cant_search_people": "",
|
|
||||||
"cant_search_places": "",
|
|
||||||
"change_date": "غيّر التاريخ",
|
"change_date": "غيّر التاريخ",
|
||||||
"change_expiration_time": "تغيير وقت انتهاء الصلاحية",
|
"change_expiration_time": "تغيير وقت انتهاء الصلاحية",
|
||||||
"change_location": "غيّر الموقع",
|
"change_location": "غيّر الموقع",
|
||||||
@@ -480,6 +467,7 @@
|
|||||||
"confirm": "تأكيد",
|
"confirm": "تأكيد",
|
||||||
"confirm_admin_password": "تأكيد كلمة مرور المسؤول",
|
"confirm_admin_password": "تأكيد كلمة مرور المسؤول",
|
||||||
"confirm_delete_shared_link": "هل أنت متأكد أنك تريد حذف هذا الرابط المشترك؟",
|
"confirm_delete_shared_link": "هل أنت متأكد أنك تريد حذف هذا الرابط المشترك؟",
|
||||||
|
"confirm_keep_this_delete_others": "سيتم حذف جميع الأصول الأخرى في المجموعة باستثناء هذا الأصل. هل أنت متأكد من أنك تريد المتابعة؟",
|
||||||
"confirm_password": "تأكيد كلمة المرور",
|
"confirm_password": "تأكيد كلمة المرور",
|
||||||
"contain": "محتواة",
|
"contain": "محتواة",
|
||||||
"context": "السياق",
|
"context": "السياق",
|
||||||
@@ -529,6 +517,7 @@
|
|||||||
"delete_key": "حذف المفتاح",
|
"delete_key": "حذف المفتاح",
|
||||||
"delete_library": "حذف المكتبة",
|
"delete_library": "حذف المكتبة",
|
||||||
"delete_link": "حذف الرابط",
|
"delete_link": "حذف الرابط",
|
||||||
|
"delete_others": "حذف الأخرى",
|
||||||
"delete_shared_link": "حذف الرابط المشترك",
|
"delete_shared_link": "حذف الرابط المشترك",
|
||||||
"delete_tag": "حذف العلامة",
|
"delete_tag": "حذف العلامة",
|
||||||
"delete_tag_confirmation_prompt": "هل أنت متأكد أنك تريد حذف العلامة {tagName}؟",
|
"delete_tag_confirmation_prompt": "هل أنت متأكد أنك تريد حذف العلامة {tagName}؟",
|
||||||
@@ -562,13 +551,6 @@
|
|||||||
"duplicates": "التكرارات",
|
"duplicates": "التكرارات",
|
||||||
"duplicates_description": "قم بحل كل مجموعة من خلال الإشارة إلى التكرارات، إن وجدت",
|
"duplicates_description": "قم بحل كل مجموعة من خلال الإشارة إلى التكرارات، إن وجدت",
|
||||||
"duration": "المدة",
|
"duration": "المدة",
|
||||||
"durations": {
|
|
||||||
"days": "",
|
|
||||||
"hours": "",
|
|
||||||
"minutes": "",
|
|
||||||
"months": "",
|
|
||||||
"years": ""
|
|
||||||
},
|
|
||||||
"edit": "تعديل",
|
"edit": "تعديل",
|
||||||
"edit_album": "تعديل الألبوم",
|
"edit_album": "تعديل الألبوم",
|
||||||
"edit_avatar": "تعديل الصورة الشخصية",
|
"edit_avatar": "تعديل الصورة الشخصية",
|
||||||
@@ -593,8 +575,6 @@
|
|||||||
"editor_crop_tool_h2_aspect_ratios": "نسب العرض إلى الارتفاع",
|
"editor_crop_tool_h2_aspect_ratios": "نسب العرض إلى الارتفاع",
|
||||||
"editor_crop_tool_h2_rotation": "التدوير",
|
"editor_crop_tool_h2_rotation": "التدوير",
|
||||||
"email": "البريد الإلكتروني",
|
"email": "البريد الإلكتروني",
|
||||||
"empty": "",
|
|
||||||
"empty_album": "",
|
|
||||||
"empty_trash": "أفرغ سلة المهملات",
|
"empty_trash": "أفرغ سلة المهملات",
|
||||||
"empty_trash_confirmation": "هل أنت متأكد أنك تريد إفراغ سلة المهملات؟ سيؤدي هذا إلى إزالة جميع المحتويات الموجودة في سلة المهملات بشكل نهائي من Immich.\nلا يمكنك التراجع عن هذا الإجراء!",
|
"empty_trash_confirmation": "هل أنت متأكد أنك تريد إفراغ سلة المهملات؟ سيؤدي هذا إلى إزالة جميع المحتويات الموجودة في سلة المهملات بشكل نهائي من Immich.\nلا يمكنك التراجع عن هذا الإجراء!",
|
||||||
"enable": "تفعيل",
|
"enable": "تفعيل",
|
||||||
@@ -628,6 +608,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_load_asset": "فشل تحميل المحتوى",
|
"failed_to_load_asset": "فشل تحميل المحتوى",
|
||||||
"failed_to_load_assets": "فشل تحميل المحتويات",
|
"failed_to_load_assets": "فشل تحميل المحتويات",
|
||||||
"failed_to_load_people": "فشل تحميل الأشخاص",
|
"failed_to_load_people": "فشل تحميل الأشخاص",
|
||||||
@@ -655,8 +636,6 @@
|
|||||||
"unable_to_change_location": "غير قادر على تغيير الموقع",
|
"unable_to_change_location": "غير قادر على تغيير الموقع",
|
||||||
"unable_to_change_password": "غير قادر على تغيير كلمة المرور",
|
"unable_to_change_password": "غير قادر على تغيير كلمة المرور",
|
||||||
"unable_to_change_visibility": "غير قادر على تغيير الظهور لـ {count, plural, one {# شخص} other {# أشخاص}}",
|
"unable_to_change_visibility": "غير قادر على تغيير الظهور لـ {count, plural, one {# شخص} other {# أشخاص}}",
|
||||||
"unable_to_check_item": "",
|
|
||||||
"unable_to_check_items": "",
|
|
||||||
"unable_to_complete_oauth_login": "غير قادر على إكمال تسجيل الدخول عبر OAuth",
|
"unable_to_complete_oauth_login": "غير قادر على إكمال تسجيل الدخول عبر OAuth",
|
||||||
"unable_to_connect": "غير قادر على الإتصال",
|
"unable_to_connect": "غير قادر على الإتصال",
|
||||||
"unable_to_connect_to_server": "غير قادر على الإتصال بالسيرفر",
|
"unable_to_connect_to_server": "غير قادر على الإتصال بالسيرفر",
|
||||||
@@ -697,12 +676,10 @@
|
|||||||
"unable_to_remove_album_users": "تعذر إزالة المستخدمين من الألبوم",
|
"unable_to_remove_album_users": "تعذر إزالة المستخدمين من الألبوم",
|
||||||
"unable_to_remove_api_key": "تعذر إزالة مفتاح API",
|
"unable_to_remove_api_key": "تعذر إزالة مفتاح API",
|
||||||
"unable_to_remove_assets_from_shared_link": "غير قادر على إزالة المحتويات من الرابط المشترك",
|
"unable_to_remove_assets_from_shared_link": "غير قادر على إزالة المحتويات من الرابط المشترك",
|
||||||
"unable_to_remove_comment": "",
|
|
||||||
"unable_to_remove_deleted_assets": "غير قادر على إزالة الملفات غير المتصلة",
|
"unable_to_remove_deleted_assets": "غير قادر على إزالة الملفات غير المتصلة",
|
||||||
"unable_to_remove_library": "غير قادر على إزالة المكتبة",
|
"unable_to_remove_library": "غير قادر على إزالة المكتبة",
|
||||||
"unable_to_remove_partner": "غير قادر على إزالة الشريك",
|
"unable_to_remove_partner": "غير قادر على إزالة الشريك",
|
||||||
"unable_to_remove_reaction": "غير قادر على إزالة رد الفعل",
|
"unable_to_remove_reaction": "غير قادر على إزالة رد الفعل",
|
||||||
"unable_to_remove_user": "",
|
|
||||||
"unable_to_repair_items": "غير قادر على إصلاح العناصر",
|
"unable_to_repair_items": "غير قادر على إصلاح العناصر",
|
||||||
"unable_to_reset_password": "غير قادر على إعادة تعيين كلمة المرور",
|
"unable_to_reset_password": "غير قادر على إعادة تعيين كلمة المرور",
|
||||||
"unable_to_resolve_duplicate": "غير قادر على حل التكرارات",
|
"unable_to_resolve_duplicate": "غير قادر على حل التكرارات",
|
||||||
@@ -732,10 +709,6 @@
|
|||||||
"unable_to_update_user": "غير قادر على تحديث المستخدم",
|
"unable_to_update_user": "غير قادر على تحديث المستخدم",
|
||||||
"unable_to_upload_file": "تعذر رفع الملف"
|
"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": "خروج من العرض التقديمي",
|
"exit_slideshow": "خروج من العرض التقديمي",
|
||||||
"expand_all": "توسيع الكل",
|
"expand_all": "توسيع الكل",
|
||||||
@@ -750,33 +723,27 @@
|
|||||||
"external": "خارجي",
|
"external": "خارجي",
|
||||||
"external_libraries": "المكتبات الخارجية",
|
"external_libraries": "المكتبات الخارجية",
|
||||||
"face_unassigned": "غير معين",
|
"face_unassigned": "غير معين",
|
||||||
"failed_to_get_people": "",
|
|
||||||
"favorite": "مفضل",
|
"favorite": "مفضل",
|
||||||
"favorite_or_unfavorite_photo": "تفضيل أو إلغاء تفضيل الصورة",
|
"favorite_or_unfavorite_photo": "تفضيل أو إلغاء تفضيل الصورة",
|
||||||
"favorites": "المفضلة",
|
"favorites": "المفضلة",
|
||||||
"feature": "",
|
|
||||||
"feature_photo_updated": "تم تحديث الصورة المميزة",
|
"feature_photo_updated": "تم تحديث الصورة المميزة",
|
||||||
"featurecollection": "",
|
|
||||||
"features": "الميزات",
|
"features": "الميزات",
|
||||||
"features_setting_description": "إدارة ميزات التطبيق",
|
"features_setting_description": "إدارة ميزات التطبيق",
|
||||||
"file_name": "إسم الملف",
|
"file_name": "إسم الملف",
|
||||||
"file_name_or_extension": "اسم الملف أو امتداده",
|
"file_name_or_extension": "اسم الملف أو امتداده",
|
||||||
"filename": "اسم الملف",
|
"filename": "اسم الملف",
|
||||||
"files": "",
|
|
||||||
"filetype": "نوع الملف",
|
"filetype": "نوع الملف",
|
||||||
"filter_people": "تصفية الاشخاص",
|
"filter_people": "تصفية الاشخاص",
|
||||||
"find_them_fast": "يمكنك العثور عليها بسرعة بالاسم من خلال البحث",
|
"find_them_fast": "يمكنك العثور عليها بسرعة بالاسم من خلال البحث",
|
||||||
"fix_incorrect_match": "إصلاح المطابقة غير الصحيحة",
|
"fix_incorrect_match": "إصلاح المطابقة غير الصحيحة",
|
||||||
"folders": "المجلدات",
|
"folders": "المجلدات",
|
||||||
"folders_feature_description": "تصفح عرض المجلد للصور ومقاطع الفيديو الموجودة على نظام الملفات",
|
"folders_feature_description": "تصفح عرض المجلد للصور ومقاطع الفيديو الموجودة على نظام الملفات",
|
||||||
"force_re-scan_library_files": "فرض إعادة فحص جميع ملفات المكتبة",
|
|
||||||
"forward": "إلى الأمام",
|
"forward": "إلى الأمام",
|
||||||
"general": "عام",
|
"general": "عام",
|
||||||
"get_help": "الحصول على المساعدة",
|
"get_help": "الحصول على المساعدة",
|
||||||
"getting_started": "البدء",
|
"getting_started": "البدء",
|
||||||
"go_back": "الرجوع للخلف",
|
"go_back": "الرجوع للخلف",
|
||||||
"go_to_search": "اذهب إلى البحث",
|
"go_to_search": "اذهب إلى البحث",
|
||||||
"go_to_share_page": "انتقل إلى صفحة المشاركة",
|
|
||||||
"group_albums_by": "تجميع الألبومات حسب...",
|
"group_albums_by": "تجميع الألبومات حسب...",
|
||||||
"group_no": "بدون تجميع",
|
"group_no": "بدون تجميع",
|
||||||
"group_owner": "تجميع حسب المالك",
|
"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_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_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_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_logo": "شعار immich",
|
||||||
"immich_web_interface": "واجهة ويب immich",
|
"immich_web_interface": "واجهة ويب immich",
|
||||||
"import_from_json": "استيراد من JSON",
|
"import_from_json": "استيراد من JSON",
|
||||||
@@ -826,10 +789,11 @@
|
|||||||
"invite_people": "دعوة الأشخاص",
|
"invite_people": "دعوة الأشخاص",
|
||||||
"invite_to_album": "دعوة إلى الألبوم",
|
"invite_to_album": "دعوة إلى الألبوم",
|
||||||
"items_count": "{count, plural, one {# عنصر} other {# عناصر}}",
|
"items_count": "{count, plural, one {# عنصر} other {# عناصر}}",
|
||||||
"job_settings_description": "",
|
|
||||||
"jobs": "الوظائف",
|
"jobs": "الوظائف",
|
||||||
"keep": "احتفظ",
|
"keep": "احتفظ",
|
||||||
"keep_all": "احتفظ بالكل",
|
"keep_all": "احتفظ بالكل",
|
||||||
|
"keep_this_delete_others": "احتفظ بهذا، واحذف الآخرين",
|
||||||
|
"kept_this_deleted_others": "تم الاحتفاظ بهذا الأصل وحذف {count, plural, one {# asset} other {# assets}}",
|
||||||
"keyboard_shortcuts": "اختصارات لوحة المفاتيح",
|
"keyboard_shortcuts": "اختصارات لوحة المفاتيح",
|
||||||
"language": "اللغة",
|
"language": "اللغة",
|
||||||
"language_setting_description": "اختر لغتك المفضلة",
|
"language_setting_description": "اختر لغتك المفضلة",
|
||||||
@@ -841,31 +805,6 @@
|
|||||||
"level": "المستوى",
|
"level": "المستوى",
|
||||||
"library": "مكتبة",
|
"library": "مكتبة",
|
||||||
"library_options": "خيارات المكتبة",
|
"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": "المضيئ",
|
"light": "المضيئ",
|
||||||
"like_deleted": "تم حذف الإعجاب",
|
"like_deleted": "تم حذف الإعجاب",
|
||||||
"link_motion_video": "رابط فيديو الحركة",
|
"link_motion_video": "رابط فيديو الحركة",
|
||||||
@@ -887,6 +826,7 @@
|
|||||||
"look": "الشكل",
|
"look": "الشكل",
|
||||||
"loop_videos": "تكرار مقاطع الفيديو",
|
"loop_videos": "تكرار مقاطع الفيديو",
|
||||||
"loop_videos_description": "فَعْل لتكرار مقطع فيديو تلقائيًا في عارض التفاصيل.",
|
"loop_videos_description": "فَعْل لتكرار مقطع فيديو تلقائيًا في عارض التفاصيل.",
|
||||||
|
"main_branch_warning": "أنت تستخدم إصداراً تطويرياً؛ ونحن نوصي بشدة باستخدام إصدار النشر!",
|
||||||
"make": "صنع",
|
"make": "صنع",
|
||||||
"manage_shared_links": "إدارة الروابط المشتركة",
|
"manage_shared_links": "إدارة الروابط المشتركة",
|
||||||
"manage_sharing_with_partners": "إدارة المشاركة مع الشركاء",
|
"manage_sharing_with_partners": "إدارة المشاركة مع الشركاء",
|
||||||
@@ -969,7 +909,6 @@
|
|||||||
"onboarding_welcome_user": "مرحبا، {user}",
|
"onboarding_welcome_user": "مرحبا، {user}",
|
||||||
"online": "متصل",
|
"online": "متصل",
|
||||||
"only_favorites": "المفضلة فقط",
|
"only_favorites": "المفضلة فقط",
|
||||||
"only_refreshes_modified_files": "تحديث الملفات المعدلة فقط",
|
|
||||||
"open_in_map_view": "فتح في عرض الخريطة",
|
"open_in_map_view": "فتح في عرض الخريطة",
|
||||||
"open_in_openstreetmap": "فتح في OpenStreetMap",
|
"open_in_openstreetmap": "فتح في OpenStreetMap",
|
||||||
"open_the_search_filters": "افتح مرشحات البحث",
|
"open_the_search_filters": "افتح مرشحات البحث",
|
||||||
@@ -1007,7 +946,6 @@
|
|||||||
"people_edits_count": "تم تعديل {count, plural, one {# شخص } other {# أشخاص }}",
|
"people_edits_count": "تم تعديل {count, plural, one {# شخص } other {# أشخاص }}",
|
||||||
"people_feature_description": "تصفح الصور ومقاطع الفيديو المجمعة حسب الأشخاص",
|
"people_feature_description": "تصفح الصور ومقاطع الفيديو المجمعة حسب الأشخاص",
|
||||||
"people_sidebar_description": "عرض رابط للأشخاص في الشريط الجانبي",
|
"people_sidebar_description": "عرض رابط للأشخاص في الشريط الجانبي",
|
||||||
"perform_library_tasks": "",
|
|
||||||
"permanent_deletion_warning": "تحذير الحذف الدائم",
|
"permanent_deletion_warning": "تحذير الحذف الدائم",
|
||||||
"permanent_deletion_warning_setting_description": "إظهار تحذير عند حذف المحتويات نهائيًا",
|
"permanent_deletion_warning_setting_description": "إظهار تحذير عند حذف المحتويات نهائيًا",
|
||||||
"permanently_delete": "حذف بشكل دائم",
|
"permanently_delete": "حذف بشكل دائم",
|
||||||
@@ -1029,7 +967,6 @@
|
|||||||
"play_memories": "تشغيل الذكريات",
|
"play_memories": "تشغيل الذكريات",
|
||||||
"play_motion_photo": "تشغيل الصور المتحركة",
|
"play_motion_photo": "تشغيل الصور المتحركة",
|
||||||
"play_or_pause_video": "تشغيل الفيديو أو إيقافه مؤقتًا",
|
"play_or_pause_video": "تشغيل الفيديو أو إيقافه مؤقتًا",
|
||||||
"point": "",
|
|
||||||
"port": "المنفذ",
|
"port": "المنفذ",
|
||||||
"preset": "الإعداد المسبق",
|
"preset": "الإعداد المسبق",
|
||||||
"preview": "معاينة",
|
"preview": "معاينة",
|
||||||
@@ -1074,12 +1011,10 @@
|
|||||||
"purchase_server_description_2": "حالة الداعم",
|
"purchase_server_description_2": "حالة الداعم",
|
||||||
"purchase_server_title": "الخادم",
|
"purchase_server_title": "الخادم",
|
||||||
"purchase_settings_server_activated": "يتم إدارة مفتاح منتج الخادم من قبل مدير النظام",
|
"purchase_settings_server_activated": "يتم إدارة مفتاح منتج الخادم من قبل مدير النظام",
|
||||||
"range": "",
|
|
||||||
"rating": "تقييم نجمي",
|
"rating": "تقييم نجمي",
|
||||||
"rating_clear": "مسح التقييم",
|
"rating_clear": "مسح التقييم",
|
||||||
"rating_count": "{count, plural, one {# نجمة} other {# نجوم}}",
|
"rating_count": "{count, plural, one {# نجمة} other {# نجوم}}",
|
||||||
"rating_description": "اعرض تقييم EXIF في لوحة المعلومات",
|
"rating_description": "اعرض تقييم EXIF في لوحة المعلومات",
|
||||||
"raw": "",
|
|
||||||
"reaction_options": "خيارات رد الفعل",
|
"reaction_options": "خيارات رد الفعل",
|
||||||
"read_changelog": "قراءة سجل التغيير",
|
"read_changelog": "قراءة سجل التغيير",
|
||||||
"reassign": "إعادة التعيين",
|
"reassign": "إعادة التعيين",
|
||||||
@@ -1124,7 +1059,6 @@
|
|||||||
"reset": "إعادة ضبط",
|
"reset": "إعادة ضبط",
|
||||||
"reset_password": "إعادة تعيين كلمة المرور",
|
"reset_password": "إعادة تعيين كلمة المرور",
|
||||||
"reset_people_visibility": "إعادة ضبط ظهور الأشخاص",
|
"reset_people_visibility": "إعادة ضبط ظهور الأشخاص",
|
||||||
"reset_settings_to_default": "",
|
|
||||||
"reset_to_default": "إعادة التعيين إلى الافتراضي",
|
"reset_to_default": "إعادة التعيين إلى الافتراضي",
|
||||||
"resolve_duplicates": "معالجة النسخ المكررة",
|
"resolve_duplicates": "معالجة النسخ المكررة",
|
||||||
"resolved_all_duplicates": "تم حل جميع التكرارات",
|
"resolved_all_duplicates": "تم حل جميع التكرارات",
|
||||||
@@ -1144,9 +1078,7 @@
|
|||||||
"saved_settings": "تم حفظ الإعدادات",
|
"saved_settings": "تم حفظ الإعدادات",
|
||||||
"say_something": "قل شيئًا",
|
"say_something": "قل شيئًا",
|
||||||
"scan_all_libraries": "فحص كل المكتبات",
|
"scan_all_libraries": "فحص كل المكتبات",
|
||||||
"scan_all_library_files": "إعادة فحص كافة ملفات المكتبة",
|
|
||||||
"scan_library": "مسح",
|
"scan_library": "مسح",
|
||||||
"scan_new_library_files": "فحص ملفات المكتبة الجديدة",
|
|
||||||
"scan_settings": "إعدادات الفحص",
|
"scan_settings": "إعدادات الفحص",
|
||||||
"scanning_for_album": "جارٍ الفحص عن ألبوم...",
|
"scanning_for_album": "جارٍ الفحص عن ألبوم...",
|
||||||
"search": "بحث",
|
"search": "بحث",
|
||||||
@@ -1189,7 +1121,6 @@
|
|||||||
"selected_count": "{count, plural, other {# محددة }}",
|
"selected_count": "{count, plural, other {# محددة }}",
|
||||||
"send_message": "أرسل رسالة",
|
"send_message": "أرسل رسالة",
|
||||||
"send_welcome_email": "أرسل بريدًا إلكترونيًا ترحيبيًا",
|
"send_welcome_email": "أرسل بريدًا إلكترونيًا ترحيبيًا",
|
||||||
"server": "الخادم",
|
|
||||||
"server_offline": "الخادم غير متصل",
|
"server_offline": "الخادم غير متصل",
|
||||||
"server_online": "الخادم متصل",
|
"server_online": "الخادم متصل",
|
||||||
"server_stats": "إحصائيات الخادم",
|
"server_stats": "إحصائيات الخادم",
|
||||||
@@ -1294,6 +1225,7 @@
|
|||||||
"they_will_be_merged_together": "سيتم دمجهم معًا",
|
"they_will_be_merged_together": "سيتم دمجهم معًا",
|
||||||
"third_party_resources": "موارد الطرف الثالث",
|
"third_party_resources": "موارد الطرف الثالث",
|
||||||
"time_based_memories": "ذكريات استنادًا للوقت",
|
"time_based_memories": "ذكريات استنادًا للوقت",
|
||||||
|
"timeline": "الخط الزمني",
|
||||||
"timezone": "المنطقة الزمنية",
|
"timezone": "المنطقة الزمنية",
|
||||||
"to_archive": "أرشفة",
|
"to_archive": "أرشفة",
|
||||||
"to_change_password": "تغيير كلمة المرور",
|
"to_change_password": "تغيير كلمة المرور",
|
||||||
@@ -1303,7 +1235,7 @@
|
|||||||
"to_trash": "حذف",
|
"to_trash": "حذف",
|
||||||
"toggle_settings": "الإعدادات",
|
"toggle_settings": "الإعدادات",
|
||||||
"toggle_theme": "تبديل المظهر الداكن",
|
"toggle_theme": "تبديل المظهر الداكن",
|
||||||
"toggle_visibility": "تبديل الرؤية",
|
"total": "الإجمالي",
|
||||||
"total_usage": "الاستخدام الإجمالي",
|
"total_usage": "الاستخدام الإجمالي",
|
||||||
"trash": "المهملات",
|
"trash": "المهملات",
|
||||||
"trash_all": "نقل الكل إلى سلة المهملات",
|
"trash_all": "نقل الكل إلى سلة المهملات",
|
||||||
@@ -1313,12 +1245,10 @@
|
|||||||
"trashed_items_will_be_permanently_deleted_after": "سيتم حذفُ العناصر المحذوفة نِهائيًا بعد {days, plural, one {# يوم} other {# أيام }}.",
|
"trashed_items_will_be_permanently_deleted_after": "سيتم حذفُ العناصر المحذوفة نِهائيًا بعد {days, plural, one {# يوم} other {# أيام }}.",
|
||||||
"type": "النوع",
|
"type": "النوع",
|
||||||
"unarchive": "أخرج من الأرشيف",
|
"unarchive": "أخرج من الأرشيف",
|
||||||
"unarchived": "",
|
|
||||||
"unarchived_count": "{count, plural, other {غير مؤرشفة #}}",
|
"unarchived_count": "{count, plural, other {غير مؤرشفة #}}",
|
||||||
"unfavorite": "أزل التفضيل",
|
"unfavorite": "أزل التفضيل",
|
||||||
"unhide_person": "أظهر الشخص",
|
"unhide_person": "أظهر الشخص",
|
||||||
"unknown": "غير معروف",
|
"unknown": "غير معروف",
|
||||||
"unknown_album": "",
|
|
||||||
"unknown_year": "سنة غير معروفة",
|
"unknown_year": "سنة غير معروفة",
|
||||||
"unlimited": "غير محدود",
|
"unlimited": "غير محدود",
|
||||||
"unlink_motion_video": "إلغاء ربط فيديو الحركة",
|
"unlink_motion_video": "إلغاء ربط فيديو الحركة",
|
||||||
@@ -1350,13 +1280,13 @@
|
|||||||
"use_custom_date_range": "استخدم النطاق الزمني المخصص بدلاً من ذلك",
|
"use_custom_date_range": "استخدم النطاق الزمني المخصص بدلاً من ذلك",
|
||||||
"user": "مستخدم",
|
"user": "مستخدم",
|
||||||
"user_id": "معرف المستخدم",
|
"user_id": "معرف المستخدم",
|
||||||
"user_license_settings": "رخصة",
|
|
||||||
"user_license_settings_description": "ادر رخصتك",
|
|
||||||
"user_liked": "قام {user} بالإعجاب {type, select, photo {بهذه الصورة} video {بهذا الفيديو} asset {بهذا المحتوى} other {بها}}",
|
"user_liked": "قام {user} بالإعجاب {type, select, photo {بهذه الصورة} video {بهذا الفيديو} asset {بهذا المحتوى} other {بها}}",
|
||||||
"user_purchase_settings": "الشراء",
|
"user_purchase_settings": "الشراء",
|
||||||
"user_purchase_settings_description": "إدارة عملية الشراء الخاصة بك",
|
"user_purchase_settings_description": "إدارة عملية الشراء الخاصة بك",
|
||||||
"user_role_set": "قم بتعيين {user} كـ {role}",
|
"user_role_set": "قم بتعيين {user} كـ {role}",
|
||||||
"user_usage_detail": "تفاصيل استخدام المستخدم",
|
"user_usage_detail": "تفاصيل استخدام المستخدم",
|
||||||
|
"user_usage_stats": "إحصائيات استخدام الحساب",
|
||||||
|
"user_usage_stats_description": "عرض إحصائيات استخدام الحساب",
|
||||||
"username": "اسم المستخدم",
|
"username": "اسم المستخدم",
|
||||||
"users": "المستخدمين",
|
"users": "المستخدمين",
|
||||||
"utilities": "أدوات",
|
"utilities": "أدوات",
|
||||||
@@ -1364,7 +1294,7 @@
|
|||||||
"variables": "المتغيرات",
|
"variables": "المتغيرات",
|
||||||
"version": "الإصدار",
|
"version": "الإصدار",
|
||||||
"version_announcement_closing": "صديقك، أليكس",
|
"version_announcement_closing": "صديقك، أليكس",
|
||||||
"version_announcement_message": "مرحباً يا صديقي، هنالك نسخة جديدة من التطبيق. خذ وقتك لزيارة <link>ملاحظات الإصدار</link> والتأكد من أن ملف <code>docker-compose.yml</code> وإعداد <code>.env</code> مُحدّثين لتجنب أي إعدادات خاطئة، خاصةً إذا كنت تستخدم WatchTower أو أي آلية تقوم بتحديث التطبيق تلقائياً.",
|
"version_announcement_message": "مرحبًا! يتوفر إصدار جديد من Immich. يُرجى تخصيص بعض الوقت لقراءة <link>ملاحظات الإصدار</link> للتأكد من تحديث إعداداتك لمنع أي أخطاء في التكوين، خاصة إذا كنت تستخدم WatchTower أو أي آلية تتولى تحديث مثيل Immich الخاص بك تلقائيًا.",
|
||||||
"version_history": "تاريخ الإصدار",
|
"version_history": "تاريخ الإصدار",
|
||||||
"version_history_item": "تم تثبيت {version} في {date}",
|
"version_history_item": "تم تثبيت {version} في {date}",
|
||||||
"video": "فيديو",
|
"video": "فيديو",
|
||||||
@@ -1378,10 +1308,10 @@
|
|||||||
"view_all_users": "عرض كافة المستخدمين",
|
"view_all_users": "عرض كافة المستخدمين",
|
||||||
"view_in_timeline": "عرض في الجدول الزمني",
|
"view_in_timeline": "عرض في الجدول الزمني",
|
||||||
"view_links": "عرض الروابط",
|
"view_links": "عرض الروابط",
|
||||||
|
"view_name": "عرض",
|
||||||
"view_next_asset": "عرض المحتوى التالي",
|
"view_next_asset": "عرض المحتوى التالي",
|
||||||
"view_previous_asset": "عرض المحتوى السابق",
|
"view_previous_asset": "عرض المحتوى السابق",
|
||||||
"view_stack": "عرض التكديس",
|
"view_stack": "عرض التكديس",
|
||||||
"viewer": "",
|
|
||||||
"visibility_changed": "الرؤية تغيرت لـ {count, plural, one {شخص واحد} other {# عدة أشخاص}}",
|
"visibility_changed": "الرؤية تغيرت لـ {count, plural, one {شخص واحد} other {# عدة أشخاص}}",
|
||||||
"waiting": "في الانتظار",
|
"waiting": "في الانتظار",
|
||||||
"warning": "تحذير",
|
"warning": "تحذير",
|
||||||
|
|||||||
14
i18n/az.json
@@ -1,8 +1,10 @@
|
|||||||
{
|
{
|
||||||
"about": "Haqqında",
|
"about": "Yenilə",
|
||||||
"account": "Hesab",
|
"account": "Hesab",
|
||||||
"account_settings": "Hesab parametrləri",
|
"account_settings": "Hesab parametrləri",
|
||||||
"acknowledge": "Təsdiq et",
|
"acknowledge": "Təsdiq et",
|
||||||
|
"action": "Əməliyyat",
|
||||||
|
"actions": "Əməliyyatlar",
|
||||||
"active": "Aktiv",
|
"active": "Aktiv",
|
||||||
"activity": "Fəaliyyət",
|
"activity": "Fəaliyyət",
|
||||||
"add": "Əlavə et",
|
"add": "Əlavə et",
|
||||||
@@ -10,9 +12,12 @@
|
|||||||
"add_a_location": "Məkan əlavə et",
|
"add_a_location": "Məkan əlavə et",
|
||||||
"add_a_name": "Ad əlavə et",
|
"add_a_name": "Ad əlavə et",
|
||||||
"add_a_title": "Başlıq ə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_location": "Məkanı əlavə et",
|
||||||
"add_more_users": "Daha çox istifadəçi əlavə et",
|
"add_more_users": "Daha çox istifadəçi əlavə et",
|
||||||
"add_partner": "Partnyor əlavə et",
|
"add_partner": "Partnyor əlavə et",
|
||||||
|
"add_path": "Yol əlavə et",
|
||||||
"add_photos": "Şəkilləri əlavə et",
|
"add_photos": "Şəkilləri əlavə et",
|
||||||
"add_to": "... əlavə et",
|
"add_to": "... əlavə et",
|
||||||
"add_to_album": "Albom ə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_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 <link> Server Əmri</link> -ni istifadə edin.",
|
"authentication_settings_reenable": "Yenidən aktiv etmək üçün <link> Server Əmri</link> -ni istifadə edin.",
|
||||||
"background_task_job": "Arxa plan tapşırıqları",
|
"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",
|
"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_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_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?",
|
"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_delayed": "{jobCount, plural, other {# gecikməli}}",
|
||||||
"jobs_failed": "{jobCount, plural, other {# uğursuz}}",
|
"jobs_failed": "{jobCount, plural, other {# uğursuz}}",
|
||||||
"library_created": "{library} kitabxanası yaradıldı",
|
"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 <link>Crontab Guru</link>",
|
|
||||||
"library_cron_expression_presets": "Kron zamanlamasının ilkin parametrləri",
|
|
||||||
"library_deleted": "Kitabxana silindi",
|
"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_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",
|
"library_scanning": "Periodik skan",
|
||||||
|
|||||||
91
i18n/be.json
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"about": "Пра праграму",
|
"about": "Аб",
|
||||||
"account": "Уліковы запіс",
|
"account": "Уліковы запіс",
|
||||||
"account_settings": "Налады акаўнта",
|
"account_settings": "Налады ўліковага запісу",
|
||||||
"acknowledge": "Пацвердзіць",
|
"acknowledge": "Пацвердзіць",
|
||||||
"action": "Дзеянне",
|
"action": "Дзеянне",
|
||||||
"actions": "Дзеянні",
|
"actions": "Дзеянні",
|
||||||
@@ -23,10 +23,93 @@
|
|||||||
"add_to": "Дадаць у...",
|
"add_to": "Дадаць у...",
|
||||||
"add_to_album": "Дадаць у альбом",
|
"add_to_album": "Дадаць у альбом",
|
||||||
"add_to_shared_album": "Дадаць у агульны альбом",
|
"add_to_shared_album": "Дадаць у агульны альбом",
|
||||||
|
"add_url": "Дадаць URL",
|
||||||
"added_to_archive": "Дададзена ў архіў",
|
"added_to_archive": "Дададзена ў архіў",
|
||||||
"added_to_favorites": "Дададзена ў абраныя",
|
"added_to_favorites": "Дададзена ў абраныя",
|
||||||
"added_to_favorites_count": "Дададзена {count, number} да абранага",
|
"added_to_favorites_count": "Дададзена {count, number} да абранага",
|
||||||
"admin": {
|
"admin": {
|
||||||
"add_exclusion_pattern_description": "Дадайце шаблоны выключэнняў. Падтрымліваецца выкарыстанне сімвалаў * , ** і ?. Каб ігнараваць усе файлы ў любой дырэкторыі з назвай \"Raw\", выкарыстоўвайце \"**/Raw/**\". Каб ігнараваць усе файлы, якія заканчваюцца на \".tif\", выкарыстоўвайце \"**/.tif\". Каб ігнараваць абсолютны шлях, выкарыстоўвайце \"/path/to/ignore/**\"."
|
"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": "Каб зноў уключыць, выкарыстайце <link>Каманду сервера</link>.",
|
||||||
|
"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. Для атрымання дадатковай інфармацыі, калі ласка, звярніцеся, напрыклад, да <link>Crontab Guru</link>",
|
||||||
|
"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. Калі ласка, знайдзіце час, каб прачытаць <link>нататкі да выпуску</link>, каб пераканацца, што ваша налада актуальная і пазбегнуць магчымых памылак канфігурацыі, асабліва калі вы карыстаецеся 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": "Павялічыць відарыс"
|
||||||
}
|
}
|
||||||
|
|||||||
204
i18n/bg.json
@@ -23,17 +23,23 @@
|
|||||||
"add_to": "Добави към...",
|
"add_to": "Добави към...",
|
||||||
"add_to_album": "Добави към албум",
|
"add_to_album": "Добави към албум",
|
||||||
"add_to_shared_album": "Добави към споделен албум",
|
"add_to_shared_album": "Добави към споделен албум",
|
||||||
|
"add_url": "Добави URL",
|
||||||
"added_to_archive": "Добавено към архива",
|
"added_to_archive": "Добавено към архива",
|
||||||
"added_to_favorites": "Добавени към любимите ви",
|
"added_to_favorites": "Добавени към любимите ви",
|
||||||
"added_to_favorites_count": "Добавени {count, number} към любими",
|
"added_to_favorites_count": "Добавени {count, number} към любими",
|
||||||
"admin": {
|
"admin": {
|
||||||
"add_exclusion_pattern_description": "Добави модели за изключване. Поддържа се \"globbing\" с помощта на *, ** и ?. За да игнорирате всички файлове в директория с име \"Raw\", използвайте \"**/Raw/**\". За да игнорирате всички файлове, завършващи на \".tif\", използвайте \"**/*.tif\". За да игнорирате абсолютен път, използвайте \"/path/to/ignore/**\".",
|
"add_exclusion_pattern_description": "Добави модели за изключване. Поддържа се \"globbing\" с помощта на *, ** и ?. За да игнорирате всички файлове в директория с име \"Raw\", използвайте \"**/Raw/**\". За да игнорирате всички файлове, завършващи на \".tif\", използвайте \"**/*.tif\". За да игнорирате абсолютен път, използвайте \"/path/to/ignore/**\".",
|
||||||
"asset_offline_description": "Този външен библиотечен елемент не може да бъде открит на диска и е преместен в кошчето за боклук. Ако файлът е преместен в библиотеката, проверете вашата история за нов съответстващ елемент. За да възстановите елемента, моля проверете дали файловият път отдолу може да бъде достъпен от Immich и сканирайте библиотеката.",
|
"asset_offline_description": "Този външен библиотечен елемент не може да бъде открит на диска и е преместен в кошчето за боклук. Ако файлът е преместен в библиотеката, проверете вашата история за нов съответстващ елемент. За да възстановите елемента, моля проверете дали файловият път отдолу може да бъде достъпен от Immich и сканирайте библиотеката.",
|
||||||
"authentication_settings": "Настройки за удостоверяване",
|
"authentication_settings": "Настройки за удостоверяване",
|
||||||
"authentication_settings_description": "Управление на парола, OAuth и други настройки за удостоверяване",
|
"authentication_settings_description": "Управление на парола, OAuth и други настройки за удостоверяване",
|
||||||
"authentication_settings_disable_all": "Сигурни ли сте, че искате да деактивирате всички методи за вписване? Вписването ще бъде напълно деактивирано.",
|
"authentication_settings_disable_all": "Сигурни ли сте, че искате да деактивирате всички методи за вписване? Вписването ще бъде напълно деактивирано.",
|
||||||
"authentication_settings_reenable": "За да реактивирате, изполвайте <link>Server Command</link>.",
|
"authentication_settings_reenable": "За да реактивирате, изполвайте <link>Server Command</link>.",
|
||||||
"background_task_job": "Процеси на заден фон",
|
"background_task_job": "Процеси на заден фон",
|
||||||
|
"backup_database": "Резервна База данни",
|
||||||
|
"backup_database_enable_description": "Разрешаване на резервни копия на базата данни",
|
||||||
|
"backup_keep_last_amount": "Брой резервни копия за запазване",
|
||||||
|
"backup_settings": "Настройка на резервни копия",
|
||||||
|
"backup_settings_description": "Управление на настройките за резервно копие на базата данни",
|
||||||
"check_all": "Провери всичко",
|
"check_all": "Провери всичко",
|
||||||
"cleared_jobs": "Изчистени задачи от тип: {job}",
|
"cleared_jobs": "Изчистени задачи от тип: {job}",
|
||||||
"config_set_by_file": "Конфигурацията е зададена от файл",
|
"config_set_by_file": "Конфигурацията е зададена от файл",
|
||||||
@@ -43,6 +49,9 @@
|
|||||||
"confirm_reprocess_all_faces": "Сигурни ли сте, че искате да се обработят лицата отново? Това ще изчисти всички именувани хора.",
|
"confirm_reprocess_all_faces": "Сигурни ли сте, че искате да се обработят лицата отново? Това ще изчисти всички именувани хора.",
|
||||||
"confirm_user_password_reset": "Сигурни ли сте, че искате да нулирате паролата на {user}?",
|
"confirm_user_password_reset": "Сигурни ли сте, че искате да нулирате паролата на {user}?",
|
||||||
"create_job": "Създайте задача",
|
"create_job": "Създайте задача",
|
||||||
|
"cron_expression": "Cron израз",
|
||||||
|
"cron_expression_description": "Настрой интервала на сканиране използвайки cron формата. За повече информация <link>Crontab Guru</link>",
|
||||||
|
"cron_expression_presets": "Примерни Cron изрази",
|
||||||
"disable_login": "Изключете вписването",
|
"disable_login": "Изключете вписването",
|
||||||
"duplicate_detection_job_description": "Стартиране машинно обучение на ресурси, за откриване на подобни изображения. Разчита на Интелигентно Търсене",
|
"duplicate_detection_job_description": "Стартиране машинно обучение на ресурси, за откриване на подобни изображения. Разчита на Интелигентно Търсене",
|
||||||
"exclusion_pattern_description": "Модели за изключване позволяват да игнорирате файлове и папки, когато сканирате вашата библиотека. Това е потребно, ако имате папки, които съдържат файлове, които не искате да импортирате. Примерно - RAW файлове.",
|
"exclusion_pattern_description": "Модели за изключване позволяват да игнорирате файлове и папки, когато сканирате вашата библиотека. Това е потребно, ако имате папки, които съдържат файлове, които не искате да импортирате. Примерно - RAW файлове.",
|
||||||
@@ -54,21 +63,23 @@
|
|||||||
"failed_job_command": "Командата {command} е неуспешна за задача: {job}",
|
"failed_job_command": "Командата {command} е неуспешна за задача: {job}",
|
||||||
"force_delete_user_warning": "ВНИМАНИЕ: Това веднага ще изтрие потребителя и всичките му ресурси. Действието е необратимо и файловете не могат да бъдат възстановени.",
|
"force_delete_user_warning": "ВНИМАНИЕ: Това веднага ще изтрие потребителя и всичките му ресурси. Действието е необратимо и файловете не могат да бъдат възстановени.",
|
||||||
"forcing_refresh_library_files": "Принуждаване обновяване на всички файлове в библиотеката",
|
"forcing_refresh_library_files": "Принуждаване обновяване на всички файлове в библиотеката",
|
||||||
|
"image_format": "Формат",
|
||||||
"image_format_description": "WebP създава по-малки файлове от JPEG, но ги кодира по-бавно.",
|
"image_format_description": "WebP създава по-малки файлове от JPEG, но ги кодира по-бавно.",
|
||||||
"image_prefer_embedded_preview": "Предпочитане на вградените прегледи",
|
"image_prefer_embedded_preview": "Предпочитане на вградените прегледи",
|
||||||
"image_prefer_embedded_preview_setting_description": "Използване на вградените прегледи в RAW снимките като вход за обработка на изображенията, когато има такива. Това може да доведе до по-точни цветове за някои изображения, но качеството на прегледите зависи от камерата и изображението може да има повече компресионни артефакти.",
|
"image_prefer_embedded_preview_setting_description": "Използване на вградените прегледи в RAW снимките като вход за обработка на изображенията, когато има такива. Това може да доведе до по-точни цветове за някои изображения, но качеството на прегледите зависи от камерата и изображението може да има повече компресионни артефакти.",
|
||||||
"image_prefer_wide_gamut": "Предпочитане на широка гама",
|
"image_prefer_wide_gamut": "Предпочитане на широка гама",
|
||||||
"image_prefer_wide_gamut_setting_description": "Използване на Display P3 за миниатюри. Това запазва по-добре жизнеността на изображенията с широки цветови пространства, но изображенията може да изглеждат по различен начин на стари устройства със стара версия на браузъра. sRGB изображенията се запазват като sRGB, за да се избегнат цветови промени.",
|
"image_prefer_wide_gamut_setting_description": "Използване на Display P3 за миниатюри. Това запазва по-добре жизнеността на изображенията с широки цветови пространства, но изображенията може да изглеждат по различен начин на стари устройства със стара версия на браузъра. sRGB изображенията се запазват като sRGB, за да се избегнат цветови промени.",
|
||||||
"image_preview_format": "Формат на прегледите",
|
"image_preview_description": "Среден размер на изображението с премахнати метаданни, използвано при преглед на един актив и за машинно обучение",
|
||||||
"image_preview_resolution": "Резолюция на прегледите",
|
"image_preview_quality_description": "Качество на предварителния преглед от 1 до 100. По-високата стойност е по-добра, но води до по-големи файлове и може да намали бързодействието на приложението. Задаването на ниска стойност може да повлияе на качеството на машинното обучение.",
|
||||||
"image_preview_resolution_description": "Използва се при разглеждане на единична снимка и за машинно обучение. По-високите резолюции могат да запазят повече детайли, но отнемат повече време за кодиране, имат по-големи размери на файловете и могат да намалят отзивчивостта на приложението.",
|
"image_preview_title": "Настойки на прегледа",
|
||||||
"image_quality": "Качество",
|
"image_quality": "Качество",
|
||||||
"image_quality_description": "Качество на изображението от 1-100. По-голяма стойност води до по-добро качество, но създава по-големи файлове. Тази настройка засяга изображенията от тип преглед и миниатюра.",
|
"image_resolution": "Резолюция",
|
||||||
|
"image_resolution_description": "По-високите резолюции могат да запазят повече детайли, но изискват повече време за кодиране, имат по-големи размери на файловете и могат да намалят бързодействието на приложението.",
|
||||||
"image_settings": "Настройки за изображенията",
|
"image_settings": "Настройки за изображенията",
|
||||||
"image_settings_description": "Управляване качеството и резолюцията на създадените изображения",
|
"image_settings_description": "Управляване качеството и резолюцията на създадените изображения",
|
||||||
"image_thumbnail_format": "Формат на миниатюрните изображения",
|
"image_thumbnail_description": "Малка миниатюра с премахнати метаданни, използвана при преглед на групи снимки, като основния екран",
|
||||||
"image_thumbnail_resolution": "Резолюция на миниатюрните изображения",
|
"image_thumbnail_quality_description": "Качество на миниатюрата от 1 до 100. По-високата стойност е по-добра, но води до по-големи файлове и може да намали бързодействието на приложението.",
|
||||||
"image_thumbnail_resolution_description": "Използва се при разглеждане на групи от снимки (основна времева линия, изглед на албум и др.). По-високите резолюции могат да запазят повече детайли, но отнемат повече време за кодиране, имат по-големи размери на файловете и могат да намалят отзивчивостта на приложението.",
|
"image_thumbnail_title": "Настройки на миниатюрите",
|
||||||
"job_concurrency": "Паралелност на {job}",
|
"job_concurrency": "Паралелност на {job}",
|
||||||
"job_created": "Задачата е създадена",
|
"job_created": "Задачата е създадена",
|
||||||
"job_not_concurrency_safe": "Тази задача не е безопасна за паралелно изпълнение.",
|
"job_not_concurrency_safe": "Тази задача не е безопасна за паралелно изпълнение.",
|
||||||
@@ -78,9 +89,6 @@
|
|||||||
"jobs_delayed": "{jobCount, plural, other {# delayed}}",
|
"jobs_delayed": "{jobCount, plural, other {# delayed}}",
|
||||||
"jobs_failed": "{jobCount, plural, other {# failed}}",
|
"jobs_failed": "{jobCount, plural, other {# failed}}",
|
||||||
"library_created": "Създадена библиотека: {library}",
|
"library_created": "Създадена библиотека: {library}",
|
||||||
"library_cron_expression": "Cron израз",
|
|
||||||
"library_cron_expression_description": "Задайте интервала за сканиране чрез cron интервал. За повече информация, вижте например <link>Crontab Guru</link>",
|
|
||||||
"library_cron_expression_presets": "Предварителни настройки на Cron израза",
|
|
||||||
"library_deleted": "Библиотека е изтрита",
|
"library_deleted": "Библиотека е изтрита",
|
||||||
"library_import_path_description": "Посочете папка за импортиране. Тази папка, включително подпапките, ще бъдат сканирани за изображения и видеоклипове.",
|
"library_import_path_description": "Посочете папка за импортиране. Тази папка, включително подпапките, ще бъдат сканирани за изображения и видеоклипове.",
|
||||||
"library_scanning": "Периодично сканиране",
|
"library_scanning": "Периодично сканиране",
|
||||||
@@ -123,7 +131,7 @@
|
|||||||
"machine_learning_smart_search_description": "Семантично търсене на изображения с помощта на CLIP вграждания",
|
"machine_learning_smart_search_description": "Семантично търсене на изображения с помощта на CLIP вграждания",
|
||||||
"machine_learning_smart_search_enabled": "Включване на Интелигентно Търсене",
|
"machine_learning_smart_search_enabled": "Включване на Интелигентно Търсене",
|
||||||
"machine_learning_smart_search_enabled_description": "Ако е деактивирано, изображенията няма да бъдат кодирани за Интелигентно Търсене.",
|
"machine_learning_smart_search_enabled_description": "Ако е деактивирано, изображенията няма да бъдат кодирани за Интелигентно Търсене.",
|
||||||
"machine_learning_url_description": "URL адрес на сървъра за машинно обучение",
|
"machine_learning_url_description": "URL на сървъра за машинно обучение. Ако са предоставени повече от един URL, всеки сървър ще бъде опитан един по един, докато един не отговори успешно, в реда от първия до последния",
|
||||||
"manage_concurrency": "Управление на паралелност",
|
"manage_concurrency": "Управление на паралелност",
|
||||||
"manage_log_settings": "Управление на настройките на записване",
|
"manage_log_settings": "Управление на настройките на записване",
|
||||||
"map_dark_style": "Тъмен стил",
|
"map_dark_style": "Тъмен стил",
|
||||||
@@ -199,11 +207,11 @@
|
|||||||
"password_settings": "Вписване с парола",
|
"password_settings": "Вписване с парола",
|
||||||
"password_settings_description": "Управление на настройките за влизане с парола",
|
"password_settings_description": "Управление на настройките за влизане с парола",
|
||||||
"paths_validated_successfully": "Всички пътища са валидирани успешно",
|
"paths_validated_successfully": "Всички пътища са валидирани успешно",
|
||||||
|
"person_cleanup_job": "Почистване на лица",
|
||||||
"quota_size_gib": "Размер на квотата (GiB)",
|
"quota_size_gib": "Размер на квотата (GiB)",
|
||||||
"refreshing_all_libraries": "Опресняване на всички библиотеки",
|
"refreshing_all_libraries": "Опресняване на всички библиотеки",
|
||||||
"registration": "Администраторска регистрация",
|
"registration": "Администраторска регистрация",
|
||||||
"registration_description": "Тъй като сте първият потребител в системата, ще бъдете назначен като администратор и ще отговаряте за административните задачи, а допълнителните потребители ще бъдат създадени от вас.",
|
"registration_description": "Тъй като сте първият потребител в системата, ще бъдете назначен като администратор и ще отговаряте за административните задачи, а допълнителните потребители ще бъдат създадени от вас.",
|
||||||
"removing_deleted_files": "Премахване на офлайн файлове",
|
|
||||||
"repair_all": "Поправяне на всичко",
|
"repair_all": "Поправяне на всичко",
|
||||||
"repair_matched_items": "{count, plural, one {Съвпадащ елемент (#)} other {Съвпадащи елементи (#)}}",
|
"repair_matched_items": "{count, plural, one {Съвпадащ елемент (#)} other {Съвпадащи елементи (#)}}",
|
||||||
"repaired_items": "{count, plural, one {Поправен елемент (#)} other {Поправени елементи (#)}}",
|
"repaired_items": "{count, plural, one {Поправен елемент (#)} other {Поправени елементи (#)}}",
|
||||||
@@ -211,12 +219,12 @@
|
|||||||
"reset_settings_to_default": "Възстановяване на настройките по подразбиране",
|
"reset_settings_to_default": "Възстановяване на настройките по подразбиране",
|
||||||
"reset_settings_to_recent_saved": "Възстановяване на настройките до последните запазени настройки",
|
"reset_settings_to_recent_saved": "Възстановяване на настройките до последните запазени настройки",
|
||||||
"scanning_library": "Сканиране на библиотеката",
|
"scanning_library": "Сканиране на библиотеката",
|
||||||
"scanning_library_for_changed_files": "Сканиране на библиотеката за променени файлове",
|
|
||||||
"scanning_library_for_new_files": "Сканиране на библиотеката за нови файлове",
|
|
||||||
"search_jobs": "Търсене на задачи...",
|
"search_jobs": "Търсене на задачи...",
|
||||||
"send_welcome_email": "Изпращане на имейл за добре дошли",
|
"send_welcome_email": "Изпращане на имейл за добре дошли",
|
||||||
"server_external_domain_settings": "Външен домейн",
|
"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": "Всички потребители (име и имейл) са изброени при добавяне на потребител в споделени албуми. Когато е деактивирано, списъкът с потребители ще бъде достъпен само за администраторите.",
|
||||||
"server_settings": "Настройки на сървъра",
|
"server_settings": "Настройки на сървъра",
|
||||||
"server_settings_description": "Управление на настройките на сървъра",
|
"server_settings_description": "Управление на настройките на сървъра",
|
||||||
"server_welcome_message": "Поздравително съобщение",
|
"server_welcome_message": "Поздравително съобщение",
|
||||||
@@ -241,6 +249,17 @@
|
|||||||
"storage_template_settings_description": "Управление на структурата на папките и името на файла за качване",
|
"storage_template_settings_description": "Управление на структурата на папките и името на файла за качване",
|
||||||
"storage_template_user_label": "<code>{label}</code> е етикетът за съхранение на потребителя",
|
"storage_template_user_label": "<code>{label}</code> е етикетът за съхранение на потребителя",
|
||||||
"system_settings": "Системни настройки",
|
"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": "Персонализиран CSS",
|
||||||
"theme_custom_css_settings_description": "Каскадните стилови таблици позволяват персонализиране на дизайна на Immich.",
|
"theme_custom_css_settings_description": "Каскадните стилови таблици позволяват персонализиране на дизайна на Immich.",
|
||||||
"theme_settings": "Настройки на темата",
|
"theme_settings": "Настройки на темата",
|
||||||
@@ -297,10 +316,8 @@
|
|||||||
"transcoding_temporal_aq_description": "Само за NVENC. Повишава качеството на сцени с висока детайлност и ниско ниво на движение. Може да не е съвместимо с по-стари устройства.",
|
"transcoding_temporal_aq_description": "Само за NVENC. Повишава качеството на сцени с висока детайлност и ниско ниво на движение. Може да не е съвместимо с по-стари устройства.",
|
||||||
"transcoding_threads": "Нишки",
|
"transcoding_threads": "Нишки",
|
||||||
"transcoding_threads_description": "По-високите стойности водят до по-бързо разкодиране, но оставят по-малко място за сървъра да обработва други задачи, докато е активен. Тази стойност не трябва да надвишава броя на процесорните ядра. Увеличава максимално използването, ако е зададено на 0.",
|
"transcoding_threads_description": "По-високите стойности водят до по-бързо разкодиране, но оставят по-малко място за сървъра да обработва други задачи, докато е активен. Тази стойност не трябва да надвишава броя на процесорните ядра. Увеличава максимално използването, ако е зададено на 0.",
|
||||||
"transcoding_tone_mapping": "",
|
"transcoding_tone_mapping": "Tone-mapping",
|
||||||
"transcoding_tone_mapping_description": "Опитва се да запази външния вид на HDR видеоклипове, когато се преобразува в SDR. Всеки алгоритъм прави различни компромиси за цвят, детайлност и яркост. Hable запазва детайлите, Mobius запазва цвета, а Reinhard запазва яркостта.",
|
"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": "Правила за транскодиране",
|
||||||
"transcoding_transcode_policy_description": "Правила за това кога видеоклипът трябва да бъде транскодиран. HDR видеоклиповете винаги ще бъдат транскодирани (освен ако транскодирането е деактивирано).",
|
"transcoding_transcode_policy_description": "Правила за това кога видеоклипът трябва да бъде транскодиран. HDR видеоклиповете винаги ще бъдат транскодирани (освен ако транскодирането е деактивирано).",
|
||||||
"transcoding_two_pass_encoding": "Кодиране с двойно минаване",
|
"transcoding_two_pass_encoding": "Кодиране с двойно минаване",
|
||||||
@@ -314,6 +331,7 @@
|
|||||||
"trash_settings_description": "Управление на настройките на кошчето",
|
"trash_settings_description": "Управление на настройките на кошчето",
|
||||||
"untracked_files": "Непроследени файлове",
|
"untracked_files": "Непроследени файлове",
|
||||||
"untracked_files_description": "Тези файлове не се проследяват от приложението. Те могат да бъдат резултат от неуспешни премествания, прекъснати качвания или оставени поради грешка",
|
"untracked_files_description": "Тези файлове не се проследяват от приложението. Те могат да бъдат резултат от неуспешни премествания, прекъснати качвания или оставени поради грешка",
|
||||||
|
"user_cleanup_job": "Почистване на потребители",
|
||||||
"user_delete_delay": "<b>{user}</b> aкаунтът и файловете на потребителя ще бъдат планирани за постоянно изтриване след {delay, plural, one {# ден} other {# дни}}.",
|
"user_delete_delay": "<b>{user}</b> aкаунтът и файловете на потребителя ще бъдат планирани за постоянно изтриване след {delay, plural, one {# ден} other {# дни}}.",
|
||||||
"user_delete_delay_settings": "Забавяне на изтриване",
|
"user_delete_delay_settings": "Забавяне на изтриване",
|
||||||
"user_delete_delay_settings_description": "Брой дни след окончателно изтриване акаунта на потребителя. Задачата за изтриване на потребител се изпълнява в полунощ, за да се провери за потребители, които са готови за изтриване. Промените на тази настройка ще влязат в сила при следващото изпълнение.",
|
"user_delete_delay_settings_description": "Брой дни след окончателно изтриване акаунта на потребителя. Задачата за изтриване на потребител се изпълнява в полунощ, за да се провери за потребители, които са готови за изтриване. Промените на тази настройка ще влязат в сила при следващото изпълнение.",
|
||||||
@@ -338,6 +356,9 @@
|
|||||||
"admin_password": "Администраторска парола",
|
"admin_password": "Администраторска парола",
|
||||||
"administration": "Администрация",
|
"administration": "Администрация",
|
||||||
"advanced": "Разширено",
|
"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": "Албумът е добавен",
|
||||||
"album_added_notification_setting_description": "Получавайте известие по имейл, когато бъдете добавени към споделен албум",
|
"album_added_notification_setting_description": "Получавайте известие по имейл, когато бъдете добавени към споделен албум",
|
||||||
"album_cover_updated": "Обложката на албума е актуализирана",
|
"album_cover_updated": "Обложката на албума е актуализирана",
|
||||||
@@ -357,7 +378,7 @@
|
|||||||
"album_user_removed": "Премахнат {user}",
|
"album_user_removed": "Премахнат {user}",
|
||||||
"album_with_link_access": "Нека всеки с линк вижда снимки и хора в този албум.",
|
"album_with_link_access": "Нека всеки с линк вижда снимки и хора в този албум.",
|
||||||
"albums": "Албуми",
|
"albums": "Албуми",
|
||||||
"albums_count": "",
|
"albums_count": "{count, plural, one {{count, number} Album} other {{count, number} Albums}}",
|
||||||
"all": "Всички",
|
"all": "Всички",
|
||||||
"all_albums": "Всички албуми",
|
"all_albums": "Всички албуми",
|
||||||
"all_people": "Всички хора",
|
"all_people": "Всички хора",
|
||||||
@@ -366,24 +387,44 @@
|
|||||||
"allow_edits": "Позволяване на редакции",
|
"allow_edits": "Позволяване на редакции",
|
||||||
"allow_public_user_to_download": "Позволете на публичен потребител да може да изтегля",
|
"allow_public_user_to_download": "Позволете на публичен потребител да може да изтегля",
|
||||||
"allow_public_user_to_upload": "Позволете на публичния потребител да може да качва",
|
"allow_public_user_to_upload": "Позволете на публичния потребител да може да качва",
|
||||||
|
"anti_clockwise": "Обратно на часовниковата стрелка",
|
||||||
"api_key": "API ключ",
|
"api_key": "API ключ",
|
||||||
"api_key_description": "Тази стойност ще бъде показана само веднъж. Моля, не забравяйте да го копирате, преди да затворите прозореца.",
|
"api_key_description": "Тази стойност ще бъде показана само веднъж. Моля, не забравяйте да го копирате, преди да затворите прозореца.",
|
||||||
"api_key_empty": "Името на вашия API ключ не трябва да е празно",
|
"api_key_empty": "Името на вашия API ключ не трябва да е празно",
|
||||||
"api_keys": "API ключове",
|
"api_keys": "API ключове",
|
||||||
"app_settings": "Настройки ма приложението",
|
"app_settings": "Настройки ма приложението",
|
||||||
"appears_in": "",
|
"appears_in": "Излиза в",
|
||||||
"archive": "Архив",
|
"archive": "Архив",
|
||||||
"archive_or_unarchive_photo": "Архивиране или деархивиране на снимка",
|
"archive_or_unarchive_photo": "Архивиране или деархивиране на снимка",
|
||||||
"archive_size": "Размер на архива",
|
"archive_size": "Размер на архива",
|
||||||
"archive_size_description": "Конфигурирайте размера на архива за изтегляния (в GiB)",
|
"archive_size_description": "Конфигурирайте размера на архива за изтегляния (в GiB)",
|
||||||
"archived": "",
|
"archived_count": "{count, plural, other {Archived #}}",
|
||||||
"are_these_the_same_person": "Това едно и също лице ли е?",
|
"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": "Ресурсът е офлайн",
|
||||||
|
"asset_offline_description": "Този външен актив вече не се намира на диска. Моля, свържете се с администратора на Immich за помощ.",
|
||||||
"asset_skipped": "Пропуснато",
|
"asset_skipped": "Пропуснато",
|
||||||
|
"asset_skipped_in_trash": "В кошчето",
|
||||||
"asset_uploaded": "Качено",
|
"asset_uploaded": "Качено",
|
||||||
"asset_uploading": "Качване...",
|
"asset_uploading": "Качване...",
|
||||||
"assets": "Ресурси",
|
"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 {<b>{name}</b>} 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": "Удостоверени устройства",
|
"authorized_devices": "Удостоверени устройства",
|
||||||
"back": "Назад",
|
"back": "Назад",
|
||||||
"back_close_deselect": "Назад, затваряне или премахване на избора",
|
"back_close_deselect": "Назад, затваряне или премахване на избора",
|
||||||
@@ -391,9 +432,12 @@
|
|||||||
"birthdate_saved": "Датата на раждане е запазена успешно",
|
"birthdate_saved": "Датата на раждане е запазена успешно",
|
||||||
"birthdate_set_description": "Датата на раждане се използва за изчисляване на възрастта на този човек към момента на снимката.",
|
"birthdate_set_description": "Датата на раждане се използва за изчисляване на възрастта на този човек към момента на снимката.",
|
||||||
"blurred_background": "Замъглен заден фон",
|
"blurred_background": "Замъглен заден фон",
|
||||||
"bulk_delete_duplicates_confirmation": "",
|
"bugs_and_feature_requests": "Бъгове и заявки за функции",
|
||||||
"bulk_keep_duplicates_confirmation": "",
|
"build": "Build",
|
||||||
"bulk_trash_duplicates_confirmation": "",
|
"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",
|
"buy": "Купете Immich",
|
||||||
"camera": "Камера",
|
"camera": "Камера",
|
||||||
"camera_brand": "Марка на камерата",
|
"camera_brand": "Марка на камерата",
|
||||||
@@ -403,10 +447,6 @@
|
|||||||
"cannot_merge_people": "Не може да обединява хора",
|
"cannot_merge_people": "Не може да обединява хора",
|
||||||
"cannot_undo_this_action": "Не можете да отмените това действие!",
|
"cannot_undo_this_action": "Не можете да отмените това действие!",
|
||||||
"cannot_update_the_description": "Описанието не може да бъде актуализирано",
|
"cannot_update_the_description": "Описанието не може да бъде актуализирано",
|
||||||
"cant_apply_changes": "",
|
|
||||||
"cant_get_faces": "",
|
|
||||||
"cant_search_people": "",
|
|
||||||
"cant_search_places": "",
|
|
||||||
"change_date": "Промени датата",
|
"change_date": "Промени датата",
|
||||||
"change_expiration_time": "Променете времето на изтичане",
|
"change_expiration_time": "Променете времето на изтичане",
|
||||||
"change_location": "Промени локацията",
|
"change_location": "Промени локацията",
|
||||||
@@ -425,9 +465,11 @@
|
|||||||
"clear_all_recent_searches": "Изчистете всички скорошни търсения",
|
"clear_all_recent_searches": "Изчистете всички скорошни търсения",
|
||||||
"clear_message": "Изчисти съобщението",
|
"clear_message": "Изчисти съобщението",
|
||||||
"clear_value": "Изчисти стойността",
|
"clear_value": "Изчисти стойността",
|
||||||
|
"clockwise": "По часовниковата стрелка",
|
||||||
"close": "Затвори",
|
"close": "Затвори",
|
||||||
"collapse": "Свиване",
|
"collapse": "Свиване",
|
||||||
"collapse_all": "Свиване на всичко",
|
"collapse_all": "Свиване на всичко",
|
||||||
|
"color": "Цвят",
|
||||||
"color_theme": "Цветова тема",
|
"color_theme": "Цветова тема",
|
||||||
"comment_deleted": "Коментарът е изтрит",
|
"comment_deleted": "Коментарът е изтрит",
|
||||||
"comment_options": "Опции за коментар",
|
"comment_options": "Опции за коментар",
|
||||||
@@ -436,8 +478,9 @@
|
|||||||
"confirm": "Потвърди",
|
"confirm": "Потвърди",
|
||||||
"confirm_admin_password": "Потвърждаване на паролата на администратора",
|
"confirm_admin_password": "Потвърждаване на паролата на администратора",
|
||||||
"confirm_delete_shared_link": "Сигурни ли сте, че искате да изтриете тази споделена връзка?",
|
"confirm_delete_shared_link": "Сигурни ли сте, че искате да изтриете тази споделена връзка?",
|
||||||
|
"confirm_keep_this_delete_others": "Всички останали файлове в стека ще бъдат изтрити, с изключение на този файл. Сигурни ли сте, че искате да продължите?",
|
||||||
"confirm_password": "Потвърдете паролата",
|
"confirm_password": "Потвърдете паролата",
|
||||||
"contain": "",
|
"contain": "В рамките на",
|
||||||
"context": "Контекст",
|
"context": "Контекст",
|
||||||
"continue": "Продължи",
|
"continue": "Продължи",
|
||||||
"copied_image_to_clipboard": "Изображението е копирано в клипборда.",
|
"copied_image_to_clipboard": "Изображението е копирано в клипборда.",
|
||||||
@@ -450,7 +493,7 @@
|
|||||||
"copy_password": "Копиране на парола",
|
"copy_password": "Копиране на парола",
|
||||||
"copy_to_clipboard": "Копиране в клипборда",
|
"copy_to_clipboard": "Копиране в клипборда",
|
||||||
"country": "Държава",
|
"country": "Държава",
|
||||||
"cover": "",
|
"cover": "Cover",
|
||||||
"covers": "Обложка",
|
"covers": "Обложка",
|
||||||
"create": "Създай",
|
"create": "Създай",
|
||||||
"create_album": "Създай албум",
|
"create_album": "Създай албум",
|
||||||
@@ -459,7 +502,10 @@
|
|||||||
"create_link_to_share": "Създаване на линк за споделяне",
|
"create_link_to_share": "Създаване на линк за споделяне",
|
||||||
"create_link_to_share_description": "Позволете на всеки, който има линк, да види избраната(ите) снимка(и)",
|
"create_link_to_share_description": "Позволете на всеки, който има линк, да види избраната(ите) снимка(и)",
|
||||||
"create_new_person": "Създаване на ново лице",
|
"create_new_person": "Създаване на ново лице",
|
||||||
|
"create_new_person_hint": "Присвойте избраните файлове на нов човек",
|
||||||
"create_new_user": "Създаване на нов потребител",
|
"create_new_user": "Създаване на нов потребител",
|
||||||
|
"create_tag": "Създай таг",
|
||||||
|
"create_tag_description": "Създайте нов таг. За вложени тагове, моля, въведете пълния път на тага, включително наклонените черти.",
|
||||||
"create_user": "Създай потребител",
|
"create_user": "Създай потребител",
|
||||||
"created": "Създадено",
|
"created": "Създадено",
|
||||||
"current_device": "Текущо устройство",
|
"current_device": "Текущо устройство",
|
||||||
@@ -473,7 +519,7 @@
|
|||||||
"date_range": "Период от време",
|
"date_range": "Период от време",
|
||||||
"day": "Ден",
|
"day": "Ден",
|
||||||
"deduplicate_all": "Дедупликиране на всички",
|
"deduplicate_all": "Дедупликиране на всички",
|
||||||
"default_locale": "",
|
"default_locale": "Локализация по подразбиране",
|
||||||
"default_locale_description": "Форматиране на дати и числа в зависимост от местоположението на браузъра",
|
"default_locale_description": "Форматиране на дати и числа в зависимост от местоположението на браузъра",
|
||||||
"delete": "Изтрий",
|
"delete": "Изтрий",
|
||||||
"delete_album": "Изтрий албум",
|
"delete_album": "Изтрий албум",
|
||||||
@@ -482,14 +528,19 @@
|
|||||||
"delete_key": "Изтрий ключ",
|
"delete_key": "Изтрий ключ",
|
||||||
"delete_library": "Изтрий библиотека",
|
"delete_library": "Изтрий библиотека",
|
||||||
"delete_link": "Изтрий линк",
|
"delete_link": "Изтрий линк",
|
||||||
|
"delete_others": "Изтрий останалите",
|
||||||
"delete_shared_link": "Изтриване на споделен линк",
|
"delete_shared_link": "Изтриване на споделен линк",
|
||||||
|
"delete_tag": "Изтрий таг",
|
||||||
|
"delete_tag_confirmation_prompt": "Сигурни ли сте, че искате да изтриете таг {tagName}?",
|
||||||
"delete_user": "Изтрий потребител",
|
"delete_user": "Изтрий потребител",
|
||||||
"deleted_shared_link": "Изтрит споделен линк",
|
"deleted_shared_link": "Изтрит споделен линк",
|
||||||
|
"deletes_missing_assets": "Изтрива файлове, които липсват на диска",
|
||||||
"description": "Описание",
|
"description": "Описание",
|
||||||
"details": "Детайли",
|
"details": "Детайли",
|
||||||
"direction": "Посока",
|
"direction": "Посока",
|
||||||
"disabled": "Изключено",
|
"disabled": "Изключено",
|
||||||
"disallow_edits": "Забраняване на редакциите",
|
"disallow_edits": "Забраняване на редакциите",
|
||||||
|
"discord": "Discord",
|
||||||
"discover": "Открий",
|
"discover": "Открий",
|
||||||
"dismiss_all_errors": "Отхвърляне на всички грешки",
|
"dismiss_all_errors": "Отхвърляне на всички грешки",
|
||||||
"dismiss_error": "Отхвърляне на грешка",
|
"dismiss_error": "Отхвърляне на грешка",
|
||||||
@@ -498,15 +549,18 @@
|
|||||||
"display_original_photos": "Показване на оригинални снимки",
|
"display_original_photos": "Показване на оригинални снимки",
|
||||||
"display_original_photos_setting_description": "Показване на оригиналната снимка вместо миниатюри, когато оригиналният актив е съвместим с мрежата. Това може да доведе до по-бавни скорости на показване на снимки.",
|
"display_original_photos_setting_description": "Показване на оригиналната снимка вместо миниатюри, когато оригиналният актив е съвместим с мрежата. Това може да доведе до по-бавни скорости на показване на снимки.",
|
||||||
"do_not_show_again": "Не показвайте това съобщение отново",
|
"do_not_show_again": "Не показвайте това съобщение отново",
|
||||||
|
"documentation": "Документация",
|
||||||
"done": "Готово",
|
"done": "Готово",
|
||||||
"download": "Изтегли",
|
"download": "Изтегли",
|
||||||
|
"download_include_embedded_motion_videos": "Вградени видеа",
|
||||||
|
"download_include_embedded_motion_videos_description": "Включете видеата, вградени в динамични снимки, като отделен файл",
|
||||||
"download_settings": "Изтегли",
|
"download_settings": "Изтегли",
|
||||||
"download_settings_description": "Управление на настройките, свързани с изтеглянето на файлове",
|
"download_settings_description": "Управление на настройките, свързани с изтеглянето на файлове",
|
||||||
"downloading": "Изтегляне",
|
"downloading": "Изтегляне",
|
||||||
"downloading_asset_filename": "Изтегляне на файл {filename}",
|
"downloading_asset_filename": "Изтегляне на файл {filename}",
|
||||||
"drop_files_to_upload": "Пуснете файловете, за да ги качите",
|
"drop_files_to_upload": "Пуснете файловете, за да ги качите",
|
||||||
"duplicates": "Дубликати",
|
"duplicates": "Дубликати",
|
||||||
"duplicates_description": "",
|
"duplicates_description": "Изберете всяка група, като посочите кои, ако има такива, са дубликати",
|
||||||
"duration": "Продължителност",
|
"duration": "Продължителност",
|
||||||
"edit": "Редактиране",
|
"edit": "Редактиране",
|
||||||
"edit_album": "Редактиране на албум",
|
"edit_album": "Редактиране на албум",
|
||||||
@@ -522,10 +576,15 @@
|
|||||||
"edit_location": "Редактиране на местоположението",
|
"edit_location": "Редактиране на местоположението",
|
||||||
"edit_name": "Редактиране на име",
|
"edit_name": "Редактиране на име",
|
||||||
"edit_people": "Редактиране на хора",
|
"edit_people": "Редактиране на хора",
|
||||||
|
"edit_tag": "Редактирай таг",
|
||||||
"edit_title": "Редактиране на заглавието",
|
"edit_title": "Редактиране на заглавието",
|
||||||
"edit_user": "Редактиране на потребител",
|
"edit_user": "Редактиране на потребител",
|
||||||
"edited": "Редактирано",
|
"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": "Имейл",
|
"email": "Имейл",
|
||||||
"empty_trash": "Изпразване на кош",
|
"empty_trash": "Изпразване на кош",
|
||||||
"empty_trash_confirmation": "Сигурни ли сте, че искате да изпразните кошчето? Това ще премахне всичко в кошчето за постоянно от Immich.\nНе можете да отмените това действие!",
|
"empty_trash_confirmation": "Сигурни ли сте, че искате да изпразните кошчето? Това ще премахне всичко в кошчето за постоянно от Immich.\nНе можете да отмените това действие!",
|
||||||
@@ -539,7 +598,9 @@
|
|||||||
"cannot_navigate_next_asset": "Не можете да преминете към следващия файл",
|
"cannot_navigate_next_asset": "Не можете да преминете към следващия файл",
|
||||||
"cannot_navigate_previous_asset": "Не можете да преминете към предишния актив",
|
"cannot_navigate_previous_asset": "Не можете да преминете към предишния актив",
|
||||||
"cant_apply_changes": "Не могат да се приложат промение",
|
"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_faces": "Не мога да намеря лица",
|
||||||
"cant_get_number_of_comments": "Не може да получи броя на коментарите",
|
"cant_get_number_of_comments": "Не може да получи броя на коментарите",
|
||||||
"cant_search_people": "Не може да търси хора",
|
"cant_search_people": "Не може да търси хора",
|
||||||
@@ -558,19 +619,28 @@
|
|||||||
"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_load_asset": "Неуспешно зареждане на файл",
|
"failed_to_load_asset": "Неуспешно зареждане на файл",
|
||||||
"failed_to_load_assets": "Неуспешно зареждане на файлове",
|
"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": "Неправилен имейл или парола",
|
"incorrect_email_or_password": "Неправилен имейл или парола",
|
||||||
"paths_validation_failed": "",
|
"paths_validation_failed": "{paths, plural, one {# път} other {# пътища}} не преминаха валидация",
|
||||||
"profile_picture_transparent_pixels": "Профилните снимки не могат да имат прозрачни пиксели. Моля, увеличете и/или преместете изображението.",
|
"profile_picture_transparent_pixels": "Профилните снимки не могат да имат прозрачни пиксели. Моля, увеличете и/или преместете изображението.",
|
||||||
"quota_higher_than_disk_size": "Зададена е квота, по-голяма от размера на диска",
|
"quota_higher_than_disk_size": "Зададена е квота, по-голяма от размера на диска",
|
||||||
"repair_unable_to_check_items": "",
|
"repair_unable_to_check_items": "Неуспешно проверяване на {count, select, one {обект} other {обекти}}",
|
||||||
"unable_to_add_album_users": "",
|
"unable_to_add_album_users": "Неуспешно добавяне на потребители в албум",
|
||||||
"unable_to_add_comment": "",
|
"unable_to_add_assets_to_shared_link": "Неуспешно добавяне на обекти в споделен линк",
|
||||||
"unable_to_add_exclusion_pattern": "",
|
"unable_to_add_comment": "Неуспешно добавяне на коментар",
|
||||||
"unable_to_add_import_path": "",
|
"unable_to_add_exclusion_pattern": "Неуспешно добавяне на шаблон за изключение",
|
||||||
"unable_to_add_partners": "",
|
"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_album_user_role": "Не може да се промени ролята на потребителя на албума",
|
||||||
"unable_to_change_date": "Не може да се промени датата",
|
"unable_to_change_date": "Не може да се промени датата",
|
||||||
"unable_to_change_favorite": "Не може да промени фаворит за актив",
|
"unable_to_change_favorite": "Не може да промени фаворит за актив",
|
||||||
@@ -601,11 +671,12 @@
|
|||||||
"unable_to_get_comments_number": "Не може да получи брой коментари",
|
"unable_to_get_comments_number": "Не може да получи брой коментари",
|
||||||
"unable_to_get_shared_link": "Неуспешно създаване на споделена връзка",
|
"unable_to_get_shared_link": "Неуспешно създаване на споделена връзка",
|
||||||
"unable_to_hide_person": "Не може да скрие човек",
|
"unable_to_hide_person": "Не може да скрие човек",
|
||||||
"unable_to_link_oauth_account": "",
|
"unable_to_link_motion_video": "Неуспешно свързване на видео с движение",
|
||||||
"unable_to_load_album": "",
|
"unable_to_link_oauth_account": "Неуспешно свързване на OAuth акаунт",
|
||||||
"unable_to_load_asset_activity": "",
|
"unable_to_load_album": "Неуспешно зареждане на албум",
|
||||||
"unable_to_load_items": "",
|
"unable_to_load_asset_activity": "Неуспешно зареждане на активност на обект",
|
||||||
"unable_to_load_liked_status": "",
|
"unable_to_load_items": "Неуспешно зареждане на обекти",
|
||||||
|
"unable_to_load_liked_status": "Неуспешно зареждане на статус на харесване",
|
||||||
"unable_to_play_video": "",
|
"unable_to_play_video": "",
|
||||||
"unable_to_refresh_user": "",
|
"unable_to_refresh_user": "",
|
||||||
"unable_to_remove_album_users": "",
|
"unable_to_remove_album_users": "",
|
||||||
@@ -650,7 +721,6 @@
|
|||||||
"external": "Външно",
|
"external": "Външно",
|
||||||
"external_libraries": "Външни библиотеки",
|
"external_libraries": "Външни библиотеки",
|
||||||
"face_unassigned": "Незададено",
|
"face_unassigned": "Незададено",
|
||||||
"failed_to_get_people": "",
|
|
||||||
"favorite": "Любим",
|
"favorite": "Любим",
|
||||||
"favorite_or_unfavorite_photo": "",
|
"favorite_or_unfavorite_photo": "",
|
||||||
"favorites": "Любими",
|
"favorites": "Любими",
|
||||||
@@ -662,14 +732,12 @@
|
|||||||
"filter_people": "Филтриране на хора",
|
"filter_people": "Филтриране на хора",
|
||||||
"find_them_fast": "Намерете ги бързо по име с търсене",
|
"find_them_fast": "Намерете ги бързо по име с търсене",
|
||||||
"fix_incorrect_match": "Поправяне на неправилно съвпадение",
|
"fix_incorrect_match": "Поправяне на неправилно съвпадение",
|
||||||
"force_re-scan_library_files": "Принудително повторно сканиране на всички библиотечни файлове",
|
|
||||||
"forward": "Напред",
|
"forward": "Напред",
|
||||||
"general": "Общи",
|
"general": "Общи",
|
||||||
"get_help": "Помощ",
|
"get_help": "Помощ",
|
||||||
"getting_started": "",
|
"getting_started": "",
|
||||||
"go_back": "Връщане назад",
|
"go_back": "Връщане назад",
|
||||||
"go_to_search": "Преминаване към търсене",
|
"go_to_search": "Преминаване към търсене",
|
||||||
"go_to_share_page": "",
|
|
||||||
"group_albums_by": "Групирай албум по...",
|
"group_albums_by": "Групирай албум по...",
|
||||||
"group_owner": "Групиране по собственик",
|
"group_owner": "Групиране по собственик",
|
||||||
"group_year": "Групиране по година",
|
"group_year": "Групиране по година",
|
||||||
@@ -685,7 +753,6 @@
|
|||||||
"hour": "Час",
|
"hour": "Час",
|
||||||
"image": "Изображение",
|
"image": "Изображение",
|
||||||
"image_alt_text_date": "на {date}",
|
"image_alt_text_date": "на {date}",
|
||||||
"image_alt_text_place": "в {city}, {country}",
|
|
||||||
"immich_logo": "Immich лого",
|
"immich_logo": "Immich лого",
|
||||||
"immich_web_interface": "",
|
"immich_web_interface": "",
|
||||||
"import_from_json": "Импортиране от JSON",
|
"import_from_json": "Импортиране от JSON",
|
||||||
@@ -718,29 +785,6 @@
|
|||||||
"level": "Ниво",
|
"level": "Ниво",
|
||||||
"library": "Библиотека",
|
"library": "Библиотека",
|
||||||
"library_options": "Опции на библиотеката",
|
"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": "Светло",
|
"light": "Светло",
|
||||||
"link_options": "Опции на линк за споделяне",
|
"link_options": "Опции на линк за споделяне",
|
||||||
"link_to_oauth": "",
|
"link_to_oauth": "",
|
||||||
@@ -832,7 +876,6 @@
|
|||||||
"onboarding_welcome_user": "Добре дошъл, {user}",
|
"onboarding_welcome_user": "Добре дошъл, {user}",
|
||||||
"online": "Онлайн",
|
"online": "Онлайн",
|
||||||
"only_favorites": "Само любими",
|
"only_favorites": "Само любими",
|
||||||
"only_refreshes_modified_files": "Опреснява само модифицирани файлове",
|
|
||||||
"open_the_search_filters": "Отваряне на филтрите за търсене",
|
"open_the_search_filters": "Отваряне на филтрите за търсене",
|
||||||
"options": "Настройки",
|
"options": "Настройки",
|
||||||
"or": "или",
|
"or": "или",
|
||||||
@@ -870,7 +913,6 @@
|
|||||||
"permanent_deletion_warning_setting_description": "Показване на предупреждение при трайно изтриване на активи",
|
"permanent_deletion_warning_setting_description": "Показване на предупреждение при трайно изтриване на активи",
|
||||||
"permanently_delete": "Трайно изтриване",
|
"permanently_delete": "Трайно изтриване",
|
||||||
"permanently_deleted_asset": "",
|
"permanently_deleted_asset": "",
|
||||||
"permanently_deleted_assets": "",
|
|
||||||
"person": "Човек",
|
"person": "Човек",
|
||||||
"photos": "Снимки",
|
"photos": "Снимки",
|
||||||
"photos_count": "",
|
"photos_count": "",
|
||||||
@@ -931,8 +973,6 @@
|
|||||||
"saved_settings": "",
|
"saved_settings": "",
|
||||||
"say_something": "",
|
"say_something": "",
|
||||||
"scan_all_libraries": "",
|
"scan_all_libraries": "",
|
||||||
"scan_all_library_files": "",
|
|
||||||
"scan_new_library_files": "",
|
|
||||||
"scan_settings": "",
|
"scan_settings": "",
|
||||||
"scanning_for_album": "",
|
"scanning_for_album": "",
|
||||||
"search": "Търсене",
|
"search": "Търсене",
|
||||||
@@ -967,7 +1007,6 @@
|
|||||||
"selected": "Избрано",
|
"selected": "Избрано",
|
||||||
"send_message": "Изпратете съобщение",
|
"send_message": "Изпратете съобщение",
|
||||||
"send_welcome_email": "Изпратете имейл за добре дошли",
|
"send_welcome_email": "Изпратете имейл за добре дошли",
|
||||||
"server": "Сървър",
|
|
||||||
"server_offline": "Сървър офлайн",
|
"server_offline": "Сървър офлайн",
|
||||||
"server_online": "Сървър онлайн",
|
"server_online": "Сървър онлайн",
|
||||||
"server_stats": "Статус на сървъра",
|
"server_stats": "Статус на сървъра",
|
||||||
@@ -1070,7 +1109,6 @@
|
|||||||
"to_trash": "Кошче",
|
"to_trash": "Кошче",
|
||||||
"toggle_settings": "Превключване на настройките",
|
"toggle_settings": "Превключване на настройките",
|
||||||
"toggle_theme": "Превключване на тема",
|
"toggle_theme": "Превключване на тема",
|
||||||
"toggle_visibility": "",
|
|
||||||
"total_usage": "Общо използвано",
|
"total_usage": "Общо използвано",
|
||||||
"trash": "кошче",
|
"trash": "кошче",
|
||||||
"trash_all": "Изхвърли всички",
|
"trash_all": "Изхвърли всички",
|
||||||
@@ -1079,7 +1117,6 @@
|
|||||||
"trashed_items_will_be_permanently_deleted_after": "Изхвърлените в кошчето елементи ще бъдат изтрити за постоянно след {days, plural, one {# day} other {# days}}.",
|
"trashed_items_will_be_permanently_deleted_after": "Изхвърлените в кошчето елементи ще бъдат изтрити за постоянно след {days, plural, one {# day} other {# days}}.",
|
||||||
"type": "Тип",
|
"type": "Тип",
|
||||||
"unarchive": "Разархивирай",
|
"unarchive": "Разархивирай",
|
||||||
"unarchived": "",
|
|
||||||
"unfavorite": "Премахване от любимите",
|
"unfavorite": "Премахване от любимите",
|
||||||
"unhide_person": "",
|
"unhide_person": "",
|
||||||
"unknown": "Неизвестно",
|
"unknown": "Неизвестно",
|
||||||
@@ -1113,6 +1150,8 @@
|
|||||||
"user_purchase_settings_description": "Управлявай покупката си",
|
"user_purchase_settings_description": "Управлявай покупката си",
|
||||||
"user_role_set": "Задай {user} като {role}",
|
"user_role_set": "Задай {user} като {role}",
|
||||||
"user_usage_detail": "Подробности за използването на потребителя",
|
"user_usage_detail": "Подробности за използването на потребителя",
|
||||||
|
"user_usage_stats": "Статистика за използването на акаунта",
|
||||||
|
"user_usage_stats_description": "Преглед на статистиката за използването на акаунта",
|
||||||
"username": "Потребителско име",
|
"username": "Потребителско име",
|
||||||
"users": "Потребители",
|
"users": "Потребители",
|
||||||
"utilities": "Инструменти",
|
"utilities": "Инструменти",
|
||||||
@@ -1135,13 +1174,12 @@
|
|||||||
"view_next_asset": "Преглед на следващия файл",
|
"view_next_asset": "Преглед на следващия файл",
|
||||||
"view_previous_asset": "Преглед на предишния файл",
|
"view_previous_asset": "Преглед на предишния файл",
|
||||||
"view_stack": "Покажи в стек",
|
"view_stack": "Покажи в стек",
|
||||||
"viewer": "",
|
|
||||||
"visibility_changed": "Видимостта е променена за {count, plural, one {# person} other {# people}}",
|
"visibility_changed": "Видимостта е променена за {count, plural, one {# person} other {# people}}",
|
||||||
"waiting": "в изчакване",
|
"waiting": "в изчакване",
|
||||||
"warning": "Внимание",
|
"warning": "Внимание",
|
||||||
"week": "Седмица",
|
"week": "Седмица",
|
||||||
"welcome": "Добре дошли",
|
"welcome": "Добре дошли",
|
||||||
"welcome_to_immich": "Добре дошли в immich",
|
"welcome_to_immich": "Добре дошли в Immich",
|
||||||
"year": "Година",
|
"year": "Година",
|
||||||
"yes": "Да",
|
"yes": "Да",
|
||||||
"you_dont_have_any_shared_links": "Нямате споделени връзки",
|
"you_dont_have_any_shared_links": "Нямате споделени връзки",
|
||||||
|
|||||||
39
i18n/bi.json
@@ -33,7 +33,6 @@
|
|||||||
"confirm_email_below": "",
|
"confirm_email_below": "",
|
||||||
"confirm_reprocess_all_faces": "",
|
"confirm_reprocess_all_faces": "",
|
||||||
"confirm_user_password_reset": "",
|
"confirm_user_password_reset": "",
|
||||||
"crontab_guru": "",
|
|
||||||
"disable_login": "",
|
"disable_login": "",
|
||||||
"duplicate_detection_job_description": "",
|
"duplicate_detection_job_description": "",
|
||||||
"exclusion_pattern_description": "",
|
"exclusion_pattern_description": "",
|
||||||
@@ -49,16 +48,9 @@
|
|||||||
"image_prefer_embedded_preview_setting_description": "",
|
"image_prefer_embedded_preview_setting_description": "",
|
||||||
"image_prefer_wide_gamut": "",
|
"image_prefer_wide_gamut": "",
|
||||||
"image_prefer_wide_gamut_setting_description": "",
|
"image_prefer_wide_gamut_setting_description": "",
|
||||||
"image_preview_format": "",
|
|
||||||
"image_preview_resolution": "",
|
|
||||||
"image_preview_resolution_description": "",
|
|
||||||
"image_quality": "",
|
"image_quality": "",
|
||||||
"image_quality_description": "",
|
|
||||||
"image_settings": "",
|
"image_settings": "",
|
||||||
"image_settings_description": "",
|
"image_settings_description": "",
|
||||||
"image_thumbnail_format": "",
|
|
||||||
"image_thumbnail_resolution": "",
|
|
||||||
"image_thumbnail_resolution_description": "",
|
|
||||||
"job_concurrency": "",
|
"job_concurrency": "",
|
||||||
"job_not_concurrency_safe": "",
|
"job_not_concurrency_safe": "",
|
||||||
"job_settings": "",
|
"job_settings": "",
|
||||||
@@ -67,8 +59,6 @@
|
|||||||
"jobs_delayed": "",
|
"jobs_delayed": "",
|
||||||
"jobs_failed": "",
|
"jobs_failed": "",
|
||||||
"library_created": "",
|
"library_created": "",
|
||||||
"library_cron_expression": "",
|
|
||||||
"library_cron_expression_presets": "",
|
|
||||||
"library_deleted": "",
|
"library_deleted": "",
|
||||||
"library_import_path_description": "",
|
"library_import_path_description": "",
|
||||||
"library_scanning": "",
|
"library_scanning": "",
|
||||||
@@ -172,15 +162,12 @@
|
|||||||
"paths_validated_successfully": "",
|
"paths_validated_successfully": "",
|
||||||
"quota_size_gib": "",
|
"quota_size_gib": "",
|
||||||
"refreshing_all_libraries": "",
|
"refreshing_all_libraries": "",
|
||||||
"removing_deleted_files": "",
|
|
||||||
"repair_all": "",
|
"repair_all": "",
|
||||||
"repair_matched_items": "",
|
"repair_matched_items": "",
|
||||||
"repaired_items": "",
|
"repaired_items": "",
|
||||||
"require_password_change_on_login": "",
|
"require_password_change_on_login": "",
|
||||||
"reset_settings_to_default": "",
|
"reset_settings_to_default": "",
|
||||||
"reset_settings_to_recent_saved": "",
|
"reset_settings_to_recent_saved": "",
|
||||||
"scanning_library_for_changed_files": "",
|
|
||||||
"scanning_library_for_new_files": "",
|
|
||||||
"send_welcome_email": "",
|
"send_welcome_email": "",
|
||||||
"server_external_domain_settings": "",
|
"server_external_domain_settings": "",
|
||||||
"server_external_domain_settings_description": "",
|
"server_external_domain_settings_description": "",
|
||||||
@@ -255,8 +242,6 @@
|
|||||||
"transcoding_threads_description": "",
|
"transcoding_threads_description": "",
|
||||||
"transcoding_tone_mapping": "",
|
"transcoding_tone_mapping": "",
|
||||||
"transcoding_tone_mapping_description": "",
|
"transcoding_tone_mapping_description": "",
|
||||||
"transcoding_tone_mapping_npl": "",
|
|
||||||
"transcoding_tone_mapping_npl_description": "",
|
|
||||||
"transcoding_transcode_policy": "",
|
"transcoding_transcode_policy": "",
|
||||||
"transcoding_transcode_policy_description": "",
|
"transcoding_transcode_policy_description": "",
|
||||||
"transcoding_two_pass_encoding": "",
|
"transcoding_two_pass_encoding": "",
|
||||||
@@ -308,7 +293,6 @@
|
|||||||
"appears_in": "",
|
"appears_in": "",
|
||||||
"archive": "",
|
"archive": "",
|
||||||
"archive_or_unarchive_photo": "",
|
"archive_or_unarchive_photo": "",
|
||||||
"archived": "",
|
|
||||||
"asset_offline": "",
|
"asset_offline": "",
|
||||||
"assets": "",
|
"assets": "",
|
||||||
"authorized_devices": "",
|
"authorized_devices": "",
|
||||||
@@ -322,10 +306,6 @@
|
|||||||
"cancel_search": "",
|
"cancel_search": "",
|
||||||
"cannot_merge_people": "",
|
"cannot_merge_people": "",
|
||||||
"cannot_update_the_description": "",
|
"cannot_update_the_description": "",
|
||||||
"cant_apply_changes": "",
|
|
||||||
"cant_get_faces": "",
|
|
||||||
"cant_search_people": "",
|
|
||||||
"cant_search_places": "",
|
|
||||||
"change_date": "",
|
"change_date": "",
|
||||||
"change_expiration_time": "",
|
"change_expiration_time": "",
|
||||||
"change_location": "",
|
"change_location": "",
|
||||||
@@ -411,13 +391,6 @@
|
|||||||
"download": "",
|
"download": "",
|
||||||
"downloading": "",
|
"downloading": "",
|
||||||
"duration": "",
|
"duration": "",
|
||||||
"durations": {
|
|
||||||
"days": "",
|
|
||||||
"hours": "",
|
|
||||||
"minutes": "",
|
|
||||||
"months": "",
|
|
||||||
"years": ""
|
|
||||||
},
|
|
||||||
"edit_album": "",
|
"edit_album": "",
|
||||||
"edit_avatar": "",
|
"edit_avatar": "",
|
||||||
"edit_date": "",
|
"edit_date": "",
|
||||||
@@ -436,7 +409,6 @@
|
|||||||
"edited": "",
|
"edited": "",
|
||||||
"editor": "",
|
"editor": "",
|
||||||
"email": "",
|
"email": "",
|
||||||
"empty_album": "",
|
|
||||||
"empty_trash": "",
|
"empty_trash": "",
|
||||||
"enable": "",
|
"enable": "",
|
||||||
"enabled": "",
|
"enabled": "",
|
||||||
@@ -522,7 +494,6 @@
|
|||||||
"extension": "",
|
"extension": "",
|
||||||
"external": "",
|
"external": "",
|
||||||
"external_libraries": "",
|
"external_libraries": "",
|
||||||
"failed_to_get_people": "",
|
|
||||||
"favorite": "",
|
"favorite": "",
|
||||||
"favorite_or_unfavorite_photo": "",
|
"favorite_or_unfavorite_photo": "",
|
||||||
"favorites": "",
|
"favorites": "",
|
||||||
@@ -534,14 +505,12 @@
|
|||||||
"filter_people": "",
|
"filter_people": "",
|
||||||
"find_them_fast": "",
|
"find_them_fast": "",
|
||||||
"fix_incorrect_match": "",
|
"fix_incorrect_match": "",
|
||||||
"force_re-scan_library_files": "",
|
|
||||||
"forward": "",
|
"forward": "",
|
||||||
"general": "",
|
"general": "",
|
||||||
"get_help": "",
|
"get_help": "",
|
||||||
"getting_started": "",
|
"getting_started": "",
|
||||||
"go_back": "",
|
"go_back": "",
|
||||||
"go_to_search": "",
|
"go_to_search": "",
|
||||||
"go_to_share_page": "",
|
|
||||||
"group_albums_by": "",
|
"group_albums_by": "",
|
||||||
"has_quota": "",
|
"has_quota": "",
|
||||||
"hide_gallery": "",
|
"hide_gallery": "",
|
||||||
@@ -656,7 +625,6 @@
|
|||||||
"oldest_first": "",
|
"oldest_first": "",
|
||||||
"online": "",
|
"online": "",
|
||||||
"only_favorites": "",
|
"only_favorites": "",
|
||||||
"only_refreshes_modified_files": "",
|
|
||||||
"open_the_search_filters": "",
|
"open_the_search_filters": "",
|
||||||
"options": "",
|
"options": "",
|
||||||
"organize_your_library": "",
|
"organize_your_library": "",
|
||||||
@@ -745,8 +713,6 @@
|
|||||||
"saved_settings": "",
|
"saved_settings": "",
|
||||||
"say_something": "",
|
"say_something": "",
|
||||||
"scan_all_libraries": "",
|
"scan_all_libraries": "",
|
||||||
"scan_all_library_files": "",
|
|
||||||
"scan_new_library_files": "",
|
|
||||||
"scan_settings": "",
|
"scan_settings": "",
|
||||||
"search": "",
|
"search": "",
|
||||||
"search_albums": "",
|
"search_albums": "",
|
||||||
@@ -777,7 +743,6 @@
|
|||||||
"selected": "",
|
"selected": "",
|
||||||
"send_message": "",
|
"send_message": "",
|
||||||
"send_welcome_email": "",
|
"send_welcome_email": "",
|
||||||
"server": "",
|
|
||||||
"server_stats": "",
|
"server_stats": "",
|
||||||
"set": "",
|
"set": "",
|
||||||
"set_as_album_cover": "",
|
"set_as_album_cover": "",
|
||||||
@@ -847,7 +812,6 @@
|
|||||||
"to_favorite": "",
|
"to_favorite": "",
|
||||||
"toggle_settings": "",
|
"toggle_settings": "",
|
||||||
"toggle_theme": "",
|
"toggle_theme": "",
|
||||||
"toggle_visibility": "",
|
|
||||||
"total_usage": "",
|
"total_usage": "",
|
||||||
"trash": "",
|
"trash": "",
|
||||||
"trash_all": "",
|
"trash_all": "",
|
||||||
@@ -855,11 +819,9 @@
|
|||||||
"trashed_items_will_be_permanently_deleted_after": "",
|
"trashed_items_will_be_permanently_deleted_after": "",
|
||||||
"type": "",
|
"type": "",
|
||||||
"unarchive": "",
|
"unarchive": "",
|
||||||
"unarchived": "",
|
|
||||||
"unfavorite": "",
|
"unfavorite": "",
|
||||||
"unhide_person": "",
|
"unhide_person": "",
|
||||||
"unknown": "",
|
"unknown": "",
|
||||||
"unknown_album": "",
|
|
||||||
"unknown_year": "",
|
"unknown_year": "",
|
||||||
"unlimited": "",
|
"unlimited": "",
|
||||||
"unlink_oauth": "",
|
"unlink_oauth": "",
|
||||||
@@ -893,7 +855,6 @@
|
|||||||
"view_links": "",
|
"view_links": "",
|
||||||
"view_next_asset": "",
|
"view_next_asset": "",
|
||||||
"view_previous_asset": "",
|
"view_previous_asset": "",
|
||||||
"viewer": "",
|
|
||||||
"waiting": "",
|
"waiting": "",
|
||||||
"week": "",
|
"week": "",
|
||||||
"welcome_to_immich": "",
|
"welcome_to_immich": "",
|
||||||
|
|||||||
1
i18n/bn.json
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{}
|
||||||
115
i18n/ca.json
@@ -1,8 +1,8 @@
|
|||||||
{
|
{
|
||||||
"about": "Quant a",
|
"about": "Sobre",
|
||||||
"account": "Compte",
|
"account": "Compte",
|
||||||
"account_settings": "Configuració del compte",
|
"account_settings": "Configuració del compte",
|
||||||
"acknowledge": "Reconeix",
|
"acknowledge": "Confirmar",
|
||||||
"action": "Acció",
|
"action": "Acció",
|
||||||
"actions": "Accions",
|
"actions": "Accions",
|
||||||
"active": "Actiu",
|
"active": "Actiu",
|
||||||
@@ -14,26 +14,32 @@
|
|||||||
"add_a_name": "Afegir un nom",
|
"add_a_name": "Afegir un nom",
|
||||||
"add_a_title": "Afegir un títol",
|
"add_a_title": "Afegir un títol",
|
||||||
"add_exclusion_pattern": "Afegir un patró d'exclusió",
|
"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_location": "Afegir la ubicació",
|
||||||
"add_more_users": "Afegir més usuaris",
|
"add_more_users": "Afegir més usuaris",
|
||||||
"add_partner": "Afegir company/a",
|
"add_partner": "Afegir company/a",
|
||||||
"add_path": "Afegir un camí",
|
"add_path": "Afegir una ruta",
|
||||||
"add_photos": "Afegir fotografies",
|
"add_photos": "Afegir fotografies",
|
||||||
"add_to": "Afegir a...",
|
"add_to": "Afegir a...",
|
||||||
"add_to_album": "Afegir a un l'àlbum",
|
"add_to_album": "Afegir a un l'àlbum",
|
||||||
"add_to_shared_album": "Afegir a un àlbum compartit",
|
"add_to_shared_album": "Afegir a un àlbum compartit",
|
||||||
|
"add_url": "Afegir URL",
|
||||||
"added_to_archive": "Afegit als arxivats",
|
"added_to_archive": "Afegit als arxivats",
|
||||||
"added_to_favorites": "Afegit als preferits",
|
"added_to_favorites": "Afegit als preferits",
|
||||||
"added_to_favorites_count": "{count, number} afegits als preferits",
|
"added_to_favorites_count": "{count, number} afegits als preferits",
|
||||||
"admin": {
|
"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.",
|
"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": "Configuració de l'autenticació",
|
||||||
"authentication_settings_description": "Gestiona la contrasenya, OAuth i altres configuracions 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_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 <link>Comanda de Servidor</link>.",
|
"authentication_settings_reenable": "Per a tornar a habilitar, empra una <link>Comanda de Servidor</link>.",
|
||||||
"background_task_job": "Tasques en segon pla",
|
"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",
|
"check_all": "Marca-ho tot",
|
||||||
"cleared_jobs": "Tasques esborrades per a: {job}",
|
"cleared_jobs": "Tasques esborrades per a: {job}",
|
||||||
"config_set_by_file": "La configuració està definida per un fitxer de configuració",
|
"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_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}?",
|
"confirm_user_password_reset": "Esteu segur que voleu reinicialitzar la contrasenya de l'usuari {user}?",
|
||||||
"create_job": "Crear tasca",
|
"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 <link>Crontab Guru</link>",
|
||||||
|
"cron_expression_presets": "Ajustos predefinits d'expressions Cron",
|
||||||
"disable_login": "Deshabiliteu l'inici de sessió",
|
"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",
|
"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.",
|
"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})",
|
"external_library_created_at": "Llibreria externa (creada el {date})",
|
||||||
@@ -63,22 +70,15 @@
|
|||||||
"image_prefer_wide_gamut": "Prefereix àmplia gamma",
|
"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_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_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_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_preview_title": "Paràmetres de previsualització",
|
||||||
"image_quality": "Qualitat",
|
"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": "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_resolution_description": "Les resolucions més altes poden conservar més detalls però triguen més a codificar-se, tenen mides de fitxer més grans i poden reduir la capacitat de resposta de l'aplicació.",
|
||||||
"image_settings": "Configuració d'imatges",
|
"image_settings": "Configuració d'imatges",
|
||||||
"image_settings_description": "Gestiona la qualitat i resolució de les imatges generades",
|
"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_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_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",
|
"image_thumbnail_title": "Configuració de miniatures",
|
||||||
"job_concurrency": "{job} concurrència",
|
"job_concurrency": "{job} concurrència",
|
||||||
"job_created": "Tasca creada",
|
"job_created": "Tasca creada",
|
||||||
@@ -89,9 +89,6 @@
|
|||||||
"jobs_delayed": "{jobCount, plural, other {# posposades}}",
|
"jobs_delayed": "{jobCount, plural, other {# posposades}}",
|
||||||
"jobs_failed": "{jobCount, plural, other {# fallides}}",
|
"jobs_failed": "{jobCount, plural, other {# fallides}}",
|
||||||
"library_created": "Bilbioteca creada: {library}",
|
"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, <link>Crontab Guru</link>",
|
|
||||||
"library_cron_expression_presets": "Expressions cron predeterminades",
|
|
||||||
"library_deleted": "Bilbioteca eliminada",
|
"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_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",
|
"library_scanning": "Escaneig periòdic",
|
||||||
@@ -158,7 +155,7 @@
|
|||||||
"metadata_settings_description": "Administrar la configuració de les metadades",
|
"metadata_settings_description": "Administrar la configuració de les metadades",
|
||||||
"migration_job": "Migració",
|
"migration_job": "Migració",
|
||||||
"migration_job_description": "Migra les miniatures d'elements i cares cap a la nova estructura de carpetes",
|
"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",
|
"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_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!",
|
"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_enable_description": "Inicia sessió amb correu electrònic i contrasenya",
|
||||||
"password_settings": "Inici de sessió amb contrasenya",
|
"password_settings": "Inici de sessió amb contrasenya",
|
||||||
"password_settings_description": "Gestiona la configuració de l'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",
|
"person_cleanup_job": "Neteja de persona",
|
||||||
"quota_size_gib": "Tamany de la quota (GiB)",
|
"quota_size_gib": "Tamany de la quota (GiB)",
|
||||||
"refreshing_all_libraries": "Actualitzant totes les biblioteques",
|
"refreshing_all_libraries": "Actualitzant totes les biblioteques",
|
||||||
"registration": "Registre d'administrador",
|
"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.",
|
"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_all": "Reparar tot",
|
||||||
"repair_matched_items": "Coincidència {count, plural, one {# element} other {# elements}}",
|
"repair_matched_items": "Coincidència {count, plural, one {# element} other {# elements}}",
|
||||||
"repaired_items": "Corregit {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_default": "Restablir configuracions per defecte",
|
||||||
"reset_settings_to_recent_saved": "Restablir la configuració guardada més recent",
|
"reset_settings_to_recent_saved": "Restablir la configuració guardada més recent",
|
||||||
"scanning_library": "Escanejant biblioteca",
|
"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...",
|
"search_jobs": "Tasques de cerca...",
|
||||||
"send_welcome_email": "Enviar correu electrònic de benvinguda",
|
"send_welcome_email": "Enviar correu electrònic de benvinguda",
|
||||||
"server_external_domain_settings": "Domini extern",
|
"server_external_domain_settings": "Domini extern",
|
||||||
@@ -261,7 +255,6 @@
|
|||||||
"these_files_matched_by_checksum": "Aquests fitxers coincideixen amb els seus checksums",
|
"these_files_matched_by_checksum": "Aquests fitxers coincideixen amb els seus checksums",
|
||||||
"thumbnail_generation_job": "Generar miniatures",
|
"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",
|
"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": "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_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)",
|
"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_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": "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_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": "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_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",
|
"transcoding_two_pass_encoding": "Codificació de dues passades",
|
||||||
@@ -395,7 +386,6 @@
|
|||||||
"archive_or_unarchive_photo": "Arxivar o desarxivar fotografia",
|
"archive_or_unarchive_photo": "Arxivar o desarxivar fotografia",
|
||||||
"archive_size": "Mida de l'arxiu",
|
"archive_size": "Mida de l'arxiu",
|
||||||
"archive_size_description": "Configureu la mida de l'arxiu de les descàrregues (en GiB)",
|
"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 #}}",
|
"archived_count": "{count, plural, one {Arxivat #} other {Arxivats #}}",
|
||||||
"are_these_the_same_person": "Són la mateixa persona?",
|
"are_these_the_same_person": "Són la mateixa persona?",
|
||||||
"are_you_sure_to_do_this": "Esteu segurs que voleu fer-ho?",
|
"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_merge_people": "No es pot fusionar gent",
|
||||||
"cannot_undo_this_action": "Aquesta acció no es pot desfer!",
|
"cannot_undo_this_action": "Aquesta acció no es pot desfer!",
|
||||||
"cannot_update_the_description": "No es pot actualitzar la descripció",
|
"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_date": "Canvia la data",
|
||||||
"change_expiration_time": "Canvia la data d'expiració",
|
"change_expiration_time": "Canvia la data d'expiració",
|
||||||
"change_location": "Canvia la ubicació",
|
"change_location": "Canvia la ubicació",
|
||||||
@@ -480,6 +466,7 @@
|
|||||||
"confirm": "Confirmar",
|
"confirm": "Confirmar",
|
||||||
"confirm_admin_password": "Confirmeu la contrasenya d'administrador",
|
"confirm_admin_password": "Confirmeu la contrasenya d'administrador",
|
||||||
"confirm_delete_shared_link": "Esteu segurs que voleu eliminar aquest enllaç compartit?",
|
"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",
|
"confirm_password": "Confirmació de contrasenya",
|
||||||
"contain": "Contingut",
|
"contain": "Contingut",
|
||||||
"context": "Context",
|
"context": "Context",
|
||||||
@@ -529,6 +516,7 @@
|
|||||||
"delete_key": "Suprimeix la clau",
|
"delete_key": "Suprimeix la clau",
|
||||||
"delete_library": "Suprimeix la Llibreria",
|
"delete_library": "Suprimeix la Llibreria",
|
||||||
"delete_link": "Esborra l'enllaç",
|
"delete_link": "Esborra l'enllaç",
|
||||||
|
"delete_others": "Suprimeix altres",
|
||||||
"delete_shared_link": "Odstranit sdílený odkaz",
|
"delete_shared_link": "Odstranit sdílený odkaz",
|
||||||
"delete_tag": "Eliminar etiqueta",
|
"delete_tag": "Eliminar etiqueta",
|
||||||
"delete_tag_confirmation_prompt": "Estàs segur que vols eliminar l'etiqueta {tagName}?",
|
"delete_tag_confirmation_prompt": "Estàs segur que vols eliminar l'etiqueta {tagName}?",
|
||||||
@@ -562,13 +550,6 @@
|
|||||||
"duplicates": "Duplicats",
|
"duplicates": "Duplicats",
|
||||||
"duplicates_description": "Resol cada grup indicant quins, si n'hi ha, són duplicats",
|
"duplicates_description": "Resol cada grup indicant quins, si n'hi ha, són duplicats",
|
||||||
"duration": "Duració",
|
"duration": "Duració",
|
||||||
"durations": {
|
|
||||||
"days": "",
|
|
||||||
"hours": "",
|
|
||||||
"minutes": "",
|
|
||||||
"months": "",
|
|
||||||
"years": ""
|
|
||||||
},
|
|
||||||
"edit": "Editar",
|
"edit": "Editar",
|
||||||
"edit_album": "Edita l'àlbum",
|
"edit_album": "Edita l'àlbum",
|
||||||
"edit_avatar": "Edita l'avatar",
|
"edit_avatar": "Edita l'avatar",
|
||||||
@@ -576,8 +557,8 @@
|
|||||||
"edit_date_and_time": "Edita data i hora",
|
"edit_date_and_time": "Edita data i hora",
|
||||||
"edit_exclusion_pattern": "Edita patró d'exclusió",
|
"edit_exclusion_pattern": "Edita patró d'exclusió",
|
||||||
"edit_faces": "Edita les cares",
|
"edit_faces": "Edita les cares",
|
||||||
"edit_import_path": "Edita el camí d'importació",
|
"edit_import_path": "Edita la ruta d'importació",
|
||||||
"edit_import_paths": "Edita camins d'importació",
|
"edit_import_paths": "Edita les rutes d'importació",
|
||||||
"edit_key": "Edita clau",
|
"edit_key": "Edita clau",
|
||||||
"edit_link": "Edita enllaç",
|
"edit_link": "Edita enllaç",
|
||||||
"edit_location": "Edita ubicació",
|
"edit_location": "Edita ubicació",
|
||||||
@@ -593,8 +574,6 @@
|
|||||||
"editor_crop_tool_h2_aspect_ratios": "Relació d'aspecte",
|
"editor_crop_tool_h2_aspect_ratios": "Relació d'aspecte",
|
||||||
"editor_crop_tool_h2_rotation": "Rotació",
|
"editor_crop_tool_h2_rotation": "Rotació",
|
||||||
"email": "Correu electrònic",
|
"email": "Correu electrònic",
|
||||||
"empty": "",
|
|
||||||
"empty_album": "",
|
|
||||||
"empty_trash": "Buidar la paperera",
|
"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ó!",
|
"empty_trash_confirmation": "Esteu segur que voleu buidar la paperera? Això eliminarà tots els recursos a la paperera permanentment d'Immich.\nNo podeu desfer aquesta acció!",
|
||||||
"enable": "Activar",
|
"enable": "Activar",
|
||||||
@@ -628,13 +607,14 @@
|
|||||||
"failed_to_create_shared_link": "No s'ha pogut crear l'enllaç compartit",
|
"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_edit_shared_link": "No s'ha pogut editar l'enllaç compartit",
|
||||||
"failed_to_get_people": "No s'han pogut aconseguir persones",
|
"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_asset": "No s'ha pogut carregar l'element",
|
||||||
"failed_to_load_assets": "No s'han pogut carregar els elements",
|
"failed_to_load_assets": "No s'han pogut carregar els elements",
|
||||||
"failed_to_load_people": "No s'han pogut carregar les persones",
|
"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_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_stack_assets": "No s'han pogut apilar els elements",
|
||||||
"failed_to_unstack_assets": "No s'han pogut desapilar 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",
|
"incorrect_email_or_password": "Correu electrònic o contrasenya incorrectes",
|
||||||
"paths_validation_failed": "{paths, plural, one {# ruta} other {# rutes}} no ha pogut validar",
|
"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.",
|
"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_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_comment": "No es pot afegir el comentari",
|
||||||
"unable_to_add_exclusion_pattern": "No s'ha pogut afegir el patró d’exclusió",
|
"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_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_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",
|
"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_location": "No es pot canviar la ubicació",
|
||||||
"unable_to_change_password": "No es pot canviar la contrasenya",
|
"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_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_complete_oauth_login": "No es pot completar l'inici de sessió OAuth",
|
||||||
"unable_to_connect": "No pot connectar",
|
"unable_to_connect": "No pot connectar",
|
||||||
"unable_to_connect_to_server": "No es pot connectar al servidor",
|
"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_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_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_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_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_library": "No es pot eliminar la biblioteca",
|
||||||
"unable_to_remove_partner": "No es pot eliminar company/a",
|
"unable_to_remove_partner": "No es pot eliminar company/a",
|
||||||
"unable_to_remove_reaction": "No es pot eliminar la reacció",
|
"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_repair_items": "No es poden reparar els elements",
|
||||||
"unable_to_reset_password": "No es pot restablir la contrasenya",
|
"unable_to_reset_password": "No es pot restablir la contrasenya",
|
||||||
"unable_to_resolve_duplicate": "No es pot resoldre el duplicat",
|
"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_update_user": "No es pot actualitzar l'usuari",
|
||||||
"unable_to_upload_file": "No es pot carregar el fitxer"
|
"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",
|
"exif": "Exif",
|
||||||
"exit_slideshow": "Surt de la presentació de diapositives",
|
"exit_slideshow": "Surt de la presentació de diapositives",
|
||||||
"expand_all": "Ampliar-ho tot",
|
"expand_all": "Ampliar-ho tot",
|
||||||
@@ -750,33 +722,27 @@
|
|||||||
"external": "Extern",
|
"external": "Extern",
|
||||||
"external_libraries": "Llibreries externes",
|
"external_libraries": "Llibreries externes",
|
||||||
"face_unassigned": "Sense assignar",
|
"face_unassigned": "Sense assignar",
|
||||||
"failed_to_get_people": "",
|
|
||||||
"favorite": "Preferit",
|
"favorite": "Preferit",
|
||||||
"favorite_or_unfavorite_photo": "Foto preferida o no preferida",
|
"favorite_or_unfavorite_photo": "Foto preferida o no preferida",
|
||||||
"favorites": "Preferits",
|
"favorites": "Preferits",
|
||||||
"feature": "",
|
|
||||||
"feature_photo_updated": "Foto destacada actualitzada",
|
"feature_photo_updated": "Foto destacada actualitzada",
|
||||||
"featurecollection": "",
|
|
||||||
"features": "Característiques",
|
"features": "Característiques",
|
||||||
"features_setting_description": "Administrar les funcions de l'aplicació",
|
"features_setting_description": "Administrar les funcions de l'aplicació",
|
||||||
"file_name": "Nom de l'arxiu",
|
"file_name": "Nom de l'arxiu",
|
||||||
"file_name_or_extension": "Nom de l'arxiu o extensió",
|
"file_name_or_extension": "Nom de l'arxiu o extensió",
|
||||||
"filename": "Nom del fitxer",
|
"filename": "Nom del fitxer",
|
||||||
"files": "",
|
|
||||||
"filetype": "Tipus d'arxiu",
|
"filetype": "Tipus d'arxiu",
|
||||||
"filter_people": "Filtra persones",
|
"filter_people": "Filtra persones",
|
||||||
"find_them_fast": "Trobeu-los ràpidament pel nom amb la cerca",
|
"find_them_fast": "Trobeu-los ràpidament pel nom amb la cerca",
|
||||||
"fix_incorrect_match": "Corregiu la coincidència incorrecta",
|
"fix_incorrect_match": "Corregiu la coincidència incorrecta",
|
||||||
"folders": "Carpetes",
|
"folders": "Carpetes",
|
||||||
"folders_feature_description": "Explorar la vista de carpetes per les fotos i vídeos del sistema d'arxius",
|
"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",
|
"forward": "Endavant",
|
||||||
"general": "General",
|
"general": "General",
|
||||||
"get_help": "Aconseguir ajuda",
|
"get_help": "Aconseguir ajuda",
|
||||||
"getting_started": "Començant",
|
"getting_started": "Començant",
|
||||||
"go_back": "Torna",
|
"go_back": "Torna",
|
||||||
"go_to_search": "Vés a cercar",
|
"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_albums_by": "Agrupa àlbums per...",
|
||||||
"group_no": "Cap agrupació",
|
"group_no": "Cap agrupació",
|
||||||
"group_owner": "Agrupar per propietari",
|
"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_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_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}",
|
"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_logo": "Logotip d'Immich",
|
||||||
"immich_web_interface": "Interfície web Immich",
|
"immich_web_interface": "Interfície web Immich",
|
||||||
"import_from_json": "Importar des de JSON",
|
"import_from_json": "Importar des de JSON",
|
||||||
@@ -823,10 +788,11 @@
|
|||||||
"invite_people": "Convida gent",
|
"invite_people": "Convida gent",
|
||||||
"invite_to_album": "Convida a l'àlbum",
|
"invite_to_album": "Convida a l'àlbum",
|
||||||
"items_count": "{count, plural, one {# element} other {# elements}}",
|
"items_count": "{count, plural, one {# element} other {# elements}}",
|
||||||
"job_settings_description": "",
|
|
||||||
"jobs": "Tasques",
|
"jobs": "Tasques",
|
||||||
"keep": "Mantenir",
|
"keep": "Mantenir",
|
||||||
"keep_all": "Mantenir-ho tot",
|
"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",
|
"keyboard_shortcuts": "Dreceres de teclat",
|
||||||
"language": "Idioma",
|
"language": "Idioma",
|
||||||
"language_setting_description": "Seleccioneu el vostre idioma",
|
"language_setting_description": "Seleccioneu el vostre idioma",
|
||||||
@@ -838,19 +804,6 @@
|
|||||||
"level": "Nivell",
|
"level": "Nivell",
|
||||||
"library": "Bibilioteca",
|
"library": "Bibilioteca",
|
||||||
"library_options": "Opcions de biblioteca",
|
"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",
|
"light": "Llum",
|
||||||
"like_deleted": "M'agrada suprimit",
|
"like_deleted": "M'agrada suprimit",
|
||||||
"link_motion_video": "Enllaçar vídeo en moviment",
|
"link_motion_video": "Enllaçar vídeo en moviment",
|
||||||
@@ -955,7 +908,6 @@
|
|||||||
"onboarding_welcome_user": "Benvingut, {user}",
|
"onboarding_welcome_user": "Benvingut, {user}",
|
||||||
"online": "En línia",
|
"online": "En línia",
|
||||||
"only_favorites": "Només preferits",
|
"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_map_view": "Obrir a la vista del mapa",
|
||||||
"open_in_openstreetmap": "Obre a OpenStreetMap",
|
"open_in_openstreetmap": "Obre a OpenStreetMap",
|
||||||
"open_the_search_filters": "Obriu els filtres de cerca",
|
"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_edits_count": "{count, plural, one {# persona editada} other {# persones editades}}",
|
||||||
"people_feature_description": "Explorar fotos i vídeos agrupades per persona",
|
"people_feature_description": "Explorar fotos i vídeos agrupades per persona",
|
||||||
"people_sidebar_description": "Mostrar un enllaç a Persones a la barra lateral",
|
"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": "Avís d'eliminació permanent",
|
||||||
"permanent_deletion_warning_setting_description": "Mostrar un avís quan s'eliminin els elements permanentment",
|
"permanent_deletion_warning_setting_description": "Mostrar un avís quan s'eliminin els elements permanentment",
|
||||||
"permanently_delete": "Eliminar permanentment",
|
"permanently_delete": "Eliminar permanentment",
|
||||||
@@ -1015,7 +966,6 @@
|
|||||||
"play_memories": "Reproduir records",
|
"play_memories": "Reproduir records",
|
||||||
"play_motion_photo": "Reproduir Fotos en Moviment",
|
"play_motion_photo": "Reproduir Fotos en Moviment",
|
||||||
"play_or_pause_video": "Reproduir o posar en pausa el vídeo",
|
"play_or_pause_video": "Reproduir o posar en pausa el vídeo",
|
||||||
"point": "",
|
|
||||||
"port": "Port",
|
"port": "Port",
|
||||||
"preset": "Preestablert",
|
"preset": "Preestablert",
|
||||||
"preview": "Previsualització",
|
"preview": "Previsualització",
|
||||||
@@ -1060,12 +1010,10 @@
|
|||||||
"purchase_server_description_2": "Estat del contribuent",
|
"purchase_server_description_2": "Estat del contribuent",
|
||||||
"purchase_server_title": "Servidor",
|
"purchase_server_title": "Servidor",
|
||||||
"purchase_settings_server_activated": "La clau de producte del servidor la gestiona l'administrador",
|
"purchase_settings_server_activated": "La clau de producte del servidor la gestiona l'administrador",
|
||||||
"range": "",
|
|
||||||
"rating": "Valoració",
|
"rating": "Valoració",
|
||||||
"rating_clear": "Esborrar valoració",
|
"rating_clear": "Esborrar valoració",
|
||||||
"rating_count": "{count, plural, one {# estrella} other {# estrelles}}",
|
"rating_count": "{count, plural, one {# estrella} other {# estrelles}}",
|
||||||
"rating_description": "Mostrar la valoració EXIF al panell d'informació",
|
"rating_description": "Mostrar la valoració EXIF al panell d'informació",
|
||||||
"raw": "",
|
|
||||||
"reaction_options": "Opcions de reacció",
|
"reaction_options": "Opcions de reacció",
|
||||||
"read_changelog": "Llegeix el registre de canvis",
|
"read_changelog": "Llegeix el registre de canvis",
|
||||||
"reassign": "Reassignar",
|
"reassign": "Reassignar",
|
||||||
@@ -1110,7 +1058,6 @@
|
|||||||
"reset": "Restablir",
|
"reset": "Restablir",
|
||||||
"reset_password": "Restablir contrasenya",
|
"reset_password": "Restablir contrasenya",
|
||||||
"reset_people_visibility": "Restablir la visibilitat de les persones",
|
"reset_people_visibility": "Restablir la visibilitat de les persones",
|
||||||
"reset_settings_to_default": "",
|
|
||||||
"reset_to_default": "Restableix els valors predeterminats",
|
"reset_to_default": "Restableix els valors predeterminats",
|
||||||
"resolve_duplicates": "Resoldre duplicats",
|
"resolve_duplicates": "Resoldre duplicats",
|
||||||
"resolved_all_duplicates": "Tots els duplicats resolts",
|
"resolved_all_duplicates": "Tots els duplicats resolts",
|
||||||
@@ -1130,9 +1077,7 @@
|
|||||||
"saved_settings": "Configuració guardada",
|
"saved_settings": "Configuració guardada",
|
||||||
"say_something": "Digues quelcom",
|
"say_something": "Digues quelcom",
|
||||||
"scan_all_libraries": "Escanejar totes les llibreries",
|
"scan_all_libraries": "Escanejar totes les llibreries",
|
||||||
"scan_all_library_files": "Re-escanejar tots els fitxers de la llibreria",
|
|
||||||
"scan_library": "Escaneja",
|
"scan_library": "Escaneja",
|
||||||
"scan_new_library_files": "Escanejar nous fitxers de la llibreria",
|
|
||||||
"scan_settings": "Configuració d'escaneig",
|
"scan_settings": "Configuració d'escaneig",
|
||||||
"scanning_for_album": "S'està buscant l'àlbum...",
|
"scanning_for_album": "S'està buscant l'àlbum...",
|
||||||
"search": "Cerca",
|
"search": "Cerca",
|
||||||
@@ -1175,7 +1120,6 @@
|
|||||||
"selected_count": "{count, plural, one {# seleccionat} other {# seleccionats}}",
|
"selected_count": "{count, plural, one {# seleccionat} other {# seleccionats}}",
|
||||||
"send_message": "Envia missatge",
|
"send_message": "Envia missatge",
|
||||||
"send_welcome_email": "Envia correu de benvinguda",
|
"send_welcome_email": "Envia correu de benvinguda",
|
||||||
"server": "Servidor",
|
|
||||||
"server_offline": "Servidor fora de línia",
|
"server_offline": "Servidor fora de línia",
|
||||||
"server_online": "Servidor en línia",
|
"server_online": "Servidor en línia",
|
||||||
"server_stats": "Estadístiques del servidor",
|
"server_stats": "Estadístiques del servidor",
|
||||||
@@ -1289,7 +1233,6 @@
|
|||||||
"to_trash": "Paperera",
|
"to_trash": "Paperera",
|
||||||
"toggle_settings": "Canvia configuració",
|
"toggle_settings": "Canvia configuració",
|
||||||
"toggle_theme": "Alternar tema",
|
"toggle_theme": "Alternar tema",
|
||||||
"toggle_visibility": "Canvia visibilitat",
|
|
||||||
"total_usage": "Ús total",
|
"total_usage": "Ús total",
|
||||||
"trash": "Paperera",
|
"trash": "Paperera",
|
||||||
"trash_all": "Envia-ho tot a la 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}}.",
|
"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",
|
"type": "Tipus",
|
||||||
"unarchive": "Desarxivar",
|
"unarchive": "Desarxivar",
|
||||||
"unarchived": "Desarxivat",
|
|
||||||
"unarchived_count": "{count, plural, other {# elements desarxivats}}",
|
"unarchived_count": "{count, plural, other {# elements desarxivats}}",
|
||||||
"unfavorite": "Reverteix preferit",
|
"unfavorite": "Reverteix preferit",
|
||||||
"unhide_person": "Mostra persona",
|
"unhide_person": "Mostra persona",
|
||||||
"unknown": "Desconegut",
|
"unknown": "Desconegut",
|
||||||
"unknown_album": "Àlbum desconegut",
|
|
||||||
"unknown_year": "Any desconegut",
|
"unknown_year": "Any desconegut",
|
||||||
"unlimited": "Il·limitat",
|
"unlimited": "Il·limitat",
|
||||||
"unlink_motion_video": "Desvincular vídeo en moviment",
|
"unlink_motion_video": "Desvincular vídeo en moviment",
|
||||||
@@ -1336,12 +1277,13 @@
|
|||||||
"use_custom_date_range": "Fes servir un rang de dates personalitzat",
|
"use_custom_date_range": "Fes servir un rang de dates personalitzat",
|
||||||
"user": "Usuari",
|
"user": "Usuari",
|
||||||
"user_id": "ID d'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_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": "Compra",
|
||||||
"user_purchase_settings_description": "Gestiona la teva compra",
|
"user_purchase_settings_description": "Gestiona la teva compra",
|
||||||
"user_role_set": "Establir {user} com a {role}",
|
"user_role_set": "Establir {user} com a {role}",
|
||||||
"user_usage_detail": "Detall d'ús d'usuari",
|
"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",
|
"username": "Nom d'usuari",
|
||||||
"users": "Usuaris",
|
"users": "Usuaris",
|
||||||
"utilities": "Utilitats",
|
"utilities": "Utilitats",
|
||||||
@@ -1349,7 +1291,7 @@
|
|||||||
"variables": "Variables",
|
"variables": "Variables",
|
||||||
"version": "Versió",
|
"version": "Versió",
|
||||||
"version_announcement_closing": "El teu amic Alex",
|
"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 <link>release notes</link> i assegureu-vos que el vostre <code>docker-compose.yml</code> i <code>.env</code> 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 <link>notes de llançament</link> 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": "Historial de versions",
|
||||||
"version_history_item": "Instal·lat {version} el {date}",
|
"version_history_item": "Instal·lat {version} el {date}",
|
||||||
"video": "Vídeo",
|
"video": "Vídeo",
|
||||||
@@ -1366,7 +1308,6 @@
|
|||||||
"view_next_asset": "Mostra el següent element",
|
"view_next_asset": "Mostra el següent element",
|
||||||
"view_previous_asset": "Mostra l'element anterior",
|
"view_previous_asset": "Mostra l'element anterior",
|
||||||
"view_stack": "Veure la pila",
|
"view_stack": "Veure la pila",
|
||||||
"viewer": "Visualitzador",
|
|
||||||
"visibility_changed": "La visibilitat ha canviat per {count, plural, one {# persona} other {# persones}}",
|
"visibility_changed": "La visibilitat ha canviat per {count, plural, one {# persona} other {# persones}}",
|
||||||
"waiting": "Esperant",
|
"waiting": "Esperant",
|
||||||
"warning": "Avís",
|
"warning": "Avís",
|
||||||
|
|||||||
151
i18n/cs.json
@@ -23,6 +23,7 @@
|
|||||||
"add_to": "Přidat do...",
|
"add_to": "Přidat do...",
|
||||||
"add_to_album": "Přidat do alba",
|
"add_to_album": "Přidat do alba",
|
||||||
"add_to_shared_album": "Přidat do sdíleného 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_archive": "Přidáno do archivu",
|
||||||
"added_to_favorites": "Přidáno do oblíbených",
|
"added_to_favorites": "Přidáno do oblíbených",
|
||||||
"added_to_favorites_count": "Přidáno {count, number} do oblíbených",
|
"added_to_favorites_count": "Přidáno {count, number} do oblíbených",
|
||||||
@@ -38,7 +39,7 @@
|
|||||||
"backup_database_enable_description": "Povolit 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_keep_last_amount": "Počet předchozích záloh k uchování",
|
||||||
"backup_settings": "Nastavení zálohování",
|
"backup_settings": "Nastavení zálohování",
|
||||||
"backup_settings_description": "Spravovat nastavení zálohování databáze",
|
"backup_settings_description": "Správa nastavení zálohování databáze",
|
||||||
"check_all": "Vše zkontrolovat",
|
"check_all": "Vše zkontrolovat",
|
||||||
"cleared_jobs": "Hotové úlohy pro: {job}",
|
"cleared_jobs": "Hotové úlohy pro: {job}",
|
||||||
"config_set_by_file": "Konfigurace je aktuálně prováděna konfiguračním souborem",
|
"config_set_by_file": "Konfigurace je aktuálně prováděna konfiguračním souborem",
|
||||||
@@ -51,9 +52,7 @@
|
|||||||
"cron_expression": "Výraz cron",
|
"cron_expression": "Výraz cron",
|
||||||
"cron_expression_description": "Nastavte interval prohledávání pomocí cron formátu. Další informace naleznete např. v <link>Crontab Guru</link>",
|
"cron_expression_description": "Nastavte interval prohledávání pomocí cron formátu. Další informace naleznete např. v <link>Crontab Guru</link>",
|
||||||
"cron_expression_presets": "Předvolby výrazů cron",
|
"cron_expression_presets": "Předvolby výrazů cron",
|
||||||
"crontab_guru": "Crontab Guru",
|
|
||||||
"disable_login": "Zakázat přihlášení",
|
"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í",
|
"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.",
|
"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})",
|
"external_library_created_at": "Externí knihovna (vytvořena {date})",
|
||||||
@@ -71,22 +70,15 @@
|
|||||||
"image_prefer_wide_gamut": "Preferovat široký gamut",
|
"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_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_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_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_preview_title": "Náhledy",
|
||||||
"image_quality": "Kvalita",
|
"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": "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_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": "Obrázky",
|
||||||
"image_settings_description": "Správa kvality a rozlišení generovaných obrázků",
|
"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_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_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",
|
"image_thumbnail_title": "Miniatury",
|
||||||
"job_concurrency": "Souběžnost úlohy {job}",
|
"job_concurrency": "Souběžnost úlohy {job}",
|
||||||
"job_created": "Úloha vytvořena",
|
"job_created": "Úloha vytvořena",
|
||||||
@@ -97,9 +89,6 @@
|
|||||||
"jobs_delayed": "{jobCount, plural, one {# zpožděný} few {# zpožděné} other {# zpožděných}}",
|
"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}}",
|
"jobs_failed": "{jobCount, plural, one {# neúspěšný} few {# neúspěšné} other {# neúspěšných}}",
|
||||||
"library_created": "Vytvořena knihovna: {library}",
|
"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 <link>Crontab Guru</link>",
|
|
||||||
"library_cron_expression_presets": "Předvolby výrazu pro Cron",
|
|
||||||
"library_deleted": "Knihovna smazána",
|
"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_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í",
|
"library_scanning": "Pravidelné prohledávání",
|
||||||
@@ -142,7 +131,7 @@
|
|||||||
"machine_learning_smart_search_description": "Sémantické vyhledávání obrázků pomocí CLIP embeddings",
|
"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": "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_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_concurrency": "Správa souběžnosti",
|
||||||
"manage_log_settings": "Správa nastavení protokolu",
|
"manage_log_settings": "Správa nastavení protokolu",
|
||||||
"map_dark_style": "Tmavý motiv",
|
"map_dark_style": "Tmavý motiv",
|
||||||
@@ -168,11 +157,11 @@
|
|||||||
"migration_job_description": "Migrace miniatur snímků a obličejů do nejnovější struktury složek",
|
"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_paths_added": "Nebyly přidány žádné cesty",
|
||||||
"no_pattern_added": "Nebyl přidán žádný vzor",
|
"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_cannot_be_changed_later": "UPOZORNĚNÍ: Toto nelze později změnit!",
|
||||||
"note_unlimited_quota": "Upozornění: Pro neomezenou kvótu zadejte 0",
|
"note_unlimited_quota": "Upozornění: Pro neomezenou kvótu zadejte 0",
|
||||||
"notification_email_from_address": "Adresa Od",
|
"notification_email_from_address": "Adresa Od",
|
||||||
"notification_email_from_address_description": "E-mailová adresa odesílatele, např.: \"Immich Photo Server <noreply@example.com>\"",
|
"notification_email_from_address_description": "E-mailová adresa odesílatele, např.: „Immich Photo Server <noreply@example.com>“",
|
||||||
"notification_email_host_description": "Adresa e-mailového serveru (např. smtp.immich.app)",
|
"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": "Ignorovat chyby certifikátů",
|
||||||
"notification_email_ignore_certificate_errors_description": "Ignorovat chyby ověření certifikátu TLS (nedoporučuje se)",
|
"notification_email_ignore_certificate_errors_description": "Ignorovat chyby ověření certifikátu TLS (nedoporučuje se)",
|
||||||
@@ -223,7 +212,6 @@
|
|||||||
"refreshing_all_libraries": "Obnovení všech knihoven",
|
"refreshing_all_libraries": "Obnovení všech knihoven",
|
||||||
"registration": "Registrace správce",
|
"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.",
|
"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_all": "Opravit vše",
|
||||||
"repair_matched_items": "Shoda {count, plural, one {# položky} other {# položek}}",
|
"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}}",
|
"repaired_items": "{count, plural, one {Opravena # položka} few {Opraveny # položky} other {Opraveno # položek}}",
|
||||||
@@ -231,12 +219,12 @@
|
|||||||
"reset_settings_to_default": "Obnovení výchozího nastavení",
|
"reset_settings_to_default": "Obnovení výchozího nastavení",
|
||||||
"reset_settings_to_recent_saved": "Obnovit poslední uložené nastavení",
|
"reset_settings_to_recent_saved": "Obnovit poslední uložené nastavení",
|
||||||
"scanning_library": "Prohledat knihovnu",
|
"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...",
|
"search_jobs": "Hledat úlohy...",
|
||||||
"send_welcome_email": "Odeslat uvítací e-mail",
|
"send_welcome_email": "Odeslat uvítací e-mail",
|
||||||
"server_external_domain_settings": "Externí doména",
|
"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_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": "Server",
|
||||||
"server_settings_description": "Správa nastavení serveru",
|
"server_settings_description": "Správa nastavení serveru",
|
||||||
"server_welcome_message": "Uvítací zpráva",
|
"server_welcome_message": "Uvítací zpráva",
|
||||||
@@ -262,6 +250,16 @@
|
|||||||
"storage_template_user_label": "<code>{label}</code> je štítek úložiště uživatele",
|
"storage_template_user_label": "<code>{label}</code> je štítek úložiště uživatele",
|
||||||
"system_settings": "Systémová nastavení",
|
"system_settings": "Systémová nastavení",
|
||||||
"tag_cleanup_job": "Promazání značek",
|
"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": "Vlastní CSS",
|
||||||
"theme_custom_css_settings_description": "Kaskádové styly umožňují přizpůsobit design aplikace Immich.",
|
"theme_custom_css_settings_description": "Kaskádové styly umožňují přizpůsobit design aplikace Immich.",
|
||||||
"theme_settings": "Motivy",
|
"theme_settings": "Motivy",
|
||||||
@@ -269,7 +267,6 @@
|
|||||||
"these_files_matched_by_checksum": "Tyto soubory jsou porovnávány podle jejich kontrolních součtů",
|
"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": "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",
|
"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": "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_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)",
|
"transcoding_acceleration_nvenc": "NVENC (vyžaduje NVIDIA GPU)",
|
||||||
@@ -321,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_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": "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_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": "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_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í",
|
"transcoding_two_pass_encoding": "Dvouprůchodové kódování",
|
||||||
@@ -403,7 +398,6 @@
|
|||||||
"archive_or_unarchive_photo": "Archivovat nebo odarchivovat fotku",
|
"archive_or_unarchive_photo": "Archivovat nebo odarchivovat fotku",
|
||||||
"archive_size": "Velikost archivu",
|
"archive_size": "Velikost archivu",
|
||||||
"archive_size_description": "Nastavte velikost archivu pro stahování (v GiB)",
|
"archive_size_description": "Nastavte velikost archivu pro stahování (v GiB)",
|
||||||
"archived": "Archivováno",
|
|
||||||
"archived_count": "{count, plural, other {Archivováno #}}",
|
"archived_count": "{count, plural, other {Archivováno #}}",
|
||||||
"are_these_the_same_person": "Jedná se o stejnou osobu?",
|
"are_these_the_same_person": "Jedná se o stejnou osobu?",
|
||||||
"are_you_sure_to_do_this": "Opravdu to chcete udělat?",
|
"are_you_sure_to_do_this": "Opravdu to chcete udělat?",
|
||||||
@@ -424,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_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 <b>{name}</b>} other {nového alba}}",
|
"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 <b>{name}</b>} other {nového alba}}",
|
||||||
"assets_count": "{count, plural, one {# položka} few {# položky} other {# položek}}",
|
"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_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_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}}",
|
"assets_removed_count": "{count, plural, one {Odstraněna # položka} few {Odstraněny # položky} other {Odstraněno # položek}}",
|
||||||
@@ -454,10 +447,6 @@
|
|||||||
"cannot_merge_people": "Nelze sloučit osoby",
|
"cannot_merge_people": "Nelze sloučit osoby",
|
||||||
"cannot_undo_this_action": "Tuto akci nelze vrátit zpět!",
|
"cannot_undo_this_action": "Tuto akci nelze vrátit zpět!",
|
||||||
"cannot_update_the_description": "Nelze aktualizovat popis",
|
"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_date": "Změnit datum",
|
||||||
"change_expiration_time": "Změna konce platnosti",
|
"change_expiration_time": "Změna konce platnosti",
|
||||||
"change_location": "Změna polohy",
|
"change_location": "Změna polohy",
|
||||||
@@ -489,6 +478,7 @@
|
|||||||
"confirm": "Potvrdit",
|
"confirm": "Potvrdit",
|
||||||
"confirm_admin_password": "Potvrzení hesla správce",
|
"confirm_admin_password": "Potvrzení hesla správce",
|
||||||
"confirm_delete_shared_link": "Opravdu chcete odstranit tento sdílený odkaz?",
|
"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",
|
"confirm_password": "Potvrzení hesla",
|
||||||
"contain": "Obsah",
|
"contain": "Obsah",
|
||||||
"context": "Kontext",
|
"context": "Kontext",
|
||||||
@@ -538,6 +528,7 @@
|
|||||||
"delete_key": "Smazat klíč",
|
"delete_key": "Smazat klíč",
|
||||||
"delete_library": "Smazat knihovnu",
|
"delete_library": "Smazat knihovnu",
|
||||||
"delete_link": "Smazat odkaz",
|
"delete_link": "Smazat odkaz",
|
||||||
|
"delete_others": "Odstranit ostatní",
|
||||||
"delete_shared_link": "Smazat sdílený odkaz",
|
"delete_shared_link": "Smazat sdílený odkaz",
|
||||||
"delete_tag": "Smazat značku",
|
"delete_tag": "Smazat značku",
|
||||||
"delete_tag_confirmation_prompt": "Opravdu chcete odstranit značku {tagName}?",
|
"delete_tag_confirmation_prompt": "Opravdu chcete odstranit značku {tagName}?",
|
||||||
@@ -571,13 +562,6 @@
|
|||||||
"duplicates": "Duplicity",
|
"duplicates": "Duplicity",
|
||||||
"duplicates_description": "Vyřešte každou skupinu tak, že uvedete, které skupiny jsou duplicitní",
|
"duplicates_description": "Vyřešte každou skupinu tak, že uvedete, které skupiny jsou duplicitní",
|
||||||
"duration": "Doba trvání",
|
"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": "Upravit",
|
||||||
"edit_album": "Upravit album",
|
"edit_album": "Upravit album",
|
||||||
"edit_avatar": "Upravit avatar",
|
"edit_avatar": "Upravit avatar",
|
||||||
@@ -602,8 +586,6 @@
|
|||||||
"editor_crop_tool_h2_aspect_ratios": "Poměr stran",
|
"editor_crop_tool_h2_aspect_ratios": "Poměr stran",
|
||||||
"editor_crop_tool_h2_rotation": "Otočení",
|
"editor_crop_tool_h2_rotation": "Otočení",
|
||||||
"email": "E-mail",
|
"email": "E-mail",
|
||||||
"empty": "Prázdné",
|
|
||||||
"empty_album": "Prázdné album",
|
|
||||||
"empty_trash": "Vyprázdnit koš",
|
"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!",
|
"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",
|
"enable": "Povolit",
|
||||||
@@ -637,6 +619,7 @@
|
|||||||
"failed_to_create_shared_link": "Nepodařilo se vytvořit sdílený odkaz",
|
"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_edit_shared_link": "Nepodařilo se upravit sdílený odkaz",
|
||||||
"failed_to_get_people": "Nepodařilo se načíst lidi",
|
"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_asset": "Nepodařilo se načíst položku",
|
||||||
"failed_to_load_assets": "Nepodařilo se načíst položky",
|
"failed_to_load_assets": "Nepodařilo se načíst položky",
|
||||||
"failed_to_load_people": "Chyba načítání osob",
|
"failed_to_load_people": "Chyba načítání osob",
|
||||||
@@ -664,8 +647,6 @@
|
|||||||
"unable_to_change_location": "Nelze změnit polohu",
|
"unable_to_change_location": "Nelze změnit polohu",
|
||||||
"unable_to_change_password": "Nelze změnit heslo",
|
"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_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_complete_oauth_login": "Nelze dokončit OAuth přihlášení",
|
||||||
"unable_to_connect": "Nelze se připojit",
|
"unable_to_connect": "Nelze se připojit",
|
||||||
"unable_to_connect_to_server": "Nepodařilo se připojit k serveru",
|
"unable_to_connect_to_server": "Nepodařilo se připojit k serveru",
|
||||||
@@ -706,12 +687,10 @@
|
|||||||
"unable_to_remove_album_users": "Nelze odebrat uživatele z alba",
|
"unable_to_remove_album_users": "Nelze odebrat uživatele z alba",
|
||||||
"unable_to_remove_api_key": "Nelze odstranit API klíč",
|
"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_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_deleted_assets": "Nelze odstranit offline soubory",
|
||||||
"unable_to_remove_library": "Nelze odstranit knihovnu",
|
"unable_to_remove_library": "Nelze odstranit knihovnu",
|
||||||
"unable_to_remove_partner": "Nelze odebrat partnera",
|
"unable_to_remove_partner": "Nelze odebrat partnera",
|
||||||
"unable_to_remove_reaction": "Nelze odstranit reakci",
|
"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_repair_items": "Nelze opravit položky",
|
||||||
"unable_to_reset_password": "Nelze obnovit heslo",
|
"unable_to_reset_password": "Nelze obnovit heslo",
|
||||||
"unable_to_resolve_duplicate": "Nelze vyřešit duplicitu",
|
"unable_to_resolve_duplicate": "Nelze vyřešit duplicitu",
|
||||||
@@ -741,10 +720,6 @@
|
|||||||
"unable_to_update_user": "Nelze aktualizovat uživatele",
|
"unable_to_update_user": "Nelze aktualizovat uživatele",
|
||||||
"unable_to_upload_file": "Nepodařilo se nahrát soubor"
|
"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",
|
"exif": "Exif",
|
||||||
"exit_slideshow": "Ukončit prezentaci",
|
"exit_slideshow": "Ukončit prezentaci",
|
||||||
"expand_all": "Rozbalit vše",
|
"expand_all": "Rozbalit vše",
|
||||||
@@ -759,33 +734,28 @@
|
|||||||
"external": "Externí",
|
"external": "Externí",
|
||||||
"external_libraries": "Externí knihovny",
|
"external_libraries": "Externí knihovny",
|
||||||
"face_unassigned": "Nepřiřazena",
|
"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": "Oblíbit",
|
||||||
"favorite_or_unfavorite_photo": "Oblíbit nebo zrušit oblíbení fotky",
|
"favorite_or_unfavorite_photo": "Oblíbit nebo zrušit oblíbení fotky",
|
||||||
"favorites": "Oblíbené",
|
"favorites": "Oblíbené",
|
||||||
"feature": "Funkce",
|
|
||||||
"feature_photo_updated": "Hlavní fotka aktualizována",
|
"feature_photo_updated": "Hlavní fotka aktualizována",
|
||||||
"featurecollection": "Kolekce Funkcí",
|
|
||||||
"features": "Funkce",
|
"features": "Funkce",
|
||||||
"features_setting_description": "Správa funkcí aplikace",
|
"features_setting_description": "Správa funkcí aplikace",
|
||||||
"file_name": "Název souboru",
|
"file_name": "Název souboru",
|
||||||
"file_name_or_extension": "Název nebo přípona souboru",
|
"file_name_or_extension": "Název nebo přípona souboru",
|
||||||
"filename": "Filename",
|
"filename": "Filename",
|
||||||
"files": "",
|
|
||||||
"filetype": "Filetype",
|
"filetype": "Filetype",
|
||||||
"filter_people": "Filtrovat lidi",
|
"filter_people": "Filtrovat lidi",
|
||||||
"find_them_fast": "Najděte je rychle vyhledáním jejich jména",
|
"find_them_fast": "Najděte je rychle vyhledáním jejich jména",
|
||||||
"fix_incorrect_match": "Opravit nesprávnou shodu",
|
"fix_incorrect_match": "Opravit nesprávnou shodu",
|
||||||
"folders": "Složky",
|
"folders": "Složky",
|
||||||
"folders_feature_description": "Procházení zobrazení složek s fotografiemi a videi v souborovém systému",
|
"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",
|
"forward": "Dopředu",
|
||||||
"general": "Obecné",
|
"general": "Obecné",
|
||||||
"get_help": "Získat pomoc",
|
"get_help": "Získat pomoc",
|
||||||
"getting_started": "Začínáme",
|
"getting_started": "Začínáme",
|
||||||
"go_back": "Přejít zpět",
|
"go_back": "Přejít zpět",
|
||||||
"go_to_search": "Přejít na vyhledávání",
|
"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_albums_by": "Seskupit alba podle...",
|
||||||
"group_no": "Neseskupovat",
|
"group_no": "Neseskupovat",
|
||||||
"group_owner": "Seskupit podle uživatele",
|
"group_owner": "Seskupit podle uživatele",
|
||||||
@@ -811,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_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_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_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_logo": "Immich Logo",
|
||||||
"immich_web_interface": "Webové rozhraní Immich",
|
"immich_web_interface": "Webové rozhraní Immich",
|
||||||
"import_from_json": "Import z JSONu",
|
"import_from_json": "Import z JSONu",
|
||||||
@@ -835,10 +801,11 @@
|
|||||||
"invite_people": "Pozvat lidi",
|
"invite_people": "Pozvat lidi",
|
||||||
"invite_to_album": "Pozvat do alba",
|
"invite_to_album": "Pozvat do alba",
|
||||||
"items_count": "{count, plural, one {# položka} few {# položky} other {# položek}}",
|
"items_count": "{count, plural, one {# položka} few {# položky} other {# položek}}",
|
||||||
"job_settings_description": "Správa souběhu úloh",
|
|
||||||
"jobs": "Úlohy",
|
"jobs": "Úlohy",
|
||||||
"keep": "Ponechat",
|
"keep": "Ponechat",
|
||||||
"keep_all": "Ponechat vše",
|
"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",
|
"keyboard_shortcuts": "Klávesové zkratky",
|
||||||
"language": "Jazyk",
|
"language": "Jazyk",
|
||||||
"language_setting_description": "Vyberte upřednostňovaný jazyk",
|
"language_setting_description": "Vyberte upřednostňovaný jazyk",
|
||||||
@@ -850,31 +817,6 @@
|
|||||||
"level": "Úroveň",
|
"level": "Úroveň",
|
||||||
"library": "Knihovna",
|
"library": "Knihovna",
|
||||||
"library_options": "Možnosti knihovny",
|
"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ý",
|
"light": "Světlý",
|
||||||
"like_deleted": "Lajk smazán",
|
"like_deleted": "Lajk smazán",
|
||||||
"link_motion_video": "Připojit pohyblivé video",
|
"link_motion_video": "Připojit pohyblivé video",
|
||||||
@@ -974,13 +916,11 @@
|
|||||||
"oldest_first": "Nejstarší první",
|
"oldest_first": "Nejstarší první",
|
||||||
"onboarding": "Zahájení",
|
"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_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_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_description": "Nastavíme vaši instanci pomocí několika běžných nastavení.",
|
||||||
"onboarding_welcome_user": "Vítej, {user}",
|
"onboarding_welcome_user": "Vítej, {user}",
|
||||||
"online": "Online",
|
"online": "Online",
|
||||||
"only_favorites": "Pouze oblíbené",
|
"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_map_view": "Otevřít v zobrazení mapy",
|
||||||
"open_in_openstreetmap": "Otevřít v OpenStreetMap",
|
"open_in_openstreetmap": "Otevřít v OpenStreetMap",
|
||||||
"open_the_search_filters": "Otevřít vyhledávací filtry",
|
"open_the_search_filters": "Otevřít vyhledávací filtry",
|
||||||
@@ -997,7 +937,7 @@
|
|||||||
"partner_can_access": "{partner} má přístup",
|
"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_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_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",
|
"partners": "Partneři",
|
||||||
"password": "Heslo",
|
"password": "Heslo",
|
||||||
"password_does_not_match": "Heslo se neshoduje",
|
"password_does_not_match": "Heslo se neshoduje",
|
||||||
@@ -1018,14 +958,12 @@
|
|||||||
"people_edits_count": "Upraveno {count, plural, one {# osoba} few {# osoby} other {# lidí}}",
|
"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_feature_description": "Procházení fotografií a videí seskupených podle osob",
|
||||||
"people_sidebar_description": "Zobrazit sekci Lidé v postranním panelu",
|
"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": "Upozornění na trvalé smazání",
|
||||||
"permanent_deletion_warning_setting_description": "Zobrazit varování při trvalém odstranění položek",
|
"permanent_deletion_warning_setting_description": "Zobrazit varování při trvalém odstranění položek",
|
||||||
"permanently_delete": "Trvale odstranit",
|
"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 <b>#</b> položky} other {těchto <b>#</b> položek}}? Tím {count, plural, one {ji také odstraníte z jejích} other {je také odstraníte z jejich}} alb.",
|
"permanently_delete_assets_prompt": "Opravdu chcete trvale smazat {count, plural, one {tuto položku} few {tyto <b>#</b> položky} other {těchto <b>#</b> 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_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}}",
|
"permanently_deleted_assets_count": "{count, plural, one {Položka trvale vymazána} other {Položky trvale vymazány}}",
|
||||||
"person": "Osoba",
|
"person": "Osoba",
|
||||||
"person_hidden": "{name}{hidden, select, true { (skryto)} other {}}",
|
"person_hidden": "{name}{hidden, select, true { (skryto)} other {}}",
|
||||||
@@ -1041,7 +979,6 @@
|
|||||||
"play_memories": "Přehrát vzpomníky",
|
"play_memories": "Přehrát vzpomníky",
|
||||||
"play_motion_photo": "Přehrát pohybovou fotografii",
|
"play_motion_photo": "Přehrát pohybovou fotografii",
|
||||||
"play_or_pause_video": "Přehrát nebo pozastavit video",
|
"play_or_pause_video": "Přehrát nebo pozastavit video",
|
||||||
"point": "Bod",
|
|
||||||
"port": "Port",
|
"port": "Port",
|
||||||
"preset": "Přednastavení",
|
"preset": "Přednastavení",
|
||||||
"preview": "Náhled",
|
"preview": "Náhled",
|
||||||
@@ -1065,19 +1002,19 @@
|
|||||||
"purchase_button_reminder": "Připomenout za 30 dní",
|
"purchase_button_reminder": "Připomenout za 30 dní",
|
||||||
"purchase_button_remove_key": "Odstranit klíč",
|
"purchase_button_remove_key": "Odstranit klíč",
|
||||||
"purchase_button_select": "Vybrat",
|
"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_1": "Pro jednotlivce",
|
||||||
"purchase_individual_description_2": "Stav podporovatele",
|
"purchase_individual_description_2": "Stav podporovatele",
|
||||||
"purchase_individual_title": "Individuální",
|
"purchase_individual_title": "Individuální",
|
||||||
"purchase_input_suggestion": "Máte produktový klíč? Zadejte klíč níže",
|
"purchase_input_suggestion": "Máte produktový klíč? Zadejte ho níže",
|
||||||
"purchase_license_subtitle": "Koupit Immich na podporu dalšího rozvoje služby",
|
"purchase_license_subtitle": "Koupit Immich a podpořit další rozvoj služby",
|
||||||
"purchase_lifetime_description": "Doživotní platnost",
|
"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_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_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_panel_title": "Podpořit projekt",
|
||||||
"purchase_per_server": "Na server",
|
"purchase_per_server": "Za server",
|
||||||
"purchase_per_user": "Na uživatele",
|
"purchase_per_user": "Za uživatele",
|
||||||
"purchase_remove_product_key": "Odstranění produktového klíče",
|
"purchase_remove_product_key": "Odstranění produktového klíče",
|
||||||
"purchase_remove_product_key_prompt": "Opravdu chcete odebrat produktový klíč?",
|
"purchase_remove_product_key_prompt": "Opravdu chcete odebrat produktový klíč?",
|
||||||
"purchase_remove_server_product_key": "Odstranění serverového produktového klíče",
|
"purchase_remove_server_product_key": "Odstranění serverového produktového klíče",
|
||||||
@@ -1086,12 +1023,10 @@
|
|||||||
"purchase_server_description_2": "Stav podporovatele",
|
"purchase_server_description_2": "Stav podporovatele",
|
||||||
"purchase_server_title": "Server",
|
"purchase_server_title": "Server",
|
||||||
"purchase_settings_server_activated": "Produktový klíč serveru spravuje správce",
|
"purchase_settings_server_activated": "Produktový klíč serveru spravuje správce",
|
||||||
"range": "Rozsah",
|
|
||||||
"rating": "Hodnocení hvězdičkami",
|
"rating": "Hodnocení hvězdičkami",
|
||||||
"rating_clear": "Vyčistit hodnocení",
|
"rating_clear": "Vyčistit hodnocení",
|
||||||
"rating_count": "{count, plural, one {# hvězdička} few {# hvězdičky} other {# hvězdček}}",
|
"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",
|
"rating_description": "Zobrazit EXIF hodnocení v informačním panelu",
|
||||||
"raw": "Raw",
|
|
||||||
"reaction_options": "Možnosti reakce",
|
"reaction_options": "Možnosti reakce",
|
||||||
"read_changelog": "Přečtěte si seznam změn",
|
"read_changelog": "Přečtěte si seznam změn",
|
||||||
"reassign": "Přeřadit",
|
"reassign": "Přeřadit",
|
||||||
@@ -1099,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",
|
"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ě",
|
"reassing_hint": "Přiřazení vybraných položek existující osobě",
|
||||||
"recent": "Nedávné",
|
"recent": "Nedávné",
|
||||||
|
"recent-albums": "Nedávná alba",
|
||||||
"recent_searches": "Nedávná vyhledávání",
|
"recent_searches": "Nedávná vyhledávání",
|
||||||
"refresh": "Obnovit",
|
"refresh": "Obnovit",
|
||||||
"refresh_encoded_videos": "Obnovit kódovaná videa",
|
"refresh_encoded_videos": "Obnovit kódovaná videa",
|
||||||
@@ -1120,6 +1056,7 @@
|
|||||||
"remove_from_album": "Odstranit z alba",
|
"remove_from_album": "Odstranit z alba",
|
||||||
"remove_from_favorites": "Odstranit z oblíbených",
|
"remove_from_favorites": "Odstranit z oblíbených",
|
||||||
"remove_from_shared_link": "Odstranit ze sdíleného odkazu",
|
"remove_from_shared_link": "Odstranit ze sdíleného odkazu",
|
||||||
|
"remove_url": "Odstranit URL",
|
||||||
"remove_user": "Odebrat uživatele",
|
"remove_user": "Odebrat uživatele",
|
||||||
"removed_api_key": "Odstraněn API klíč: {name}",
|
"removed_api_key": "Odstraněn API klíč: {name}",
|
||||||
"removed_from_archive": "Odstraněno z archivu",
|
"removed_from_archive": "Odstraněno z archivu",
|
||||||
@@ -1136,7 +1073,6 @@
|
|||||||
"reset": "Výchozí",
|
"reset": "Výchozí",
|
||||||
"reset_password": "Obnovit heslo",
|
"reset_password": "Obnovit heslo",
|
||||||
"reset_people_visibility": "Obnovit viditelnost lidí",
|
"reset_people_visibility": "Obnovit viditelnost lidí",
|
||||||
"reset_settings_to_default": "Obnovit výchozí nastavení",
|
|
||||||
"reset_to_default": "Obnovit výchozí nastavení",
|
"reset_to_default": "Obnovit výchozí nastavení",
|
||||||
"resolve_duplicates": "Vyřešit duplicity",
|
"resolve_duplicates": "Vyřešit duplicity",
|
||||||
"resolved_all_duplicates": "Vyřešeny všechny duplicity",
|
"resolved_all_duplicates": "Vyřešeny všechny duplicity",
|
||||||
@@ -1156,9 +1092,7 @@
|
|||||||
"saved_settings": "Nastavení uloženo",
|
"saved_settings": "Nastavení uloženo",
|
||||||
"say_something": "Řekněte něco",
|
"say_something": "Řekněte něco",
|
||||||
"scan_all_libraries": "Prohledat všechny knihovny",
|
"scan_all_libraries": "Prohledat všechny knihovny",
|
||||||
"scan_all_library_files": "Prohledání všech souborů knihovny",
|
|
||||||
"scan_library": "Prohledat",
|
"scan_library": "Prohledat",
|
||||||
"scan_new_library_files": "Hledat nové soubory v knihovně",
|
|
||||||
"scan_settings": "Nastavení prohledávání",
|
"scan_settings": "Nastavení prohledávání",
|
||||||
"scanning_for_album": "Prohledávání alba...",
|
"scanning_for_album": "Prohledávání alba...",
|
||||||
"search": "Hledat",
|
"search": "Hledat",
|
||||||
@@ -1201,7 +1135,6 @@
|
|||||||
"selected_count": "{count, plural, one {# vybraný} few {# vybrané} other {# vybraných}}",
|
"selected_count": "{count, plural, one {# vybraný} few {# vybrané} other {# vybraných}}",
|
||||||
"send_message": "Odeslat zprávu",
|
"send_message": "Odeslat zprávu",
|
||||||
"send_welcome_email": "Poslat uvítací e-mail",
|
"send_welcome_email": "Poslat uvítací e-mail",
|
||||||
"server": "Server",
|
|
||||||
"server_offline": "Server offline",
|
"server_offline": "Server offline",
|
||||||
"server_online": "Server online",
|
"server_online": "Server online",
|
||||||
"server_stats": "Statistiky serveru",
|
"server_stats": "Statistiky serveru",
|
||||||
@@ -1306,17 +1239,17 @@
|
|||||||
"they_will_be_merged_together": "Budou sloučeny dohromady",
|
"they_will_be_merged_together": "Budou sloučeny dohromady",
|
||||||
"third_party_resources": "Zdroje třetích stran",
|
"third_party_resources": "Zdroje třetích stran",
|
||||||
"time_based_memories": "Časové vzpomínky",
|
"time_based_memories": "Časové vzpomínky",
|
||||||
|
"timeline": "Časová osa",
|
||||||
"timezone": "Časové pásmo",
|
"timezone": "Časové pásmo",
|
||||||
"to_archive": "Archivovat",
|
"to_archive": "Archivovat",
|
||||||
"to_change_password": "Změnit heslo",
|
"to_change_password": "Změnit heslo",
|
||||||
"to_favorite": "Oblíbit",
|
"to_favorite": "Oblíbit",
|
||||||
"to_login": "Přihlásit",
|
"to_login": "Přihlásit",
|
||||||
"to_parent": "Přejít k rodiči",
|
"to_parent": "Přejít k rodiči",
|
||||||
"to_root": "Přejít ke kořenu",
|
|
||||||
"to_trash": "Vyhodit",
|
"to_trash": "Vyhodit",
|
||||||
"toggle_settings": "Přepnout nastavení",
|
"toggle_settings": "Přepnout nastavení",
|
||||||
"toggle_theme": "Přepnout tmavý motiv",
|
"toggle_theme": "Přepnout tmavý motiv",
|
||||||
"toggle_visibility": "Přepnout viditelnost",
|
"total": "Celkem",
|
||||||
"total_usage": "Celkové využití",
|
"total_usage": "Celkové využití",
|
||||||
"trash": "Koš",
|
"trash": "Koš",
|
||||||
"trash_all": "Vyhodit vše",
|
"trash_all": "Vyhodit vše",
|
||||||
@@ -1326,12 +1259,10 @@
|
|||||||
"trashed_items_will_be_permanently_deleted_after": "Smazané položky budou trvale odstraněny po {days, plural, one {# dni} other {# dnech}}.",
|
"trashed_items_will_be_permanently_deleted_after": "Smazané položky budou trvale odstraněny po {days, plural, one {# dni} other {# dnech}}.",
|
||||||
"type": "Typ",
|
"type": "Typ",
|
||||||
"unarchive": "Odarchivovat",
|
"unarchive": "Odarchivovat",
|
||||||
"unarchived": "Odarchivováno",
|
|
||||||
"unarchived_count": "{count, plural, one {Odarchivována #} few {Odarchivovány #} other {Odarchivováno #}}",
|
"unarchived_count": "{count, plural, one {Odarchivována #} few {Odarchivovány #} other {Odarchivováno #}}",
|
||||||
"unfavorite": "Zrušit oblíbení",
|
"unfavorite": "Zrušit oblíbení",
|
||||||
"unhide_person": "Zrušit skrytí osoby",
|
"unhide_person": "Zrušit skrytí osoby",
|
||||||
"unknown": "Neznámý",
|
"unknown": "Neznámý",
|
||||||
"unknown_album": "Neznámé album",
|
|
||||||
"unknown_year": "Neznámý rok",
|
"unknown_year": "Neznámý rok",
|
||||||
"unlimited": "Neomezeně",
|
"unlimited": "Neomezeně",
|
||||||
"unlink_motion_video": "Odpojit pohyblivé video",
|
"unlink_motion_video": "Odpojit pohyblivé video",
|
||||||
@@ -1339,7 +1270,7 @@
|
|||||||
"unlinked_oauth_account": "OAuth účet odpojen",
|
"unlinked_oauth_account": "OAuth účet odpojen",
|
||||||
"unnamed_album": "Nepojmenované album",
|
"unnamed_album": "Nepojmenované album",
|
||||||
"unnamed_album_delete_confirmation": "Opravdu chcete toto album smazat?",
|
"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",
|
"unsaved_change": "Neuložená změna",
|
||||||
"unselect_all": "Zrušit výběr všech",
|
"unselect_all": "Zrušit výběr všech",
|
||||||
"unselect_all_duplicates": "Zrušit výběr všech duplicit",
|
"unselect_all_duplicates": "Zrušit výběr všech duplicit",
|
||||||
@@ -1363,13 +1294,13 @@
|
|||||||
"use_custom_date_range": "Použít vlastní rozsah dat",
|
"use_custom_date_range": "Použít vlastní rozsah dat",
|
||||||
"user": "Uživatel",
|
"user": "Uživatel",
|
||||||
"user_id": "ID uživatele",
|
"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_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": "Nákup",
|
||||||
"user_purchase_settings_description": "Správa vašeho nákupu",
|
"user_purchase_settings_description": "Správa vašeho nákupu",
|
||||||
"user_role_set": "Uživatel {user} nastaven jako {role}",
|
"user_role_set": "Uživatel {user} nastaven jako {role}",
|
||||||
"user_usage_detail": "Podrobnosti využití uživatelů",
|
"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",
|
"username": "Uživateleské jméno",
|
||||||
"users": "Uživatelé",
|
"users": "Uživatelé",
|
||||||
"utilities": "Nástroje",
|
"utilities": "Nástroje",
|
||||||
@@ -1377,7 +1308,7 @@
|
|||||||
"variables": "Proměnné",
|
"variables": "Proměnné",
|
||||||
"version": "Verze",
|
"version": "Verze",
|
||||||
"version_announcement_closing": "Váš přítel Alex",
|
"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í <link>poznámek k vydání</link> a zajisti si, aby <code>docker-compose.yml</code> a nastavení <code>.env</code> 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í <link>poznámek k vydání</link> 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": "Historie verzí",
|
||||||
"version_history_item": "Nainstalováno {version} dne {date}",
|
"version_history_item": "Nainstalováno {version} dne {date}",
|
||||||
"video": "Video",
|
"video": "Video",
|
||||||
@@ -1391,10 +1322,10 @@
|
|||||||
"view_all_users": "Zobrazit všechny uživatele",
|
"view_all_users": "Zobrazit všechny uživatele",
|
||||||
"view_in_timeline": "Zobrazit na časové ose",
|
"view_in_timeline": "Zobrazit na časové ose",
|
||||||
"view_links": "Zobrazit odkazy",
|
"view_links": "Zobrazit odkazy",
|
||||||
|
"view_name": "Zobrazit",
|
||||||
"view_next_asset": "Zobrazit další položku",
|
"view_next_asset": "Zobrazit další položku",
|
||||||
"view_previous_asset": "Zobrazit předchozí položku",
|
"view_previous_asset": "Zobrazit předchozí položku",
|
||||||
"view_stack": "Zobrazit seskupení",
|
"view_stack": "Zobrazit seskupení",
|
||||||
"viewer": "Prohlížeč",
|
|
||||||
"visibility_changed": "Viditelnost změněna u {count, plural, one {# osoby} few {# osob} other {# lidí}}",
|
"visibility_changed": "Viditelnost změněna u {count, plural, one {# osoby} few {# osob} other {# lidí}}",
|
||||||
"waiting": "Čekající",
|
"waiting": "Čekající",
|
||||||
"warning": "Upozornění",
|
"warning": "Upozornění",
|
||||||
|
|||||||
@@ -23,6 +23,7 @@
|
|||||||
"add_to": "Мӗн те пулин хуш...",
|
"add_to": "Мӗн те пулин хуш...",
|
||||||
"add_to_album": "Альбома хуш",
|
"add_to_album": "Альбома хуш",
|
||||||
"add_to_shared_album": "Пӗрлехи альбома хуш",
|
"add_to_shared_album": "Пӗрлехи альбома хуш",
|
||||||
|
"add_url": "URL хушӑр",
|
||||||
"added_to_archive": "Архива хушнӑ",
|
"added_to_archive": "Архива хушнӑ",
|
||||||
"added_to_favorites": "Суйласа илнине хушнӑ",
|
"added_to_favorites": "Суйласа илнине хушнӑ",
|
||||||
"added_to_favorites_count": "Суйласа илнине {count, number} хушнӑ",
|
"added_to_favorites_count": "Суйласа илнине {count, number} хушнӑ",
|
||||||
@@ -45,5 +46,7 @@
|
|||||||
"image_preview_title": "Малтанлӑха пӑхмалли ӗнерлевсем",
|
"image_preview_title": "Малтанлӑха пӑхмалли ӗнерлевсем",
|
||||||
"image_quality": "Пахалӑх",
|
"image_quality": "Пахалӑх",
|
||||||
"image_resolution": "Виҫе"
|
"image_resolution": "Виҫе"
|
||||||
}
|
},
|
||||||
|
"user_usage_stats": "Шута ҫырни усӑ курмалли статистика",
|
||||||
|
"user_usage_stats_description": "Шута ҫырни усӑ курмалли статистикӑна пӑхасси"
|
||||||
}
|
}
|
||||||
|
|||||||
71
i18n/da.json
@@ -2,12 +2,12 @@
|
|||||||
"about": "Om",
|
"about": "Om",
|
||||||
"account": "Konto",
|
"account": "Konto",
|
||||||
"account_settings": "Kontoindstillinger",
|
"account_settings": "Kontoindstillinger",
|
||||||
"acknowledge": "Anerkend",
|
"acknowledge": "Godkend",
|
||||||
"action": "Handling",
|
"action": "Handling",
|
||||||
"actions": "Handlinger",
|
"actions": "Handlinger",
|
||||||
"active": "Aktive",
|
"active": "Aktive",
|
||||||
"activity": "Aktivitet",
|
"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": "Tilføj",
|
||||||
"add_a_description": "Tilføj en beskrivelse",
|
"add_a_description": "Tilføj en beskrivelse",
|
||||||
"add_a_location": "Tilføj en placering",
|
"add_a_location": "Tilføj en placering",
|
||||||
@@ -23,11 +23,13 @@
|
|||||||
"add_to": "Tilføj til...",
|
"add_to": "Tilføj til...",
|
||||||
"add_to_album": "Tilføj til album",
|
"add_to_album": "Tilføj til album",
|
||||||
"add_to_shared_album": "Tilføj til delt album",
|
"add_to_shared_album": "Tilføj til delt album",
|
||||||
|
"add_url": "Tilføj URL",
|
||||||
"added_to_archive": "Tilføjet til arkiv",
|
"added_to_archive": "Tilføjet til arkiv",
|
||||||
"added_to_favorites": "Tilføjet til favoritter",
|
"added_to_favorites": "Tilføjet til favoritter",
|
||||||
"added_to_favorites_count": "Tilføjet {count, number} til favoritter",
|
"added_to_favorites_count": "Tilføjet {count, number} til favoritter",
|
||||||
"admin": {
|
"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/**\".",
|
"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": "Godkendelsesindstillinger",
|
||||||
"authentication_settings_description": "Administrer adgangskode, OAuth og andre 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_disable_all": "Er du sikker på at du vil deaktivere alle loginmuligheder? Login vil blive helt deaktiveret.",
|
||||||
@@ -47,9 +49,9 @@
|
|||||||
"confirm_reprocess_all_faces": "Er du sikker på, at du vil genbehandle alle ansigter? Dette vil også rydde navngivne personer.",
|
"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?",
|
"confirm_user_password_reset": "Er du sikker på, at du vil nulstille {user}s adgangskode?",
|
||||||
"create_job": "Opret job",
|
"create_job": "Opret job",
|
||||||
"crontab_guru": "Crontab Guru",
|
"cron_expression": "Cron formel",
|
||||||
|
"cron_expression_description": "Indstil skannings intervallet i cron format. For mere information se: <link>Crontab Guru</link>",
|
||||||
"disable_login": "Deaktiver login",
|
"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",
|
"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.",
|
"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})",
|
"external_library_created_at": "Eksternt bibliotek (oprettet {date})",
|
||||||
@@ -67,19 +69,12 @@
|
|||||||
"image_prefer_wide_gamut": "Foretrækker bred farveskala",
|
"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_prefer_wide_gamut_setting_description": "Brug Display P3 til miniaturebilleder. Dette bevarer billeder med brede farveskalaers dynamik bedre, men billeder kan komme til at se anderledes ud på gamle enheder med en gammel browserversion. sRGB-billeder bliver beholdt som sRGB for at undgå farveskift.",
|
||||||
"image_preview_description": "Mellemstørrelse billede med fjernet metadata, der bruges, når du ser en enkelt mediefil og til machine learning",
|
"image_preview_description": "Mellemstørrelse billede med fjernet metadata, der bruges, når du ser en enkelt mediefil og til machine learning",
|
||||||
"image_preview_format": "Forhåndsvisningsformat",
|
|
||||||
"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_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_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_title": "Indstillinger for forhåndsvisning",
|
"image_preview_title": "Indstillinger for forhåndsvisning",
|
||||||
"image_quality": "Kvalitet",
|
"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_resolution": "Opløsning",
|
||||||
"image_settings": "Billedindstillinger",
|
"image_settings": "Billedindstillinger",
|
||||||
"image_settings_description": "Administrer kvaliteten og opløsningen af genererede billeder",
|
"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",
|
"image_thumbnail_title": "Thumbnail-indstillinger",
|
||||||
"job_concurrency": "{job} samtidighed",
|
"job_concurrency": "{job} samtidighed",
|
||||||
"job_not_concurrency_safe": "Denne opgave er ikke sikker at køre samtidigt med andre.",
|
"job_not_concurrency_safe": "Denne opgave er ikke sikker at køre samtidigt med andre.",
|
||||||
@@ -89,9 +84,6 @@
|
|||||||
"jobs_delayed": "{jobCount, plural, one {# forsinket} other {# forsinkede}}",
|
"jobs_delayed": "{jobCount, plural, one {# forsinket} other {# forsinkede}}",
|
||||||
"jobs_failed": "{jobCount, plural, one {# fejlet} other {# fejlede}}",
|
"jobs_failed": "{jobCount, plural, one {# fejlet} other {# fejlede}}",
|
||||||
"library_created": "Skabte bibliotek: {library}",
|
"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 <link>Crontab Guru</link>",
|
|
||||||
"library_cron_expression_presets": "Cron-udtryksforudindstillinger",
|
|
||||||
"library_deleted": "Bibliotek slettet",
|
"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_import_path_description": "Angiv en mappe, der skal importeres. Denne mappe, inklusive undermapper, vil blive scannet for billeder og videoer.",
|
||||||
"library_scanning": "Periodisk scanning",
|
"library_scanning": "Periodisk scanning",
|
||||||
@@ -215,7 +207,6 @@
|
|||||||
"refreshing_all_libraries": "Opdaterer alle biblioteker",
|
"refreshing_all_libraries": "Opdaterer alle biblioteker",
|
||||||
"registration": "Administratorregistrering",
|
"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.",
|
"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_all": "Reparér alle",
|
||||||
"repair_matched_items": "Har parret {count, plural, one {# element} other {# elementer}}",
|
"repair_matched_items": "Har parret {count, plural, one {# element} other {# elementer}}",
|
||||||
"repaired_items": "Reparerede {count, plural, one {# element} other {# elementer}}",
|
"repaired_items": "Reparerede {count, plural, one {# element} other {# elementer}}",
|
||||||
@@ -223,8 +214,6 @@
|
|||||||
"reset_settings_to_default": "Nulstil indstillingerne til standard",
|
"reset_settings_to_default": "Nulstil indstillingerne til standard",
|
||||||
"reset_settings_to_recent_saved": "Nulstil indstillinger til de senest gemte indstillinger",
|
"reset_settings_to_recent_saved": "Nulstil indstillinger til de senest gemte indstillinger",
|
||||||
"scanning_library": "Scanner bibliotek",
|
"scanning_library": "Scanner bibliotek",
|
||||||
"scanning_library_for_changed_files": "Skanner bibliotek efter ændrede filer",
|
|
||||||
"scanning_library_for_new_files": "Skanner bibliotek efter nye filer",
|
|
||||||
"send_welcome_email": "Send velkomst-email",
|
"send_welcome_email": "Send velkomst-email",
|
||||||
"server_external_domain_settings": "Eksternt domæne",
|
"server_external_domain_settings": "Eksternt domæne",
|
||||||
"server_external_domain_settings_description": "Domæne til offentligt delte links, inklusiv http(s)://",
|
"server_external_domain_settings_description": "Domæne til offentligt delte links, inklusiv http(s)://",
|
||||||
@@ -259,7 +248,6 @@
|
|||||||
"these_files_matched_by_checksum": "Disse filer er blevet matchet med deres checksummer",
|
"these_files_matched_by_checksum": "Disse filer er blevet matchet med deres checksummer",
|
||||||
"thumbnail_generation_job": "Generér miniaturebilleder",
|
"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",
|
"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": "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_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)",
|
"transcoding_acceleration_nvenc": "NVENC (kræver NVIDIA GPU)",
|
||||||
@@ -311,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_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": "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_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": "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_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",
|
"transcoding_two_pass_encoding": "To-omgangsindkodning",
|
||||||
@@ -393,7 +379,6 @@
|
|||||||
"archive_or_unarchive_photo": "Arkivér eller dearkivér billede",
|
"archive_or_unarchive_photo": "Arkivér eller dearkivér billede",
|
||||||
"archive_size": "Arkiv størelse",
|
"archive_size": "Arkiv størelse",
|
||||||
"archive_size_description": "Konfigurer arkivstørrelsen for downloads (i GiB)",
|
"archive_size_description": "Konfigurer arkivstørrelsen for downloads (i GiB)",
|
||||||
"archived": "Arkiveret",
|
|
||||||
"are_these_the_same_person": "Er disse den samme person?",
|
"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?",
|
"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_added_to_album": "Tilføjet til album",
|
||||||
@@ -424,10 +409,6 @@
|
|||||||
"cannot_merge_people": "Kan ikke sammenflette personer",
|
"cannot_merge_people": "Kan ikke sammenflette personer",
|
||||||
"cannot_undo_this_action": "Du kan ikke fortryde denne handling!",
|
"cannot_undo_this_action": "Du kan ikke fortryde denne handling!",
|
||||||
"cannot_update_the_description": "Kan ikke opdatere beskrivelsen",
|
"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_date": "Ændr dato",
|
||||||
"change_expiration_time": "Ændr udløbstidspunkt",
|
"change_expiration_time": "Ændr udløbstidspunkt",
|
||||||
"change_location": "Ændr sted",
|
"change_location": "Ændr sted",
|
||||||
@@ -526,13 +507,6 @@
|
|||||||
"downloading": "Downloader",
|
"downloading": "Downloader",
|
||||||
"duplicates": "Duplikater",
|
"duplicates": "Duplikater",
|
||||||
"duration": "Varighed",
|
"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": "Rediger",
|
||||||
"edit_album": "Redigér album",
|
"edit_album": "Redigér album",
|
||||||
"edit_avatar": "Redigér avatar",
|
"edit_avatar": "Redigér avatar",
|
||||||
@@ -555,8 +529,6 @@
|
|||||||
"editor_close_without_save_title": "Luk editor?",
|
"editor_close_without_save_title": "Luk editor?",
|
||||||
"editor_crop_tool_h2_rotation": "Rotation",
|
"editor_crop_tool_h2_rotation": "Rotation",
|
||||||
"email": "E-mail",
|
"email": "E-mail",
|
||||||
"empty": "",
|
|
||||||
"empty_album": "Tomt album",
|
|
||||||
"empty_trash": "Tøm papirkurv",
|
"empty_trash": "Tøm papirkurv",
|
||||||
"enable": "Aktivér",
|
"enable": "Aktivér",
|
||||||
"enabled": "Aktiveret",
|
"enabled": "Aktiveret",
|
||||||
@@ -598,8 +570,6 @@
|
|||||||
"unable_to_change_date": "Ikke i stand til at ændre dato",
|
"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_location": "Ikke i stand til at ændre sted",
|
||||||
"unable_to_change_password": "Kunne ikke ændre adgangskode",
|
"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_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_admin_account": "",
|
||||||
"unable_to_create_api_key": "Kunne ikke oprette ny API-nøgle",
|
"unable_to_create_api_key": "Kunne ikke oprette ny API-nøgle",
|
||||||
@@ -627,12 +597,10 @@
|
|||||||
"unable_to_refresh_user": "Ikke i stand til at genopfriske bruger",
|
"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_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_api_key": "Kunne ikke fjerne API-nøgle",
|
||||||
"unable_to_remove_comment": "",
|
|
||||||
"unable_to_remove_deleted_assets": "Kunne ikke fjerne offlinefiler",
|
"unable_to_remove_deleted_assets": "Kunne ikke fjerne offlinefiler",
|
||||||
"unable_to_remove_library": "Ikke i stand til at fjerne bibliotek",
|
"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_partner": "Ikke i stand til at fjerne partner",
|
||||||
"unable_to_remove_reaction": "Ikke i stand til at reaktion",
|
"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_repair_items": "Ikke i stand til at reparere ting",
|
||||||
"unable_to_reset_password": "Ikke i stand til at nulstille adgangskode",
|
"unable_to_reset_password": "Ikke i stand til at nulstille adgangskode",
|
||||||
"unable_to_resolve_duplicate": "Kunne ikke opklare duplikat",
|
"unable_to_resolve_duplicate": "Kunne ikke opklare duplikat",
|
||||||
@@ -656,10 +624,6 @@
|
|||||||
"unable_to_update_timeline_display_status": "Kunne ikke opdate status for tidslinjevisning",
|
"unable_to_update_timeline_display_status": "Kunne ikke opdate status for tidslinjevisning",
|
||||||
"unable_to_update_user": "Ikke i stand til at opdatere bruger"
|
"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",
|
"exif": "Exif",
|
||||||
"exit_slideshow": "Forlad slideshow",
|
"exit_slideshow": "Forlad slideshow",
|
||||||
"expand_all": "Udvid alle",
|
"expand_all": "Udvid alle",
|
||||||
@@ -672,32 +636,26 @@
|
|||||||
"extension": "Udvidelse",
|
"extension": "Udvidelse",
|
||||||
"external": "Ekstern",
|
"external": "Ekstern",
|
||||||
"external_libraries": "Eksterne biblioteker",
|
"external_libraries": "Eksterne biblioteker",
|
||||||
"failed_to_get_people": "At hente personer slog fejl",
|
|
||||||
"favorite": "Favorit",
|
"favorite": "Favorit",
|
||||||
"favorite_or_unfavorite_photo": "Tilføj eller fjern fra yndlingsbilleder",
|
"favorite_or_unfavorite_photo": "Tilføj eller fjern fra yndlingsbilleder",
|
||||||
"favorites": "Favoritter",
|
"favorites": "Favoritter",
|
||||||
"feature": "",
|
|
||||||
"feature_photo_updated": "Forsidebillede uploadet",
|
"feature_photo_updated": "Forsidebillede uploadet",
|
||||||
"featurecollection": "",
|
|
||||||
"features": "Funktioner",
|
"features": "Funktioner",
|
||||||
"features_setting_description": "Administrer app-funktioner",
|
"features_setting_description": "Administrer app-funktioner",
|
||||||
"file_name": "Filnavn",
|
"file_name": "Filnavn",
|
||||||
"file_name_or_extension": "Filnavn eller filtype",
|
"file_name_or_extension": "Filnavn eller filtype",
|
||||||
"filename": "Filnavn",
|
"filename": "Filnavn",
|
||||||
"files": "",
|
|
||||||
"filetype": "Filtype",
|
"filetype": "Filtype",
|
||||||
"filter_people": "Filtrér personer",
|
"filter_people": "Filtrér personer",
|
||||||
"find_them_fast": "Find dem hurtigt med søgning via navn",
|
"find_them_fast": "Find dem hurtigt med søgning via navn",
|
||||||
"fix_incorrect_match": "Fix forkert match",
|
"fix_incorrect_match": "Fix forkert match",
|
||||||
"folders": "Mapper",
|
"folders": "Mapper",
|
||||||
"force_re-scan_library_files": "Tving genskanning af alle biblioteksfiler",
|
|
||||||
"forward": "Fremad",
|
"forward": "Fremad",
|
||||||
"general": "Generel",
|
"general": "Generel",
|
||||||
"get_help": "Få hjælp",
|
"get_help": "Få hjælp",
|
||||||
"getting_started": "Kom godt i gang",
|
"getting_started": "Kom godt i gang",
|
||||||
"go_back": "Gå tilbage",
|
"go_back": "Gå tilbage",
|
||||||
"go_to_search": "Gå til søgning",
|
"go_to_search": "Gå til søgning",
|
||||||
"go_to_share_page": "Gå til delingsside",
|
|
||||||
"group_albums_by": "Gruppér albummer efter...",
|
"group_albums_by": "Gruppér albummer efter...",
|
||||||
"group_no": "Ingen gruppering",
|
"group_no": "Ingen gruppering",
|
||||||
"has_quota": "Har kvote",
|
"has_quota": "Har kvote",
|
||||||
@@ -711,7 +669,6 @@
|
|||||||
"host": "Host",
|
"host": "Host",
|
||||||
"hour": "Time",
|
"hour": "Time",
|
||||||
"image": "Billede",
|
"image": "Billede",
|
||||||
"img": "",
|
|
||||||
"immich_logo": "Immich logo",
|
"immich_logo": "Immich logo",
|
||||||
"immich_web_interface": "Immich webinterface",
|
"immich_web_interface": "Immich webinterface",
|
||||||
"import_from_json": "Importér fra JSON",
|
"import_from_json": "Importér fra JSON",
|
||||||
@@ -730,7 +687,6 @@
|
|||||||
},
|
},
|
||||||
"invite_people": "Inviter personer",
|
"invite_people": "Inviter personer",
|
||||||
"invite_to_album": "Inviter til album",
|
"invite_to_album": "Inviter til album",
|
||||||
"job_settings_description": "",
|
|
||||||
"jobs": "Opgaver",
|
"jobs": "Opgaver",
|
||||||
"keep": "Behold",
|
"keep": "Behold",
|
||||||
"keep_all": "Behold alle",
|
"keep_all": "Behold alle",
|
||||||
@@ -835,7 +791,6 @@
|
|||||||
"onboarding_welcome_user": "Velkommen, {user}",
|
"onboarding_welcome_user": "Velkommen, {user}",
|
||||||
"online": "Online",
|
"online": "Online",
|
||||||
"only_favorites": "Kun favoritter",
|
"only_favorites": "Kun favoritter",
|
||||||
"only_refreshes_modified_files": "Kun genopfrisk ændrede filer",
|
|
||||||
"open_in_map_view": "Åben i kortvisning",
|
"open_in_map_view": "Åben i kortvisning",
|
||||||
"open_in_openstreetmap": "Åben i OpenStreetMap",
|
"open_in_openstreetmap": "Åben i OpenStreetMap",
|
||||||
"open_the_search_filters": "Åbn søgefiltre",
|
"open_the_search_filters": "Åbn søgefiltre",
|
||||||
@@ -870,7 +825,6 @@
|
|||||||
"pending": "Afventer",
|
"pending": "Afventer",
|
||||||
"people": "Personer",
|
"people": "Personer",
|
||||||
"people_sidebar_description": "Vis et link til Personer i sidepanelet",
|
"people_sidebar_description": "Vis et link til Personer i sidepanelet",
|
||||||
"perform_library_tasks": "",
|
|
||||||
"permanent_deletion_warning": "Advarsel om permanent sletning",
|
"permanent_deletion_warning": "Advarsel om permanent sletning",
|
||||||
"permanent_deletion_warning_setting_description": "Vis en advarsel, når medier slettes permanent",
|
"permanent_deletion_warning_setting_description": "Vis en advarsel, når medier slettes permanent",
|
||||||
"permanently_delete": "Slet permanent",
|
"permanently_delete": "Slet permanent",
|
||||||
@@ -886,7 +840,6 @@
|
|||||||
"play_memories": "Afspil minder",
|
"play_memories": "Afspil minder",
|
||||||
"play_motion_photo": "Afspil bevægelsesbillede",
|
"play_motion_photo": "Afspil bevægelsesbillede",
|
||||||
"play_or_pause_video": "Afspil eller paus video",
|
"play_or_pause_video": "Afspil eller paus video",
|
||||||
"point": "",
|
|
||||||
"port": "Port",
|
"port": "Port",
|
||||||
"preset": "Forudindstilling",
|
"preset": "Forudindstilling",
|
||||||
"preview": "Forhåndsvisning",
|
"preview": "Forhåndsvisning",
|
||||||
@@ -896,8 +849,6 @@
|
|||||||
"primary": "Primære",
|
"primary": "Primære",
|
||||||
"profile_picture_set": "Profilbillede sat.",
|
"profile_picture_set": "Profilbillede sat.",
|
||||||
"public_share": "Offentlig deling",
|
"public_share": "Offentlig deling",
|
||||||
"range": "",
|
|
||||||
"raw": "",
|
|
||||||
"reaction_options": "Reaktionsindstillinger",
|
"reaction_options": "Reaktionsindstillinger",
|
||||||
"read_changelog": "Læs ændringslog",
|
"read_changelog": "Læs ændringslog",
|
||||||
"recent": "For nylig",
|
"recent": "For nylig",
|
||||||
@@ -920,7 +871,6 @@
|
|||||||
"reset": "Nulstil",
|
"reset": "Nulstil",
|
||||||
"reset_password": "Nulstil adgangskode",
|
"reset_password": "Nulstil adgangskode",
|
||||||
"reset_people_visibility": "Nulstil personsynlighed",
|
"reset_people_visibility": "Nulstil personsynlighed",
|
||||||
"reset_settings_to_default": "",
|
|
||||||
"restore": "Gendan",
|
"restore": "Gendan",
|
||||||
"restore_all": "Gendan alle",
|
"restore_all": "Gendan alle",
|
||||||
"restore_user": "Gendan bruger",
|
"restore_user": "Gendan bruger",
|
||||||
@@ -934,8 +884,6 @@
|
|||||||
"saved_settings": "Gemte indstillinger",
|
"saved_settings": "Gemte indstillinger",
|
||||||
"say_something": "Skriv noget",
|
"say_something": "Skriv noget",
|
||||||
"scan_all_libraries": "Skan gennem alle biblioteker",
|
"scan_all_libraries": "Skan gennem alle biblioteker",
|
||||||
"scan_all_library_files": "Genskan alle biblioteksfiler",
|
|
||||||
"scan_new_library_files": "Skan nye biblioteksfiler",
|
|
||||||
"scan_settings": "Skanningsindstillinger",
|
"scan_settings": "Skanningsindstillinger",
|
||||||
"search": "Søg",
|
"search": "Søg",
|
||||||
"search_albums": "Søg i albummer",
|
"search_albums": "Søg i albummer",
|
||||||
@@ -966,7 +914,6 @@
|
|||||||
"selected": "Valgt",
|
"selected": "Valgt",
|
||||||
"send_message": "Send besked",
|
"send_message": "Send besked",
|
||||||
"send_welcome_email": "Send velkomstemail",
|
"send_welcome_email": "Send velkomstemail",
|
||||||
"server": "Server",
|
|
||||||
"server_stats": "Serverstatus",
|
"server_stats": "Serverstatus",
|
||||||
"set": "Sæt",
|
"set": "Sæt",
|
||||||
"set_as_album_cover": "Sæt som albumcover",
|
"set_as_album_cover": "Sæt som albumcover",
|
||||||
@@ -1037,7 +984,6 @@
|
|||||||
"to_favorite": "Gør til favorit",
|
"to_favorite": "Gør til favorit",
|
||||||
"toggle_settings": "Slå indstillinger til eller fra",
|
"toggle_settings": "Slå indstillinger til eller fra",
|
||||||
"toggle_theme": "Slå mørkt tema til eller fra",
|
"toggle_theme": "Slå mørkt tema til eller fra",
|
||||||
"toggle_visibility": "Slå synlighed til eller fra",
|
|
||||||
"total_usage": "Samlet forbrug",
|
"total_usage": "Samlet forbrug",
|
||||||
"trash": "Papirkurv",
|
"trash": "Papirkurv",
|
||||||
"trash_all": "Smid alle ud",
|
"trash_all": "Smid alle ud",
|
||||||
@@ -1045,11 +991,9 @@
|
|||||||
"trashed_items_will_be_permanently_deleted_after": "Mediefiler i skraldespanden vil blive slettet permanent efter {days, plural, one {# dag} other {# dage}}.",
|
"trashed_items_will_be_permanently_deleted_after": "Mediefiler i skraldespanden vil blive slettet permanent efter {days, plural, one {# dag} other {# dage}}.",
|
||||||
"type": "Type",
|
"type": "Type",
|
||||||
"unarchive": "Afakivér",
|
"unarchive": "Afakivér",
|
||||||
"unarchived": "Uarkiveret",
|
|
||||||
"unfavorite": "Fjern favorit",
|
"unfavorite": "Fjern favorit",
|
||||||
"unhide_person": "Hold op med at gemme person væk",
|
"unhide_person": "Hold op med at gemme person væk",
|
||||||
"unknown": "Ukendt",
|
"unknown": "Ukendt",
|
||||||
"unknown_album": "Ukendt album",
|
|
||||||
"unknown_year": "Ukendt år",
|
"unknown_year": "Ukendt år",
|
||||||
"unlimited": "Ubegrænset",
|
"unlimited": "Ubegrænset",
|
||||||
"unlink_oauth": "Frakobl OAuth",
|
"unlink_oauth": "Frakobl OAuth",
|
||||||
@@ -1067,6 +1011,8 @@
|
|||||||
"user": "Bruger",
|
"user": "Bruger",
|
||||||
"user_id": "Bruger-ID",
|
"user_id": "Bruger-ID",
|
||||||
"user_usage_detail": "Detaljer om brugers forbrug",
|
"user_usage_detail": "Detaljer om brugers forbrug",
|
||||||
|
"user_usage_stats": "Konto anvendelsesstatistik",
|
||||||
|
"user_usage_stats_description": "Vis konto anvendelsesstatistik",
|
||||||
"username": "Brugernavn",
|
"username": "Brugernavn",
|
||||||
"users": "Brugere",
|
"users": "Brugere",
|
||||||
"utilities": "Værktøjer",
|
"utilities": "Værktøjer",
|
||||||
@@ -1083,7 +1029,6 @@
|
|||||||
"view_links": "Vis links",
|
"view_links": "Vis links",
|
||||||
"view_next_asset": "Se næste medie",
|
"view_next_asset": "Se næste medie",
|
||||||
"view_previous_asset": "Se forrige medie",
|
"view_previous_asset": "Se forrige medie",
|
||||||
"viewer": "Viewer",
|
|
||||||
"waiting": "Venter",
|
"waiting": "Venter",
|
||||||
"week": "Uge",
|
"week": "Uge",
|
||||||
"welcome": "Velkommen",
|
"welcome": "Velkommen",
|
||||||
|
|||||||
148
i18n/de.json
@@ -11,7 +11,7 @@
|
|||||||
"add": "Hinzufügen",
|
"add": "Hinzufügen",
|
||||||
"add_a_description": "Beschreibung hinzufügen",
|
"add_a_description": "Beschreibung hinzufügen",
|
||||||
"add_a_location": "Standort 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_a_title": "Titel hinzufügen",
|
||||||
"add_exclusion_pattern": "Ausschlussmuster hinzufügen",
|
"add_exclusion_pattern": "Ausschlussmuster hinzufügen",
|
||||||
"add_import_path": "Importpfad hinzufügen",
|
"add_import_path": "Importpfad hinzufügen",
|
||||||
@@ -23,6 +23,7 @@
|
|||||||
"add_to": "Hinzufügen zu ...",
|
"add_to": "Hinzufügen zu ...",
|
||||||
"add_to_album": "Zu Album hinzufügen",
|
"add_to_album": "Zu Album hinzufügen",
|
||||||
"add_to_shared_album": "Zu geteiltem 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_archive": "Zum Archiv hinzugefügt",
|
||||||
"added_to_favorites": "Zu Favoriten hinzugefügt",
|
"added_to_favorites": "Zu Favoriten hinzugefügt",
|
||||||
"added_to_favorites_count": "{count, number} zu Favoriten hinzugefügt",
|
"added_to_favorites_count": "{count, number} zu Favoriten hinzugefügt",
|
||||||
@@ -51,9 +52,7 @@
|
|||||||
"cron_expression": "Cron-Ausdruck",
|
"cron_expression": "Cron-Ausdruck",
|
||||||
"cron_expression_description": "Stellen Sie das Scanintervall im Cron-Format ein. Weitere Informationen finden Sie beispielsweise unter <link>Crontab Guru</link>",
|
"cron_expression_description": "Stellen Sie das Scanintervall im Cron-Format ein. Weitere Informationen finden Sie beispielsweise unter <link>Crontab Guru</link>",
|
||||||
"cron_expression_presets": "Cron-Ausdruck-Vorlagen",
|
"cron_expression_presets": "Cron-Ausdruck-Vorlagen",
|
||||||
"crontab_guru": "Crontab Guru",
|
|
||||||
"disable_login": "Login deaktvieren",
|
"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",
|
"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.",
|
"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})",
|
"external_library_created_at": "Externe Bibliothek (erstellt am {date})",
|
||||||
@@ -71,22 +70,15 @@
|
|||||||
"image_prefer_wide_gamut": "Breites Spektrum bevorzugen",
|
"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_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_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_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_preview_title": "Vorschaueinstellungen",
|
||||||
"image_quality": "Qualität",
|
"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": "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_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": "Bildeinstellungen",
|
||||||
"image_settings_description": "Qualität und Auflösung von generierten Bildern verwalten",
|
"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_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_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",
|
"image_thumbnail_title": "Miniaturansicht-Einstellungen",
|
||||||
"job_concurrency": "{job} (Anzahl gleichzeitiger Prozesse)",
|
"job_concurrency": "{job} (Anzahl gleichzeitiger Prozesse)",
|
||||||
"job_created": "Aufgabe erstellt",
|
"job_created": "Aufgabe erstellt",
|
||||||
@@ -97,9 +89,6 @@
|
|||||||
"jobs_delayed": "{jobCount, plural, other {# verzögert}}",
|
"jobs_delayed": "{jobCount, plural, other {# verzögert}}",
|
||||||
"jobs_failed": "{jobCount, plural, other {# fehlgeschlagen}}",
|
"jobs_failed": "{jobCount, plural, other {# fehlgeschlagen}}",
|
||||||
"library_created": "Bibliothek erstellt: {library}",
|
"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. <link>Crontab Guru</link>",
|
|
||||||
"library_cron_expression_presets": "Cron-Expression Voreinstellungen",
|
|
||||||
"library_deleted": "Bibliothek gelöscht",
|
"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_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",
|
"library_scanning": "Periodisches Scannen",
|
||||||
@@ -142,7 +131,7 @@
|
|||||||
"machine_learning_smart_search_description": "Semantische Bildsuche mittels CLIP-Einbettungen",
|
"machine_learning_smart_search_description": "Semantische Bildsuche mittels CLIP-Einbettungen",
|
||||||
"machine_learning_smart_search_enabled": "Intelligente Suche aktivieren",
|
"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_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_concurrency": "Gleichzeitige Ausführungen verwalten",
|
||||||
"manage_log_settings": "Log-Einstellungen verwalten",
|
"manage_log_settings": "Log-Einstellungen verwalten",
|
||||||
"map_dark_style": "Dunkler Stil",
|
"map_dark_style": "Dunkler Stil",
|
||||||
@@ -223,7 +212,6 @@
|
|||||||
"refreshing_all_libraries": "Alle Bibliotheken aktualisieren",
|
"refreshing_all_libraries": "Alle Bibliotheken aktualisieren",
|
||||||
"registration": "Admin-Registrierung",
|
"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.",
|
"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_all": "Alle reparieren",
|
||||||
"repair_matched_items": "{count, plural, one {# Eintrag} other {# Einträge}} gefunden",
|
"repair_matched_items": "{count, plural, one {# Eintrag} other {# Einträge}} gefunden",
|
||||||
"repaired_items": "{count, plural, one {# Eintrag} other {# Einträge}} repariert",
|
"repaired_items": "{count, plural, one {# Eintrag} other {# Einträge}} repariert",
|
||||||
@@ -231,12 +219,12 @@
|
|||||||
"reset_settings_to_default": "Einstellungen auf Standard zurücksetzen",
|
"reset_settings_to_default": "Einstellungen auf Standard zurücksetzen",
|
||||||
"reset_settings_to_recent_saved": "Einstellungen auf die zuletzt gespeicherten Einstellungen zurücksetzen",
|
"reset_settings_to_recent_saved": "Einstellungen auf die zuletzt gespeicherten Einstellungen zurücksetzen",
|
||||||
"scanning_library": "Bibliothek scannen",
|
"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...",
|
"search_jobs": "Aufgaben suchen...",
|
||||||
"send_welcome_email": "Begrüssungsmail senden",
|
"send_welcome_email": "Begrüssungsmail senden",
|
||||||
"server_external_domain_settings": "Externe Domain",
|
"server_external_domain_settings": "Externe Domain",
|
||||||
"server_external_domain_settings_description": "Domäne für öffentlich freigegebene Links, einschließlich http(s)://",
|
"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": "Servereinstellungen",
|
||||||
"server_settings_description": "Servereinstellungen verwalten",
|
"server_settings_description": "Servereinstellungen verwalten",
|
||||||
"server_welcome_message": "Willkommensnachricht",
|
"server_welcome_message": "Willkommensnachricht",
|
||||||
@@ -262,6 +250,16 @@
|
|||||||
"storage_template_user_label": "<code>{label}</code> is die Speicherpfadbezeichnung des Benutzers",
|
"storage_template_user_label": "<code>{label}</code> is die Speicherpfadbezeichnung des Benutzers",
|
||||||
"system_settings": "Systemeinstellungen",
|
"system_settings": "Systemeinstellungen",
|
||||||
"tag_cleanup_job": "Tags aufräumen",
|
"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": "Benutzerdefiniertes CSS",
|
||||||
"theme_custom_css_settings_description": "Mit Cascading Style Sheets (CSS) kann das Design von Immich angepasst werden.",
|
"theme_custom_css_settings_description": "Mit Cascading Style Sheets (CSS) kann das Design von Immich angepasst werden.",
|
||||||
"theme_settings": "Theme-Einstellungen",
|
"theme_settings": "Theme-Einstellungen",
|
||||||
@@ -269,7 +267,6 @@
|
|||||||
"these_files_matched_by_checksum": "Diese Dateien wurden anhand ihrer Prüfsummen abgeglichen",
|
"these_files_matched_by_checksum": "Diese Dateien wurden anhand ihrer Prüfsummen abgeglichen",
|
||||||
"thumbnail_generation_job": "Miniaturansichten generieren",
|
"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",
|
"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": "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_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)",
|
"transcoding_acceleration_nvenc": "NVENC (NVIDIA-GPU erforderlich)",
|
||||||
@@ -321,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_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": "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_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": "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_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",
|
"transcoding_two_pass_encoding": "Two-Pass Codierung",
|
||||||
@@ -403,7 +398,6 @@
|
|||||||
"archive_or_unarchive_photo": "Foto archivieren bzw. Archivierung aufheben",
|
"archive_or_unarchive_photo": "Foto archivieren bzw. Archivierung aufheben",
|
||||||
"archive_size": "Archivgröße",
|
"archive_size": "Archivgröße",
|
||||||
"archive_size_description": "Archivgröße für Downloads konfigurieren (in GiB)",
|
"archive_size_description": "Archivgröße für Downloads konfigurieren (in GiB)",
|
||||||
"archived": "Archiviert",
|
|
||||||
"archived_count": "{count, plural, other {# archiviert}}",
|
"archived_count": "{count, plural, other {# archiviert}}",
|
||||||
"are_these_the_same_person": "Ist das dieselbe Person?",
|
"are_these_the_same_person": "Ist das dieselbe Person?",
|
||||||
"are_you_sure_to_do_this": "Bist du sicher, dass du das tun willst?",
|
"are_you_sure_to_do_this": "Bist du sicher, dass du das tun willst?",
|
||||||
@@ -424,9 +418,8 @@
|
|||||||
"assets_added_to_album_count": "{count, plural, one {# Datei} other {# Dateien}} zum Album hinzugefügt",
|
"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 {<b>{name}</b>} other {neuem Album}} hinzugefügt",
|
"assets_added_to_name_count": "{count, plural, one {# Element} other {# Elemente}} zu {hasName, select, true {<b>{name}</b>} other {neuem Album}} hinzugefügt",
|
||||||
"assets_count": "{count, plural, one {# Datei} other {# Dateien}}",
|
"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_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_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_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",
|
"assets_restored_count": "{count, plural, one {# Datei} other {# Dateien}} wiederhergestellt",
|
||||||
@@ -442,7 +435,7 @@
|
|||||||
"bugs_and_feature_requests": "Fehler & Verbesserungsvorschläge",
|
"bugs_and_feature_requests": "Fehler & Verbesserungsvorschläge",
|
||||||
"build": "Build",
|
"build": "Build",
|
||||||
"build_image": "Build Abbild",
|
"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_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.",
|
"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",
|
"buy": "Immich erwerben",
|
||||||
@@ -454,10 +447,6 @@
|
|||||||
"cannot_merge_people": "Personen können nicht zusammengeführt werden",
|
"cannot_merge_people": "Personen können nicht zusammengeführt werden",
|
||||||
"cannot_undo_this_action": "Diese Aktion kann nicht rückgängig gemacht werden!",
|
"cannot_undo_this_action": "Diese Aktion kann nicht rückgängig gemacht werden!",
|
||||||
"cannot_update_the_description": "Beschreibung kann nicht aktualisiert 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_date": "Datum ändern",
|
||||||
"change_expiration_time": "Verfallszeitpunkt ändern",
|
"change_expiration_time": "Verfallszeitpunkt ändern",
|
||||||
"change_location": "Ort ändern",
|
"change_location": "Ort ändern",
|
||||||
@@ -489,6 +478,7 @@
|
|||||||
"confirm": "Bestätigen",
|
"confirm": "Bestätigen",
|
||||||
"confirm_admin_password": "Administrator Passwort 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_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",
|
"confirm_password": "Passwort bestätigen",
|
||||||
"contain": "Vollständig",
|
"contain": "Vollständig",
|
||||||
"context": "Kontext",
|
"context": "Kontext",
|
||||||
@@ -534,10 +524,11 @@
|
|||||||
"delete": "Löschen",
|
"delete": "Löschen",
|
||||||
"delete_album": "Album löschen",
|
"delete_album": "Album löschen",
|
||||||
"delete_api_key_prompt": "Bist du sicher, dass du diesen API-Schlüssel löschen willst?",
|
"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_key": "Schlüssel löschen",
|
||||||
"delete_library": "Bibliothek löschen",
|
"delete_library": "Bibliothek löschen",
|
||||||
"delete_link": "Link löschen",
|
"delete_link": "Link löschen",
|
||||||
|
"delete_others": "Andere löschen",
|
||||||
"delete_shared_link": "geteilten Link löschen",
|
"delete_shared_link": "geteilten Link löschen",
|
||||||
"delete_tag": "Tag löschen",
|
"delete_tag": "Tag löschen",
|
||||||
"delete_tag_confirmation_prompt": "Bist du sicher, dass der Tag {tagName} gelöscht werden soll?",
|
"delete_tag_confirmation_prompt": "Bist du sicher, dass der Tag {tagName} gelöscht werden soll?",
|
||||||
@@ -571,13 +562,6 @@
|
|||||||
"duplicates": "Duplikate",
|
"duplicates": "Duplikate",
|
||||||
"duplicates_description": "Löse jede Gruppe auf, indem du angibst, welche, wenn überhaupt, Duplikate sind",
|
"duplicates_description": "Löse jede Gruppe auf, indem du angibst, welche, wenn überhaupt, Duplikate sind",
|
||||||
"duration": "Dauer",
|
"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": "Bearbeiten",
|
||||||
"edit_album": "Album bearbeiten",
|
"edit_album": "Album bearbeiten",
|
||||||
"edit_avatar": "Avatar bearbeiten",
|
"edit_avatar": "Avatar bearbeiten",
|
||||||
@@ -602,10 +586,8 @@
|
|||||||
"editor_crop_tool_h2_aspect_ratios": "Seitenverhältnisse",
|
"editor_crop_tool_h2_aspect_ratios": "Seitenverhältnisse",
|
||||||
"editor_crop_tool_h2_rotation": "Drehung",
|
"editor_crop_tool_h2_rotation": "Drehung",
|
||||||
"email": "E-Mail",
|
"email": "E-Mail",
|
||||||
"empty": "Leer",
|
|
||||||
"empty_album": "Leeres Album",
|
|
||||||
"empty_trash": "Papierkorb leeren",
|
"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",
|
"enable": "Aktivieren",
|
||||||
"enabled": "Aktiviert",
|
"enabled": "Aktiviert",
|
||||||
"end_date": "Enddatum",
|
"end_date": "Enddatum",
|
||||||
@@ -637,6 +619,7 @@
|
|||||||
"failed_to_create_shared_link": "Geteilter Link konnte nicht erstellt werden",
|
"failed_to_create_shared_link": "Geteilter Link konnte nicht erstellt werden",
|
||||||
"failed_to_edit_shared_link": "Geteilter Link konnte nicht bearbeitet werden",
|
"failed_to_edit_shared_link": "Geteilter Link konnte nicht bearbeitet werden",
|
||||||
"failed_to_get_people": "Personen konnten nicht abgerufen 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_asset": "Fehler beim Laden der Datei",
|
||||||
"failed_to_load_assets": "Fehler beim Laden der Dateien",
|
"failed_to_load_assets": "Fehler beim Laden der Dateien",
|
||||||
"failed_to_load_people": "Fehler beim Laden von Personen",
|
"failed_to_load_people": "Fehler beim Laden von Personen",
|
||||||
@@ -664,8 +647,6 @@
|
|||||||
"unable_to_change_location": "Ort kann nicht verändert werden",
|
"unable_to_change_location": "Ort kann nicht verändert werden",
|
||||||
"unable_to_change_password": "Passwort konnte nicht geä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_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_complete_oauth_login": "OAuth-Anmeldung konnte nicht abgeschlossen werden",
|
||||||
"unable_to_connect": "Verbindung konnte nicht hergestellt werden",
|
"unable_to_connect": "Verbindung konnte nicht hergestellt werden",
|
||||||
"unable_to_connect_to_server": "Verbindung zum Server konnte nicht hergestellt werden",
|
"unable_to_connect_to_server": "Verbindung zum Server konnte nicht hergestellt werden",
|
||||||
@@ -706,12 +687,10 @@
|
|||||||
"unable_to_remove_album_users": "Mitglieder der Alben können nicht entfernt werden",
|
"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_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_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_deleted_assets": "Offline-Dateien konnten nicht entfernt werden",
|
||||||
"unable_to_remove_library": "Bibliothek kann nicht entfernt werden",
|
"unable_to_remove_library": "Bibliothek kann nicht entfernt werden",
|
||||||
"unable_to_remove_partner": "Partner 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_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_repair_items": "Objekte können nicht repariert werden",
|
||||||
"unable_to_reset_password": "Passwort kann nicht zurückgesetzt werden",
|
"unable_to_reset_password": "Passwort kann nicht zurückgesetzt werden",
|
||||||
"unable_to_resolve_duplicate": "Duplikate können nicht aufgelöst werden",
|
"unable_to_resolve_duplicate": "Duplikate können nicht aufgelöst werden",
|
||||||
@@ -741,16 +720,12 @@
|
|||||||
"unable_to_update_user": "Der Nutzer konnte nicht aktualisiert werden",
|
"unable_to_update_user": "Der Nutzer konnte nicht aktualisiert werden",
|
||||||
"unable_to_upload_file": "Datei konnte nicht hochgeladen 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",
|
"exif": "EXIF",
|
||||||
"exit_slideshow": "Diashow beenden",
|
"exit_slideshow": "Diashow beenden",
|
||||||
"expand_all": "Alle aufklappen",
|
"expand_all": "Alle aufklappen",
|
||||||
"expire_after": "Verfällt nach",
|
"expire_after": "Verfällt nach",
|
||||||
"expired": "Verfallen",
|
"expired": "Verfallen",
|
||||||
"expires_date": "Läuft am {date} ab",
|
"expires_date": "Läuft {date} ab",
|
||||||
"explore": "Erkunden",
|
"explore": "Erkunden",
|
||||||
"explorer": "Datei-Explorer",
|
"explorer": "Datei-Explorer",
|
||||||
"export": "Exportieren",
|
"export": "Exportieren",
|
||||||
@@ -759,33 +734,28 @@
|
|||||||
"external": "Extern",
|
"external": "Extern",
|
||||||
"external_libraries": "Externe Bibliotheken",
|
"external_libraries": "Externe Bibliotheken",
|
||||||
"face_unassigned": "Nicht zugewiesen",
|
"face_unassigned": "Nicht zugewiesen",
|
||||||
"failed_to_get_people": "Personen konnten nicht ermittelt werden",
|
"failed_to_load_assets": "Laden der Assets fehlgeschlagen",
|
||||||
"favorite": "Favorit",
|
"favorite": "Favorit",
|
||||||
"favorite_or_unfavorite_photo": "Favorisiertes oder nicht favorisiertes Foto",
|
"favorite_or_unfavorite_photo": "Favorisiertes oder nicht favorisiertes Foto",
|
||||||
"favorites": "Favoriten",
|
"favorites": "Favoriten",
|
||||||
"feature": "Funktion",
|
|
||||||
"feature_photo_updated": "Profilbild aktualisiert",
|
"feature_photo_updated": "Profilbild aktualisiert",
|
||||||
"featurecollection": "Funktionssammlung",
|
|
||||||
"features": "Funktionen",
|
"features": "Funktionen",
|
||||||
"features_setting_description": "Funktionen der App verwalten",
|
"features_setting_description": "Funktionen der App verwalten",
|
||||||
"file_name": "Dateiname",
|
"file_name": "Dateiname",
|
||||||
"file_name_or_extension": "Dateiname oder -erweiterung",
|
"file_name_or_extension": "Dateiname oder -erweiterung",
|
||||||
"filename": "Dateiname",
|
"filename": "Dateiname",
|
||||||
"files": "",
|
|
||||||
"filetype": "Dateityp",
|
"filetype": "Dateityp",
|
||||||
"filter_people": "Personen filtern",
|
"filter_people": "Personen filtern",
|
||||||
"find_them_fast": "Finde sie schneller mit der Suche nach Namen",
|
"find_them_fast": "Finde sie schneller mit der Suche nach Namen",
|
||||||
"fix_incorrect_match": "Fehlerhafte Übereinstimmung beheben",
|
"fix_incorrect_match": "Fehlerhafte Übereinstimmung beheben",
|
||||||
"folders": "Ordner",
|
"folders": "Ordner",
|
||||||
"folders_feature_description": "Durchsuchen der Ordneransicht für Fotos und Videos im Dateisystem",
|
"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",
|
"forward": "Vorwärts",
|
||||||
"general": "Allgemein",
|
"general": "Allgemein",
|
||||||
"get_help": "Hilfe erhalten",
|
"get_help": "Hilfe erhalten",
|
||||||
"getting_started": "Erste Schritte",
|
"getting_started": "Erste Schritte",
|
||||||
"go_back": "Zurück",
|
"go_back": "Zurück",
|
||||||
"go_to_search": "Zur Suche gehen",
|
"go_to_search": "Zur Suche gehen",
|
||||||
"go_to_share_page": "Zur Freigabeseite gehen",
|
|
||||||
"group_albums_by": "Alben gruppieren nach...",
|
"group_albums_by": "Alben gruppieren nach...",
|
||||||
"group_no": "Keine Gruppierung",
|
"group_no": "Keine Gruppierung",
|
||||||
"group_owner": "Gruppierung nach Besitzer",
|
"group_owner": "Gruppierung nach Besitzer",
|
||||||
@@ -811,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_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_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_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_logo": "Immich-Logo",
|
||||||
"immich_web_interface": "Immich-Web-Oberfläche",
|
"immich_web_interface": "Immich-Web-Oberfläche",
|
||||||
"import_from_json": "Aus JSON importieren",
|
"import_from_json": "Aus JSON importieren",
|
||||||
@@ -835,10 +801,11 @@
|
|||||||
"invite_people": "Personen einladen",
|
"invite_people": "Personen einladen",
|
||||||
"invite_to_album": "Zum Album einladen",
|
"invite_to_album": "Zum Album einladen",
|
||||||
"items_count": "{count, plural, one {# Eintrag} other {# Einträge}}",
|
"items_count": "{count, plural, one {# Eintrag} other {# Einträge}}",
|
||||||
"job_settings_description": "Parallelität von Jobs verwalten",
|
|
||||||
"jobs": "Aufgaben",
|
"jobs": "Aufgaben",
|
||||||
"keep": "Behalten",
|
"keep": "Behalten",
|
||||||
"keep_all": "Alle 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",
|
"keyboard_shortcuts": "Tastenkürzel",
|
||||||
"language": "Sprache",
|
"language": "Sprache",
|
||||||
"language_setting_description": "Wähle deine bevorzugte Sprache",
|
"language_setting_description": "Wähle deine bevorzugte Sprache",
|
||||||
@@ -850,31 +817,6 @@
|
|||||||
"level": "Level",
|
"level": "Level",
|
||||||
"library": "Bibliothek",
|
"library": "Bibliothek",
|
||||||
"library_options": "Bibliotheksoptionen",
|
"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",
|
"light": "Hell",
|
||||||
"like_deleted": "Like gelöscht",
|
"like_deleted": "Like gelöscht",
|
||||||
"link_motion_video": "Bewegungsvideo verknüpfen",
|
"link_motion_video": "Bewegungsvideo verknüpfen",
|
||||||
@@ -979,7 +921,6 @@
|
|||||||
"onboarding_welcome_user": "Willkommen, {user}",
|
"onboarding_welcome_user": "Willkommen, {user}",
|
||||||
"online": "Online",
|
"online": "Online",
|
||||||
"only_favorites": "Nur Favoriten",
|
"only_favorites": "Nur Favoriten",
|
||||||
"only_refreshes_modified_files": "Nur geänderte Dateien aktualisieren",
|
|
||||||
"open_in_map_view": "In Kartenansicht öffnen",
|
"open_in_map_view": "In Kartenansicht öffnen",
|
||||||
"open_in_openstreetmap": "In OpenStreetMap öffnen",
|
"open_in_openstreetmap": "In OpenStreetMap öffnen",
|
||||||
"open_the_search_filters": "Die Suchfilter öffnen",
|
"open_the_search_filters": "Die Suchfilter öffnen",
|
||||||
@@ -1017,15 +958,13 @@
|
|||||||
"people_edits_count": "{count, plural, one {# Person} other {# Personen}} bearbeitet",
|
"people_edits_count": "{count, plural, one {# Person} other {# Personen}} bearbeitet",
|
||||||
"people_feature_description": "Fotos und Videos nach Personen gruppiert durchsuchen",
|
"people_feature_description": "Fotos und Videos nach Personen gruppiert durchsuchen",
|
||||||
"people_sidebar_description": "Eine Verknüpfung zu Personen in der Seitenleiste anzeigen",
|
"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": "Warnung vor endgültiger Löschung",
|
||||||
"permanent_deletion_warning_setting_description": "Anzeige einer Warnung beim permanenten Löschen von Objekten",
|
"permanent_deletion_warning_setting_description": "Anzeige einer Warnung beim endgültigen Löschen von Objekten",
|
||||||
"permanently_delete": "Dauerhaft löschen",
|
"permanently_delete": "Endgültig löschen",
|
||||||
"permanently_delete_assets_count": "{count, plural, one {Datei} other {Dateien}} dauerhaft gelöscht",
|
"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 <b>#</b> Dateien}} dauerhaft gelöscht werden soll? Dadurch {count, plural, one {wird} other {werden}} diese auch aus deinen Alben entfernt.",
|
"permanently_delete_assets_prompt": "Bist du sicher, dass {count, plural, one {diese Datei} other {diese <b>#</b> Dateien}} endgültig 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_asset": "Endgültig 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}} endgültig gelöscht",
|
||||||
"permanently_deleted_assets_count": "{count, plural, one {# Datei} other {# Dateien}} dauerhaft gelöscht",
|
|
||||||
"person": "Person",
|
"person": "Person",
|
||||||
"person_hidden": "{name}{hidden, select, true { (verborgen)} other {}}",
|
"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.",
|
"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.",
|
||||||
@@ -1040,7 +979,6 @@
|
|||||||
"play_memories": "Erinnerungen abspielen",
|
"play_memories": "Erinnerungen abspielen",
|
||||||
"play_motion_photo": "Bewegte Bilder abspielen",
|
"play_motion_photo": "Bewegte Bilder abspielen",
|
||||||
"play_or_pause_video": "Video abspielen oder pausieren",
|
"play_or_pause_video": "Video abspielen oder pausieren",
|
||||||
"point": "Hinweis",
|
|
||||||
"port": "Port",
|
"port": "Port",
|
||||||
"preset": "Voreinstellung",
|
"preset": "Voreinstellung",
|
||||||
"preview": "Vorschau",
|
"preview": "Vorschau",
|
||||||
@@ -1085,12 +1023,10 @@
|
|||||||
"purchase_server_description_2": "Unterstützerstatus",
|
"purchase_server_description_2": "Unterstützerstatus",
|
||||||
"purchase_server_title": "Server",
|
"purchase_server_title": "Server",
|
||||||
"purchase_settings_server_activated": "Der Server-Produktschlüssel wird durch den Administrator verwaltet",
|
"purchase_settings_server_activated": "Der Server-Produktschlüssel wird durch den Administrator verwaltet",
|
||||||
"range": "Reichweite",
|
|
||||||
"rating": "Bewertung",
|
"rating": "Bewertung",
|
||||||
"rating_clear": "Bewertung löschen",
|
"rating_clear": "Bewertung löschen",
|
||||||
"rating_count": "{count, plural, one {# Stern} other {# Sterne}}",
|
"rating_count": "{count, plural, one {# Stern} other {# Sterne}}",
|
||||||
"rating_description": "Stellt die EXIF-Bewertung im Informationsbereich dar",
|
"rating_description": "Stellt die EXIF-Bewertung im Informationsbereich dar",
|
||||||
"raw": "RAW",
|
|
||||||
"reaction_options": "Reaktionsmöglichkeiten",
|
"reaction_options": "Reaktionsmöglichkeiten",
|
||||||
"read_changelog": "Changelog lesen",
|
"read_changelog": "Changelog lesen",
|
||||||
"reassign": "Neu zuweisen",
|
"reassign": "Neu zuweisen",
|
||||||
@@ -1098,6 +1034,7 @@
|
|||||||
"reassigned_assets_to_new_person": "{count, plural, one {# Datei wurde} other {# Dateien wurden}} einer neuen Person zugewiesen",
|
"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",
|
"reassing_hint": "Markierte Dateien einer vorhandenen Person zuweisen",
|
||||||
"recent": "Neuste",
|
"recent": "Neuste",
|
||||||
|
"recent-albums": "Neuste Alben",
|
||||||
"recent_searches": "Letzte Suchen",
|
"recent_searches": "Letzte Suchen",
|
||||||
"refresh": "Aktualisieren",
|
"refresh": "Aktualisieren",
|
||||||
"refresh_encoded_videos": "Kodierte Videos aktualisieren",
|
"refresh_encoded_videos": "Kodierte Videos aktualisieren",
|
||||||
@@ -1119,6 +1056,7 @@
|
|||||||
"remove_from_album": "Aus Album entfernen",
|
"remove_from_album": "Aus Album entfernen",
|
||||||
"remove_from_favorites": "Aus Favoriten entfernen",
|
"remove_from_favorites": "Aus Favoriten entfernen",
|
||||||
"remove_from_shared_link": "Aus geteiltem Link entfernen",
|
"remove_from_shared_link": "Aus geteiltem Link entfernen",
|
||||||
|
"remove_url": "URL entfernen",
|
||||||
"remove_user": "Nutzer entfernen",
|
"remove_user": "Nutzer entfernen",
|
||||||
"removed_api_key": "API-Schlüssel {name} wurde entfernt",
|
"removed_api_key": "API-Schlüssel {name} wurde entfernt",
|
||||||
"removed_from_archive": "Aus dem Archiv entfernt",
|
"removed_from_archive": "Aus dem Archiv entfernt",
|
||||||
@@ -1135,7 +1073,6 @@
|
|||||||
"reset": "Zurücksetzen",
|
"reset": "Zurücksetzen",
|
||||||
"reset_password": "Passwort zurücksetzen",
|
"reset_password": "Passwort zurücksetzen",
|
||||||
"reset_people_visibility": "Sichtbarkeit von Personen 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",
|
"reset_to_default": "Auf Standard zurücksetzen",
|
||||||
"resolve_duplicates": "Duplikate entfernen",
|
"resolve_duplicates": "Duplikate entfernen",
|
||||||
"resolved_all_duplicates": "Alle Duplikate aufgelöst",
|
"resolved_all_duplicates": "Alle Duplikate aufgelöst",
|
||||||
@@ -1155,9 +1092,7 @@
|
|||||||
"saved_settings": "Einstellungen gespeichert",
|
"saved_settings": "Einstellungen gespeichert",
|
||||||
"say_something": "Etwas sagen",
|
"say_something": "Etwas sagen",
|
||||||
"scan_all_libraries": "Alle Bibliotheken scannen",
|
"scan_all_libraries": "Alle Bibliotheken scannen",
|
||||||
"scan_all_library_files": "Alle Bibliotheksdateien erneut scannen",
|
|
||||||
"scan_library": "Scannen",
|
"scan_library": "Scannen",
|
||||||
"scan_new_library_files": "Neue Bibliotheksdateien scannen",
|
|
||||||
"scan_settings": "Scan-Einstellungen",
|
"scan_settings": "Scan-Einstellungen",
|
||||||
"scanning_for_album": "Nach Alben scannen...",
|
"scanning_for_album": "Nach Alben scannen...",
|
||||||
"search": "Suche",
|
"search": "Suche",
|
||||||
@@ -1200,7 +1135,6 @@
|
|||||||
"selected_count": "{count, plural, other {# ausgewählt}}",
|
"selected_count": "{count, plural, other {# ausgewählt}}",
|
||||||
"send_message": "Nachricht senden",
|
"send_message": "Nachricht senden",
|
||||||
"send_welcome_email": "Begrüssungsmail senden",
|
"send_welcome_email": "Begrüssungsmail senden",
|
||||||
"server": "Server",
|
|
||||||
"server_offline": "Server offline",
|
"server_offline": "Server offline",
|
||||||
"server_online": "Server online",
|
"server_online": "Server online",
|
||||||
"server_stats": "Server-Statistiken",
|
"server_stats": "Server-Statistiken",
|
||||||
@@ -1305,17 +1239,17 @@
|
|||||||
"they_will_be_merged_together": "Sie werden zusammengeführt",
|
"they_will_be_merged_together": "Sie werden zusammengeführt",
|
||||||
"third_party_resources": "Drittanbieter-Quellen",
|
"third_party_resources": "Drittanbieter-Quellen",
|
||||||
"time_based_memories": "Zeitbasierte Erinnerungen",
|
"time_based_memories": "Zeitbasierte Erinnerungen",
|
||||||
|
"timeline": "Zeitleiste",
|
||||||
"timezone": "Zeitzone",
|
"timezone": "Zeitzone",
|
||||||
"to_archive": "Archivieren",
|
"to_archive": "Archivieren",
|
||||||
"to_change_password": "Passwort ändern",
|
"to_change_password": "Passwort ändern",
|
||||||
"to_favorite": "Zu Favoriten hinzufügen",
|
"to_favorite": "Zu Favoriten hinzufügen",
|
||||||
"to_login": "Anmelden",
|
"to_login": "Anmelden",
|
||||||
"to_parent": "Gehe zum Übergeordneten",
|
"to_parent": "Gehe zum Übergeordneten",
|
||||||
"to_root": "Zur Wurzel",
|
|
||||||
"to_trash": "In den Papierkorb verschieben",
|
"to_trash": "In den Papierkorb verschieben",
|
||||||
"toggle_settings": "Einstellungen umschalten",
|
"toggle_settings": "Einstellungen umschalten",
|
||||||
"toggle_theme": "Dunkles Theme umschalten",
|
"toggle_theme": "Dunkles Theme umschalten",
|
||||||
"toggle_visibility": "Sichtbarkeit umschalten",
|
"total": "Gesamt",
|
||||||
"total_usage": "Gesamtnutzung",
|
"total_usage": "Gesamtnutzung",
|
||||||
"trash": "Papierkorb",
|
"trash": "Papierkorb",
|
||||||
"trash_all": "Alle löschen",
|
"trash_all": "Alle löschen",
|
||||||
@@ -1325,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.",
|
"trashed_items_will_be_permanently_deleted_after": "Gelöschte Objekte werden nach {days, plural, one {# Tag} other {# Tagen}} endgültig gelöscht.",
|
||||||
"type": "Typ",
|
"type": "Typ",
|
||||||
"unarchive": "Entarchivieren",
|
"unarchive": "Entarchivieren",
|
||||||
"unarchived": "Unarchiviert",
|
|
||||||
"unarchived_count": "{count, plural, other {# entarchiviert}}",
|
"unarchived_count": "{count, plural, other {# entarchiviert}}",
|
||||||
"unfavorite": "Entfavorisieren",
|
"unfavorite": "Entfavorisieren",
|
||||||
"unhide_person": "Person einblenden",
|
"unhide_person": "Person einblenden",
|
||||||
"unknown": "Unbekannt",
|
"unknown": "Unbekannt",
|
||||||
"unknown_album": "Unbekanntes Album",
|
|
||||||
"unknown_year": "Unbekanntes Jahr",
|
"unknown_year": "Unbekanntes Jahr",
|
||||||
"unlimited": "Unlimitiert",
|
"unlimited": "Unlimitiert",
|
||||||
"unlink_motion_video": "Verknüpfung zum Bewegungsvideo aufheben",
|
"unlink_motion_video": "Verknüpfung zum Bewegungsvideo aufheben",
|
||||||
@@ -1362,13 +1294,13 @@
|
|||||||
"use_custom_date_range": "Stattdessen einen benutzerdefinierten Datumsbereich verwenden",
|
"use_custom_date_range": "Stattdessen einen benutzerdefinierten Datumsbereich verwenden",
|
||||||
"user": "Nutzer",
|
"user": "Nutzer",
|
||||||
"user_id": "Nutzer-ID",
|
"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_liked": "{type, select, photo {Dieses Foto} video {Dieses Video} asset {Diese Datei} other {Dies}} gefällt {user}",
|
||||||
"user_purchase_settings": "Kauf",
|
"user_purchase_settings": "Kauf",
|
||||||
"user_purchase_settings_description": "Kauf verwalten",
|
"user_purchase_settings_description": "Kauf verwalten",
|
||||||
"user_role_set": "{user} als {role} festlegen",
|
"user_role_set": "{user} als {role} festlegen",
|
||||||
"user_usage_detail": "Nutzungsdetails der Nutzer",
|
"user_usage_detail": "Nutzungsdetails der Nutzer",
|
||||||
|
"user_usage_stats": "Statistiken zur Kontonutzung",
|
||||||
|
"user_usage_stats_description": "Statistiken zur Kontonutzung anzeigen",
|
||||||
"username": "Nutzername",
|
"username": "Nutzername",
|
||||||
"users": "Benutzer",
|
"users": "Benutzer",
|
||||||
"utilities": "Hilfsmittel",
|
"utilities": "Hilfsmittel",
|
||||||
@@ -1376,7 +1308,7 @@
|
|||||||
"variables": "Variablen",
|
"variables": "Variablen",
|
||||||
"version": "Version",
|
"version": "Version",
|
||||||
"version_announcement_closing": "Dein Freund, Alex",
|
"version_announcement_closing": "Dein Freund, Alex",
|
||||||
"version_announcement_message": "Hallo Freund, es gibt eine neue Version dieser Anwendung. Bitte nimm dir Zeit, die <link>Versionshinweise</link> zu lesen und stelle sicher, dass deine <code>docker-compose.yml</code>- und <code>.env</code>-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 <link>Versionshinweise</link> zu lesen, um Fehlkonfigurationen zu vermeiden, insbesondere wenn du WatchTower oder ein anderes Verfahren verwendest, das Immich automatisch aktualisiert.",
|
||||||
"version_history": "Versionshistorie",
|
"version_history": "Versionshistorie",
|
||||||
"version_history_item": "{version} am {date} installiert",
|
"version_history_item": "{version} am {date} installiert",
|
||||||
"video": "Video",
|
"video": "Video",
|
||||||
@@ -1390,10 +1322,10 @@
|
|||||||
"view_all_users": "Alle Nutzer anzeigen",
|
"view_all_users": "Alle Nutzer anzeigen",
|
||||||
"view_in_timeline": "In Zeitleiste anzeigen",
|
"view_in_timeline": "In Zeitleiste anzeigen",
|
||||||
"view_links": "Links anzeigen",
|
"view_links": "Links anzeigen",
|
||||||
|
"view_name": "Ansicht",
|
||||||
"view_next_asset": "Nächste Datei anzeigen",
|
"view_next_asset": "Nächste Datei anzeigen",
|
||||||
"view_previous_asset": "Vorherige Datei anzeigen",
|
"view_previous_asset": "Vorherige Datei anzeigen",
|
||||||
"view_stack": "Stapel anzeigen",
|
"view_stack": "Stapel anzeigen",
|
||||||
"viewer": "Zuschauer",
|
|
||||||
"visibility_changed": "Sichtbarkeit für {count, plural, one {# Person} other {# Personen}} geändert",
|
"visibility_changed": "Sichtbarkeit für {count, plural, one {# Person} other {# Personen}} geändert",
|
||||||
"waiting": "Wartend",
|
"waiting": "Wartend",
|
||||||
"warning": "Warnung",
|
"warning": "Warnung",
|
||||||
|
|||||||