Compare commits

..

1 Commits

Author SHA1 Message Date
Daniel Dietzler 6bc445a03b chore: move workflows components to different folder 2026-05-28 12:23:27 +02:00
1085 changed files with 33229 additions and 109139 deletions
@@ -15,7 +15,7 @@ services:
volumes:
- ${UPLOAD_LOCATION:-upload-devcontainer-volume}${UPLOAD_LOCATION:+/photos}:/data
- /etc/localtime:/etc/localtime:ro
- build_cache:/buildcache
- pnpm_store_server:/buildcache/pnpm-store
- ../packages/plugin-core:/build/plugins/immich-plugin-core
immich-web:
env_file: !reset []
+1
View File
@@ -0,0 +1 @@
custom: ['https://buy.immich.app', 'https://immich.store']
+1 -1
View File
@@ -15,7 +15,7 @@ jobs:
outputs:
uses_template: ${{ steps.check.outputs.uses_template }}
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
sparse-checkout: .github/pull_request_template.md
sparse-checkout-cone-mode: false
+9 -11
View File
@@ -51,7 +51,7 @@ jobs:
should_run: ${{ steps.check.outputs.should_run }}
steps:
- id: token
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
with:
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
@@ -79,22 +79,21 @@ jobs:
steps:
- id: token
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
with:
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
ref: ${{ inputs.ref }}
persist-credentials: false
token: ${{ steps.token.outputs.token }}
- name: Setup Mise
uses: immich-app/devtools/actions/use-mise@3bca63ca3c15020293b36b51737a3ee2c773340b # use-mise-action-v3.1.0
uses: immich-app/devtools/actions/use-mise@7b8610a904d57da241e4ddba17fa62b62b15aed4 # use-mise-action-v2.0.2
with:
github_token: ${{ steps.token.outputs.token }}
working_directory: ./mobile
- name: Create the Keystore
if: ${{ !github.event.pull_request.head.repo.fork }}
@@ -103,7 +102,7 @@ jobs:
working-directory: ./mobile
run: printf "%s" $KEY_JKS | base64 -d > android/key.jks
- uses: actions/setup-java@ad2b38190b15e4d6bdf0c97fb4fca8412226d287 # v5.3.0
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
with:
distribution: 'zulu'
java-version: '17'
@@ -202,7 +201,7 @@ jobs:
steps:
- id: token
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
with:
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
@@ -211,16 +210,15 @@ jobs:
run: sudo xcode-select -s /Applications/Xcode_26.2.app/Contents/Developer
- name: Checkout code
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
ref: ${{ inputs.ref || github.sha }}
persist-credentials: false
- name: Setup Mise
uses: immich-app/devtools/actions/use-mise@3bca63ca3c15020293b36b51737a3ee2c773340b # use-mise-action-v3.1.0
uses: immich-app/devtools/actions/use-mise@7b8610a904d57da241e4ddba17fa62b62b15aed4 # use-mise-action-v2.0.2
with:
github_token: ${{ steps.token.outputs.token }}
working_directory: ./mobile
- name: Install Flutter dependencies
working-directory: ./mobile
@@ -237,7 +235,7 @@ jobs:
run: flutter build ios --config-only --no-codesign
- name: Setup Ruby
uses: ruby/setup-ruby@89f90524b88a01fe6e0b732220432cc6142926af # v1.313.0
uses: ruby/setup-ruby@afeafc3d1ab54a631816aba4c914a0081c12ff2f # v1.310.0
with:
ruby-version: '3.3'
bundler-cache: true
+2 -2
View File
@@ -19,13 +19,13 @@ jobs:
actions: write
steps:
- id: token
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
with:
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
- name: Check out code
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
token: ${{ steps.token.outputs.token }}
+2 -37
View File
@@ -4,7 +4,6 @@ on:
pull_request:
paths:
- 'open-api/**'
- 'mobile/lib/utils/openapi_patching.dart'
- '.github/workflows/check-openapi.yml'
concurrency:
@@ -20,47 +19,13 @@ jobs:
contents: read
steps:
- name: Checkout
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- name: Check for breaking API changes
uses: oasdiff/oasdiff-action/breaking@e24529087d93f837b28b50bb66ba9016380a7fcc # v0.1.2
uses: oasdiff/oasdiff-action/breaking@6147a58e5d1249a12f42fc864ab791d571a30015 # v0.0.47
with:
base: https://raw.githubusercontent.com/${{ github.repository }}/main/open-api/immich-openapi-specs.json
revision: open-api/immich-openapi-specs.json
fail-on: ERR
review: false
check-mobile-patches:
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: Checkout
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
with:
persist-credentials: false
- name: Setup Mise
uses: immich-app/devtools/actions/use-mise@3bca63ca3c15020293b36b51737a3ee2c773340b # use-mise-action-v3.1.0
with:
github_token: ${{ github.token }}
working_directory: ./mobile
- name: Get packages
working-directory: ./mobile
run: flutter pub get
- name: Fetch base spec from main
run: |
curl -fsSL \
"https://raw.githubusercontent.com/${{ github.repository }}/main/open-api/immich-openapi-specs.json" \
-o /tmp/base-spec.json
- name: Check newly-required fields have a backward-compat patch
working-directory: ./mobile
env:
OPENAPI_BASE_SPEC: /tmp/base-spec.json
OPENAPI_REVISION_SPEC: ../open-api/immich-openapi-specs.json
run: flutter test test/openapi_patches_coverage.dart
+12 -14
View File
@@ -31,27 +31,25 @@ jobs:
working-directory: ./packages/cli
steps:
- id: token
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
with:
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
- name: Checkout code
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
token: ${{ steps.token.outputs.token }}
- name: Setup Mise
uses: immich-app/devtools/actions/use-mise@3bca63ca3c15020293b36b51737a3ee2c773340b # use-mise-action-v3.1.0
uses: immich-app/devtools/actions/use-mise@7b8610a904d57da241e4ddba17fa62b62b15aed4 # use-mise-action-v2.0.2
with:
github_token: ${{ steps.token.outputs.token }}
- name: Publish
if: ${{ github.event_name == 'release' }}
env:
NPM_TAG: ${{ github.event.release.prerelease && 'rc' || 'latest' }}
run: mise run ci-publish -- --tag "$NPM_TAG"
run: mise run ci-publish
docker:
name: Docker
@@ -63,25 +61,25 @@ jobs:
steps:
- id: token
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
with:
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
- name: Checkout
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
token: ${{ steps.token.outputs.token }}
- name: Set up QEMU
uses: docker/setup-qemu-action@06116385d9baf250c9f4dcb4858b16962ea869c3 # v4.1.0
uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a # v4.0.0
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0
- name: Login to GitHub Container Registry
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0
if: ${{ !github.event.pull_request.head.repo.fork }}
with:
registry: ghcr.io
@@ -96,7 +94,7 @@ jobs:
- name: Generate docker image tags
id: metadata
uses: docker/metadata-action@80c7e94dd9b9319bd5eb7a0e0fe9291e23a2a2e9 # v6.1.0
uses: docker/metadata-action@030e881283bb7a6894de51c315a6bfe6a94e05cf # v6.0.0
with:
flavor: |
latest=false
@@ -104,10 +102,10 @@ jobs:
name=ghcr.io/${{ github.repository_owner }}/immich-cli
tags: |
type=raw,value=${{ steps.package-version.outputs.version }},enable=${{ github.event_name == 'release' }}
type=raw,value=latest,enable=${{ github.event_name == 'release' && !github.event.release.prerelease }}
type=raw,value=latest,enable=${{ github.event_name == 'release' }}
- name: Build and push image
uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7.2.0
uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f # v7.1.0
with:
file: packages/cli/Dockerfile
platforms: linux/amd64,linux/arm64
+2 -6
View File
@@ -14,11 +14,7 @@ jobs:
should_run: ${{ steps.should_run.outputs.run }}
steps:
- id: should_run
run: |
echo "run=${{
(github.event_name == 'issues' || github.event.discussion.category.name == 'Feature Request')
&& !contains(fromJSON('["OWNER", "MEMBER", "COLLABORATOR"]'), github.event.issue.author_association || github.event.discussion.author_association)
}}" >> "$GITHUB_OUTPUT"
run: echo "run=${{ github.event_name == 'issues' || github.event.discussion.category.name == 'Feature Request' }}" >> $GITHUB_OUTPUT
get_body:
runs-on: ubuntu-latest
@@ -39,7 +35,7 @@ jobs:
needs: [get_body, should_run]
if: ${{ needs.should_run.outputs.should_run == 'true' }}
container:
image: ghcr.io/immich-app/mdq:main@sha256:2a64c7f045cb7b580fbdf3614d7d1805f5775fec453e3d1023764180efa8c70b
image: ghcr.io/immich-app/mdq:main@sha256:0a8b8867773a0f8368061f47578603f438349f8f1f28b0e16105f481e5c794e0
outputs:
checked: ${{ steps.get_checkbox.outputs.checked }}
steps:
+5 -5
View File
@@ -44,20 +44,20 @@ jobs:
steps:
- id: token
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
with:
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
- name: Checkout repository
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
token: ${{ steps.token.outputs.token }}
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v4.36.2
uses: github/codeql-action/init@9e0d7b8d25671d64c341c19c0152d693099fb5ba # v4.35.5
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
@@ -70,7 +70,7 @@ jobs:
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v4.36.2
uses: github/codeql-action/autobuild@9e0d7b8d25671d64c341c19c0152d693099fb5ba # v4.35.5
# ️ Command-line programs to run using the OS shell.
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
@@ -83,6 +83,6 @@ jobs:
# ./location_of_script_within_repo/buildscript.sh
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v4.36.2
uses: github/codeql-action/analyze@9e0d7b8d25671d64c341c19c0152d693099fb5ba # v4.35.5
with:
category: '/language:${{matrix.language}}'
+7 -7
View File
@@ -23,7 +23,7 @@ jobs:
should_run: ${{ steps.check.outputs.should_run }}
steps:
- id: token
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
with:
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
@@ -60,7 +60,7 @@ jobs:
suffix: ['', '-cuda', '-rocm', '-openvino', '-armnn', '-rknn']
steps:
- name: Login to GitHub Container Registry
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
@@ -90,7 +90,7 @@ jobs:
suffix: ['']
steps:
- name: Login to GitHub Container Registry
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
@@ -132,7 +132,7 @@ jobs:
suffixes: '-rocm'
platforms: linux/amd64
runner-mapping: '{"linux/amd64": "pokedex-large"}'
uses: immich-app/devtools/.github/workflows/multi-runner-build.yml@50dc3a14f0606ecd8fc28d78d3a3c655115ab695 # multi-runner-build-workflow-v3.1.0
uses: immich-app/devtools/.github/workflows/multi-runner-build.yml@5813c7c4f7016c748ae7ac5d5f684846649d4d20 # multi-runner-build-workflow-v2.4.0
permissions:
contents: read
actions: read
@@ -147,7 +147,7 @@ jobs:
platforms: ${{ matrix.platforms }}
runner-mapping: ${{ matrix.runner-mapping }}
suffixes: ${{ matrix.suffixes }}
dockerhub-push: ${{ github.event_name == 'release' && !github.event.release.prerelease }}
dockerhub-push: ${{ github.event_name == 'release' }}
build-args: |
DEVICE=${{ matrix.device }}
@@ -155,7 +155,7 @@ jobs:
name: Build and Push Server
needs: pre-job
if: ${{ fromJSON(needs.pre-job.outputs.should_run).server == true }}
uses: immich-app/devtools/.github/workflows/multi-runner-build.yml@50dc3a14f0606ecd8fc28d78d3a3c655115ab695 # multi-runner-build-workflow-v3.1.0
uses: immich-app/devtools/.github/workflows/multi-runner-build.yml@5813c7c4f7016c748ae7ac5d5f684846649d4d20 # multi-runner-build-workflow-v2.4.0
permissions:
contents: read
actions: read
@@ -167,7 +167,7 @@ jobs:
image: immich-server
context: .
dockerfile: server/Dockerfile
dockerhub-push: ${{ github.event_name == 'release' && !github.event.release.prerelease }}
dockerhub-push: ${{ github.event_name == 'release' }}
build-args: |
DEVICE=cpu
+4 -4
View File
@@ -21,7 +21,7 @@ jobs:
should_run: ${{ steps.check.outputs.should_run }}
steps:
- id: token
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
with:
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
@@ -54,19 +54,19 @@ jobs:
steps:
- id: token
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
with:
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
- name: Checkout code
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
token: ${{ steps.token.outputs.token }}
- name: Setup Mise
uses: immich-app/devtools/actions/use-mise@3bca63ca3c15020293b36b51737a3ee2c773340b # use-mise-action-v3.1.0
uses: immich-app/devtools/actions/use-mise@7b8610a904d57da241e4ddba17fa62b62b15aed4 # use-mise-action-v2.0.2
with:
github_token: ${{ steps.token.outputs.token }}
+6 -14
View File
@@ -20,7 +20,7 @@ jobs:
artifact: ${{ steps.get-artifact.outputs.result }}
steps:
- id: token
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
with:
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
@@ -98,16 +98,9 @@ jobs:
shouldDeploy: true
};
} else if (eventType == "release") {
const tag = context.payload.workflow_run.head_branch;
const { data: release } = await github.rest.repos.getReleaseByTag({
owner: context.repo.owner,
repo: context.repo.repo,
tag,
});
parameters = {
event: "release",
name: tag,
prerelease: release.prerelease,
name: context.payload.workflow_run.head_branch,
shouldDeploy: !isFork
};
}
@@ -126,19 +119,19 @@ jobs:
if: ${{ fromJson(needs.checks.outputs.artifact).found && fromJson(needs.checks.outputs.parameters).shouldDeploy }}
steps:
- id: token
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
with:
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
- name: Checkout code
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
token: ${{ steps.token.outputs.token }}
- name: Setup Mise
uses: immich-app/devtools/actions/use-mise@3bca63ca3c15020293b36b51737a3ee2c773340b # use-mise-action-v3.1.0
uses: immich-app/devtools/actions/use-mise@7b8610a904d57da241e4ddba17fa62b62b15aed4 # use-mise-action-v2.0.2
with:
github_token: ${{ steps.token.outputs.token }}
@@ -153,7 +146,6 @@ jobs:
const parameters = JSON.parse(process.env.PARAM_JSON);
core.setOutput("event", parameters.event);
core.setOutput("name", parameters.name);
core.setOutput("prerelease", parameters.prerelease);
core.setOutput("shouldDeploy", parameters.shouldDeploy);
- name: Download artifact
@@ -211,7 +203,7 @@ jobs:
run: mise run //docs:deploy
- name: Deploy Docs Release Domain
if: ${{ steps.parameters.outputs.event == 'release' && steps.parameters.outputs.prerelease != 'true' }}
if: ${{ steps.parameters.outputs.event == 'release' }}
env:
TF_VAR_prefix_name: ${{ steps.parameters.outputs.name}}
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
+3 -3
View File
@@ -17,19 +17,19 @@ jobs:
pull-requests: write
steps:
- id: token
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
with:
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
- name: Checkout code
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
token: ${{ steps.token.outputs.token }}
- name: Setup Mise
uses: immich-app/devtools/actions/use-mise@3bca63ca3c15020293b36b51737a3ee2c773340b # use-mise-action-v3.1.0
uses: immich-app/devtools/actions/use-mise@7b8610a904d57da241e4ddba17fa62b62b15aed4 # use-mise-action-v2.0.2
with:
github_token: ${{ steps.token.outputs.token }}
+4 -4
View File
@@ -15,20 +15,20 @@ jobs:
pull-requests: write
steps:
- id: token
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
with:
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
- name: Checkout code
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
ref: ${{ github.event.pull_request.head.ref }}
persist-credentials: true
token: ${{ steps.token.outputs.token }}
- name: Setup Mise
uses: immich-app/devtools/actions/use-mise@3bca63ca3c15020293b36b51737a3ee2c773340b # use-mise-action-v3.1.0
uses: immich-app/devtools/actions/use-mise@7b8610a904d57da241e4ddba17fa62b62b15aed4 # use-mise-action-v2.0.2
with:
github_token: ${{ steps.token.outputs.token }}
@@ -45,7 +45,7 @@ jobs:
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
if: always()
with:
github-token: ${{ steps.token.outputs.token }}
github-token: ${{ steps.generate-token.outputs.token }}
script: |
github.rest.issues.removeLabel({
issue_number: context.payload.pull_request.number,
+1 -1
View File
@@ -14,7 +14,7 @@ jobs:
pull-requests: write
steps:
- id: token
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
with:
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
+1 -1
View File
@@ -12,7 +12,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- id: token
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
with:
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
+12 -25
View File
@@ -3,20 +3,16 @@ name: Prepare new release
on:
workflow_dispatch:
inputs:
releaseType:
description: 'Release type'
serverBump:
description: 'Bump server version'
required: true
default: 'false'
type: choice
options:
- 'false'
- major
- minor
- patch
- premajor
- preminor
- prepatch
- prerelease
- release
mobileBump:
description: 'Bump mobile build number'
required: false
@@ -50,45 +46,38 @@ jobs:
outputs:
ref: ${{ steps.push-tag.outputs.commit_long_sha }}
version: ${{ steps.output.outputs.version }}
rc: ${{ steps.output.outputs.rc }}
permissions: {} # No job-level permissions are needed because it uses the app-token
steps:
- id: token
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
with:
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
- name: Checkout code
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
token: ${{ steps.token.outputs.token }}
persist-credentials: true
ref: main
- name: Setup Mise
uses: immich-app/devtools/actions/use-mise@3bca63ca3c15020293b36b51737a3ee2c773340b # use-mise-action-v3.1.0
uses: immich-app/devtools/actions/use-mise@7b8610a904d57da241e4ddba17fa62b62b15aed4 # use-mise-action-v2.0.2
with:
github_token: ${{ steps.token.outputs.token }}
# TODO move to mise
- name: Install uv
uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
- name: Bump version
env:
RELEASE_TYPE: ${{ inputs.releaseType }}
SERVER_BUMP: ${{ inputs.serverBump }}
MOBILE_BUMP: ${{ inputs.mobileBump }}
run: mise //:release --type "${RELEASE_TYPE}" --mobile "${MOBILE_BUMP}"
run: misc/release/pump-version.sh -s "${SERVER_BUMP}" -m "${MOBILE_BUMP}"
- id: output
run: |
echo "version=$IMMICH_VERSION" >> $GITHUB_OUTPUT
if [[ "$IMMICH_VERSION" =~ -rc\.[0-9]+$ ]]; then
echo "rc=true" >> $GITHUB_OUTPUT
else
echo "rc=false" >> $GITHUB_OUTPUT
fi
run: echo "version=$IMMICH_VERSION" >> $GITHUB_OUTPUT
- name: Commit and tag
id: push-tag
@@ -104,7 +93,6 @@ jobs:
needs: bump_version
permissions:
contents: read
pull-requests: write
secrets:
KEY_JKS: ${{ secrets.KEY_JKS }}
ALIAS: ${{ secrets.ALIAS }}
@@ -137,7 +125,7 @@ jobs:
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
- name: Checkout
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
token: ${{ steps.generate-token.outputs.token }}
persist-credentials: false
@@ -149,10 +137,9 @@ jobs:
github-token: ${{ steps.generate-token.outputs.token }}
- name: Create draft release
uses: softprops/action-gh-release@b4309332981a82ec1c5618f44dd2e27cc8bfbfda # v3.0.0
uses: softprops/action-gh-release@3bb12739c298aeb8a4eeaf626c5b8d85266b0e65 # v2.6.2
with:
draft: true
prerelease: ${{ needs.bump_version.outputs.rc }}
tag_name: ${{ needs.bump_version.outputs.version }}
token: ${{ steps.generate-token.outputs.token }}
generate_release_notes: true
+2 -2
View File
@@ -14,7 +14,7 @@ jobs:
pull-requests: write
steps:
- id: token
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
with:
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
@@ -32,7 +32,7 @@ jobs:
pull-requests: write
steps:
- id: token
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
with:
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
+4 -6
View File
@@ -16,19 +16,19 @@ jobs:
packages: write
steps:
- id: token
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
with:
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
- name: Checkout code
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
token: ${{ steps.token.outputs.token }}
- name: Setup Mise
uses: immich-app/devtools/actions/use-mise@3bca63ca3c15020293b36b51737a3ee2c773340b # use-mise-action-v3.1.0
uses: immich-app/devtools/actions/use-mise@7b8610a904d57da241e4ddba17fa62b62b15aed4 # use-mise-action-v2.0.2
with:
github_token: ${{ steps.token.outputs.token }}
@@ -39,6 +39,4 @@ jobs:
run: pnpm --filter @immich/sdk build
- name: Publish
env:
NPM_TAG: ${{ github.event.release.prerelease && 'rc' || 'latest' }}
run: pnpm --filter @immich/sdk publish --provenance --no-git-checks --tag "$NPM_TAG"
run: pnpm --filter @immich/sdk publish --provenance --no-git-checks
+8 -7
View File
@@ -20,7 +20,7 @@ jobs:
should_run: ${{ steps.check.outputs.should_run }}
steps:
- id: token
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
with:
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
@@ -49,22 +49,21 @@ jobs:
working-directory: ./mobile
steps:
- id: token
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
with:
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
- name: Checkout code
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
token: ${{ steps.token.outputs.token }}
- name: Setup Mise
uses: immich-app/devtools/actions/use-mise@3bca63ca3c15020293b36b51737a3ee2c773340b # use-mise-action-v3.1.0
uses: immich-app/devtools/actions/use-mise@7b8610a904d57da241e4ddba17fa62b62b15aed4 # use-mise-action-v2.0.2
with:
github_token: ${{ steps.token.outputs.token }}
working_directory: ./mobile
- name: Install dependencies
run: flutter pub get
@@ -73,6 +72,10 @@ jobs:
run: flutter pub get
working-directory: ./mobile/packages/ui
- name: Install dependencies for UI Showcase
run: flutter pub get
working-directory: ./mobile/packages/ui/showcase
- name: Generate translation files
run: mise //mobile:codegen:translation
@@ -90,8 +93,6 @@ jobs:
mobile/**/*.g.dart
mobile/**/*.gr.dart
mobile/**/*.drift.dart
mobile/**/*.g.swift
mobile/**/*.g.kt
- name: Verify files have not changed
if: steps.verify-changed-files.outputs.files_changed == 'true'
+48 -83
View File
@@ -17,7 +17,7 @@ jobs:
should_run: ${{ steps.check.outputs.should_run }}
steps:
- id: token
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
with:
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
@@ -28,10 +28,6 @@ jobs:
with:
github-token: ${{ steps.token.outputs.token }}
filters: |
scripts:
- 'packages/scripts/**'
- 'pnpm-lock.yaml'
- 'mise.toml'
i18n:
- 'i18n/**'
- 'mise.toml'
@@ -45,8 +41,6 @@ jobs:
- 'server/**'
- 'pnpm-lock.yaml'
- 'mise.toml'
- 'packages/plugin-core/**'
- 'packages/plugin-sdk/**'
cli:
- 'packages/cli/**'
- 'packages/sdk/**'
@@ -68,34 +62,6 @@ jobs:
- '.github/workflows/test.yml'
force-events: 'workflow_dispatch'
script-unit-tests:
name: Scripts unit tests
needs: pre-job
if: ${{ fromJSON(needs.pre-job.outputs.should_run).scripts == true }}
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- id: token
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
with:
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
- name: Checkout code
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
with:
persist-credentials: false
token: ${{ steps.token.outputs.token }}
- name: Setup Mise
uses: immich-app/devtools/actions/use-mise@3bca63ca3c15020293b36b51737a3ee2c773340b # use-mise-action-v3.1.0
with:
github_token: ${{ steps.token.outputs.token }}
- name: Run unit tests
run: pnpm --filter @immich/scripts test
server-unit-tests:
name: Test & Lint Server
needs: pre-job
@@ -105,19 +71,19 @@ jobs:
contents: read
steps:
- id: token
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
with:
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
- name: Checkout code
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
token: ${{ steps.token.outputs.token }}
- name: Setup Mise
uses: immich-app/devtools/actions/use-mise@3bca63ca3c15020293b36b51737a3ee2c773340b # use-mise-action-v3.1.0
uses: immich-app/devtools/actions/use-mise@7b8610a904d57da241e4ddba17fa62b62b15aed4 # use-mise-action-v2.0.2
with:
github_token: ${{ steps.token.outputs.token }}
@@ -136,19 +102,19 @@ jobs:
working-directory: ./packages/cli
steps:
- id: token
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
with:
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
- name: Checkout code
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
token: ${{ steps.token.outputs.token }}
- name: Setup Mise
uses: immich-app/devtools/actions/use-mise@3bca63ca3c15020293b36b51737a3ee2c773340b # use-mise-action-v3.1.0
uses: immich-app/devtools/actions/use-mise@7b8610a904d57da241e4ddba17fa62b62b15aed4 # use-mise-action-v2.0.2
with:
github_token: ${{ steps.token.outputs.token }}
@@ -167,19 +133,19 @@ jobs:
working-directory: ./packages/cli
steps:
- id: token
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
with:
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
- name: Checkout code
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
token: ${{ steps.token.outputs.token }}
- name: Setup Mise
uses: immich-app/devtools/actions/use-mise@3bca63ca3c15020293b36b51737a3ee2c773340b # use-mise-action-v3.1.0
uses: immich-app/devtools/actions/use-mise@7b8610a904d57da241e4ddba17fa62b62b15aed4 # use-mise-action-v2.0.2
with:
github_token: ${{ steps.token.outputs.token }}
@@ -211,19 +177,19 @@ jobs:
working-directory: ./web
steps:
- id: token
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
with:
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
- name: Checkout code
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
token: ${{ steps.token.outputs.token }}
- name: Setup Mise
uses: immich-app/devtools/actions/use-mise@3bca63ca3c15020293b36b51737a3ee2c773340b # use-mise-action-v3.1.0
uses: immich-app/devtools/actions/use-mise@7b8610a904d57da241e4ddba17fa62b62b15aed4 # use-mise-action-v2.0.2
with:
github_token: ${{ steps.token.outputs.token }}
@@ -249,19 +215,19 @@ jobs:
working-directory: ./web
steps:
- id: token
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
with:
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
- name: Checkout code
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
token: ${{ steps.token.outputs.token }}
- name: Setup Mise
uses: immich-app/devtools/actions/use-mise@3bca63ca3c15020293b36b51737a3ee2c773340b # use-mise-action-v3.1.0
uses: immich-app/devtools/actions/use-mise@7b8610a904d57da241e4ddba17fa62b62b15aed4 # use-mise-action-v2.0.2
with:
github_token: ${{ steps.token.outputs.token }}
@@ -277,19 +243,19 @@ jobs:
contents: read
steps:
- id: token
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
with:
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
- name: Checkout code
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
token: ${{ steps.token.outputs.token }}
- name: Setup Mise
uses: immich-app/devtools/actions/use-mise@3bca63ca3c15020293b36b51737a3ee2c773340b # use-mise-action-v3.1.0
uses: immich-app/devtools/actions/use-mise@7b8610a904d57da241e4ddba17fa62b62b15aed4 # use-mise-action-v2.0.2
with:
github_token: ${{ steps.token.outputs.token }}
@@ -327,19 +293,19 @@ jobs:
working-directory: ./e2e
steps:
- id: token
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
with:
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
- name: Checkout code
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
token: ${{ steps.token.outputs.token }}
- name: Setup Mise
uses: immich-app/devtools/actions/use-mise@3bca63ca3c15020293b36b51737a3ee2c773340b # use-mise-action-v3.1.0
uses: immich-app/devtools/actions/use-mise@7b8610a904d57da241e4ddba17fa62b62b15aed4 # use-mise-action-v2.0.2
with:
github_token: ${{ steps.token.outputs.token }}
@@ -359,20 +325,20 @@ jobs:
working-directory: ./server
steps:
- id: token
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
with:
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
- name: Checkout code
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
submodules: 'recursive'
token: ${{ steps.token.outputs.token }}
- name: Setup Mise
uses: immich-app/devtools/actions/use-mise@3bca63ca3c15020293b36b51737a3ee2c773340b # use-mise-action-v3.1.0
uses: immich-app/devtools/actions/use-mise@7b8610a904d57da241e4ddba17fa62b62b15aed4 # use-mise-action-v2.0.2
with:
github_token: ${{ steps.token.outputs.token }}
@@ -395,20 +361,20 @@ jobs:
runner: [ubuntu-latest, ubuntu-24.04-arm]
steps:
- id: token
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
with:
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
- name: Checkout code
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
submodules: 'recursive'
token: ${{ steps.token.outputs.token }}
- name: Setup pnpm
uses: pnpm/action-setup@0ebf47130e4866e96fce0953f49152a61190b271 # v6.0.9
uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v5.0.0
- name: Setup Node
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
@@ -472,20 +438,20 @@ jobs:
runner: [ubuntu-latest, ubuntu-24.04-arm]
steps:
- id: token
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
with:
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
- name: Checkout code
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
submodules: 'recursive'
token: ${{ steps.token.outputs.token }}
- name: Setup pnpm
uses: pnpm/action-setup@0ebf47130e4866e96fce0953f49152a61190b271 # v6.0.9
uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v5.0.0
- name: Setup Node
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
@@ -580,21 +546,20 @@ jobs:
contents: read
steps:
- id: token
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
with:
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
token: ${{ steps.token.outputs.token }}
- name: Setup Mise
uses: immich-app/devtools/actions/use-mise@3bca63ca3c15020293b36b51737a3ee2c773340b # use-mise-action-v3.1.0
uses: immich-app/devtools/actions/use-mise@7b8610a904d57da241e4ddba17fa62b62b15aed4 # use-mise-action-v2.0.2
with:
github_token: ${{ steps.token.outputs.token }}
working_directory: ./mobile
- name: Install dependencies
run: flutter pub get
@@ -618,18 +583,18 @@ jobs:
working-directory: ./machine-learning
steps:
- id: token
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
with:
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
token: ${{ steps.token.outputs.token }}
- name: Setup Mise
uses: immich-app/devtools/actions/use-mise@3bca63ca3c15020293b36b51737a3ee2c773340b # use-mise-action-v3.1.0
uses: immich-app/devtools/actions/use-mise@7b8610a904d57da241e4ddba17fa62b62b15aed4 # use-mise-action-v2.0.2
with:
github_token: ${{ steps.token.outputs.token }}
@@ -648,19 +613,19 @@ jobs:
working-directory: ./.github
steps:
- id: token
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
with:
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
- name: Checkout code
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
token: ${{ steps.token.outputs.token }}
- name: Setup Mise
uses: immich-app/devtools/actions/use-mise@3bca63ca3c15020293b36b51737a3ee2c773340b # use-mise-action-v3.1.0
uses: immich-app/devtools/actions/use-mise@7b8610a904d57da241e4ddba17fa62b62b15aed4 # use-mise-action-v2.0.2
with:
github_token: ${{ steps.token.outputs.token }}
@@ -678,12 +643,12 @@ jobs:
contents: read
steps:
- id: token
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
with:
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
token: ${{ steps.token.outputs.token }}
@@ -699,19 +664,19 @@ jobs:
contents: read
steps:
- id: token
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
with:
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
- name: Checkout code
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
token: ${{ steps.token.outputs.token }}
- name: Setup Mise
uses: immich-app/devtools/actions/use-mise@3bca63ca3c15020293b36b51737a3ee2c773340b # use-mise-action-v3.1.0
uses: immich-app/devtools/actions/use-mise@7b8610a904d57da241e4ddba17fa62b62b15aed4 # use-mise-action-v2.0.2
with:
github_token: ${{ steps.token.outputs.token }}
@@ -757,19 +722,19 @@ jobs:
- 5432:5432
steps:
- id: token
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
with:
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
- name: Checkout code
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
token: ${{ steps.token.outputs.token }}
- name: Setup Mise
uses: immich-app/devtools/actions/use-mise@3bca63ca3c15020293b36b51737a3ee2c773340b # use-mise-action-v3.1.0
uses: immich-app/devtools/actions/use-mise@7b8610a904d57da241e4ddba17fa62b62b15aed4 # use-mise-action-v2.0.2
with:
github_token: ${{ steps.token.outputs.token }}
+2 -2
View File
@@ -24,7 +24,7 @@ jobs:
should_run: ${{ steps.check.outputs.should_run }}
steps:
- id: token
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
with:
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
@@ -47,7 +47,7 @@ jobs:
if: ${{ fromJSON(needs.pre-job.outputs.should_run).i18n == true }}
steps:
- id: token
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
with:
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
-1
View File
@@ -60,7 +60,6 @@
"explorer.fileNesting.patterns": {
"*.dart": "${capture}.g.dart,${capture}.gr.dart,${capture}.drift.dart",
"*.ts": "${capture}.spec.ts,${capture}.mock.ts",
"*.js": "${capture}.spec.js,${capture}.mock.js",
"package.json": "package-lock.json, yarn.lock, pnpm-lock.yaml, bun.lockb, bun.lock, pnpm-workspace.yaml, .pnpmfile.cjs"
},
"search.exclude": {
+1 -1
View File
@@ -4,4 +4,4 @@
/web/ @danieldietzler
/machine-learning/ @mertalev
/e2e/ @danieldietzler
/mobile/ @shenlong-tanwen @santoshakil
/mobile/ @shenlong-tanwen
+134
View File
@@ -0,0 +1,134 @@
# Contributor Covenant Code of Conduct
## Our Pledge
We as members, contributors, and leaders pledge to make participation
in our community a harassment-free experience for everyone, regardless
of age, body size, visible or invisible disability, ethnicity, sex
characteristics, gender identity and expression, level of experience,
education, socio-economic status, nationality, personal appearance,
race, religion, or sexual identity and orientation.
We pledge to act and interact in ways that contribute to an open,
welcoming, diverse, inclusive, and healthy community.
## Our Standards
Examples of behavior that contributes to a positive environment for
our community include:
- Demonstrating empathy and kindness toward other people
- Being respectful of differing opinions, viewpoints, and experiences
- Giving and gracefully accepting constructive feedback
- Accepting responsibility and apologizing to those affected by our
mistakes, and learning from the experience
- Focusing on what is best not just for us as individuals, but for the
overall community
Examples of unacceptable behavior include:
- The use of sexualized language or imagery, and sexual attention or
advances of any kind
- Trolling, insulting or derogatory comments, and personal or
political attacks
- Public or private harassment
- Publishing others' private information, such as a physical or email
address, without their explicit permission
- Other conduct which could reasonably be considered inappropriate in
a professional setting
## Enforcement Responsibilities
Community leaders are responsible for clarifying and enforcing our
standards of acceptable behavior and will take appropriate and fair
corrective action in response to any behavior that they deem
inappropriate, threatening, offensive, or harmful.
Community leaders have the right and responsibility to remove, edit,
or reject comments, commits, code, wiki edits, issues, and other
contributions that are not aligned to this Code of Conduct, and will
communicate reasons for moderation decisions when appropriate.
## Scope
This Code of Conduct applies within all community spaces, and also
applies when an individual is officially representing the community in
public spaces. Examples of representing our community include using an
official e-mail address, posting via an official social media account,
or acting as an appointed representative at an online or offline
event.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior
may be reported to the community leaders responsible for enforcement
at our Discord channel. All complaints
will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and
security of the reporter of any incident.
## Enforcement Guidelines
Community leaders will follow these Community Impact Guidelines in
determining the consequences for any action they deem in violation of
this Code of Conduct:
### 1. Correction
**Community Impact**: Use of inappropriate language or other behavior
deemed unprofessional or unwelcome in the community.
**Consequence**: A private, written warning from community leaders,
providing clarity around the nature of the violation and an
explanation of why the behavior was inappropriate. A public apology
may be requested.
### 2. Warning
**Community Impact**: A violation through a single incident or series
of actions.
**Consequence**: A warning with consequences for continued
behavior. No interaction with the people involved, including
unsolicited interaction with those enforcing the Code of Conduct, for
a specified period of time. This includes avoiding interactions in
community spaces as well as external channels like social
media. Violating these terms may lead to a temporary or permanent ban.
### 3. Temporary Ban
**Community Impact**: A serious violation of community standards,
including sustained inappropriate behavior.
**Consequence**: A temporary ban from any sort of interaction or
public communication with the community for a specified period of
time. No public or private interaction with the people involved,
including unsolicited interaction with those enforcing the Code of
Conduct, is allowed during this period. Violating these terms may lead
to a permanent ban.
### 4. Permanent Ban
**Community Impact**: Demonstrating a pattern of violation of
community standards, including sustained inappropriate behavior,
harassment of an individual, or aggression toward or disparagement of
classes of individuals.
**Consequence**: A permanent ban from any sort of public interaction
within the community.
## Attribution
This Code of Conduct is adapted from the [Contributor
Covenant][homepage], version 2.0, available at
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
Community Impact Guidelines were inspired by [Mozilla's code of
conduct enforcement ladder](https://github.com/mozilla/diversity).
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see the
FAQ at https://www.contributor-covenant.org/faq. Translations are
available at https://www.contributor-covenant.org/translations.
+24 -15
View File
@@ -1,46 +1,46 @@
dev:
@printf "This command has been removed. Please use:\n\n mise dev # or mise //:dev from another directory\n\n" >&2 && exit 1
@printf "This command has been removed. Please use:\n\n mise dev # or mise //:dev from another directory\n\n"\n\n >&2 && exit 1
dev-down:
@printf "This command has been removed. Please use:\n\n mise dev-down # or mise //:dev-down from another directory\n\n" >&2 && exit 1
@printf "This command has been removed. Please use:\n\n mise dev-down # or mise //:dev-down from another directory\n\n"\n\n >&2 && exit 1
dev-update:
@printf "This command has been removed. Please use:\n\n mise dev-update # or mise //:dev-update from another directory\n\n" >&2 && exit 1
@printf "This command has been removed. Please use:\n\n mise dev-update # or mise //:dev-update from another directory\n\n"\n\n >&2 && exit 1
dev-scale:
@printf "This command has been removed. Please use:\n\n mise dev-scale # or mise //:dev-scale from another directory\n\n" >&2 && exit 1
@printf "This command has been removed. Please use:\n\n mise dev-scale # or mise //:dev-scale from another directory\n\n"\n\n >&2 && exit 1
dev-docs:
npm --prefix docs run start
.PHONY: e2e
e2e:
@printf "This command has been removed. Please use:\n\n mise e2e # or mise //:e2e from another directory\n\n" >&2 && exit 1
@printf "This command has been removed. Please use:\n\n mise e2e # or mise //:e2e from another directory\n\n"\n\n >&2 && exit 1
e2e-dev:
@printf "This command has been removed. Please use:\n\n mise e2e-dev # or mise //:e2e-dev from another directory\n\n" >&2 && exit 1
@printf "This command has been removed. Please use:\n\n mise e2e-dev # or mise //:e2e-dev from another directory\n\n"\n\n >&2 && exit 1
e2e-update:
@printf "This command has been removed. Please use:\n\n mise e2e-update # or mise //:e2e-update from another directory\n\n" >&2 && exit 1
@printf "This command has been removed. Please use:\n\n mise e2e-update # or mise //:e2e-update from another directory\n\n"\n\n >&2 && exit 1
e2e-down:
@printf "This command has been removed. Please use:\n\n mise e2e-down # or mise //:e2e-down from another directory\n\n" >&2 && exit 1
@printf "This command has been removed. Please use:\n\n mise e2e-down # or mise //:e2e-down from another directory\n\n"\n\n >&2 && exit 1
prod:
@printf "This command has been removed. Please use:\n\n mise prod # or mise //:prod from another directory\n\n" >&2 && exit 1
@printf "This command has been removed. Please use:\n\n mise prod # or mise //:prod from another directory\n\n"\n\n >&2 && exit 1
prod-down:
@printf "This command has been removed. Please use:\n\n mise prod-down # or mise //:prod-down from another directory\n\n" >&2 && exit 1
@printf "This command has been removed. Please use:\n\n mise prod-down # or mise //:prod-down from another directory\n\n"\n\n >&2 && exit 1
prod-scale:
@printf "This command has been removed. Please use:\n\n mise prod-scale # or mise //:prod-scale from another directory\n\n" >&2 && exit 1
@printf "This command has been removed. Please use:\n\n mise prod-scale # or mise //:prod-scale from another directory\n\n"\n\n >&2 && exit 1
.PHONY: open-api
open-api:
@printf "This command has been removed. Please use:\n\n mise open-api # or mise //:open-api from another directory\n\n" >&2 && exit 1
@printf "This command has been removed. Please use:\n\n mise open-api # or mise //:open-api from another directory\n\n"\n\n >&2 && exit 1
sql:
@printf "This command has been removed. Please use:\n\n mise sql # or mise //:sql from another directory\n\n" >&2 && exit 1
@printf "This command has been removed. Please use:\n\n mise sql # or mise //:sql from another directory\n\n"\n\n >&2 && exit 1
renovate:
@@ -52,7 +52,16 @@ renovate:
MODULES = e2e server web cli sdk docs .github
test-e2e:
@printf "This command has been removed. Please use:\n\n mise //e2e:test # or mise //e2e:test-web for web tests, respectively\n\n" >&2 && exit 1
docker compose -f ./e2e/docker-compose.yml build
pnpm --filter immich-e2e run test
pnpm --filter immich-e2e run test:web
clean:
@printf "This command has been removed. Please use:\n\n mise clean # or mise //:clean from another directory\n\n" >&2 && exit 1
find . -name "node_modules" -type d -prune -exec rm -rf {} +
find . -name "dist" -type d -prune -exec rm -rf '{}' +
find . -name "build" -type d -prune -exec rm -rf '{}' +
find . -name ".svelte-kit" -type d -prune -exec rm -rf '{}' +
find . -name "coverage" -type d -prune -exec rm -rf '{}' +
find . -name ".pnpm-store" -type d -prune -exec rm -rf '{}' +
command -v docker >/dev/null 2>&1 && docker compose -f ./docker/docker-compose.dev.yml down -v --remove-orphans || true
command -v docker >/dev/null 2>&1 && docker compose -f ./e2e/docker-compose.yml down -v --remove-orphans || true
+5
View File
@@ -0,0 +1,5 @@
# Security Policy
## Reporting a Vulnerability
Please report security issues to `security@immich.app`
+1 -1
View File
@@ -154,7 +154,7 @@ services:
redis:
container_name: immich_redis
image: docker.io/valkey/valkey:9@sha256:4963247afc4cd33c7d3b2d2816b9f7f8eeebab148d29056c2ca4d7cbc966f2d9
image: docker.io/valkey/valkey:9@sha256:8436e10bc65c94886a91d4415b6a6dfa9cb5a306fb3b996e5bb67cd2b4854193
healthcheck:
test: redis-cli ping || exit 1
+3 -3
View File
@@ -56,7 +56,7 @@ services:
redis:
container_name: immich_redis
image: docker.io/valkey/valkey:9@sha256:4963247afc4cd33c7d3b2d2816b9f7f8eeebab148d29056c2ca4d7cbc966f2d9
image: docker.io/valkey/valkey:9@sha256:8436e10bc65c94886a91d4415b6a6dfa9cb5a306fb3b996e5bb67cd2b4854193
healthcheck:
test: redis-cli ping || exit 1
restart: always
@@ -85,7 +85,7 @@ services:
container_name: immich_prometheus
ports:
- 9090:9090
image: prom/prometheus@sha256:a75c5a35bc21d7afe69551eefa3cb1e1fb1775fe759408007a66b54ec3de1f29
image: prom/prometheus@sha256:e4254400b85610324913f0dc4acf92603d9984e7519414c5a12811aa6146acc3
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
- prometheus-data:/prometheus
@@ -97,7 +97,7 @@ services:
command: ['./run.sh', '-disable-reporting']
ports:
- 3000:3000
image: grafana/grafana:12.4.4-ubuntu@sha256:df2e7ef5f32f771794cf76bad5f2bceac227036460a2cc269a9045e5662abc58
image: grafana/grafana:12.4.3-ubuntu@sha256:ca3f764fdc48cebdf22dd206f33ecb0795a9a7210eacd1b5c02204aebd78b223
volumes:
- grafana-data:/var/lib/grafana
+1 -1
View File
@@ -61,7 +61,7 @@ services:
redis:
container_name: immich_redis
image: docker.io/valkey/valkey:9@sha256:4963247afc4cd33c7d3b2d2816b9f7f8eeebab148d29056c2ca4d7cbc966f2d9
image: docker.io/valkey/valkey:9@sha256:8436e10bc65c94886a91d4415b6a6dfa9cb5a306fb3b996e5bb67cd2b4854193
user: '1000:1000'
security_opt:
- no-new-privileges:true
+1 -1
View File
@@ -49,7 +49,7 @@ services:
redis:
container_name: immich_redis
image: docker.io/valkey/valkey:9@sha256:4963247afc4cd33c7d3b2d2816b9f7f8eeebab148d29056c2ca4d7cbc966f2d9
image: docker.io/valkey/valkey:9@sha256:8436e10bc65c94886a91d4415b6a6dfa9cb5a306fb3b996e5bb67cd2b4854193
healthcheck:
test: redis-cli ping || exit 1
restart: always
@@ -14,8 +14,6 @@ Under Email, enter the required details to connect with an SMTP server.
You can use [this guide](/guides/smtp-gmail) to use Gmail's SMTP server.
You can use [this guide](/guides/smtp-microsoft365) to use Microsoft's SMTP server.
## User's notifications settings
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:
@@ -17,7 +17,7 @@ running `apt install postgresql-NN-pgvector`, where `NN` is your Postgres versio
You must install VectorChord into your instance of Postgres using their [instructions][vchord-install]. After installation, add `shared_preload_libraries = 'vchord.so'` to your `postgresql.conf`. If you already have some `shared_preload_libraries` set, you can separate each extension with a comma. For example, `shared_preload_libraries = 'pg_stat_statements, vchord.so'`.
:::note Supported versions
Immich is known to work with Postgres versions `>= 14, < 20`.
Immich is known to work with Postgres versions `>= 14, < 19`.
VectorChord is known to work with pgvector versions `>= 0.7, < 0.9`.
@@ -144,7 +144,7 @@ ALTER TABLE face_search ALTER COLUMN embedding SET DATA TYPE vector(512);
<details>
<summary>Migration steps</summary>
1. Ensure you have at least `0.7.0` of pgvector installed. If it is below that, please upgrade it and run the SQL command `ALTER EXTENSION vector UPDATE;` using psql or your choice of database client
1. Ensure you have at least 0.7.0 of pgvector installed. If it is below that, please upgrade it and run the SQL command `ALTER EXTENSION vector UPDATE;` using psql or your choice of database client
2. Follow the Prerequisites to install VectorChord
3. If Immich does not have superuser permissions, run the SQL command `CREATE EXTENSION vchord CASCADE;`
4. Remove the `DB_VECTOR_EXTENSION=pgvector` environmental variable as it will make Immich still use pgvector if set
+1 -1
View File
@@ -112,7 +112,7 @@ services:
traefik.enable: true
# increase readingTimeouts for the entrypoint used here
traefik.http.routers.immich.entrypoints: websecure
traefik.http.routers.immich.rule: Host(`immich.example.com`)
traefik.http.routers.immich.rule: Host(`immich.your-domain.com`)
traefik.http.services.immich.loadbalancer.server.port: 2283
```
+1 -1
View File
@@ -90,7 +90,7 @@ immich-admin list-users
[
{
id: 'e65e6f88-2a30-4dbe-8dd9-1885f4889b53',
email: 'immich@example.com',
email: 'immich@example.com.com',
name: 'Immich Admin',
storageLabel: 'admin',
externalPath: null,
+1 -1
View File
@@ -7,7 +7,7 @@ Immich uses the [OpenAPI](https://swagger.io/specification/) standard to generat
OpenAPI is used to generate the client (Typescript, Dart) SDK. `openapi-generator-cli` can be installed [here](https://openapi-generator.tech/docs/installation/). The generated SDK is based on the `immich-openapi-specs.json` file, which is autogenerated by the server **when running in development mode**. The `immich-openapi-specs.json` file can be modified with `@nestjs/swagger` decorators used or referenced by controller endpoints. See the [NestJS OpenAPI docs](https://docs.nestjs.com/openapi/types-and-parameters) for more info. When you add a new endpoint or modify an existing one, you must run the server in development mode and run the command below to update the client SDK.
```bash
mise open-api
make open-api
```
You can find the generated client SDK in the `packages/sdk/client` for Typescript SDK and `mobile/openapi` for Dart SDK.
+1 -1
View File
@@ -218,7 +218,7 @@ When the Dev Container starts, it automatically:
- Debug ports: 9230 (workers), 9231 (API)
:::info
The Dev Container setup replaces the `mise dev` command from the traditional setup. All services start automatically when you open the container.
The Dev Container setup replaces the `make dev` command from the traditional setup. All services start automatically when you open the container.
:::
### Accessing Services
+1 -1
View File
@@ -12,11 +12,11 @@ Our [GitHub Repository](https://github.com/immich-app/immich) is a [monorepo](ht
| `.vscode/` | VSCode debug launch profiles |
| `packages/cli` | Source code for the CLI |
| `packages/sdk` | Source code for the generated OpenAPI SDK |
| `packages/scripts` | Scripts for version bumps and draft releases |
| `docker/` | Docker compose resources for dev, test, production |
| `design/` | Screenshots and logos for the README |
| `docs/` | Source code for the [https://immich.app](https://immich.app) website |
| `machine-learning/` | Source code for the `immich-machine-learning` docker image |
| `misc/release/` | Scripts for version bumps and draft releases |
| `mobile/` | Source code for the mobile app, both Android and iOS |
| `server/` | Source code for the `immich-server` docker image |
| `web/` | Source code for the `web` |
+1 -1
View File
@@ -2,7 +2,7 @@
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 (`mise dev`, ....). Feel free to contribute!
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:
+2 -20
View File
@@ -45,7 +45,7 @@ All the services are packaged to run as with single Docker Compose command.
5. From the root directory, run:
```bash title="Start development server"
mise dev
make dev # required Makefile installed on the system.
```
5. Access the dev instance in your browser at http://localhost:3000, or connect via the mobile app.
@@ -88,7 +88,7 @@ To see local changes to `@immich/ui` in Immich, do the following:
3. Uncomment the corresponding volume in web service of the `docker/docker-compose.dev.yml` file (`../../ui:/usr/src/ui`)
4. Uncomment the corresponding alias in the `web/vite.config.ts` file (`'@immich/ui': path.resolve(\_\_dirname, '../../ui/packages/ui')`)
5. Uncomment the import statement in `web/src/app.css` file `@import '../../../ui/packages/ui/dist/theme/default.css';` and comment out `@import '@immich/ui/theme/default.css';`
6. Start up the stack via `mise dev`
6. Start up the stack via `make dev`
7. After making changes in `@immich/ui`, rebuild it (`pnpm run build`)
### Mobile app
@@ -109,24 +109,6 @@ mise //mobile:translation
The mobile app asks you what backend to connect to. You can utilize the demo backend (https://demo.immich.app/) if you don't need to change server code or upload photos. Alternatively, you can run the server yourself per the instructions above.
#### UI components and widget previews
Shared design-system widgets (buttons, inputs, forms) live in the
[`immich_ui` package](https://github.com/immich-app/immich/tree/main/mobile/packages/ui/)
under `mobile/packages/ui/`. Components are defined in `lib/src/components/`
and have matching previews in `lib/src/previews/`.
To inspect a component in isolation with a light/dark toggle and hot reload,
launch [Flutter's Widget Previewer](https://docs.flutter.dev/tools/widget-previewer):
```bash
cd mobile/packages/ui
flutter widget-preview start
```
In VS Code or Android Studio with the Flutter plugin, the previewer
auto-starts when you open the **Flutter Widget Preview** tab in the sidebar.
## IDE setup
### Lint / format extensions
+1 -1
View File
@@ -12,7 +12,7 @@ You need to run `mise //server:install` before _once_.
The e2e tests can be run by first starting up a test production environment via:
```bash
mise e2e
make e2e
```
Before you can run the tests, you need to run the following commands _once_:
+10 -10
View File
@@ -15,14 +15,14 @@ When using "Deduplicate All" or viewing suggestions, Immich automatically presel
### Synchronizing metadata
When resolving duplicates, metadata from trashed assets is automatically synchronized to the kept asset. This synchronization only happens when **exactly one** asset is kept and at least one asset is trashed. When more than one asset is kept, metadata is not merged — the assets keep their own metadata and are simply removed from the duplicate group. The following metadata is synchronized:
When resolving duplicates, metadata from trashed assets is automatically synchronized to the kept assets. The following metadata is synchronized:
| Name | Description |
| ----------- | ------------------------------------------------------------------------------------------------------------------------------ |
| Album | The kept asset will be added to _every_ album that the other assets in the group belong to. |
| Favorite | If any of the assets in the group have been added to favorites, the kept asset will also be added to favorites. |
| Rating | If one or more assets in the duplicate group have a rating, the highest rating is selected and synchronized to the kept asset. |
| Description | Descriptions from each asset are combined together and synchronized to the kept asset. |
| Visibility | The most restrictive visibility is applied to the kept asset. |
| Location | Latitude and longitude are copied if all assets with geolocation data in the group share the same coordinates. |
| Tag | Tags from all assets in the group are merged and applied to the kept asset. |
| Name | Description |
| ----------- | ------------------------------------------------------------------------------------------------------------------------------- |
| Album | The kept assets will be added to _every_ album that the other assets in the group belong to. |
| Favorite | If any of the assets in the group have been added to favorites, every kept asset will also be added to favorites. |
| Rating | If one or more assets in the duplicate group have a rating, the highest rating is selected and synchronized to the kept assets. |
| Description | Descriptions from each asset are combined together and synchronized to all the kept assets. |
| Visibility | The most restrictive visibility is applied to the kept assets. |
| Location | Latitude and longitude are copied if all assets with geolocation data in the group share the same coordinates. |
| Tag | Tags from all assets in the group are merged and applied to every kept asset. |
+1 -3
View File
@@ -13,9 +13,7 @@ import MobileAppBackup from '/docs/partials/_mobile-app-backup.md';
:::info Android verification
Below are the SHA-256 fingerprints for the certificates signing the android applications.
- Google Play releases:
`5A:22:C1:83:47:54:05:F5:49:C4:EB:9F:B2:6C:2E:93:A3:EF:9C:57:66:15:0A:7A:F3:8C:8D:3F:E5:15:CC:D6`
- GitHub releases:
- Playstore / Github releases:
`86:C5:C4:55:DF:AF:49:85:92:3A:8F:35:AD:B3:1D:0C:9E:0B:95:7D:7F:94:C2:D2:AF:6A:24:38:AA:96:00:20`
- F-Droid releases:
`FA:8B:43:95:F4:A6:47:71:A0:53:D1:C7:57:73:5F:A2:30:13:74:F5:3D:58:0D:D1:75:AA:F7:A1:35:72:9C:BF`
+1 -1
View File
@@ -17,7 +17,7 @@ services:
ports:
- "8888:80"
environment:
PGADMIN_DEFAULT_EMAIL: admin@example.com
PGADMIN_DEFAULT_EMAIL: user-name@domain-name.com
PGADMIN_DEFAULT_PASSWORD: strong-password
volumes:
- pgadmin-data:/var/lib/pgadmin
Binary file not shown.

Before

Width:  |  Height:  |  Size: 102 KiB

-19
View File
@@ -1,19 +0,0 @@
# SMTP settings using Microsoft 365
This guide walks you through how to get the information you need to set up your Immich instance to send emails using Microsoft's SMTP server.
## Create an app password
You will need to generate an app password to use your Microsoft email in Immich. Depending on if you have a personal or business account, you can use https://go.microsoft.com/fwlink/?linkid=2274139 or https://myaccount.microsoft.com/securtiy-info respectively.
## Entering the SMTP credential in Immich
Entering your credential in Immich's email notification settings at `Administration -> Settings -> Notification Settings`
Host: smtp-mail.outlook.com
Port: 587
username: your mail address
Password: app password you created earlier
SMTPS: set it to disabled
<img src={require('./img/email-ms-settings.webp').default} width="80%" title="SMTP settings" />
+1 -3
View File
@@ -20,11 +20,9 @@ Hardware and software requirements for Immich:
- **RAM**: Minimum 6GB, recommended 8GB.
- **CPU**: Minimum 2 cores, recommended 4 cores.
- Immich runs on the `amd64` and `arm64` platforms.
Since `v3`, the machine learning container on `amd64` requires the `>= x86-64-v2` [microarchitecture level](https://en.wikipedia.org/wiki/X86-64#Microarchitecture_levels).
Since `v2.6`, the machine learning container on `amd64` requires the `>= x86-64-v2` [microarchitecture level](https://en.wikipedia.org/wiki/X86-64#Microarchitecture_levels).
Most CPUs released since ~2012 support this microarchitecture.
If you are using a virtual machine, ensure you have selected a [supported microarchitecture](https://pve.proxmox.com/pve-docs/chapter-qm.html#_qemu_cpu_types).
If you are unable to support this instruction set, the last version to support `x86-64-v1` is `v2.7.5`.
Note that this release is no longer supported, and you must run a matching `immich-server` version.
- **Storage**: Recommended Unix-compatible filesystem (EXT4, ZFS, APFS, etc.) with support for user/group ownership and permissions.
- The generation of thumbnails and transcoded video can increase the size of the photo library by 10-20% on average.
+1 -4
View File
@@ -1,8 +1,5 @@
# @generated - this file is auto-generated by `mise lock` https://mise.en.dev/dev-tools/mise-lock.html
[[tools.wrangler]]
version = "4.100.0"
version = "4.66.0"
backend = "npm:wrangler"
[tools.wrangler.options]
allow_builds = '["esbuild", "sharp", "workerd"]'
+1 -1
View File
@@ -28,4 +28,4 @@ run = "prettier --write ."
run = "wrangler pages deploy build --project-name=${PROJECT_NAME} --branch=${BRANCH_NAME}"
[tools]
wrangler = "4.100.0"
wrangler = "4.91.0"
-4
View File
@@ -1,8 +1,4 @@
[
{
"label": "v3.0.0-rc.3",
"url": "https://docs.v3.0.0-rc.3.archive.immich.app"
},
{
"label": "v2.7.5",
"url": "https://docs.v2.7.5.archive.immich.app"
+2 -3
View File
@@ -4,8 +4,7 @@ services:
e2e-auth-server:
container_name: immich-e2e-auth-server
build:
context: ../
dockerfile: packages/e2e-auth-server/Dockerfile
context: ../packages/e2e-auth-server
ports:
- 2286:2286
@@ -45,7 +44,7 @@ services:
redis:
container_name: immich-e2e-redis
image: docker.io/valkey/valkey:9@sha256:4963247afc4cd33c7d3b2d2816b9f7f8eeebab148d29056c2ca4d7cbc966f2d9
image: docker.io/valkey/valkey:9@sha256:8436e10bc65c94886a91d4415b6a6dfa9cb5a306fb3b996e5bb67cd2b4854193
healthcheck:
test: redis-cli ping || exit 1
+1 -16
View File
@@ -1,21 +1,11 @@
[tasks.install]
run = "pnpm install --filter immich-e2e --frozen-lockfile"
[tasks.build]
dir = "{{ config_root }}"
run = "docker compose build"
[tasks.test]
depends = ["//e2e:build", "//e2e:ci-setup"]
env._.path = "./node_modules/.bin"
run = "vitest --run"
[tasks.playwright-install]
env._.path = "./node_modules/.bin"
run = "playwright install"
[tasks."test-web"]
depends = ["//e2e:build", "//e2e:ci-setup", "//e2e:playwright-install"]
env._.path = "./node_modules/.bin"
run = "playwright test"
@@ -40,12 +30,7 @@ run = "tsc --noEmit"
[tasks.ci-setup]
depends = [
"//:sdk:install",
"//:sdk:build",
"//packages/cli:install",
"//packages/cli:build",
]
depends = ["//:sdk:install", "//:sdk:build", "//cli:install", "//cli:build"]
run = { task = ":install" }
+3 -2
View File
@@ -1,6 +1,6 @@
{
"name": "immich-e2e",
"version": "3.0.0-rc.3",
"version": "2.7.5",
"description": "",
"main": "index.js",
"type": "module",
@@ -32,7 +32,7 @@
"@playwright/test": "^1.44.1",
"@socket.io/component-emitter": "^3.1.2",
"@types/luxon": "^3.4.2",
"@types/node": "^24.13.2",
"@types/node": "^24.12.4",
"@types/pg": "^8.15.1",
"@types/pngjs": "^6.0.4",
"@types/supertest": "^7.0.0",
@@ -54,6 +54,7 @@
"typescript": "^6.0.0",
"typescript-eslint": "^8.28.0",
"utimes": "^5.2.1",
"vite-tsconfig-paths": "^6.1.1",
"vitest": "^4.0.0"
}
}
@@ -99,7 +99,7 @@ describe('/admin/maintenance', () => {
},
{
interval: 500,
timeout: 60_000,
timeout: 10_000,
},
)
.toBeTruthy();
@@ -190,7 +190,7 @@ describe('/admin/maintenance', () => {
},
{
interval: 500,
timeout: 60_000,
timeout: 10_000,
},
)
.toBeFalsy();
+7 -8
View File
@@ -504,14 +504,13 @@ describe('/albums', () => {
});
});
it('should deduplicate owner from albumUsers on create', async () => {
it('should not be able to share album with owner', async () => {
const { status, body } = await request(app)
.post('/albums')
.send({ albumName: 'New album', albumUsers: [{ role: AlbumUserRole.Editor, userId: user1.userId }] })
.set('Authorization', `Bearer ${user1.accessToken}`);
expect(status).toBe(201);
expect(body.albumUsers).toHaveLength(1);
expect(body.albumUsers[0]).toMatchObject({ role: AlbumUserRole.Owner, user: { id: user1.userId } });
expect(status).toBe(400);
expect(body).toEqual(errorDto.badRequest('Cannot share album with owner'));
});
});
@@ -730,8 +729,8 @@ describe('/albums', () => {
.set('Authorization', `Bearer ${user1.accessToken}`)
.send({ albumUsers: [{ userId: user1.userId, role: AlbumUserRole.Editor }] });
expect(status).toBe(200);
expect(body.albumUsers.length).toEqual(1);
expect(status).toBe(400);
expect(body).toEqual(errorDto.badRequest('User already added'));
});
it('should not be able to add existing user to shared album', async () => {
@@ -745,8 +744,8 @@ describe('/albums', () => {
.set('Authorization', `Bearer ${user1.accessToken}`)
.send({ albumUsers: [{ userId: user2.userId, role: AlbumUserRole.Editor }] });
expect(status).toBe(200);
expect(body.albumUsers.length).toEqual(2);
expect(status).toBe(400);
expect(body).toEqual(errorDto.badRequest('User already added'));
});
});
@@ -1,669 +0,0 @@
import {
AssetMediaResponseDto,
IntegrityReportResponseDto,
LoginResponseDto,
ManualJobName,
QueueCommand,
QueueName,
} from '@immich/sdk';
import { readFile } from 'node:fs/promises';
import { app, testAssetDir, utils } from 'src/utils';
import request from 'supertest';
import { afterEach, beforeAll, describe, expect, it } from 'vitest';
const assetFilepath = `${testAssetDir}/metadata/gps-position/thompson-springs.jpg`;
const asset1Filepath = `${testAssetDir}/albums/nature/el_torcal_rocks.jpg`;
const asset2Filepath = `${testAssetDir}/albums/nature/wood_anemones.jpg`;
describe('/admin/integrity', () => {
let admin: LoginResponseDto;
let asset: AssetMediaResponseDto;
let user1: LoginResponseDto;
let asset1: AssetMediaResponseDto;
let user2: LoginResponseDto;
let asset2: AssetMediaResponseDto;
beforeAll(async () => {
await utils.resetDatabase();
admin = await utils.adminSetup();
user1 = await utils.userSetup(admin.accessToken, {
email: '1@example.com',
name: '1',
password: '1',
});
user2 = await utils.userSetup(admin.accessToken, {
email: '2@example.com',
name: '2',
password: '2',
});
for (const queue of Object.values(QueueName)) {
if (queue === QueueName.IntegrityCheck) {
continue;
}
await utils.queueCommand(admin.accessToken, queue, {
command: QueueCommand.Pause,
});
}
asset = await utils.createAsset(admin.accessToken, {
assetData: {
filename: 'asset.jpg',
bytes: await readFile(assetFilepath),
},
});
asset1 = await utils.createAsset(user1.accessToken, {
assetData: {
filename: 'asset.jpg',
bytes: await readFile(asset1Filepath),
},
});
asset2 = await utils.createAsset(user2.accessToken, {
assetData: {
filename: 'asset.jpg',
bytes: await readFile(asset2Filepath),
},
});
await utils.mkFolder('/data/bak');
await utils.copyFolder(`/data/upload/${admin.userId}`, `/data/bak/${admin.userId}`);
for (const queue of Object.values(QueueName)) {
if (queue === QueueName.IntegrityCheck) {
continue;
}
await utils.queueCommand(admin.accessToken, queue, {
command: QueueCommand.Empty,
});
await utils.queueCommand(admin.accessToken, queue, {
command: QueueCommand.Resume,
});
}
});
afterEach(async () => {
await utils.deleteFolder(`/data/upload/${admin.userId}`);
await utils.copyFolder(`/data/bak/${admin.userId}`, `/data/upload/${admin.userId}`);
});
describe('POST /summary (& jobs)', async () => {
it.sequential('reports no issues', async () => {
await utils.createJob(admin.accessToken, {
name: ManualJobName.IntegrityUntrackedFiles,
});
await utils.createJob(admin.accessToken, {
name: ManualJobName.IntegrityMissingFiles,
});
await utils.createJob(admin.accessToken, {
name: ManualJobName.IntegrityChecksumMismatch,
});
await utils.waitForQueueFinish(admin.accessToken, QueueName.IntegrityCheck);
await utils.createJob(admin.accessToken, {
name: ManualJobName.IntegrityUntrackedFilesDeleteAll,
});
await utils.waitForQueueFinish(admin.accessToken, QueueName.IntegrityCheck);
const { status, body } = await request(app)
.get('/admin/integrity/summary')
.set('Authorization', `Bearer ${admin.accessToken}`)
.send();
expect(status).toBe(200);
expect(body).toEqual({
missing_file: 0,
untracked_file: 0,
checksum_mismatch: 0,
});
});
it.sequential('should detect an untracked file (job: check untracked files)', async () => {
await utils.putTextFile('untracked', `/data/upload/${admin.userId}/untracked1.png`);
await utils.createJob(admin.accessToken, {
name: ManualJobName.IntegrityUntrackedFiles,
});
await utils.waitForQueueFinish(admin.accessToken, QueueName.IntegrityCheck);
const { status, body } = await request(app)
.get('/admin/integrity/summary')
.set('Authorization', `Bearer ${admin.accessToken}`)
.send();
expect(status).toBe(200);
expect(body).toEqual(
expect.objectContaining({
untracked_file: 1,
}),
);
});
it.sequential('should detect outdated untracked file reports (job: refresh untracked files)', async () => {
// these should not be detected:
await utils.putTextFile('untracked', `/data/upload/${admin.userId}/untracked2.png`);
await utils.putTextFile('untracked', `/data/upload/${admin.userId}/untracked3.png`);
await utils.createJob(admin.accessToken, {
name: ManualJobName.IntegrityUntrackedFilesRefresh,
});
await utils.waitForQueueFinish(admin.accessToken, QueueName.IntegrityCheck);
const { status, body } = await request(app)
.get('/admin/integrity/summary')
.set('Authorization', `Bearer ${admin.accessToken}`)
.send();
expect(status).toBe(200);
expect(body).toEqual(
expect.objectContaining({
untracked_file: 0,
}),
);
});
it.sequential('should delete untracked files (job: delete all untracked file reports)', async () => {
await utils.putTextFile('untracked', `/data/upload/${admin.userId}/untracked1.png`);
await utils.createJob(admin.accessToken, {
name: ManualJobName.IntegrityUntrackedFiles,
});
await utils.waitForQueueFinish(admin.accessToken, QueueName.IntegrityCheck);
await utils.createJob(admin.accessToken, {
name: ManualJobName.IntegrityUntrackedFilesDeleteAll,
});
await utils.waitForQueueFinish(admin.accessToken, QueueName.IntegrityCheck);
const { status, body } = await request(app)
.get('/admin/integrity/summary')
.set('Authorization', `Bearer ${admin.accessToken}`)
.send();
expect(status).toBe(200);
expect(body).toEqual(
expect.objectContaining({
untracked_file: 0,
}),
);
});
it.sequential('should detect a missing file and not a checksum mismatch (job: check missing files)', async () => {
await utils.deleteFolder(`/data/upload/${admin.userId}`);
await utils.createJob(admin.accessToken, {
name: ManualJobName.IntegrityMissingFiles,
});
await utils.waitForQueueFinish(admin.accessToken, QueueName.IntegrityCheck);
const { status, body } = await request(app)
.get('/admin/integrity/summary')
.set('Authorization', `Bearer ${admin.accessToken}`)
.send();
expect(status).toBe(200);
expect(body).toEqual(
expect.objectContaining({
missing_file: 1,
checksum_mismatch: 0,
}),
);
});
it.sequential('should detect outdated missing file reports (job: refresh missing files)', async () => {
await utils.createJob(admin.accessToken, {
name: ManualJobName.IntegrityMissingFilesRefresh,
});
await utils.waitForQueueFinish(admin.accessToken, QueueName.IntegrityCheck);
const { status, body } = await request(app)
.get('/admin/integrity/summary')
.set('Authorization', `Bearer ${admin.accessToken}`)
.send();
expect(status).toBe(200);
expect(body).toEqual(
expect.objectContaining({
missing_file: 0,
checksum_mismatch: 0,
}),
);
});
it.sequential('should delete assets with missing files (job: delete all missing file reports)', async () => {
await utils.deleteFolder(`/data/upload/${user1.userId}`);
await utils.createJob(admin.accessToken, {
name: ManualJobName.IntegrityMissingFiles,
});
await utils.waitForQueueFinish(admin.accessToken, QueueName.IntegrityCheck);
const { status: listStatus, body: listBody } = await request(app)
.get('/admin/integrity/summary')
.set('Authorization', `Bearer ${admin.accessToken}`)
.send();
expect(listStatus).toBe(200);
expect(listBody).toEqual(
expect.objectContaining({
missing_file: 1,
}),
);
await utils.createJob(admin.accessToken, {
name: ManualJobName.IntegrityMissingFilesDeleteAll,
});
await utils.waitForQueueFinish(admin.accessToken, QueueName.IntegrityCheck);
const { status, body } = await request(app)
.get('/admin/integrity/summary')
.set('Authorization', `Bearer ${admin.accessToken}`)
.send();
expect(status).toBe(200);
expect(body).toEqual(
expect.objectContaining({
missing_file: 0,
}),
);
await expect(utils.getAssetInfo(user1.accessToken, asset1.id)).resolves.toEqual(
expect.objectContaining({
isTrashed: true,
}),
);
});
it.sequential('should detect a checksum mismatch (job: check file checksums)', async () => {
await utils.truncateFolder(`/data/upload/${admin.userId}`);
await utils.createJob(admin.accessToken, {
name: ManualJobName.IntegrityChecksumMismatch,
});
await utils.waitForQueueFinish(admin.accessToken, QueueName.IntegrityCheck);
const { status, body } = await request(app)
.get('/admin/integrity/summary')
.set('Authorization', `Bearer ${admin.accessToken}`)
.send();
expect(status).toBe(200);
expect(body).toEqual(
expect.objectContaining({
checksum_mismatch: 1,
}),
);
});
it.sequential('should detect outdated checksum mismatch reports (job: refresh file checksums)', async () => {
await utils.createJob(admin.accessToken, {
name: ManualJobName.IntegrityChecksumMismatchRefresh,
});
await utils.waitForQueueFinish(admin.accessToken, QueueName.IntegrityCheck);
const { status, body } = await request(app)
.get('/admin/integrity/summary')
.set('Authorization', `Bearer ${admin.accessToken}`)
.send();
expect(status).toBe(200);
expect(body).toEqual(
expect.objectContaining({
checksum_mismatch: 0,
}),
);
});
it.sequential(
'should delete assets with mismatched checksum (job: delete all checksum mismatch reports)',
async () => {
await utils.truncateFolder(`/data/upload/${user2.userId}`);
await utils.createJob(admin.accessToken, {
name: ManualJobName.IntegrityChecksumMismatch,
});
await utils.waitForQueueFinish(admin.accessToken, QueueName.IntegrityCheck);
const { status: listStatus, body: listBody } = await request(app)
.get('/admin/integrity/summary')
.set('Authorization', `Bearer ${admin.accessToken}`)
.send();
expect(listStatus).toBe(200);
expect(listBody).toEqual(
expect.objectContaining({
checksum_mismatch: 1,
}),
);
await utils.createJob(admin.accessToken, {
name: ManualJobName.IntegrityChecksumMismatchDeleteAll,
});
await utils.waitForQueueFinish(admin.accessToken, QueueName.IntegrityCheck);
const { status, body } = await request(app)
.get('/admin/integrity/summary')
.set('Authorization', `Bearer ${admin.accessToken}`)
.send();
expect(status).toBe(200);
expect(body).toEqual(
expect.objectContaining({
checksum_mismatch: 0,
}),
);
await expect(utils.getAssetInfo(user2.accessToken, asset2.id)).resolves.toEqual(
expect.objectContaining({
isTrashed: true,
}),
);
},
);
});
describe('POST /report', async () => {
it.sequential('reports untracked files', async () => {
await utils.putTextFile('untracked', `/data/upload/${admin.userId}/untracked1.png`);
await utils.createJob(admin.accessToken, {
name: ManualJobName.IntegrityUntrackedFiles,
});
await utils.waitForQueueFinish(admin.accessToken, QueueName.IntegrityCheck);
const { status, body } = await request(app)
.get('/admin/integrity/report?type=untracked_file')
.set('Authorization', `Bearer ${admin.accessToken}`)
.send();
expect(status).toBe(200);
expect(body).toEqual({
nextCursor: undefined,
items: expect.arrayContaining([
{
id: expect.any(String),
type: 'untracked_file',
path: `/data/upload/${admin.userId}/untracked1.png`,
assetId: null,
fileAssetId: null,
createdAt: expect.any(String),
},
]),
});
});
it.sequential('reports missing files', async () => {
await utils.deleteFolder(`/data/upload/${admin.userId}`);
await utils.createJob(admin.accessToken, {
name: ManualJobName.IntegrityMissingFiles,
});
await utils.waitForQueueFinish(admin.accessToken, QueueName.IntegrityCheck);
const { status, body } = await request(app)
.get('/admin/integrity/report?type=missing_file')
.set('Authorization', `Bearer ${admin.accessToken}`)
.send();
expect(status).toBe(200);
expect(body).toEqual({
nextCursor: undefined,
items: expect.arrayContaining([
{
id: expect.any(String),
type: 'missing_file',
path: expect.any(String),
assetId: asset.id,
fileAssetId: null,
createdAt: expect.any(String),
},
]),
});
});
it.sequential('reports checksum mismatched files', async () => {
await utils.truncateFolder(`/data/upload/${admin.userId}`);
await utils.createJob(admin.accessToken, {
name: ManualJobName.IntegrityChecksumMismatch,
});
await utils.waitForQueueFinish(admin.accessToken, QueueName.IntegrityCheck);
const { status, body } = await request(app)
.get('/admin/integrity/report?type=checksum_mismatch')
.set('Authorization', `Bearer ${admin.accessToken}`)
.send();
expect(status).toBe(200);
expect(body).toEqual({
nextCursor: undefined,
items: expect.arrayContaining([
{
id: expect.any(String),
type: 'checksum_mismatch',
path: expect.any(String),
assetId: asset.id,
fileAssetId: null,
createdAt: expect.any(String),
},
]),
});
});
});
describe('DELETE /report/:id', async () => {
it.sequential('delete untracked files', async () => {
await utils.putTextFile('untracked', `/data/upload/${admin.userId}/untracked1.png`);
await utils.createJob(admin.accessToken, {
name: ManualJobName.IntegrityUntrackedFiles,
});
await utils.waitForQueueFinish(admin.accessToken, QueueName.IntegrityCheck);
const { status: listStatus, body: listBody } = await request(app)
.get('/admin/integrity/report?type=untracked_file')
.set('Authorization', `Bearer ${admin.accessToken}`)
.send();
expect(listStatus).toBe(200);
const report = (listBody as IntegrityReportResponseDto).items.find(
(item) => item.path === `/data/upload/${admin.userId}/untracked1.png`,
)!;
const { status } = await request(app)
.delete(`/admin/integrity/report/${report.id}`)
.set('Authorization', `Bearer ${admin.accessToken}`)
.send();
expect(status).toBe(200);
await utils.createJob(admin.accessToken, {
name: ManualJobName.IntegrityUntrackedFiles,
});
await utils.waitForQueueFinish(admin.accessToken, QueueName.IntegrityCheck);
const { status: listStatus2, body: listBody2 } = await request(app)
.get('/admin/integrity/report?type=untracked_file')
.set('Authorization', `Bearer ${admin.accessToken}`)
.send();
expect(listStatus2).toBe(200);
expect(listBody2).not.toBe(
expect.objectContaining({
items: expect.arrayContaining([
expect.objectContaining({
id: report.id,
}),
]),
}),
);
});
it.sequential('delete assets missing files', async () => {
await utils.deleteFolder(`/data/upload/${admin.userId}`);
await utils.createJob(admin.accessToken, {
name: ManualJobName.IntegrityMissingFiles,
});
await utils.waitForQueueFinish(admin.accessToken, QueueName.IntegrityCheck);
const { status: listStatus, body: listBody } = await request(app)
.get('/admin/integrity/report?type=missing_file')
.set('Authorization', `Bearer ${admin.accessToken}`)
.send();
expect(listStatus).toBe(200);
expect(listBody.items.length).toBe(1);
const report = (listBody as IntegrityReportResponseDto).items[0];
const { status } = await request(app)
.delete(`/admin/integrity/report/${report.id}`)
.set('Authorization', `Bearer ${admin.accessToken}`)
.send();
expect(status).toBe(200);
await utils.createJob(admin.accessToken, {
name: ManualJobName.IntegrityMissingFiles,
});
await utils.waitForQueueFinish(admin.accessToken, QueueName.IntegrityCheck);
const { status: listStatus2, body: listBody2 } = await request(app)
.get('/admin/integrity/report?type=missing_file')
.set('Authorization', `Bearer ${admin.accessToken}`)
.send();
expect(listStatus2).toBe(200);
expect(listBody2.items.length).toBe(0);
});
it.sequential('delete assets with failing checksum', async () => {
await utils.truncateFolder(`/data/upload/${admin.userId}`);
await utils.createJob(admin.accessToken, {
name: ManualJobName.IntegrityChecksumMismatch,
});
await utils.waitForQueueFinish(admin.accessToken, QueueName.IntegrityCheck);
const { status: listStatus, body: listBody } = await request(app)
.get('/admin/integrity/report?type=checksum_mismatch')
.set('Authorization', `Bearer ${admin.accessToken}`)
.send();
expect(listStatus).toBe(200);
expect(listBody.items.length).toBe(1);
const report = (listBody as IntegrityReportResponseDto).items[0];
const { status } = await request(app)
.delete(`/admin/integrity/report/${report.id}`)
.set('Authorization', `Bearer ${admin.accessToken}`)
.send();
expect(status).toBe(200);
await utils.createJob(admin.accessToken, {
name: ManualJobName.IntegrityChecksumMismatch,
});
await utils.waitForQueueFinish(admin.accessToken, QueueName.IntegrityCheck);
const { status: listStatus2, body: listBody2 } = await request(app)
.get('/admin/integrity/report?type=checksum_mismatch')
.set('Authorization', `Bearer ${admin.accessToken}`)
.send();
expect(listStatus2).toBe(200);
expect(listBody2.items.length).toBe(0);
});
});
describe('GET /report/:type/csv', () => {
it.sequential('exports untracked files as csv', async () => {
await utils.putTextFile('untracked', `/data/upload/${admin.userId}/untracked1.png`);
await utils.createJob(admin.accessToken, {
name: ManualJobName.IntegrityUntrackedFiles,
});
await utils.waitForQueueFinish(admin.accessToken, QueueName.IntegrityCheck);
const { status, headers, text } = await request(app)
.get('/admin/integrity/report/untracked_file/csv')
.set('Authorization', `Bearer ${admin.accessToken}`)
.send();
expect(status).toBe(200);
expect(headers['content-type']).toContain('text/csv');
expect(headers['content-disposition']).toContain('.csv');
expect(text).toContain('id,type,assetId,fileAssetId,path');
expect(text).toContain(`untracked_file`);
expect(text).toContain(`/data/upload/${admin.userId}/untracked1.png`);
});
});
describe('GET /report/:id/file', () => {
it.sequential('downloads untracked file', async () => {
await utils.putTextFile('untracked-content', `/data/upload/${admin.userId}/untracked1.png`);
await utils.createJob(admin.accessToken, {
name: ManualJobName.IntegrityUntrackedFiles,
});
await utils.waitForQueueFinish(admin.accessToken, QueueName.IntegrityCheck);
const { body: listBody } = await request(app)
.get('/admin/integrity/report?type=untracked_file')
.set('Authorization', `Bearer ${admin.accessToken}`)
.send();
const report = (listBody as IntegrityReportResponseDto).items.find(
(item) => item.path === `/data/upload/${admin.userId}/untracked1.png`,
)!;
const { status, headers, body } = await request(app)
.get(`/admin/integrity/report/${report.id}/file`)
.set('Authorization', `Bearer ${admin.accessToken}`)
.buffer(true)
.send();
expect(status).toBe(200);
expect(headers['content-type']).toContain('application/octet-stream');
expect(body.toString()).toBe('untracked-content');
});
});
});
+6 -47
View File
@@ -2,7 +2,6 @@ import { AssetVisibility, LoginResponseDto } from '@immich/sdk';
import { readFile } from 'node:fs/promises';
import { basename, join } from 'node:path';
import { Socket } from 'socket.io-client';
import { createUserDto } from 'src/fixtures';
import { errorDto } from 'src/responses';
import { app, testAssetDir, utils } from 'src/utils';
import request from 'supertest';
@@ -10,48 +9,28 @@ import { afterAll, beforeAll, describe, expect, it } from 'vitest';
describe('/map', () => {
let websocket: Socket;
let partnerWebsocket: Socket;
let admin: LoginResponseDto;
let partner: LoginResponseDto;
let partnerArchivedAssetId: string;
let adminArchivedAssetId: string;
beforeAll(async () => {
await utils.resetDatabase();
admin = await utils.adminSetup({ onboarding: false });
partner = await utils.userSetup(admin.accessToken, createUserDto.user1);
websocket = await utils.connectWebsocket(admin.accessToken);
partnerWebsocket = await utils.connectWebsocket(partner.accessToken);
const adminFiles = ['formats/heic/IMG_2682.heic', 'metadata/gps-position/thompson-springs.jpg'];
const adminArchivedFile = 'metadata/dates/datetimeoriginal-gps.jpg';
const partnerFile = 'metadata/gps-position/thompson-springs.jpg';
const files = ['formats/heic/IMG_2682.heic', 'metadata/gps-position/thompson-springs.jpg'];
utils.resetEvents();
const uploadFile = async (accessToken: string, input: string) => {
const uploadFile = async (input: string) => {
const filepath = join(testAssetDir, input);
const { id } = await utils.createAsset(accessToken, {
const { id } = await utils.createAsset(admin.accessToken, {
assetData: { bytes: await readFile(filepath), filename: basename(filepath) },
});
await utils.waitForWebsocketEvent({ event: 'assetUpload', id });
return id;
};
await Promise.all(adminFiles.map((f) => uploadFile(admin.accessToken, f)));
[adminArchivedAssetId, partnerArchivedAssetId] = await Promise.all([
uploadFile(admin.accessToken, adminArchivedFile),
uploadFile(partner.accessToken, partnerFile),
]);
await Promise.all([
utils.archiveAssets(admin.accessToken, [adminArchivedAssetId]),
utils.archiveAssets(partner.accessToken, [partnerArchivedAssetId]),
utils.createPartner(partner.accessToken, admin.userId),
]);
await Promise.all(files.map((f) => uploadFile(f)));
});
afterAll(() => {
utils.disconnectWebsocket(websocket);
utils.disconnectWebsocket(partnerWebsocket);
});
describe('GET /map/markers', () => {
@@ -61,6 +40,7 @@ describe('/map', () => {
expect(body).toEqual(errorDto.unauthorized);
});
// TODO archive one of these assets
it('should get map markers for all non-archived assets', async () => {
const { status, body } = await request(app)
.get('/map/markers')
@@ -89,28 +69,7 @@ describe('/map', () => {
]);
});
it('should not expose partner archived asset locations', async () => {
const { status, body } = await request(app)
.get('/map/markers')
.query({ withPartners: true, isArchived: true })
.set('Authorization', `Bearer ${admin.accessToken}`);
expect(status).toBe(200);
const ids = body.map((m: { id: string }) => m.id);
expect(ids).not.toContain(partnerArchivedAssetId);
expect(ids).toContain(adminArchivedAssetId);
});
it('should include own archived asset locations', async () => {
const { status, body } = await request(app)
.get('/map/markers')
.query({ isArchived: true })
.set('Authorization', `Bearer ${admin.accessToken}`);
expect(status).toBe(200);
expect(body.map((m: { id: string }) => m.id)).toContain(adminArchivedAssetId);
});
// TODO archive one of these assets
it('should get all map markers', async () => {
const { status, body } = await request(app)
.get('/map/markers')
@@ -259,6 +259,17 @@ describe('/search', () => {
assets: [assetHeic],
}),
},
{
should: "should search city ('')",
deferred: () => ({
dto: {
city: '',
visibility: AssetVisibility.Timeline,
includeNull: true,
},
assets: [assetLast],
}),
},
{
should: 'should search city (null)',
deferred: () => ({
@@ -280,6 +291,18 @@ describe('/search', () => {
assets: [assetDensity],
}),
},
{
should: "should search state ('')",
deferred: () => ({
dto: {
state: '',
visibility: AssetVisibility.Timeline,
withExif: true,
includeNull: true,
},
assets: [assetLast, assetNotocactus],
}),
},
{
should: 'should search state (null)',
deferred: () => ({
@@ -301,6 +324,17 @@ describe('/search', () => {
assets: [assetFalcon],
}),
},
{
should: "should search country ('')",
deferred: () => ({
dto: {
country: '',
visibility: AssetVisibility.Timeline,
includeNull: true,
},
assets: [assetLast],
}),
},
{
should: 'should search country (null)',
deferred: () => ({
@@ -95,7 +95,6 @@ describe('/server', () => {
major: expect.any(Number),
minor: expect.any(Number),
patch: expect.any(Number),
prerelease: expect.anything(),
});
});
});
@@ -116,7 +115,6 @@ describe('/server', () => {
oauthAutoLaunch: false,
ocr: false,
passwordLogin: true,
realtimeTranscoding: false,
search: true,
sidecar: true,
trash: true,
@@ -141,7 +139,6 @@ describe('/server', () => {
maintenanceMode: false,
mapDarkStyleUrl: 'https://tiles.immich.cloud/v1/style/dark.json',
mapLightStyleUrl: 'https://tiles.immich.cloud/v1/style/light.json',
minFaces: 3,
});
});
});
@@ -21,18 +21,18 @@ describe('/system-config', () => {
const response1 = await request(app)
.put('/system-config')
.set('Authorization', `Bearer ${admin.accessToken}`)
.send({ ...config, newVersionCheck: { enabled: false, channel: 'stable' } });
.send({ ...config, newVersionCheck: { enabled: false } });
expect(response1.status).toBe(200);
expect(response1.body).toEqual({ ...config, newVersionCheck: { enabled: false, channel: 'stable' } });
expect(response1.body).toEqual({ ...config, newVersionCheck: { enabled: false } });
const response2 = await request(app)
.put('/system-config')
.set('Authorization', `Bearer ${admin.accessToken}`)
.send({ ...config, newVersionCheck: { enabled: true, channel: 'stable' } });
.send({ ...config, newVersionCheck: { enabled: true } });
expect(response2.status).toBe(200);
expect(response2.body).toEqual({ ...config, newVersionCheck: { enabled: true, channel: 'stable' } });
expect(response2.body).toEqual({ ...config, newVersionCheck: { enabled: true } });
});
it('should reject an invalid config entry', async () => {
-15
View File
@@ -230,21 +230,6 @@ describe('/users', () => {
const after = await getMyPreferences({ headers: asBearerAuth(admin.accessToken) });
expect(after).toMatchObject({ download: { includeEmbeddedVideos: true } });
});
it('should update minimum face count to display people', async () => {
const before = await getMyPreferences({ headers: asBearerAuth(admin.accessToken) });
expect(before).toMatchObject({ people: { minimumFaces: 3 } });
const { status, body } = await request(app)
.put('/users/me/preferences')
.send({ people: { minimumFaces: 2 } })
.set('Authorization', `Bearer ${admin.accessToken}`);
expect(status).toBe(200);
expect(body).toMatchObject({ people: { minimumFaces: 2 } });
const after = await getMyPreferences({ headers: asBearerAuth(admin.accessToken) });
expect(after).toMatchObject({ people: { minimumFaces: 2 } });
});
});
describe('GET /users/:id', () => {
-41
View File
@@ -1,41 +0,0 @@
import { LoginResponseDto, ManualJobName, QueueName } from '@immich/sdk';
import { expect, test } from '@playwright/test';
import { utils } from 'src/utils';
test.describe.configure({ mode: 'serial' });
test.describe.skip('Integrity', () => {
let admin: LoginResponseDto;
test.beforeAll(async () => {
utils.initSdk();
await utils.resetDatabase();
admin = await utils.adminSetup();
});
test('run integrity jobs to update stats', async ({ context, page }) => {
await utils.setAuthCookies(context, admin.accessToken);
await utils.createJob(admin.accessToken, {
name: ManualJobName.IntegrityUntrackedFiles,
});
await utils.waitForQueueFinish(admin.accessToken, QueueName.IntegrityCheck);
await page.goto('/admin/maintenance');
const count = page.getByText('Untracked Files').locator('..').locator('..').locator('div').nth(1);
const previousCount = Number.parseInt((await count.textContent()) ?? '');
await utils.mkFolder(`/data/upload/${admin.userId}`);
await utils.putTextFile('untracked', `/data/upload/${admin.userId}/untracked1.png`);
const checkButton = page.getByText('Integrity Report').locator('..').getByRole('button', { name: 'Check All' });
await checkButton.click();
await expect(checkButton).toBeEnabled();
await expect(count).toContainText((previousCount + 1).toString());
});
});
+3 -46
View File
@@ -192,7 +192,6 @@ export const utils = {
'user',
'system_metadata',
'tag',
'integrity_report',
];
const truncateTables = tables.filter((table) => table !== 'system_metadata');
@@ -560,54 +559,10 @@ export const utils = {
mkdirSync(`${testAssetDir}/temp`, { recursive: true });
},
putFile(source: string, dest: string) {
return executeCommand('docker', ['cp', source, `immich-e2e-server:${dest}`]).promise;
},
async putTextFile(contents: string, dest: string) {
const dir = await mkdtemp(join(tmpdir(), 'test-'));
const fn = join(dir, 'file');
await pipeline(Readable.from(contents), createWriteStream(fn));
return executeCommand('docker', ['cp', fn, `immich-e2e-server:${dest}`]).promise;
},
async move(source: string, dest: string) {
return executeCommand('docker', ['exec', 'immich-e2e-server', 'mv', source, dest]).promise;
},
async copyFolder(source: string, dest: string) {
return executeCommand('docker', ['exec', 'immich-e2e-server', 'cp', '-r', source, dest]).promise;
},
async deleteFile(path: string) {
return executeCommand('docker', ['exec', 'immich-e2e-server', 'rm', path]).promise;
},
async deleteFolder(path: string) {
return executeCommand('docker', ['exec', 'immich-e2e-server', 'rm', '-r', path]).promise;
},
async truncateFolder(path: string) {
return executeCommand('docker', [
'exec',
'immich-e2e-server',
'find',
path,
'-type',
'f',
'-exec',
'truncate',
'-s',
'1',
'{}',
';',
]).promise;
},
async mkFolder(path: string) {
return executeCommand('docker', ['exec', 'immich-e2e-server', 'mkdir', '-p', path]).promise;
},
createBackup: async (accessToken: string) => {
await utils.createJob(accessToken, {
name: ManualJobName.BackupDatabase,
@@ -624,8 +579,10 @@ export const utils = {
resetBackups: async (accessToken: string) => {
const { backups } = await listDatabaseBackups({ headers: asBearerAuth(accessToken) });
const backupFiles = backups.map((b) => b.filename);
await deleteDatabaseBackup(
{ databaseBackupDeleteDto: { backups: backups.map((dto) => dto.filename) } },
{ databaseBackupDeleteDto: { backups: backupFiles } },
{ headers: asBearerAuth(accessToken) },
);
},
+2 -3
View File
@@ -1,3 +1,4 @@
import tsconfigPaths from 'vite-tsconfig-paths';
import { defineConfig } from 'vitest/config';
const skipDockerSetup = process.env.VITEST_DISABLE_DOCKER_SETUP === 'true';
@@ -23,7 +24,5 @@ export default defineConfig({
maxWorkers: 1,
isolate: false,
},
resolve: {
tsconfigPaths: true,
},
plugins: [tsconfigPaths()],
});
+2 -3
View File
@@ -1,3 +1,4 @@
import tsconfigPaths from 'vite-tsconfig-paths';
import { defineConfig } from 'vitest/config';
const skipDockerSetup = process.env.VITEST_DISABLE_DOCKER_SETUP === 'true';
@@ -23,7 +24,5 @@ export default defineConfig({
maxWorkers: 1,
isolate: false,
},
resolve: {
tsconfigPaths: true,
},
plugins: [tsconfigPaths()],
});
+21 -12
View File
@@ -5,34 +5,31 @@
"acknowledge": "Neem kennis",
"action": "Aksie",
"action_common_update": "Werk by",
"action_description": "n Stel van aksies om op die gefiltreerde bates uit te voer",
"actions": "Aksies",
"active": "Aktief",
"active_count": "Aktief: {count}",
"activity": "Aktiwiteite",
"activity_changed": "Aktiwiteit is {enabled, select, true {geaktiveer} other {gedeaktiveer}}",
"add": "Voeg toe",
"add_a_description": "Voeg n beskrywing toe",
"add_a_location": "Voeg n ligging toe",
"add_a_name": "Voeg n naam toe",
"add_a_title": "Voeg n titel toe",
"add_action": "Voeg aksie toe",
"add_assets": "Voeg bates by",
"add_birthday": "Voeg n verjaarsdag toe",
"add_endpoint": "Voeg eindpunt toe",
"add_exclusion_pattern": "Voeg uitsluitingspatroon toe",
"add_location": "Voeg ligging toe",
"add_more_users": "Voeg meer gebruikers toe",
"add_partner": "Voeg vennoot toe",
"add_path": "Voeg pad toe",
"add_photos": "Voeg fotos toe",
"add_tag": "Voeg etiket toe",
"add_to": "Voeg toe tot…",
"add_to_album": "Voeg toe tot album",
"add_to_album_bottom_sheet_added": "Tot {album} toegevoeg",
"add_to_album_bottom_sheet_already_exists": "Reeds in {album}",
"add_to_album_bottom_sheet_some_local_assets": "Sommige plaaslike bates kon nie toe gevoeg word tot die album nie",
"add_to_albums": "Voeg toe tot albums",
"add_to_albums_count": "Voeg toe tot albums ({count})",
"add_to_bottom_bar": "Voeg toe",
"add_upload_to_stack": "Voeg oplaai by stapel",
"add_to_shared_album": "Voeg toe tot gedeelde album",
"add_url": "Voeg bronadres toe",
"added_to_archive": "Tot argief toegevoeg",
"added_to_favorites": "Tot gunstelinge toegevoeg",
@@ -49,7 +46,6 @@
"backup_database": "Skep Databasisstortlêer",
"backup_database_enable_description": "Aktiveer databasisstortlêers",
"backup_keep_last_amount": "Aantal vorige stortlêers om te hou",
"backup_onboarding_2_description": "plaaslike kopieë op verskillende toestelle. Dit sluit die hooflêers en n rugsteun van daardie lêers plaaslik in.",
"backup_onboarding_3_description": "totale kopieë van u data, insluitend die oorspronklike lêers. Dit sluit 1 kopie op n ander perseel en 2 lokale kopieë in.",
"backup_onboarding_description": "n <backblaze-link>3-2-1-rugsteunstrategie</backblaze-link> word sterk aanbeveel om u data veilig te hou. Hou kopieë van u fotos/videos sowel as die Immich-databasis vir n volledige rugsteunoplossing.",
"backup_onboarding_footer": "Lees hierdie <link>dokument</link> vir meer inligting oor hoe om n rugsteunkopie van Immich te maak.",
@@ -65,7 +61,6 @@
"confirm_reprocess_all_faces": "Is u seker u wil alle gesigte herverwerk? Dit sal ook genoemde mense skoonmaak.",
"confirm_user_password_reset": "Is u seker u wil {user} se wagwoord terugstel?",
"confirm_user_pin_code_reset": "Is u seker u wil {user} se PIN-kode herstel?",
"copy_config_to_clipboard_description": "Kopieer die huidige stelselkonfigurasie as n JSONobjek na die klipbord",
"create_job": "Skep taak",
"cron_expression": "Cron-uitdrukking",
"cron_expression_description": "Stel die skanderingsinterval in met die cron-formaat. Kyk gerus na bv. <link>Crontab Guru</link> vir meer inligting",
@@ -73,8 +68,6 @@
"disable_login": "Deaktiveer aantekening",
"duplicate_detection_job_description": "Begin masjienleer op items om soortgelyke beelde op te spoor. Maak staat op Slimsoek",
"exclusion_pattern_description": "Met uitsluitingspatrone kan u lêers en vouers ignoreer wanneer u u biblioteek skandeer. Dit is nuttig as u vouers het wat lêers bevat wat u nie wil invoer nie, soos RAW-lêers.",
"export_config_as_json_description": "Laai die huidige stelselkonfigurasie af as n JSONlêer",
"external_libraries_page_description": "Admin eksterne biblioteekbladsy",
"face_detection": "Gesigherkenning",
"face_detection_description": "Identifiseer die gesigte in media d.m.v. masjienleer. Vir videos word slegs die duimnael oorweeg. “Herlaai” (ver)werk al die media weer. “Stel terug” verwyder alle huidige gesigdata. “Onverwerk” plaas items in die ry wat nog nie verwerk is nie. Geïdentifiseerde gesigte sal ná voltooiing van Gesigidentifikasie vir Gesigherkenning in die ry geplaas word om hulle in bestaande of nuwe persone te groepeer.",
"facial_recognition_job_description": "Groepeer gesigte in mense. Die stap is vinniger nadat Gesigherkenning klaar is. “Herstel” (her-)groepeer alle gesigte. “Vermiste” plaas gesigte in ry wat nie n persoon gekoppel het nie.",
@@ -136,6 +129,7 @@
"advanced": "Gevorderd",
"albums": "Albums",
"all": "Alle",
"anti_clockwise": "Linksom",
"archive": "Argief",
"asset_skipped": "Oorgeslaan",
"asset_uploaded": "Opgelaai",
@@ -147,6 +141,7 @@
"camera": "Kamera",
"cancel": "Kanselleer",
"city": "Stad",
"clockwise": "Regsom",
"close": "Sluit",
"color": "Kleur",
"confirm": "Bevestig",
@@ -187,12 +182,14 @@
"unsaved_change": "Onbewaarde verandering",
"unselect_all": "Ontkies alles",
"unselect_all_duplicates": "Ontkies alle duplikate",
"unselect_all_in": "Ontkies alles in {group}",
"unstack": "Ontstapel",
"unstack_action_prompt": "{count} ongestapel",
"unstacked_assets_count": "{count, plural, one {# item} other {# items}} ontstapel",
"unsupported_field_type": "Onondersteunde veldtipe",
"unsupported_file_type": "Lêer {file} kan nie opgelaai word nie omdat die lêertipe {type} nie ondersteun word nie.",
"untagged": "Sonder etiket",
"untitled_workflow": "Naamlose werkvloei",
"up_next": "Volgende",
"update_location_action_prompt": "Werk die ligging van {count} gekose items by met:",
"updated_at": "Bygewerk",
@@ -200,6 +197,8 @@
"upload": "Laai op",
"upload_concurrency": "Aantal gelyktydige oplaaie",
"upload_details": "Oplaaidetails",
"upload_dialog_info": "Wil u n rugsteun maak van die gekose item(s) op die bediener?",
"upload_dialog_title": "Laai item op",
"upload_error_with_count": "Oplaaifout vir {count, plural, one {# item} other {# items}}",
"upload_errors": "Oplaai voltooi met {count, plural, one {# fout} other {# foute}}, verfris die blad om die nuwe items te sien.",
"upload_finished": "Klaar opgelaai",
@@ -228,6 +227,7 @@
"user_privacy": "Gebruikersprivaatheid",
"user_purchase_settings": "Koop",
"user_purchase_settings_description": "Bestuur u aankoop",
"user_role_set": "Stel {user} in as {role}",
"user_usage_detail": "Gedetailleerde gebruik van gebruikers",
"user_usage_stats": "Statistieke vir rekeninggebruik",
"user_usage_stats_description": "Bekyk statistieke van rekeninggebruik",
@@ -237,6 +237,7 @@
"utilities": "Gereedskap",
"validate": "Valideer",
"validate_endpoint_error": "Voer asb. n geldige bronadres in",
"validation_error": "Valideerfout",
"variables": "Veranderlikes",
"version": "Weergawe",
"version_announcement_closing": "Jou friend, Alex",
@@ -248,6 +249,7 @@
"video_hover_setting_description": "Speel videoduimnael wanneer muis oor item hang. Selfs indien gedeaktiveer kan afspeel begin deur oor die afspeelknop te hang.",
"videos": "Videos",
"videos_count": "{count, plural, one {# video} other {# videos}}",
"videos_only": "Slegs videos",
"view": "Bekyk",
"view_album": "Bekyk album",
"view_all": "Bekyk alle",
@@ -256,16 +258,21 @@
"view_details": "Bekyk detail",
"view_in_timeline": "Bekyk in tydlyn",
"view_link": "Bekyk skakel",
"view_links": "Bekyk skakels",
"view_name": "Bekyk",
"view_next_asset": "Bekyk volgende item",
"view_previous_asset": "Bekyk vorige item",
"view_qr_code": "Bekyk QR-kode",
"view_similar_photos": "Bekyk soortgelyke fotos",
"view_stack": "Bekyk stapel",
"view_user": "Bekyk gebruiker",
"viewer_remove_from_stack": "Verwyder van stapel",
"viewer_stack_use_as_main_asset": "Gebruik as hoofitem",
"viewer_unstack": "Ontstapel",
"visibility": "Sigbaarheid",
"visibility_changed": "Sigbaarheid verander vir {count, plural, one {# mens} other {# mense}}",
"visual": "Visueel",
"visual_builder": "Visuele bouer",
"waiting": "Wag",
"waiting_count": "Wagtend: {count}",
"warning": "Waarskuwing",
@@ -284,6 +291,7 @@
"workflow_navigation_prompt": "Is u seker u wil verlaat sonder om u veranderinge te bewaar?",
"workflow_summary": "Werkvloei-opsomming",
"workflow_update_success": "Werkvloei suksesvol bygewerk",
"workflow_updated": "Werkvloei bygewerk",
"workflows": "Werkvloeie",
"workflows_help_text": "Werkvloeie outomatiseer aksies op u items gebaseer op snellers en filters",
"wrong_pin_code": "Verkeerde PIN-kode",
@@ -293,5 +301,6 @@
"you_dont_have_any_shared_links": "U het geen gedeelde skakels nie",
"your_wifi_name": "U Wi-Fi-naam",
"zero_to_clear_rating": "druk 0 om itemgradering te wis",
"zoom_image": "Zoem in"
"zoom_image": "Zoem in",
"zoom_to_bounds": "Zoem na rande"
}
+333 -146
View File
File diff suppressed because it is too large Load Diff
+7 -23
View File
@@ -5,23 +5,23 @@
"acknowledge": "Təsdiq et",
"action": "Əməliyyat",
"action_common_update": "Yenilə",
"action_description": "Filtrlənmiş aktivliklər üzərində yerinə yetiriləcək əməliyyatlar toplusu",
"actions": "Əməliyyatlar",
"active": "Aktiv",
"active_count": "Aktiv: {count}",
"activity": "Fəaliyyət",
"activity_changed": "Fəaliyyət {enabled, select, true {aktivdir} other {aktiv deyil}}",
"add": "Əlavə et",
"add_a_description": "Təsviri əlavə et",
"add_a_location": "Məkan əlavə et",
"add_a_name": "Ad əlavə et",
"add_a_title": "Başlıq əlavə et",
"add_action": "Yeni əməliyyat əlavə et",
"add_assets": "Aktivlik əlavə et",
"add_birthday": "Doğum günü əlavə et",
"add_endpoint": "Son nöqtə əlavə et",
"add_exclusion_pattern": "Çıxarma nümunəsi əlavə et",
"add_location": "Məkan əlavə et",
"add_more_users": "Daha çox istifadəçi əlavə et",
"add_partner": "Partnyor əlavə et",
"add_path": "Yol əlavə et",
"add_photos": "Şəkillər əlavə et",
"add_tag": "Etiket əlavə et",
"add_to": "Bura əlavə et…",
@@ -29,9 +29,11 @@
"add_to_album_bottom_sheet_added": "{album} albomuna əlavə edildi",
"add_to_album_bottom_sheet_already_exists": "Artıq {album} albomunda var",
"add_to_album_bottom_sheet_some_local_assets": "Bəzi lokal resurslar alboma əlavə edilə bilmədi",
"add_to_album_toggle": "{album} üçün seçimi dəyişin",
"add_to_albums": "Albomlara əlavə et",
"add_to_albums_count": "({count}) albomlarına əlavə et",
"add_to_bottom_bar": "Əlavə et",
"add_to_shared_album": "Paylaşılan alboma əlavə et",
"add_upload_to_stack": "Yeni yüklənmə əlavə et",
"add_url": "URL əlavə et",
"added_to_archive": "Arxivə əlavə edildi",
@@ -44,7 +46,7 @@
"authentication_settings": "Səlahiyyətləndirmə parametrləri",
"authentication_settings_description": "Şifrə, OAuth və digər səlahiyyətləndirmə parametrləri",
"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ı",
"backup_database": "Verilənlər bazasının dump-ını yaradın",
"backup_database_enable_description": "Verilənlər bazasının artıq nüsxələrini aktiv et",
@@ -52,7 +54,6 @@
"backup_onboarding_1_description": "buludda və ya başqa fiziki yerdə saytdan kənar surət.",
"backup_onboarding_2_description": "müxtəlif cihazlarda yerli nüsxələr. Bura əsas fayllar və həmin faylların ehtiyat lokal nüsxəsi daxildir.",
"backup_onboarding_3_description": "orijinal fayllar da daxil olmaqla məlumatlarınızın ümumi surətləri. Buraya 1 kənar nüsxə və 2 lokal nüsxə daxildir.",
"backup_onboarding_description": "<backblaze-link>3-2-1 yedəkləmə strategiyası</backblaze-link> məlumatlarınızı qorumaq üçün tövsiyə olunur. Yüklədiyiniz şəkil və videoların, həmçinin Immich verilənlər bazasının surətlərini saxlamalısınız ki, hərtərəfli yedəkləmə həlli əldə edəsiniz.",
"backup_onboarding_footer": "Immich-in ehtiyat nüsxəsini çıxarmaq haqqında ətraflı məlumat üçün <link>sənədlərə</link> müraciət edin.",
"backup_onboarding_parts_title": "3-2-1 ehtiyat nüsxəsinə aşağıdakılar daxildir:",
"backup_onboarding_title": "Ehtiyat surətlər",
@@ -60,31 +61,14 @@
"backup_settings_description": "Verilənlər bazasının ehtiyat nüsxə parametrlərini idarə et",
"cleared_jobs": "{job} üçün tapşırıqlar silindi",
"config_set_by_file": "Konfiqurasiya hal-hazırda konfiqurasiya faylı ilə təyin olunub",
"confirm_delete_library": "{library} kitabxanasını silmək istədiyinizə ə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_reprocess_all_faces": "Bütün üzləri yenidən emal etmək istədiyinizə əminsiniz? Bu, həmçinin adlandırılmış şəxsləri siləcək.",
"confirm_user_password_reset": "{user} adlı istifadəçinin şifrəsini sıfırlamaq istədiyinizdən əminmisiniz?",
"confirm_user_pin_code_reset": "{user} istifadəçisinin PIN kodunu sıfırlamaq istədiyinizə əminsiniz?",
"copy_config_to_clipboard_description": "Cari sistem konfiqurasiyasını JSON obyekt kimi mübadilə buferinə kopyalayın",
"create_job": "İş yarat",
"cron_expression": "Cron ifadəsi",
"cron_expression_description": "Cron formatından istifadə edərək skan intervalını təyin edin. Ətraflı məlumat üçün nümunələrə baxa bilərsiniz. <link>Crontab Guru</link>",
"cron_expression_presets": "Cron ifadəsi ön ayarları",
"disable_login": "Giriş etməni söndür",
"duplicate_detection_job_description": "Bənzər şəkilləri tapmaq üçün maşın öyrənməsini işə salın. Bu prosses Smart Search funksiyasına əsaslanır",
"exclusion_pattern_description": "İstisna nümunələri kitabxananızı skan edərkən faylları və qovluqları nəzərə almamağa imkan verir. Bu, RAW faylları kimi idxal etmək istəmədiyiniz faylları olan qovluqlarınız olduqda faydalıdır.",
"export_config_as_json_description": "Cari sistem konfiqurasiyasını JSON faylı kimi endirin",
"external_libraries_page_description": "Admin xarici kitabxana səhifəsi",
"face_detection": "Üz tanıma",
"failed_job_command": "{command} əmri {job} işi üçün uğursuz oldu",
"force_delete_user_warning": "XƏBƏRDARLIQ: Bu əməliyyat istifadəçi və bütün məlumatları siləcəkdir. Bu prossesi və silinən faylları geri qaytarmaq olmaz.",
"image_format": "Format",
"image_format_description": "WebP, JPEG faylına görə daha kiçik həcmə sahibdir, lakin onu kodlaşdırmaq daha çox vaxt alır.",
"image_fullsize_description": "Böyüdülmüş halda istifadə edilən, metadata-sı silinmiş tam ölçülü şəkil",
"image_fullsize_enabled": "Tam ölçülü şəkil generasiyasını aktiv et",
"image_fullsize_enabled_description": "Veb üçün uyğun olmayan formatlar üçün tam ölçülü şəkil yaradın. “Daxili önizləməyə üstünlük ver” aktiv olduqda, daxili önizləmələr çevrilmədən birbaşa istifadə olunur. JPEG kimi veb üçün uyğun formatlara təsir etmir.",
"image_fullsize_quality_description": "Tam ölçülü şəkil keyfiyyəti (1-100). Daha yüksək dəyər daha yaxşı keyfiyyət verir, lakin daha böyük ölçülü fayl yaradır.",
"image_fullsize_title": "Tam ölçülü şəkil tənzimləmələri",
"image_preview_title": "Önizləmə parametrləri",
"image_quality": "Keyfiyyət",
"image_resolution": "Çözümlülük",
+93 -1707
View File
File diff suppressed because it is too large Load Diff
+337 -151
View File
File diff suppressed because it is too large Load Diff
+4
View File
@@ -5,6 +5,7 @@
"acknowledge": "Akcept",
"active": "Stap Mekem",
"activity": "Wanem hemi Mekem",
"activity_changed": "WAnem hemi Mekem hemi",
"add": "Ad",
"add_a_description": "Putem Description blo hem",
"add_a_location": "Putem place blo hem",
@@ -12,9 +13,11 @@
"add_a_title": "Putem wan name blo hem",
"add_exclusion_pattern": "Putem wan paten wae hemi karem aot",
"add_location": "Putem wan place blo hem",
"add_more_users": "Putem mor man",
"readonly_mode_enabled": "Mod blo yu no save janjem i on",
"reassigned_assets_to_new_person": "Janjem{count, plural, one {# asset} other {# assets}} blo nu man",
"reassing_hint": "janjem ol sumtin yu bin joos i go blo wan man",
"recent_albums": "album i no old tu mas",
"recent_searches": "lukabout wea i no old tu mas",
"time_based_memories_duration": "hao mus second blo wan wan imij i stap lo scrin.",
"timezone": "taemzon",
@@ -30,6 +33,7 @@
"trash_action_prompt": "{count} igo lo plaes lo toti",
"trash_all": "Putem ol i go lo toti",
"trash_count": "Toti {count, number}",
"trash_emptied": "basket blo toti i empti nomo",
"trash_no_results_message": "Foto mo video lo basket blo toti yu save lukem lo plaes ia.",
"trash_page_delete_all": "Delete oli ol"
}
+27 -5
View File
@@ -10,31 +10,39 @@
"active": "সচল",
"active_count": "Active: {count}",
"activity": "কার্যকলাপ",
"activity_changed": "একটিভিটি এখন {enabled, select, true {enabled} other {disabled}} আছে",
"add": "যোগ করুন",
"add_a_description": "একটি বিবরণ যোগ করুন",
"add_a_location": "একটি অবস্থান যোগ করুন",
"add_a_name": "একটি নাম যোগ করুন",
"add_a_title": "একটি শিরোনাম যোগ করুন",
"add_action": "কর্ম যোগ করুন",
"add_action_description": "সম্পাদন করার জন্য একটি কাজ যোগ করতে ক্লিক করুন",
"add_assets": "সম্পদ যোগ করুন",
"add_birthday": "জন্মদিন যোগ করুন",
"add_endpoint": "এন্ডপয়েন্ট যোগ করুন",
"add_exclusion_pattern": "বহির্ভূতকরণ নমুনা",
"add_filter": "ফিল্টার যোগ করুন",
"add_filter_description": "একটি ফিল্টার শর্ত যোগ করতে ক্লিক করুন",
"add_location": "অবস্থান যুক্ত করুন",
"add_more_users": "আরো ব্যবহারকারী যুক্ত করুন",
"add_partner": "অংশীদার যোগ করুন",
"add_path": "পাথ যুক্ত করুন",
"add_photos": "ছবি যুক্ত করুন",
"add_step": "ধাপ যোগ করুন",
"add_tag": "ট্যাগ যুক্ত করুন",
"add_to": "যুক্ত করুন…",
"add_to_album": "এলবাম এ যোগ করুন",
"add_to_album_bottom_sheet_added": "{album} এ যোগ করা হয়েছে",
"add_to_album_bottom_sheet_already_exists": "{album} এ আগে থেকেই আছে",
"add_to_album_bottom_sheet_some_local_assets": "কিছু স্থানীয় ছবি বা ভিডিও অ্যালবামে যোগ করা যায়নি",
"add_to_album_toggle": "{album} - এর নির্বাচন পরিবর্তন করুন",
"add_to_albums": "অ্যালবামে যোগ করুন",
"add_to_albums_count": "অ্যালবামে যোগ করুন ({count})",
"add_to_bottom_bar": "এ যোগ করুন",
"add_to_shared_album": "শেয়ার করা অ্যালবামে যোগ করুন",
"add_upload_to_stack": "আপলোড স্ট্যাকে যোগ করুন",
"add_url": "লিঙ্ক যোগ করুন",
"add_workflow_step": "কাজের ধাপ যোগ করুন",
"added_to_archive": "আর্কাইভ এ যোগ করা হয়েছে",
"added_to_favorites": "ফেভারিটে যোগ করা হয়েছে",
"added_to_favorites_count": "পছন্দের তালিকায় {count, number} যোগ করা হয়েছে",
@@ -73,7 +81,6 @@
"cron_expression_description": "Cron ফরম্যাট ব্যবহার করে স্ক্যানিং ইন্টারভ্যাল নির্ধারণ করুন। আরও তথ্যের জন্য দয়া করে <link>Crontab Guru</link> দেখুন",
"cron_expression_presets": "Cron এক্সপ্রেশন প্রিসেট",
"disable_login": "লগইন অক্ষম করুন",
"download_csv": "CSV ডাউনলোড করুন",
"duplicate_detection_job_description": "সদৃশ ছবি শনাক্ত করতে অ্যাসেটগুলোর উপর মেশিন লার্নিং চালান। এটি Smart Search-এর উপর নির্ভর করে",
"exclusion_pattern_description": "এক্সক্লুশন প্যাটার্ন ব্যবহার করে লাইব্রেরি স্ক্যান করার সময় নির্দিষ্ট ফাইল ও ফোল্ডার উপেক্ষা করা যায়। এটি তখনই উপকারী যখন কিছু ফোল্ডারে এমন ফাইল থাকে যা আপনি ইমপোর্ট করতে চান না, যেমন RAW ফাইল।",
"export_config_as_json_description": "বর্তমান সিস্টেম কনফিগারেশনটিকে একটি JSON ফাইল হিসেবে ডাউনলোড করুন",
@@ -183,11 +190,9 @@
"machine_learning_smart_search_enabled": "স্মার্ট সার্চ সক্ষম করুন",
"machine_learning_smart_search_enabled_description": "নিষ্ক্রিয় থাকলে, স্মার্ট সার্চের জন্য ছবিগুলো এনকোড (encode) করা হবে না।",
"machine_learning_url_description": "মেশিন লার্নিং সার্ভারের URL। যদি একের বেশি URL প্রদান করা হয়, তবে একটি সফলভাবে সাড়া না দেওয়া পর্যন্ত প্রতিটি সার্ভারে এক এক করে চেষ্টা করা হবে (প্রথম থেকে শেষ ক্রমানুসারে)। যে সার্ভারগুলো সাড়া দেবে না, সেগুলো পুনরায় সচল হওয়া পর্যন্ত সাময়িকভাবে উপেক্ষা করা হবে।",
"maintenance_backup_management": "ব্যাকআপ ব্যবস্থাপনা",
"maintenance_delete_backup": "ব্যাকআপ (Backup)মুছুন",
"maintenance_delete_backup_description": "এই ফাইলটি চিরতরে মুছে ফেলা হবে।",
"maintenance_delete_error": "ব্যাকআপ মুছে ফেলতে ব্যর্থ হয়েছে।",
"maintenance_integrity_check": "যাচাই",
"maintenance_restore_backup": "ব্যাকআপ পুনরুদ্ধার(Restore) করুন",
"maintenance_restore_backup_description": "Immich মুছে ফেলা হবে এবং নির্বাচিত ব্যাকআপ থেকে পুনরুদ্ধার করা হবে। কার্যক্রম চালিয়ে যাওয়ার আগে একটি ব্যাকআপ তৈরি করা হবে।",
"maintenance_restore_backup_different_version": "এই ব্যাকআপটি Immich-এর একটি ভিন্ন সংস্করণের মাধ্যমে তৈরি করা হয়েছিল!",
@@ -453,6 +458,8 @@
"album_delete_confirmation": "আপনি কি সত্যিই অ্যালবাম {album} মুছে ফেলতে চান?",
"album_delete_confirmation_description": "অ্যালবামটি শেয়ার করা থাকলেও অন্য ব্যবহারকারীরা আর এটি অ্যাক্সেস করতে পারবেন না।",
"album_info_updated": "অ্যালবামের তথ্য আপডেট করা হয়েছে",
"album_leave": "অ্যালবাম থেকে বেরিয়ে যেতে চান ?",
"album_leave_confirmation": "আপনি কি নিশ্চিত যে আপনি {album} ছেড়ে যেতে চান?",
"album_name": "অ্যালবামের নাম",
"album_options": "অ্যালবামের অপশনসমূহ",
"album_remove_user": "ব্যবহারকারী সরাতে চান?",
@@ -460,6 +467,8 @@
"album_share_no_users": "এই অ্যালবামটি সব ব্যবহারকারীর সঙ্গে শেয়ার করা হয়েছে, বা শেয়ার করার জন্য কোনো ব্যবহারকারী নেই।",
"album_updated": "অ্যালবাম আপডেট করা হয়েছে",
"album_updated_setting_description": "নতুন অ্যাসেট যুক্ত হলে শেয়ার করা অ্যালবামের জন্য ইমেইল নোটিফিকেশন পান",
"album_user_left": "বাম {album}",
"album_user_removed": "{user} কে সরানো হয়েছে",
"album_with_link_access": "লিঙ্ক থাকা যে কেউ এই অ্যালবামের ছবি ও মানুষজনকে দেখতে পারবে।",
"albums": "অ্যালবামসমূহ",
"all": "সব",
@@ -467,8 +476,10 @@
"all_people": "সব ব্যবহারকারী",
"all_videos": "সব ভিডিও",
"allow_dark_mode": "ডার্ক মোড চালু করুন",
"allow_edits": "এডিটের অনুমতি দিন",
"allow_public_user_to_download": "সাধারণ ব্যবহারকারী ডাউনলোড করতে পারবে",
"allow_public_user_to_upload": "সাধারণ ব্যবহারকারী আপলোড করতে পারবে",
"anti_clockwise": "বিপরীত দিক",
"api_key": "API কী",
"api_key_description": "এই মান একবারই দেখানো হবে। উইন্ডো বন্ধ করার আগে অবশ্যই এটি কপি করুন।",
"api_key_empty": "API কী-এর নাম খালি রাখা যাবে না",
@@ -484,6 +495,8 @@
"asset_added_to_album": "অ্যালবামে যুক্ত করা হয়েছে",
"asset_adding_to_album": "অ্যালবামে যুক্ত করা হচ্ছে…",
"asset_description_updated": "অ্যাসেটের বিবরণ আপডেট করা হয়েছে",
"asset_filename_is_offline": "{filename} অ্যাসেটটি বর্তমানে অফলাইন",
"asset_has_unassigned_faces": "অ্যাসেটটির কিছু মুখ অনির্ধারিত ফেস রয়েছে",
"asset_hashing": "হ্যাশিং চলছে…",
"asset_offline": "অ্যাসেট বর্তমানে অফলাইন",
"asset_offline_description": "এই এক্সটার্নাল অ্যাসেটটি এখন ডিস্কে নেই। সহায়তার জন্য Immich অ্যাডমিনিস্ট্রেটরের সাথে যোগাযোগ করুন।",
@@ -504,6 +517,7 @@
"back": "ফিরে যান",
"back_close_deselect": "ফিরে যান, বন্ধ করুন বা নির্বাচন বাতিল করুন",
"backward": "পিছনে",
"birthdate_saved": "জন্ম তারিখ সংরক্ষণ সম্পন্ন",
"birthdate_set_description": "একটি ছবির সময়ে ব্যক্তির বয়স গণনার জন্য জন্ম তারিখ ব্যবহার করা হয়।",
"blurred_background": "ব্লারড ব্যাকগ্রাউন্ড",
"bugs_and_feature_requests": "বাগ ও ফিচার রিকোয়েস্ট",
@@ -522,6 +536,7 @@
"cannot_undo_this_action": "এই কাজ পূর্বাবস্থায় ফেরানো যাবে না!",
"cannot_update_the_description": "বিবরণ পরিবর্তন সম্ভব নয়",
"change_date": "তারিখ পরিবর্তন",
"change_expiration_time": "মেয়াদ শেষের সময় পরিবর্তন",
"change_location": "লোকেশন পরিবর্তন",
"change_name": "নাম পরিবর্তন করুন",
"change_name_successfully": "নাম সফলভাবে পরিবর্তন হয়েছে",
@@ -537,10 +552,12 @@
"clear_all_recent_searches": "সাম্প্রতিক সব অনুসন্ধান পরিষ্কার করুন",
"clear_message": "মেসেজ পরিষ্কার করুন",
"clear_value": "ভ্যালু মুছুন",
"clockwise": "ঘড়ির কাঁটার দিকে",
"close": "বন্ধ",
"collapse": "সংকুচিত করুন",
"collapse_all": "সব সংকুচিত",
"color": "রং",
"color_theme": "কালার থিম",
"comment_deleted": "মন্তব্য মুছে ফেলা হয়েছে",
"comment_options": "মন্তব্য অপশন",
"comments_and_likes": "মন্তব্য ও লাইক",
@@ -556,6 +573,7 @@
"copied_image_to_clipboard": "ছবি ক্লিপবোর্ডে কপি হয়েছে।",
"copied_to_clipboard": "ক্লিপবোর্ডে কপি হয়েছে!",
"copy_error": "Error-টি কপি করুন",
"copy_file_path": "ফাইল পাথ কপি",
"copy_image": "ছবি কপি",
"copy_link": "লিঙ্ক কপি",
"copy_link_to_clipboard": "ক্লিপবোর্ডে লিঙ্ক কপি করুন",
@@ -598,13 +616,16 @@
"delete_tag_confirmation_prompt": "আপনি কি নিশ্চিতভাবে {tagName} ট্যাগটি মুছতে চান?",
"delete_user": "ইউজার মুছুন",
"deleted_shared_link": "শেয়ার করা লিঙ্কটি মুছুন",
"deletes_missing_assets": "ডিস্ক থেকে হারানো অ্যাসেটগুলো মুছে",
"description": "বিবরন",
"details": "বিস্তারিত",
"direction": "দিকনির্দেশনা",
"disabled": "নিষ্ক্রিয়",
"disallow_edits": "সম্পাদনা করার অনুমতি দেবেন না",
"discord": "ডিসকর্ড",
"discover": "ডিসকভার",
"dismiss_all_errors": "সব ত্রুটি বাতিল করুন",
"dismiss_error": "ত্রুটি বাতিল করুন",
"display_options": "ডিসপ্লে অপশন",
"display_order": "ডিসপ্লে অর্ডার",
"display_original_photos": "অরিজিনাল ছবি দেখান",
@@ -624,5 +645,6 @@
"you_dont_have_any_shared_links": "আপনার কোনো শেয়ার করা লিঙ্ক নেই (You don't have any shared links)",
"your_wifi_name": "আপনার ওয়াই-ফাই এর নাম (Your Wi-Fi name)",
"zero_to_clear_rating": "অ্যাসেট রেটিং মুছে ফেলতে ০ চাপুন",
"zoom_image": "ছবি জুম করুন (Zoom Image)"
"zoom_image": "ছবি জুম করুন (Zoom Image)",
"zoom_to_bounds": "বাউন্ডস অনুযায়ী জুম করুন (Zoom to bounds)"
}
-1
View File
@@ -1 +0,0 @@
{}
+331 -145
View File
File diff suppressed because it is too large Load Diff
+329 -146
View File
File diff suppressed because it is too large Load Diff
+6
View File
@@ -8,6 +8,7 @@
"actions": "Ӗҫсем",
"active": "Хастар",
"activity": "Хастарлӑх",
"activity_changed": "Хастарлӑха {enabled, select, true {кӗртнӗ} other {сӳнтернӗ}}",
"add": "Хуш",
"add_a_description": "Ҫырса кӑтартни хуш",
"add_a_location": "Вырӑн хуш",
@@ -17,11 +18,14 @@
"add_endpoint": "Вӗҫӗмлӗ пӑнчӑ хушар",
"add_exclusion_pattern": "Кӑларса пӑрахмалли йӗрке хуш",
"add_location": "Вырӑн хуш",
"add_more_users": "Усӑҫсем ытларах хуш",
"add_partner": "Мӑшӑр хуш",
"add_path": "Ҫулне хуш",
"add_photos": "Сӑнӳкерчӗксем хуш",
"add_tag": "Тег хуш",
"add_to": "Мӗн те пулин хуш…",
"add_to_album": "Альбома хуш",
"add_to_shared_album": "Пӗрлехи альбома хуш",
"add_url": "URL хушӑр",
"added_to_archive": "Архива хушнӑ",
"added_to_favorites": "Суйласа илнине хушнӑ",
@@ -66,6 +70,7 @@
"feature_photo_updated": "Уйрӑм сӑнӳкерчӗк ҫӗнетнӗ",
"manage_sharing_with_partners": "Партнерсемпе пайланассине йӗркелесе пырӑр",
"map": "Карттӑ",
"map_marker_for_images": "{city}, {country} ҫинче ӳкернӗ ӳкерчӗксем валли карттӑ маркерӗ",
"map_marker_with_image": "Карттӑ маркерӗ ӳкерчӗкпе",
"map_settings": "Карттӑ ĕнерленĕвĕ",
"no_explore_results_message": "Хӑвӑр коллекципе киленмешкӗн сӑнӳкерчӗксем ытларах тийӗр.",
@@ -75,6 +80,7 @@
"people": "Ҫынсем",
"photos": "Сӑнӳкерчӗксем",
"photos_and_videos": "Сӑнӳкерчӗксем тете Видеосем",
"photos_count": "{count, plural, one {{count, number} Сӑнӳкерчӗк} other {{count, number} Сӑнӳкерчӗксем}}",
"photos_from_previous_years": "Иртнӗ ҫулсенчи сӑнӳкерчӗксем",
"place": "Тӗл",
"places": "Тӗлсем",
+329 -114
View File
File diff suppressed because it is too large Load Diff
+348 -165
View File
File diff suppressed because it is too large Load Diff
+25 -63
View File
@@ -1,40 +1,48 @@
{
"about": "Über",
"account": "Konto",
"account_settings": "Kontoistellige",
"account_settings": "Konto Einstellungen",
"acknowledge": "Bestätigä",
"action": "Aktion",
"action_common_update": "Update",
"action_description": "Aktionä, wo uf de gfilterte Medie usgführt wärde sölled",
"actions": "Aktionä",
"action_description": "Aktionä, wo uf de gefilterti Mediä ausgführt werdä solled",
"actions": "Aktionen",
"active": "Aktiv",
"active_count": "Aktiv: {count}",
"activity": "Aktivität",
"activity_changed": "Aktivität ist {enabled, select, true {aktiviert} other {deaktiviert}}",
"add": "Hinzuefüge",
"add_a_description": "Beschribig aege",
"add_a_location": "Standort afüege",
"add_a_description": "Beschreibung hinzufügen",
"add_a_location": "Standort hinzuefügä",
"add_a_name": "Namä hinzefügä",
"add_a_title": "Titel hinzufeügä",
"add_action": "Aktion hinzuefügä",
"add_action_description": "Klick do zum e Aktion hinzuefüge",
"add_assets": "Mediä hinzuefüge",
"add_birthday": "Geburtstag hinzuefüge",
"add_endpoint": "Endpunkt hinzuefüge",
"add_exclusion_pattern": "Ausschlussmuster hinzufügen",
"add_filter": "Filter hinzufügen",
"add_filter_description": "Klicke hier um eine Filterbedingung hinzuzufügen",
"add_location": "Standort hinzufügen",
"add_more_users": "Mehr Benutzer hinzufügen",
"add_partner": "Partner hinzufügen",
"add_path": "Pfad hinzufügen",
"add_photos": "Fotos hinzufügen",
"add_step": "Schritt hinzuefüege",
"add_tag": "Tag hinzufügen",
"add_to": "Hinzufügen zu…",
"add_to_album": "Zu Album hinzufügen",
"add_to_album_bottom_sheet_added": "Zu {album} hinzugefügt",
"add_to_album_bottom_sheet_already_exists": "Bereits in {album}",
"add_to_album_bottom_sheet_some_local_assets": "Einige lokale Dateien konnten nicht zum Album hinzugefügt werden",
"add_to_album_toggle": "Auswahl umschalten für {album}",
"add_to_albums": "Zu Alben hinzufügen",
"add_to_albums_count": "Zu Alben hinzufügen ({count})",
"add_to_bottom_bar": "zueege zu",
"add_to_bottom_bar": "Hinzufügen zu",
"add_to_shared_album": "Zu geteiltem Album hinzufügen",
"add_upload_to_stack": "Upload zum Stapel hinzufügen",
"add_url": "URL zueege",
"add_url": "URL hinzufügen",
"add_workflow_step": "Workflow-Schritt hinzufügen",
"added_to_archive": "Zum Archiv hinzugefügt",
"added_to_favorites": "Zu Favoriten hinzugefügt",
"added_to_favorites_count": "{count, number} zu Favoriten hinzugefügt",
@@ -46,7 +54,7 @@
"authentication_settings_description": "Passwort-, OAuth- und andere Authentifizierungseinstellungen verwalten",
"authentication_settings_disable_all": "Bist du sicher, dass du alle Loginmethoden deaktivieren willst? Die Anmeldung wird vollständig deaktiviert.",
"authentication_settings_reenable": "Nutze einen <link>Server-Befehl</link> zur Reaktivierung.",
"background_task_job": "Hintergrundfarbä",
"background_task_job": "Hintergrundaufgaben",
"backup_database": "Datenbanksicherung erstellen",
"backup_database_enable_description": "Datenbank regelmässig sichern",
"backup_keep_last_amount": "Anzahl der aufzubewahrenden früheren Sicherungen",
@@ -56,7 +64,7 @@
"backup_onboarding_description": "Eine <backblaze-link>3-2-1 Sicherungsstrategie</backblaze-link> wird empfohlen, um deine Daten zu schützen. Du solltest sowohl Kopien deiner hochgeladenen Fotos/Videos als auch der Immich-Datenbank aufbewahren, um eine umfassende Sicherungslösung zu haben.",
"backup_onboarding_footer": "Weitere Informationen zum Sichern von Immich findest du in der <link>Dokumentation</link>.",
"backup_onboarding_parts_title": "Eine 3-2-1-Sicherung umfasst:",
"backup_onboarding_title": "Sicherige",
"backup_onboarding_title": "Backups",
"backup_settings": "Einstellungen für Datenbanksicherung",
"backup_settings_description": "Einstellungen zur regelmässigen Sicherung der Datenbank.",
"cleared_jobs": "Folgende Aufgaben zurückgesetzt: {job}",
@@ -68,17 +76,16 @@
"confirm_user_password_reset": "Bist du sicher, dass du das Passwort für {user} zurücksetzen möchtest?",
"confirm_user_pin_code_reset": "Bist du sicher, dass du den PIN-Code von {user} zurücksetzen möchtest?",
"copy_config_to_clipboard_description": "Aktuelle Systemkonfiguration als JSON-Objekt in die Zwischenablage kopieren",
"create_job": "Ufgab erstelle",
"create_job": "Aufgabe erstellen",
"cron_expression": "Cron-Ausdruck",
"cron_expression_description": "Setze das Scanintervall im Cron-Format. Für mehr Informationen, siehe z. B. <link>Crontab Guru</link>",
"cron_expression_presets": "Vorlagen für Cron-Ausdrücke",
"disable_login": "Login deaktivierä",
"download_csv": "CSV herunterladen",
"disable_login": "Login deaktivieren",
"duplicate_detection_job_description": "Verwendet maschinelles Lernen auf den Dateien, um Duplikate zu finden. Baut auf der intelligenten Suche auf",
"exclusion_pattern_description": "Mit Ausschlussmustern können Dateien und Ordner beim Scannen deiner 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.",
"export_config_as_json_description": "Aktuelle Systemkonfiguration als JSON-Datei herunterladen",
"external_libraries_page_description": "Externe Bibliotheksseite für Administratoren",
"face_detection": "Gsichtserkennig",
"face_detection": "Gesichtserkennung",
"face_detection_description": "Diese Aufgabe erkennt mit maschinellem Lernen Gesichter in Dateien. Bei Videos wird nur das Vorschaubild verwendet. „Aktualisieren“ verarbeitet alle Dateien neu. „Zurücksetzen“ setzt zusätzlich alle Gesichter zurück. „Fehlende“ fügt nur nicht verarbeitete Dateien in die Warteschlange ein. Erfasste Gesichter werden zur Gesichtsidentifizierung in die Warteschlange eingefügt, um sie in bestehende oder neue Personen zu gruppieren.",
"facial_recognition_job_description": "Diese Aufgabe gruppiert im Anschluss an die Gesichtserkennung die erkannten Gesichter zu Personen. „Zurücksetzen“ gruppiert alle Gesichter neu, während „Fehlende“ Gesichter ohne Zuordnung in die Warteschlange stellt.",
"failed_job_command": "Befehl {command} ist für Aufgabe {job} fehlgeschlagen",
@@ -92,7 +99,7 @@
"image_fullsize_title": "Hochauflösende Vorschaueinstellungen",
"image_prefer_embedded_preview": "Eingebettete Vorschau bevorzugen",
"image_prefer_embedded_preview_setting_description": "Verwende eingebettete Vorschaubilder in RAW-Fotos als Grundlage für die Bildverarbeitung, sofern diese zur Verfügung stehen. Dies kann bei einigen Bildern genauere Farben erzeugen, allerdings ist die Qualität der Vorschau kameraabhängig und das Bild kann mehr Kompressionsartefakte aufweisen.",
"image_prefer_wide_gamut": "weiterer Farbraum bevorzugen",
"image_prefer_wide_gamut": "Breites Spektrum bevorzugen",
"image_prefer_wide_gamut_setting_description": "Display P3 (DCI-P3) für Vorschaubilder verwenden. 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": "Mittelgrosses Bild mit entfernten Metadaten, das bei der Betrachtung einer einzelnen Datei und für maschinelles Lernen verwendet wird",
"image_preview_quality_description": "Vorschauqualität von 1-100. Ein höherer Wert ist besser, erzeugt dadurch aber grössere Dateien und kann die Reaktionsfähigkeit der App beeinträchtigen. Ein niedriger Wert kann dafür aber die Qualität des maschinellen Lernens beeinträchtigen.",
@@ -100,7 +107,7 @@
"image_progressive": "Fortlaufend",
"image_progressive_description": "JPEG-Bilder schrittweise kodieren, um ein stufenweises Laden zu ermöglichen. Dies hat keine Auswirkungen auf WebP-Bilder.",
"image_quality": "Qualität",
"image_resolution": "Uflösig",
"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össere Dateigrössen und können die Reaktionsfähigkeit der App beeinträchtigen.",
"image_settings": "Bildeinstellungen",
"image_settings_description": "Qualität und Auflösung der generierten Bilder verwalten",
@@ -113,8 +120,6 @@
"job_not_concurrency_safe": "Diese Aufgabe kann nicht mehrmals parallel laufen gelassen werden.",
"job_settings": "Aufgabeneinstellungen",
"job_settings_description": "Gleichzeitige Ausführung von Aufgaben verwalten",
"jobs_delayed": "Qualität",
"jobs_failed": "{jobCount, plural, other {# failed}}",
"jobs_over_time": "Jobs im Laufe der Zeit",
"library_created": "Bibliothek erstellt: {library}",
"library_deleted": "Bibliothek gelöscht",
@@ -122,49 +127,6 @@
"library_folder_description": "Wähle einen Ordner zum Importieren. Dieser Ordner wird inklusive Unterordnern nach Bildern und Videos durchsucht.",
"library_remove_exclusion_pattern_prompt": "Bilst du sicher, dass du dieses Ausschlussmuster entfernen möchtest?",
"library_remove_folder_prompt": "Bist du sicher, dass du diesen Import-Ordner entfernen möchtest?",
"library_scanning": "Regelmässiges Scannen",
"library_scanning_description": "Regelmässiges Scannen der Bibliothek konfigurieren",
"library_scanning_enable_description": "Regelmässiges Scannen der Bibliothek aktivieren",
"library_settings": "Externe Bibliothek",
"library_settings_description": "Einstellungen für externe Bibliotheken verwalten",
"library_tasks_description": "Externe Bibliotheken nach neuen und/oder geänderten Assets durchsuchen",
"library_updated": "Aktualisierte Bibliothek",
"library_watching_enable_description": "Änderungen an Dateien in externen Bibliotheken überwachen",
"library_watching_settings": "Bibliothek beobachten [EXPERIMENTELL]",
"library_watching_settings_description": "Automatisch nach geänderten Dateien suchen",
"logging_enable_description": "Logging aktivieren",
"logging_level_description": "Wenn aktiviert, welches Logging-Level soll verwendet werden.",
"logging_settings": "Logging",
"machine_learning_availability_checks": "Verfügbarkeitsüberprüfungen",
"machine_learning_availability_checks_description": "Verfügbare Machine-Learning-Server automatisch erkennen und bevorzugen",
"machine_learning_availability_checks_enabled": "Verfügbarkeitsüberprüfungen aktivieren",
"machine_learning_availability_checks_interval": "Überprüfungsintervall",
"machine_learning_availability_checks_interval_description": "Intervall in Millisekunden zwischen Verfügbarkeitsüberprüfungen",
"machine_learning_availability_checks_timeout": "Zeitüberschreitung der Anfrage",
"machine_learning_availability_checks_timeout_description": "Timeout in Millisekunden für Verfügbarkeitsüberprüfungen",
"machine_learning_clip_model": "CLIP Model",
"machine_learning_clip_model_description": "Der Name eines der <link>hier</link> gelisteten CLIP-Modelle. Hinweis: Nach dem Ändern eines Modells muss der Smart Search-Vorgang für alle Bilder erneut gestartet werden.",
"machine_learning_duplicate_detection": "Duplikatserkennung",
"machine_learning_duplicate_detection_enabled": "Duplikatserkennung aktivieren",
"machine_learning_duplicate_detection_enabled_description": "Falls deaktiviert, werden exakt identische Assets weiterhin dedupliziert.",
"machine_learning_duplicate_detection_setting_description": "Verwende CLIP embeddings um wahrscheinliche Dublikate zu finden",
"machine_learning_enabled": "Maschinelles Lernen aktivieren",
"machine_learning_enabled_description": "Falls deaktiviert, werden alle ML-Funktionen deaktiviert, unabhängig von den untenstehenden Einstellungen.",
"machine_learning_facial_recognition": "Gesichtserkennung",
"machine_learning_facial_recognition_description": "Gesichter in Bildern erkennen, identifizieren und gruppieren",
"machine_learning_facial_recognition_model": "Model für die Gesichtserkennung",
"machine_learning_facial_recognition_model_description": "Modell sind noch abstigender Grössi ufglitet. Grösseri Modell sind langsamer und bruched meh Arbeitsspeicher, aber produziered besseri Resultat. Gsichterkennig muss für alli Fotis neu usgfüehrt wärde, nochdem s Modell gwächslet worde esch.",
"machine_learning_facial_recognition_setting": "Gsichtserkennig ischalte",
"machine_learning_facial_recognition_setting_description": "Wenn usgschalte wärded Fotis ned für Gsichtserkennig enkodiert und wärded ned ide Personesektion uf de",
"machine_learning_max_detection_distance": "Maximali Erkennigsdistanz",
"machine_learning_max_detection_distance_description": "Maximali Distanz zwüsche zwei Bilder, um si als Duplikat z erkenne, zwische 0.001 - 0.1. Höcheri Wärt erkenned meh Duplikat, aber chönd Falschpositivi erzüge."
},
"video_quality": "Videoqualität",
"videos": "Videos",
"view": "Aasicht",
"view_album": "Album aazeige",
"view_all": "Alles aazeige",
"view_all_users": "Alli Nutzer aazeige",
"view_details": "Details aaluege",
"view_link": "Link aazeige"
"library_scanning": "Regelmässiges Scannen"
}
}
+323 -12
View File
File diff suppressed because it is too large Load Diff
+317 -56
View File
File diff suppressed because it is too large Load Diff
-2253
View File
File diff suppressed because it is too large Load Diff
+165 -887
View File
File diff suppressed because it is too large Load Diff
+329 -143
View File
File diff suppressed because it is too large Load Diff
+347 -154
View File
File diff suppressed because it is too large Load Diff
+14 -2116
View File
File diff suppressed because it is too large Load Diff
+26
View File
@@ -16,12 +16,17 @@
"add_a_name": "افزودن نام",
"add_a_title": "افزودن عنوان",
"add_action": "افزودن عملیات",
"add_action_description": "برای افزودن و اعمال یک عملیات کلیک کنید",
"add_assets": "افزودن عکس یا فیلم",
"add_birthday": "افزودن تاریخ تولد",
"add_endpoint": "افزودن پایانه",
"add_exclusion_pattern": "افزودن الگوی استثنا",
"add_filter": "افزودن فیلتر",
"add_filter_description": "برای افزودن یک شرط فیلتر کلیک کنید",
"add_location": "افزودن مکان",
"add_more_users": "افزودن کاربرهای بیشتر",
"add_partner": "افزودن شریک",
"add_path": "افزودن مسیر",
"add_photos": "افزودن عکس ها",
"add_tag": "افزودن تگ",
"add_to": "افزودن به …",
@@ -29,11 +34,14 @@
"add_to_album_bottom_sheet_added": "به آلبوم {album} اضافه شد",
"add_to_album_bottom_sheet_already_exists": "قبلا در آلبوم {album} موجود است",
"add_to_album_bottom_sheet_some_local_assets": "برخی از محتواهای محلی را نشد به آلبوم اضافه کرد",
"add_to_album_toggle": "تغییر وضعیت انتخاب برای {album}",
"add_to_albums": "افزودن به آلبوم",
"add_to_albums_count": "افزودن به آلبوم ها {count}",
"add_to_bottom_bar": "افزودن به",
"add_to_shared_album": "افزودن به آلبوم اشتراکی",
"add_upload_to_stack": "افزودن فایل ارسالی به مجموعه",
"add_url": "افزودن آدرس URL",
"add_workflow_step": "افزودن یک مرحله به روند کار",
"added_to_archive": "به آرشیو اضافه شد",
"added_to_favorites": "به علاقه مندی ها اضافه شد",
"added_to_favorites_count": "{count, number} تا به علاقه مندی ها اضافه شد",
@@ -398,6 +406,7 @@
"all": "همه",
"all_people": "همه افراد",
"allow_dark_mode": "اجازه دادن به حالت تاریک",
"allow_edits": "اجازه ویرایش",
"api_key": "کلید API",
"api_keys": "کلیدهای API",
"app_settings": "تنظیمات برنامه",
@@ -418,6 +427,7 @@
"cannot_merge_people": "نمی‌توان افراد را ادغام کرد",
"cannot_update_the_description": "نمی‌توان توضیحات را به‌روزرسانی کرد",
"change_date": "تغییر تاریخ",
"change_expiration_time": "تغییر زمان انقضا",
"change_location": "تغییر مکان",
"change_name": "تغییر نام",
"change_name_successfully": "نام با موفقیت تغییر یافت",
@@ -433,6 +443,7 @@
"clear_value": "پاک کردن مقدار",
"close": "بستن",
"collapse_all": "جمع کردن همه",
"color_theme": "تم رنگ",
"comment_options": "گزینه‌های نظر",
"comments_are_disabled": "نظرات غیرفعال هستند",
"confirm": "تأیید",
@@ -444,6 +455,7 @@
"copied_image_to_clipboard": "تصویر به کلیپ‌بورد کپی شد.",
"copied_to_clipboard": "به کلیپ‌بورد کپی شد!",
"copy_error": "خطا در کپی",
"copy_file_path": "کپی مسیر فایل",
"copy_image": "کپی تصویر",
"copy_link": "کپی لینک",
"copy_link_to_clipboard": "کپی لینک به کلیپ‌بورد",
@@ -481,8 +493,10 @@
"details": "جزئیات",
"direction": "جهت",
"disabled": "غیرفعال",
"disallow_edits": "عدم اجازه ویرایش",
"discover": "کشف کردن",
"dismiss_all_errors": "رد تمام خطاها",
"dismiss_error": "رد خطا",
"display_options": "گزینه‌های نمایش",
"display_order": "ترتیب نمایش",
"display_original_photos": "نمایش عکس‌های اصلی",
@@ -565,6 +579,7 @@
"let_others_respond": "اجازه به دیگران برای پاسخ‌گویی",
"level": "سطح",
"library": "کتابخانه",
"library_options": "گزینه‌های کتابخانه",
"light": "روشن",
"link_to_oauth": "اتصال به OAuth",
"linked_oauth_account": "حساب OAuth متصل شده",
@@ -579,6 +594,7 @@
"main_branch_warning": "شما در حال استفاده از نسخه توسعه‌دهندگان هستید که آزمایشی و ناپایدار است. اکیداً توصیه می‌کنیم از نسخه رسمی استفاده کنید!",
"main_menu": "منوی اصلی",
"make": "ساختن",
"manage_shared_links": "مدیریت لینک‌های اشتراکی",
"manage_sharing_with_partners": "مدیریت محتوای مشترک با همسر",
"manage_the_app_settings": "مدیریت تنظیمات برنامه",
"manage_your_account": "مدیریت حساب کاربری",
@@ -586,10 +602,13 @@
"manage_your_devices": "مدیریت دستگاه‌های متصل",
"manage_your_oauth_connection": "مدیریت اتصال OAuth",
"map": "نقشه",
"map_assets_in_bounds": "{count} عکس ها",
"map_cannot_get_user_location": "موقعیت مکانی در دسترس نیست",
"map_location_dialog_yes": "بله",
"map_location_picker_page_use_location": "استفاده از این موقعیت مکانی",
"map_location_service_disabled_content": "برای نمایش دارایی‌ها بر اساس موقعیت مکانی، نیاز به فعال‌سازی سرویس مکان‌یابی دارید. می‌خواهید همین حالا فعال شود؟",
"map_location_service_disabled_title": "سرویس مکان‌یابی غیرفعال است",
"map_marker_for_images": "نشانگر روی نقشه برای عکس‌های گرفته‌شده در {city}, {country}",
"map_marker_with_image": "علامت‌گذاری نقشه با عکس",
"map_no_location_permission_content": "برای نمایش عکس‌های اطرافتان، برنامه نیاز به دسترسی به موقعیت مکانی دارد. اجازه دسترسی می‌دهید؟",
"map_no_location_permission_title": "دسترسی به موقعیت شما فعال نیست",
@@ -599,6 +618,7 @@
"map_settings_date_range_option_days": "{days} روز گذشته",
"map_settings_date_range_option_year": "پارسال",
"map_settings_date_range_option_years": "{years} سال گذشته",
"map_settings_dialog_title": "تنظیمات نقشه",
"map_settings_include_show_archived": "شامل موارد بایگانی شده",
"map_settings_include_show_partners": "شامل همسر",
"matches": "تطابق‌ها",
@@ -697,9 +717,12 @@
"refresh": "تازه سازی",
"refreshed": "تازه سازی شد",
"remove": "حذف",
"remove_deleted_assets": "حذف محتواهای حذف‌شده",
"remove_from_album": "حذف از آلبوم",
"remove_from_favorites": "حذف از علاقه‌مندی‌ها",
"rename": "تغییر نام",
"repair": "تعمیر",
"replace_with_upload": "جایگزینی با آپلود",
"reset": "بازنشانی",
"reset_password": "بازنشانی رمز عبور",
"restore": "بازیابی",
@@ -713,6 +736,7 @@
"saved_settings": "تنظیمات ذخیره شد",
"say_something": "چیزی بگویید",
"scan_all_libraries": "اسکن همه کتابخانه‌ها",
"scan_settings": "تنظیمات اسکن",
"search": "جستجو",
"search_albums": "جستجوی آلبوم‌ها",
"search_by_context": "جستجو براساس زمینه",
@@ -733,6 +757,7 @@
"select_face": "انتخاب چهره",
"select_featured_photo": "انتخاب عکس ویژه",
"select_keep_all": "انتخاب نگهداری همه",
"select_library_owner": "انتخاب مالک کتابخانه",
"select_new_face": "انتخاب چهره جدید",
"select_photos": "انتخاب عکس‌ها",
"selected": "انتخاب شده",
@@ -816,6 +841,7 @@
"view": "مشاهده",
"view_all": "مشاهده همه",
"view_all_users": "مشاهده همه کاربران",
"view_links": "مشاهده لینک‌ها",
"view_next_asset": "مشاهده محتوای بعدی",
"view_previous_asset": "مشاهده محتوای قبلی",
"waiting": "در انتظار",
+331 -57
View File
File diff suppressed because it is too large Load Diff
+8 -28
View File
@@ -7,39 +7,34 @@
"action_common_update": "I-update",
"actions": "Mga Aksyon",
"active": "Tumatakbo",
"active_count": "Aktibo: {count}",
"activity": "Mga Aktibidad",
"activity_changed": "Ang aktibidad ay {enabled, select, true {naka-enable} other {hindi naka-enable}}",
"add": "Mag dagdag",
"add_a_description": "Dagdagan ng deskripsyon",
"add_a_location": "Dagdagan ng lugar",
"add_a_name": "Dagdagan ng pangalan",
"add_a_title": "Dagdagan ng pamagat",
"add_action": "Magdagdag ng aksyon",
"add_assets": "Dagdagan ng asset",
"add_birthday": "Maglagay ng kaarawan",
"add_endpoint": "Dagdagan ng dulo",
"add_exclusion_pattern": "Magdagdag ng exlusion pattern",
"add_location": "Magdagdag ng lugar",
"add_more_users": "Magdagdag ng mga user",
"add_partner": "Magdagdag ng kasangga",
"add_path": "Magdagdag ng path",
"add_photos": "Magdagdag ng litrato",
"add_step": "Magdagdag ng step",
"add_tag": "Magdagdag ng tag",
"add_to": "Idagdag sa…",
"add_to_album": "Idagdag sa album",
"add_to_album_bottom_sheet_added": "Naidagdag sa {album}",
"add_to_album_bottom_sheet_already_exists": "Nasa {album} na",
"add_to_album_bottom_sheet_some_local_assets": "May ilang mga local assets ang hindi maidagdag sa album",
"add_to_albums": "Idagdag sa mga album",
"add_to_albums_count": "Idagdag sa mga album ({count})",
"add_to_bottom_bar": "Idagdag sa",
"add_upload_to_stack": "Magdagdag ng upload para ma-stack",
"add_to_shared_album": "Idagdag sa shared album",
"add_url": "Magdagdag ng URL",
"added_to_archive": "Naidagdag sa archive",
"added_to_favorites": "Naidagdag sa mga paborito",
"added_to_favorites_count": "Naidagdag ang {count, number} sa mga paborito",
"admin": {
"add_exclusion_pattern_description": "Dagdagan ng pattern para maibukod. Supportado ang pag-tutugma gamit ang *, **, at ?. Para hindi maisama ang mga file sa direktoryo na may pangalang \"Raw\", gamitin ang \"**/Raw/**\". Para hindi maisama ang lahat ng mga file na nagtatapos sa \".tif\", gamitin ang \"**/*.tif\". Para hindi maisama ang isang tiyak na folder, gamitin ang \"/path/to/ignore/**\".",
"admin_user": "Admin User",
"asset_offline_description": "Ang external library asset na ito ay hindi na makikita sa disk at nailipat na sa basurahan. Kung ang file ay nailipat sa loob ng library, tignan ang iyong timeline para sa kaukulang asset. Para maibalik ang asset na ito, siguraduhin na ang file ay maa-access ng Immich at muling i-scan ang library.",
"authentication_settings": "Setting ng mga Pagkakakilanlan",
"authentication_settings_description": "Pamahalaan ang password, OAuth, and iba pang setting ng pagkakakilanlan",
@@ -49,10 +44,6 @@
"backup_database": "Gumawa ng Dump ng Database",
"backup_database_enable_description": "Paganahin ang Database Dumps",
"backup_keep_last_amount": "Bilang ng mga itatagong nakaraang dump",
"backup_onboarding_1_description": "offsite na kopya sa cloud o sa ibang pisikal na lokasyon.",
"backup_onboarding_footer": "Para sa karagdagang impormasyon tungkol sa pag-backup ng Immich, maaaring tignan sa <link>dokumentasyon</link>.",
"backup_onboarding_parts_title": "Ang 3-2-1 backup ay kasama:",
"backup_onboarding_title": "Backups",
"backup_settings": "Setting ng mga Database Dump",
"backup_settings_description": "Pamahalaan ang mga setting ng database dump.",
"cleared_jobs": "Tinanggal na ang mga trabaho para sa {job}",
@@ -70,44 +61,33 @@
"disable_login": "I-disable ang login",
"duplicate_detection_job_description": "Hanapin ang mga magkakatulad na imahe gamit ang machine learning. Umaasa sa Smart Search",
"exclusion_pattern_description": "Maaaring gamitin ang mga pattern na pangbukod para hindi pansinin ang ilang file o folder habang binabasa ang iyong library. Mainam itong solusyon para sa mga folder na may file na ayaw niyong ma-import, tulad ng mga RAW na file.",
"face_detection": "Face detection",
"force_delete_user_warning": "BABALA: Tatanggalin itong user at lahat ng asset nila, Hindi ito mababawi at ang kanilang files ay hindi na mababalik",
"image_format": "Format",
"note_cannot_be_changed_later": "TANDAAN: Hindi na ito pwede baguhin sa susunod!",
"server_welcome_message_description": "Mensahe na ipapakita sa login page.",
"user_restore_description": "Ang account ni <b>{user}</b> ay maibabalik."
},
"album_user_left": "Umalis sa {album}",
"all_albums": "Lahat ng albums",
"all_people": "Lahat ng tao",
"all_videos": "Lahat ng video",
"api_key_description": "Isang beses lamang na ipapakita itong value. Siguraduhin na ikopya itong value bago iclose ang window na ito.",
"are_these_the_same_person": "Itong tao na ito ay parehas?",
"asset_adding_to_album": "Dinadagdag sa album...",
"asset_filename_is_offline": "Offline ang asset {filename}",
"asset_uploading": "Ina-upload...",
"change_your_password": "Palitan ang iyong password",
"country": "Bansa",
"create_album_page_untitled": "Walang pamagat",
"documentation": "Dokumentasyion",
"done": "Tapos na",
"download": "I-download",
"edit": "I-edit",
"edit_album": "I-edit ang album",
"edit_avatar": "I-edit ang avatar",
"edit_birthday": "I-edit ang birthday",
"edit_date": "I-edit ang petsa",
"edit_date_and_time": "I-edit ang petsa at oras",
"editor_close_without_save_title": "Isara ang editor?",
"explore": "I-explore",
"export": "I-export",
"has_quota": "May quota",
"hour": "Oras",
"info": "Informasyon",
"jobs": "Mga trabaho",
"language": "Wika",
"leave": "Umalis",
"no_results": "Walang resulta",
"shared_link_edit_expire_after_option_minutes": "{count} minuto",
"shared_link_edit_expire_after_option_months": "{count} buwan",
"shared_link_edit_expire_after_option_year": "{count} taon",
"shared_link_edit_password_hint": "I-enter ang share password",
"year": "Taon"
"no_results": "Walang resulta"
}
+342 -159
View File
File diff suppressed because it is too large Load Diff
+325 -138
View File
File diff suppressed because it is too large Load Diff
+327 -140
View File
File diff suppressed because it is too large Load Diff
+195 -24
View File
@@ -5,34 +5,36 @@
"acknowledge": "Bestätige",
"action": "Aktion",
"action_common_update": "Aktualisiere",
"action_description": "A Gruppe fo Aktione wo söll usgfüert werde",
"actions": "Aktione",
"active": "Aktiv",
"active_count": "Aktive:{count}",
"activity": "Aktivität",
"activity_changed": "Aktivität isch {enabled, select, true {aktiviert} other {deaktiviert}}",
"add": "Aafüege",
"add_a_description": "Beschriebig hinzuäzfüägä",
"add_a_location": "Standort hiifüege",
"add_a_name": "Name hiifüege",
"add_a_title": "Titel hiifüege",
"add_action": "Aktion hiifüege",
"add_assets": "Objäkt Hinzuefüege",
"add_birthday": "Geburtsdatum hiifüege",
"add_endpoint": "Endpunkt hiifüege",
"add_exclusion_pattern": "Ausschlussmuster hiifüege",
"add_location": "Standort hiifüege",
"add_more_users": "Wiiteri Nutzer hiifüege",
"add_partner": "Partner hiifüege",
"add_path": "Pfad hiifüege",
"add_photos": "Fotos hiifüege",
"add_step": "Schritt hinzuefüege",
"add_tag": "Tag hiifüege",
"add_to": "Hiifüege zu …",
"add_to_album": "Zum Album hiifüege",
"add_to_album_bottom_sheet_added": "Zu {album} hiigfüegt",
"add_to_album_bottom_sheet_already_exists": "Bereits in {album}",
"add_to_album_bottom_sheet_some_local_assets": "E paar lokali Dateie händ nöd chönne zum Album hiigfüegt werde",
"add_to_album_toggle": "Uswahl umschalte für {album}",
"add_to_albums": "Zu Albe hiifüege",
"add_to_albums_count": "Zu Albe hiifüege ({count})",
"add_to_bottom_bar": "Hiifüege zu",
"add_to_shared_album": "Zum gteilte Album hiifüege",
"add_upload_to_stack": "Upload zum Stapel hiifüege",
"add_url": "URL hiifüege",
"added_to_archive": "Zum Archiv hiigfüegt",
@@ -180,15 +182,10 @@
"machine_learning_smart_search_enabled": "Intelligenti Suechi aktiviere",
"machine_learning_smart_search_enabled_description": "Wenn die Option deaktiviert isch, werde dBilder nöd für dintelligenti Suechi bruucht.",
"machine_learning_url_description": "DURL vom Server fürs maschinelli Lärne. Wenn meh als eini URL aagee wird, wird jeder Server einzeln usprobiert, bis einer erfolgrich antwortet und zwar i dr Räihäfolg vom erschte bis zum letschte. Server, wo nöd antworted, werde vorübergehend ignoriert, bis si wieder verfügbar sind.",
"maintenance_delete_backup": "Backup lösche",
"maintenance_restore_backup": "Backup wiederherstelle",
"maintenance_restore_backup_description": "Immich wird glöscht und vom usgwählte Backup wiederhergstellt. Es Backup wird vorher erstellt.",
"maintenance_restore_backup_different_version": "Das Backup esch mitere andere Version vo Immich erstellt worde!",
"maintenance_settings": "Wartig",
"maintenance_settings_description": "Immich i de Wartigsmodus versetze.",
"maintenance_start": "Wartigsmodus startä",
"maintenance_start_error": "Wartigsmodus het nöd chönne gstartet werde.",
"maintenance_upload_backup_error": "Backup hed ned chönne ufeglade werde, esch es en .sql/.sql.gz Datei?",
"manage_concurrency": "Gliichziitigi Uusfüerig verwalte",
"manage_concurrency_description": "Gang zur Job-Site, um dJob-Parallelität z verwalte",
"manage_log_settings": "Log-Iistellige verwalte",
@@ -251,8 +248,6 @@
"notification_enable_email_notifications": "E-Mail-Benochrichtigige aktiviere",
"notification_settings": "Benochrichtigigs-Iistellige",
"notification_settings_description": "Benochrichtigigs-Iistellige (inkl. E-Mail) verwalte",
"oauth_allow_insecure_requests": "Unsicheri Aafroge erlaube",
"oauth_allow_insecure_requests_description": "ACHTUNG: Das deaktiviert TLS Zertifikats-Validierig für OAuth aafroge und setzt dech möglicherwiis MITM Attacke us.",
"oauth_auto_launch": "Auto-Start",
"oauth_auto_launch_description": "Automatischer Start vom OAuth-Aahmäldvorgang bim Ufruäfä vo dr Aahmäldigs-Site",
"oauth_auto_register": "Automatischi Registrierig",
@@ -260,7 +255,6 @@
"oauth_button_text": "Button-Text",
"oauth_client_secret_description": "Erforderlich, wenn PKCE (Proof Key for Code Exchange) nöd vom OAuth-Anbieter unterstützt wird",
"oauth_enable_description": "Ahmeldig mit OAuth",
"oauth_end_session_url_description": "Benutzer zu dere URI witerleite wenn sie sech uslogged.",
"oauth_mobile_redirect_uri": "Mobile Umleitigs-URI",
"oauth_mobile_redirect_uri_override": "Mobile Umleitigs-URI überschriebe",
"oauth_mobile_redirect_uri_override_description": "Iischalte, wenn dr OAuth-Anbieter kei mobile URI wie „{callback}“ erlaubt",
@@ -438,6 +432,8 @@
"admin_password": "Administrator Passwort",
"administration": "Verwaltig",
"advanced": "Erwiitert",
"advanced_settings_enable_alternate_media_filter_subtitle": "Bruuch die Option, um Medie während dr Synchronisierung nach andere Kriterie z filtere. Versuech das nume, wenn Problem mit dr Erkenig vo allne Albe dur dApp auftrete.",
"advanced_settings_enable_alternate_media_filter_title": "[EXPERIMENTELL] Benutz alternative Filter für dSynchronisierig vo de Geräte-Albe",
"advanced_settings_log_level_title": "Log-Level: {level}",
"advanced_settings_prefer_remote_subtitle": "Einigi Gerät sind sehr langsam bim Lade vo lokale Vorschaubilder. Aktivier die Iistellige, um stattdesse dServer-Bilder z lade.",
"advanced_settings_prefer_remote_title": "Server-Bilder bevorzuge",
@@ -445,6 +441,8 @@
"advanced_settings_proxy_headers_title": "Benutzerdefinierti Proxy-Header [Experimentell]",
"advanced_settings_readonly_mode_subtitle": "Aktiviert dr schriibgschützte Modus, i dem dFotos nume aazeigt werde chöi. Funktione wie mehri Bilder uswähle, teile, übertrage und lösche sind deaktiviert. Aktivier/Deaktivier dr schriibgschützte Modus über dr Benutzer-Avatar uf em Hauptbildschirm",
"advanced_settings_readonly_mode_title": "Schriibgschützte Modus",
"advanced_settings_self_signed_ssl_subtitle": "Verifizierig vo SSL-Zertifikate vom Server überspringe. Nötig bi selbstsignierte Zertifikate.",
"advanced_settings_self_signed_ssl_title": "Selbstsignierti SSL-Zertifikate erlaubä [Experimentell]",
"advanced_settings_sync_remote_deletions_subtitle": "Automatisches Lösche oder Wiederherstellig vo ener Datei uf däm Gerät, wenn die Aktion im Web durgfüert wird",
"advanced_settings_sync_remote_deletions_title": "Mit Server-Löschige synchronisiere [Experimentell]",
"advanced_settings_tile_subtitle": "Erwiiterti Benutzer-Iistellige",
@@ -460,7 +458,11 @@
"album_delete_confirmation": "Bisch du sicher, dass du sAlbum {album} wotsch lösche?",
"album_delete_confirmation_description": "Wenn das Album gteiltt worde isch, chönnt anderi Benutzer nümme druf zuegriife.",
"album_deleted": "Album glöscht",
"album_info_card_backup_album_excluded": "USGSCHLOSSÄ",
"album_info_card_backup_album_included": "IHGSCHLOSSÄ",
"album_info_updated": "Album-Infos aktualisiert",
"album_leave": "Album verloh?",
"album_leave_confirmation": "Bisch du sicher, dass du sAlbum {album} verla lasse wotsch?",
"album_name": "Albumname",
"album_options": "Albumoptione",
"album_remove_user": "Nutzer entfernä?",
@@ -470,8 +472,15 @@
"album_summary": "Album Zämmefassig",
"album_updated": "Album aktualisiert",
"album_updated_setting_description": "Erhalt e E-Mail-Benachrichtigig, wenn e freigähs Album neui Dateie enthält",
"album_upload_assets": "Dateie vo dim Computer ufelade und zu Album hinzuefüege",
"album_user_left": "{album} verlasse",
"album_user_removed": "{user} entfernt",
"album_viewer_appbar_delete_confirm": "Bisch du sicher, dass du das Album us dim Konto wotsch lösche?",
"album_viewer_appbar_share_err_delete": "Album het nöd chenne glöscht werde",
"album_viewer_appbar_share_err_leave": "Album het nöd chenne verloh werde",
"album_viewer_appbar_share_err_remove": "Bi dr Löschung vo Element us em Album isch es Problem uufgetrete",
"album_viewer_appbar_share_err_title": "Dr Titel het nöd chönne gänderet werde",
"album_viewer_appbar_share_leave": "Album verloh",
"album_viewer_appbar_share_to": "Teile über",
"album_viewer_page_share_add_users": "Nutzer hinzufüegä",
"album_with_link_access": "Lah jede mit em Link dFotos und dPersone i däm Album aaluege.",
"albums": "Albene",
@@ -483,20 +492,21 @@
"all": "Alli",
"all_albums": "Alli Albene",
"all_people": "Alli Persone",
"all_photos": "Alli Fotis",
"all_videos": "Alli Videos",
"allow_dark_mode": "Dunkle-Modus erlaube",
"allow_edits": "Bearbeitig erlaube",
"allow_public_user_to_download": "Erlaub öffentliche Benutzer zdownloade",
"allow_public_user_to_upload": "Erlaub öffentliche Benutzer ufezlade",
"allowed": "Erlaubt",
"alt_text_qr_code": "QR-Code Bild",
"always_keep": "Immer bhalte",
"anti_clockwise": "Gäge de Uhrzeigersinn",
"api_key": "API-Schlüssel",
"api_key_description": "Dä Wert wird nume einisch aazeigt. Bitte kopier ihn, bevor du sFänschter schliessisch.",
"api_key_empty": "Din API-Schlüssel-Name dörf nöd leer si",
"api_keys": "API-Schlüssel",
"app_architecture_variant": "Variante (Architektur)",
"app_bar_signout_dialog_content": "Bisch du sicher, dass du dich abmälde wotsch?",
"app_bar_signout_dialog_ok": "Jo",
"app_bar_signout_dialog_title": "Abmälde",
"app_download_links": "App Download Links",
"app_settings": "App-Ihstellige",
@@ -507,46 +517,62 @@
"archive": "Archiv",
"archive_action_prompt": "{count} zum Archiv hinzuegfüegt",
"archive_or_unarchive_photo": "Foti archivierä bzw. Archvierig ufhebä",
"archive_page_no_archived_assets": "Kei archivierti Inhält gfundä",
"archive_page_title": "Archiv ({count})",
"archive_size": "Archivgrössi",
"archive_size_description": "Archivgrössi für Downloads konfiguriere (in GiB)",
"archived": "Archiviert",
"archived_count": "{count, plural, other {# archiviert}}",
"are_these_the_same_person": "Isch das di gliichi Person?",
"are_you_sure_to_do_this": "Bisch du sicher, dass du das wotsch mache?",
"asset_action_delete_err_read_only": "Schriibgschützti Inhält chönd nöd glöscht werde, überspringe",
"asset_action_share_err_offline": "Die Offline-Date chönnd nöd glesä werdä, überspringä",
"asset_added_to_album": "Zum Album hinzugfüegt",
"asset_adding_to_album": "Hinzufüegä zum Album…",
"asset_created": "Datei erstellt",
"asset_description_updated": "Die Beschribiig vo de Datei isch aktualisiert worde",
"asset_filename_is_offline": "Datei {filename} isch offline",
"asset_has_unassigned_faces": "Datei het nöd zuegwiseni Gsichter",
"asset_hashing": "Berechni Prüfsummi…",
"asset_list_group_by_sub_title": "Gruppiere noch",
"asset_list_layout_settings_dynamic_layout_title": "Dynamischs Layout",
"asset_list_layout_settings_group_automatically": "Automatisch",
"asset_list_layout_settings_group_by": "Gruppierä Elemente noch",
"asset_list_layout_settings_group_by_month_day": "Monet + Tag",
"asset_list_layout_sub_title": "Layout",
"asset_list_settings_subtitle": "Iistellige fürs Foto-Gitter-Layout",
"asset_list_settings_title": "Fotigitter",
"asset_not_found_on_device_android": "Datei ned ufem Grät gfunde",
"asset_offline": "Datei offline",
"asset_offline_description": "Die externi Datei isch nümme uf em Datenträger vorhande. Bitte wend dich ah din Immich-Administrator, um Hilf z becho.",
"asset_restored_successfully": "Datei erfolgriich wiederhergstellt",
"asset_skipped": "Übersprungä",
"asset_skipped_in_trash": "Im Papierkorb",
"asset_trashed": "Datei glöscht",
"asset_troubleshoot": "Datei Fehlerbehebig",
"asset_uploaded": "Ufeglade",
"asset_uploading": "Ufelade…",
"asset_viewer_settings_subtitle": "Verwaltig vo de Iistellige für dFoto-Aazeig",
"asset_viewer_settings_title": "Foto-Aazeig",
"assets": "Dateie",
"assets_added_count": "{count, plural, one {# Datei} other {# Dateie}} hinzugefügt",
"assets_added_to_album_count": "{count, plural, one {# Datei} other {# Dateie}} zum Album hinzugefügt",
"assets_added_to_albums_count": "{assetTotal, plural, one {# Datei} other {# Dateie}} zu {albumTotal, plural, one {# Album} other {# Albene}} hinzugefügt",
"assets_cannot_be_added_to_album_count": "{count, plural, one {Datei chan}other {Dateie chönnd}} nöd zum Album hinzuegfüegt werde",
"assets_cannot_be_added_to_albums": "{count, plural, one {Datei chan} other {Dateie chönnd}} nöd zu dene Albe hinzuegfüegt werde",
"assets_count": "{count, plural, one {# Datei} other {# Dateie}}",
"assets_deleted_permanently": "{count} Elemänt(e) permanent glöscht",
"assets_deleted_permanently_from_server": "{count} Elemänt(e) permanent vom Immich-Server glöscht",
"assets_downloaded_failed": "{count, plural, one {# Datei abeglade {error} gschiiteret} other {# Dateie abeglade {error} gschiiteret}}",
"assets_downloaded_successfully": "{count, plural, one {# Datei erfolgreich abeglade} other {# Dateie erfolgreich abeglade}}",
"assets_moved_to_trash_count": "{count, plural, one {# Datei} other {# Dateie}} i de Papirkorb verschobe",
"assets_permanently_deleted_count": "{count, plural, one {# Datei} other {# Dateie}} endgültig glöscht",
"assets_removed_count": "{count, plural, one {# Datei} other {# Dateie}} entfernt",
"assets_removed_permanently_from_device": "{count} Element(er) permanent vo dim Gerät glöscht",
"assets_restore_confirmation": "Bisch du sicher, dass du alli Date us em Papirkorb wiederherställe wotsch? Die Aktion cha nöd rückgängig gmacht werde! Beachte, dass Offline-Dateie uf die Wiis nöd wiederherställt werde chönnd.",
"assets_restored_count": "{count, plural, one {# Datei} other {# Dateie}} wiederhergstellt",
"assets_restored_successfully": "{count} Elemänt(e) erfolgriich wiederhergstellt",
"assets_trashed": "{count} Element(e) glöscht",
"assets_trashed_count": "{count, plural, one {# Datei} other {# Dateie}} ih de Papierkorb verschobe",
"assets_trashed_from_server": "{count} Elemänt(e) vom Immich-Server glöscht",
"assets_were_part_of_album_count": "{count, plural, one {# Datei isch} other {# Dateie sind}} bereits im Album vorhanden",
"assets_were_part_of_albums_count": "{count, plural, one {Datei isch} other {Dateie sind}} bereits i de Albene",
"authorized_devices": "Verwendeti Grät",
@@ -555,44 +581,84 @@
"autoplay_slideshow": "Automatische Diashow",
"back": "Zrugg",
"back_close_deselect": "Zrugg, Schliesse oder Abwählä",
"background_backup_running_error": "Sicherig läuft im Hintergrund. Manuelli Sicherig cha nöd gstartet werde",
"background_location_permission": "Hintergrund Standortfreigob",
"background_location_permission_content": "Um im Hintergrund zwüsche de Netzwerke wächsle zchönne, mues Immich *immer* Zuegriff uf dr genaue Standort ha, damit dApp dr Name vom WLAN-Netzwerk ermittle cha",
"background_options": "Hintergrund Optione",
"backup": "Sicherig",
"backup_album_selection_page_albums_device": "Albene uf dem Grät ({count})",
"backup_album_selection_page_albums_tap": "Aatippe zum sichere, nomol aatippe zum usschliesse",
"backup_album_selection_page_assets_scatter": "Elemente (Fotos / Videos) chönnd sich über mehreri Albe verteile. Drum chönnd die vor dr Sicherig iigschlosse oder usgschlosse werde.",
"backup_album_selection_page_select_albums": "Albene uuswählä",
"backup_album_selection_page_selection_info": "Uuswahlinformatione",
"backup_album_selection_page_total_assets": "Element gsamt",
"backup_albums_sync": "Synchronisation vo de Sicherigsalbene",
"backup_all": "Alli",
"backup_background_service_backup_failed_message": "Es isch e Fähler bi dr Sicherig uufträtä. Versueche erneut…",
"backup_background_service_complete_notification": "Datei Backup abgschlossä",
"backup_background_service_connection_failed_message": "Es het kei Verbindung zum Server chönne hergstellt werde. Nomol versueche…",
"backup_background_service_current_upload_notification": "Lädt {filename} hoch",
"backup_background_service_default_notification": "Suech nach neue Element…",
"backup_background_service_error_title": "Fähler bi de Sicherig",
"backup_background_service_in_progress_notification": "Elemänt werdet gsicheret…",
"backup_background_service_upload_failure_notification": "{filename} het nöd chönne ufeglade werde",
"backup_controller_page_albums": "Gsicherti Albene",
"backup_controller_page_background_app_refresh_disabled_content": "Aktiviere Hintergrundaktualisierige i de Iihstellige -> Allgemein -> Hintergrundaktualisierige, um Sicherige im Hintergrund z ermöglichä.",
"backup_controller_page_background_app_refresh_disabled_title": "Hintergrundaktualisierige sind deaktiviert",
"backup_controller_page_background_app_refresh_enable_button_text": "Gang zu de Iistellige",
"backup_controller_page_background_battery_info_link": "Zeig mir wie",
"backup_controller_page_background_battery_info_message": "Für di beschte Resultat bi HintergrundSicherige: deaktiviere alli Batterieoptimierig und all Beschränkige für HintergrundAktivitäte vo Immich.\n\nWäge dem das gerätespezifisch isch, lueg bitte i de Infoe vom Hersteller vo dim Gerät nach.",
"backup_controller_page_background_battery_info_ok": "Ok",
"backup_controller_page_background_battery_info_title": "Batterieoptimierige",
"backup_controller_page_background_charging": "Nume während des Ladens",
"backup_controller_page_background_configure_error": "Hand nöd chönne de Hintergrundservice konfiguriere",
"backup_controller_page_background_delay": "Sicherig vo neue Elemente verzögeret um: {duration}",
"backup_controller_page_background_description": "Schalt de Hintergrundservice iih, um neui Elemente automatisch im Hintergrund z sichere, ohni dApp z öffne",
"backup_controller_page_background_is_off": "Automatischi Sicherig im Hintergrund isch deaktiviert",
"backup_controller_page_background_is_on": "Automatischi Sicherig im Hintergrund isch aktiviert",
"backup_controller_page_background_turn_off": "Hintergrundservice ussschaltä",
"backup_controller_page_background_turn_on": "Hintergrundservice iihschaltä",
"backup_controller_page_background_wifi": "Nume im WLAN",
"backup_controller_page_backup": "Sicherig",
"backup_controller_page_backup_selected": "Usgwählt: ",
"backup_controller_page_backup_sub": "Gsicherti Fotis und Videos",
"backup_controller_page_created": "Erstellt am: {date}",
"backup_controller_page_desc_backup": "Aktivier dSicherig, um Elemänt immer automatisch uf de Server ufezlade, während du dApp bruuchsch.",
"backup_controller_page_excluded": "Usgschlossä: ",
"backup_controller_page_failed": "Fählgschagä ({count})",
"backup_controller_page_filename": "Dateiname: {filename} [{size}]",
"backup_controller_page_id": "ID: {id}",
"backup_controller_page_info": "Informatione zur Sicherig",
"backup_controller_page_none_selected": "Keini usgwählt",
"backup_controller_page_remainder": "Verbliibend",
"backup_controller_page_remainder_sub": "No z sichere Fotis und Videos",
"backup_controller_page_server_storage": "Server-Speicher",
"backup_controller_page_start_backup": "Sicherig starte",
"backup_controller_page_status_off": "Sicherig im Vordergrund isch inaktiv",
"backup_controller_page_status_on": "Sicherig im Vordergrund isch aktiv",
"backup_controller_page_storage_format": "{used} von {total} gnutzt",
"backup_controller_page_to_backup": "No z sichere Albene",
"backup_controller_page_total_sub": "Alli Fotis und Videos",
"backup_controller_page_turn_off": "Sicherig im Vordergrund ussschalte",
"backup_controller_page_turn_on": "Sicherig im Vordergrund iihschalte",
"backup_controller_page_uploading_file_info": "Informatione",
"backup_err_only_album": "Das einzigi Album cha nöd entfernet werde",
"backup_error_sync_failed": "Synchronisierung gschiiteret. Sicherig cha nöd verarbeitet werde.",
"backup_info_card_assets": "Elemänt",
"backup_manual_cancelled": "Abbroche",
"backup_manual_in_progress": "Sicherig lauft scho. Bitte versuech es spöter nomol",
"backup_manual_success": "Erfolgriich",
"backup_manual_title": "Sicherigsstatus",
"backup_options": "Backup Optione",
"backup_options_page_title": "Sicherigsoptione",
"backup_setting_subtitle": "Verwaltig vo de Upload-iihstellige im Hintergrund und Vordergrund",
"backup_settings_subtitle": "Upload-Iihstellige verwalte",
"backward": "Rückwärts",
"biometric_auth_enabled": "Biometrische Authentifizierig aktiviert",
"biometric_locked_out": "Du bisch vo de biometrische Authenfizierig usgschlossä",
"biometric_no_options": "Kei biometrische Optione verfüegbar",
"biometric_not_available": "Dbiometrischi Authentifizierig isch uf däm Gerät nöd verfügbar",
"birthdate_saved": "Geburtsdatum erfolgrich gspeichert",
"birthdate_set_description": "Das Geburtsdatum wird bruucht, um sAlter vo däre Person zum Ziitpunkt vo enem Foto z berechne.",
"blurred_background": "Unscharfe Hintergrund",
"bugs_and_feature_requests": "Fähler & Verbesserigsvorschläg",
@@ -602,6 +668,20 @@
"bulk_keep_duplicates_confirmation": "Bisch du sicher, dass du {count, plural, one {# duplizierte Datei} other {# duplizierte Dateie}} behalte wotsch? Das wird alli Duplikat-Gruppä uuflöse, ohni öppis z lösche.",
"bulk_trash_duplicates_confirmation": "Bisch du sicher, dass du {count, plural, one {# duplizierte Datei} other {# duplizierte Dateie gemeinsam}} i de Papirkorb verschiebe wotsch? Das wird dgrössti Datei vo jeder Gruppe behalte und alli andere Duplikate i de Papirkorb verschiebe.",
"buy": "Immich erwerbä",
"cache_settings_clear_cache_button": "Zwüschespeicher lösche",
"cache_settings_clear_cache_button_title": "Löscht dr Zwüschecache vo dr App. Das wird dLeistungsfähigkeit vo dr App deutlich einschränke, bis dr Zwüschecache wieder ufbaut worde isch.",
"cache_settings_duplicated_assets_clear_button": "LÄÄRE",
"cache_settings_duplicated_assets_subtitle": "Fotos und Videos, wo vo dr App blockiert werdend",
"cache_settings_duplicated_assets_title": "Duplikate ({count})",
"cache_settings_statistics_album": "Vorschaubilder i dä Bibliothek",
"cache_settings_statistics_full": "Originalbilder",
"cache_settings_statistics_shared": "Vorschaubilder vo geteilte Albene",
"cache_settings_statistics_thumbnail": "Vorschaubilder",
"cache_settings_statistics_title": "Zwüschespiicher-Nutzig",
"cache_settings_subtitle": "Kontrolliere, wie Immich dr Zwüschecache bruucht",
"cache_settings_tile_subtitle": "Lokale Spiicher verwalte",
"cache_settings_tile_title": "Lokale Spiicher",
"cache_settings_title": "Zwüschespiicher Ihstellige",
"camera": "Kamera",
"camera_brand": "Kamera-Marke",
"camera_model": "Kamera-Modell",
@@ -614,10 +694,10 @@
"cannot_update_the_description": "Beschriibrig cha nöd aktualisiert werde",
"cast": "Überträge",
"cast_description": "Konfiguration verfügbarer Ziel",
"change": "Ändere",
"change_date": "Datum ändere",
"change_description": "Beschriibig aahpasse",
"change_display_order": "Aahzeigereihefolg ändere",
"change_expiration_time": "Verfallsziitpunkt ändere",
"change_location": "Standort ändere",
"change_name": "Name ändere",
"change_name_successfully": "Name isch erfolgrich gänderet worde",
@@ -635,16 +715,16 @@
"changed_visibility_successfully": "DSichtbarkeit isch erfolgrich gänderet worde",
"charging": "Uufladä",
"charging_requirement_mobile_backup": "Sicherig im Hintergrund fordert, dass sGerät ufglade wird",
"check_corrupt_asset_backup": "Uf bschädigti Asset-Sicherige prüefe",
"check_corrupt_asset_backup_button": "Überprüefig durrefüehrä",
"check_corrupt_asset_backup_description": "Führ die Prüefig nume mit aktiviertem WLAN dur, nachdem alli Dateie gsiichert worde sind. Dä Vorgang cha e paar Minute duurä.",
"check_logs": "Logs prüafä",
"checksum": "Prüefsumme",
"choose": "Uswähle",
"choose_matching_people_to_merge": "Wähl passendi Persone zum Zämmezfüehre",
"city": "Stadt",
"cleanup_confirm_description": "Immich hed {count} Dateie (vorem {date} erstellt) sicher ufem Server gfunde. Sölled die lokale Kopie vo dem Grät glöscht werde?",
"cleanup_confirm_prompt_title": "Vo dem Grät entferne?",
"cleanup_deleted_assets": "{count} Dateie i de lokali Papierchorb verschobe",
"cleanup_found_assets": "{count} ufegladni Dateie gfunde",
"cleanup_found_assets_with_size": "{count} gsicherti Dateie gfunde ({size})",
"cleanup_icloud_shared_albums_excluded": "Teilti iCloud Albe sind vom Scan usgschlosse",
"clear": "Lääre",
"clear_all": "Alles lääre",
@@ -652,16 +732,20 @@
"clear_file_cache": "Dateie-Cache lääre",
"clear_message": "Nochrichte lääre",
"clear_value": "Wert lääre",
"client_cert_dialog_msg_confirm": "Ok",
"client_cert_enter_password": "Passwort iigäh",
"client_cert_import": "Importiere",
"client_cert_import_success_msg": "Client Zertifikat isch importiert wordä",
"client_cert_invalid_msg": "Ungültigi Zertifikatsdatei oder falsches Passwort",
"client_cert_remove_msg": "Client Zertifikat isch entfernt wordä",
"client_cert_subtitle": "Unterstützt nume sPKCS12 (.p12, .pfx) Format. Zertifikat-Import oder -Entferne sind nume vor em Login möglech",
"client_cert_title": "SSL-Client-Zertifikat [Experimentell]",
"clockwise": "Im Uhrzeigersinn",
"close": "Schlüssä",
"collapse": "Zämmeklappe",
"collapse_all": "Alles zämmeklappe",
"color": "Farb",
"color_theme": "Farb-Theme",
"command": "Befähl",
"comment_deleted": "Kommentar glöscht",
"comment_options": "Kommentaroptione",
@@ -683,13 +767,18 @@
"contain": "Vollständig",
"context": "Kontext",
"continue": "Fortsetze",
"control_bottom_app_bar_create_new_album": "Neus Album erstellä",
"control_bottom_app_bar_delete_from_immich": "Vo Immich löschä",
"control_bottom_app_bar_delete_from_local": "Vom Grät lösche",
"control_bottom_app_bar_edit_location": "Standort bearbeite",
"control_bottom_app_bar_edit_time": "Datum und Uhrziit bearbeite",
"control_bottom_app_bar_share_link": "Link teile",
"control_bottom_app_bar_share_to": "Teile mit",
"control_bottom_app_bar_trash_from_immich": "I de Papierkorb verschiebä",
"copied_image_to_clipboard": "SBild isch i dZwüscheablag kopiert worde.",
"copied_to_clipboard": "I dZwüscheablage kopiert!",
"copy_error": "Kopier-Fähler",
"copy_file_path": "Dateipfad kopiere",
"copy_image": "Bild kopiere",
"copy_link": "Link kopiere",
"copy_link_to_clipboard": "Link I dZwüscheablage kopiere",
@@ -722,20 +811,25 @@
"created_at": "Erstellt",
"creating_linked_albums": "Erstelle verknüpfti Albene...",
"crop": "Zueschniidä",
"crop_aspect_ratio_fixed": "Fixiert",
"crop_aspect_ratio_free": "Frei",
"crop_aspect_ratio_original": "Original",
"curated_object_page_title": "Sachä",
"current_device": "Aktuells Grät",
"current_pin_code": "Aktuelle PIN Code",
"current_server_address": "Aktuelli Serveradresse",
"custom_locale": "Benutzerdefinierti Sproch",
"custom_locale_description": "Datumsahgoob und Zahle je nach Sproch und Land formatiere",
"custom_url": "Benutzerdefinierti URL",
"daily_title_text_date": "E, dd MMM",
"daily_title_text_date_year": "E, dd MMM, yyyy",
"dark": "Dunkäl",
"dark_theme": "Dunkli Aahsicht umschalte",
"date": "Datum",
"date_after": "Datum noch",
"date_and_time": "Datum und Ziit",
"date_before": "Datum vor",
"date_format": "E d. LLL y • hh:mm",
"date_of_birth_saved": "SGeburtsdatum isch erfolgrich gspiicheret worde",
"date_range": "Datumsberiich",
"day": "Tag",
@@ -749,6 +843,8 @@
"delete_dialog_alert": "Die Elemente werde unwiderruflich vo Immich und vom Grät entfernt",
"delete_dialog_alert_local": "Die Inhält werdend vom Grät glöscht, bliibend aber uf dem Immich-Server",
"delete_dialog_alert_local_non_backed_up": "Einigi Inhalt sind nöd i Immich gsiichert und werde dauerhaft vom Gerät gelöscht",
"delete_dialog_alert_remote": "Die Inhält werdend dauerhaft vom Immich-Server glöscht",
"delete_dialog_ok_force": "Trotzdem lösche",
"delete_dialog_title": "Endgültig lösche",
"delete_duplicates_confirmation": "Bisch du sicher, dass du diä Duplikat endgültig lösche wotsch?",
"delete_face": "Gsicht löschä",
@@ -767,16 +863,21 @@
"delete_tag_confirmation_prompt": "Bisch du sicher, dass de {tagName} glöscht werde sött?",
"delete_user": "Nutzer lösche",
"deleted_shared_link": "teilte link lösche",
"deletes_missing_assets": "Löscht Dateie, welli uf de Feschtplatte fählend",
"description": "Beschriibig",
"description_input_hint_text": "Beschriibig hinzufüegä...",
"description_input_submit_error": "DBeschribig het nöd chenne gänderet werde, bitte lueg im Log für meh Details",
"deselect_all": "Alli abwähle",
"details": "Details",
"direction": "Richtig",
"disable": "Deaktiviere",
"disabled": "Deaktiviert",
"disallow_edits": "Bearbeitig verbüütä",
"discord": "Discord",
"discover": "Entdeckä",
"discovered_devices": "Gfundeni Grät",
"dismiss_all_errors": "Alli Fähler ignorierä",
"dismiss_error": "Fähler ignorierä",
"display_options": "Aahzeigeoptione",
"display_order": "Aahzeigereihefolg",
"display_original_photos": "Originali Fotis Aahzeige",
@@ -785,9 +886,11 @@
"documentation": "Dokumentation",
"done": "Fertig",
"download": "Abelade",
"download_action_prompt": "Abelade vo {count} Dateie",
"download_canceled": "Download abbroche",
"download_complete": "Download vollständig",
"download_enqueue": "Download i dWarteschlange gstellt",
"download_error": "Download fählerhaft",
"download_failed": "Download fählgschlage",
"download_finished": "Download abgschlosse",
"download_include_embedded_motion_videos": "Iigbetteti Videos",
@@ -797,6 +900,9 @@
"download_paused": "Download pausiert",
"download_settings": "Download",
"download_settings_description": "Iihstelligä fürs Abeladä vo Dateie verwalte",
"download_started": "Download gstartet",
"download_sucess": "Download erfolgriich",
"download_sucess_android": "Die Datei wurde nach DCIM/Immich abeglade",
"download_waiting_to_retry": "Warte uf neue Versuech",
"downloading": "Abelade",
"downloading_asset_filename": "Datei {filename} wird abeglade",
@@ -813,7 +919,9 @@
"edit_date_and_time": "Datum und Uhrziit bearbeite",
"edit_date_and_time_action_prompt": "{count} Date und Ziite gänderet",
"edit_date_and_time_by_offset": "Datum ändere um Versatz",
"edit_date_and_time_by_offset_interval": "Neue Datumsbereich: {from} - {to}",
"edit_description": "Beschriibig bearbeite",
"edit_description_prompt": "Bitte wähl e neui Beschriibig:",
"edit_exclusion_pattern": "Usschlussmuster bearbeite",
"edit_faces": "Gsichter bearbeite",
"edit_key": "Schlüssel bearbeite",
@@ -828,6 +936,8 @@
"edit_user": "Nutzer bearbeite",
"edit_workflow": "Workflow bearbeite",
"editor": "Bearbeiter",
"editor_close_without_save_prompt": "D’Änderige werden nöd gspeichert",
"editor_close_without_save_title": "Editor schlüssä?",
"email": "E-Mail",
"email_notifications": "E-Mail Benochrichtigunge",
"empty_folder": "Dä Ordner isch leer",
@@ -843,7 +953,9 @@
"enter_your_pin_code": "PIN-Code Iigäh",
"enter_your_pin_code_subtitle": "Gib din PIN-Code ii, um uf dr gschperrte Ordner zuezgriffä",
"error": "Fähler",
"error_change_sort_album": "Änderig vo dr Aazeigeräihefolg isch gscheitert",
"error_delete_face": "Fähler bim Löschä vom Gsicht",
"error_getting_places": "Fähler bim Abruefä vo dä Ört",
"error_loading_image": "Fähler bim Lade vom Bild",
"error_loading_partners": "Fähler bim Lade vo de Partner: {error}",
"error_saving_image": "Fähler: {error}",
@@ -972,9 +1084,17 @@
"exif": "EXIF",
"exif_bottom_sheet_description": "Beschriibig dezuefüege...",
"exif_bottom_sheet_description_error": "Fähler bim d Aktualisierig vo de Beschriibig",
"exif_bottom_sheet_details": "DETAILS",
"exif_bottom_sheet_location": "STANDORT",
"exif_bottom_sheet_no_description": "Kei Beschriibig",
"exif_bottom_sheet_people": "PERSONE",
"exif_bottom_sheet_person_add_person": "Name dezuefüege",
"exit_slideshow": "Diashow beende",
"expand_all": "Alli ufklappe",
"experimental_settings_new_asset_list_subtitle": "In Arbet",
"experimental_settings_new_asset_list_title": "Experimentells Föteli-Gitter aktiviere",
"experimental_settings_subtitle": "Benutzig uf eigni Gfohr!",
"experimental_settings_title": "Experimentell",
"expire_after": "Verfällt noch",
"expired": "Verfalle",
"expires_date": "Lauft ab: {date}",
@@ -999,8 +1119,10 @@
"favorite_action_prompt": "{count} zu de Favorite hinzuegfüegt",
"favorite_or_unfavorite_photo": "Favorisierts oder nöd favorisierts Foti",
"favorites": "Favorite",
"favorites_page_no_favorites": "Kei favorisierte Inhält gfundä",
"feature_photo_updated": "Profilbild aktualisiert",
"features": "Funktione",
"features_in_development": "Feature isch in Entwicklig",
"features_setting_description": "Funkione i de App verwalte",
"file_name_or_extension": "Dateiname oder -erwiiterig",
"file_size": "Dateigrössi",
@@ -1009,6 +1131,7 @@
"filter": "Filter",
"filter_people": "Persone filterä",
"filter_places": "Ort filterä",
"find_them_fast": "Finded sie schneller mit de Suechi noch Näme",
"first": "Erste",
"fix_incorrect_match": "Fählerhafti Überiistimmig behebe",
"folder": "Ordner",
@@ -1037,6 +1160,7 @@
"group_owner": "Gruppiere noch Bsitzer",
"group_places_by": "Ort gruppiere noch...",
"group_year": "Gruppierig noch Johr",
"haptic_feedback_switch": "Haptisches Feedback aktiviere",
"haptic_feedback_title": "Haptisches Feedback",
"has_quota": "Kontingent",
"hash_asset": "Dateihash",
@@ -1055,12 +1179,29 @@
"hide_person": "Person verbergä",
"hide_text_recognition": "Texterkennung verbergä",
"hide_unnamed_people": "Unbenannti Person verbergä",
"home_page_add_to_album_conflicts": "{added} Elemente zu {album} hinzugfüegt. {failed} Elemente sind bereits vorhande.",
"home_page_add_to_album_err_local": "Es chönd no nöd lokali Element zu Albe dezuegfuegt werde, überspringe",
"home_page_add_to_album_success": "{added} Element zu {album} dezuegfuegt.",
"home_page_album_err_partner": "Inhält vo Partner chönd im Momänt nöd zu Albe dezuegfuegt werde",
"home_page_archive_err_local": "Cha lokali Element nöd archiviere, überspringe",
"home_page_archive_err_partner": "Inhält vo Partner chönd nöd archiviert werde",
"home_page_building_timeline": "Ziitachse wird erstellt",
"home_page_delete_err_partner": "Inhält vo Partner chönd nöd glöscht werde, überspringe",
"home_page_delete_remote_err_local": "Lokali Element in de Uswahl zum Entferne vo Remote-Element, Überspringe",
"home_page_favorite_err_local": "Cha lokali Element no nöd favorisiere, überspringe",
"home_page_favorite_err_partner": "Inhält vo Partner chönd nöd favorisiert werde, überspringe",
"home_page_first_time_notice": "Wenn Du d'App zum erschte Mol bruuchsch, wähl bitte es Album zum Siichere uus, demit d'Ziitachs mit Föteli und Videos cha gfüllt werde",
"home_page_locked_error_local": "Lokali Dateie chönd nöd i de gsperrti Ordner verschobe werde, überspringe",
"home_page_locked_error_partner": "Dateie vo Partner chönd nöd i de gsperrti Ordner verschobe werde, überspringe",
"home_page_share_err_local": "Lokali Inhält chönd nöd per Link teilt werde, überspringe",
"home_page_upload_err_limit": "Es chönd max. 30 Element gliichzitig ufelglade werde, überspringe",
"host": "Host",
"hour": "Stund",
"hours": "Stunde",
"id": "ID",
"idle": "Untätig",
"ignore_icloud_photos": "iCloud Fotos ignorierä",
"ignore_icloud_photos_description": "Föteli, wo i de iCloud gspiicheret sind, wärded nöd uf de immich Server ufeglade",
"image": "Föteli",
"image_alt_text_date": "{isVideo, select, true {Video} other {Bild}} ufgnoo am {date}",
"image_alt_text_date_1_person": "{isVideo, select, true {Video} other {Bild}} ufgnoo mit {person1} am {date}",
@@ -1072,6 +1213,10 @@
"image_alt_text_date_place_2_people": "{isVideo, select, true {Video} other {Bild}} ufgnoo in {city}, {country} mit {person1} und {person2} am {date}",
"image_alt_text_date_place_3_people": "{isVideo, select, true {Video} other {Bild}} ufgnoo 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}} ufgnoo in {city}, {country} mit {person1}, {person2} und {additionalCount, number} andere am {date}",
"image_saved_successfully": "Bild gspiicheret",
"image_viewer_page_state_provider_download_started": "Download gstartet",
"image_viewer_page_state_provider_download_success": "Erfolgriich abeglade",
"image_viewer_page_state_provider_share_error": "Fähler bim Teile",
"immich_logo": "Immich-Logo",
"immich_web_interface": "Immich-Web-Oberflächi",
"import_from_json": "Us JSON importierä",
@@ -1096,6 +1241,12 @@
"invalid_date_format": "Ungültigs Datumsformat",
"invite_people": "Persone ilade",
"invite_to_album": "Zum Album ilade",
"ios_debug_info_fetch_ran_at": "Abruäf lauft {dateTime}",
"ios_debug_info_last_sync_at": "Zletscht aktualisiert {dateTime}",
"ios_debug_info_no_processes_queued": "Kei Hintergründsprozäss i de Waarteschlange",
"ios_debug_info_no_sync_yet": "No kei Hindergrundsynchronisierigs-Uftrag usgfüehrt",
"ios_debug_info_processes_queued": "{count, plural, one {{count} Hindergrundsprozäss i de Waarteschlange} other {{count} Hindergrundsprozäss i de Waarteschlange}}",
"ios_debug_info_processing_ran_at": "Prozess lauft {dateTime}",
"items_count": "{count, plural, one {# Iitrag} other {# Iiträg}}",
"jobs": "Ufgobe",
"keep": "Bhalte",
@@ -1122,6 +1273,9 @@
"library": "Bibliothek",
"library_add_folder": "Ordner dezuefüege",
"library_edit_folder": "Ordner bearbeite",
"library_options": "Bibliotheksoptione",
"library_page_device_albums": "Albene uf dem Grät",
"library_page_new_album": "Neus Album",
"library_page_sort_asset_count": "Aazahl vo de Inhält",
"library_page_sort_created": "Zletscht erstellt",
"library_page_sort_last_modified": "Zletscht bearbeitet",
@@ -1161,9 +1315,11 @@
"login": "Aamälde",
"login_disabled": "Login isch deaktiviert",
"login_form_api_exception": "API Fähler. Bitte d'Serveradressa überprüäfe und noochemaa probiere.",
"login_form_back_button_text": "Zrugg",
"login_form_email_hint": "dini@email.ch",
"login_form_endpoint_hint": "http://din-server-ip:port",
"login_form_endpoint_url": "Server-URL",
"login_form_err_http": "Bitte gib http:// oder https:// aa",
"login_form_err_invalid_email": "Uungültigi E-Mail",
"login_form_err_invalid_url": "Uungültigi URL",
"login_form_err_leading_whitespace": "Läärzeiche am Aafang",
@@ -1173,6 +1329,7 @@
"login_form_failed_login": "Fähler bim Login, bitte überprüäf d'Server-URL, dini E-Mail oder's Passwoort",
"login_form_handshake_exception": "Fähler bim Verbindigsufbau mit em Server. Falls du en sälbscht-underschriibigs Zärtifikaat verwändisch, aktivier d'Uunderstützig defür i de Iistellige.",
"login_form_password_hint": "Passwort",
"login_form_save_login": "Aagmäldet bliibe",
"login_form_server_empty": "Serveradressa iigä.",
"login_form_server_error": "Es het nöd chönne Verbindig zum Server ufgnoh werde.",
"login_has_been_disabled": "D'Aamäldig isch deaktiviert worde.",
@@ -1189,6 +1346,7 @@
"main_menu": "Hauptmenü",
"maintenance_description": "Immich isch i de <link>Wartigmodus</link> versetzt worde.",
"maintenance_end": "Wartigsmodus beendä",
"maintenance_end_error": "Wartigmodus het nöd chenne beendet werde.",
"maintenance_logged_in_as": "Aktuell aagmäldet als {user}",
"maintenance_title": "Vorübergehend nöd verfügbar",
"make": "Markä",
@@ -1197,6 +1355,7 @@
"manage_media_access_settings": "Iistellige öffne",
"manage_media_access_subtitle": "Erlaub Immich, Mediedateie z verwalte und z verschiebe.",
"manage_media_access_title": "Verwaltig vo Mediedateie",
"manage_shared_links": "Freigäbeni Links verwalte",
"manage_sharing_with_partners": "Gmeinsami Nutzig mit Partner verwalte",
"manage_the_app_settings": "App-Iistellige verwalte",
"manage_your_account": "Dis Chonto verwalte",
@@ -1204,10 +1363,13 @@
"manage_your_devices": "Dini iigloggte Gerät verwalte",
"manage_your_oauth_connection": "Dini OAuth-Verchnüpfig verwalte",
"map": "Charte",
"map_assets_in_bounds": "{count, plural, =0 {Kei Fotos i däm Gebiet} one {# Foto} other {# Fotos}}",
"map_cannot_get_user_location": "Standort het nöd chenne ermittelt werde",
"map_location_dialog_yes": "Jo",
"map_location_picker_page_use_location": "Ufnahmeort verwände",
"map_location_service_disabled_content": "DOrtigsdienscht müend aktiviert si, um Inhält am aktuelle Standort aazeige z chönne. Wotsch dOrtigsdienscht jetzt aktiviere?",
"map_location_service_disabled_title": "Ortigsdienscht deaktiviert",
"map_marker_for_images": "Charte-Markierige für Bilder, wo i {city}, {country} ufgnoh worde sind",
"map_marker_with_image": "Charte-Markierig mit Bild",
"map_no_location_permission_content": "DOrtigsdienscht müend aktiviert si, um Inhält am aktuelle Standort aazeige z chönne. Wotsch dOrtigsdienscht jetzt aktiviere?",
"map_no_location_permission_title": "Kei Zuegriff uf dä Standort",
@@ -1217,11 +1379,14 @@
"map_settings_date_range_option_days": "Letschte {days} Täg",
"map_settings_date_range_option_year": "Letschtes Johr",
"map_settings_date_range_option_years": "Letschte {years} Johre",
"map_settings_dialog_title": "Charte-Iistellige",
"map_settings_include_show_archived": "Archivierti azeige",
"map_settings_include_show_partners": "Partner iibeziehä",
"map_settings_only_show_favorites": "Nur Favoritä azeige",
"map_settings_theme_settings": "Chartedesign",
"map_zoom_to_see_photos": "Ansicht chliiner mache, um Fotos z gseh",
"mark_all_as_read": "Alli als gläse markiere",
"mark_as_read": "Als gläse markiere",
"marked_all_as_read": "Alli als gläse markiert",
"matches": "Treffer",
"matching_assets": "Passendi Dateie",
@@ -1249,6 +1414,7 @@
"mobile_app_download_onboarding_note": "Herunterlade vo dr mobile App über eini vo de folgende Möglichkeitä",
"model": "Modäll",
"month": "Monet",
"monthly_title_text_date_format": "MMMM y",
"more": "Meh",
"move": "Verschiebä",
"move_off_locked_folder": "Us em gschperrte Ordner verschiebe",
@@ -1256,7 +1422,11 @@
"move_to_lock_folder_action_prompt": "{count} zum gschperrte Ordner hinzuegfüegt",
"move_to_locked_folder": "I dä gschperrte Ordner verschiebe",
"move_to_locked_folder_confirmation": "Die Fotos und Videos werde us allne Albe entfernet und chönnd nume no im gschperrte Ordner azeigt werde",
"moved_to_archive": "{count, plural, one {# Datei} other {# Dateie}} archiviert",
"moved_to_library": "{count, plural, one {# Datei} other {# Dateie}} i d'Bibliotheek verschobe",
"moved_to_trash": "I de Papiirschorb verschobe",
"multiselect_grid_edit_date_time_err_read_only": "S Daatum und d'Uhrziit vo schriibgschütztem Inehalt chan nöd veränderet werde, überspringe",
"multiselect_grid_edit_gps_err_read_only": "De Uufnaameort vo schriibgschütztem Inhält chan nöd veränderet werde, überspringe",
"mute_memories": "Erinnerige stumm schalte",
"my_albums": "Mini Albä",
"name": "Name",
@@ -1272,10 +1442,12 @@
"never": "Niemols",
"new_album": "Neus Album",
"new_api_key": "Neue API-Schlüssel",
"new_date_range": "Neue Datumsberiich",
"new_password": "Neus Passwort",
"new_person": "Neui Person",
"new_pin_code": "Neue PIN-Code",
"new_pin_code_subtitle": "Das isch din erschte Zuegriff uf de gspärrti Ordner. Erstell en PIN-Code, um sicher uf die Siite z'cho",
"new_timeline": "Neui Zytschine",
"new_update": "Neus Update",
"new_user_created": "Neue Benutzer isch erstellt worde",
"new_version_available": "NEUI VERSION VERFÜEGBAR",
@@ -1299,6 +1471,7 @@
"no_favorites_message": "Füeg Favoriite dezue, zum dini beschte Bild und Videos schnäll finde",
"no_libraries_message": "Erstell e externi Bibliotheek, zum dini Föteli und Videos aluäge",
"no_local_assets_found": "Kei lokali Datei mit dä Prüäfsumme gfunde",
"no_location_set": "Kei Standoort feschtgleit",
"no_locked_photos_message": "Föteli und Videos im gspärrte Ordner sind versteckt und wärded nöd aazeigt, wänn du dini Bibliotheek dursuächsch.",
"no_name": "Kei Name",
"no_notifications": "Kei Benochrichtigunge",
@@ -1308,6 +1481,7 @@
"no_results": "Kei Ergebniss",
"no_results_description": "Versuech's mit eme Synonüm oder eme allgemäinere Stichwort",
"no_shared_albums_message": "Erstell es Album, zum Föteli und Videos mit Persone i dim Näzwerk teile",
"no_uploads_in_progress": "Kei Upload am Laufä",
"not_allowed": "Nöd erlaubt",
"not_available": "N/A",
"not_in_any_album": "I keinem Album",
@@ -1333,8 +1507,5 @@
"on_this_device": "Uf däm Grät",
"onboarding": "Iistig",
"onboarding_locale_description": "Wähl dini bevorzugti Sprooch. Du chasch die au spöter i dine Iistellige ändere.",
"onboarding_privacy_description": "Diä folgende (optionali) Funktione hänged vo externä Diänscht ab und chönd jederziit i de Iistellige deaktiviärt wärde.",
"upload_finished": "Ufelade beändet",
"users": "Benutzer",
"waiting": "Usstehend"
"onboarding_privacy_description": "Diä folgende (optionali) Funktione hänged vo externä Diänscht ab und chönd jederziit i de Iistellige deaktiviärt wärde."
}
+10 -1
View File
@@ -2,7 +2,7 @@
"about": "વિશે",
"account": "ખાતું",
"account_settings": "ખાતાનાં સેટિંગ્સ",
"acknowledge": "જાણકારી",
"acknowledge": "જાણકારી મળી",
"action": "ક્રિયા",
"action_common_update": "સુધારો",
"action_description": "છાંટેલી વસ્તુઓ પર કરી શકાય તેવી ક્રિયાઓ",
@@ -10,18 +10,24 @@
"active": "સક્રિય",
"active_count": "સક્રિય: {count}",
"activity": "પ્રવૃત્તિ",
"activity_changed": "પ્રવૃત્તિ {enabled, select, true {સક્રિય} other {નિષ્ક્રિય}} છે",
"add": "ઉમેરો",
"add_a_description": "એક વર્ણન ઉમેરો",
"add_a_location": "એક સ્થાન ઉમેરો",
"add_a_name": "એક નામ ઉમેરો",
"add_a_title": "એક શીર્ષક ઉમેરો",
"add_action": "ક્રિયા ઉમેરો",
"add_action_description": "ક્રિયા ઉમેરવા માટે ક્લિક કરો",
"add_assets": "સંસાધનો ઉમેરો",
"add_birthday": "જન્મદિવસ ઉમેરો",
"add_endpoint": "એન્ડપોઇન્ટ ઉમેરો",
"add_exclusion_pattern": "બાકાત રાખવાની પદ્ધતિ ઉમેરો",
"add_filter": "ફિલ્ટર ઉમેરો",
"add_filter_description": "ફિલ્ટર શરત ઉમેરવા માટે ક્લિક કરો",
"add_location": "સ્થાન ઉમેરો",
"add_more_users": "વધારે યુઝર ઉમેરો",
"add_partner": "સાથી ઉમેરો",
"add_path": "પાથ ઉમેરો",
"add_photos": "ફોટો ઉમેરો",
"add_tag": "ટેગ ઉમેરો",
"add_to": "માં ઉમેરો",
@@ -29,11 +35,14 @@
"add_to_album_bottom_sheet_added": "{album} માં ઉમેરો",
"add_to_album_bottom_sheet_already_exists": "પહેલેથી જ {album} માં છે",
"add_to_album_bottom_sheet_some_local_assets": "કેટલાક લોકલ એસેટ્સને એલ્બમમાં ઉમેરવામાં આવી શક્યા નથી",
"add_to_album_toggle": "{album} માટે પસંદગી ટૉગલ કરો",
"add_to_albums": "આલ્બમો ઉમેરો",
"add_to_albums_count": "આલ્બમો માં ઉમેરો {count}",
"add_to_bottom_bar": "માં ઉમેરો",
"add_to_shared_album": "શેર કરેલ આલ્બમમાં ઉમેરો",
"add_upload_to_stack": "અપલોડને સ્ટેકમાં ઉમેરો",
"add_url": "URL ઉમેરો",
"add_workflow_step": "વર્કફ્લો પગલુ ઉમેરો",
"added_to_archive": "આર્કાઇવમાં સંગ્રહિત કરવામાં આવી છે",
"added_to_favorites": "મનપસંદ તરીકે ચિન્હીત કરેલ છે",
"added_to_favorites_count": "મનપસંદ તરીકે {count, number} ને ચિહ્નિત કરવામાં આવેલ છે",
+324 -40
View File
File diff suppressed because it is too large Load Diff
+320 -1
View File
File diff suppressed because it is too large Load Diff
+300 -19
View File
File diff suppressed because it is too large Load Diff
+329 -150
View File
File diff suppressed because it is too large Load Diff
+27
View File
@@ -15,6 +15,7 @@
"add_birthday": "Ավելացնել ծննդյան ամսաթիվ",
"add_endpoint": "Ավելացնել վերջնակետ",
"add_location": "Ավելացնել տեղ",
"add_more_users": "Ավելացնել հավելյալ օգտատերեր",
"add_partner": "Ավելացնել գործընկեր",
"add_photos": "Ավելացնել նկարներ",
"added_to_archive": "Ավելացվել է արխիվում",
@@ -24,8 +25,12 @@
"authentication_settings_disable_all": "Վստա՞հ եք, որ ցանկանում եք անջատել մուտքային մեթոդները։ Մուտքն ամբողջությամբ կանջատվի։"
},
"back": "Հետ",
"backup_all": "Բոլոր",
"backup_controller_page_background_battery_info_link": "Ցույց տուր ինչպես",
"backup_controller_page_background_battery_info_ok": "Լավ",
"backup_controller_page_background_wifi": "Միայն Wi-Fi միացումում",
"backup_controller_page_created": "Ստեղծվել է {date}֊ին",
"backup_controller_page_uploading_file_info": "Վերբեռնվում է ֆայլի տեղեկությունները",
"biometric_auth_enabled": "Կենսաչափական նույնականցումը միացված է",
"change_display_order": "Փոփոխել ցուցադրման հաջորդականությունը",
"change_location": "Փոխել տեղը",
@@ -33,9 +38,12 @@
"change_password_form_reenter_new_password": "Կրկին մուտքագրել նոր գաղտնաբառը",
"change_pin_code": "Փոփոխել ՊԻՆ կոդը",
"city": "Քաղաք",
"client_cert_dialog_msg_confirm": "Լավ",
"client_cert_title": "SSL հաճախորդի հավաստագիր",
"color": "Գույն",
"common_create_new_album": "Ստեղծել նոր ալբոմ",
"control_bottom_app_bar_create_new_album": "Ստեղծել նոր ալբոմ",
"control_bottom_app_bar_delete_from_immich": "Ջնջել Immich֊ից",
"control_bottom_app_bar_delete_from_local": "Ջնջել սարքավորումից",
"control_bottom_app_bar_edit_location": "Փոխել Տեղը",
"control_bottom_app_bar_trash_from_immich": "Տեղափոխել աղբաման",
@@ -43,8 +51,10 @@
"create_new": "ՍՏԵՂԾԵԼ ՆՈՐ",
"create_new_person": "Ստեղծել նոր անձ",
"create_shared_album_page_share_select_photos": "Ընտրե Նկարներ",
"curated_object_page_title": "Բաներ",
"current_pin_code": "Տվյալ ՊԻՆ կոդը",
"current_server_address": "Ընթացիկ սերվերի հասցե",
"daily_title_text_date": "E, MMM dd",
"dark": "Մութ",
"dark_theme": "Միացնել/անջատել մուգ տեսքը",
"day": "Օր",
@@ -53,27 +63,37 @@
"download_notfound": "Ներբեռնվածը չի հայտնաբերվել",
"edit_location": "Փոխել տեղը",
"enter_wifi_name": "Մուտքագրել Wi-Fi անունը",
"exif_bottom_sheet_person_add_person": "Ավելացնել անուն",
"experimental_settings_new_asset_list_subtitle": "Ընթացքում է",
"failed_to_authenticate": "Նույնականացումը ձախողվել է",
"folder_not_found": "Թղթապանակը չի հայտնաբերվել",
"hi_user": "Բարեւ {name} ({email})",
"ignore_icloud_photos": "Անտեսել iCloud֊ի նկարները",
"invalid_date_format": "Անվավեր ամսաթվի ձևաչափ",
"ios_debug_info_last_sync_at": "Վերջին թարմացումը {dateTime}֊ին",
"language_no_results_title": "Լեզուներ չեն գտնվել",
"library_page_device_albums": "Սարքավորման ալբոմները",
"location_picker_choose_on_map": "Ընտրել քարտեզի վրա",
"login_form_endpoint_url": "Սերվերի վերջնակետի URL",
"login_form_save_login": "Մնալ մուտքագրված",
"login_password_changed_success": "Գաղտնաբառը հաջողությամբ փոփոխվել է",
"map_assets_in_bounds": "{count} նկարներ",
"map_location_picker_page_use_location": "Օգտագործել այս տեղը",
"map_location_service_disabled_title": "Տեղորոշման ծառայություններն անջատված են",
"map_no_location_permission_title": "Տեղորոշման թույլտվությունը մերժված է",
"map_settings_date_range_option_day": "Վերջին 24 ժամում",
"map_settings_date_range_option_days": "Վերջին {days} օրում",
"map_settings_date_range_option_years": "Վերջին {years} տարում",
"mark_as_read": "Նշել կարդացած",
"new_pin_code": "Նոր ՊԻՆ կոդ",
"on_this_device": "Այս սարքավորումում",
"partner_list_user_photos": "{}-ին նկարները",
"permission_onboarding_go_to_settings": "Գնալ կարգավորումներ",
"photos": "Նկարներ",
"pin_verification": "ՊԻՆ կոդի ստուգում",
"reset_pin_code": "Վերականգնել ՊԻՆ կոդը",
"save": "Պահե",
"save_to_gallery": "Պահպանել պատկերասրահում",
"scan_library": "Նայե",
"search": "Փնտրե",
"search_city": "Որոնե քաղաք…",
@@ -86,11 +106,14 @@
"search_filter_media_type_title": "Ընտրել մեդիայի տեսակը",
"search_no_more_result": "Այլևս արդյունքներ չկան",
"search_no_people": "Ոչ մի անձ",
"search_page_motion_photos": "Շարժվող Նկարներ",
"select_photos": "Ընտրե նկարներ",
"setting_image_viewer_original_title": "Բեռնել բնագիր նկարը",
"setting_image_viewer_preview_title": "Բեռնել նախադիտման նկարը",
"setting_notifications_notify_never": "երբեք",
"setting_notifications_notify_seconds": "{count} վայրկյան",
"setting_video_viewer_original_video_title": "Ստիպել բնագիր տեսահոլովակը",
"share_add_photos": "Ավելացնել նկարներ",
"shared_album_activities_input_disable": "Մեկնաբանություններն անջատված են",
"shared_link_clipboard_copied_massage": "Պատճենահանված է",
"shared_link_edit_expire_after_option_day": "1 օր",
@@ -103,12 +126,16 @@
"shared_link_edit_expire_after_option_year": "{count} տարի",
"shared_link_manage_links": "Կառավարել կիսված հղումները",
"shared_with_me": "Ինձ հետ կիսված",
"sharing_silver_appbar_create_shared_album": "Նոր կիսված ալբոմ",
"sharing_silver_appbar_share_partner": "Կիսել գործընկերոջ հետ",
"sort_oldest": "Ամենահին նկարը",
"sort_recent": "Ամենանոր նկարը",
"theme_setting_image_viewer_quality_title": "Նկարի դիտման որակ",
"theme_setting_system_primary_color_title": "Օգտագործել համակարգի գույնը",
"timezone": "Ժամային գոտի",
"to_trash": "Աղբ",
"trash": "Աղբ",
"trash_page_title": "Աղբ ({count})",
"type": "Տեսակ",
"unknown": "Անհայտ",
"unknown_country": "Անհայտ Երկիր",
+325 -138
View File
File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More