diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json
index 9563be6125..79126fd658 100644
--- a/.devcontainer/devcontainer.json
+++ b/.devcontainer/devcontainer.json
@@ -5,8 +5,7 @@
"immich-server",
"redis",
"database",
- "immich-machine-learning",
- "init"
+ "immich-machine-learning"
],
"dockerComposeFile": [
"../docker/docker-compose.dev.yml",
diff --git a/.devcontainer/mobile/container-compose-overrides.yml b/.devcontainer/mobile/container-compose-overrides.yml
index d6cd95018f..99e41cbece 100644
--- a/.devcontainer/mobile/container-compose-overrides.yml
+++ b/.devcontainer/mobile/container-compose-overrides.yml
@@ -6,28 +6,35 @@ services:
- IMMICH_SERVER_URL=http://127.0.0.1:2283/
volumes: !override # bind mount host to /workspaces/immich
- ..:/workspaces/immich
- - cli_node_modules:/workspaces/immich/cli/node_modules
- - e2e_node_modules:/workspaces/immich/e2e/node_modules
- - open_api_node_modules:/workspaces/immich/open-api/typescript-sdk/node_modules
- - server_node_modules:/workspaces/immich/server/node_modules
- - web_node_modules:/workspaces/immich/web/node_modules
- - ${UPLOAD_LOCATION}/photos:/data
+ - ${UPLOAD_LOCATION:-upload-devcontainer-volume}${UPLOAD_LOCATION:+/photos}:/data
+ - pnpm-store:/usr/src/app/.pnpm-store
+ - server-node_modules:/usr/src/app/server/node_modules
+ - web-node_modules:/usr/src/app/web/node_modules
+ - github-node_modules:/usr/src/app/.github/node_modules
+ - cli-node_modules:/usr/src/app/cli/node_modules
+ - docs-node_modules:/usr/src/app/docs/node_modules
+ - e2e-node_modules:/usr/src/app/e2e/node_modules
+ - sdk-node_modules:/usr/src/app/open-api/typescript-sdk/node_modules
+ - app-node_modules:/usr/src/app/node_modules
+ - sveltekit:/usr/src/app/web/.svelte-kit
+ - coverage:/usr/src/app/web/coverage
- /etc/localtime:/etc/localtime:ro
-
+ immich-web:
+ env_file: !reset []
+ immich-machine-learning:
+ env_file: !reset []
database:
+ env_file: !reset []
+ environment: !override
+ POSTGRES_PASSWORD: ${DB_PASSWORD-postgres}
+ POSTGRES_USER: ${DB_USERNAME-postgres}
+ POSTGRES_DB: ${DB_DATABASE_NAME-immich}
+ POSTGRES_INITDB_ARGS: '--data-checksums'
+ POSTGRES_HOST_AUTH_METHOD: md5
volumes:
- - ${UPLOAD_LOCATION}/postgres:/var/lib/postgresql/data
-
+ - ${UPLOAD_LOCATION:-postgres-devcontainer-volume}${UPLOAD_LOCATION:+/postgres}:/var/lib/postgresql/data
+ redis:
+ env_file: !reset []
volumes:
- # Node modules for each service to avoid conflicts and ensure consistent dependencies
- cli_node_modules:
- e2e_node_modules:
- open_api_node_modules:
- server_node_modules:
- web_node_modules:
-
- # UPLOAD_LOCATION must be set to a absolute path or vol-upload
- vol-upload:
-
- # DB_DATA_LOCATION must be set to a absolute path or vol-database
- vol-database:
+ upload-devcontainer-volume:
+ postgres-devcontainer-volume:
diff --git a/.devcontainer/mobile/devcontainer.json b/.devcontainer/mobile/devcontainer.json
index 0dbcc8e9c8..140a2ecac3 100644
--- a/.devcontainer/mobile/devcontainer.json
+++ b/.devcontainer/mobile/devcontainer.json
@@ -40,7 +40,7 @@
"userEnvProbe": "loginInteractiveShell",
"remoteEnv": {
// The location where your uploaded files are stored
- "UPLOAD_LOCATION": "${localEnv:UPLOAD_LOCATION:./Library}",
+ "UPLOAD_LOCATION": "${localEnv:UPLOAD_LOCATION:./library}",
// Connection secret for postgres. You should change it to a random password
// Please use only the characters `A-Za-z0-9`, without special characters or spaces
"DB_PASSWORD": "${localEnv:DB_PASSWORD:postgres}",
diff --git a/.github/.nvmrc b/.github/.nvmrc
index e2228113dd..442c7587a9 100644
--- a/.github/.nvmrc
+++ b/.github/.nvmrc
@@ -1 +1 @@
-22.19.0
+22.20.0
diff --git a/.github/labeler.yml b/.github/labeler.yml
index c0c52f1d7e..d8923a3035 100644
--- a/.github/labeler.yml
+++ b/.github/labeler.yml
@@ -6,7 +6,6 @@ cli:
documentation:
- changed-files:
- any-glob-to-any-file:
- - docs/blob/**
- docs/docs/**
- docs/src/**
- docs/static/**
diff --git a/.github/workflows/build-mobile.yml b/.github/workflows/build-mobile.yml
index 71fa358942..454b954597 100644
--- a/.github/workflows/build-mobile.yml
+++ b/.github/workflows/build-mobile.yml
@@ -32,24 +32,18 @@ jobs:
permissions:
contents: read
outputs:
- should_run: ${{ steps.found_paths.outputs.mobile == 'true' || steps.should_force.outputs.should_force == 'true' }}
+ should_run: ${{ steps.check.outputs.should_run }}
steps:
- - name: Checkout code
- uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
- with:
- persist-credentials: false
-
- - id: found_paths
- uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
+ - name: Check what should run
+ id: check
+ uses: immich-app/devtools/actions/pre-job@5f91b52dfbb92b8d96ca411ab59c896cd59714ca # pre-job-action-v1.1.0
with:
filters: |
mobile:
- 'mobile/**'
- workflow:
- - '.github/workflows/build-mobile.yml'
- - name: Check if we should force jobs to run
- id: should_force
- run: echo "should_force=${{ steps.found_paths.outputs.workflow == 'true' || github.event_name == 'workflow_call' || github.event_name == 'workflow_dispatch' }}" >> "$GITHUB_OUTPUT"
+ force-filters: |
+ - '.github/workflows/build-mobile.yml'
+ force-events: 'workflow_call,workflow_dispatch'
build-sign-android:
name: Build and sign Android
@@ -57,7 +51,7 @@ jobs:
permissions:
contents: read
# Skip when PR from a fork
- if: ${{ !github.event.pull_request.head.repo.fork && github.actor != 'dependabot[bot]' && needs.pre-job.outputs.should_run == 'true' }}
+ if: ${{ !github.event.pull_request.head.repo.fork && github.actor != 'dependabot[bot]' && fromJSON(needs.pre-job.outputs.should_run).mobile == true }}
runs-on: mich
steps:
@@ -79,7 +73,7 @@ jobs:
- name: Restore Gradle Cache
id: cache-gradle-restore
- uses: actions/cache/restore@0400d5f644dc74513175e3cd8d07132dd4860809 # v4
+ uses: actions/cache/restore@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
with:
path: |
~/.gradle/caches
@@ -136,7 +130,7 @@ jobs:
- name: Save Gradle Cache
id: cache-gradle-save
- uses: actions/cache/save@0400d5f644dc74513175e3cd8d07132dd4860809 # v4
+ uses: actions/cache/save@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
if: github.ref == 'refs/heads/main'
with:
path: |
diff --git a/.github/workflows/cli.yml b/.github/workflows/cli.yml
index 777f1898ec..27dab9aef3 100644
--- a/.github/workflows/cli.yml
+++ b/.github/workflows/cli.yml
@@ -50,7 +50,7 @@ jobs:
- run: pnpm install --frozen-lockfile
- run: pnpm build
- - run: pnpm publish
+ - run: pnpm publish --no-git-checks
if: ${{ github.event_name == 'release' }}
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
@@ -76,7 +76,7 @@ jobs:
uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1
- name: Login to GitHub Container Registry
- uses: docker/login-action@184bdaa0721073962dff0199f1fb9940f07167d1 # v3.5.0
+ uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0
if: ${{ !github.event.pull_request.head.repo.fork }}
with:
registry: ghcr.io
diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml
index 503dd30d9a..4d4cbdf49b 100644
--- a/.github/workflows/codeql-analysis.yml
+++ b/.github/workflows/codeql-analysis.yml
@@ -50,7 +50,7 @@ jobs:
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
- uses: github/codeql-action/init@192325c86100d080feab897ff886c34abd4c83a3 # v3.30.3
+ uses: github/codeql-action/init@3599b3baa15b485a2e49ef411a7a4bb2452e7f93 # v3.30.5
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
@@ -63,7 +63,7 @@ jobs:
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
- uses: github/codeql-action/autobuild@192325c86100d080feab897ff886c34abd4c83a3 # v3.30.3
+ uses: github/codeql-action/autobuild@3599b3baa15b485a2e49ef411a7a4bb2452e7f93 # v3.30.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
@@ -76,6 +76,6 @@ jobs:
# ./location_of_script_within_repo/buildscript.sh
- name: Perform CodeQL Analysis
- uses: github/codeql-action/analyze@192325c86100d080feab897ff886c34abd4c83a3 # v3.30.3
+ uses: github/codeql-action/analyze@3599b3baa15b485a2e49ef411a7a4bb2452e7f93 # v3.30.5
with:
category: '/language:${{matrix.language}}'
diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml
index 6e2bcdb84d..7a63fcc881 100644
--- a/.github/workflows/docker.yml
+++ b/.github/workflows/docker.yml
@@ -20,15 +20,11 @@ jobs:
permissions:
contents: read
outputs:
- should_run_server: ${{ steps.found_paths.outputs.server == 'true' || steps.should_force.outputs.should_force == 'true' }}
- should_run_ml: ${{ steps.found_paths.outputs.machine-learning == 'true' || steps.should_force.outputs.should_force == 'true' }}
+ should_run: ${{ steps.check.outputs.should_run }}
steps:
- - name: Checkout code
- uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
- with:
- persist-credentials: false
- - id: found_paths
- uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
+ - name: Check what should run
+ id: check
+ uses: immich-app/devtools/actions/pre-job@5f91b52dfbb92b8d96ca411ab59c896cd59714ca # pre-job-action-v1.1.0
with:
filters: |
server:
@@ -38,14 +34,11 @@ jobs:
- 'i18n/**'
machine-learning:
- 'machine-learning/**'
- workflow:
- - '.github/workflows/docker.yml'
- - '.github/workflows/multi-runner-build.yml'
- - '.github/actions/image-build'
-
- - name: Check if we should force jobs to run
- id: should_force
- run: echo "should_force=${{ steps.found_paths.outputs.workflow == 'true' || github.event_name == 'workflow_dispatch' || github.event_name == 'release' }}" >> "$GITHUB_OUTPUT"
+ force-filters: |
+ - '.github/workflows/docker.yml'
+ - '.github/workflows/multi-runner-build.yml'
+ - '.github/actions/image-build'
+ force-events: 'workflow_dispatch,release'
retag_ml:
name: Re-Tag ML
@@ -53,14 +46,14 @@ jobs:
permissions:
contents: read
packages: write
- if: ${{ needs.pre-job.outputs.should_run_ml == 'false' && !github.event.pull_request.head.repo.fork }}
+ if: ${{ fromJSON(needs.pre-job.outputs.should_run).machine-learning == false && !github.event.pull_request.head.repo.fork }}
runs-on: ubuntu-latest
strategy:
matrix:
suffix: ['', '-cuda', '-rocm', '-openvino', '-armnn', '-rknn']
steps:
- name: Login to GitHub Container Registry
- uses: docker/login-action@184bdaa0721073962dff0199f1fb9940f07167d1 # v3.5.0
+ uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
@@ -82,14 +75,14 @@ jobs:
permissions:
contents: read
packages: write
- if: ${{ needs.pre-job.outputs.should_run_server == 'false' && !github.event.pull_request.head.repo.fork }}
+ if: ${{ fromJSON(needs.pre-job.outputs.should_run).server == false && !github.event.pull_request.head.repo.fork }}
runs-on: ubuntu-latest
strategy:
matrix:
suffix: ['']
steps:
- name: Login to GitHub Container Registry
- uses: docker/login-action@184bdaa0721073962dff0199f1fb9940f07167d1 # v3.5.0
+ uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
@@ -108,7 +101,7 @@ jobs:
machine-learning:
name: Build and Push ML
needs: pre-job
- if: ${{ needs.pre-job.outputs.should_run_ml == 'true' }}
+ if: ${{ fromJSON(needs.pre-job.outputs.should_run).machine-learning == true }}
strategy:
fail-fast: false
matrix:
@@ -153,7 +146,7 @@ jobs:
server:
name: Build and Push Server
needs: pre-job
- if: ${{ needs.pre-job.outputs.should_run_server == 'true' }}
+ if: ${{ fromJSON(needs.pre-job.outputs.should_run).server == true }}
uses: immich-app/devtools/.github/workflows/multi-runner-build.yml@129aeda75a450666ce96e8bc8126652e717917a7 # multi-runner-build-workflow-0.1.1
permissions:
contents: read
diff --git a/.github/workflows/docs-build.yml b/.github/workflows/docs-build.yml
index 2514ee8639..0879c30386 100644
--- a/.github/workflows/docs-build.yml
+++ b/.github/workflows/docs-build.yml
@@ -18,32 +18,28 @@ jobs:
permissions:
contents: read
outputs:
- should_run: ${{ steps.found_paths.outputs.docs == 'true' || steps.found_paths.outputs.open-api == 'true' || steps.should_force.outputs.should_force == 'true' }}
+ should_run: ${{ steps.check.outputs.should_run }}
steps:
- - name: Checkout code
- uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
- with:
- persist-credentials: false
- - id: found_paths
- uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
+ - name: Check what should run
+ id: check
+ uses: immich-app/devtools/actions/pre-job@5f91b52dfbb92b8d96ca411ab59c896cd59714ca # pre-job-action-v1.1.0
with:
filters: |
docs:
- 'docs/**'
- workflow:
- - '.github/workflows/docs-build.yml'
open-api:
- 'open-api/immich-openapi-specs.json'
- - name: Check if we should force jobs to run
- id: should_force
- run: echo "should_force=${{ steps.found_paths.outputs.workflow == 'true' || github.event_name == 'release' || github.ref_name == 'main' }}" >> "$GITHUB_OUTPUT"
+ force-filters: |
+ - '.github/workflows/docs-build.yml'
+ force-events: 'release'
+ force-branches: 'main'
build:
name: Docs Build
needs: pre-job
permissions:
contents: read
- if: ${{ needs.pre-job.outputs.should_run == 'true' }}
+ if: ${{ fromJSON(needs.pre-job.outputs.should_run).docs == true }}
runs-on: ubuntu-latest
defaults:
run:
diff --git a/.github/workflows/fix-format.yml b/.github/workflows/fix-format.yml
index bec34c2713..849de79a47 100644
--- a/.github/workflows/fix-format.yml
+++ b/.github/workflows/fix-format.yml
@@ -16,7 +16,7 @@ jobs:
steps:
- name: Generate a token
id: generate-token
- uses: actions/create-github-app-token@a8d616148505b5069dccd32f177bb87d7f39123b # v2.1.1
+ uses: actions/create-github-app-token@67018539274d69449ef7c02e8e71183d1719ab42 # v2.1.4
with:
app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
diff --git a/.github/workflows/merge-translations.yml b/.github/workflows/merge-translations.yml
index a0329c8f73..d494460320 100644
--- a/.github/workflows/merge-translations.yml
+++ b/.github/workflows/merge-translations.yml
@@ -10,6 +10,11 @@ on:
required: true
WEBLATE_TOKEN:
required: true
+ inputs:
+ skip:
+ description: 'Skip translations'
+ required: false
+ type: boolean
permissions: {}
@@ -25,6 +30,7 @@ jobs:
steps:
- name: Find translation PR
id: find_pr
+ if: ${{ inputs.skip != true }}
env:
GH_TOKEN: ${{ github.token }}
run: |
@@ -51,18 +57,21 @@ jobs:
- name: Generate a token
id: generate_token
- uses: actions/create-github-app-token@a8d616148505b5069dccd32f177bb87d7f39123b # v2.1.1
+ if: ${{ inputs.skip != true }}
+ uses: actions/create-github-app-token@67018539274d69449ef7c02e8e71183d1719ab42 # v2.1.4
with:
app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
- name: Lock weblate
+ if: ${{ inputs.skip != true }}
env:
WEBLATE_TOKEN: ${{ secrets.WEBLATE_TOKEN }}
run: |
curl --fail-with-body -X POST -H "Authorization: Token $WEBLATE_TOKEN" "$WEBLATE_HOST/api/components/$WEBLATE_COMPONENT/lock/" -d lock=true
- name: Commit translations
+ if: ${{ inputs.skip != true }}
env:
WEBLATE_TOKEN: ${{ secrets.WEBLATE_TOKEN }}
run: |
@@ -71,6 +80,7 @@ jobs:
- name: Merge PR
id: merge_pr
+ if: ${{ inputs.skip != true }}
env:
GH_TOKEN: ${{ steps.generate_token.outputs.token }}
PR_NUMBER: ${{ steps.find_pr.outputs.PR_NUMBER }}
@@ -83,6 +93,7 @@ jobs:
gh pr merge "$PR_NUMBER" --repo "$GITHUB_REPOSITORY" --auto --squash
- name: Wait for PR to merge
+ if: ${{ inputs.skip != true }}
env:
GH_TOKEN: ${{ steps.generate_token.outputs.token }}
PR_NUMBER: ${{ steps.find_pr.outputs.PR_NUMBER }}
@@ -106,7 +117,12 @@ jobs:
exit 1
- name: Unlock weblate
+ if: ${{ inputs.skip != true }}
env:
WEBLATE_TOKEN: ${{ secrets.WEBLATE_TOKEN }}
run: |
curl --fail-with-body -X POST -H "Authorization: Token $WEBLATE_TOKEN" "$WEBLATE_HOST/api/components/$WEBLATE_COMPONENT/lock/" -d lock=false
+
+ - name: Report success
+ run: |
+ echo "Workflow completed successfully (or was skipped)"
diff --git a/.github/workflows/prepare-release.yml b/.github/workflows/prepare-release.yml
index add68ffbd7..8b6dc0af1c 100644
--- a/.github/workflows/prepare-release.yml
+++ b/.github/workflows/prepare-release.yml
@@ -10,12 +10,17 @@ on:
type: choice
options:
- 'false'
+ - major
- minor
- patch
mobileBump:
description: 'Bump mobile build number'
required: false
type: boolean
+ skipTranslations:
+ description: 'Skip translations'
+ required: false
+ type: boolean
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}-root
@@ -26,6 +31,8 @@ permissions: {}
jobs:
merge_translations:
uses: ./.github/workflows/merge-translations.yml
+ with:
+ skip: ${{ inputs.skipTranslations }}
permissions:
pull-requests: write
secrets:
@@ -35,13 +42,14 @@ jobs:
bump_version:
runs-on: ubuntu-latest
+ needs: [merge_translations]
outputs:
ref: ${{ steps.push-tag.outputs.commit_long_sha }}
permissions: {} # No job-level permissions are needed because it uses the app-token
steps:
- name: Generate a token
id: generate-token
- uses: actions/create-github-app-token@a8d616148505b5069dccd32f177bb87d7f39123b # v2.1.1
+ uses: actions/create-github-app-token@67018539274d69449ef7c02e8e71183d1719ab42 # v2.1.4
with:
app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
@@ -51,6 +59,7 @@ jobs:
with:
token: ${{ steps.generate-token.outputs.token }}
persist-credentials: true
+ ref: main
- name: Install uv
uses: astral-sh/setup-uv@d4b2f3b6ecc6e67c4457f6d3e41ec42d3d0fcb86 # v5.4.2
@@ -102,7 +111,7 @@ jobs:
steps:
- name: Generate a token
id: generate-token
- uses: actions/create-github-app-token@a8d616148505b5069dccd32f177bb87d7f39123b # v2.1.1
+ uses: actions/create-github-app-token@67018539274d69449ef7c02e8e71183d1719ab42 # v2.1.4
with:
app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
diff --git a/.github/workflows/sdk.yml b/.github/workflows/sdk.yml
index 460e7da4a7..c541fac3c1 100644
--- a/.github/workflows/sdk.yml
+++ b/.github/workflows/sdk.yml
@@ -35,6 +35,6 @@ jobs:
- name: Build
run: pnpm build
- name: Publish
- run: pnpm publish
+ run: pnpm publish --no-git-checks
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
diff --git a/.github/workflows/static_analysis.yml b/.github/workflows/static_analysis.yml
index e11330d428..d30f95422c 100644
--- a/.github/workflows/static_analysis.yml
+++ b/.github/workflows/static_analysis.yml
@@ -17,28 +17,23 @@ jobs:
permissions:
contents: read
outputs:
- should_run: ${{ steps.found_paths.outputs.mobile == 'true' || steps.should_force.outputs.should_force == 'true' }}
+ should_run: ${{ steps.check.outputs.should_run }}
steps:
- - name: Checkout code
- uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
- with:
- persist-credentials: false
- - id: found_paths
- uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
+ - name: Check what should run
+ id: check
+ uses: immich-app/devtools/actions/pre-job@5f91b52dfbb92b8d96ca411ab59c896cd59714ca # pre-job-action-v1.1.0
with:
filters: |
mobile:
- 'mobile/**'
- workflow:
- - '.github/workflows/static_analysis.yml'
- - name: Check if we should force jobs to run
- id: should_force
- run: echo "should_force=${{ steps.found_paths.outputs.workflow == 'true' || github.event_name == 'release' }}" >> "$GITHUB_OUTPUT"
+ force-filters: |
+ - '.github/workflows/static_analysis.yml'
+ force-events: 'workflow_dispatch,release'
mobile-dart-analyze:
name: Run Dart Code Analysis
needs: pre-job
- if: ${{ needs.pre-job.outputs.should_run == 'true' }}
+ if: ${{ fromJSON(needs.pre-job.outputs.should_run).mobile == true }}
runs-on: ubuntu-latest
permissions:
contents: read
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index cd02d8341a..eaf9e2c080 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -14,23 +14,11 @@ jobs:
permissions:
contents: read
outputs:
- should_run_i18n: ${{ steps.found_paths.outputs.i18n == 'true' || steps.should_force.outputs.should_force == 'true' }}
- should_run_web: ${{ steps.found_paths.outputs.web == 'true' || steps.should_force.outputs.should_force == 'true' }}
- should_run_server: ${{ steps.found_paths.outputs.server == 'true' || steps.should_force.outputs.should_force == 'true' }}
- should_run_cli: ${{ steps.found_paths.outputs.cli == 'true' || steps.should_force.outputs.should_force == 'true' }}
- should_run_e2e: ${{ steps.found_paths.outputs.e2e == 'true' || steps.should_force.outputs.should_force == 'true' }}
- should_run_mobile: ${{ steps.found_paths.outputs.mobile == 'true' || steps.should_force.outputs.should_force == 'true' }}
- should_run_ml: ${{ steps.found_paths.outputs.machine-learning == 'true' || steps.should_force.outputs.should_force == 'true' }}
- should_run_e2e_web: ${{ steps.found_paths.outputs.e2e == 'true' || steps.found_paths.outputs.web == 'true' || steps.should_force.outputs.should_force == 'true' }}
- should_run_e2e_server_cli: ${{ steps.found_paths.outputs.e2e == 'true' || steps.found_paths.outputs.server == 'true' || steps.found_paths.outputs.cli == 'true' || steps.should_force.outputs.should_force == 'true' }}
- should_run_.github: ${{ steps.found_paths.outputs['.github'] == 'true' || steps.should_force.outputs.should_force == 'true' }} # redundant to have should_force but if someone changes the trigger then this won't have to be changed
+ should_run: ${{ steps.check.outputs.should_run }}
steps:
- - name: Checkout code
- uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
- with:
- persist-credentials: false
- - id: found_paths
- uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
+ - name: Check what should run
+ id: check
+ uses: immich-app/devtools/actions/pre-job@5f91b52dfbb92b8d96ca411ab59c896cd59714ca # pre-job-action-v1.1.0
with:
filters: |
i18n:
@@ -50,17 +38,16 @@ jobs:
- 'mobile/**'
machine-learning:
- 'machine-learning/**'
- workflow:
- - '.github/workflows/test.yml'
.github:
- '.github/**'
- - name: Check if we should force jobs to run
- id: should_force
- run: echo "should_force=${{ steps.found_paths.outputs.workflow == 'true' || github.event_name == 'workflow_dispatch' }}" >> "$GITHUB_OUTPUT"
+ force-filters: |
+ - '.github/workflows/test.yml'
+ force-events: 'workflow_dispatch'
+
server-unit-tests:
name: Test & Lint Server
needs: pre-job
- if: ${{ needs.pre-job.outputs.should_run_server == 'true' }}
+ if: ${{ fromJSON(needs.pre-job.outputs.should_run).server == true }}
runs-on: ubuntu-latest
permissions:
contents: read
@@ -97,7 +84,7 @@ jobs:
cli-unit-tests:
name: Unit Test CLI
needs: pre-job
- if: ${{ needs.pre-job.outputs.should_run_cli == 'true' }}
+ if: ${{ fromJSON(needs.pre-job.outputs.should_run).cli == true }}
runs-on: ubuntu-latest
permissions:
contents: read
@@ -137,7 +124,7 @@ jobs:
cli-unit-tests-win:
name: Unit Test CLI (Windows)
needs: pre-job
- if: ${{ needs.pre-job.outputs.should_run_cli == 'true' }}
+ if: ${{ fromJSON(needs.pre-job.outputs.should_run).cli == true }}
runs-on: windows-latest
permissions:
contents: read
@@ -172,7 +159,7 @@ jobs:
web-lint:
name: Lint Web
needs: pre-job
- if: ${{ needs.pre-job.outputs.should_run_web == 'true' }}
+ if: ${{ fromJSON(needs.pre-job.outputs.should_run).web == true }}
runs-on: mich
permissions:
contents: read
@@ -198,7 +185,7 @@ jobs:
- name: Run pnpm install
run: pnpm rebuild && pnpm install --frozen-lockfile
- name: Run linter
- run: pnpm lint:p
+ run: pnpm lint
if: ${{ !cancelled() }}
- name: Run formatter
run: pnpm format
@@ -209,7 +196,7 @@ jobs:
web-unit-tests:
name: Test Web
needs: pre-job
- if: ${{ needs.pre-job.outputs.should_run_web == 'true' }}
+ if: ${{ fromJSON(needs.pre-job.outputs.should_run).web == true }}
runs-on: ubuntu-latest
permissions:
contents: read
@@ -243,7 +230,7 @@ jobs:
i18n-tests:
name: Test i18n
needs: pre-job
- if: ${{ needs.pre-job.outputs.should_run_i18n == 'true' }}
+ if: ${{ fromJSON(needs.pre-job.outputs.should_run).i18n == true }}
runs-on: ubuntu-latest
permissions:
contents: read
@@ -281,7 +268,7 @@ jobs:
e2e-tests-lint:
name: End-to-End Lint
needs: pre-job
- if: ${{ needs.pre-job.outputs.should_run_e2e == 'true' }}
+ if: ${{ fromJSON(needs.pre-job.outputs.should_run).e2e == true }}
runs-on: ubuntu-latest
permissions:
contents: read
@@ -320,7 +307,7 @@ jobs:
server-medium-tests:
name: Medium Tests (Server)
needs: pre-job
- if: ${{ needs.pre-job.outputs.should_run_server == 'true' }}
+ if: ${{ fromJSON(needs.pre-job.outputs.should_run).server == true }}
runs-on: ubuntu-latest
permissions:
contents: read
@@ -348,7 +335,7 @@ jobs:
e2e-tests-server-cli:
name: End-to-End Tests (Server & CLI)
needs: pre-job
- if: ${{ needs.pre-job.outputs.should_run_e2e_server_cli == 'true' }}
+ if: ${{ fromJSON(needs.pre-job.outputs.should_run).e2e == true || fromJSON(needs.pre-job.outputs.should_run).server == true || fromJSON(needs.pre-job.outputs.should_run).cli == true }}
runs-on: ${{ matrix.runner }}
permissions:
contents: read
@@ -396,7 +383,7 @@ jobs:
e2e-tests-web:
name: End-to-End Tests (Web)
needs: pre-job
- if: ${{ needs.pre-job.outputs.should_run_e2e_web == 'true' }}
+ if: ${{ fromJSON(needs.pre-job.outputs.should_run).e2e == true || fromJSON(needs.pre-job.outputs.should_run).web == true }}
runs-on: ${{ matrix.runner }}
permissions:
contents: read
@@ -449,7 +436,7 @@ jobs:
mobile-unit-tests:
name: Unit Test Mobile
needs: pre-job
- if: ${{ needs.pre-job.outputs.should_run_mobile == 'true' }}
+ if: ${{ fromJSON(needs.pre-job.outputs.should_run).mobile == true }}
runs-on: ubuntu-latest
permissions:
contents: read
@@ -471,7 +458,7 @@ jobs:
ml-unit-tests:
name: Unit Test ML
needs: pre-job
- if: ${{ needs.pre-job.outputs.should_run_ml == 'true' }}
+ if: ${{ fromJSON(needs.pre-job.outputs.should_run).machine-learning == true }}
runs-on: ubuntu-latest
permissions:
contents: read
@@ -507,7 +494,7 @@ jobs:
github-files-formatting:
name: .github Files Formatting
needs: pre-job
- if: ${{ needs.pre-job.outputs['should_run_.github'] == 'true' }}
+ if: ${{ fromJSON(needs.pre-job.outputs.should_run)['.github'] == true }}
runs-on: ubuntu-latest
permissions:
contents: read
diff --git a/.github/workflows/weblate-lock.yml b/.github/workflows/weblate-lock.yml
index d765db6c1a..d7deb244f9 100644
--- a/.github/workflows/weblate-lock.yml
+++ b/.github/workflows/weblate-lock.yml
@@ -21,25 +21,24 @@ jobs:
permissions:
contents: read
outputs:
- should_run: ${{ steps.found_paths.outputs.i18n == 'true' }}
+ should_run: ${{ steps.check.outputs.should_run }}
steps:
- - name: Checkout code
- uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
- with:
- persist-credentials: false
- - id: found_paths
- uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
+ - name: Check what should run
+ id: check
+ uses: immich-app/devtools/actions/pre-job@5f91b52dfbb92b8d96ca411ab59c896cd59714ca # pre-job-action-v1.1.0
with:
filters: |
i18n:
- 'i18n/!(en)**\.json'
+ exclude-branches: 'chore/translations'
+ skip-force-logic: 'true'
enforce-lock:
name: Check Weblate Lock
needs: [pre-job]
runs-on: ubuntu-latest
permissions: {}
- if: ${{ needs.pre-job.outputs.should_run == 'true' }}
+ if: ${{ fromJSON(needs.pre-job.outputs.should_run).i18n == true }}
steps:
- name: Bot review status
env:
diff --git a/.gitignore b/.gitignore
index 25731cc2aa..3220701cc6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -18,6 +18,7 @@ mobile/libisar.dylib
mobile/openapi/test
mobile/openapi/doc
mobile/openapi/.openapi-generator/FILES
+mobile/ios/build
open-api/typescript-sdk/build
mobile/android/fastlane/report.xml
diff --git a/.vscode/launch.json b/.vscode/launch.json
index 0cc9b256ca..9ed2bb77b8 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -18,6 +18,20 @@
"name": "Immich Workers",
"remoteRoot": "/usr/src/app/server",
"localRoot": "${workspaceFolder}/server"
+ },
+ {
+ "type": "node",
+ "request": "launch",
+ "name": "Immich CLI",
+ "program": "${workspaceFolder}/cli/dist/index.js",
+ "args": ["upload", "--help"],
+ "runtimeArgs": ["--enable-source-maps"],
+ "console": "integratedTerminal",
+ "resolveSourceMapLocations": ["${workspaceFolder}/cli/dist/**/*.js.map"],
+ "sourceMaps": true,
+ "outFiles": ["${workspaceFolder}/cli/dist/**/*.js"],
+ "skipFiles": ["
-
-## OAuth Integration 🎉
-
-I want to borrow this chance to express my gratitude to [@EnricoBilla](https://github.com/EnricoBilla), who has been the trailblazer for this feature since the beginning days of Immich. His PR has sparked ideas, suggestions, and discussion among the team member on how to integrate this feature successfully into the app. Thank you so much for your work and your time.
-
-OAuth is now integrated into the system. Please follow the guide [here](https://immich.app/docs/usage/oauth) to set up your OAuth integration
-
-After setting up the correct environment variables in the `.env` file, as shown below
-
-| Key | Type | Default | Description |
-| ------------------- | ------- | -------------------- | ------------------------------------------------------------------------- |
-| OAUTH_ENABLED | boolean | false | Enable/disable OAuth2 |
-| OAUTH_ISSUER_URL | URL | (required) | Required. Self-discovery URL for client |
-| OAUTH_CLIENT_ID | string | (required) | Required. Client ID |
-| OAUTH_CLIENT_SECRET | string | (required) | Required. Client Secret |
-| OAUTH_SCOPE | string | openid email profile | Full list of scopes to send with the request (space delimited) |
-| OAUTH_AUTO_REGISTER | boolean | true | When true, will automatically register a user the first time they sign in |
-| OAUTH_BUTTON_TEXT | string | Login with OAuth | Text for the OAuth button on the web |
-
-```bash title="Authentik Example"
-OAUTH_ENABLED=true
-OAUTH_ISSUER_URL=http://10.1.15.216:9000/application/o/immich-test/
-OAUTH_CLIENT_ID=30596v8f78a4b6a97d5985c3076b6b4c4d12ddc33
-OAUTH_CLIENT_SECRET=50f1eafdec353b95b1c638db390db4ab67ef035a51212dbec2f56175e2eb272b5d572c099176e6fe116ecf47ffdd544bgdb9e2edc588307ee0339d25eeccd88
-OAUTH_BUTTON_TEXT=Login with Authentik
-```
-
-The web will have the option to sign in with OAuth.
-
-
-
-The mobile app will check if the server has OAuth enabled before displaying the OAuth
-sign-in button.
-
-
-
-## Support
-
-
-
-If you find the project helpful and it helps you in some ways, you can support the project [one time](https://github.com/sponsors/alextran1502?frequency=one-time&sponsor=alextran1502) or [monthly](https://github.com/sponsors/alextran1502) from GitHub Sponsor
-
-It is a great way to let me know that you want me to continue developing and working on this project for years to come.
-
-## Details
-
-For more details, please check out the [release note](https://github.com/immich-app/immich/releases/tag/v1.36.0_55-dev)
diff --git a/docs/blog/2023/06-24/update.mdx b/docs/blog/2023/06-24/update.mdx
deleted file mode 100644
index 464d3e44d9..0000000000
--- a/docs/blog/2023/06-24/update.mdx
+++ /dev/null
@@ -1,103 +0,0 @@
----
-title: Immich Update - June 2023
-authors: [alextran]
-tags: [update]
----
-
-Hello everybody, Alex here!
-
-I am back with another update on Immich. It has been only a month since my last update (May 18th, 2023), but it seems forever. I think the rapid releases of Immich and the amount of work make the perspective of time change in Immich’s world. We have some exciting updates that I think you will like.
-
-Before going into detail, on behalf of the core team, I would like to thank all of you for loving Immich and contributing to the project. Thank you for helping me make Immich an enjoyable alternative solution to Google Photos so that you have complete control of your data and privacy. I know we are still young and have a lot of work to do, but I am confident we will get there with help from the community. I appreciate all of you from the bottom of my heart!
-
-
-
-And now, to the exciting part, what is new in Immich’s world?
-
-- Initial support for existing gallery.
-- Memory feature.
-- Support XMP sidecar.
-- Support more raw formats.
-- Justified layout for web timeline and blurred thumbnail hash.
-- Mechanism to host machine learning on a completely different machine.
-
-## Support for existing gallery
-
-I know this is the most controversial feature when it comes to Immich’s way of ingesting photos and videos. For many users, having to upload photos and videos to Immich is simply not working. We listen, discuss, and digest this feature internally more than you imagine because it is not a simple feature to tackle while keeping the performance and the user experience at the top level, which is Immich’s primary goal.
-
-Thankfully, we have many great contributors and developers that want to make this come true. So we came up with an initial implementation of this feature in the form of a supporting read-only gallery.
-
-To be concise, Immich can now read in the gallery files, register the path into the database, and then generate necessary files and put them through Immich’s machine learning pipeline so you can use all the goodness of Immich without the need to upload them. Since this is the initial implementation, some actions/behavior are not yet supported, and we aim to build toward them in future releases, namely:
-
-- Assets are not automatically synced and must instead be manually synced with the CLI tool.
-- Only new files that are added to the gallery will be detected.
-- Deleted and moved files will not be detected.
-
-## Memory feature
-
-This is considered a fun feature that the team and I wanted to build for so long, but we had to put it off because of the refactoring of the code base. The code base is now in a good enough form to circle back and add more exciting features.
-
-This memory feature is very much similar to GPhotos' implementation of “x years since…”. We are aiming to add more categories of memories in the future, such as “Spotlight of the day” or “Day of the Week highlights”
-
-
-
-This feature is now available on the web and will be ported to the mobile app in the near future.
-
-## Support XMP Sidecar
-
-Immich can now import/upload XMP sidecars from the CLI and use the information as the metadata of assets.
-
-## Support more raw formats.
-
-With the recent updates on the dependencies of Immich, we are now extending and hardening support for multiple raw formats. So users with DSLR or mirrorless cameras can now upload their original files to Immich and have them displayed in high-quality thumbnails on the web and mobile view.
-
-## Justified layout for web timeline and blurred thumbnail hash
-
-This is an aesthetic improvement in user experience when browsing the timeline. Photos and videos are now displayed correctly with perspective orientation, making the browsing experience more pleasurable.
-
-To further improve the browsing experience, we now added a blur hash to the thumbnail, so the transition is more natural with a dreamy fade in effect, similar to how our brain goes from faded to vivid memory
-
-
-
-## Hosting machine learning container on a different machine
-
-With more capabilities Immich is building toward, machine learning will get more powerful and therefore require more resources to run effectively. However, we understand that users might not have the best server resources where they host the Immich instance. Therefore, we changed how machine learning interacts and receives the photos and videos to run through its inference pipeline.
-
-The machine learning container is now a headless system that can run on any machine. As long as your Immich instance can communicate with the system running the machine learning container, it can send the files and receive the required information to make Immich powerful in terms of searching and intelligence. This helps you to utilize a more powerful machine in your home/infrastructure to perform the CPU-intensive tasks while letting Immich only handle the I/O operations for a pleasant and smooth experience.
-
----
-
-So, those are the highlights for the team and the community after a busy month. There are a lot more changes and improvements. I encourage you to read some release notes, starting from version [v1.57.0](https://github.com/immich-app/immich/releases/tag/v1.57.0) to now.
-
-Thank you, and I am asking for your support for the project. I hope to be a full-time maintainer of Immich one day to dedicate myself to the project as my life works for the community and my family. You can find the support channels below:
-
-- Monthly donation via [GitHub Sponsors](https://github.com/sponsors/alextran1502)
-- One-time donation via [GitHub Sponsors](https://github.com/sponsors/alextran1502?frequency=one-time&sponsor=alextran1502)
-- [Liberapay](https://liberapay.com/alex.tran1502/)
-- [buymeacoffee](https://www.buymeacoffee.com/altran1502)
-- Bitcoin: 3QVAb9dCHutquVejeNXitPqZX26Yg5kxb7
-- Give a project a star - the contributors love gazing at the stars and seeing their creations shining in the sky.
-
-Join our friendly [Discord](https://discord.immich.app) to talk and discuss Immich, tech, or anything
-
-Cheer!
-
-Until next time!
-
-Alex
diff --git a/docs/blog/2023/07-29/images/web-shortcuts-panel.png b/docs/blog/2023/07-29/images/web-shortcuts-panel.png
deleted file mode 100644
index 5a16c9f289..0000000000
Binary files a/docs/blog/2023/07-29/images/web-shortcuts-panel.png and /dev/null differ
diff --git a/docs/blog/2023/07-29/update.mdx b/docs/blog/2023/07-29/update.mdx
deleted file mode 100644
index 6d50ddfdc0..0000000000
--- a/docs/blog/2023/07-29/update.mdx
+++ /dev/null
@@ -1,151 +0,0 @@
----
-title: Immich Update - July 2023
-authors: [alextran]
-tags: [update, v1.64.0-v1.71.0]
----
-
-Hello, Immich fans, another month, another milestone. We hope you are staying cool and safe in this scorching hot summer across the globe.
-
-Immich recently got some good recognition when getting to the front page of HackerNews, which helped to let more people know about the project's existence. The project will help more and more people find a solution to control the privacy of their most precious moments. And with the gain in popularity and recognition, we have gotten new users and more questions from the community than ever.
-
-I want to express my gratitude to all the contributors and the community who have been tremendously helpful to new users' questions and provided technical support.
-
-Below are the highlights of new features we added to the application over the past month, along with countless bug fixes and improvements across the board, from developer experience to resource optimization and UI/UX improvement. I hope you find these topics as exciting as I am.
-
-## Highlights
-
-- Memories feature.
-- Facial recognition improvements.
-- Improvements on multi selection behavior on the web.
-- Shortcuts for common actions on the web.
-- Support viewer for 360-panorama photos.
-
-
-
----
-
-### Memories feature
-
-We've added the memory feature on the mobile app, so you can reminisce about your past memories.
-
-
-
-### Facial recognition improvements
-
-Over the past few releases, we have added many UI improvements to the facial recognition feature to help you manage the recognized people better. Some of the highlights:
-
-#### Choose a new feature photo for a person.
-
-
-
-#### Hide and show faces.
-
-You can now select irrelevant faces to hide them. The hidden faces won’t be displayed in search results and the people section in the info panel.
-
-#### Merge faces.
-
-This is useful when you have multiple faces of the same person in your photos, and you want to merge them into one.
-
-
-
-We also added a nifty mechanism that when naming a face, similar names will prompt you a merge face option for the convenience.
-
-
-
-### Improvements on multi selection behavior on the web
-
-We have added a new multi selection behavior on the web to help you select multiple items easier. You can now select a range of photos and videos by holding the `Shift` key.
-
-
-
-### Shortcuts for common actions on the web.
-
-Some of us only navigate the world and the web with a keyboard (looking at you, Vim and Emacs users). So it would take away the sacred weapon of choice to require many clicks to perform repetitive actions. So we added quick shortcuts for the following action on the web.
-
-
-
-### Support viewer for 360-panorama photos.
-
-Photos with the EXIF property of `ProjectionType` will now have a special viewer on the web to view all the angles of the panorama.
-
-The thumbnail of the 360 degrees panoramas will have a special icon on the top right of the thumbnail
-
-
-
-
:::note
-Some jobs ([External Libraries](/docs/features/libraries) scanning, Database Dump) are configured in their own sections in System Settings.
+Some jobs ([External Libraries](/features/libraries) scanning, Database Dump) are configured in their own sections in System Settings.
:::
+
+## Job processing order
+
+The below diagram shows the job run order for newly uploaded files
+
+```mermaid
+graph TD
+ A[Asset Upload] --> B[Metadata Extraction]
+ B --> C[Storage Template Migration]
+ C --> D["Thumbnail Generation (Large, small, blurred and person)"]
+ D --> E[Smart Search]
+ D --> F[Face Detection]
+ D --> G[Video Transcoding]
+ E --> H[Duplicate Detection]
+ F --> I[Facial Recognition]
+```
diff --git a/docs/docs/administration/oauth.md b/docs/docs/administration/oauth.md
index 55a0ce9469..47f4a96c6a 100644
--- a/docs/docs/administration/oauth.md
+++ b/docs/docs/administration/oauth.md
@@ -28,7 +28,7 @@ Before enabling OAuth in Immich, a new client application needs to be configured
2. Configure Redirect URIs/Origins
The **Sign-in redirect URIs** should include:
- - `app.immich:///oauth-callback` - for logging in with OAuth from the [Mobile App](/docs/features/mobile-app.mdx)
+ - `app.immich:///oauth-callback` - for logging in with OAuth from the [Mobile App](/features/mobile-app.mdx)
- `http://DOMAIN:PORT/auth/login` - for logging in with OAuth from the Web Client
- `http://DOMAIN:PORT/user-settings` - for manually linking OAuth in the Web Client
@@ -98,7 +98,7 @@ The redirect URI for the mobile app is `app.immich:///oauth-callback`, which is
2. Whitelist the new endpoint as a valid redirect URI with your provider.
3. Specify the new endpoint as the `Mobile Redirect URI Override`, in the OAuth settings.
-With these steps in place, you should be able to use OAuth from the [Mobile App](/docs/features/mobile-app.mdx) without a custom scheme redirect URI.
+With these steps in place, you should be able to use OAuth from the [Mobile App](/features/mobile-app.mdx) without a custom scheme redirect URI.
:::info
Immich has a route (`/api/oauth/mobile-redirect`) that is already configured to forward requests to `app.immich:///oauth-callback`, and can be used for step 1.
diff --git a/docs/docs/administration/server-commands.md b/docs/docs/administration/server-commands.md
index a25673abf2..3838635c24 100644
--- a/docs/docs/administration/server-commands.md
+++ b/docs/docs/administration/server-commands.md
@@ -16,7 +16,7 @@ The `immich-server` docker image comes preinstalled with an administrative CLI (
## How to run a command
-To run a command, [connect](/docs/guides/docker-help.md#attach-to-a-container) to the `immich_server` container and then execute the command via `immich-admin
diff --git a/docs/docs/features/sharing.md b/docs/docs/features/sharing.md
index ff0a03beea..9ba7470407 100644
--- a/docs/docs/features/sharing.md
+++ b/docs/docs/features/sharing.md
@@ -24,7 +24,7 @@ After creating an album, you can access the sharing options by clicking on the s
Partner sharing allows you to share your _entire_ library with other users of your choice. They can then view your library and download the assets.
-You can read this guide to learn more about [partner sharing](/docs/features/partner-sharing).
+You can read this guide to learn more about [partner sharing](/features/partner-sharing).
## Public sharing
diff --git a/docs/docs/features/tags.md b/docs/docs/features/tags.md
index a5b6752c81..79a9696d9a 100644
--- a/docs/docs/features/tags.md
+++ b/docs/docs/features/tags.md
@@ -1,6 +1,6 @@
# Tags
-Immich supports hierarchical tags, with the ability to read existing tags from the XMP `TagsList` field and IPTC `Keywords` field. Any changes to tags made through Immich are also written back to a [sidecar](/docs/features/xmp-sidecars) file. You can re-run the metadata extraction jobs for all assets to import your existing tags.
+Immich supports hierarchical tags, with the ability to read existing tags from the XMP `TagsList` field and IPTC `Keywords` field. Any changes to tags made through Immich are also written back to a [sidecar](/features/xmp-sidecars) file. You can re-run the metadata extraction jobs for all assets to import your existing tags.
## Enable tags feature
diff --git a/docs/docs/features/user-settings.md b/docs/docs/features/user-settings.md
index a2d0308541..402105cd43 100644
--- a/docs/docs/features/user-settings.md
+++ b/docs/docs/features/user-settings.md
@@ -15,9 +15,9 @@ You can access the [user settings](https://my.immich.app/user-settings) by click
---
:::tip Reset Password
-The admin can reset a user password through the [User Management](/docs/administration/user-management.mdx) screen.
+The admin can reset a user password through the [User Management](/administration/user-management.mdx) screen.
:::
:::tip Reset Admin Password
-The admin password can be reset using a [Server Command](/docs/administration/server-commands.md)
+The admin password can be reset using a [Server Command](/administration/server-commands.md)
:::
diff --git a/docs/docs/guides/better-facial-clusters.md b/docs/docs/guides/better-facial-clusters.md
index f4409b441c..40796983a5 100644
--- a/docs/docs/guides/better-facial-clusters.md
+++ b/docs/docs/guides/better-facial-clusters.md
@@ -10,7 +10,7 @@ This guide explains how to optimize facial recognition in systems with large ima
- **Best Suited For:** Large image libraries after importing a significant number of images.
- **Warning:** This method deletes all previously assigned names.
-- **Tip:** **Always take a [backup](/docs/administration/backup-and-restore#database) before proceeding!**
+- **Tip:** **Always take a [backup](/administration/backup-and-restore#database) before proceeding!**
---
diff --git a/docs/docs/guides/custom-locations.md b/docs/docs/guides/custom-locations.md
index af8ca438e7..e0274d3bd9 100644
--- a/docs/docs/guides/custom-locations.md
+++ b/docs/docs/guides/custom-locations.md
@@ -9,7 +9,7 @@ It is important to remember to update the backup settings after following the gu
In our `.env` file, we will define the paths we want to use. Note that you don't have to define all of these: UPLOAD_LOCATION will be the base folder that files are stored in by default, with the other paths acting as overrides.
```diff title=".env"
-# You can find documentation for all the supported environment variables [here](/docs/install/environment-variables)
+# You can find documentation for all the supported environment variables [here](/install/environment-variables)
# Custom location where your uploaded, thumbnails, and transcoded video files are stored
- UPLOAD_LOCATION=./library
diff --git a/docs/docs/guides/database-queries.md b/docs/docs/guides/database-queries.md
index 1a5c2ed193..5cdcdc04c4 100644
--- a/docs/docs/guides/database-queries.md
+++ b/docs/docs/guides/database-queries.md
@@ -7,7 +7,7 @@ Keep in mind that mucking around in the database might set the Moon on fire. Avo
:::tip
Run `docker exec -it immich_postgres psql --dbname=
-
-## Welcome!
-
-Hello, I am glad you are here.
-
-My name is Alex. I am an Electrical Engineer by schooling, then turned into a Software Engineer by trade and the pure love of problem solving.
-
-We were lying in bed with our newborn, and my wife said, "We are starting to accumulate a lot of photos and videos of our baby, and I don't want to pay for **_App-Which-Must-Not-Be-Named_** anymore. You always want to build something for me, so why don't you build me an app which can do that?"
-
-That was how the idea started to grow in my head. After that, I began to find existing solutions in the self-hosting space with similar backup functionality and the performance level of the **_App-Which-Must-Not-Be-Named_**. I found that the current solutions mainly focus on the gallery-type application. However, I want a simple-to-use backup tool with a native mobile app that can view photos and videos efficiently. So I set sail on this journey as a hungry engineer on the hunt.
-
-Another motivation that pushed me to deliver my execution of the **_App-Which-Must-Not-Be-Named_** alternative or replacement is for contributing back to the open source community that I have greatly benefited from over the years.
-
-I'm proud to share this creation with you, which values privacy, memories, and the joy of looking back at those moments in an easy-to-use and friendly interface.
-
-If you like the application or it helps you in some way, please consider [supporting](./support-the-project.md) the project. It will help me to continue to develop and maintain the application.
diff --git a/docs/docs/partials/_server-backup.md b/docs/docs/partials/_server-backup.md
index b9479600aa..34e09670e9 100644
--- a/docs/docs/partials/_server-backup.md
+++ b/docs/docs/partials/_server-backup.md
@@ -1,7 +1,6 @@
Now that you have imported some pictures, you should setup server backups to preserve your memories.
-You can do so by following our [backup guide](/docs/administration/backup-and-restore.md).
+You can do so by following our [backup guide](/administration/backup-and-restore.md).
-:::danger
-Immich is still under heavy development _and_ handles very important data.
-It is essential that you set up good backups, and test them.
+:::info
+A 3-2-1 backup strategy is still crucial. The team has the responsibility to ensure that the application doesn’t cause loss of your precious memories; however, we cannot guarantee that hard drives will not fail, or an electrical event causes unexpected shutdown of your server/system, leading to data loss. Therefore, we still encourage users to follow best practices when safeguarding their data. Keep multiple copies of your most precious data: at least two local copies and one copy offsite in cold storage.
:::
diff --git a/docs/docs/partials/_storage-template.md b/docs/docs/partials/_storage-template.md
index 20e9caac43..84236e0ac1 100644
--- a/docs/docs/partials/_storage-template.md
+++ b/docs/docs/partials/_storage-template.md
@@ -1,7 +1,7 @@
-Immich allows the admin user to set the uploaded filename pattern at the directory and filename level as well as the [storage label for a user](/docs/administration/user-management/#set-storage-label-for-user).
+Immich allows the admin user to set the uploaded filename pattern at the directory and filename level as well as the [storage label for a user](/administration/user-management/#set-storage-label-for-user).
:::tip
-You can read more about the differences between storage template engine on and off [here](/docs/administration/backup-and-restore#asset-types-and-storage-locations)
+You can read more about the differences between storage template engine on and off [here](/administration/backup-and-restore#asset-types-and-storage-locations)
:::
The admin user can set the template by using the template builder in the `Administration -> Settings -> Storage Template`. Immich provides a set of variables that you can use in constructing the template, along with additional custom text. If the template produces [multiple files with the same filename, they won't be overwritten](https://github.com/immich-app/immich/discussions/3324) as a sequence number is appended to the filename.
diff --git a/docs/docusaurus.config.js b/docs/docusaurus.config.js
index d612dda253..70e0189a00 100644
--- a/docs/docusaurus.config.js
+++ b/docs/docusaurus.config.js
@@ -7,7 +7,7 @@ const prism = require('prism-react-renderer');
const config = {
title: 'Immich',
tagline: 'High performance self-hosted photo and video backup solution directly from your mobile phone',
- url: 'https://immich.app',
+ url: 'https://docs.immich.app',
baseUrl: '/',
onBrokenLinks: 'throw',
onBrokenMarkdownLinks: 'warn',
@@ -42,26 +42,19 @@ const config = {
],
presets: [
[
- 'docusaurus-preset-openapi',
- /** @type {import('docusaurus-preset-openapi').Options} */
+ 'classic',
+ /** @type {import('@docusaurus/preset-classic').Options} */
({
docs: {
showLastUpdateAuthor: true,
showLastUpdateTime: true,
+ routeBasePath: '/',
sidebarPath: require.resolve('./sidebars.js'),
// Please change this to your repo.
// Remove this to remove the "edit this page" links.
editUrl: 'https://github.com/immich-app/immich/tree/main/docs/',
},
- api: {
- path: '../open-api/immich-openapi-specs.json',
- routeBasePath: '/docs/api',
- },
- // blog: {
- // showReadingTime: true,
- // editUrl: "https://github.com/immich-app/immich/tree/main/docs/",
- // },
theme: {
customCss: require.resolve('./src/css/custom.css'),
},
@@ -72,11 +65,6 @@ const config = {
themeConfig:
/** @type {import('@docusaurus/preset-classic').ThemeConfig} */
({
- announcementBar: {
- id: 'site_announcement_immich',
- content: `⚠️ The project is under very active development. Expect bugs and changes. Do not use it as the only way to store your photos and videos!`,
- isCloseable: false,
- },
docs: {
sidebar: {
autoCollapseCategories: false,
@@ -95,17 +83,17 @@ const config = {
position: 'right',
},
{
- to: '/docs/overview/welcome',
+ to: '/overview/quick-start',
position: 'right',
label: 'Docs',
},
{
- to: '/roadmap',
+ href: 'https://immich.app/roadmap',
position: 'right',
label: 'Roadmap',
},
{
- to: '/docs/api',
+ href: 'https://api.immich.app/',
position: 'right',
label: 'API',
},
@@ -139,16 +127,16 @@ const config = {
title: 'Overview',
items: [
{
- label: 'Welcome',
- to: '/docs/overview/welcome',
+ label: 'Quick start',
+ to: '/overview/quick-start',
},
{
label: 'Installation',
- to: '/docs/install/requirements',
+ to: '/install/requirements',
},
{
label: 'Contributing',
- to: '/docs/overview/support-the-project',
+ to: '/overview/support-the-project',
},
{
label: 'Privacy Policy',
@@ -161,15 +149,15 @@ const config = {
items: [
{
label: 'Roadmap',
- to: '/roadmap',
+ href: 'https://immich.app/roadmap',
},
{
label: 'API',
- to: '/docs/api',
+ href: 'https://api.immich.app/',
},
{
label: 'Cursed Knowledge',
- to: '/cursed-knowledge',
+ href: 'https://immich.app/cursed-knowledge',
},
],
},
diff --git a/docs/package.json b/docs/package.json
index 1a1dbcf84c..d984427622 100644
--- a/docs/package.json
+++ b/docs/package.json
@@ -25,7 +25,6 @@
"@mdx-js/react": "^3.0.0",
"autoprefixer": "^10.4.17",
"docusaurus-lunr-search": "^3.3.2",
- "docusaurus-preset-openapi": "^0.7.5",
"lunr": "^2.3.9",
"postcss": "^8.4.25",
"prism-react-renderer": "^2.3.1",
@@ -58,6 +57,6 @@
"node": ">=20"
},
"volta": {
- "node": "22.19.0"
+ "node": "22.20.0"
}
}
diff --git a/docs/src/components/community-projects.tsx b/docs/src/components/community-projects.tsx
index efce831df0..6b74ae7ad8 100644
--- a/docs/src/components/community-projects.tsx
+++ b/docs/src/components/community-projects.tsx
@@ -23,11 +23,6 @@ const projects: CommunityProjectProps[] = [
description: 'A Python script to sync folders as albums.',
url: 'https://git.orenit.solutions/open/immichalbumpull',
},
- {
- title: 'Remove offline files',
- description: 'A simple way to remove orphaned offline assets from the Immich database',
- url: 'https://github.com/Thoroslives/immich_remove_offline_files',
- },
{
title: 'Immich-Tools',
description: 'Provides scripts for handling problems on the repair page.',
@@ -120,6 +115,11 @@ const projects: CommunityProjectProps[] = [
description: 'Auto-stack photos with identical filenames and differing extensions (i.e. JPG+RAW)',
url: 'https://github.com/sid3windr/immich-stack',
},
+ {
+ title: 'Immich Stack',
+ description: 'Automatically groups similar photos into stacks within the Immich photo management system.',
+ url: 'https://github.com/Majorfi/immich-stack/',
+ },
];
function CommunityProject({ title, description, url }: CommunityProjectProps): JSX.Element {
diff --git a/docs/src/components/version-switcher.tsx b/docs/src/components/version-switcher.tsx
index 5cb23891aa..739d7bd001 100644
--- a/docs/src/components/version-switcher.tsx
+++ b/docs/src/components/version-switcher.tsx
@@ -11,7 +11,7 @@ export default function VersionSwitcher(): JSX.Element {
useEffect(() => {
async function getVersions() {
try {
- let baseUrl = 'https://immich.app';
+ let baseUrl = 'https://docs.immich.app';
if (window.location.origin === 'http://localhost:3005') {
baseUrl = window.location.origin;
}
@@ -21,12 +21,13 @@ export default function VersionSwitcher(): JSX.Element {
const archiveVersions = await response.json();
const allVersions = [
- { label: 'Next', url: 'https://main.preview.immich.app' },
- { label: 'Latest', url: 'https://immich.app' },
+ { label: 'Next', url: 'https://docs.main.preview.immich.app' },
+ { label: 'Latest', url: 'https://docs.immich.app' },
...archiveVersions,
- ].map(({ label, url }) => ({
+ ].map(({ label, url, rootPath }) => ({
label,
url: new URL(url),
+ rootPath,
}));
setVersions(allVersions);
@@ -50,12 +51,18 @@ export default function VersionSwitcher(): JSX.Element {
className="version-switcher-34ab39"
label={activeLabel}
mobile={windowSize === 'mobile'}
- items={versions.map(({ label, url }) => ({
- label,
- to: new URL(location.pathname + location.search + location.hash, url).href,
- target: '_self',
- className: label === activeLabel ? 'dropdown__link--active menu__link--active' : '', // workaround because React Router `- Cursed knowledge we have learned as a result of building Immich that we wish we never knew. -
-- Self-hosted{' '} - - photo and - video management{' '} - - solution -
- -- Easily back up, organize, and manage your photos on your own server. Immich helps you - browse, search and organize your photos and videos with ease, without - sacrificing your privacy. -
-Download the mobile app
-- Download the Immich app and start backing up your photos and videos securely to your own server -
-This project is available under GNU AGPL v3 license.
-Privacy should not be a luxury
-{description}
-{label} എന്നത് ഉപയോക്താവിന്റെ സ്റ്റോറേജ് ലേബലാണ്",
+ "system_settings": "സിസ്റ്റം ക്രമീകരണങ്ങൾ",
+ "tag_cleanup_job": "ടാഗ് ക്ലീനപ്പ്",
+ "template_email_available_tags": "നിങ്ങളുടെ ടെംപ്ലേറ്റിൽ ഇനിപ്പറയുന്ന വേരിയബിളുകൾ ഉപയോഗിക്കാം: {tags}",
+ "template_email_if_empty": "ടെംപ്ലേറ്റ് ശൂന്യമാണെങ്കിൽ, ഡിഫോൾട്ട് ഇമെയിൽ ഉപയോഗിക്കും.",
+ "template_email_invite_album": "ആൽബം ക്ഷണിക്കാനുള്ള ടെംപ്ലേറ്റ്",
+ "template_email_preview": "പ്രിവ്യൂ",
+ "template_email_settings": "ഇമെയിൽ ടെംപ്ലേറ്റുകൾ",
+ "template_email_update_album": "ആൽബം അപ്ഡേറ്റ് ടെംപ്ലേറ്റ്",
+ "template_email_welcome": "സ്വാഗത ഇമെയിൽ ടെംപ്ലേറ്റ്",
+ "template_settings": "അറിയിപ്പ് ടെംപ്ലേറ്റുകൾ",
+ "template_settings_description": "അറിയിപ്പുകൾക്കായി ഇഷ്ടാനുസൃത ടെംപ്ലേറ്റുകൾ കൈകാര്യം ചെയ്യുക",
+ "theme_custom_css_settings": "കസ്റ്റം CSS",
+ "theme_custom_css_settings_description": "കാസ്കേഡിംഗ് സ്റ്റൈൽ ഷീറ്റുകൾ (CSS) Immich-ന്റെ ഡിസൈൻ ഇഷ്ടാനുസൃതമാക്കാൻ അനുവദിക്കുന്നു.",
+ "theme_settings": "തീം ക്രമീകരണങ്ങൾ",
+ "theme_settings_description": "Immich വെബ് ഇന്റർഫേസിന്റെ കസ്റ്റമൈസേഷൻ കൈകാര്യം ചെയ്യുക",
+ "thumbnail_generation_job": "തംബ്നെയിലുകൾ നിർമ്മിക്കുക",
+ "thumbnail_generation_job_description": "ഓരോ അസറ്റിനും വലുതും ചെറുതും മങ്ങിയതുമായ തംബ്നെയിലുകളും ഓരോ വ്യക്തിക്കും തംബ്നെയിലുകളും നിർമ്മിക്കുക",
+ "transcoding_acceleration_api": "ആക്സിലറേഷൻ API",
+ "transcoding_acceleration_api_description": "ട്രാൻസ്കോഡിംഗ് ത്വരിതപ്പെടുത്തുന്നതിന് നിങ്ങളുടെ ഉപകരണവുമായി സംവദിക്കുന്ന API. ഈ ക്രമീകരണം 'ബെസ്റ്റ് എഫേർട്ട്' ആണ്: പരാജയപ്പെട്ടാൽ സോഫ്റ്റ്വെയർ ട്രാൻസ്കോഡിംഗിലേക്ക് മാറും. നിങ്ങളുടെ ഹാർഡ്വെയർ അനുസരിച്ച് VP9 പ്രവർത്തിക്കുകയോ പ്രവർത്തിക്കാതിരിക്കുകയോ ചെയ്യാം.",
+ "transcoding_acceleration_nvenc": "NVENC (NVIDIA GPU ആവശ്യമാണ്)",
+ "transcoding_acceleration_qsv": "ക്വിക്ക് സിങ്ക് (7-ാം തലമുറ ഇന്റൽ സിപിയു അല്ലെങ്കിൽ അതിനുശേഷമുള്ളത് ആവശ്യമാണ്)",
+ "transcoding_acceleration_rkmpp": "RKMPP (Rockchip SOC-കളിൽ മാത്രം)",
+ "transcoding_acceleration_vaapi": "VAAPI",
+ "transcoding_accepted_audio_codecs": "അംഗീകൃത ഓഡിയോ കോഡെക്കുകൾ",
+ "transcoding_accepted_audio_codecs_description": "ട്രാൻസ്കോഡ് ചെയ്യേണ്ടാത്ത ഓഡിയോ കോഡെക്കുകൾ തിരഞ്ഞെടുക്കുക. ചില ട്രാൻസ്കോഡ് നയങ്ങൾക്ക് വേണ്ടി മാത്രം ഉപയോഗിക്കുന്നു.",
+ "transcoding_accepted_containers": "അംഗീകൃത കണ്ടെയ്നറുകൾ",
+ "transcoding_accepted_containers_description": "MP4-ലേക്ക് റീമക്സ് ചെയ്യേണ്ടാത്ത കണ്ടെയ്നർ ഫോർമാറ്റുകൾ തിരഞ്ഞെടുക്കുക. ചില ട്രാൻസ്കോഡ് നയങ്ങൾക്ക് വേണ്ടി മാത്രം ഉപയോഗിക്കുന്നു.",
+ "transcoding_accepted_video_codecs": "അംഗീകൃത വീഡിയോ കോഡെക്കുകൾ",
+ "transcoding_accepted_video_codecs_description": "ട്രാൻസ്കോഡ് ചെയ്യേണ്ടാത്ത വീഡിയോ കോഡെക്കുകൾ തിരഞ്ഞെടുക്കുക. ചില ട്രാൻസ്കോഡ് നയങ്ങൾക്ക് വേണ്ടി മാത്രം ഉപയോഗിക്കുന്നു.",
+ "transcoding_advanced_options_description": "മിക്ക ഉപയോക്താക്കളും മാറ്റം വരുത്തേണ്ടതില്ലാത്ത ഓപ്ഷനുകൾ",
+ "transcoding_audio_codec": "ഓഡിയോ കോഡെക്",
+ "transcoding_audio_codec_description": "Opus ഏറ്റവും ഉയർന്ന നിലവാരമുള്ള ഓപ്ഷനാണ്, പക്ഷേ പഴയ ഉപകരണങ്ങളുമായോ സോഫ്റ്റ്വെയറുമായോ ഇതിന് കുറഞ്ഞ അനുയോജ്യതയേ ഉള്ളൂ.",
+ "transcoding_bitrate_description": "പരമാവധി ബിറ്റ്റേറ്റിനേക്കാൾ ഉയർന്നതോ അംഗീകൃത ഫോർമാറ്റിൽ അല്ലാത്തതോ ആയ വീഡിയോകൾ",
+ "transcoding_codecs_learn_more": "ഇവിടെ ഉപയോഗിച്ചിരിക്കുന്ന പദങ്ങളെക്കുറിച്ച് കൂടുതലറിയാൻ, {label} este eticheta de stocare a utilizatorului",
"system_settings": "Setǎri de Sistem",
@@ -289,9 +297,9 @@
"template_settings_description": "Gestionați șabloanele personalizate pentru notificări",
"theme_custom_css_settings": "CSS personalizat",
"theme_custom_css_settings_description": "Foile de stil în cascadă (CSS) permit personalizarea designului Immich.",
- "theme_settings": "Setări Temă",
+ "theme_settings": "Setări temă",
"theme_settings_description": "Gestionează personalizarea interfeței web Immich",
- "thumbnail_generation_job": "Generare Miniaturi",
+ "thumbnail_generation_job": "Generare miniaturi",
"thumbnail_generation_job_description": "Generează miniaturi mari, mici și estompate pentru fiecare resursă, precum și miniaturi pentru fiecare persoană",
"transcoding_acceleration_api": "API de accelerare",
"transcoding_acceleration_api_description": "API-ul care va interacționa cu dispozitivul tău pentru a accelera transcodarea. Această setare este 'cel mai bun efort': va reveni la transcodarea software în caz de eșec. VP9 poate funcționa sau nu, în funcție de hardware-ul tău.",
@@ -317,7 +325,7 @@
"transcoding_disabled_description": "Nu transcodifică niciun videoclip; acest lucru poate afecta redarea pe anumite dispozitive",
"transcoding_encoding_options": "Opțiuni codificare",
"transcoding_encoding_options_description": "Setează codecuri , calitatea, rezoluția și alte opțiuni pentru videoclipuri codificare",
- "transcoding_hardware_acceleration": "Accelerare Hardware",
+ "transcoding_hardware_acceleration": "Accelerare hardware",
"transcoding_hardware_acceleration_description": "Experimental: transcodare mai rapidă, dar poate reduce calitatea la aceeași rată de biți",
"transcoding_hardware_decoding": "Decodare hardware",
"transcoding_hardware_decoding_setting_description": "Se aplică doar pentru NVENC, QSV și RKMPP. Activează accelerarea completă în loc de doar accelerarea codificării. S-ar putea să nu funcționeze pentru toate videoclipurile.",
@@ -337,7 +345,7 @@
"transcoding_reference_frames": "Cadre de referință",
"transcoding_reference_frames_description": "Numărul de cadre de referință atunci când se comprimă un cadru dat. Valorile mai mari îmbunătățesc eficiența compresiei, dar încetinesc codarea. 0 setează această valoare automat.",
"transcoding_required_description": "Numai videoclipuri care nu sunt într-un format acceptat",
- "transcoding_settings": "Setări de Transcodare Video",
+ "transcoding_settings": "Setări de transcodare video",
"transcoding_settings_description": "Gestionează care videoclipuri să transcodam și cum să le procesam",
"transcoding_target_resolution": "Rezoluția țintă",
"transcoding_target_resolution_description": "Rezoluțiile mai mari pot păstra mai multe detalii, dar necesită mai mult timp pentru codare, au dimensiuni mai mari ale fișierelor și pot reduce răspunsul aplicației.",
@@ -368,27 +376,25 @@
"user_delete_immediately": "Contul și resursele utilizatorului {user} vor fi puse în coadă pentru ștergere permanentă imediat.",
"user_delete_immediately_checkbox": "Pune utilizatorul și resursele în coadă pentru ștergere imediată",
"user_details": "Detalii utilizator",
- "user_management": "Gestionarea Utilizatorilor",
+ "user_management": "Gestionarea utilizatorilor",
"user_password_has_been_reset": "Parola utilizatorului a fost resetată:",
"user_password_reset_description": "Vă rugăm să furnizați utilizatorului parola temporară și să îi informați că va trebui să o schimbe la următoarea autentificare.",
"user_restore_description": "Contul utilizatorului {user} va fi restaurat.",
"user_restore_scheduled_removal": "Restaurare utilizator - ștergere programată pe {date, date, long}",
- "user_settings": "Setǎri Utilizator",
+ "user_settings": "Setǎri utilizator",
"user_settings_description": "Gestioneazǎ setǎrile utilizatorului",
"user_successfully_removed": "Utilizatorul {email} a fost eliminat cu succes.",
"version_check_enabled_description": "Activează verificarea versiunii",
"version_check_implications": "Funcția de verificare a versiunii se bazează pe comunicarea periodică cu github.com",
- "version_check_settings": "Verificare Versiune",
+ "version_check_settings": "Verificare versiune",
"version_check_settings_description": "Activeazǎ/dezactiveazǎ notificarea unei noi versiuni",
"video_conversion_job": "Transcodați videoclipuri",
"video_conversion_job_description": "Transcodați videoclipurile pentru o compatibilitate mai mare cu browserele și dispozitivele"
},
- "admin_email": "E-mail Administrator",
- "admin_password": "Parolă Administrator",
+ "admin_email": "E-mail administrator",
+ "admin_password": "Parolă administrator",
"administration": "Administrare",
"advanced": "Avansat",
- "advanced_settings_beta_timeline_subtitle": "Încearcă noua experiență în aplicație",
- "advanced_settings_beta_timeline_title": "Cronologie beta",
"advanced_settings_enable_alternate_media_filter_subtitle": "Utilizați această opțiune pentru a filtra conținutul media în timpul sincronizării pe baza unor criterii alternative. Încercați numai dacă întâmpinați probleme cu aplicația la detectarea tuturor albumelor.",
"advanced_settings_enable_alternate_media_filter_title": "[EXPERIMENTAL] Utilizați filtrul alternativ de sincronizare a albumelor de pe dispozitiv",
"advanced_settings_log_level_title": "Nivel log: {level}",
@@ -396,7 +402,7 @@
"advanced_settings_prefer_remote_title": "Preferă fotografii la distanță",
"advanced_settings_proxy_headers_subtitle": "Definește antetele proxy pe care Immich ar trebui să le trimită cu fiecare solicitare de rețea",
"advanced_settings_proxy_headers_title": "Antete Proxy",
- "advanced_settings_readonly_mode_subtitle": "Activează modul doar-citire, în care fotografiile pot fi doar vizualizate, iar acțiuni precum selectarea mai multor imagini, partajarea, redarea pe alt dispozitiv sau ștergerea sunt dezactivate. Activează/Dezactivează modul doar-citire din avatarul utilizatorului de pe ecranul principal.",
+ "advanced_settings_readonly_mode_subtitle": "Activează modul doar-citire, în care fotografiile pot fi doar vizualizate, iar acțiuni precum selectarea mai multor imagini, partajarea, redarea pe alt dispozitiv sau ștergerea sunt dezactivate. Activează/Dezactivează modul doar-citire din avatarul utilizatorului de pe ecranul principal",
"advanced_settings_readonly_mode_title": "Mod doar-citire",
"advanced_settings_self_signed_ssl_subtitle": "Omite verificare certificate SSL pentru distinația server-ului, necesar pentru certificate auto-semnate.",
"advanced_settings_self_signed_ssl_title": "Permite certificate SSL auto-semnate",
@@ -425,6 +431,7 @@
"album_remove_user_confirmation": "Ești sigur că dorești eliminarea {user}?",
"album_search_not_found": "Nu s-au găsit albume care să corespundă căutării dumneavoastră",
"album_share_no_users": "Se pare că ai partajat acest album cu toți utilizatorii sau nu ai niciun utilizator cu care să-l partajezi.",
+ "album_summary": "Rezumat album",
"album_updated": "Album actualizat",
"album_updated_setting_description": "Primiți o notificare prin e-mail când un album partajat are elemente noi",
"album_user_left": "A părăsit {album}",
@@ -461,7 +468,7 @@
"app_bar_signout_dialog_content": "Ești sigur că vrei să te deconectezi?",
"app_bar_signout_dialog_ok": "Da",
"app_bar_signout_dialog_title": "Deconectare",
- "app_settings": "Setări Aplicație",
+ "app_settings": "Setări aplicație",
"appears_in": "Apare în",
"apply_count": "Aplică ({count, number})",
"archive": "Arhivă",
@@ -482,7 +489,7 @@
"asset_description_updated": "Descrierea resursei a fost actualizată",
"asset_filename_is_offline": "Resursa {filename} este offline",
"asset_has_unassigned_faces": "Resursa are fețe neatribuite",
- "asset_hashing": "Calculare amprentă digitală",
+ "asset_hashing": "Calculare amprentă digitală…",
"asset_list_group_by_sub_title": "Grupare după",
"asset_list_layout_settings_dynamic_layout_title": "Aspect dinamic",
"asset_list_layout_settings_group_automatically": "Automat",
@@ -496,6 +503,8 @@
"asset_restored_successfully": "Date restaurate cu succes",
"asset_skipped": "Sărit",
"asset_skipped_in_trash": "În coșul de gunoi",
+ "asset_trashed": "Resursă ștearsă",
+ "asset_troubleshoot": "Depanare resursă",
"asset_uploaded": "Încărcat",
"asset_uploading": "Se incarcă…",
"asset_viewer_settings_subtitle": "Gestionați setările de vizualizare a galeriei",
@@ -522,14 +531,17 @@
"assets_trashed_count": "Mutat în coșul de gunoi {count, plural, one {# resursă} other {# resurse}}",
"assets_trashed_from_server": "{count} resursă(e) eliminate de pe serverul Immich",
"assets_were_part_of_album_count": "{count, plural, one {Resursa era} other {Resursele erau}} deja parte din album",
+ "assets_were_part_of_albums_count": "{count, plural, one {Asset was} other {Assets were}} deja parte din albume",
"authorized_devices": "Dispozitive Autorizate",
"automatic_endpoint_switching_subtitle": "Conectează-te local prin rețeaua Wi‐Fi configurată când este valabilă și prin rețele alternative în caz contrar",
"automatic_endpoint_switching_title": "Alternare URL automată",
"autoplay_slideshow": "Derulare slideshow automat",
"back": "Înapoi",
"back_close_deselect": "Înapoi, închidere sau deselectare",
+ "background_backup_running_error": "Procesul de backup în fundal este activ, nu se poate porni backup manual",
"background_location_permission": "Permisiune locație în fundal",
"background_location_permission_content": "Pentru a putea schimba rețeaua activă în fundal, Immich are nevoie de acces *permanent* la locația precisă pentru a citi numele rețelei Wi-Fi",
+ "background_options": "Opțiuni de fundal",
"backup": "Backup",
"backup_album_selection_page_albums_device": "Albume în dispozitiv ({count})",
"backup_album_selection_page_albums_tap": "Apasă odata pentru a include, de două ori pentru a exclude",
@@ -537,6 +549,7 @@
"backup_album_selection_page_select_albums": "Selectează albume",
"backup_album_selection_page_selection_info": "Informații selecție",
"backup_album_selection_page_total_assets": "Total resurse unice",
+ "backup_albums_sync": "Sincronizarea albumelor de backup",
"backup_all": "Toate",
"backup_background_service_backup_failed_message": "Eșuare backup resurse. Reîncercare…",
"backup_background_service_connection_failed_message": "Conectare la server eșuată. Reîncercare…",
@@ -576,7 +589,7 @@
"backup_controller_page_remainder": "Rămas(e)",
"backup_controller_page_remainder_sub": "Fotografii și videoclipuri din selecție rămase pentru backup",
"backup_controller_page_server_storage": "Stocare server",
- "backup_controller_page_start_backup": "Începe backup",
+ "backup_controller_page_start_backup": "Începe copia de rezervă",
"backup_controller_page_status_off": "Backup-ul automat în prim-plan este oprit",
"backup_controller_page_status_on": "Backup-ul automat în prim-plan este pornit",
"backup_controller_page_storage_format": "{used} din {total} folosit",
@@ -586,12 +599,14 @@
"backup_controller_page_turn_on": "Activează backup-ul în prim-plan",
"backup_controller_page_uploading_file_info": "Informații încărcare fișier",
"backup_err_only_album": "Nu poți șterge singurul album",
+ "backup_error_sync_failed": "Sincronizarea a eșuat. Nu se poate procesa copia de rezervă.",
"backup_info_card_assets": "resurse",
"backup_manual_cancelled": "Anulat",
"backup_manual_in_progress": "Încărcarea este deja în curs. Încearcă din nou mai târziu",
"backup_manual_success": "Succes",
"backup_manual_title": "Status încărcare",
- "backup_options_page_title": "Opțiuni Backup",
+ "backup_options": "Opțiuni copie de rezervă",
+ "backup_options_page_title": "Opțiuni copie de rezervă",
"backup_setting_subtitle": "Schimbă opțiuni pentru backup în prim-plan și în fundal",
"backup_settings_subtitle": "Gestionați setările de încărcare",
"backward": "În sens invers",
@@ -602,7 +617,7 @@
"birthdate_saved": "Data nașterii salvată cu succes",
"birthdate_set_description": "Data nașterii este utilizată pentru a calcula vârsta acestei persoane la momentul realizării fotografiei.",
"blurred_background": "Fundal neclar",
- "bugs_and_feature_requests": "Erori și Solicitări de Caracteristici",
+ "bugs_and_feature_requests": "Erori și solicitări de caracteristici",
"build": "Versiunea",
"build_image": "Versiune Imagine",
"bulk_delete_duplicates_confirmation": "Ești sigur că vrei să ștergi în masă {count, plural, one {# resursă duplicată} other {# resurse duplicate}}? Aceasta va păstra cea mai mare resursă din fiecare grup și va șterge permanent toate celelalte duplicate. Nu poți anula această acțiune!",
@@ -652,6 +667,8 @@
"change_pin_code": "Schimbă codul PIN",
"change_your_password": "Schimbă-ți parola",
"changed_visibility_successfully": "Schimbare vizibilitate cu succes",
+ "charging": "Încărcare",
+ "charging_requirement_mobile_backup": "Pentru copia de rezervă în fundal, dispozitivul trebuie să fie în curs de încărcare",
"check_corrupt_asset_backup": "Verifică copii de rezervă a resurselor corupte",
"check_corrupt_asset_backup_button": "Efectuează verificarea",
"check_corrupt_asset_backup_description": "Rulează această verificare doar prin Wi-Fi și doar după ce toate resursele au fost salvate în copia de rezerva. Procedura poate dura câteva minute.",
@@ -703,7 +720,7 @@
"control_bottom_app_bar_delete_from_immich": "Șterge din Immich",
"control_bottom_app_bar_delete_from_local": "Șterge din dispozitiv",
"control_bottom_app_bar_edit_location": "Editează locație",
- "control_bottom_app_bar_edit_time": "Editează Data și Ora",
+ "control_bottom_app_bar_edit_time": "Editează data și ora",
"control_bottom_app_bar_share_link": "Partajează linkul",
"control_bottom_app_bar_share_to": "Distribuire către",
"control_bottom_app_bar_trash_from_immich": "Mută în coș",
@@ -738,6 +755,7 @@
"create_user": "Creează utilizator",
"created": "Creat",
"created_at": "Creat",
+ "creating_linked_albums": "Crearea albumelor cu link...",
"crop": "Decupează",
"curated_object_page_title": "Obiecte",
"current_device": "Dispozitiv curent",
@@ -757,6 +775,7 @@
"date_of_birth_saved": "Data nașterii salvată cu succes",
"date_range": "Interval de date",
"day": "Zi",
+ "days": "Zile",
"deduplicate_all": "Deduplicați Toate",
"deduplication_criteria_1": "Marimea imagini în octeți",
"deduplication_criteria_2": "Numărul de date EXIF",
@@ -841,10 +860,12 @@
"edit": "Editare",
"edit_album": "Editare album",
"edit_avatar": "Editare avatar",
- "edit_birthday": "Editează ziua de naștere",
+ "edit_birthday": "Modifică ziua de naștere",
"edit_date": "Editare dată",
"edit_date_and_time": "Editare dată și oră",
"edit_date_and_time_action_prompt": "{count} data și ora modificării",
+ "edit_date_and_time_by_offset": "Schimbă data prin decalaj",
+ "edit_date_and_time_by_offset_interval": "Noul interval de date: {from} - {to}",
"edit_description": "Editează descrierea",
"edit_description_prompt": "Vă rugăm să selectați o descriere nouă:",
"edit_exclusion_pattern": "Editarea modelului de excludere",
@@ -854,7 +875,7 @@
"edit_key": "Tastă de editare",
"edit_link": "Editare link",
"edit_location": "Editare locație",
- "edit_location_action_prompt": "{count} locație(i) editată(e)",
+ "edit_location_action_prompt": "{count} locație(i) modificată(e)",
"edit_location_dialog_title": "Locație",
"edit_name": "Editare nume",
"edit_people": "Editare persoane",
@@ -884,7 +905,9 @@
"error": "Eroare",
"error_change_sort_album": "Nu s-a putut modifica ordinea de sortare a albumului",
"error_delete_face": "Eroare la ștergerea feței din activ",
+ "error_getting_places": "Eroare la obținerea locațiilor",
"error_loading_image": "Eroare la încărcarea imaginii",
+ "error_loading_partners": "Eroare la încărcarea partenerilor: {error}",
"error_saving_image": "Eroare: {error}",
"error_tag_face_bounding_box": "Eroare la etichetarea feței - nu se pot obține coordonatele casetei de delimitare",
"error_title": "Eroare - ceva nu a mers",
@@ -917,6 +940,7 @@
"failed_to_load_notifications": "Nu s-au putut încărca notificările",
"failed_to_load_people": "Eșec la încărcarea persoanelor",
"failed_to_remove_product_key": "Eșec la eliminarea cheii de produs",
+ "failed_to_reset_pin_code": "Nu s-a reușit resetarea codului PIN",
"failed_to_stack_assets": "Eșec la combinarea resurselor",
"failed_to_unstack_assets": "Eșec la desfășurarea resurselor",
"failed_to_update_notification_status": "Nu s-a putut actualiza starea notificării",
@@ -925,6 +949,7 @@
"paths_validation_failed": "{paths, plural, one {# cale} other {# căi}} nu a trecut validarea",
"profile_picture_transparent_pixels": "Pozele de profil nu pot avea pixeli transparenți. Te rugăm să mărești imaginea și/sau să o muți.",
"quota_higher_than_disk_size": "Ați stabilit o valoare a spațiului de stocare mai mare decât dimensiunea discului",
+ "something_went_wrong": "Ceva nu a mers bine",
"unable_to_add_album_users": "Imposibil de adăugat utilizatori în album",
"unable_to_add_assets_to_shared_link": "Imposibil de adăugat resurse la link-ul partajat",
"unable_to_add_comment": "Imposibil de adăugat comentariu",
@@ -1032,7 +1057,7 @@
"export_database_description": "Exportați baza de date SQLite",
"extension": "Extensie",
"external": "Extern",
- "external_libraries": "Biblioteci Externe",
+ "external_libraries": "Biblioteci externe",
"external_network": "Rețea externă",
"external_network_sheet_info": "Când nu se află în rețeaua Wi-Fi preferată, aplicația se va conecta la server prin prima dintre adresele URL de mai jos pe care o poate accesa, începând de sus în jos",
"face_unassigned": "Nealocat",
@@ -1047,6 +1072,7 @@
"favorites_page_no_favorites": "Nu au fost găsite resurse favorite",
"feature_photo_updated": "Fotografie caracteristică actualizată",
"features": "Caracteristici",
+ "features_in_development": "Funcții în dezvoltare",
"features_setting_description": "Gestionați funcțiile aplicației",
"file_name": "Nume de fișier",
"file_name_or_extension": "Numele sau extensia fișierului",
@@ -1056,21 +1082,26 @@
"filter_people": "Filtrați persoanele",
"filter_places": "Filtrează locurile",
"find_them_fast": "Găsiți-le rapid prin căutare după nume",
+ "first": "Primul",
"fix_incorrect_match": "Remediați potrivirea incorectă",
"folder": "Dosar",
"folder_not_found": "Dosar negăsit",
"folders": "Foldere",
"folders_feature_description": "Răsfoire în conținutul folderului pentru fotografiile și videoclipurile din sistemul de fișiere",
+ "forgot_pin_code_question": "Ai uitat codul PIN?",
"forward": "Redirecționare",
"gcast_enabled": "Google Cast",
"gcast_enabled_description": "Această funcție încarcă resurse externe de la Google pentru a funcționa.",
"general": "General",
+ "geolocation_instruction_location": "Apasă pe o resursă cu coordonate GPS pentru a folosi locația sa, sau selectează direct o locație de pe hartă",
"get_help": "Obțineți Ajutor",
"get_wifiname_error": "Nu s-a putut obține numele rețelei Wi-Fi. Asigurați-vă că ați acordat permisiunile necesare și că sunteți conectat la o rețea Wi-Fi",
"getting_started": "Noțiuni de Bază",
"go_back": "Întoarcere",
"go_to_folder": "Accesați folderul",
"go_to_search": "Spre căutare",
+ "gps": "GPS",
+ "gps_missing": "Fără GPS",
"grant_permission": "Acordați permisiunea",
"group_albums_by": "Grupați albume de...",
"group_country": "Grupare după țară",
@@ -1081,6 +1112,9 @@
"haptic_feedback_switch": "Activează feedback-ul haptic",
"haptic_feedback_title": "Feedback haptic",
"has_quota": "Are spațiu de stocare",
+ "hash_asset": "Hash-ul resursei",
+ "hashed_assets": "Resurse hashed",
+ "hashing": "Generare hash",
"header_settings_add_header_tip": "Adăugați antet",
"header_settings_field_validator_msg": "Valoarea nu poate fi goală",
"header_settings_header_name_input": "Numele antetului",
@@ -1107,11 +1141,12 @@
"home_page_favorite_err_partner": "Momentan nu se pot adăuga fișierele partenerului la favorite, omitere",
"home_page_first_time_notice": "Dacă este prima dată când utilizezi aplicația, te rugăm să te asiguri că alegi unul sau mai multe albume de backup, astfel încât cronologia să poată fi populată cu fotografiile și videoclipurile din aceste albume",
"home_page_locked_error_local": "Nu se pot muta resursele locale în folderul blocat, se omit",
- "home_page_locked_error_partner": "Nu se pot muta materialele partenerului în folderul blocat, se omit.",
+ "home_page_locked_error_partner": "Nu se pot muta resursele partenerului în folderul blocat, se omit.",
"home_page_share_err_local": "Nu se pot distribui fișiere locale prin link, omitere",
"home_page_upload_err_limit": "Se pot încărca maxim 30 de resurse odată, omitere",
"host": "Gazdă",
"hour": "Oră",
+ "hours": "Ore",
"id": "ID",
"idle": "Inactiv",
"ignore_icloud_photos": "Ignoră fotografiile din iCloud",
@@ -1171,10 +1206,13 @@
"language_no_results_title": "Nu au fost găsite limbi",
"language_search_hint": "Căutați limbi...",
"language_setting_description": "Selectați limba preferată",
+ "large_files": "Fișiere mari",
+ "last": "Ultimul",
"last_seen": "Văzut ultima dată",
"latest_version": "Ultima Versiune",
"latitude": "Latitudine",
"leave": "Părăsiți",
+ "leave_album": "Părăsește albumul",
"lens_model": "Model obiectiv",
"let_others_respond": "Permite altora să răspundă",
"level": "Nivel",
@@ -1188,6 +1226,7 @@
"library_page_sort_title": "Titlu album",
"licenses": "Licențe",
"light": "Lumină",
+ "like": "Îmi place",
"like_deleted": "Preferat șters",
"link_motion_video": "Link video în mișcare",
"link_to_oauth": "Link către OAuth",
@@ -1198,6 +1237,7 @@
"local": "Local",
"local_asset_cast_failed": "Nu se poate converti un element care nu este încărcat pe server",
"local_assets": "Asset-uri locale",
+ "local_media_summary": "Rezumatul fișierelor media locale",
"local_network": "Rețea locală",
"local_network_sheet_info": "Aplicația se va conecta la server prin intermediul acestei adrese URL atunci când utilizează rețeaua Wi-Fi specificată",
"location_permission": "Permisiunea de locație",
@@ -1209,6 +1249,7 @@
"location_picker_longitude_hint": "Introdu longitudinea aici",
"lock": "Blocare",
"locked_folder": "Dosar blocat",
+ "log_detail_title": "Detalii jurnal",
"log_out": "Deconectare",
"log_out_all_devices": "Deconectați-vă de la toate dispozitivele",
"logged_in_as": "Conectat ca {user}",
@@ -1239,6 +1280,7 @@
"login_password_changed_success": "Parola a fost actualizată cu succes",
"logout_all_device_confirmation": "Sigur doriți să deconectați toate dispozitivele?",
"logout_this_device_confirmation": "Sigur doriți să deconectați acest dispozitiv?",
+ "logs": "Jurnale",
"longitude": "Longitudine",
"look": "Examinare",
"loop_videos": "Buclă videoclipuri",
@@ -1246,6 +1288,7 @@
"main_branch_warning": "Utilizați o versiune de dezvoltare; vă recomandăm insistent să utilizați o versiune de lansare!",
"main_menu": "Meniu principal",
"make": "Face",
+ "manage_geolocation": "Gestionați locația",
"manage_shared_links": "Administrați link-urile distribuite",
"manage_sharing_with_partners": "Gestionați partajarea cu partenerii",
"manage_the_app_settings": "Gestionați setările aplicației",
@@ -1254,7 +1297,7 @@
"manage_your_devices": "Gestionați-vă dispozitivele conectate",
"manage_your_oauth_connection": "Gestionați-vă conexiunea OAuth",
"map": "Hartă",
- "map_assets_in_bounds": "{count, plural, one {# poză} other {# poze}}",
+ "map_assets_in_bounds": "{count, plural, =0 {Nu există fotografii în această zonă} one {# fotografie} other {# fotografii}}",
"map_cannot_get_user_location": "Nu se poate obține locația utilizatorului",
"map_location_dialog_yes": "Da",
"map_location_picker_page_use_location": "Folosește această locație",
@@ -1280,6 +1323,7 @@
"mark_as_read": "Marchează ca citit",
"marked_all_as_read": "Marcate toate ca citite",
"matches": "Corespunde",
+ "matching_assets": "Resurse similare",
"media_type": "Tip media",
"memories": "Amintiri",
"memories_all_caught_up": "Sunteți la zi",
@@ -1297,7 +1341,8 @@
"merge_people_successfully": "Persoane îmbinate cu succes",
"merged_people_count": "Imbinate {count, plural, one {# persoană} other {# persoane}}",
"minimize": "Minimizare",
- "minute": "Minute",
+ "minute": "Minut",
+ "minutes": "Minute",
"missing": "Lipsă",
"model": "Model",
"month": "Lună",
@@ -1317,6 +1362,10 @@
"my_albums": "Albumele mele",
"name": "Nume",
"name_or_nickname": "Nume sau poreclǎ",
+ "network_requirement_photos_upload": "Utilizați datele mobile pentru a face copii de rezervă ale fotografiilor",
+ "network_requirement_videos_upload": "Utilizați datele mobile pentru a face copii de rezervă ale videoclipurilor",
+ "network_requirements": "Cerințe privind rețeaua",
+ "network_requirements_updated": "Cerințele rețelei s-au modificat, resetarea cozii copiei de rezervă",
"networking_settings": "Rețele",
"networking_subtitle": "Gestionați setările endpoint-ului serverului",
"never": "Niciodată",
@@ -1326,6 +1375,7 @@
"new_person": "Persoanǎ nouǎ",
"new_pin_code": "Cod PIN nou",
"new_pin_code_subtitle": "Aceasta este prima dată când accesați folderul blocat. Creați un cod PIN pentru a accesa în siguranță această pagină",
+ "new_timeline": "Noua cronologie",
"new_user_created": "Utilizator nou creat",
"new_version_available": "VERSIUNE NOUĂ DISPONIBILĂ",
"newest_first": "Cel mai nou primul",
@@ -1339,20 +1389,25 @@
"no_assets_message": "CLICK PENTRU A ÎNCĂRCA PRIMA TA FOTOGRAFIE",
"no_assets_to_show": "Nicio resursă de afișat",
"no_cast_devices_found": "Nu s-au găsit dispozitive de difuzare",
+ "no_checksum_local": "Nu există checksum – nu se pot prelua resursele locale",
+ "no_checksum_remote": "Nu există checksum – nu se pot prelua resursele la distanță",
"no_duplicates_found": "Nu au fost găsite duplicate.",
"no_exif_info_available": "Nu există informații exif disponibile",
"no_explore_results_message": "Încarcați mai multe fotografii pentru a vă explora colecția.",
"no_favorites_message": "Adăugați favorite pentru a găsi rapid cele mai bune fotografii și videoclipuri",
"no_libraries_message": "Creați o bibliotecă externă pentru a vă vizualiza fotografiile și videoclipurile",
+ "no_local_assets_found": "Nicio resursă locală găsită cu acest checksum",
"no_locked_photos_message": "Fotografiile și videoclipurile din folderul blocat sunt ascunse și nu vor apărea atunci când răsfoiți sau căutați în bibliotecă.",
"no_name": "Fără Nume",
"no_notifications": "Nicio notificare",
"no_people_found": "Nu au fost găsite persoane potrivite căutării",
"no_places": "Nu există locuri",
+ "no_remote_assets_found": "Nicio resursă de la distanță găsită cu acest checksum",
"no_results": "Fără rezultate",
"no_results_description": "Încercați un sinonim sau un cuvânt cheie mai general",
"no_shared_albums_message": "Creați un album pentru a partaja fotografii și videoclipuri cu persoanele din rețeaua dvs",
"no_uploads_in_progress": "Nicio încărcare în curs",
+ "not_available": "N/A",
"not_in_any_album": "Nu există în niciun album",
"not_selected": "Neselectat",
"note_apply_storage_label_to_previously_uploaded assets": "Notă: Pentru a aplica eticheta de stocare la resursele încărcate anterior, rulați",
@@ -1368,6 +1423,7 @@
"oauth": "OAuth",
"official_immich_resources": "Resurse Oficiale Immich",
"offline": "Offline",
+ "offset": "Decalaj",
"ok": "Bine",
"oldest_first": "Cel mai vechi mai întâi",
"on_this_device": "Pe acest dispozitiv",
@@ -1386,6 +1442,8 @@
"open_the_search_filters": "Deschideți filtrele de căutare",
"options": "Opțiuni",
"or": "sau",
+ "organize_into_albums": "Organizați în albume",
+ "organize_into_albums_description": "Pune fotografiile existente în albume folosind setările curente de sincronizare",
"organize_your_library": "Organizează-ți biblioteca",
"original": "original",
"other": "Alte",
@@ -1445,6 +1503,9 @@
"permission_onboarding_permission_limited": "Permisiune limitată. Pentru a permite Immich să facă copii de siguranță și să gestioneze întreaga colecție de galerii, acordă permisiuni pentru fotografii și videoclipuri în Setări.",
"permission_onboarding_request": "Immich necesită permisiunea de a vizualiza fotografiile și videoclipurile tale.",
"person": "Persoanǎ",
+ "person_age_months": "{months, plural, one {# month} other {# months}} vechime",
+ "person_age_year_months": "1 year, {months, plural, one {# month} other {# months}} vechime",
+ "person_age_years": "{years, plural, other {# years}} vechime",
"person_birthdate": "Născut pe {date}",
"person_hidden": "{name}{hidden, select, true { (ascuns)} other {}}",
"photo_shared_all_users": "Se pare că ți-ai partajat fotografiile tuturor utilizatorilor sau că nu ai niciun utilizator căruia să le distribui.",
@@ -1468,6 +1529,7 @@
"port": "Port",
"preferences_settings_subtitle": "Gestionați preferințele aplicației",
"preferences_settings_title": "Preferințe",
+ "preparing": "Se prepară",
"preset": "Presetat",
"preview": "Previzualizare",
"previous": "Anterior",
@@ -1484,6 +1546,7 @@
"profile_drawer_client_out_of_date_minor": "Aplicația nu folosește ultima versiune. Te rugăm să actualizezi la ultima versiune minoră.",
"profile_drawer_client_server_up_to_date": "Aplicația client și server-ul sunt actualizate",
"profile_drawer_github": "GitHub",
+ "profile_drawer_readonly_mode": "Mod doar citire activat. Ține apăsat pe pictograma avatarului utilizatorului pentru a ieși.",
"profile_drawer_server_out_of_date_major": "Server-ul nu folosește ultima versiune. Te rugăm să actualizezi la ultima versiune majoră.",
"profile_drawer_server_out_of_date_minor": "Server-ul nu folosește ultima versiune. Te rugăm să actulizezi la ultima versiune minoră.",
"profile_image_of_user": "Imagine de profil a lui {user}",
@@ -1522,6 +1585,7 @@
"purchase_server_description_2": "Statutul de suporter",
"purchase_server_title": "Server",
"purchase_settings_server_activated": "Cheia de produs a serverului este gestionată de administrator",
+ "query_asset_id": "Interoghează ID-ul resursei",
"queue_status": "Se pun în coadă {count}/{total}",
"rating": "Evaluare cu stele",
"rating_clear": "Anulați evaluarea",
@@ -1529,6 +1593,9 @@
"rating_description": "Afișați evaluarea EXIF în panoul de informații",
"reaction_options": "Opțiuni de reacție",
"read_changelog": "Citiți Jurnalul de Modificări",
+ "readonly_mode_disabled": "Modul doar citire dezactivat",
+ "readonly_mode_enabled": "Modul doar citire activat",
+ "ready_for_upload": "Pregătit pentru încărcare",
"reassign": "Reatribuiți",
"reassigned_assets_to_existing_person": "Re-alocat {count, plural, one {# resursă} other {# resurse}} to {name, select, null {unei persoane existente} other {{name}}}",
"reassigned_assets_to_new_person": "Re-alocat {count, plural, one {# resursă} other {# resurse}} unei noi persoane",
@@ -1553,6 +1620,7 @@
"regenerating_thumbnails": "Se regenerează miniaturile",
"remote": "De la distanță",
"remote_assets": "Elemente la distanță",
+ "remote_media_summary": "Rezumat media de la distanță",
"remove": "Eliminați",
"remove_assets_album_confirmation": "Sigur doriți să eliminați {count, plural, one {# resursă} other {# resurse}} din album?",
"remove_assets_shared_link_confirmation": "Sigur doriți să eliminați {count, plural, one {# resursă} other {# resurse}} din acest link comun?",
@@ -1590,6 +1658,9 @@
"reset_password": "Resetare parolă",
"reset_people_visibility": "Resetați vizibilitatea persoanelor",
"reset_pin_code": "Resetare cod PIN",
+ "reset_pin_code_description": "Dacă ți-ai uitat codul PIN, poți contacta administratorul serverului pentru a-l reseta",
+ "reset_pin_code_success": "Codul PIN a fost resetat cu succes",
+ "reset_pin_code_with_password": "Puteți reseta oricând codul PIN cu ajutorul parolei",
"reset_sqlite": "Resetare bază de date SQLite",
"reset_sqlite_confirmation": "Sigur doriți să resetați baza de date SQLite? Va trebui să vă deconectați și să vă conectați din nou pentru a resincroniza datele",
"reset_sqlite_success": "Resetarea cu succes a bazei de date SQLite",
@@ -1602,8 +1673,10 @@
"restore_user": "Restabiliți utilizatorul",
"restored_asset": "Resursă restaurată",
"resume": "Reluare",
+ "resume_paused_jobs": "Reluați {count, plural, one {# paused job} other {# paused jobs}}",
"retry_upload": "Reîncercați încărcarea",
"review_duplicates": "Examinați duplicatele",
+ "review_large_files": "Revizuirea fișierelor mari",
"role": "Rol",
"role_editor": "Editor",
"role_viewer": "Vizualizator",
@@ -1615,7 +1688,7 @@
"saved_settings": "Setări salvate",
"say_something": "Spuneți ceva",
"scaffold_body_error_occurred": "A apărut o eroare",
- "scan_all_libraries": "Scanați Toate Bibliotecile",
+ "scan_all_libraries": "Scanați toate bibliotecile",
"scan_library": "Scanare",
"scan_settings": "Setări Scanare",
"scanning_for_album": "Se scanează după album...",
@@ -1694,6 +1767,7 @@
"select_user_for_sharing_page_err_album": "Creare album eșuată",
"selected": "Selectat",
"selected_count": "{count, plural, other {# selectat}}",
+ "selected_gps_coordinates": "Coordonate GPS selectate",
"send_message": "Trimiteți mesaj",
"send_welcome_email": "Trimiteți email de bun venit",
"server_endpoint": "Endpoint server",
@@ -1702,7 +1776,7 @@
"server_offline": "Serverul este offline",
"server_online": "Server online",
"server_privacy": "Confidențialitatea serverului",
- "server_stats": "Statistici Server",
+ "server_stats": "Statistici server",
"server_version": "Versiune Server",
"set": "Setați",
"set_as_album_cover": "Setați ca și copertă a albumului",
@@ -1761,6 +1835,7 @@
"shared_link_clipboard_copied_massage": "Copiat în clipboard",
"shared_link_clipboard_text": "Link: {link}\nParolă: {password}",
"shared_link_create_error": "Eroare în timpul creării linkului de distribuire",
+ "shared_link_custom_url_description": "Accesează acest link partajat cu un URL personalizat",
"shared_link_edit_description_hint": "Introdu descrierea distribuirii",
"shared_link_edit_expire_after_option_day": "1 zi",
"shared_link_edit_expire_after_option_days": "{count} zile",
@@ -1786,6 +1861,7 @@
"shared_link_info_chip_metadata": "EXIF",
"shared_link_manage_links": "Administrează link-urile distribuite",
"shared_link_options": "Opțiuni de link partajat",
+ "shared_link_password_description": "Solicită o parolă pentru a accesa acest link partajat",
"shared_links": "Link-uri distribuite",
"shared_links_description": "Partajare imagini și clipuri printr-un link",
"shared_photos_and_videos_count": "{assetCount, plural, other {# fotografii și videoclipuri partajate.}}",
@@ -1820,6 +1896,7 @@
"show_slideshow_transition": "Afișați tranziția de prezentare",
"show_supporter_badge": "Insigna suporterului",
"show_supporter_badge_description": "Arată o insignă de suporter",
+ "show_text_search_menu": "Afișează meniul de căutare text",
"shuffle": "Amestecați",
"sidebar": "Bara laterală",
"sidebar_display_description": "Afișați un link către vizualizare în bara laterală",
@@ -1835,6 +1912,7 @@
"sort_created": "Data creării",
"sort_items": "Numărul de articole",
"sort_modified": "Data modificării",
+ "sort_newest": "Cea mai nouă fotografie",
"sort_oldest": "Cea mai veche fotografie",
"sort_people_by_similarity": "Sortează oameni după asemanare",
"sort_recent": "Cea mai recentă fotografie",
@@ -1849,6 +1927,7 @@
"stacktrace": "Urmă stivă",
"start": "Început",
"start_date": "Data de începere",
+ "start_date_before_end_date": "Data de început trebuie să fie înainte de data de sfârșit",
"state": "Situaţie",
"status": "Stare",
"stop_casting": "Opriți difuzarea",
@@ -1873,6 +1952,8 @@
"sync_albums_manual_subtitle": "Sincronizează toate videoclipurile și fotografiile încărcate cu albumele de rezervă selectate",
"sync_local": "Sincronizare locală",
"sync_remote": "Sincronizare la distanță",
+ "sync_status": "Status-ul sincronizării",
+ "sync_status_subtitle": "Vizualizează și gestionează sistemul de sincronizare",
"sync_upload_album_setting_subtitle": "Creează și încarcă fotografiile și videoclipurile tale în albumele selectate de pe Immich",
"tag": "Etichetă",
"tag_assets": "Eticheta resurselor",
@@ -1910,7 +1991,9 @@
"to_change_password": "Schimbaţi parola",
"to_favorite": "Favorit",
"to_login": "Conectare",
+ "to_multi_select": "pentru selecție multiplă",
"to_parent": "Du-te la părinte",
+ "to_select": "a selecta",
"to_trash": "Coș de gunoi",
"toggle_settings": "Activați setările",
"total": "Total",
@@ -1930,6 +2013,7 @@
"trash_page_select_assets_btn": "Selectează resurse",
"trash_page_title": "Coș ({count})",
"trashed_items_will_be_permanently_deleted_after": "Elementele din coșul de gunoi vor fi șterse definitiv după {days, plural, one {# zi} other {# zile}}.",
+ "troubleshoot": "Depanați",
"type": "Tip",
"unable_to_change_pin_code": "Nu se poate schimba codul PIN",
"unable_to_setup_pin_code": "Nu se poate configura codul PIN",
@@ -1956,10 +2040,11 @@
"unselect_all_duplicates": "Deselectați toate duplicatele",
"unselect_all_in": "Deselectați toate din {group}",
"unstack": "Dezasamblați",
- "unstack_action_prompt": "{count} unstacked",
+ "unstack_action_prompt": "{count} neîmpachetate",
"unstacked_assets_count": "Nestivuit {count, plural, one {# resursă} other {# resurse}}",
"untagged": "Neetichetat",
"up_next": "Mai departe",
+ "update_location_action_prompt": "Actualizează locația pentru {count} resurse selectate cu:",
"updated_at": "Actualizat",
"updated_password": "Parolă actualizată",
"upload": "Încărcați",
@@ -2026,13 +2111,14 @@
"view_next_asset": "Vizualizați următoarea resursă",
"view_previous_asset": "Vizualizați resursa anterioară",
"view_qr_code": "Vezi cod QR",
+ "view_similar_photos": "Vizualizați poze similare",
"view_stack": "Vizualizați Stiva",
"view_user": "Vizualizare utilizator",
"viewer_remove_from_stack": "Șterge din grup",
"viewer_stack_use_as_main_asset": "Folosește ca resursă principală",
"viewer_unstack": "Anulează grup",
"visibility_changed": "Vizibilitatea schimbată pentru {count, plural, one {# persoană} other {# persoane}}",
- "waiting": "Așteptați",
+ "waiting": "În așteptare",
"warning": "Avertisment",
"week": "Sǎptǎmânǎ",
"welcome": "Bun venit",
@@ -2044,5 +2130,6 @@
"yes": "Da",
"you_dont_have_any_shared_links": "Nu aveți linkuri partajate",
"your_wifi_name": "Numele rețelei tale WiFi",
- "zoom_image": "Măriți Imaginea"
+ "zoom_image": "Măriți Imaginea",
+ "zoom_to_bounds": "Mărește la margini"
}
diff --git a/i18n/ru.json b/i18n/ru.json
index 287f0288bd..51d80614d3 100644
--- a/i18n/ru.json
+++ b/i18n/ru.json
@@ -7,7 +7,7 @@
"action_common_update": "Обновить",
"actions": "Действия",
"active": "Выполняется",
- "activity": "Активность",
+ "activity": "Действия",
"activity_changed": "Активность {enabled, select, true {включена} other {отключена}}",
"add": "Добавить",
"add_a_description": "Добавить описание",
@@ -26,8 +26,9 @@
"add_tag": "Добавить тег",
"add_to": "Добавить в…",
"add_to_album": "Добавить в альбом",
- "add_to_album_bottom_sheet_added": "Добавлено в {album}",
- "add_to_album_bottom_sheet_already_exists": "Уже в {album}",
+ "add_to_album_bottom_sheet_added": "Добавлено в альбом {album}",
+ "add_to_album_bottom_sheet_already_exists": "Уже в альбоме {album}",
+ "add_to_album_bottom_sheet_some_local_assets": "Некоторые объекты не добавлены в альбом, поскольку еще не загружены на сервер",
"add_to_album_toggle": "Переключить выделение для альбома {album}",
"add_to_albums": "Добавить в альбомы",
"add_to_albums_count": "Добавить в альбомы ({count})",
@@ -39,7 +40,7 @@
"admin": {
"add_exclusion_pattern_description": "Добавьте шаблоны исключений. Поддерживаются символы подстановки *, ** и ?. Чтобы игнорировать все файлы в любом каталоге с именем \"Raw\", укажите \"**/Raw/**\". Чтобы игнорировать все файлы, заканчивающиеся на \".tif\", используйте \"**/*.tif\". Чтобы игнорировать путь целиком, укажите \"/path/to/ignore/**\".",
"admin_user": "Администратор",
- "asset_offline_description": "Этот файл внешней библиотеки не был найден на диске и был перемещён в корзину. Если файл был перемещён внутри библиотеки, проверьте временную шкалу, чтобы найти новый соответствующий ресурс. Чтобы восстановить файл, убедитесь, что путь ниже доступен для Immich и выполните сканирование библиотеки.",
+ "asset_offline_description": "Этот объект из внешней библиотеки не был обнаружен на диске и поэтому перемещён в корзину. Если файл объекта был перемещён внутри библиотеки, проверьте временную шкалу, чтобы найти новый соответствующий объект. Чтобы восстановить файл, убедитесь, что следующий путь доступен для Immich, и выполните сканирование библиотеки.",
"authentication_settings": "Настройки аутентификации",
"authentication_settings_description": "Управление паролями, OAuth и другими настройками аутентификации",
"authentication_settings_disable_all": "Вы уверены, что хотите отключить все методы входа? Вход будет полностью отключен.",
@@ -65,9 +66,9 @@
"confirm_reprocess_all_faces": "Вы уверены, что хотите повторно определить все лица? Будут также удалены имена со всех лиц.",
"confirm_user_password_reset": "Вы действительно хотите сбросить пароль пользователя {user}?",
"confirm_user_pin_code_reset": "Вы действительно хотите сбросить PIN-код пользователя {user}?",
- "create_job": "Создать задание",
+ "create_job": "Создать задачу",
"cron_expression": "Расписание (выражение планировщика cron)",
- "cron_expression_description": "Частота и время выполнения задания в формате планировщика cron. Воспользуйтесь при необходимости визуальным редактором Crontab Guru",
+ "cron_expression_description": "Частота и время выполнения задачи в формате планировщика cron. Воспользуйтесь при необходимости визуальным редактором Crontab Guru",
"cron_expression_presets": "Расписание (предустановленные варианты)",
"disable_login": "Отключить вход",
"duplicate_detection_job_description": "Запускает определение похожих изображений при помощи машинного зрения (зависит от умного поиска)",
@@ -77,7 +78,7 @@
"face_detection_description": "Обнаруживает лица на объектах с использованием машинного обучения. Для видео анализируется только миниатюра. Кнопка \"Обновить\" запускает повторную обработку всех объектов. \"Сброс\" — дополнительно удаляет все имеющиеся данные о лицах. \"Отсутствующие\" — ставит в очередь объекты, которые ещё не были обработаны. Обнаруженные лица помещаются в очередь для задачи Распознавание лиц и последующей их привязки к существующим или новым людям.",
"facial_recognition_job_description": "Группирует и назначает обнаруженные лица людям. Выполняется после завершения задачи Обнаружение лиц. Кнопка \"Сброс\" (пере)назначает все лица. \"Отсутствующие\" — добавляет в очередь обработки лица, не привязанные к человеку.",
"failed_job_command": "Команда {command} не выполнена для задачи: {job}",
- "force_delete_user_warning": "ПРЕДУПРЕЖДЕНИЕ: Это приведет к немедленному удалению пользователя и его ресурсов. Это действие невозможно отменить, и файлы не могут быть восстановлены.",
+ "force_delete_user_warning": "ПРЕДУПРЕЖДЕНИЕ: Это приведет к немедленному удалению пользователя и всех его объектов. Это действие невозможно отменить, файлы не смогут быть восстановлены.",
"image_format": "Формат",
"image_format_description": "WebP создает файлы меньшего размера, чем JPEG, но кодирует медленнее.",
"image_fullsize_description": "Полноразмерное изображение без метаданных, используется при увеличении",
@@ -100,11 +101,11 @@
"image_thumbnail_description": "Маленькая миниатюра с удаленными метаданными, используемая при просмотре групп фотографий, таких как основная временная шкала",
"image_thumbnail_quality_description": "Качество миниатюр от 1 до 100. Чем выше качество, тем лучше, но при этом создаются файлы большего размера и может снизиться скорость отклика приложения.",
"image_thumbnail_title": "Настройки миниатюр",
- "job_concurrency": "Параллельная обработка задания - {job}",
- "job_created": "Задание создано",
+ "job_concurrency": "Число параллельных потоков задачи {job}",
+ "job_created": "Задача создана",
"job_not_concurrency_safe": "Эта задача не обеспечивает безопасность параллельности выполнения.",
- "job_settings": "Настройки заданий",
- "job_settings_description": "Управление параллельной обработкой заданий",
+ "job_settings": "Настройки задач",
+ "job_settings_description": "Управление параллельностью выполнения задач",
"job_status": "Состояние выполнения задач",
"jobs_delayed": "{jobCount, plural, one {# отложена} other {# отложено}}",
"jobs_failed": "{jobCount, plural, other {# не удалось выполнить}}",
@@ -123,20 +124,27 @@
"logging_enable_description": "Включить ведение журнала",
"logging_level_description": "Если включено, выберите желаемый уровень журналирования.",
"logging_settings": "Ведение журнала",
+ "machine_learning_availability_checks": "Проверка доступности",
+ "machine_learning_availability_checks_description": "Автоматически определять и использовать доступные серверы машинного обучения",
+ "machine_learning_availability_checks_enabled": "Включить проверку доступности",
+ "machine_learning_availability_checks_interval": "Интервал проверки",
+ "machine_learning_availability_checks_interval_description": "Интервал в миллисекундах между проверками",
+ "machine_learning_availability_checks_timeout": "Тайм-аут запроса",
+ "machine_learning_availability_checks_timeout_description": "Время ожидания ответа сервера в миллисекундах для определения доступности",
"machine_learning_clip_model": "CLIP модель",
- "machine_learning_clip_model_description": "Названия моделей CLIP размещены здесь. Обратите внимание, что при изменении модели необходимо заново запустить задачу «Интеллектуальный поиск» для всех изображений.",
+ "machine_learning_clip_model_description": "Названия доступных CLIP моделей размещены здесь.\nПри изменении модели необходимо заново запустить задачу «Интеллектуальный поиск» для всех объектов.",
"machine_learning_duplicate_detection": "Поиск дубликатов",
"machine_learning_duplicate_detection_enabled": "Включить обнаружение дубликатов",
- "machine_learning_duplicate_detection_enabled_description": "Если этот параметр отключен, абсолютно идентичные файлы всё равно будут удалены из дубликатов.",
- "machine_learning_duplicate_detection_setting_description": "Используйте встраивания CLIP для поиска вероятных дубликатов",
- "machine_learning_enabled": "Включите машинное обучение",
- "machine_learning_enabled_description": "При отключении, все функции ML будут отключены независимо от следующих параметров.",
+ "machine_learning_duplicate_detection_enabled_description": "Если этот параметр отключён, абсолютно идентичные файлы всё равно не будут загружаться.",
+ "machine_learning_duplicate_detection_setting_description": "Использование CLIP моделей для выявления возможных дубликатов",
+ "machine_learning_enabled": "Включить машинное обучение",
+ "machine_learning_enabled_description": "При выключении будут отключены все функции ML независимо от следующих параметров.",
"machine_learning_facial_recognition": "Распознавание лиц",
"machine_learning_facial_recognition_description": "Обнаруживать, распознавать и группировать лица на изображениях",
"machine_learning_facial_recognition_model": "Модель для распознавания лиц",
- "machine_learning_facial_recognition_model_description": "Модели перечислены в порядке убывания размера. Большие модели работают медленнее и используют больше памяти, но дают лучшие результаты. Обратите внимание, что при смене модели необходимо повторно запустить задание распознавания лиц для всех изображений.",
+ "machine_learning_facial_recognition_model_description": "Модели перечислены в порядке убывания их размера. Большие модели работают медленнее и используют больше памяти, но дают лучшие результаты. При смене модели необходимо повторно запустить задачу распознавания лиц для всех изображений.",
"machine_learning_facial_recognition_setting": "Включить функцию распознавания лиц",
- "machine_learning_facial_recognition_setting_description": "Если отключить эту функцию, изображения не будут кодироваться для распознавания лиц и не будут заполнять раздел Люди на обзорной странице.",
+ "machine_learning_facial_recognition_setting_description": "При отключении этой функции изображения не будут кодироваться для распознавания лиц, и не будет заполняться раздел Люди.",
"machine_learning_max_detection_distance": "Максимальное различие изображений",
"machine_learning_max_detection_distance_description": "Максимальное различие между двумя изображениями, чтобы считать их дубликатами, в диапазоне 0,001-0,1. Более высокие значения позволяют обнаружить больше дубликатов, но могут привести к ложным срабатываниям.",
"machine_learning_max_recognition_distance": "Порог распознавания",
@@ -146,13 +154,13 @@
"machine_learning_min_recognized_faces": "Минимум распознанных лиц",
"machine_learning_min_recognized_faces_description": "Минимальное количество распознанных лиц для создания человека. Увеличение этого параметра делает распознавание лиц более точным, но при этом увеличивается вероятность того, что лицо не будет присвоено человеку.",
"machine_learning_settings": "Настройки машинного обучения",
- "machine_learning_settings_description": "Управление функциями и настройками машинного обучения",
+ "machine_learning_settings_description": "Управление функциями и настройками машинного обучения (ML)",
"machine_learning_smart_search": "Интеллектуальный поиск",
- "machine_learning_smart_search_description": "Семантический поиск изображений с использованием вложений CLIP",
+ "machine_learning_smart_search_description": "Семантический (контекстный) поиск объектов с использованием CLIP моделей",
"machine_learning_smart_search_enabled": "Включить интеллектуальный поиск",
- "machine_learning_smart_search_enabled_description": "Если этот параметр отключен, изображения не будут кодироваться для интеллектуального поиска.",
+ "machine_learning_smart_search_enabled_description": "При отключении этой функции изображения не будут кодироваться для интеллектуального поиска.",
"machine_learning_url_description": "URL-адрес сервера машинного обучения. Если указано несколько, запросы будут отправляться по очереди на каждый, пока от одного из них не будет получен успешный ответ. Серверы, которые не отвечают, будут временно игнорироваться до тех пор, пока не станут снова доступны.",
- "manage_concurrency": "Управление параллельностью заданий",
+ "manage_concurrency": "Управление параллельностью",
"manage_log_settings": "Управление настройками журнала",
"map_dark_style": "Тёмный стиль",
"map_enable_description": "Включить функции карты",
@@ -170,9 +178,9 @@
"memory_cleanup_job": "Очистка воспоминаний",
"memory_generate_job": "Создание воспоминаний",
"metadata_extraction_job": "Извлечение метаданных",
- "metadata_extraction_job_description": "Извлекает метаданные из каждого файла, такие как местоположение, лица и разрешение",
+ "metadata_extraction_job_description": "Извлечение метаданных из файлов, таких как местоположение, лица и разрешение",
"metadata_faces_import_setting": "Включить импорт лиц",
- "metadata_faces_import_setting_description": "Импорт лиц из изображений EXIF-данных и файлов sidecar",
+ "metadata_faces_import_setting_description": "Импорт лиц из EXIF-данных и файлов sidecar",
"metadata_settings": "Настройки метаданных",
"metadata_settings_description": "Управление настройками метаданных",
"migration_job": "Миграция",
@@ -247,7 +255,7 @@
"reset_settings_to_default": "Сброс настроек до значений по умолчанию",
"reset_settings_to_recent_saved": "Не сохранённые изменения сброшены к последним сохраненным значениям",
"scanning_library": "Сканирование библиотеки",
- "search_jobs": "Поиск заданий…",
+ "search_jobs": "Поиск задач…",
"send_welcome_email": "Отправить приветственное письмо",
"server_external_domain_settings": "Внешний домен",
"server_external_domain_settings_description": "Домен для публичных ссылок, включая http(s)://",
@@ -268,8 +276,8 @@
"storage_template_hash_verification_enabled_description": "Включает проверку хеша, не отключайте её, если не уверены в последствиях",
"storage_template_migration": "Применение шаблона хранилища",
"storage_template_migration_description": "Применяет текущий {template} к ранее загруженным объектам",
- "storage_template_migration_info": "Расширения файлов всегда будут сохраняться в нижнем регистре. Изменения в шаблоне будут применяться только к новым ресурсам. Чтобы применить шаблон к ранее загруженным ресурсам, запустите {job}.",
- "storage_template_migration_job": "Задание по применению шаблона хранилища",
+ "storage_template_migration_info": "Расширения файлов всегда будут сохраняться в нижнем регистре. Изменения в шаблоне будут применяться только к новым объектам. Чтобы применить шаблон к ранее загруженным объектам, запустите {job}.",
+ "storage_template_migration_job": "Задача по применению шаблона хранилища",
"storage_template_more_details": "Для получения дополнительной информации об этой функции обратитесь к разделам документации