mirror of
https://github.com/immich-app/immich.git
synced 2026-05-18 03:10:24 +03:00
Compare commits
165 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 06b6f16cd6 | |||
| 3eb03f7934 | |||
| 03ed3daa31 | |||
| 02581e81a7 | |||
| 3ab3d5cf43 | |||
| 0ef04d9baa | |||
| df016f9228 | |||
| 17779c1e74 | |||
| 01d6a244d8 | |||
| 21d6755f39 | |||
| e91c017dd0 | |||
| 43687cd8b4 | |||
| 06729ee5a5 | |||
| b0c9743d9a | |||
| 37cc028868 | |||
| 84a2b7a3c8 | |||
| 89b3433346 | |||
| 3ff0d47ee3 | |||
| aeaf846482 | |||
| b031548791 | |||
| fcea617313 | |||
| 024f20ea26 | |||
| 0a4ed6fd71 | |||
| b6e2ce1f35 | |||
| e323e778cd | |||
| 6a87797649 | |||
| f4a4649bbc | |||
| 6ca54ee722 | |||
| 8e3035f783 | |||
| 79801595db | |||
| 3e1c8aacb1 | |||
| 91ac56cef2 | |||
| 58beac8fe0 | |||
| f632d320f5 | |||
| 2ddaf6a611 | |||
| 1932c60e1c | |||
| dc6f8e746e | |||
| ad7aedb843 | |||
| 571e6a8560 | |||
| 4791313def | |||
| f88fdae048 | |||
| bcef7aa6b6 | |||
| ce292bdce9 | |||
| 4eee023648 | |||
| 8f4b0fce49 | |||
| c6b3127b35 | |||
| 4d6a50c2cb | |||
| 15f3947ae6 | |||
| e142e3aca7 | |||
| 38438c8d9a | |||
| a278c10c75 | |||
| 2276443c56 | |||
| bb44773e57 | |||
| 14d9e90a03 | |||
| 03e042213c | |||
| db589455f4 | |||
| fb0a54d548 | |||
| 7013cc0904 | |||
| dcaf7b4a65 | |||
| 12f7b2a005 | |||
| 7837d40f57 | |||
| b4f719653f | |||
| f370b4bac6 | |||
| d788169bf3 | |||
| eea820fa2f | |||
| 271f1cb868 | |||
| 8c8dc9d32f | |||
| fd18e55f7c | |||
| faab9e620d | |||
| 5ba3efafd8 | |||
| 8b3c9bf9c3 | |||
| 41f285aa3e | |||
| fdac6c8bc4 | |||
| d7f05d2510 | |||
| 3100bd5eed | |||
| 8a024e2b50 | |||
| 25a6a38b30 | |||
| 7c6750941e | |||
| 832ed4d015 | |||
| 238895cad9 | |||
| e2ec04e86c | |||
| 6050526360 | |||
| bfd76570c5 | |||
| 37e6a49652 | |||
| 36caeb34ec | |||
| 87713c7f2f | |||
| 2039c129f2 | |||
| 52b00b0bad | |||
| 21af184045 | |||
| 1fcc2b704b | |||
| 7de73dc176 | |||
| fe2bf0c6dd | |||
| d4a97f2d25 | |||
| bd58db4fcc | |||
| 7f43c6a3a3 | |||
| 87175ee56c | |||
| 13587bf13c | |||
| f09769a2f3 | |||
| bfdff12ee0 | |||
| eb6dca6a31 | |||
| c2e3739a58 | |||
| f6bd514cdc | |||
| d93ab7707e | |||
| 6bb47c802f | |||
| 90a69e2ba6 | |||
| 6580394cfe | |||
| 42ff3b705d | |||
| 0f00053bb1 | |||
| c5c59ed040 | |||
| 576b1eb999 | |||
| 24189702da | |||
| ad0d01005e | |||
| 3e6d053f93 | |||
| 1bb3fd985f | |||
| f72aa54a1f | |||
| dafe9d7966 | |||
| 7acda0572d | |||
| 98bc9f6a6e | |||
| 63a3b405c3 | |||
| 0058df798d | |||
| 97100a4362 | |||
| af39384efb | |||
| 01712cf0a7 | |||
| 2015f95ff5 | |||
| d4f29ab6ac | |||
| 3decc864b5 | |||
| eca0e60db8 | |||
| 8cff5883b5 | |||
| 3d320d9751 | |||
| b9e0e65bdb | |||
| 88e5e8d6ea | |||
| ee107c98d5 | |||
| affe0ac5ee | |||
| f1d8ab8aae | |||
| c0898b96ca | |||
| 5e9bda7fab | |||
| b60e9c6771 | |||
| b554664791 | |||
| 97c62136b7 | |||
| c1051c7ed2 | |||
| 65bd0a9320 | |||
| bf32864644 | |||
| 7ef7ecec5b | |||
| bc4abd18e4 | |||
| b74cfd4424 | |||
| 7dc84f56c0 | |||
| 92634f923b | |||
| 96b6165bd3 | |||
| 2624f3884f | |||
| f9b7ce9407 | |||
| 013ea37a0d | |||
| b2b4385271 | |||
| 081c75bb21 | |||
| da337578fb | |||
| acf4109171 | |||
| 66601a1fdc | |||
| 02ff077367 | |||
| 94bb6c1a5e | |||
| fe9e5afcf4 | |||
| 5e89efba64 | |||
| 5a457d72c9 | |||
| 45ccdb37fb | |||
| 9263e2f2e1 | |||
| a3ee615c5b | |||
| 39cfad7136 |
@@ -75,7 +75,7 @@
|
|||||||
{
|
{
|
||||||
"label": "Build Immich CLI",
|
"label": "Build Immich CLI",
|
||||||
"type": "shell",
|
"type": "shell",
|
||||||
"command": "pnpm --filter cli build:dev"
|
"command": "pnpm --filter @immich/cli build:dev"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ services:
|
|||||||
- ${UPLOAD_LOCATION:-upload-devcontainer-volume}${UPLOAD_LOCATION:+/photos}:/data
|
- ${UPLOAD_LOCATION:-upload-devcontainer-volume}${UPLOAD_LOCATION:+/photos}:/data
|
||||||
- /etc/localtime:/etc/localtime:ro
|
- /etc/localtime:/etc/localtime:ro
|
||||||
- pnpm_store_server:/buildcache/pnpm-store
|
- pnpm_store_server:/buildcache/pnpm-store
|
||||||
- ../plugins:/build/corePlugin
|
- ../packages/plugins:/build/corePlugin
|
||||||
immich-web:
|
immich-web:
|
||||||
env_file: !reset []
|
env_file: !reset []
|
||||||
immich-machine-learning:
|
immich-machine-learning:
|
||||||
|
|||||||
+1
-3
@@ -30,9 +30,7 @@ machine-learning/
|
|||||||
misc/
|
misc/
|
||||||
mobile/
|
mobile/
|
||||||
|
|
||||||
open-api/typescript-sdk/build/
|
packages/sdk/build/
|
||||||
!open-api/typescript-sdk/package.json
|
|
||||||
!open-api/typescript-sdk/package-lock.json
|
|
||||||
|
|
||||||
server/upload/
|
server/upload/
|
||||||
server/src/queries
|
server/src/queries
|
||||||
|
|||||||
+2
-2
@@ -24,7 +24,7 @@ mobile/lib/infrastructure/repositories/db.repository.steps.dart linguist-generat
|
|||||||
mobile/test/drift/main/generated/** -diff -merge
|
mobile/test/drift/main/generated/** -diff -merge
|
||||||
mobile/test/drift/main/generated/** linguist-generated=true
|
mobile/test/drift/main/generated/** linguist-generated=true
|
||||||
|
|
||||||
open-api/typescript-sdk/fetch-client.ts -diff -merge
|
packages/sdk/fetch-client.ts -diff -merge
|
||||||
open-api/typescript-sdk/fetch-client.ts linguist-generated=true
|
packages/sdk/fetch-client.ts linguist-generated=true
|
||||||
|
|
||||||
*.sh text eol=lf
|
*.sh text eol=lf
|
||||||
|
|||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
cli:
|
cli:
|
||||||
- changed-files:
|
- changed-files:
|
||||||
- any-glob-to-any-file:
|
- any-glob-to-any-file:
|
||||||
- cli/src/**
|
- packages/cli/src/**
|
||||||
|
|
||||||
documentation:
|
documentation:
|
||||||
- changed-files:
|
- changed-files:
|
||||||
|
|||||||
@@ -51,14 +51,14 @@ jobs:
|
|||||||
should_run: ${{ steps.check.outputs.should_run }}
|
should_run: ${{ steps.check.outputs.should_run }}
|
||||||
steps:
|
steps:
|
||||||
- id: token
|
- id: token
|
||||||
uses: immich-app/devtools/actions/create-workflow-token@57ff6ebfd507b045514442683ff06ff1b2f6efbd # create-workflow-token-action-v1.0.2
|
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
|
||||||
with:
|
with:
|
||||||
app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }}
|
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||||
|
|
||||||
- name: Check what should run
|
- name: Check what should run
|
||||||
id: check
|
id: check
|
||||||
uses: immich-app/devtools/actions/pre-job@f50e3b600b6ac1763ddb8f3dfc69093512b967a1 # pre-job-action-v2.0.3
|
uses: immich-app/devtools/actions/pre-job@91f342bb4477c4bc10c576ae739da875d85aa164 # pre-job-action-v2.0.4
|
||||||
with:
|
with:
|
||||||
github-token: ${{ steps.token.outputs.token }}
|
github-token: ${{ steps.token.outputs.token }}
|
||||||
filters: |
|
filters: |
|
||||||
@@ -73,24 +73,30 @@ jobs:
|
|||||||
needs: pre-job
|
needs: pre-job
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
# Skip when PR from a fork
|
pull-requests: write
|
||||||
if: ${{ !github.event.pull_request.head.repo.fork && github.actor != 'dependabot[bot]' && fromJSON(needs.pre-job.outputs.should_run).mobile == true }}
|
if: ${{ github.actor != 'dependabot[bot]' && fromJSON(needs.pre-job.outputs.should_run).mobile == true }}
|
||||||
runs-on: mich
|
runs-on: mich
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- id: token
|
- id: token
|
||||||
uses: immich-app/devtools/actions/create-workflow-token@57ff6ebfd507b045514442683ff06ff1b2f6efbd # create-workflow-token-action-v1.0.2
|
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
|
||||||
with:
|
with:
|
||||||
app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }}
|
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||||
|
|
||||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||||
with:
|
with:
|
||||||
ref: ${{ inputs.ref || github.sha }}
|
ref: ${{ inputs.ref }}
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
token: ${{ steps.token.outputs.token }}
|
token: ${{ steps.token.outputs.token }}
|
||||||
|
|
||||||
|
- name: Setup Mise
|
||||||
|
uses: immich-app/devtools/actions/use-mise@cf6e190bacde3d7bda59372a786b36ac7d01536a # use-mise-action-v2.0.1
|
||||||
|
with:
|
||||||
|
github_token: ${{ steps.token.outputs.token }}
|
||||||
|
|
||||||
- name: Create the Keystore
|
- name: Create the Keystore
|
||||||
|
if: ${{ !github.event.pull_request.head.repo.fork }}
|
||||||
env:
|
env:
|
||||||
KEY_JKS: ${{ secrets.KEY_JKS }}
|
KEY_JKS: ${{ secrets.KEY_JKS }}
|
||||||
working-directory: ./mobile
|
working-directory: ./mobile
|
||||||
@@ -110,16 +116,8 @@ jobs:
|
|||||||
~/.gradle/wrapper
|
~/.gradle/wrapper
|
||||||
~/.android/sdk
|
~/.android/sdk
|
||||||
mobile/android/.gradle
|
mobile/android/.gradle
|
||||||
mobile/.dart_tool
|
|
||||||
key: build-mobile-gradle-${{ runner.os }}-main
|
key: build-mobile-gradle-${{ runner.os }}-main
|
||||||
|
|
||||||
- name: Setup Flutter SDK
|
|
||||||
uses: subosito/flutter-action@1a449444c387b1966244ae4d4f8c696479add0b2 # v2.23.0
|
|
||||||
with:
|
|
||||||
channel: 'stable'
|
|
||||||
flutter-version-file: ./mobile/pubspec.yaml
|
|
||||||
cache: true
|
|
||||||
|
|
||||||
- name: Setup Android SDK
|
- name: Setup Android SDK
|
||||||
uses: android-actions/setup-android@40fd30fb8d7440372e1316f5d1809ec01dcd3699 # v4.0.1
|
uses: android-actions/setup-android@40fd30fb8d7440372e1316f5d1809ec01dcd3699 # v4.0.1
|
||||||
with:
|
with:
|
||||||
@@ -130,11 +128,10 @@ jobs:
|
|||||||
run: flutter pub get
|
run: flutter pub get
|
||||||
|
|
||||||
- name: Generate translation file
|
- name: Generate translation file
|
||||||
run: dart run easy_localization:generate -S ../i18n && dart run bin/generate_keys.dart
|
run: mise //mobile:codegen:translation
|
||||||
working-directory: ./mobile
|
|
||||||
|
|
||||||
- name: Generate platform APIs
|
- name: Generate platform APIs
|
||||||
run: make pigeon
|
run: mise //mobile:codegen:pigeon
|
||||||
working-directory: ./mobile
|
working-directory: ./mobile
|
||||||
|
|
||||||
- name: Build Android App Bundle
|
- name: Build Android App Bundle
|
||||||
@@ -144,20 +141,43 @@ jobs:
|
|||||||
ANDROID_KEY_PASSWORD: ${{ secrets.ANDROID_KEY_PASSWORD }}
|
ANDROID_KEY_PASSWORD: ${{ secrets.ANDROID_KEY_PASSWORD }}
|
||||||
ANDROID_STORE_PASSWORD: ${{ secrets.ANDROID_STORE_PASSWORD }}
|
ANDROID_STORE_PASSWORD: ${{ secrets.ANDROID_STORE_PASSWORD }}
|
||||||
IS_MAIN: ${{ github.ref == 'refs/heads/main' }}
|
IS_MAIN: ${{ github.ref == 'refs/heads/main' }}
|
||||||
|
PR_NUMBER: ${{ github.event.pull_request.number }}
|
||||||
run: |
|
run: |
|
||||||
if [[ $IS_MAIN == 'true' ]]; then
|
if [[ $IS_MAIN == 'true' ]]; then
|
||||||
flutter build apk --release
|
flutter build apk --release
|
||||||
flutter build apk --release --split-per-abi --target-platform android-arm,android-arm64,android-x64
|
flutter build apk --release --split-per-abi --target-platform android-arm,android-arm64,android-x64
|
||||||
else
|
else
|
||||||
flutter build apk --debug --split-per-abi --target-platform android-arm64
|
flutter build apk --release
|
||||||
fi
|
fi
|
||||||
|
|
||||||
- name: Publish Android Artifact
|
- name: Publish Android Artifact
|
||||||
|
id: upload-apk
|
||||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||||
with:
|
with:
|
||||||
name: release-apk-signed
|
name: release-apk-signed
|
||||||
path: mobile/build/app/outputs/flutter-apk/*.apk
|
path: mobile/build/app/outputs/flutter-apk/*.apk
|
||||||
|
|
||||||
|
- name: Comment APK download link on PR
|
||||||
|
if: ${{ github.event_name == 'pull_request' && !github.event.pull_request.head.repo.fork }}
|
||||||
|
uses: mshick/add-pr-comment@8e4927817251f1ff60c001f04568532b38e0b4a0 # v3.11.0
|
||||||
|
env:
|
||||||
|
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
|
||||||
|
APK_URL: ${{ steps.upload-apk.outputs.artifact-url }}
|
||||||
|
with:
|
||||||
|
github-token: ${{ steps.token.outputs.token }}
|
||||||
|
message-id: 'mobile-android-apk'
|
||||||
|
message: |
|
||||||
|
📱 **Android release APK (universal)** — `${{ env.HEAD_SHA }}`
|
||||||
|
|
||||||
|
Download: ${{ env.APK_URL }}
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>QR code</summary>
|
||||||
|
<img src="https://api.qrserver.com/v1/create-qr-code/?size=240x240&data=${{ env.APK_URL }}" alt="QR code" />
|
||||||
|
</details>
|
||||||
|
|
||||||
|
Installs as a separate app (applicationId `app.alextran.immich.pr${{ github.event.pull_request.number }}`), so it coexists with the Play Store version and any other PR builds.
|
||||||
|
|
||||||
- name: Save Gradle Cache
|
- name: Save Gradle Cache
|
||||||
id: cache-gradle-save
|
id: cache-gradle-save
|
||||||
uses: actions/cache/save@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
|
uses: actions/cache/save@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
|
||||||
@@ -168,7 +188,6 @@ jobs:
|
|||||||
~/.gradle/wrapper
|
~/.gradle/wrapper
|
||||||
~/.android/sdk
|
~/.android/sdk
|
||||||
mobile/android/.gradle
|
mobile/android/.gradle
|
||||||
mobile/.dart_tool
|
|
||||||
key: ${{ steps.cache-gradle-restore.outputs.cache-primary-key }}
|
key: ${{ steps.cache-gradle-restore.outputs.cache-primary-key }}
|
||||||
|
|
||||||
build-sign-ios:
|
build-sign-ios:
|
||||||
@@ -181,6 +200,12 @@ jobs:
|
|||||||
runs-on: macos-15
|
runs-on: macos-15
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
|
- id: token
|
||||||
|
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
|
||||||
|
with:
|
||||||
|
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||||
|
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||||
|
|
||||||
- name: Select Xcode 26
|
- name: Select Xcode 26
|
||||||
run: sudo xcode-select -s /Applications/Xcode_26.2.app/Contents/Developer
|
run: sudo xcode-select -s /Applications/Xcode_26.2.app/Contents/Developer
|
||||||
|
|
||||||
@@ -190,27 +215,23 @@ jobs:
|
|||||||
ref: ${{ inputs.ref || github.sha }}
|
ref: ${{ inputs.ref || github.sha }}
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
|
|
||||||
- name: Setup Flutter SDK
|
- name: Setup Mise
|
||||||
uses: subosito/flutter-action@1a449444c387b1966244ae4d4f8c696479add0b2 # v2.23.0
|
uses: immich-app/devtools/actions/use-mise@cf6e190bacde3d7bda59372a786b36ac7d01536a # use-mise-action-v2.0.1
|
||||||
with:
|
with:
|
||||||
channel: 'stable'
|
github_token: ${{ steps.token.outputs.token }}
|
||||||
flutter-version-file: ./mobile/pubspec.yaml
|
|
||||||
cache: true
|
|
||||||
|
|
||||||
- name: Install Flutter dependencies
|
- name: Install Flutter dependencies
|
||||||
working-directory: ./mobile
|
working-directory: ./mobile
|
||||||
run: flutter pub get
|
run: flutter pub get
|
||||||
|
|
||||||
- name: Generate translation files
|
- name: Generate translation files
|
||||||
run: dart run easy_localization:generate -S ../i18n && dart run bin/generate_keys.dart
|
run: mise //mobile:codegen:translation
|
||||||
working-directory: ./mobile
|
|
||||||
|
|
||||||
- name: Generate platform APIs
|
- name: Generate platform APIs
|
||||||
run: make pigeon
|
run: mise //mobile:codegen:pigeon
|
||||||
working-directory: ./mobile
|
|
||||||
|
|
||||||
- name: Setup Ruby
|
- name: Setup Ruby
|
||||||
uses: ruby/setup-ruby@7372622e62b60b3cb750dcd2b9e32c247ffec26a # v1.302.0
|
uses: ruby/setup-ruby@c4e5b1316158f92e3d49443a9d58b31d25ac0f8f # v1.306.0
|
||||||
with:
|
with:
|
||||||
ruby-version: '3.3'
|
ruby-version: '3.3'
|
||||||
bundler-cache: true
|
bundler-cache: true
|
||||||
|
|||||||
@@ -19,9 +19,9 @@ jobs:
|
|||||||
actions: write
|
actions: write
|
||||||
steps:
|
steps:
|
||||||
- id: token
|
- id: token
|
||||||
uses: immich-app/devtools/actions/create-workflow-token@57ff6ebfd507b045514442683ff06ff1b2f6efbd # create-workflow-token-action-v1.0.2
|
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
|
||||||
with:
|
with:
|
||||||
app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }}
|
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||||
|
|
||||||
- name: Check out code
|
- name: Check out code
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ jobs:
|
|||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
|
|
||||||
- name: Check for breaking API changes
|
- name: Check for breaking API changes
|
||||||
uses: oasdiff/oasdiff-action/breaking@f8cb9308b42121e793f835bd14c0b8090420430c # v0.0.39
|
uses: oasdiff/oasdiff-action/breaking@26ccb332c67a45ca649de9faf60552ef1b8260d9 # v0.0.46
|
||||||
with:
|
with:
|
||||||
base: https://raw.githubusercontent.com/${{ github.repository }}/main/open-api/immich-openapi-specs.json
|
base: https://raw.githubusercontent.com/${{ github.repository }}/main/open-api/immich-openapi-specs.json
|
||||||
revision: open-api/immich-openapi-specs.json
|
revision: open-api/immich-openapi-specs.json
|
||||||
|
|||||||
+16
-26
@@ -3,11 +3,11 @@ on:
|
|||||||
push:
|
push:
|
||||||
branches: [main]
|
branches: [main]
|
||||||
paths:
|
paths:
|
||||||
- 'cli/**'
|
- 'packages/cli/**'
|
||||||
- '.github/workflows/cli.yml'
|
- '.github/workflows/cli.yml'
|
||||||
pull_request:
|
pull_request:
|
||||||
paths:
|
paths:
|
||||||
- 'cli/**'
|
- 'packages/cli/**'
|
||||||
- '.github/workflows/cli.yml'
|
- '.github/workflows/cli.yml'
|
||||||
release:
|
release:
|
||||||
types: [published]
|
types: [published]
|
||||||
@@ -28,38 +28,28 @@ jobs:
|
|||||||
packages: write
|
packages: write
|
||||||
defaults:
|
defaults:
|
||||||
run:
|
run:
|
||||||
working-directory: ./cli
|
working-directory: ./packages/cli
|
||||||
steps:
|
steps:
|
||||||
- id: token
|
- id: token
|
||||||
uses: immich-app/devtools/actions/create-workflow-token@57ff6ebfd507b045514442683ff06ff1b2f6efbd # create-workflow-token-action-v1.0.2
|
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
|
||||||
with:
|
with:
|
||||||
app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }}
|
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||||
|
|
||||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||||
with:
|
with:
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
token: ${{ steps.token.outputs.token }}
|
token: ${{ steps.token.outputs.token }}
|
||||||
|
|
||||||
- name: Setup pnpm
|
- name: Setup Mise
|
||||||
uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v5.0.0
|
uses: immich-app/devtools/actions/use-mise@cf6e190bacde3d7bda59372a786b36ac7d01536a # use-mise-action-v2.0.1
|
||||||
|
|
||||||
- name: Setup Node
|
|
||||||
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
|
|
||||||
with:
|
with:
|
||||||
node-version-file: './cli/.nvmrc'
|
github_token: ${{ steps.token.outputs.token }}
|
||||||
registry-url: 'https://registry.npmjs.org'
|
|
||||||
cache: 'pnpm'
|
|
||||||
cache-dependency-path: '**/pnpm-lock.yaml'
|
|
||||||
|
|
||||||
- name: Setup typescript-sdk
|
- name: Publish
|
||||||
run: pnpm install && pnpm run build
|
|
||||||
working-directory: ./open-api/typescript-sdk
|
|
||||||
|
|
||||||
- run: pnpm install --frozen-lockfile
|
|
||||||
- run: pnpm build
|
|
||||||
- run: pnpm publish --provenance --no-git-checks
|
|
||||||
if: ${{ github.event_name == 'release' }}
|
if: ${{ github.event_name == 'release' }}
|
||||||
|
run: mise run ci-publish
|
||||||
|
|
||||||
docker:
|
docker:
|
||||||
name: Docker
|
name: Docker
|
||||||
@@ -71,9 +61,9 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- id: token
|
- id: token
|
||||||
uses: immich-app/devtools/actions/create-workflow-token@57ff6ebfd507b045514442683ff06ff1b2f6efbd # create-workflow-token-action-v1.0.2
|
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
|
||||||
with:
|
with:
|
||||||
app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }}
|
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||||
|
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
@@ -99,7 +89,7 @@ jobs:
|
|||||||
- name: Get package version
|
- name: Get package version
|
||||||
id: package-version
|
id: package-version
|
||||||
run: |
|
run: |
|
||||||
version=$(jq -r '.version' cli/package.json)
|
version=$(jq -r '.version' packages/cli/package.json)
|
||||||
echo "version=$version" >> "$GITHUB_OUTPUT"
|
echo "version=$version" >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
- name: Generate docker image tags
|
- name: Generate docker image tags
|
||||||
@@ -117,7 +107,7 @@ jobs:
|
|||||||
- name: Build and push image
|
- name: Build and push image
|
||||||
uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f # v7.1.0
|
uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f # v7.1.0
|
||||||
with:
|
with:
|
||||||
file: cli/Dockerfile
|
file: packages/cli/Dockerfile
|
||||||
platforms: linux/amd64,linux/arm64
|
platforms: linux/amd64,linux/arm64
|
||||||
push: ${{ github.event_name == 'release' }}
|
push: ${{ github.event_name == 'release' }}
|
||||||
cache-from: type=gha
|
cache-from: type=gha
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ jobs:
|
|||||||
needs: [get_body, should_run]
|
needs: [get_body, should_run]
|
||||||
if: ${{ needs.should_run.outputs.should_run == 'true' }}
|
if: ${{ needs.should_run.outputs.should_run == 'true' }}
|
||||||
container:
|
container:
|
||||||
image: ghcr.io/immich-app/mdq:main@sha256:557cca601891b8b7d78b940071d35aaf7aaeb9b327d19b22cf282118edbc5272
|
image: ghcr.io/immich-app/mdq:main@sha256:0a8b8867773a0f8368061f47578603f438349f8f1f28b0e16105f481e5c794e0
|
||||||
outputs:
|
outputs:
|
||||||
checked: ${{ steps.get_checkbox.outputs.checked }}
|
checked: ${{ steps.get_checkbox.outputs.checked }}
|
||||||
steps:
|
steps:
|
||||||
|
|||||||
@@ -44,9 +44,9 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- id: token
|
- id: token
|
||||||
uses: immich-app/devtools/actions/create-workflow-token@57ff6ebfd507b045514442683ff06ff1b2f6efbd # create-workflow-token-action-v1.0.2
|
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
|
||||||
with:
|
with:
|
||||||
app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }}
|
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||||
|
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
@@ -57,7 +57,7 @@ jobs:
|
|||||||
|
|
||||||
# Initializes the CodeQL tools for scanning.
|
# Initializes the CodeQL tools for scanning.
|
||||||
- name: Initialize CodeQL
|
- name: Initialize CodeQL
|
||||||
uses: github/codeql-action/init@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4.35.2
|
uses: github/codeql-action/init@e46ed2cbd01164d986452f91f178727624ae40d7 # v4.35.3
|
||||||
with:
|
with:
|
||||||
languages: ${{ matrix.language }}
|
languages: ${{ matrix.language }}
|
||||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||||
@@ -70,7 +70,7 @@ jobs:
|
|||||||
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
# 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)
|
# If this step fails, then you should remove it and run the build manually (see below)
|
||||||
- name: Autobuild
|
- name: Autobuild
|
||||||
uses: github/codeql-action/autobuild@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4.35.2
|
uses: github/codeql-action/autobuild@e46ed2cbd01164d986452f91f178727624ae40d7 # v4.35.3
|
||||||
|
|
||||||
# ℹ️ Command-line programs to run using the OS shell.
|
# ℹ️ 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
|
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
|
||||||
@@ -83,6 +83,6 @@ jobs:
|
|||||||
# ./location_of_script_within_repo/buildscript.sh
|
# ./location_of_script_within_repo/buildscript.sh
|
||||||
|
|
||||||
- name: Perform CodeQL Analysis
|
- name: Perform CodeQL Analysis
|
||||||
uses: github/codeql-action/analyze@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4.35.2
|
uses: github/codeql-action/analyze@e46ed2cbd01164d986452f91f178727624ae40d7 # v4.35.3
|
||||||
with:
|
with:
|
||||||
category: '/language:${{matrix.language}}'
|
category: '/language:${{matrix.language}}'
|
||||||
|
|||||||
@@ -23,14 +23,14 @@ jobs:
|
|||||||
should_run: ${{ steps.check.outputs.should_run }}
|
should_run: ${{ steps.check.outputs.should_run }}
|
||||||
steps:
|
steps:
|
||||||
- id: token
|
- id: token
|
||||||
uses: immich-app/devtools/actions/create-workflow-token@57ff6ebfd507b045514442683ff06ff1b2f6efbd # create-workflow-token-action-v1.0.2
|
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
|
||||||
with:
|
with:
|
||||||
app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }}
|
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||||
|
|
||||||
- name: Check what should run
|
- name: Check what should run
|
||||||
id: check
|
id: check
|
||||||
uses: immich-app/devtools/actions/pre-job@f50e3b600b6ac1763ddb8f3dfc69093512b967a1 # pre-job-action-v2.0.3
|
uses: immich-app/devtools/actions/pre-job@91f342bb4477c4bc10c576ae739da875d85aa164 # pre-job-action-v2.0.4
|
||||||
with:
|
with:
|
||||||
github-token: ${{ steps.token.outputs.token }}
|
github-token: ${{ steps.token.outputs.token }}
|
||||||
filters: |
|
filters: |
|
||||||
@@ -132,7 +132,7 @@ jobs:
|
|||||||
suffixes: '-rocm'
|
suffixes: '-rocm'
|
||||||
platforms: linux/amd64
|
platforms: linux/amd64
|
||||||
runner-mapping: '{"linux/amd64": "pokedex-large"}'
|
runner-mapping: '{"linux/amd64": "pokedex-large"}'
|
||||||
uses: immich-app/devtools/.github/workflows/multi-runner-build.yml@61a0fc2b41524edcc7c9fffb8bb178e6b0ccf21d # multi-runner-build-workflow-v2.3.0
|
uses: immich-app/devtools/.github/workflows/multi-runner-build.yml@5813c7c4f7016c748ae7ac5d5f684846649d4d20 # multi-runner-build-workflow-v2.4.0
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
actions: read
|
actions: read
|
||||||
@@ -155,7 +155,7 @@ jobs:
|
|||||||
name: Build and Push Server
|
name: Build and Push Server
|
||||||
needs: pre-job
|
needs: pre-job
|
||||||
if: ${{ fromJSON(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@61a0fc2b41524edcc7c9fffb8bb178e6b0ccf21d # multi-runner-build-workflow-v2.3.0
|
uses: immich-app/devtools/.github/workflows/multi-runner-build.yml@5813c7c4f7016c748ae7ac5d5f684846649d4d20 # multi-runner-build-workflow-v2.4.0
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
actions: read
|
actions: read
|
||||||
@@ -178,7 +178,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
if: always()
|
if: always()
|
||||||
steps:
|
steps:
|
||||||
- uses: immich-app/devtools/actions/success-check@53bb77345ee9f953f93bd6fd9980f07a2f24965e # success-check-action-v0.0.5
|
- uses: immich-app/devtools/actions/success-check@81113db03f6d743efee81e0058c0b43f6cd6f36d # success-check-action-v0.0.6
|
||||||
with:
|
with:
|
||||||
needs: ${{ toJSON(needs) }}
|
needs: ${{ toJSON(needs) }}
|
||||||
|
|
||||||
@@ -189,6 +189,6 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
if: always()
|
if: always()
|
||||||
steps:
|
steps:
|
||||||
- uses: immich-app/devtools/actions/success-check@53bb77345ee9f953f93bd6fd9980f07a2f24965e # success-check-action-v0.0.5
|
- uses: immich-app/devtools/actions/success-check@81113db03f6d743efee81e0058c0b43f6cd6f36d # success-check-action-v0.0.6
|
||||||
with:
|
with:
|
||||||
needs: ${{ toJSON(needs) }}
|
needs: ${{ toJSON(needs) }}
|
||||||
|
|||||||
@@ -21,14 +21,14 @@ jobs:
|
|||||||
should_run: ${{ steps.check.outputs.should_run }}
|
should_run: ${{ steps.check.outputs.should_run }}
|
||||||
steps:
|
steps:
|
||||||
- id: token
|
- id: token
|
||||||
uses: immich-app/devtools/actions/create-workflow-token@57ff6ebfd507b045514442683ff06ff1b2f6efbd # create-workflow-token-action-v1.0.2
|
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
|
||||||
with:
|
with:
|
||||||
app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }}
|
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||||
|
|
||||||
- name: Check what should run
|
- name: Check what should run
|
||||||
id: check
|
id: check
|
||||||
uses: immich-app/devtools/actions/pre-job@f50e3b600b6ac1763ddb8f3dfc69093512b967a1 # pre-job-action-v2.0.3
|
uses: immich-app/devtools/actions/pre-job@91f342bb4477c4bc10c576ae739da875d85aa164 # pre-job-action-v2.0.4
|
||||||
with:
|
with:
|
||||||
github-token: ${{ steps.token.outputs.token }}
|
github-token: ${{ steps.token.outputs.token }}
|
||||||
filters: |
|
filters: |
|
||||||
@@ -54,9 +54,9 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- id: token
|
- id: token
|
||||||
uses: immich-app/devtools/actions/create-workflow-token@57ff6ebfd507b045514442683ff06ff1b2f6efbd # create-workflow-token-action-v1.0.2
|
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
|
||||||
with:
|
with:
|
||||||
app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }}
|
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||||
|
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
@@ -64,17 +64,11 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
token: ${{ steps.token.outputs.token }}
|
token: ${{ steps.token.outputs.token }}
|
||||||
fetch-depth: 0
|
|
||||||
|
|
||||||
- name: Setup pnpm
|
- name: Setup Mise
|
||||||
uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v5.0.0
|
uses: immich-app/devtools/actions/use-mise@cf6e190bacde3d7bda59372a786b36ac7d01536a # use-mise-action-v2.0.1
|
||||||
|
|
||||||
- name: Setup Node
|
|
||||||
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
|
|
||||||
with:
|
with:
|
||||||
node-version-file: './docs/.nvmrc'
|
github_token: ${{ steps.token.outputs.token }}
|
||||||
cache: 'pnpm'
|
|
||||||
cache-dependency-path: '**/pnpm-lock.yaml'
|
|
||||||
|
|
||||||
- name: Run install
|
- name: Run install
|
||||||
run: pnpm install
|
run: pnpm install
|
||||||
|
|||||||
@@ -20,9 +20,9 @@ jobs:
|
|||||||
artifact: ${{ steps.get-artifact.outputs.result }}
|
artifact: ${{ steps.get-artifact.outputs.result }}
|
||||||
steps:
|
steps:
|
||||||
- id: token
|
- id: token
|
||||||
uses: immich-app/devtools/actions/create-workflow-token@57ff6ebfd507b045514442683ff06ff1b2f6efbd # create-workflow-token-action-v1.0.2
|
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
|
||||||
with:
|
with:
|
||||||
app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }}
|
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||||
|
|
||||||
- if: ${{ github.event.workflow_run.conclusion != 'success' }}
|
- if: ${{ github.event.workflow_run.conclusion != 'success' }}
|
||||||
@@ -119,9 +119,9 @@ jobs:
|
|||||||
if: ${{ fromJson(needs.checks.outputs.artifact).found && fromJson(needs.checks.outputs.parameters).shouldDeploy }}
|
if: ${{ fromJson(needs.checks.outputs.artifact).found && fromJson(needs.checks.outputs.parameters).shouldDeploy }}
|
||||||
steps:
|
steps:
|
||||||
- id: token
|
- id: token
|
||||||
uses: immich-app/devtools/actions/create-workflow-token@57ff6ebfd507b045514442683ff06ff1b2f6efbd # create-workflow-token-action-v1.0.2
|
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
|
||||||
with:
|
with:
|
||||||
app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }}
|
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||||
|
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
@@ -131,7 +131,9 @@ jobs:
|
|||||||
token: ${{ steps.token.outputs.token }}
|
token: ${{ steps.token.outputs.token }}
|
||||||
|
|
||||||
- name: Setup Mise
|
- name: Setup Mise
|
||||||
uses: immich-app/devtools/actions/use-mise@035e80a7d4355d5f087ffb95db9e4a0944c04e56 # use-mise-action-v1.1.3
|
uses: immich-app/devtools/actions/use-mise@cf6e190bacde3d7bda59372a786b36ac7d01536a # use-mise-action-v2.0.1
|
||||||
|
with:
|
||||||
|
github_token: ${{ steps.token.outputs.token }}
|
||||||
|
|
||||||
- name: Load parameters
|
- name: Load parameters
|
||||||
id: parameters
|
id: parameters
|
||||||
|
|||||||
@@ -17,9 +17,9 @@ jobs:
|
|||||||
pull-requests: write
|
pull-requests: write
|
||||||
steps:
|
steps:
|
||||||
- id: token
|
- id: token
|
||||||
uses: immich-app/devtools/actions/create-workflow-token@57ff6ebfd507b045514442683ff06ff1b2f6efbd # create-workflow-token-action-v1.0.2
|
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
|
||||||
with:
|
with:
|
||||||
app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }}
|
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||||
|
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
@@ -29,7 +29,9 @@ jobs:
|
|||||||
token: ${{ steps.token.outputs.token }}
|
token: ${{ steps.token.outputs.token }}
|
||||||
|
|
||||||
- name: Setup Mise
|
- name: Setup Mise
|
||||||
uses: immich-app/devtools/actions/use-mise@035e80a7d4355d5f087ffb95db9e4a0944c04e56 # use-mise-action-v1.1.3
|
uses: immich-app/devtools/actions/use-mise@cf6e190bacde3d7bda59372a786b36ac7d01536a # use-mise-action-v2.0.1
|
||||||
|
with:
|
||||||
|
github_token: ${{ steps.token.outputs.token }}
|
||||||
|
|
||||||
- name: Destroy Docs Subdomain
|
- name: Destroy Docs Subdomain
|
||||||
env:
|
env:
|
||||||
|
|||||||
@@ -14,29 +14,23 @@ jobs:
|
|||||||
contents: write
|
contents: write
|
||||||
pull-requests: write
|
pull-requests: write
|
||||||
steps:
|
steps:
|
||||||
- name: Generate a token
|
- id: token
|
||||||
id: generate-token
|
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
|
||||||
uses: actions/create-github-app-token@1b10c78c7865c340bc4f6099eb2f838309f1e8c3 # v3.1.1
|
|
||||||
with:
|
with:
|
||||||
app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }}
|
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||||
|
|
||||||
- name: 'Checkout'
|
- name: Checkout code
|
||||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||||
with:
|
with:
|
||||||
ref: ${{ github.event.pull_request.head.ref }}
|
ref: ${{ github.event.pull_request.head.ref }}
|
||||||
token: ${{ steps.generate-token.outputs.token }}
|
|
||||||
persist-credentials: true
|
persist-credentials: true
|
||||||
|
token: ${{ steps.token.outputs.token }}
|
||||||
|
|
||||||
- name: Setup pnpm
|
- name: Setup Mise
|
||||||
uses: pnpm/action-setup@08c4be7e2e672a47d11bd04269e27e5f3e8529cb # v6.0.0
|
uses: immich-app/devtools/actions/use-mise@cf6e190bacde3d7bda59372a786b36ac7d01536a # use-mise-action-v2.0.1
|
||||||
|
|
||||||
- name: Setup Node
|
|
||||||
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
|
|
||||||
with:
|
with:
|
||||||
node-version-file: './server/.nvmrc'
|
github_token: ${{ steps.token.outputs.token }}
|
||||||
cache: 'pnpm'
|
|
||||||
cache-dependency-path: '**/pnpm-lock.yaml'
|
|
||||||
|
|
||||||
- name: Fix formatting
|
- name: Fix formatting
|
||||||
run: pnpm --recursive install && pnpm run --recursive --if-present --parallel format:fix
|
run: pnpm --recursive install && pnpm run --recursive --if-present --parallel format:fix
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ on:
|
|||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
workflow_call:
|
workflow_call:
|
||||||
secrets:
|
secrets:
|
||||||
PUSH_O_MATIC_APP_ID:
|
PUSH_O_MATIC_APP_CLIENT_ID:
|
||||||
required: true
|
required: true
|
||||||
PUSH_O_MATIC_APP_KEY:
|
PUSH_O_MATIC_APP_KEY:
|
||||||
required: true
|
required: true
|
||||||
@@ -33,7 +33,7 @@ jobs:
|
|||||||
if: ${{ inputs.skip != true }}
|
if: ${{ inputs.skip != true }}
|
||||||
uses: actions/create-github-app-token@1b10c78c7865c340bc4f6099eb2f838309f1e8c3 # v3.1.1
|
uses: actions/create-github-app-token@1b10c78c7865c340bc4f6099eb2f838309f1e8c3 # v3.1.1
|
||||||
with:
|
with:
|
||||||
app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }}
|
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||||
|
|
||||||
- name: Find translation PR
|
- name: Find translation PR
|
||||||
|
|||||||
@@ -14,9 +14,9 @@ jobs:
|
|||||||
pull-requests: write
|
pull-requests: write
|
||||||
steps:
|
steps:
|
||||||
- id: token
|
- id: token
|
||||||
uses: immich-app/devtools/actions/create-workflow-token@57ff6ebfd507b045514442683ff06ff1b2f6efbd # create-workflow-token-action-v1.0.2
|
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
|
||||||
with:
|
with:
|
||||||
app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }}
|
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||||
|
|
||||||
- name: Require PR to have a changelog label
|
- name: Require PR to have a changelog label
|
||||||
|
|||||||
@@ -12,11 +12,11 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- id: token
|
- id: token
|
||||||
uses: immich-app/devtools/actions/create-workflow-token@57ff6ebfd507b045514442683ff06ff1b2f6efbd # create-workflow-token-action-v1.0.2
|
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
|
||||||
with:
|
with:
|
||||||
app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }}
|
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||||
|
|
||||||
- uses: actions/labeler@634933edcd8ababfe52f92936142cc22ac488b1b # v6.0.1
|
- uses: actions/labeler@f27b608878404679385c85cfa523b85ccb86e213 # v6.1.0
|
||||||
with:
|
with:
|
||||||
repo-token: ${{ steps.token.outputs.token }}
|
repo-token: ${{ steps.token.outputs.token }}
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ jobs:
|
|||||||
permissions:
|
permissions:
|
||||||
pull-requests: write
|
pull-requests: write
|
||||||
secrets:
|
secrets:
|
||||||
PUSH_O_MATIC_APP_ID: ${{ secrets.PUSH_O_MATIC_APP_ID }}
|
PUSH_O_MATIC_APP_CLIENT_ID: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||||
PUSH_O_MATIC_APP_KEY: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
PUSH_O_MATIC_APP_KEY: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||||
WEBLATE_TOKEN: ${{ secrets.WEBLATE_TOKEN }}
|
WEBLATE_TOKEN: ${{ secrets.WEBLATE_TOKEN }}
|
||||||
|
|
||||||
@@ -48,32 +48,27 @@ jobs:
|
|||||||
version: ${{ steps.output.outputs.version }}
|
version: ${{ steps.output.outputs.version }}
|
||||||
permissions: {} # No job-level permissions are needed because it uses the app-token
|
permissions: {} # No job-level permissions are needed because it uses the app-token
|
||||||
steps:
|
steps:
|
||||||
- name: Generate a token
|
- id: token
|
||||||
id: generate-token
|
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
|
||||||
uses: actions/create-github-app-token@1b10c78c7865c340bc4f6099eb2f838309f1e8c3 # v3.1.1
|
|
||||||
with:
|
with:
|
||||||
app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }}
|
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||||
|
|
||||||
- name: Checkout
|
- name: Checkout code
|
||||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||||
with:
|
with:
|
||||||
token: ${{ steps.generate-token.outputs.token }}
|
token: ${{ steps.token.outputs.token }}
|
||||||
persist-credentials: true
|
persist-credentials: true
|
||||||
ref: main
|
ref: main
|
||||||
|
|
||||||
- name: Install uv
|
- name: Setup Mise
|
||||||
uses: astral-sh/setup-uv@cec208311dfd045dd5311c1add060b2062131d57 # v8.0.0
|
uses: immich-app/devtools/actions/use-mise@cf6e190bacde3d7bda59372a786b36ac7d01536a # use-mise-action-v2.0.1
|
||||||
|
|
||||||
- name: Setup pnpm
|
|
||||||
uses: pnpm/action-setup@08c4be7e2e672a47d11bd04269e27e5f3e8529cb # v6.0.0
|
|
||||||
|
|
||||||
- name: Setup Node
|
|
||||||
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
|
|
||||||
with:
|
with:
|
||||||
node-version-file: './server/.nvmrc'
|
github_token: ${{ steps.token.outputs.token }}
|
||||||
cache: 'pnpm'
|
|
||||||
cache-dependency-path: '**/pnpm-lock.yaml'
|
# TODO move to mise
|
||||||
|
- name: Install uv
|
||||||
|
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
|
||||||
|
|
||||||
- name: Bump version
|
- name: Bump version
|
||||||
env:
|
env:
|
||||||
@@ -126,7 +121,7 @@ jobs:
|
|||||||
id: generate-token
|
id: generate-token
|
||||||
uses: actions/create-github-app-token@1b10c78c7865c340bc4f6099eb2f838309f1e8c3 # v3.1.1
|
uses: actions/create-github-app-token@1b10c78c7865c340bc4f6099eb2f838309f1e8c3 # v3.1.1
|
||||||
with:
|
with:
|
||||||
app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }}
|
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||||
|
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
|
|||||||
@@ -14,12 +14,12 @@ jobs:
|
|||||||
pull-requests: write
|
pull-requests: write
|
||||||
steps:
|
steps:
|
||||||
- id: token
|
- id: token
|
||||||
uses: immich-app/devtools/actions/create-workflow-token@57ff6ebfd507b045514442683ff06ff1b2f6efbd # create-workflow-token-action-v1.0.2
|
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
|
||||||
with:
|
with:
|
||||||
app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }}
|
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||||
|
|
||||||
- uses: mshick/add-pr-comment@64b8e914979889d746c99dea15a76e77ef64580a # v3.10.0
|
- uses: mshick/add-pr-comment@8e4927817251f1ff60c001f04568532b38e0b4a0 # v3.11.0
|
||||||
with:
|
with:
|
||||||
github-token: ${{ steps.token.outputs.token }}
|
github-token: ${{ steps.token.outputs.token }}
|
||||||
message-id: 'preview-status'
|
message-id: 'preview-status'
|
||||||
@@ -32,9 +32,9 @@ jobs:
|
|||||||
pull-requests: write
|
pull-requests: write
|
||||||
steps:
|
steps:
|
||||||
- id: token
|
- id: token
|
||||||
uses: immich-app/devtools/actions/create-workflow-token@57ff6ebfd507b045514442683ff06ff1b2f6efbd # create-workflow-token-action-v1.0.2
|
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
|
||||||
with:
|
with:
|
||||||
app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }}
|
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||||
|
|
||||||
- uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
- uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
||||||
@@ -48,14 +48,14 @@ jobs:
|
|||||||
name: 'preview'
|
name: 'preview'
|
||||||
})
|
})
|
||||||
|
|
||||||
- uses: mshick/add-pr-comment@64b8e914979889d746c99dea15a76e77ef64580a # v3.10.0
|
- uses: mshick/add-pr-comment@8e4927817251f1ff60c001f04568532b38e0b4a0 # v3.11.0
|
||||||
if: ${{ github.event.pull_request.head.repo.fork }}
|
if: ${{ github.event.pull_request.head.repo.fork }}
|
||||||
with:
|
with:
|
||||||
github-token: ${{ steps.token.outputs.token }}
|
github-token: ${{ steps.token.outputs.token }}
|
||||||
message-id: 'preview-status'
|
message-id: 'preview-status'
|
||||||
message: 'PRs from forks cannot have preview environments.'
|
message: 'PRs from forks cannot have preview environments.'
|
||||||
|
|
||||||
- uses: mshick/add-pr-comment@64b8e914979889d746c99dea15a76e77ef64580a # v3.10.0
|
- uses: mshick/add-pr-comment@8e4927817251f1ff60c001f04568532b38e0b4a0 # v3.11.0
|
||||||
if: ${{ !github.event.pull_request.head.repo.fork }}
|
if: ${{ !github.event.pull_request.head.repo.fork }}
|
||||||
with:
|
with:
|
||||||
github-token: ${{ steps.token.outputs.token }}
|
github-token: ${{ steps.token.outputs.token }}
|
||||||
|
|||||||
+13
-18
@@ -14,34 +14,29 @@ jobs:
|
|||||||
contents: read
|
contents: read
|
||||||
id-token: write
|
id-token: write
|
||||||
packages: write
|
packages: write
|
||||||
defaults:
|
|
||||||
run:
|
|
||||||
working-directory: ./open-api/typescript-sdk
|
|
||||||
steps:
|
steps:
|
||||||
- id: token
|
- id: token
|
||||||
uses: immich-app/devtools/actions/create-workflow-token@57ff6ebfd507b045514442683ff06ff1b2f6efbd # create-workflow-token-action-v1.0.2
|
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
|
||||||
with:
|
with:
|
||||||
app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }}
|
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||||
|
|
||||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||||
with:
|
with:
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
token: ${{ steps.token.outputs.token }}
|
token: ${{ steps.token.outputs.token }}
|
||||||
|
|
||||||
- name: Setup pnpm
|
- name: Setup Mise
|
||||||
uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v5.0.0
|
uses: immich-app/devtools/actions/use-mise@cf6e190bacde3d7bda59372a786b36ac7d01536a # use-mise-action-v2.0.1
|
||||||
|
|
||||||
# Setup .npmrc file to publish to npm
|
|
||||||
- uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
|
|
||||||
with:
|
with:
|
||||||
node-version-file: './open-api/typescript-sdk/.nvmrc'
|
github_token: ${{ steps.token.outputs.token }}
|
||||||
registry-url: 'https://registry.npmjs.org'
|
|
||||||
cache: 'pnpm'
|
|
||||||
cache-dependency-path: '**/pnpm-lock.yaml'
|
|
||||||
- name: Install deps
|
- name: Install deps
|
||||||
run: pnpm install --frozen-lockfile
|
run: pnpm --filter @immich/sdk install --frozen-lockfile
|
||||||
|
|
||||||
- name: Build
|
- name: Build
|
||||||
run: pnpm build
|
run: pnpm --filter @immich/sdk build
|
||||||
|
|
||||||
- name: Publish
|
- name: Publish
|
||||||
run: pnpm publish --provenance --no-git-checks
|
run: pnpm --filter @immich/sdk publish --provenance --no-git-checks
|
||||||
|
|||||||
@@ -20,14 +20,14 @@ jobs:
|
|||||||
should_run: ${{ steps.check.outputs.should_run }}
|
should_run: ${{ steps.check.outputs.should_run }}
|
||||||
steps:
|
steps:
|
||||||
- id: token
|
- id: token
|
||||||
uses: immich-app/devtools/actions/create-workflow-token@57ff6ebfd507b045514442683ff06ff1b2f6efbd # create-workflow-token-action-v1.0.2
|
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
|
||||||
with:
|
with:
|
||||||
app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }}
|
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||||
|
|
||||||
- name: Check what should run
|
- name: Check what should run
|
||||||
id: check
|
id: check
|
||||||
uses: immich-app/devtools/actions/pre-job@f50e3b600b6ac1763ddb8f3dfc69093512b967a1 # pre-job-action-v2.0.3
|
uses: immich-app/devtools/actions/pre-job@91f342bb4477c4bc10c576ae739da875d85aa164 # pre-job-action-v2.0.4
|
||||||
with:
|
with:
|
||||||
github-token: ${{ steps.token.outputs.token }}
|
github-token: ${{ steps.token.outputs.token }}
|
||||||
filters: |
|
filters: |
|
||||||
@@ -49,9 +49,9 @@ jobs:
|
|||||||
working-directory: ./mobile
|
working-directory: ./mobile
|
||||||
steps:
|
steps:
|
||||||
- id: token
|
- id: token
|
||||||
uses: immich-app/devtools/actions/create-workflow-token@57ff6ebfd507b045514442683ff06ff1b2f6efbd # create-workflow-token-action-v1.0.2
|
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
|
||||||
with:
|
with:
|
||||||
app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }}
|
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||||
|
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
@@ -60,38 +60,30 @@ jobs:
|
|||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
token: ${{ steps.token.outputs.token }}
|
token: ${{ steps.token.outputs.token }}
|
||||||
|
|
||||||
- name: Setup Flutter SDK
|
- name: Setup Mise
|
||||||
uses: subosito/flutter-action@1a449444c387b1966244ae4d4f8c696479add0b2 # v2.23.0
|
uses: immich-app/devtools/actions/use-mise@cf6e190bacde3d7bda59372a786b36ac7d01536a # use-mise-action-v2.0.1
|
||||||
with:
|
with:
|
||||||
channel: 'stable'
|
github_token: ${{ steps.token.outputs.token }}
|
||||||
flutter-version-file: ./mobile/pubspec.yaml
|
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: dart pub get
|
run: flutter pub get
|
||||||
|
|
||||||
- name: Install dependencies for UI package
|
- name: Install dependencies for UI package
|
||||||
run: dart pub get
|
run: flutter pub get
|
||||||
working-directory: ./mobile/packages/ui
|
working-directory: ./mobile/packages/ui
|
||||||
|
|
||||||
- name: Install dependencies for UI Showcase
|
- name: Install dependencies for UI Showcase
|
||||||
run: dart pub get
|
run: flutter pub get
|
||||||
working-directory: ./mobile/packages/ui/showcase
|
working-directory: ./mobile/packages/ui/showcase
|
||||||
|
|
||||||
- name: Install DCM
|
- name: Generate translation files
|
||||||
uses: CQLabs/setup-dcm@8697ae0790c0852e964a6ef1d768d62a6675481a # v2.0.1
|
run: mise //mobile:codegen:translation
|
||||||
with:
|
|
||||||
github-token: ${{ steps.token.outputs.token }}
|
|
||||||
version: auto
|
|
||||||
working-directory: ./mobile
|
|
||||||
|
|
||||||
- name: Generate translation file
|
|
||||||
run: dart run easy_localization:generate -S ../i18n && dart run bin/generate_keys.dart
|
|
||||||
|
|
||||||
- name: Run Build Runner
|
- name: Run Build Runner
|
||||||
run: make build
|
run: mise //mobile:codegen:dart
|
||||||
|
|
||||||
- name: Generate platform API
|
- name: Generate platform API
|
||||||
run: make pigeon
|
run: mise //mobile:codegen:pigeon
|
||||||
|
|
||||||
- name: Find file changes
|
- name: Find file changes
|
||||||
uses: tj-actions/verify-changed-files@a1c6acee9df209257a246f2cc6ae8cb6581c1edf # v20.0.4
|
uses: tj-actions/verify-changed-files@a1c6acee9df209257a246f2cc6ae8cb6581c1edf # v20.0.4
|
||||||
@@ -107,20 +99,16 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
CHANGED_FILES: ${{ steps.verify-changed-files.outputs.changed_files }}
|
CHANGED_FILES: ${{ steps.verify-changed-files.outputs.changed_files }}
|
||||||
run: |
|
run: |
|
||||||
echo "ERROR: Generated files not up to date! Run 'make build' and 'make pigeon' inside the mobile directory"
|
echo "ERROR: Generated files not up to date! Run 'mise //mobile:codegen:dart' and 'mise //mobile:codegen:pigeon'"
|
||||||
echo "Changed files: ${CHANGED_FILES}"
|
echo "Changed files: ${CHANGED_FILES}"
|
||||||
exit 1
|
exit 1
|
||||||
|
|
||||||
- name: Run dart analyze
|
- name: Run analyze
|
||||||
run: dart analyze --fatal-infos
|
run: mise //mobile:analyze
|
||||||
|
|
||||||
- name: Run dart format
|
- name: Run format
|
||||||
run: make format
|
run: mise //mobile:format
|
||||||
|
|
||||||
# TODO: Re-enable after upgrading custom_lint
|
# TODO: Re-enable after upgrading custom_lint
|
||||||
# - name: Run dart custom_lint
|
# - name: Run dart custom_lint
|
||||||
# run: dart run custom_lint
|
# run: dart run custom_lint
|
||||||
|
|
||||||
# TODO: Use https://github.com/CQLabs/dcm-action
|
|
||||||
- name: Run DCM
|
|
||||||
run: dcm analyze lib --fatal-style --fatal-warnings
|
|
||||||
|
|||||||
+207
-241
@@ -17,14 +17,14 @@ jobs:
|
|||||||
should_run: ${{ steps.check.outputs.should_run }}
|
should_run: ${{ steps.check.outputs.should_run }}
|
||||||
steps:
|
steps:
|
||||||
- id: token
|
- id: token
|
||||||
uses: immich-app/devtools/actions/create-workflow-token@57ff6ebfd507b045514442683ff06ff1b2f6efbd # create-workflow-token-action-v1.0.2
|
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
|
||||||
with:
|
with:
|
||||||
app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }}
|
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||||
|
|
||||||
- name: Check what should run
|
- name: Check what should run
|
||||||
id: check
|
id: check
|
||||||
uses: immich-app/devtools/actions/pre-job@f50e3b600b6ac1763ddb8f3dfc69093512b967a1 # pre-job-action-v2.0.3
|
uses: immich-app/devtools/actions/pre-job@91f342bb4477c4bc10c576ae739da875d85aa164 # pre-job-action-v2.0.4
|
||||||
with:
|
with:
|
||||||
github-token: ${{ steps.token.outputs.token }}
|
github-token: ${{ steps.token.outputs.token }}
|
||||||
filters: |
|
filters: |
|
||||||
@@ -33,14 +33,18 @@ jobs:
|
|||||||
web:
|
web:
|
||||||
- 'web/**'
|
- 'web/**'
|
||||||
- 'i18n/**'
|
- 'i18n/**'
|
||||||
- 'open-api/typescript-sdk/**'
|
- 'packages/sdk/**'
|
||||||
|
- 'pnpm-lock.yaml'
|
||||||
server:
|
server:
|
||||||
- 'server/**'
|
- 'server/**'
|
||||||
|
- 'pnpm-lock.yaml'
|
||||||
cli:
|
cli:
|
||||||
- 'cli/**'
|
- 'packages/cli/**'
|
||||||
- 'open-api/typescript-sdk/**'
|
- 'packages/sdk/**'
|
||||||
|
- 'pnpm-lock.yaml'
|
||||||
e2e:
|
e2e:
|
||||||
- 'e2e/**'
|
- 'e2e/**'
|
||||||
|
- 'pnpm-lock.yaml'
|
||||||
mobile:
|
mobile:
|
||||||
- 'mobile/**'
|
- 'mobile/**'
|
||||||
machine-learning:
|
machine-learning:
|
||||||
@@ -63,9 +67,9 @@ jobs:
|
|||||||
working-directory: ./server
|
working-directory: ./server
|
||||||
steps:
|
steps:
|
||||||
- id: token
|
- id: token
|
||||||
uses: immich-app/devtools/actions/create-workflow-token@57ff6ebfd507b045514442683ff06ff1b2f6efbd # create-workflow-token-action-v1.0.2
|
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
|
||||||
with:
|
with:
|
||||||
app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }}
|
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||||
|
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
@@ -74,28 +78,14 @@ jobs:
|
|||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
token: ${{ steps.token.outputs.token }}
|
token: ${{ steps.token.outputs.token }}
|
||||||
|
|
||||||
- name: Setup pnpm
|
- name: Setup Mise
|
||||||
uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v5.0.0
|
uses: immich-app/devtools/actions/use-mise@cf6e190bacde3d7bda59372a786b36ac7d01536a # use-mise-action-v2.0.1
|
||||||
- name: Setup Node
|
|
||||||
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
|
|
||||||
with:
|
with:
|
||||||
node-version-file: './server/.nvmrc'
|
github_token: ${{ steps.token.outputs.token }}
|
||||||
cache: 'pnpm'
|
|
||||||
cache-dependency-path: '**/pnpm-lock.yaml'
|
- name: Run ci-unit
|
||||||
- name: Run package manager install
|
run: mise run ci-unit
|
||||||
run: pnpm install
|
|
||||||
- name: Run linter
|
|
||||||
run: pnpm lint
|
|
||||||
if: ${{ !cancelled() }}
|
|
||||||
- name: Run formatter
|
|
||||||
run: pnpm format
|
|
||||||
if: ${{ !cancelled() }}
|
|
||||||
- name: Run tsc
|
|
||||||
run: pnpm check
|
|
||||||
if: ${{ !cancelled() }}
|
|
||||||
- name: Run small tests & coverage
|
|
||||||
run: pnpm test
|
|
||||||
if: ${{ !cancelled() }}
|
|
||||||
cli-unit-tests:
|
cli-unit-tests:
|
||||||
name: Unit Test CLI
|
name: Unit Test CLI
|
||||||
needs: pre-job
|
needs: pre-job
|
||||||
@@ -105,12 +95,12 @@ jobs:
|
|||||||
contents: read
|
contents: read
|
||||||
defaults:
|
defaults:
|
||||||
run:
|
run:
|
||||||
working-directory: ./cli
|
working-directory: ./packages/cli
|
||||||
steps:
|
steps:
|
||||||
- id: token
|
- id: token
|
||||||
uses: immich-app/devtools/actions/create-workflow-token@57ff6ebfd507b045514442683ff06ff1b2f6efbd # create-workflow-token-action-v1.0.2
|
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
|
||||||
with:
|
with:
|
||||||
app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }}
|
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||||
|
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
@@ -118,31 +108,15 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
token: ${{ steps.token.outputs.token }}
|
token: ${{ steps.token.outputs.token }}
|
||||||
- name: Setup pnpm
|
|
||||||
uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v5.0.0
|
- name: Setup Mise
|
||||||
- name: Setup Node
|
uses: immich-app/devtools/actions/use-mise@cf6e190bacde3d7bda59372a786b36ac7d01536a # use-mise-action-v2.0.1
|
||||||
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
|
|
||||||
with:
|
with:
|
||||||
node-version-file: './cli/.nvmrc'
|
github_token: ${{ steps.token.outputs.token }}
|
||||||
cache: 'pnpm'
|
|
||||||
cache-dependency-path: '**/pnpm-lock.yaml'
|
- name: Run ci-unit
|
||||||
- name: Setup typescript-sdk
|
run: mise run ci-unit
|
||||||
run: pnpm install && pnpm run build
|
|
||||||
working-directory: ./open-api/typescript-sdk
|
|
||||||
- name: Install deps
|
|
||||||
run: pnpm install
|
|
||||||
- name: Run linter
|
|
||||||
run: pnpm lint
|
|
||||||
if: ${{ !cancelled() }}
|
|
||||||
- name: Run formatter
|
|
||||||
run: pnpm format
|
|
||||||
if: ${{ !cancelled() }}
|
|
||||||
- name: Run tsc
|
|
||||||
run: pnpm check
|
|
||||||
if: ${{ !cancelled() }}
|
|
||||||
- name: Run unit tests & coverage
|
|
||||||
run: pnpm test
|
|
||||||
if: ${{ !cancelled() }}
|
|
||||||
cli-unit-tests-win:
|
cli-unit-tests-win:
|
||||||
name: Unit Test CLI (Windows)
|
name: Unit Test CLI (Windows)
|
||||||
needs: pre-job
|
needs: pre-job
|
||||||
@@ -152,12 +126,12 @@ jobs:
|
|||||||
contents: read
|
contents: read
|
||||||
defaults:
|
defaults:
|
||||||
run:
|
run:
|
||||||
working-directory: ./cli
|
working-directory: ./packages/cli
|
||||||
steps:
|
steps:
|
||||||
- id: token
|
- id: token
|
||||||
uses: immich-app/devtools/actions/create-workflow-token@57ff6ebfd507b045514442683ff06ff1b2f6efbd # create-workflow-token-action-v1.0.2
|
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
|
||||||
with:
|
with:
|
||||||
app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }}
|
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||||
|
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
@@ -165,26 +139,28 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
token: ${{ steps.token.outputs.token }}
|
token: ${{ steps.token.outputs.token }}
|
||||||
- name: Setup pnpm
|
|
||||||
uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v5.0.0
|
- name: Setup Mise
|
||||||
- name: Setup Node
|
uses: immich-app/devtools/actions/use-mise@cf6e190bacde3d7bda59372a786b36ac7d01536a # use-mise-action-v2.0.1
|
||||||
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
|
|
||||||
with:
|
with:
|
||||||
node-version-file: './cli/.nvmrc'
|
github_token: ${{ steps.token.outputs.token }}
|
||||||
cache: 'pnpm'
|
|
||||||
cache-dependency-path: '**/pnpm-lock.yaml'
|
- name: Run setup @immich/sdk
|
||||||
- name: Setup typescript-sdk
|
run: mise run //:sdk:install && mise run //:sdk:build
|
||||||
run: pnpm install --frozen-lockfile && pnpm build
|
|
||||||
working-directory: ./open-api/typescript-sdk
|
- name: Run pnpm install
|
||||||
- name: Install deps
|
|
||||||
run: pnpm install --frozen-lockfile
|
run: pnpm install --frozen-lockfile
|
||||||
|
|
||||||
# Skip linter & formatter in Windows test.
|
# Skip linter & formatter in Windows test.
|
||||||
|
|
||||||
- name: Run tsc
|
- name: Run tsc
|
||||||
run: pnpm check
|
run: pnpm check
|
||||||
if: ${{ !cancelled() }}
|
if: ${{ !cancelled() }}
|
||||||
|
|
||||||
- name: Run unit tests & coverage
|
- name: Run unit tests & coverage
|
||||||
run: pnpm test
|
run: pnpm test
|
||||||
if: ${{ !cancelled() }}
|
if: ${{ !cancelled() }}
|
||||||
|
|
||||||
web-lint:
|
web-lint:
|
||||||
name: Lint Web
|
name: Lint Web
|
||||||
needs: pre-job
|
needs: pre-job
|
||||||
@@ -197,9 +173,9 @@ jobs:
|
|||||||
working-directory: ./web
|
working-directory: ./web
|
||||||
steps:
|
steps:
|
||||||
- id: token
|
- id: token
|
||||||
uses: immich-app/devtools/actions/create-workflow-token@57ff6ebfd507b045514442683ff06ff1b2f6efbd # create-workflow-token-action-v1.0.2
|
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
|
||||||
with:
|
with:
|
||||||
app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }}
|
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||||
|
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
@@ -207,28 +183,22 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
token: ${{ steps.token.outputs.token }}
|
token: ${{ steps.token.outputs.token }}
|
||||||
- name: Setup pnpm
|
|
||||||
uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v5.0.0
|
- name: Setup Mise
|
||||||
- name: Setup Node
|
uses: immich-app/devtools/actions/use-mise@cf6e190bacde3d7bda59372a786b36ac7d01536a # use-mise-action-v2.0.1
|
||||||
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
|
|
||||||
with:
|
with:
|
||||||
node-version-file: './web/.nvmrc'
|
github_token: ${{ steps.token.outputs.token }}
|
||||||
cache: 'pnpm'
|
|
||||||
cache-dependency-path: '**/pnpm-lock.yaml'
|
- name: Run setup @immich/sdk
|
||||||
- name: Run setup typescript-sdk
|
run: mise run //:sdk:install && mise run //:sdk:build
|
||||||
run: pnpm install --frozen-lockfile && pnpm build
|
|
||||||
working-directory: ./open-api/typescript-sdk
|
|
||||||
- name: Run pnpm install
|
- name: Run pnpm install
|
||||||
run: pnpm rebuild && pnpm install --frozen-lockfile
|
run: pnpm install --frozen-lockfile
|
||||||
|
|
||||||
- name: Run linter
|
- name: Run linter
|
||||||
run: pnpm lint
|
run: pnpm lint
|
||||||
if: ${{ !cancelled() }}
|
if: ${{ !cancelled() }}
|
||||||
- name: Run formatter
|
|
||||||
run: pnpm format
|
|
||||||
if: ${{ !cancelled() }}
|
|
||||||
- name: Run svelte checks
|
|
||||||
run: pnpm check:svelte
|
|
||||||
if: ${{ !cancelled() }}
|
|
||||||
web-unit-tests:
|
web-unit-tests:
|
||||||
name: Test Web
|
name: Test Web
|
||||||
needs: pre-job
|
needs: pre-job
|
||||||
@@ -241,9 +211,9 @@ jobs:
|
|||||||
working-directory: ./web
|
working-directory: ./web
|
||||||
steps:
|
steps:
|
||||||
- id: token
|
- id: token
|
||||||
uses: immich-app/devtools/actions/create-workflow-token@57ff6ebfd507b045514442683ff06ff1b2f6efbd # create-workflow-token-action-v1.0.2
|
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
|
||||||
with:
|
with:
|
||||||
app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }}
|
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||||
|
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
@@ -251,25 +221,15 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
token: ${{ steps.token.outputs.token }}
|
token: ${{ steps.token.outputs.token }}
|
||||||
- name: Setup pnpm
|
|
||||||
uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v5.0.0
|
- name: Setup Mise
|
||||||
- name: Setup Node
|
uses: immich-app/devtools/actions/use-mise@cf6e190bacde3d7bda59372a786b36ac7d01536a # use-mise-action-v2.0.1
|
||||||
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
|
|
||||||
with:
|
with:
|
||||||
node-version-file: './web/.nvmrc'
|
github_token: ${{ steps.token.outputs.token }}
|
||||||
cache: 'pnpm'
|
|
||||||
cache-dependency-path: '**/pnpm-lock.yaml'
|
- name: Run ci-unit
|
||||||
- name: Run setup typescript-sdk
|
run: mise run ci-unit
|
||||||
run: pnpm install --frozen-lockfile && pnpm build
|
|
||||||
working-directory: ./open-api/typescript-sdk
|
|
||||||
- name: Run npm install
|
|
||||||
run: pnpm install --frozen-lockfile
|
|
||||||
- name: Run tsc
|
|
||||||
run: pnpm check:typescript
|
|
||||||
if: ${{ !cancelled() }}
|
|
||||||
- name: Run unit tests & coverage
|
|
||||||
run: pnpm test
|
|
||||||
if: ${{ !cancelled() }}
|
|
||||||
i18n-tests:
|
i18n-tests:
|
||||||
name: Test i18n
|
name: Test i18n
|
||||||
needs: pre-job
|
needs: pre-job
|
||||||
@@ -279,9 +239,9 @@ jobs:
|
|||||||
contents: read
|
contents: read
|
||||||
steps:
|
steps:
|
||||||
- id: token
|
- id: token
|
||||||
uses: immich-app/devtools/actions/create-workflow-token@57ff6ebfd507b045514442683ff06ff1b2f6efbd # create-workflow-token-action-v1.0.2
|
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
|
||||||
with:
|
with:
|
||||||
app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }}
|
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||||
|
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
@@ -289,24 +249,25 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
token: ${{ steps.token.outputs.token }}
|
token: ${{ steps.token.outputs.token }}
|
||||||
- name: Setup pnpm
|
|
||||||
uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v5.0.0
|
- name: Setup Mise
|
||||||
- name: Setup Node
|
uses: immich-app/devtools/actions/use-mise@cf6e190bacde3d7bda59372a786b36ac7d01536a # use-mise-action-v2.0.1
|
||||||
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
|
|
||||||
with:
|
with:
|
||||||
node-version-file: './web/.nvmrc'
|
github_token: ${{ steps.token.outputs.token }}
|
||||||
cache: 'pnpm'
|
|
||||||
cache-dependency-path: '**/pnpm-lock.yaml'
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: pnpm --filter=immich-i18n install --frozen-lockfile
|
run: pnpm -w install --frozen-lockfile
|
||||||
|
|
||||||
- name: Format
|
- name: Format
|
||||||
run: pnpm --filter=immich-i18n format:fix
|
run: pnpm format:fix
|
||||||
|
|
||||||
- name: Find file changes
|
- name: Find file changes
|
||||||
uses: tj-actions/verify-changed-files@a1c6acee9df209257a246f2cc6ae8cb6581c1edf # v20.0.4
|
uses: tj-actions/verify-changed-files@a1c6acee9df209257a246f2cc6ae8cb6581c1edf # v20.0.4
|
||||||
id: verify-changed-files
|
id: verify-changed-files
|
||||||
with:
|
with:
|
||||||
files: |
|
files: |
|
||||||
i18n/**
|
i18n/**
|
||||||
|
|
||||||
- name: Verify files have not changed
|
- name: Verify files have not changed
|
||||||
if: steps.verify-changed-files.outputs.files_changed == 'true'
|
if: steps.verify-changed-files.outputs.files_changed == 'true'
|
||||||
env:
|
env:
|
||||||
@@ -315,6 +276,7 @@ jobs:
|
|||||||
echo "ERROR: i18n files not up to date!"
|
echo "ERROR: i18n files not up to date!"
|
||||||
echo "Changed files: ${CHANGED_FILES}"
|
echo "Changed files: ${CHANGED_FILES}"
|
||||||
exit 1
|
exit 1
|
||||||
|
|
||||||
e2e-tests-lint:
|
e2e-tests-lint:
|
||||||
name: End-to-End Lint
|
name: End-to-End Lint
|
||||||
needs: pre-job
|
needs: pre-job
|
||||||
@@ -327,9 +289,9 @@ jobs:
|
|||||||
working-directory: ./e2e
|
working-directory: ./e2e
|
||||||
steps:
|
steps:
|
||||||
- id: token
|
- id: token
|
||||||
uses: immich-app/devtools/actions/create-workflow-token@57ff6ebfd507b045514442683ff06ff1b2f6efbd # create-workflow-token-action-v1.0.2
|
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
|
||||||
with:
|
with:
|
||||||
app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }}
|
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||||
|
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
@@ -337,30 +299,16 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
token: ${{ steps.token.outputs.token }}
|
token: ${{ steps.token.outputs.token }}
|
||||||
- name: Setup pnpm
|
|
||||||
uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v5.0.0
|
- name: Setup Mise
|
||||||
- name: Setup Node
|
uses: immich-app/devtools/actions/use-mise@cf6e190bacde3d7bda59372a786b36ac7d01536a # use-mise-action-v2.0.1
|
||||||
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
|
|
||||||
with:
|
with:
|
||||||
node-version-file: './e2e/.nvmrc'
|
github_token: ${{ steps.token.outputs.token }}
|
||||||
cache: 'pnpm'
|
|
||||||
cache-dependency-path: '**/pnpm-lock.yaml'
|
- name: Run ci-unit
|
||||||
- name: Run setup typescript-sdk
|
run: mise run ci-unit
|
||||||
run: pnpm install --frozen-lockfile && pnpm build
|
|
||||||
working-directory: ./open-api/typescript-sdk
|
|
||||||
if: ${{ !cancelled() }}
|
|
||||||
- name: Install dependencies
|
|
||||||
run: pnpm install --frozen-lockfile
|
|
||||||
if: ${{ !cancelled() }}
|
|
||||||
- name: Run linter
|
|
||||||
run: pnpm lint
|
|
||||||
if: ${{ !cancelled() }}
|
|
||||||
- name: Run formatter
|
|
||||||
run: pnpm format
|
|
||||||
if: ${{ !cancelled() }}
|
|
||||||
- name: Run tsc
|
|
||||||
run: pnpm check
|
|
||||||
if: ${{ !cancelled() }}
|
if: ${{ !cancelled() }}
|
||||||
|
|
||||||
server-medium-tests:
|
server-medium-tests:
|
||||||
name: Medium Tests (Server)
|
name: Medium Tests (Server)
|
||||||
needs: pre-job
|
needs: pre-job
|
||||||
@@ -373,9 +321,9 @@ jobs:
|
|||||||
working-directory: ./server
|
working-directory: ./server
|
||||||
steps:
|
steps:
|
||||||
- id: token
|
- id: token
|
||||||
uses: immich-app/devtools/actions/create-workflow-token@57ff6ebfd507b045514442683ff06ff1b2f6efbd # create-workflow-token-action-v1.0.2
|
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
|
||||||
with:
|
with:
|
||||||
app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }}
|
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||||
|
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
@@ -384,19 +332,16 @@ jobs:
|
|||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
submodules: 'recursive'
|
submodules: 'recursive'
|
||||||
token: ${{ steps.token.outputs.token }}
|
token: ${{ steps.token.outputs.token }}
|
||||||
- name: Setup pnpm
|
|
||||||
uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v5.0.0
|
- name: Setup Mise
|
||||||
- name: Setup Node
|
uses: immich-app/devtools/actions/use-mise@cf6e190bacde3d7bda59372a786b36ac7d01536a # use-mise-action-v2.0.1
|
||||||
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
|
|
||||||
with:
|
with:
|
||||||
node-version-file: './server/.nvmrc'
|
github_token: ${{ steps.token.outputs.token }}
|
||||||
cache: 'pnpm'
|
|
||||||
cache-dependency-path: '**/pnpm-lock.yaml'
|
- name: Run ci-medium
|
||||||
- name: Run pnpm install
|
run: mise run ci-medium
|
||||||
run: SHARP_IGNORE_GLOBAL_LIBVIPS=true pnpm install --frozen-lockfile
|
|
||||||
- name: Run medium tests
|
|
||||||
run: pnpm test:medium
|
|
||||||
if: ${{ !cancelled() }}
|
if: ${{ !cancelled() }}
|
||||||
|
|
||||||
e2e-tests-server-cli:
|
e2e-tests-server-cli:
|
||||||
name: End-to-End Tests (Server & CLI)
|
name: End-to-End Tests (Server & CLI)
|
||||||
needs: pre-job
|
needs: pre-job
|
||||||
@@ -412,9 +357,9 @@ jobs:
|
|||||||
runner: [ubuntu-latest, ubuntu-24.04-arm]
|
runner: [ubuntu-latest, ubuntu-24.04-arm]
|
||||||
steps:
|
steps:
|
||||||
- id: token
|
- id: token
|
||||||
uses: immich-app/devtools/actions/create-workflow-token@57ff6ebfd507b045514442683ff06ff1b2f6efbd # create-workflow-token-action-v1.0.2
|
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
|
||||||
with:
|
with:
|
||||||
app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }}
|
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||||
|
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
@@ -423,52 +368,57 @@ jobs:
|
|||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
submodules: 'recursive'
|
submodules: 'recursive'
|
||||||
token: ${{ steps.token.outputs.token }}
|
token: ${{ steps.token.outputs.token }}
|
||||||
|
|
||||||
- name: Setup pnpm
|
- name: Setup pnpm
|
||||||
uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v5.0.0
|
uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v5.0.0
|
||||||
|
|
||||||
- name: Setup Node
|
- name: Setup Node
|
||||||
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
|
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
|
||||||
with:
|
with:
|
||||||
node-version-file: './e2e/.nvmrc'
|
node-version-file: '.nvmrc'
|
||||||
cache: 'pnpm'
|
cache: 'pnpm'
|
||||||
cache-dependency-path: '**/pnpm-lock.yaml'
|
cache-dependency-path: '**/pnpm-lock.yaml'
|
||||||
- name: Run setup typescript-sdk
|
|
||||||
run: pnpm install --frozen-lockfile && pnpm build
|
- name: Setup packages
|
||||||
working-directory: ./open-api/typescript-sdk
|
run: pnpm --filter "@immich/*" install --frozen-lockfile && pnpm --filter "@immich/*" build
|
||||||
if: ${{ !cancelled() }}
|
|
||||||
- name: Run setup web
|
- name: Run setup web
|
||||||
run: pnpm install --frozen-lockfile && pnpm exec svelte-kit sync
|
run: pnpm install --frozen-lockfile && pnpm exec svelte-kit sync
|
||||||
working-directory: ./web
|
working-directory: ./web
|
||||||
if: ${{ !cancelled() }}
|
if: ${{ !cancelled() }}
|
||||||
- name: Run setup cli
|
|
||||||
run: pnpm install --frozen-lockfile && pnpm build
|
|
||||||
working-directory: ./cli
|
|
||||||
if: ${{ !cancelled() }}
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: pnpm install --frozen-lockfile
|
run: pnpm install --frozen-lockfile
|
||||||
if: ${{ !cancelled() }}
|
if: ${{ !cancelled() }}
|
||||||
|
|
||||||
- name: Start Docker Compose
|
- name: Start Docker Compose
|
||||||
run: docker compose up -d --build --renew-anon-volumes --force-recreate --remove-orphans --wait --wait-timeout 300
|
run: docker compose up -d --build --renew-anon-volumes --force-recreate --remove-orphans --wait --wait-timeout 300
|
||||||
if: ${{ !cancelled() }}
|
if: ${{ !cancelled() }}
|
||||||
|
|
||||||
- name: Run e2e tests (api & cli)
|
- name: Run e2e tests (api & cli)
|
||||||
env:
|
env:
|
||||||
VITEST_DISABLE_DOCKER_SETUP: true
|
VITEST_DISABLE_DOCKER_SETUP: true
|
||||||
run: pnpm test
|
run: pnpm test
|
||||||
if: ${{ !cancelled() }}
|
if: ${{ !cancelled() }}
|
||||||
|
|
||||||
- name: Run e2e tests (maintenance)
|
- name: Run e2e tests (maintenance)
|
||||||
env:
|
env:
|
||||||
VITEST_DISABLE_DOCKER_SETUP: true
|
VITEST_DISABLE_DOCKER_SETUP: true
|
||||||
run: pnpm test:maintenance
|
run: pnpm test:maintenance
|
||||||
if: ${{ !cancelled() }}
|
if: ${{ !cancelled() }}
|
||||||
|
|
||||||
- name: Capture Docker logs
|
- name: Capture Docker logs
|
||||||
if: always()
|
if: always()
|
||||||
run: docker compose logs --no-color > docker-compose-logs.txt
|
run: docker compose logs --no-color > docker-compose-logs.txt
|
||||||
working-directory: ./e2e
|
working-directory: ./e2e
|
||||||
|
|
||||||
- name: Archive Docker logs
|
- name: Archive Docker logs
|
||||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||||
if: always()
|
if: always()
|
||||||
with:
|
with:
|
||||||
name: e2e-server-docker-logs-${{ matrix.runner }}
|
name: e2e-server-docker-logs-${{ matrix.runner }}
|
||||||
path: e2e/docker-compose-logs.txt
|
path: e2e/docker-compose-logs.txt
|
||||||
|
|
||||||
e2e-tests-web:
|
e2e-tests-web:
|
||||||
name: End-to-End Tests (Web)
|
name: End-to-End Tests (Web)
|
||||||
needs: pre-job
|
needs: pre-job
|
||||||
@@ -484,9 +434,9 @@ jobs:
|
|||||||
runner: [ubuntu-latest, ubuntu-24.04-arm]
|
runner: [ubuntu-latest, ubuntu-24.04-arm]
|
||||||
steps:
|
steps:
|
||||||
- id: token
|
- id: token
|
||||||
uses: immich-app/devtools/actions/create-workflow-token@57ff6ebfd507b045514442683ff06ff1b2f6efbd # create-workflow-token-action-v1.0.2
|
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
|
||||||
with:
|
with:
|
||||||
app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }}
|
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||||
|
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
@@ -495,70 +445,84 @@ jobs:
|
|||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
submodules: 'recursive'
|
submodules: 'recursive'
|
||||||
token: ${{ steps.token.outputs.token }}
|
token: ${{ steps.token.outputs.token }}
|
||||||
|
|
||||||
- name: Setup pnpm
|
- name: Setup pnpm
|
||||||
uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v5.0.0
|
uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v5.0.0
|
||||||
|
|
||||||
- name: Setup Node
|
- name: Setup Node
|
||||||
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
|
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
|
||||||
with:
|
with:
|
||||||
node-version-file: './e2e/.nvmrc'
|
node-version-file: '.nvmrc'
|
||||||
cache: 'pnpm'
|
cache: 'pnpm'
|
||||||
cache-dependency-path: '**/pnpm-lock.yaml'
|
cache-dependency-path: '**/pnpm-lock.yaml'
|
||||||
- name: Run setup typescript-sdk
|
|
||||||
run: pnpm install --frozen-lockfile && pnpm build
|
- name: Run setup @immich/sdk
|
||||||
working-directory: ./open-api/typescript-sdk
|
run: pnpm --filter @immich/sdk install --frozen-lockfile && pnpm --filter @immich/sdk build
|
||||||
|
|
||||||
if: ${{ !cancelled() }}
|
if: ${{ !cancelled() }}
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: pnpm install --frozen-lockfile
|
run: pnpm install --frozen-lockfile
|
||||||
if: ${{ !cancelled() }}
|
if: ${{ !cancelled() }}
|
||||||
|
|
||||||
- name: Install Playwright Browsers
|
- name: Install Playwright Browsers
|
||||||
run: pnpm exec playwright install chromium --only-shell
|
run: pnpm exec playwright install chromium --only-shell
|
||||||
if: ${{ !cancelled() }}
|
if: ${{ !cancelled() }}
|
||||||
|
|
||||||
- name: Docker build
|
- name: Docker build
|
||||||
run: docker compose up -d --build --renew-anon-volumes --force-recreate --remove-orphans --wait --wait-timeout 300
|
run: docker compose up -d --build --renew-anon-volumes --force-recreate --remove-orphans --wait --wait-timeout 300
|
||||||
if: ${{ !cancelled() }}
|
if: ${{ !cancelled() }}
|
||||||
|
|
||||||
- name: Run e2e tests (web)
|
- name: Run e2e tests (web)
|
||||||
env:
|
env:
|
||||||
PLAYWRIGHT_DISABLE_WEBSERVER: true
|
PLAYWRIGHT_DISABLE_WEBSERVER: true
|
||||||
run: pnpm test:web
|
run: pnpm test:web
|
||||||
if: ${{ !cancelled() }}
|
if: ${{ !cancelled() }}
|
||||||
|
|
||||||
- name: Archive e2e test (web) results
|
- name: Archive e2e test (web) results
|
||||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||||
if: success() || failure()
|
if: success() || failure()
|
||||||
with:
|
with:
|
||||||
name: e2e-web-test-results-${{ matrix.runner }}
|
name: e2e-web-test-results-${{ matrix.runner }}
|
||||||
path: e2e/playwright-report/
|
path: e2e/playwright-report/
|
||||||
|
|
||||||
- name: Run ui tests (web)
|
- name: Run ui tests (web)
|
||||||
env:
|
env:
|
||||||
PLAYWRIGHT_DISABLE_WEBSERVER: true
|
PLAYWRIGHT_DISABLE_WEBSERVER: true
|
||||||
run: pnpm test:web:ui
|
run: pnpm test:web:ui
|
||||||
if: ${{ !cancelled() }}
|
if: ${{ !cancelled() }}
|
||||||
|
|
||||||
- name: Archive ui test (web) results
|
- name: Archive ui test (web) results
|
||||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||||
if: success() || failure()
|
if: success() || failure()
|
||||||
with:
|
with:
|
||||||
name: e2e-ui-test-results-${{ matrix.runner }}
|
name: e2e-ui-test-results-${{ matrix.runner }}
|
||||||
path: e2e/playwright-report/
|
path: e2e/playwright-report/
|
||||||
|
|
||||||
- name: Run maintenance tests
|
- name: Run maintenance tests
|
||||||
env:
|
env:
|
||||||
PLAYWRIGHT_DISABLE_WEBSERVER: true
|
PLAYWRIGHT_DISABLE_WEBSERVER: true
|
||||||
run: pnpm test:web:maintenance
|
run: pnpm test:web:maintenance
|
||||||
if: ${{ !cancelled() }}
|
if: ${{ !cancelled() }}
|
||||||
|
|
||||||
- name: Archive maintenance tests (web) results
|
- name: Archive maintenance tests (web) results
|
||||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||||
if: success() || failure()
|
if: success() || failure()
|
||||||
with:
|
with:
|
||||||
name: e2e-maintenance-isolated-test-results-${{ matrix.runner }}
|
name: e2e-maintenance-isolated-test-results-${{ matrix.runner }}
|
||||||
path: e2e/playwright-report/
|
path: e2e/playwright-report/
|
||||||
|
|
||||||
- name: Capture Docker logs
|
- name: Capture Docker logs
|
||||||
if: always()
|
if: always()
|
||||||
run: docker compose logs --no-color > docker-compose-logs.txt
|
run: docker compose logs --no-color > docker-compose-logs.txt
|
||||||
working-directory: ./e2e
|
working-directory: ./e2e
|
||||||
|
|
||||||
- name: Archive Docker logs
|
- name: Archive Docker logs
|
||||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||||
if: always()
|
if: always()
|
||||||
with:
|
with:
|
||||||
name: e2e-web-docker-logs-${{ matrix.runner }}
|
name: e2e-web-docker-logs-${{ matrix.runner }}
|
||||||
path: e2e/docker-compose-logs.txt
|
path: e2e/docker-compose-logs.txt
|
||||||
|
|
||||||
success-check-e2e:
|
success-check-e2e:
|
||||||
name: End-to-End Tests Success
|
name: End-to-End Tests Success
|
||||||
needs: [e2e-tests-server-cli, e2e-tests-web]
|
needs: [e2e-tests-server-cli, e2e-tests-web]
|
||||||
@@ -566,7 +530,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
if: always()
|
if: always()
|
||||||
steps:
|
steps:
|
||||||
- uses: immich-app/devtools/actions/success-check@53bb77345ee9f953f93bd6fd9980f07a2f24965e # success-check-action-v0.0.5
|
- uses: immich-app/devtools/actions/success-check@81113db03f6d743efee81e0058c0b43f6cd6f36d # success-check-action-v0.0.6
|
||||||
with:
|
with:
|
||||||
needs: ${{ toJSON(needs) }}
|
needs: ${{ toJSON(needs) }}
|
||||||
mobile-unit-tests:
|
mobile-unit-tests:
|
||||||
@@ -578,26 +542,31 @@ jobs:
|
|||||||
contents: read
|
contents: read
|
||||||
steps:
|
steps:
|
||||||
- id: token
|
- id: token
|
||||||
uses: immich-app/devtools/actions/create-workflow-token@57ff6ebfd507b045514442683ff06ff1b2f6efbd # create-workflow-token-action-v1.0.2
|
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
|
||||||
with:
|
with:
|
||||||
app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }}
|
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||||
|
|
||||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||||
with:
|
with:
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
token: ${{ steps.token.outputs.token }}
|
token: ${{ steps.token.outputs.token }}
|
||||||
- name: Setup Flutter SDK
|
|
||||||
uses: subosito/flutter-action@1a449444c387b1966244ae4d4f8c696479add0b2 # v2.23.0
|
- name: Setup Mise
|
||||||
|
uses: immich-app/devtools/actions/use-mise@cf6e190bacde3d7bda59372a786b36ac7d01536a # use-mise-action-v2.0.1
|
||||||
with:
|
with:
|
||||||
channel: 'stable'
|
github_token: ${{ steps.token.outputs.token }}
|
||||||
flutter-version-file: ./mobile/pubspec.yaml
|
|
||||||
- name: Generate translation file
|
- name: Install dependencies
|
||||||
run: dart run easy_localization:generate -S ../i18n && dart run bin/generate_keys.dart
|
run: flutter pub get
|
||||||
working-directory: ./mobile
|
working-directory: ./mobile
|
||||||
|
|
||||||
|
- name: Generate translation files
|
||||||
|
run: mise //mobile:codegen:translation
|
||||||
|
|
||||||
- name: Run tests
|
- name: Run tests
|
||||||
working-directory: ./mobile
|
run: mise //mobile:test
|
||||||
run: flutter test -j 1
|
|
||||||
ml-unit-tests:
|
ml-unit-tests:
|
||||||
name: Unit Test ML
|
name: Unit Test ML
|
||||||
needs: pre-job
|
needs: pre-job
|
||||||
@@ -610,34 +579,24 @@ jobs:
|
|||||||
working-directory: ./machine-learning
|
working-directory: ./machine-learning
|
||||||
steps:
|
steps:
|
||||||
- id: token
|
- id: token
|
||||||
uses: immich-app/devtools/actions/create-workflow-token@57ff6ebfd507b045514442683ff06ff1b2f6efbd # create-workflow-token-action-v1.0.2
|
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
|
||||||
with:
|
with:
|
||||||
app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }}
|
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||||
|
|
||||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||||
with:
|
with:
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
token: ${{ steps.token.outputs.token }}
|
token: ${{ steps.token.outputs.token }}
|
||||||
- name: Install uv
|
|
||||||
uses: astral-sh/setup-uv@cec208311dfd045dd5311c1add060b2062131d57 # v8.0.0
|
- name: Setup Mise
|
||||||
|
uses: immich-app/devtools/actions/use-mise@cf6e190bacde3d7bda59372a786b36ac7d01536a # use-mise-action-v2.0.1
|
||||||
with:
|
with:
|
||||||
python-version: 3.11
|
github_token: ${{ steps.token.outputs.token }}
|
||||||
- name: Install dependencies
|
|
||||||
run: |
|
- name: Run ci-unit
|
||||||
uv sync --extra cpu
|
run: mise run ci-unit
|
||||||
- name: Lint with ruff
|
|
||||||
run: |
|
|
||||||
uv run ruff check --output-format=github immich_ml
|
|
||||||
- name: Format with ruff
|
|
||||||
run: |
|
|
||||||
uv run ruff format --check immich_ml
|
|
||||||
- name: Run mypy type checking
|
|
||||||
run: |
|
|
||||||
uv run mypy --strict immich_ml/
|
|
||||||
- name: Run tests and coverage
|
|
||||||
run: |
|
|
||||||
uv run pytest --cov=immich_ml --cov-report term-missing
|
|
||||||
github-files-formatting:
|
github-files-formatting:
|
||||||
name: .github Files Formatting
|
name: .github Files Formatting
|
||||||
needs: pre-job
|
needs: pre-job
|
||||||
@@ -650,9 +609,9 @@ jobs:
|
|||||||
working-directory: ./.github
|
working-directory: ./.github
|
||||||
steps:
|
steps:
|
||||||
- id: token
|
- id: token
|
||||||
uses: immich-app/devtools/actions/create-workflow-token@57ff6ebfd507b045514442683ff06ff1b2f6efbd # create-workflow-token-action-v1.0.2
|
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
|
||||||
with:
|
with:
|
||||||
app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }}
|
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||||
|
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
@@ -660,19 +619,19 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
token: ${{ steps.token.outputs.token }}
|
token: ${{ steps.token.outputs.token }}
|
||||||
- name: Setup pnpm
|
|
||||||
uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v5.0.0
|
- name: Setup Mise
|
||||||
- name: Setup Node
|
uses: immich-app/devtools/actions/use-mise@cf6e190bacde3d7bda59372a786b36ac7d01536a # use-mise-action-v2.0.1
|
||||||
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
|
|
||||||
with:
|
with:
|
||||||
node-version-file: './.github/.nvmrc'
|
github_token: ${{ steps.token.outputs.token }}
|
||||||
cache: 'pnpm'
|
|
||||||
cache-dependency-path: '**/pnpm-lock.yaml'
|
|
||||||
- name: Run pnpm install
|
- name: Run pnpm install
|
||||||
run: pnpm install --frozen-lockfile
|
run: pnpm install --frozen-lockfile
|
||||||
|
|
||||||
- name: Run formatter
|
- name: Run formatter
|
||||||
run: pnpm format
|
run: pnpm format
|
||||||
if: ${{ !cancelled() }}
|
if: ${{ !cancelled() }}
|
||||||
|
|
||||||
shellcheck:
|
shellcheck:
|
||||||
name: ShellCheck
|
name: ShellCheck
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
@@ -680,9 +639,9 @@ jobs:
|
|||||||
contents: read
|
contents: read
|
||||||
steps:
|
steps:
|
||||||
- id: token
|
- id: token
|
||||||
uses: immich-app/devtools/actions/create-workflow-token@57ff6ebfd507b045514442683ff06ff1b2f6efbd # create-workflow-token-action-v1.0.2
|
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
|
||||||
with:
|
with:
|
||||||
app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }}
|
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||||
|
|
||||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||||
@@ -701,9 +660,9 @@ jobs:
|
|||||||
contents: read
|
contents: read
|
||||||
steps:
|
steps:
|
||||||
- id: token
|
- id: token
|
||||||
uses: immich-app/devtools/actions/create-workflow-token@57ff6ebfd507b045514442683ff06ff1b2f6efbd # create-workflow-token-action-v1.0.2
|
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
|
||||||
with:
|
with:
|
||||||
app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }}
|
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||||
|
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
@@ -711,29 +670,28 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
token: ${{ steps.token.outputs.token }}
|
token: ${{ steps.token.outputs.token }}
|
||||||
- name: Setup pnpm
|
|
||||||
uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v5.0.0
|
- name: Setup Mise
|
||||||
- name: Setup Node
|
uses: immich-app/devtools/actions/use-mise@cf6e190bacde3d7bda59372a786b36ac7d01536a # use-mise-action-v2.0.1
|
||||||
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
|
|
||||||
with:
|
with:
|
||||||
node-version-file: './server/.nvmrc'
|
github_token: ${{ steps.token.outputs.token }}
|
||||||
cache: 'pnpm'
|
|
||||||
cache-dependency-path: '**/pnpm-lock.yaml'
|
|
||||||
- name: Install server dependencies
|
- name: Install server dependencies
|
||||||
run: SHARP_IGNORE_GLOBAL_LIBVIPS=true pnpm --filter immich install --frozen-lockfile
|
run: SHARP_IGNORE_GLOBAL_LIBVIPS=true pnpm --filter immich install --frozen-lockfile
|
||||||
- name: Build the app
|
|
||||||
run: pnpm --filter immich build
|
|
||||||
- name: Run API generation
|
- name: Run API generation
|
||||||
run: ./bin/generate-open-api.sh
|
run: mise //:open-api
|
||||||
working-directory: open-api
|
working-directory: open-api
|
||||||
|
|
||||||
- name: Find file changes
|
- name: Find file changes
|
||||||
uses: tj-actions/verify-changed-files@a1c6acee9df209257a246f2cc6ae8cb6581c1edf # v20.0.4
|
uses: tj-actions/verify-changed-files@a1c6acee9df209257a246f2cc6ae8cb6581c1edf # v20.0.4
|
||||||
id: verify-changed-files
|
id: verify-changed-files
|
||||||
with:
|
with:
|
||||||
files: |
|
files: |
|
||||||
mobile/openapi
|
mobile/openapi
|
||||||
open-api/typescript-sdk
|
packages/sdk
|
||||||
open-api/immich-openapi-specs.json
|
open-api/immich-openapi-specs.json
|
||||||
|
|
||||||
- name: Verify files have not changed
|
- name: Verify files have not changed
|
||||||
if: steps.verify-changed-files.outputs.files_changed == 'true'
|
if: steps.verify-changed-files.outputs.files_changed == 'true'
|
||||||
env:
|
env:
|
||||||
@@ -742,6 +700,7 @@ jobs:
|
|||||||
echo "ERROR: Generated files not up to date!"
|
echo "ERROR: Generated files not up to date!"
|
||||||
echo "Changed files: ${CHANGED_FILES}"
|
echo "Changed files: ${CHANGED_FILES}"
|
||||||
exit 1
|
exit 1
|
||||||
|
|
||||||
sql-schema-up-to-date:
|
sql-schema-up-to-date:
|
||||||
name: SQL Schema Checks
|
name: SQL Schema Checks
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
@@ -763,9 +722,9 @@ jobs:
|
|||||||
working-directory: ./server
|
working-directory: ./server
|
||||||
steps:
|
steps:
|
||||||
- id: token
|
- id: token
|
||||||
uses: immich-app/devtools/actions/create-workflow-token@57ff6ebfd507b045514442683ff06ff1b2f6efbd # create-workflow-token-action-v1.0.2
|
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
|
||||||
with:
|
with:
|
||||||
app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }}
|
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||||
|
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
@@ -773,31 +732,35 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
token: ${{ steps.token.outputs.token }}
|
token: ${{ steps.token.outputs.token }}
|
||||||
- name: Setup pnpm
|
|
||||||
uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v5.0.0
|
- name: Setup Mise
|
||||||
- name: Setup Node
|
uses: immich-app/devtools/actions/use-mise@cf6e190bacde3d7bda59372a786b36ac7d01536a # use-mise-action-v2.0.1
|
||||||
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
|
|
||||||
with:
|
with:
|
||||||
node-version-file: './server/.nvmrc'
|
github_token: ${{ steps.token.outputs.token }}
|
||||||
cache: 'pnpm'
|
|
||||||
cache-dependency-path: '**/pnpm-lock.yaml'
|
|
||||||
- name: Install server dependencies
|
- name: Install server dependencies
|
||||||
run: SHARP_IGNORE_GLOBAL_LIBVIPS=true pnpm install --frozen-lockfile
|
run: SHARP_IGNORE_GLOBAL_LIBVIPS=true pnpm install --frozen-lockfile
|
||||||
|
|
||||||
- name: Build the app
|
- name: Build the app
|
||||||
run: pnpm build
|
run: pnpm build
|
||||||
|
|
||||||
- name: Run existing migrations
|
- name: Run existing migrations
|
||||||
run: pnpm migrations:run
|
run: pnpm migrations:run
|
||||||
|
|
||||||
- name: Test npm run schema:reset command works
|
- name: Test npm run schema:reset command works
|
||||||
run: pnpm schema:reset
|
run: pnpm schema:reset
|
||||||
|
|
||||||
- name: Generate new migrations
|
- name: Generate new migrations
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
run: pnpm migrations:generate src/TestMigration
|
run: pnpm migrations:generate src/TestMigration
|
||||||
|
|
||||||
- name: Find file changes
|
- name: Find file changes
|
||||||
uses: tj-actions/verify-changed-files@a1c6acee9df209257a246f2cc6ae8cb6581c1edf # v20.0.4
|
uses: tj-actions/verify-changed-files@a1c6acee9df209257a246f2cc6ae8cb6581c1edf # v20.0.4
|
||||||
id: verify-changed-files
|
id: verify-changed-files
|
||||||
with:
|
with:
|
||||||
files: |
|
files: |
|
||||||
server/src
|
server/src
|
||||||
|
|
||||||
- name: Verify migration files have not changed
|
- name: Verify migration files have not changed
|
||||||
if: steps.verify-changed-files.outputs.files_changed == 'true'
|
if: steps.verify-changed-files.outputs.files_changed == 'true'
|
||||||
env:
|
env:
|
||||||
@@ -807,16 +770,19 @@ jobs:
|
|||||||
echo "Changed files: ${CHANGED_FILES}"
|
echo "Changed files: ${CHANGED_FILES}"
|
||||||
cat ./src/*-TestMigration.ts
|
cat ./src/*-TestMigration.ts
|
||||||
exit 1
|
exit 1
|
||||||
|
|
||||||
- name: Run SQL generation
|
- name: Run SQL generation
|
||||||
run: pnpm sync:sql
|
run: mise //:sql
|
||||||
env:
|
env:
|
||||||
DB_URL: postgres://postgres:postgres@localhost:5432/immich
|
DB_URL: postgres://postgres:postgres@localhost:5432/immich
|
||||||
|
|
||||||
- name: Find file changes
|
- name: Find file changes
|
||||||
uses: tj-actions/verify-changed-files@a1c6acee9df209257a246f2cc6ae8cb6581c1edf # v20.0.4
|
uses: tj-actions/verify-changed-files@a1c6acee9df209257a246f2cc6ae8cb6581c1edf # v20.0.4
|
||||||
id: verify-changed-sql-files
|
id: verify-changed-sql-files
|
||||||
with:
|
with:
|
||||||
files: |
|
files: |
|
||||||
server/src/queries
|
server/src/queries
|
||||||
|
|
||||||
- name: Verify SQL files have not changed
|
- name: Verify SQL files have not changed
|
||||||
if: steps.verify-changed-sql-files.outputs.files_changed == 'true'
|
if: steps.verify-changed-sql-files.outputs.files_changed == 'true'
|
||||||
env:
|
env:
|
||||||
|
|||||||
@@ -24,19 +24,19 @@ jobs:
|
|||||||
should_run: ${{ steps.check.outputs.should_run }}
|
should_run: ${{ steps.check.outputs.should_run }}
|
||||||
steps:
|
steps:
|
||||||
- id: token
|
- id: token
|
||||||
uses: immich-app/devtools/actions/create-workflow-token@57ff6ebfd507b045514442683ff06ff1b2f6efbd # create-workflow-token-action-v1.0.2
|
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
|
||||||
with:
|
with:
|
||||||
app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }}
|
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||||
|
|
||||||
- name: Check what should run
|
- name: Check what should run
|
||||||
id: check
|
id: check
|
||||||
uses: immich-app/devtools/actions/pre-job@f50e3b600b6ac1763ddb8f3dfc69093512b967a1 # pre-job-action-v2.0.3
|
uses: immich-app/devtools/actions/pre-job@91f342bb4477c4bc10c576ae739da875d85aa164 # pre-job-action-v2.0.4
|
||||||
with:
|
with:
|
||||||
github-token: ${{ steps.token.outputs.token }}
|
github-token: ${{ steps.token.outputs.token }}
|
||||||
filters: |
|
filters: |
|
||||||
i18n:
|
i18n:
|
||||||
- modified: 'i18n/!(en|package)**\.json'
|
- modified: 'i18n/!(en)**\.json'
|
||||||
skip-force-logic: 'true'
|
skip-force-logic: 'true'
|
||||||
|
|
||||||
enforce-lock:
|
enforce-lock:
|
||||||
@@ -47,9 +47,9 @@ jobs:
|
|||||||
if: ${{ fromJSON(needs.pre-job.outputs.should_run).i18n == true }}
|
if: ${{ fromJSON(needs.pre-job.outputs.should_run).i18n == true }}
|
||||||
steps:
|
steps:
|
||||||
- id: token
|
- id: token
|
||||||
uses: immich-app/devtools/actions/create-workflow-token@57ff6ebfd507b045514442683ff06ff1b2f6efbd # create-workflow-token-action-v1.0.2
|
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
|
||||||
with:
|
with:
|
||||||
app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }}
|
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||||
|
|
||||||
- name: Bot review status
|
- name: Bot review status
|
||||||
@@ -68,6 +68,6 @@ jobs:
|
|||||||
permissions: {}
|
permissions: {}
|
||||||
if: always()
|
if: always()
|
||||||
steps:
|
steps:
|
||||||
- uses: immich-app/devtools/actions/success-check@53bb77345ee9f953f93bd6fd9980f07a2f24965e # success-check-action-v0.0.5
|
- uses: immich-app/devtools/actions/success-check@81113db03f6d743efee81e0058c0b43f6cd6f36d # success-check-action-v0.0.6
|
||||||
with:
|
with:
|
||||||
needs: ${{ toJSON(needs) }}
|
needs: ${{ toJSON(needs) }}
|
||||||
|
|||||||
+1
-1
@@ -20,7 +20,7 @@ mobile/openapi/doc
|
|||||||
mobile/openapi/.openapi-generator/FILES
|
mobile/openapi/.openapi-generator/FILES
|
||||||
mobile/ios/build
|
mobile/ios/build
|
||||||
|
|
||||||
open-api/typescript-sdk/build
|
packages/**/build
|
||||||
mobile/android/fastlane/report.xml
|
mobile/android/fastlane/report.xml
|
||||||
mobile/ios/fastlane/report.xml
|
mobile/ios/fastlane/report.xml
|
||||||
|
|
||||||
|
|||||||
Vendored
+6
-4
@@ -23,15 +23,17 @@
|
|||||||
"type": "node",
|
"type": "node",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"name": "Immich CLI",
|
"name": "Immich CLI",
|
||||||
"program": "${workspaceFolder}/cli/dist/index.js",
|
"program": "${workspaceFolder}/packages/cli/dist/index.js",
|
||||||
"args": ["upload", "--help"],
|
"args": ["upload", "--help"],
|
||||||
"runtimeArgs": ["--enable-source-maps"],
|
"runtimeArgs": ["--enable-source-maps"],
|
||||||
"console": "integratedTerminal",
|
"console": "integratedTerminal",
|
||||||
"resolveSourceMapLocations": ["${workspaceFolder}/cli/dist/**/*.js.map"],
|
"resolveSourceMapLocations": [
|
||||||
|
"${workspaceFolder}/packages/cli/dist/**/*.js.map"
|
||||||
|
],
|
||||||
"sourceMaps": true,
|
"sourceMaps": true,
|
||||||
"outFiles": ["${workspaceFolder}/cli/dist/**/*.js"],
|
"outFiles": ["${workspaceFolder}/packages/cli/dist/**/*.js"],
|
||||||
"skipFiles": ["<node_internals>/**"],
|
"skipFiles": ["<node_internals>/**"],
|
||||||
"preLaunchTask": "Build Immich CLI"
|
"preLaunchTask": "Build @immich/cli"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
+5
-1
@@ -26,7 +26,11 @@
|
|||||||
},
|
},
|
||||||
"[svelte]": {
|
"[svelte]": {
|
||||||
"editor.defaultFormatter": "svelte.svelte-vscode",
|
"editor.defaultFormatter": "svelte.svelte-vscode",
|
||||||
"editor.formatOnSave": true
|
"editor.formatOnSave": true,
|
||||||
|
"tailwindCSS.lint.suggestCanonicalClasses": "ignore"
|
||||||
|
},
|
||||||
|
"svelte.plugin.svelte.compilerWarnings": {
|
||||||
|
"state_referenced_locally": "ignore"
|
||||||
},
|
},
|
||||||
"[typescript]": {
|
"[typescript]": {
|
||||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||||
|
|||||||
@@ -37,105 +37,24 @@ prod-scale:
|
|||||||
|
|
||||||
.PHONY: open-api
|
.PHONY: open-api
|
||||||
open-api:
|
open-api:
|
||||||
cd ./open-api && bash ./bin/generate-open-api.sh
|
@printf "This command has been removed. Please use:\n\n mise open-api # or mise //:open-api from another directory\n\n"\n\n >&2 && exit 1
|
||||||
|
|
||||||
open-api-dart:
|
|
||||||
cd ./open-api && bash ./bin/generate-open-api.sh dart
|
|
||||||
|
|
||||||
open-api-typescript:
|
|
||||||
cd ./open-api && bash ./bin/generate-open-api.sh typescript
|
|
||||||
|
|
||||||
sql:
|
sql:
|
||||||
pnpm --filter immich run sync:sql
|
@printf "This command has been removed. Please use:\n\n mise sql # or mise //:sql from another directory\n\n"\n\n >&2 && exit 1
|
||||||
|
|
||||||
attach-server:
|
|
||||||
docker exec -it docker_immich-server_1 sh
|
|
||||||
|
|
||||||
renovate:
|
renovate:
|
||||||
LOG_LEVEL=debug pnpm exec renovate --platform=local --repository-cache=reset
|
LOG_LEVEL=debug pnpm exec renovate --platform=local --repository-cache=reset
|
||||||
|
|
||||||
# Directories that need to be created for volumes or build output
|
|
||||||
VOLUME_DIRS = \
|
|
||||||
./.pnpm-store \
|
|
||||||
./web/.svelte-kit \
|
|
||||||
./web/node_modules \
|
|
||||||
./web/coverage \
|
|
||||||
./e2e/node_modules \
|
|
||||||
./docs/node_modules \
|
|
||||||
./server/node_modules \
|
|
||||||
./open-api/typescript-sdk/node_modules \
|
|
||||||
./.github/node_modules \
|
|
||||||
./node_modules \
|
|
||||||
./cli/node_modules
|
|
||||||
|
|
||||||
# Include .env file if it exists
|
# Include .env file if it exists
|
||||||
-include docker/.env
|
-include docker/.env
|
||||||
|
|
||||||
MODULES = e2e server web cli sdk docs .github
|
MODULES = e2e server web cli sdk docs .github
|
||||||
|
|
||||||
# directory to package name mapping function
|
|
||||||
# cli = @immich/cli
|
|
||||||
# docs = documentation
|
|
||||||
# e2e = immich-e2e
|
|
||||||
# open-api/typescript-sdk = @immich/sdk
|
|
||||||
# server = immich
|
|
||||||
# web = immich-web
|
|
||||||
map-package = $(subst sdk,@immich/sdk,$(subst cli,@immich/cli,$(subst docs,documentation,$(subst e2e,immich-e2e,$(subst server,immich,$(subst web,immich-web,$1))))))
|
|
||||||
|
|
||||||
audit-%:
|
|
||||||
pnpm --filter $(call map-package,$*) audit fix
|
|
||||||
install-%:
|
|
||||||
pnpm --filter $(call map-package,$*) install $(if $(FROZEN),--frozen-lockfile) $(if $(OFFLINE),--offline)
|
|
||||||
build-cli: build-sdk
|
|
||||||
build-web: build-sdk
|
|
||||||
build-%: install-%
|
|
||||||
pnpm --filter $(call map-package,$*) run build
|
|
||||||
format-%:
|
|
||||||
pnpm --filter $(call map-package,$*) run format:fix
|
|
||||||
lint-%:
|
|
||||||
pnpm --filter $(call map-package,$*) run lint:fix
|
|
||||||
check-%:
|
|
||||||
pnpm --filter $(call map-package,$*) run check
|
|
||||||
check-web:
|
|
||||||
pnpm --filter immich-web run check:typescript
|
|
||||||
pnpm --filter immich-web run check:svelte
|
|
||||||
test-%:
|
|
||||||
pnpm --filter $(call map-package,$*) run test
|
|
||||||
test-e2e:
|
test-e2e:
|
||||||
docker compose -f ./e2e/docker-compose.yml build
|
docker compose -f ./e2e/docker-compose.yml build
|
||||||
pnpm --filter immich-e2e run test
|
pnpm --filter immich-e2e run test
|
||||||
pnpm --filter immich-e2e run test:web
|
pnpm --filter immich-e2e run test:web
|
||||||
test-medium:
|
|
||||||
docker run \
|
|
||||||
--rm \
|
|
||||||
-v ./server/src:/usr/src/app/src \
|
|
||||||
-v ./server/test:/usr/src/app/test \
|
|
||||||
-v ./server/vitest.config.medium.mjs:/usr/src/app/vitest.config.medium.mjs \
|
|
||||||
-v ./server/tsconfig.json:/usr/src/app/tsconfig.json \
|
|
||||||
-e NODE_ENV=development \
|
|
||||||
immich-server:latest \
|
|
||||||
-c "pnpm test:medium -- --run"
|
|
||||||
test-medium-dev:
|
|
||||||
docker exec -it immich_server /bin/sh -c "pnpm run test:medium"
|
|
||||||
|
|
||||||
install-all:
|
|
||||||
pnpm -r --filter '!documentation' install
|
|
||||||
|
|
||||||
build-all: $(foreach M,$(filter-out e2e docs .github,$(MODULES)),build-$M) ;
|
|
||||||
|
|
||||||
check-all:
|
|
||||||
pnpm -r --filter '!documentation' run "/^(check|check\:svelte|check\:typescript)$/"
|
|
||||||
lint-all:
|
|
||||||
pnpm -r --filter '!documentation' run lint:fix
|
|
||||||
format-all:
|
|
||||||
pnpm -r --filter '!documentation' run format:fix
|
|
||||||
audit-all:
|
|
||||||
pnpm -r --filter '!documentation' audit fix
|
|
||||||
hygiene-all: audit-all
|
|
||||||
pnpm -r --filter '!documentation' run "/(format:fix|check|check:svelte|check:typescript|sql)/"
|
|
||||||
|
|
||||||
test-all:
|
|
||||||
pnpm -r --filter '!documentation' run "/^test/"
|
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
find . -name "node_modules" -type d -prune -exec rm -rf {} +
|
find . -name "node_modules" -type d -prune -exec rm -rf {} +
|
||||||
@@ -146,7 +65,3 @@ clean:
|
|||||||
find . -name ".pnpm-store" -type d -prune -exec rm -rf '{}' +
|
find . -name ".pnpm-store" -type d -prune -exec rm -rf '{}' +
|
||||||
command -v docker >/dev/null 2>&1 && docker compose -f ./docker/docker-compose.dev.yml down -v --remove-orphans || true
|
command -v docker >/dev/null 2>&1 && docker compose -f ./docker/docker-compose.dev.yml down -v --remove-orphans || true
|
||||||
command -v docker >/dev/null 2>&1 && docker compose -f ./e2e/docker-compose.yml down -v --remove-orphans || true
|
command -v docker >/dev/null 2>&1 && docker compose -f ./e2e/docker-compose.yml down -v --remove-orphans || true
|
||||||
|
|
||||||
|
|
||||||
setup-server-dev: install-server
|
|
||||||
setup-web-dev: install-sdk build-sdk install-web
|
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
24.15.0
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
FROM node:24.1.0-alpine3.20@sha256:8fe019e0d57dbdce5f5c27c0b63d2775cf34b00e3755a7dea969802d7e0c2b25 AS core
|
|
||||||
|
|
||||||
WORKDIR /usr/src/app
|
|
||||||
COPY package* pnpm* .pnpmfile.cjs ./
|
|
||||||
COPY ./cli ./cli/
|
|
||||||
COPY ./open-api/typescript-sdk ./open-api/typescript-sdk/
|
|
||||||
RUN corepack enable pnpm && \
|
|
||||||
pnpm install --filter @immich/sdk --filter @immich/cli --frozen-lockfile && \
|
|
||||||
pnpm --filter @immich/sdk build && \
|
|
||||||
pnpm --filter @immich/cli build
|
|
||||||
|
|
||||||
WORKDIR /import
|
|
||||||
|
|
||||||
ENTRYPOINT ["node", "/usr/src/app/cli/dist"]
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
[tools]
|
[tools]
|
||||||
terragrunt = "1.0.1"
|
terragrunt = "1.0.3"
|
||||||
opentofu = "1.11.6"
|
opentofu = "1.11.6"
|
||||||
|
|
||||||
[tasks."tg:fmt"]
|
[tasks."tg:fmt"]
|
||||||
|
|||||||
+30
-30
@@ -2,37 +2,37 @@
|
|||||||
# Manual edits may be lost in future updates.
|
# Manual edits may be lost in future updates.
|
||||||
|
|
||||||
provider "registry.opentofu.org/cloudflare/cloudflare" {
|
provider "registry.opentofu.org/cloudflare/cloudflare" {
|
||||||
version = "4.52.5"
|
version = "4.52.7"
|
||||||
constraints = "4.52.5"
|
constraints = "4.52.7"
|
||||||
hashes = [
|
hashes = [
|
||||||
"h1:+rfzF+16ZcWZWnTyW/p1HHTzYbPKX8Zt2nIFtR/+f+E=",
|
"h1:+O72J3QYiZtYmYYZM/Eh0f4NNfl1BvjX1eju43qTQsQ=",
|
||||||
"h1:18bXaaOSq8MWKuMxo/4y7EB7/i7G90y5QsKHZRmkoDo=",
|
"h1:0oqjYIPXcXh7XiDiKI085cHDYQQ5mh8kDl9dmBtvtog=",
|
||||||
"h1:4vZVOpKeEQZsF2VrARRZFeL37Ed/gD4rRMtfnvWQres=",
|
"h1:4b4ESb87MGv5bnadgYe7sK5rEkKMZhbkQcwPubQTsR4=",
|
||||||
"h1:BZOsTF83QPKXTAaYqxPKzdl1KRjk/L2qbPpFjM0w28A=",
|
"h1:6mTr3eA1Ddb348lLmJuyvn98z4KF+ejqaUEJ76D1rzQ=",
|
||||||
"h1:CDuC+HXLvc1z6wkCRsSDcc/+QENIHEtssYshiWg3opA=",
|
"h1:9/3YH+9k9HqsvFtbmBf7SO2+xqZeZrXNKzLkjNuhUEA=",
|
||||||
"h1:DE+YFzLnqSe79pI2R4idRGx5QzLdrA7RXvngTkGfZ30=",
|
"h1:Jcq4tBWgyH4/2JsojNBSRaN0mcItVMchO+lynonrlqc=",
|
||||||
"h1:DfaJwH3Ml4yrRbdAY4AcDVy0QTQk5T3A622TXzS/u2E=",
|
"h1:Y4Vv/2RdP0Q+uxqhOxzOdKxuuEMjXPDcU0vPc5bCQzI=",
|
||||||
"h1:EIDXP0W3kgIv2pecrFmqtK/DnlqkyckzBzhxKaXU+4A=",
|
"h1:a0gW8FBKsbP9Fi0HEDoy49WIbEWVHk9+BR4/iwuBdDQ=",
|
||||||
"h1:EV4kYyaOnwGA0bh/3hU6Ezqnt1PFDxopH7i85e48IzY=",
|
"h1:gElv6iqJtg8OKN77gbw+MjrkrQmJHPkkMEi1J+0xkpU=",
|
||||||
"h1:M0iXabfzamU+MPDi0G9XACpbacFKMakmM+Z9HZ8HrsM=",
|
"h1:oslXUugD/NQ+duJgT4BhKQyfGbuFOANknMvR73fiOeM=",
|
||||||
"h1:YWmCbGF/KbsrUzcYVBLscwLizidbp95TDQa0N2qpmVo=",
|
"h1:pPItIWii5oymR+geZB219ROSPuSODPLTlM4S/u8xLvM=",
|
||||||
"h1:cxPcCB5gbrpUO1+IXkQYs1YTY50/0IlApCzGea0cwuQ=",
|
"h1:u67GWw8GwD9NDlDzp9Y5VRnSQGcCrE8rSpkGPaBpDl0=",
|
||||||
"h1:g6DldikTV2HXUu9uoeNY5FuLufgaYWF4ufgZg7wq62s=",
|
"h1:uUUa9dY0XQOycI8pxg16PFFtL0WCTi9uEJz8trTQ7pU=",
|
||||||
"h1:oi/Hrx9pwoQ+Z52CBC+rrowVH387EIj0qvnxQgDeI+0=",
|
"h1:y3rV8KF2q6GEMANNlf5EkKJurlfbKlIKpjGcdxoy7pQ=",
|
||||||
"zh:1a3400cb38863b2585968d1876706bcfc67a148e1318a1d325c6c7704adc999b",
|
"zh:0c904ce31a4c6c4a5b3bf7ff1560e77c0cc7e2450c8553ded8e8c90398e1418b",
|
||||||
"zh:4c5062cb9e9da1676f06ae92b8370186d98976cc4c7030d3cd76df12af54282a",
|
"zh:36183d310c36373fe4cb936b83c595c6fd3b0a94bc7827f28e5789ccbf59752e",
|
||||||
"zh:52110f493b5f0587ef77a1cfd1a67001fd4c617b14c6502d732ab47352bdc2f7",
|
"zh:556a568a6f0235e8f41647de9e4d3a1e7b1d6502df8b19b54ec441f1c653ea10",
|
||||||
"zh:5aa536f9eaeb43823aaf2aa80e7d39b25ef2b383405ed034aa16a28b446a9238",
|
"zh:633ebbd5b0245e75e500ef9be4d9e62288f97e8da3baaa51323892a786d90285",
|
||||||
"zh:5cc39459a1c6be8a918f17054e4fbba573825ed5597dcada588fe99614d98a5b",
|
"zh:6acfe60cf52a65ba8f044f748548d2119e7f4fd7f8ebcb14698960d87c68f529",
|
||||||
"zh:629ae6a7ba298815131da826474d199312d21cec53a4d5ded4fa56a692e6f072",
|
|
||||||
"zh:719cc7c75dc1d3eb30c22ff5102a017996d9788b948078c7e1c5b3446aeca661",
|
|
||||||
"zh:8698635a3ca04383c1e93b21d6963346bdae54d27177a48e4b1435b7f731731c",
|
|
||||||
"zh:890df766e9b839623b1f0437355032a3c006226a6c200cd911e15ee1a9014e9f",
|
"zh:890df766e9b839623b1f0437355032a3c006226a6c200cd911e15ee1a9014e9f",
|
||||||
"zh:8a9993f1dcadf1dd6ca43b23348abe374605d29945a2fafc07fb3457644e6a54",
|
"zh:904acc31ebb9d6ef68c792074b30532ee61bf515f19e0a3c75b46f126cca1f13",
|
||||||
"zh:b1b9a1e6bcc24d5863a664a411d2dc906373ae7a2399d2d65548ce7377057852",
|
"zh:a1d0a81246afc8750286d3f6fe7a8fbe6460dd2662407b28dbfbabb612e5fa9d",
|
||||||
"zh:b270184cdeec277218e84b94cb136fead753da717f9b9dc378e51907f3f00bb0",
|
"zh:a41a36fe253fc365fe2b7ffc749624688b2693b4634862fda161179ab100029f",
|
||||||
"zh:dff2bc10071210181726ce270f954995fe42c696e61e2e8f874021fed02521e5",
|
"zh:a7ef269e77ffa8715c8945a2c14322c7ff159ea44c15f62505f3cbb2cae3b32d",
|
||||||
"zh:e8e87b40b6a87dc097b0fdc20d3f725cec0d82abc9cc3755c1f89f8f6e8b0036",
|
"zh:b01aa3bed30610633b762df64332b26f8844a68c3960cebcb30f04918efc67fe",
|
||||||
"zh:ee964a6573d399a5dd22ce328fb38ca1207797a02248f14b2e4913ee390e7803",
|
"zh:b069cc2cd18cae10757df3ae030508eac8d55de7e49eda7a5e3e11f2f7fe6455",
|
||||||
|
"zh:b2d2c6313729ebb7465dceece374049e2d08bda34473901be9ff46a8836d42b2",
|
||||||
|
"zh:db0e114edaf4bc2f3d4769958807c83022bfbc619a00bdf4c4bd17faa4ab2d8b",
|
||||||
|
"zh:ecc0aa8b9044f664fd2aaf8fa992d976578f78478980555b4b8f6148e8d1a5fe",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ terraform {
|
|||||||
required_providers {
|
required_providers {
|
||||||
cloudflare = {
|
cloudflare = {
|
||||||
source = "cloudflare/cloudflare"
|
source = "cloudflare/cloudflare"
|
||||||
version = "4.52.5"
|
version = "4.52.7"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+30
-30
@@ -2,37 +2,37 @@
|
|||||||
# Manual edits may be lost in future updates.
|
# Manual edits may be lost in future updates.
|
||||||
|
|
||||||
provider "registry.opentofu.org/cloudflare/cloudflare" {
|
provider "registry.opentofu.org/cloudflare/cloudflare" {
|
||||||
version = "4.52.5"
|
version = "4.52.7"
|
||||||
constraints = "4.52.5"
|
constraints = "4.52.7"
|
||||||
hashes = [
|
hashes = [
|
||||||
"h1:+rfzF+16ZcWZWnTyW/p1HHTzYbPKX8Zt2nIFtR/+f+E=",
|
"h1:+O72J3QYiZtYmYYZM/Eh0f4NNfl1BvjX1eju43qTQsQ=",
|
||||||
"h1:18bXaaOSq8MWKuMxo/4y7EB7/i7G90y5QsKHZRmkoDo=",
|
"h1:0oqjYIPXcXh7XiDiKI085cHDYQQ5mh8kDl9dmBtvtog=",
|
||||||
"h1:4vZVOpKeEQZsF2VrARRZFeL37Ed/gD4rRMtfnvWQres=",
|
"h1:4b4ESb87MGv5bnadgYe7sK5rEkKMZhbkQcwPubQTsR4=",
|
||||||
"h1:BZOsTF83QPKXTAaYqxPKzdl1KRjk/L2qbPpFjM0w28A=",
|
"h1:6mTr3eA1Ddb348lLmJuyvn98z4KF+ejqaUEJ76D1rzQ=",
|
||||||
"h1:CDuC+HXLvc1z6wkCRsSDcc/+QENIHEtssYshiWg3opA=",
|
"h1:9/3YH+9k9HqsvFtbmBf7SO2+xqZeZrXNKzLkjNuhUEA=",
|
||||||
"h1:DE+YFzLnqSe79pI2R4idRGx5QzLdrA7RXvngTkGfZ30=",
|
"h1:Jcq4tBWgyH4/2JsojNBSRaN0mcItVMchO+lynonrlqc=",
|
||||||
"h1:DfaJwH3Ml4yrRbdAY4AcDVy0QTQk5T3A622TXzS/u2E=",
|
"h1:Y4Vv/2RdP0Q+uxqhOxzOdKxuuEMjXPDcU0vPc5bCQzI=",
|
||||||
"h1:EIDXP0W3kgIv2pecrFmqtK/DnlqkyckzBzhxKaXU+4A=",
|
"h1:a0gW8FBKsbP9Fi0HEDoy49WIbEWVHk9+BR4/iwuBdDQ=",
|
||||||
"h1:EV4kYyaOnwGA0bh/3hU6Ezqnt1PFDxopH7i85e48IzY=",
|
"h1:gElv6iqJtg8OKN77gbw+MjrkrQmJHPkkMEi1J+0xkpU=",
|
||||||
"h1:M0iXabfzamU+MPDi0G9XACpbacFKMakmM+Z9HZ8HrsM=",
|
"h1:oslXUugD/NQ+duJgT4BhKQyfGbuFOANknMvR73fiOeM=",
|
||||||
"h1:YWmCbGF/KbsrUzcYVBLscwLizidbp95TDQa0N2qpmVo=",
|
"h1:pPItIWii5oymR+geZB219ROSPuSODPLTlM4S/u8xLvM=",
|
||||||
"h1:cxPcCB5gbrpUO1+IXkQYs1YTY50/0IlApCzGea0cwuQ=",
|
"h1:u67GWw8GwD9NDlDzp9Y5VRnSQGcCrE8rSpkGPaBpDl0=",
|
||||||
"h1:g6DldikTV2HXUu9uoeNY5FuLufgaYWF4ufgZg7wq62s=",
|
"h1:uUUa9dY0XQOycI8pxg16PFFtL0WCTi9uEJz8trTQ7pU=",
|
||||||
"h1:oi/Hrx9pwoQ+Z52CBC+rrowVH387EIj0qvnxQgDeI+0=",
|
"h1:y3rV8KF2q6GEMANNlf5EkKJurlfbKlIKpjGcdxoy7pQ=",
|
||||||
"zh:1a3400cb38863b2585968d1876706bcfc67a148e1318a1d325c6c7704adc999b",
|
"zh:0c904ce31a4c6c4a5b3bf7ff1560e77c0cc7e2450c8553ded8e8c90398e1418b",
|
||||||
"zh:4c5062cb9e9da1676f06ae92b8370186d98976cc4c7030d3cd76df12af54282a",
|
"zh:36183d310c36373fe4cb936b83c595c6fd3b0a94bc7827f28e5789ccbf59752e",
|
||||||
"zh:52110f493b5f0587ef77a1cfd1a67001fd4c617b14c6502d732ab47352bdc2f7",
|
"zh:556a568a6f0235e8f41647de9e4d3a1e7b1d6502df8b19b54ec441f1c653ea10",
|
||||||
"zh:5aa536f9eaeb43823aaf2aa80e7d39b25ef2b383405ed034aa16a28b446a9238",
|
"zh:633ebbd5b0245e75e500ef9be4d9e62288f97e8da3baaa51323892a786d90285",
|
||||||
"zh:5cc39459a1c6be8a918f17054e4fbba573825ed5597dcada588fe99614d98a5b",
|
"zh:6acfe60cf52a65ba8f044f748548d2119e7f4fd7f8ebcb14698960d87c68f529",
|
||||||
"zh:629ae6a7ba298815131da826474d199312d21cec53a4d5ded4fa56a692e6f072",
|
|
||||||
"zh:719cc7c75dc1d3eb30c22ff5102a017996d9788b948078c7e1c5b3446aeca661",
|
|
||||||
"zh:8698635a3ca04383c1e93b21d6963346bdae54d27177a48e4b1435b7f731731c",
|
|
||||||
"zh:890df766e9b839623b1f0437355032a3c006226a6c200cd911e15ee1a9014e9f",
|
"zh:890df766e9b839623b1f0437355032a3c006226a6c200cd911e15ee1a9014e9f",
|
||||||
"zh:8a9993f1dcadf1dd6ca43b23348abe374605d29945a2fafc07fb3457644e6a54",
|
"zh:904acc31ebb9d6ef68c792074b30532ee61bf515f19e0a3c75b46f126cca1f13",
|
||||||
"zh:b1b9a1e6bcc24d5863a664a411d2dc906373ae7a2399d2d65548ce7377057852",
|
"zh:a1d0a81246afc8750286d3f6fe7a8fbe6460dd2662407b28dbfbabb612e5fa9d",
|
||||||
"zh:b270184cdeec277218e84b94cb136fead753da717f9b9dc378e51907f3f00bb0",
|
"zh:a41a36fe253fc365fe2b7ffc749624688b2693b4634862fda161179ab100029f",
|
||||||
"zh:dff2bc10071210181726ce270f954995fe42c696e61e2e8f874021fed02521e5",
|
"zh:a7ef269e77ffa8715c8945a2c14322c7ff159ea44c15f62505f3cbb2cae3b32d",
|
||||||
"zh:e8e87b40b6a87dc097b0fdc20d3f725cec0d82abc9cc3755c1f89f8f6e8b0036",
|
"zh:b01aa3bed30610633b762df64332b26f8844a68c3960cebcb30f04918efc67fe",
|
||||||
"zh:ee964a6573d399a5dd22ce328fb38ca1207797a02248f14b2e4913ee390e7803",
|
"zh:b069cc2cd18cae10757df3ae030508eac8d55de7e49eda7a5e3e11f2f7fe6455",
|
||||||
|
"zh:b2d2c6313729ebb7465dceece374049e2d08bda34473901be9ff46a8836d42b2",
|
||||||
|
"zh:db0e114edaf4bc2f3d4769958807c83022bfbc619a00bdf4c4bd17faa4ab2d8b",
|
||||||
|
"zh:ecc0aa8b9044f664fd2aaf8fa992d976578f78478980555b4b8f6148e8d1a5fe",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ terraform {
|
|||||||
required_providers {
|
required_providers {
|
||||||
cloudflare = {
|
cloudflare = {
|
||||||
source = "cloudflare/cloudflare"
|
source = "cloudflare/cloudflare"
|
||||||
version = "4.52.5"
|
version = "4.52.7"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,10 +25,10 @@ services:
|
|||||||
- server_node_modules:/usr/src/app/server/node_modules
|
- server_node_modules:/usr/src/app/server/node_modules
|
||||||
- web_node_modules:/usr/src/app/web/node_modules
|
- web_node_modules:/usr/src/app/web/node_modules
|
||||||
- github_node_modules:/usr/src/app/.github/node_modules
|
- github_node_modules:/usr/src/app/.github/node_modules
|
||||||
- cli_node_modules:/usr/src/app/cli/node_modules
|
- cli_node_modules:/usr/src/app/packages/cli/node_modules
|
||||||
- docs_node_modules:/usr/src/app/docs/node_modules
|
- docs_node_modules:/usr/src/app/docs/node_modules
|
||||||
- e2e_node_modules:/usr/src/app/e2e/node_modules
|
- e2e_node_modules:/usr/src/app/e2e/node_modules
|
||||||
- sdk_node_modules:/usr/src/app/open-api/typescript-sdk/node_modules
|
- sdk_node_modules:/usr/src/app/packages/sdk/node_modules
|
||||||
- app_node_modules:/usr/src/app/node_modules
|
- app_node_modules:/usr/src/app/node_modules
|
||||||
- sveltekit:/usr/src/app/web/.svelte-kit
|
- sveltekit:/usr/src/app/web/.svelte-kit
|
||||||
- coverage:/usr/src/app/web/coverage
|
- coverage:/usr/src/app/web/coverage
|
||||||
@@ -74,7 +74,7 @@ services:
|
|||||||
- ${UPLOAD_LOCATION}/photos:/data
|
- ${UPLOAD_LOCATION}/photos:/data
|
||||||
- /etc/localtime:/etc/localtime:ro
|
- /etc/localtime:/etc/localtime:ro
|
||||||
- pnpm_store_server:/buildcache/pnpm-store
|
- pnpm_store_server:/buildcache/pnpm-store
|
||||||
- ../plugins:/build/corePlugin
|
- ../packages/plugins:/build/corePlugin
|
||||||
env_file:
|
env_file:
|
||||||
- .env
|
- .env
|
||||||
environment:
|
environment:
|
||||||
@@ -157,7 +157,7 @@ services:
|
|||||||
|
|
||||||
redis:
|
redis:
|
||||||
container_name: immich_redis
|
container_name: immich_redis
|
||||||
image: docker.io/valkey/valkey:9@sha256:3b55fbaa0cd93cf0d9d961f405e4dfcc70efe325e2d84da207a0a8e6d8fde4f9
|
image: docker.io/valkey/valkey:9@sha256:8436e10bc65c94886a91d4415b6a6dfa9cb5a306fb3b996e5bb67cd2b4854193
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: redis-cli ping || exit 1
|
test: redis-cli ping || exit 1
|
||||||
|
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ services:
|
|||||||
|
|
||||||
redis:
|
redis:
|
||||||
container_name: immich_redis
|
container_name: immich_redis
|
||||||
image: docker.io/valkey/valkey:9@sha256:3b55fbaa0cd93cf0d9d961f405e4dfcc70efe325e2d84da207a0a8e6d8fde4f9
|
image: docker.io/valkey/valkey:9@sha256:8436e10bc65c94886a91d4415b6a6dfa9cb5a306fb3b996e5bb67cd2b4854193
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: redis-cli ping || exit 1
|
test: redis-cli ping || exit 1
|
||||||
restart: always
|
restart: always
|
||||||
@@ -85,7 +85,7 @@ services:
|
|||||||
container_name: immich_prometheus
|
container_name: immich_prometheus
|
||||||
ports:
|
ports:
|
||||||
- 9090:9090
|
- 9090:9090
|
||||||
image: prom/prometheus@sha256:5550dc63da361dc30f6fe02ac0e4dfc736ededfef3c8d12a634db04a67824d78
|
image: prom/prometheus@sha256:e4254400b85610324913f0dc4acf92603d9984e7519414c5a12811aa6146acc3
|
||||||
volumes:
|
volumes:
|
||||||
- ./prometheus.yml:/etc/prometheus/prometheus.yml
|
- ./prometheus.yml:/etc/prometheus/prometheus.yml
|
||||||
- prometheus-data:/prometheus
|
- prometheus-data:/prometheus
|
||||||
@@ -97,7 +97,7 @@ services:
|
|||||||
command: ['./run.sh', '-disable-reporting']
|
command: ['./run.sh', '-disable-reporting']
|
||||||
ports:
|
ports:
|
||||||
- 3000:3000
|
- 3000:3000
|
||||||
image: grafana/grafana:12.4.2-ubuntu@sha256:78839fe49e1425c02416fa8072591533a72bd9598e563b54a07d78f9e27fb5d3
|
image: grafana/grafana:12.4.3-ubuntu@sha256:ca3f764fdc48cebdf22dd206f33ecb0795a9a7210eacd1b5c02204aebd78b223
|
||||||
volumes:
|
volumes:
|
||||||
- grafana-data:/var/lib/grafana
|
- grafana-data:/var/lib/grafana
|
||||||
|
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ services:
|
|||||||
|
|
||||||
redis:
|
redis:
|
||||||
container_name: immich_redis
|
container_name: immich_redis
|
||||||
image: docker.io/valkey/valkey:9@sha256:3b55fbaa0cd93cf0d9d961f405e4dfcc70efe325e2d84da207a0a8e6d8fde4f9
|
image: docker.io/valkey/valkey:9@sha256:8436e10bc65c94886a91d4415b6a6dfa9cb5a306fb3b996e5bb67cd2b4854193
|
||||||
user: '1000:1000'
|
user: '1000:1000'
|
||||||
security_opt:
|
security_opt:
|
||||||
- no-new-privileges:true
|
- no-new-privileges:true
|
||||||
@@ -95,6 +95,3 @@ services:
|
|||||||
restart: always
|
restart: always
|
||||||
healthcheck:
|
healthcheck:
|
||||||
disable: false
|
disable: false
|
||||||
|
|
||||||
volumes:
|
|
||||||
model-cache:
|
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ services:
|
|||||||
|
|
||||||
redis:
|
redis:
|
||||||
container_name: immich_redis
|
container_name: immich_redis
|
||||||
image: docker.io/valkey/valkey:9@sha256:3b55fbaa0cd93cf0d9d961f405e4dfcc70efe325e2d84da207a0a8e6d8fde4f9
|
image: docker.io/valkey/valkey:9@sha256:8436e10bc65c94886a91d4415b6a6dfa9cb5a306fb3b996e5bb67cd2b4854193
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: redis-cli ping || exit 1
|
test: redis-cli ping || exit 1
|
||||||
restart: always
|
restart: always
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
24.15.0
|
|
||||||
@@ -81,7 +81,7 @@ VectorChord is the successor extension to pgvecto.rs, allowing for higher perfor
|
|||||||
|
|
||||||
### Migrating from pgvecto.rs
|
### Migrating from pgvecto.rs
|
||||||
|
|
||||||
Support for pgvecto.rs will be dropped in a later release, hence we recommend all users currently using pgvecto.rs to migrate to VectorChord at their convenience. There are two primary approaches to do so.
|
Support for pgvecto.rs has been dropped as of 3.0, hence all users currently using pgvecto.rs should migrate to VectorChord. There are two primary approaches to do so.
|
||||||
|
|
||||||
The easiest option is to have both extensions installed during the migration:
|
The easiest option is to have both extensions installed during the migration:
|
||||||
|
|
||||||
|
|||||||
@@ -13,8 +13,11 @@ The `immich-server` docker image comes preinstalled with an administrative CLI (
|
|||||||
| `enable-oauth-login` | Enable OAuth login |
|
| `enable-oauth-login` | Enable OAuth login |
|
||||||
| `disable-oauth-login` | Disable OAuth login |
|
| `disable-oauth-login` | Disable OAuth login |
|
||||||
| `list-users` | List Immich users |
|
| `list-users` | List Immich users |
|
||||||
|
| `grant-admin` | Grant admin privileges to a user (by email) |
|
||||||
|
| `revoke-admin` | Revoke admin privileges from a user (by email) |
|
||||||
| `version` | Print Immich version |
|
| `version` | Print Immich version |
|
||||||
| `change-media-location` | Change database file paths to align with a new media location |
|
| `change-media-location` | Change database file paths to align with a new media location |
|
||||||
|
| `schema-check` | Verify database migrations and check for schema drift |
|
||||||
|
|
||||||
## How to run a command
|
## How to run a command
|
||||||
|
|
||||||
@@ -102,6 +105,22 @@ immich-admin list-users
|
|||||||
]
|
]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Grant Admin
|
||||||
|
|
||||||
|
```
|
||||||
|
immich-admin grant-admin
|
||||||
|
? Please enter the user email: user@example.com
|
||||||
|
Admin access has been granted to user@example.com
|
||||||
|
```
|
||||||
|
|
||||||
|
Revoke Admin
|
||||||
|
|
||||||
|
```
|
||||||
|
immich-admin revoke-admin
|
||||||
|
? Please enter the user email: user@example.com
|
||||||
|
Admin access has been revoked from user@example.com
|
||||||
|
```
|
||||||
|
|
||||||
Print Immich Version
|
Print Immich Version
|
||||||
|
|
||||||
```
|
```
|
||||||
@@ -126,3 +145,12 @@ immich-admin change-media-location
|
|||||||
Database file paths updated successfully! 🎉
|
Database file paths updated successfully! 🎉
|
||||||
...
|
...
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Schema Check
|
||||||
|
|
||||||
|
```
|
||||||
|
immich-admin schema-check
|
||||||
|
Migrations are up to date
|
||||||
|
|
||||||
|
No schema drift detected
|
||||||
|
```
|
||||||
|
|||||||
+1
-1
@@ -10,4 +10,4 @@ OpenAPI is used to generate the client (Typescript, Dart) SDK. `openapi-generato
|
|||||||
make open-api
|
make open-api
|
||||||
```
|
```
|
||||||
|
|
||||||
You can find the generated client SDK in the `open-api/typescript-sdk/client` for Typescript SDK and `mobile/openapi` for Dart SDK.
|
You can find the generated client SDK in the `packages/sdk/client` for Typescript SDK and `mobile/openapi` for Dart SDK.
|
||||||
|
|||||||
@@ -205,7 +205,7 @@ When the Dev Container starts, it automatically:
|
|||||||
1. **Runs post-create script** (`container-server-post-create.sh`):
|
1. **Runs post-create script** (`container-server-post-create.sh`):
|
||||||
- Adjusts file permissions for the `node` user
|
- Adjusts file permissions for the `node` user
|
||||||
- Installs dependencies: `pnpm install` in all packages
|
- Installs dependencies: `pnpm install` in all packages
|
||||||
- Builds TypeScript SDK: `pnpm run build` in `open-api/typescript-sdk`
|
- Builds TypeScript SDK: `pnpm --filter @immich/sdk build`
|
||||||
|
|
||||||
2. **Starts development servers** via VS Code tasks:
|
2. **Starts development servers** via VS Code tasks:
|
||||||
- `Immich API Server (Nest)` - API server with hot-reloading on port 2283
|
- `Immich API Server (Nest)` - API server with hot-reloading on port 2283
|
||||||
@@ -243,8 +243,8 @@ To connect the mobile app to your Dev Container:
|
|||||||
|
|
||||||
- **Server code** (`/server`): Changes trigger automatic restart
|
- **Server code** (`/server`): Changes trigger automatic restart
|
||||||
- **Web code** (`/web`): Changes trigger hot module replacement
|
- **Web code** (`/web`): Changes trigger hot module replacement
|
||||||
- **Database migrations**: Run `pnpm run sync:sql` in the server directory
|
- **Database migrations**: Run `mise //:sql`
|
||||||
- **API changes**: Regenerate TypeScript SDK with `make open-api`
|
- **API changes**: Regenerate TypeScript SDK with `mise //:open-api`
|
||||||
|
|
||||||
## Testing
|
## Testing
|
||||||
|
|
||||||
@@ -252,20 +252,11 @@ To connect the mobile app to your Dev Container:
|
|||||||
|
|
||||||
The Dev Container supports multiple ways to run tests:
|
The Dev Container supports multiple ways to run tests:
|
||||||
|
|
||||||
#### Using Make Commands (Recommended)
|
#### Using Mise Commands (Recommended)
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Run tests for specific components
|
# Run tests for specific components
|
||||||
make test-server # Server unit tests
|
mise run checklist # in `server/`, `web/`, `packages/cli`
|
||||||
make test-web # Web unit tests
|
|
||||||
make test-e2e # End-to-end tests
|
|
||||||
make test-cli # CLI tests
|
|
||||||
|
|
||||||
# Run all tests
|
|
||||||
make test-all # Runs tests for all components
|
|
||||||
|
|
||||||
# Medium tests (integration tests)
|
|
||||||
make test-medium-dev # End-to-end tests
|
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Using PNPM Directly
|
#### Using PNPM Directly
|
||||||
@@ -289,48 +280,16 @@ pnpm run test # Run API tests
|
|||||||
pnpm run test:web # Run web UI tests
|
pnpm run test:web # Run web UI tests
|
||||||
```
|
```
|
||||||
|
|
||||||
### Code Quality Commands
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Linting
|
|
||||||
make lint-server # Lint server code
|
|
||||||
make lint-web # Lint web code
|
|
||||||
make lint-all # Lint all components
|
|
||||||
|
|
||||||
# Formatting
|
|
||||||
make format-server # Format server code
|
|
||||||
make format-web # Format web code
|
|
||||||
make format-all # Format all code
|
|
||||||
|
|
||||||
# Type checking
|
|
||||||
make check-server # Type check server
|
|
||||||
make check-web # Type check web
|
|
||||||
make check-all # Check all components
|
|
||||||
|
|
||||||
# Complete hygiene check
|
|
||||||
make hygiene-all # Run lint, format, check, SQL sync, and audit
|
|
||||||
```
|
|
||||||
|
|
||||||
### Additional Make Commands
|
### Additional Make Commands
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Build commands
|
|
||||||
make build-server # Build server
|
|
||||||
make build-web # Build web app
|
|
||||||
make build-all # Build everything
|
|
||||||
|
|
||||||
# API generation
|
# API generation
|
||||||
make open-api # Generate OpenAPI specs
|
make open-api # Generate OpenAPI specs
|
||||||
make open-api-typescript # Generate TypeScript SDK
|
make open-api-typescript # Generate TypeScript SDK
|
||||||
make open-api-dart # Generate Dart SDK
|
make open-api-dart # Generate Dart SDK
|
||||||
|
|
||||||
# Database
|
# Database
|
||||||
make sql # Sync database schema
|
mise sql # Sync database schema
|
||||||
|
|
||||||
# Dependencies
|
|
||||||
make install-server # Install server dependencies
|
|
||||||
make install-web # Install web dependencies
|
|
||||||
make install-all # Install all dependencies
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Debugging
|
### Debugging
|
||||||
|
|||||||
@@ -10,7 +10,8 @@ Our [GitHub Repository](https://github.com/immich-app/immich) is a [monorepo](ht
|
|||||||
| :------------------ | :------------------------------------------------------------------- |
|
| :------------------ | :------------------------------------------------------------------- |
|
||||||
| `.github/` | Github templates and action workflows |
|
| `.github/` | Github templates and action workflows |
|
||||||
| `.vscode/` | VSCode debug launch profiles |
|
| `.vscode/` | VSCode debug launch profiles |
|
||||||
| `cli/` | Source code for the work-in-progress CLI rewrite |
|
| `packages/cli` | Source code for the CLI |
|
||||||
|
| `packages/sdk` | Source code for the generated OpenAPI SDK |
|
||||||
| `docker/` | Docker compose resources for dev, test, production |
|
| `docker/` | Docker compose resources for dev, test, production |
|
||||||
| `design/` | Screenshots and logos for the README |
|
| `design/` | Screenshots and logos for the README |
|
||||||
| `docs/` | Source code for the [https://immich.app](https://immich.app) website |
|
| `docs/` | Source code for the [https://immich.app](https://immich.app) website |
|
||||||
|
|||||||
@@ -34,21 +34,23 @@ Run all web checks with `pnpm run check:all`
|
|||||||
Run all server checks with `pnpm run check:all`
|
Run all server checks with `pnpm run check:all`
|
||||||
:::
|
:::
|
||||||
|
|
||||||
:::info Auto Fix
|
:::tip Auto Fix
|
||||||
You can use `pnpm run __:fix` to potentially correct some issues automatically for `pnpm run format` and `lint`.
|
You can use `pnpm run __:fix` to potentially correct some issues automatically for `pnpm run format` and `lint`.
|
||||||
:::
|
:::
|
||||||
|
|
||||||
## Mobile Checks
|
## Mobile Checklist
|
||||||
|
|
||||||
The following commands must be executed from within the mobile app directory of the codebase.
|
- [ ] `mise //mobile:codegen` (auto-generate files using build_runner)
|
||||||
|
- [ ] `mise //mobile:lint` (static analysis via Dart Analyzer and DCM)
|
||||||
|
- [ ] `mise //mobile:format` (formatting via Dart Formatter)
|
||||||
|
- [ ] `mise //mobile:test` (unit tests)
|
||||||
|
|
||||||
- [ ] `make build` (auto-generate files using build_runner)
|
:::tip
|
||||||
- [ ] `make analyze` (static analysis via Dart Analyzer and DCM)
|
Run all these commands at once with `mise //mobile:checklist`
|
||||||
- [ ] `make format` (formatting via Dart Formatter)
|
:::
|
||||||
- [ ] `make test` (unit tests)
|
|
||||||
|
|
||||||
:::info Auto Fix
|
:::tip Auto Fix
|
||||||
You can use `dart fix --apply` and `dcm fix lib` to potentially correct some issues automatically for `make analyze`.
|
You can use `mise //mobile:lint-fix` to potentially correct some issues automatically for `mise //mobile:lint`.
|
||||||
:::
|
:::
|
||||||
|
|
||||||
## OpenAPI
|
## OpenAPI
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ You can access the web from `http://your-machine-ip:3000` or `http://localhost:3
|
|||||||
|
|
||||||
If you only want to do web development connected to an existing, remote backend, follow these steps:
|
If you only want to do web development connected to an existing, remote backend, follow these steps:
|
||||||
|
|
||||||
1. Build the Immich SDK - `cd open-api/typescript-sdk && pnpm i && pnpm run build && cd -`
|
1. Build the Immich SDK - `pnpm --filter @immich/sdk install && pnpm --filter @immich/sdk build`
|
||||||
2. Enter the web directory - `cd web/`
|
2. Enter the web directory - `cd web/`
|
||||||
3. Install web dependencies - `pnpm i`
|
3. Install web dependencies - `pnpm i`
|
||||||
4. Start the web development server
|
4. Start the web development server
|
||||||
|
|||||||
@@ -17,15 +17,14 @@ make e2e
|
|||||||
|
|
||||||
Before you can run the tests, you need to run the following commands _once_:
|
Before you can run the tests, you need to run the following commands _once_:
|
||||||
|
|
||||||
- `pnpm install` (in `e2e/`)
|
- `pnpm install`
|
||||||
- `pnpm run build` (in `cli/`)
|
- `pnpm --filter "@immich/*" build`
|
||||||
- `make open-api` (in the project root `/`)
|
- `mise //:open-api`
|
||||||
|
|
||||||
Once the test environment is running, the e2e tests can be run via:
|
Once the test environment is running, the e2e tests can be run via:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cd e2e/
|
mise //e2e:test
|
||||||
pnpm test
|
|
||||||
```
|
```
|
||||||
|
|
||||||
The tests check various things including:
|
The tests check various things including:
|
||||||
|
|||||||
@@ -50,6 +50,8 @@ Some basic examples:
|
|||||||
- `**/Raw/**` will exclude all files in any directory named `Raw`
|
- `**/Raw/**` will exclude all files in any directory named `Raw`
|
||||||
- `**/*.{tif,jpg}` will exclude all files with the extension `.tif` or `.jpg`
|
- `**/*.{tif,jpg}` will exclude all files with the extension `.tif` or `.jpg`
|
||||||
|
|
||||||
|
Note that `*` is a wildcard matching zero or more characters (i.e., withinin a filename or single directory name). `**` matches zero or more subdirectories, recursively. It also includes any/all files within a subdirectory, i.e., when used at the end of a pattern. For example, `**/exclude_me/**` will exclude all files in any directory named `exclude_me`, as well as all files in any subdirectories of `exclude_me`, recursively.
|
||||||
|
|
||||||
Special characters such as @ should be escaped, for instance:
|
Special characters such as @ should be escaped, for instance:
|
||||||
|
|
||||||
- `**/\@eaDir/**` will exclude all files in any directory named `@eaDir`
|
- `**/\@eaDir/**` will exclude all files in any directory named `@eaDir`
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ You do not need to redo any machine learning jobs after enabling hardware accele
|
|||||||
|
|
||||||
#### ROCm
|
#### ROCm
|
||||||
|
|
||||||
|
- On Linux, The [AMDGPU driver module](https://rocm.docs.amd.com/projects/install-on-linux/en/latest/how-to/docker.html) needs to be installed on the server and, if secure boot is used, the signing key of DKMS [needs to be enrolled in UEFI BIOS](https://wiki.debian.org/SecureBoot)
|
||||||
- The GPU must be supported by ROCm. If it isn't officially supported, you can attempt to use the `HSA_OVERRIDE_GFX_VERSION` environmental variable: `HSA_OVERRIDE_GFX_VERSION=<a supported version, e.g. 10.3.0>`. If this doesn't work, you might need to also set `HSA_USE_SVM=0`.
|
- The GPU must be supported by ROCm. If it isn't officially supported, you can attempt to use the `HSA_OVERRIDE_GFX_VERSION` environmental variable: `HSA_OVERRIDE_GFX_VERSION=<a supported version, e.g. 10.3.0>`. If this doesn't work, you might need to also set `HSA_USE_SVM=0`.
|
||||||
- The ROCm image is quite large and requires at least 35GiB of free disk space. However, pulling later updates to the service through Docker will generally only amount to a few hundred megabytes as the rest will be cached.
|
- The ROCm image is quite large and requires at least 35GiB of free disk space. However, pulling later updates to the service through Docker will generally only amount to a few hundred megabytes as the rest will be cached.
|
||||||
- This backend is new and may experience some issues. For example, GPU power consumption can be higher than usual after running inference, even if the machine learning service is idle. In this case, it will only go back to normal after being idle for 5 minutes (configurable with the [MACHINE_LEARNING_MODEL_TTL](/install/environment-variables) setting).
|
- This backend is new and may experience some issues. For example, GPU power consumption can be higher than usual after running inference, even if the machine learning service is idle. In this case, it will only go back to normal after being idle for 5 minutes (configurable with the [MACHINE_LEARNING_MODEL_TTL](/install/environment-variables) setting).
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ You can search the following types of content:
|
|||||||
| People | Faces that are recognized in your photos/videos. |
|
| People | Faces that are recognized in your photos/videos. |
|
||||||
| Contextual | Content of the photos and videos. |
|
| Contextual | Content of the photos and videos. |
|
||||||
| File name or extension | Full or partial file's name, or file's extension |
|
| File name or extension | Full or partial file's name, or file's extension |
|
||||||
|
| Full path or folder | Full or partial folder names from the original path. |
|
||||||
| Description | Description added to assets. |
|
| Description | Description added to assets. |
|
||||||
| Optical Character Recognition (OCR) | Text in images |
|
| Optical Character Recognition (OCR) | Text in images |
|
||||||
| Locations | Cities, states, and countries from reverse geocoding. |
|
| Locations | Cities, states, and countries from reverse geocoding. |
|
||||||
@@ -30,6 +31,12 @@ You can search the following types of content:
|
|||||||
|
|
||||||
<img src={require('./img/advanced-search-filters.webp').default} width="70%" title='Advanced search filters' />
|
<img src={require('./img/advanced-search-filters.webp').default} width="70%" title='Advanced search filters' />
|
||||||
|
|
||||||
|
### Full path or folder
|
||||||
|
|
||||||
|
Use this mode when you know a folder name or part of the original asset path.
|
||||||
|
|
||||||
|
Example: for /John/Projects/3D_Printing/2026-07-01/IMG_0001.jpg, searches like Projects, 3D, Printing, or 2026 match the asset.
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
Navigating to `Administration > Settings > Machine Learning Settings > Smart Search` will show the options available.
|
Navigating to `Administration > Settings > Machine Learning Settings > Smart Search` will show the options available.
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ You can learn how to set up Tailscale together with Immich with the [tutorial vi
|
|||||||
### Cons
|
### Cons
|
||||||
|
|
||||||
- The Tailscale client usually needs to run as root on your devices and it increases the attack surface slightly compared to a minimal Wireguard server. e.g., an [RCE vulnerability](https://github.com/tailscale/tailscale/security/advisories/GHSA-vqp6-rc3h-83cp) was discovered in the Windows Tailscale client in November 2022.
|
- The Tailscale client usually needs to run as root on your devices and it increases the attack surface slightly compared to a minimal Wireguard server. e.g., an [RCE vulnerability](https://github.com/tailscale/tailscale/security/advisories/GHSA-vqp6-rc3h-83cp) was discovered in the Windows Tailscale client in November 2022.
|
||||||
- Tailscale is a paid service. However, there is a generous [free tier](https://tailscale.com/pricing/) that permits up to 3 users and up to 100 devices.
|
- Tailscale is a paid service. However, there is a generous [free tier](https://tailscale.com/pricing/) suitable for personal use.
|
||||||
- Tailscale needs to be installed and running on both server-side and client-side.
|
- Tailscale needs to be installed and running on both server-side and client-side.
|
||||||
|
|
||||||
## Option 3: Reverse Proxy
|
## Option 3: Reverse Proxy
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ The default configuration looks like this:
|
|||||||
},
|
},
|
||||||
"ffmpeg": {
|
"ffmpeg": {
|
||||||
"accel": "disabled",
|
"accel": "disabled",
|
||||||
"accelDecode": false,
|
"accelDecode": true,
|
||||||
"acceptedAudioCodecs": ["aac", "mp3", "opus"],
|
"acceptedAudioCodecs": ["aac", "mp3", "opus"],
|
||||||
"acceptedContainers": ["mov", "ogg", "webm"],
|
"acceptedContainers": ["mov", "ogg", "webm"],
|
||||||
"acceptedVideoCodecs": ["h264"],
|
"acceptedVideoCodecs": ["h264"],
|
||||||
@@ -264,4 +264,4 @@ volumes:
|
|||||||
- ./configuration.yml:${IMMICH_CONFIG_FILE}
|
- ./configuration.yml:${IMMICH_CONFIG_FILE}
|
||||||
```
|
```
|
||||||
|
|
||||||
::
|
:::
|
||||||
|
|||||||
@@ -29,29 +29,31 @@ These environment variables are used by the `docker-compose.yml` file and do **N
|
|||||||
|
|
||||||
## General
|
## General
|
||||||
|
|
||||||
| Variable | Description | Default | Containers | Workers |
|
| Variable | Description | Default | Containers | Workers |
|
||||||
| :---------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------- | :--------------------------: | :----------------------- | :----------------- |
|
| :---------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :--------------------------: | :----------------------- | :----------------- |
|
||||||
| `TZ` | Timezone | <sup>\*1</sup> | server | microservices |
|
| `TZ` | Timezone | <sup>\*1</sup> | server | microservices |
|
||||||
| `IMMICH_ENV` | Environment (production, development) | `production` | server, machine learning | api, microservices |
|
| `IMMICH_ENV` | Environment (production, development) | `production` | server, machine learning | api, microservices |
|
||||||
| `IMMICH_LOG_LEVEL` | Log level (verbose, debug, log, warn, error) | `log` | server, machine learning | api, microservices |
|
| `IMMICH_LOG_LEVEL` | Log level (verbose, debug, log, warn, error) | `log` | server, machine learning | api, microservices |
|
||||||
| `IMMICH_LOG_FORMAT` | Log output format (`console`, `json`) | `console` | server | api, microservices |
|
| `IMMICH_LOG_FORMAT` | Log output format (`console`, `json`) | `console` | server | api, microservices |
|
||||||
| `IMMICH_MEDIA_LOCATION` | Media location inside the container ⚠️**You probably shouldn't set this**<sup>\*2</sup>⚠️ | `/data` | server | api, microservices |
|
| `IMMICH_MEDIA_LOCATION` | Media location inside the container ⚠️**You probably shouldn't set this**<sup>\*2</sup>⚠️ | `/data` | server | api, microservices |
|
||||||
| `IMMICH_CONFIG_FILE` | Path to config file | | server | api, microservices |
|
| `IMMICH_CONFIG_FILE` | Path to config file | | server | api, microservices |
|
||||||
| `IMMICH_HELMET_FILE` | Path to a json file with [helmet](https://www.npmjs.com/package/helmet) options. Set to `false` to disable. Set to `true` to use `server/helmet.json`. | `false` | server | api |
|
| `IMMICH_HELMET_FILE` | Path to a json file with [helmet](https://www.npmjs.com/package/helmet) options. Set to `false` to disable. Set to `true` to use `server/helmet.json`<sup>\*3</sup>. | `false` | server | api |
|
||||||
| `NO_COLOR` | Set to `true` to disable color-coded log output | `false` | server, machine learning | |
|
| `NO_COLOR` | Set to `true` to disable color-coded log output | `false` | server, machine learning | |
|
||||||
| `CPU_CORES` | Number of cores available to the Immich server | auto-detected CPU core count | server | |
|
| `CPU_CORES` | Number of cores available to the Immich server | auto-detected CPU core count | server | |
|
||||||
| `IMMICH_API_METRICS_PORT` | Port for the OTEL metrics | `8081` | server | api |
|
| `IMMICH_API_METRICS_PORT` | Port for the OTEL metrics | `8081` | server | api |
|
||||||
| `IMMICH_MICROSERVICES_METRICS_PORT` | Port for the OTEL metrics | `8082` | server | microservices |
|
| `IMMICH_MICROSERVICES_METRICS_PORT` | Port for the OTEL metrics | `8082` | server | microservices |
|
||||||
| `IMMICH_PROCESS_INVALID_IMAGES` | When `true`, generate thumbnails for invalid images | | server | microservices |
|
| `IMMICH_PROCESS_INVALID_IMAGES` | When `true`, generate thumbnails for invalid images | | server | microservices |
|
||||||
| `IMMICH_TRUSTED_PROXIES` | List of comma-separated IPs set as trusted proxies | | server | api |
|
| `IMMICH_TRUSTED_PROXIES` | List of comma-separated IPs set as trusted proxies | | server | api |
|
||||||
| `IMMICH_IGNORE_MOUNT_CHECK_ERRORS` | See [System Integrity](/administration/system-integrity) | | server | api, microservices |
|
| `IMMICH_IGNORE_MOUNT_CHECK_ERRORS` | See [System Integrity](/administration/system-integrity) | | server | api, microservices |
|
||||||
| `IMMICH_ALLOW_SETUP` | When `false` disables the `/auth/admin-sign-up` endpoint | `true` | server | api |
|
| `IMMICH_ALLOW_SETUP` | When `false` disables the `/auth/admin-sign-up` endpoint | `true` | server | api |
|
||||||
|
|
||||||
\*1: `TZ` should be set to a `TZ identifier` from [this list][tz-list]. For example, `TZ="Etc/UTC"`.
|
\*1: `TZ` should be set to a `TZ identifier` from [this list][tz-list]. For example, `TZ="Etc/UTC"`.
|
||||||
`TZ` is used by `exiftool` as a fallback in case the timezone cannot be determined from the image metadata. It is also used for logfile timestamps and cron job execution.
|
`TZ` is used by `exiftool` as a fallback in case the timezone cannot be determined from the image metadata. It is also used for logfile timestamps and cron job execution.
|
||||||
|
|
||||||
\*2: This path is where the Immich code looks for the files, which is internal to the docker container. Setting it to a path on your host will certainly break things, you should use the `UPLOAD_LOCATION` variable instead.
|
\*2: This path is where the Immich code looks for the files, which is internal to the docker container. Setting it to a path on your host will certainly break things, you should use the `UPLOAD_LOCATION` variable instead.
|
||||||
|
|
||||||
|
\*3: The [default configuration](https://helmetjs.github.io/#content-security-policy) sets `upgrade-insecure-requests`, which tells the browser to upgrade all requests to HTTPS. This breaks on HTTP-only deployments. If you cannot use HTTPS, you should use a custom helmet config file with `"upgrade-insecure-requests": null`.
|
||||||
|
|
||||||
## Workers
|
## Workers
|
||||||
|
|
||||||
| Variable | Description | Default | Containers |
|
| Variable | Description | Default | Containers |
|
||||||
@@ -81,7 +83,7 @@ Information on the current workers can be found [here](/administration/jobs-work
|
|||||||
| `DB_PASSWORD` | Database password | `postgres` | server, database<sup>\*1</sup> |
|
| `DB_PASSWORD` | Database password | `postgres` | server, database<sup>\*1</sup> |
|
||||||
| `DB_DATABASE_NAME` | Database name | `immich` | server, database<sup>\*1</sup> |
|
| `DB_DATABASE_NAME` | Database name | `immich` | server, database<sup>\*1</sup> |
|
||||||
| `DB_SSL_MODE` | Database SSL mode | | server |
|
| `DB_SSL_MODE` | Database SSL mode | | server |
|
||||||
| `DB_VECTOR_EXTENSION`<sup>\*2</sup> | Database vector extension (one of [`vectorchord`, `pgvector`, `pgvecto.rs`]) | | server |
|
| `DB_VECTOR_EXTENSION`<sup>\*2</sup> | Database vector extension (one of [`vectorchord`, `pgvector`]) | | server |
|
||||||
| `DB_SKIP_MIGRATIONS` | Whether to skip running migrations on startup (one of [`true`, `false`]) | `false` | server |
|
| `DB_SKIP_MIGRATIONS` | Whether to skip running migrations on startup (one of [`true`, `false`]) | `false` | server |
|
||||||
| `DB_STORAGE_TYPE` | Optimize concurrent IO on SSDs or sequential IO on HDDs ([`SSD`, `HDD`])<sup>\*3</sup> | `SSD` | database |
|
| `DB_STORAGE_TYPE` | Optimize concurrent IO on SSDs or sequential IO on HDDs ([`SSD`, `HDD`])<sup>\*3</sup> | `SSD` | database |
|
||||||
|
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ Scroll to the bottom of the "**Details**" section and find the `IP Address` list
|
|||||||
|
|
||||||
## Step 4 - Configure Firewall Settings
|
## Step 4 - Configure Firewall Settings
|
||||||
|
|
||||||
Once your project completes the build process, your containers will start. In order to be able to access Immich from your browser, you need to configure the firewall settings for your Synology NAS.
|
Once your project completes the build process, your containers will start. In order to be able to access Immich from your browser, you need to configure the firewall settings for your Synology NAS to allow communication between the Immich containers.
|
||||||
|
|
||||||
Open "**Control Panel**" on your Synology NAS, and select "**Security**". Navigate to "**Firewall**"
|
Open "**Control Panel**" on your Synology NAS, and select "**Security**". Navigate to "**Firewall**"
|
||||||
|
|
||||||
@@ -74,6 +74,7 @@ Read the [Post Installation](/install/post-install.mdx) steps and [upgrade instr
|
|||||||
|
|
||||||
<details>
|
<details>
|
||||||
<summary>Updating Immich using Container Manager</summary>
|
<summary>Updating Immich using Container Manager</summary>
|
||||||
|
|
||||||
Check the post installation and upgrade instructions at the links above before proceeding with this section.
|
Check the post installation and upgrade instructions at the links above before proceeding with this section.
|
||||||
|
|
||||||
## Step 1. Backup
|
## Step 1. Backup
|
||||||
@@ -110,7 +111,7 @@ Go to **Project**, select **Action** then **Build**. This will download, unpack,
|
|||||||
|
|
||||||
## Step 5. Update firewall rule
|
## Step 5. Update firewall rule
|
||||||
|
|
||||||
The default behavior is to automatically start the containers once installed. If `immich_server` runs for a few seconds and then stops, it may be because the firewall rule no longer matches the server IP address.
|
Without a fixed subnet, the default behavior is to automatically start the containers once installed. If `immich_server` runs for a few seconds and then stops, it may be because the firewall rule no longer matches the server IP address.
|
||||||
|
|
||||||
Go to the **Container** section. Click on `immich_server` and scroll down on **General** to find the IP address.
|
Go to the **Container** section. Click on `immich_server` and scroll down on **General** to find the IP address.
|
||||||

|

|
||||||
@@ -123,4 +124,67 @@ In this example, the IP addresses mismatch and the firewall rule needs to be edi
|
|||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
To prevent future firewall issues, you may set a fixed subnet. [See Set Fixed Subnet](#set-fixed-subnet) for instructions.
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<details id="set-fixed-subnet">
|
||||||
|
<summary>Set Fixed Subnet</summary>
|
||||||
|
|
||||||
|
Docker by default assigns dynamic subnets to bridge networks which can change when rebuilding containers and can cause firewall rules to break. To avoid this, define a fixed subnet in your `docker-compose.yml`:
|
||||||
|
|
||||||
|
## Step 1. Determine current subnet
|
||||||
|
|
||||||
|
Go to the **Container** section. Click on `immich_server` and scroll down on **General** to find the IP address.
|
||||||
|

|
||||||
|
|
||||||
|
## Step 2. Add network configuration
|
||||||
|
|
||||||
|
Add the following network configuration at the end of your `docker-compose.yml` file:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
networks:
|
||||||
|
immich-network:
|
||||||
|
driver: bridge
|
||||||
|
ipam:
|
||||||
|
config:
|
||||||
|
- subnet: 172.20.0.0/16
|
||||||
|
gateway: 172.20.0.1
|
||||||
|
```
|
||||||
|
|
||||||
|
If your docker container is running on a different subnet then update accordingly.
|
||||||
|
|
||||||
|
## Step 3. Add network to each service
|
||||||
|
|
||||||
|
Add the network to each service (immich-server, immich-machine-learning, redis, database):
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
services:
|
||||||
|
immich-server:
|
||||||
|
# other config options
|
||||||
|
networks:
|
||||||
|
- immich-network
|
||||||
|
|
||||||
|
immich-machine-learning:
|
||||||
|
# other config options
|
||||||
|
networks:
|
||||||
|
- immich-network
|
||||||
|
|
||||||
|
redis:
|
||||||
|
# other config options
|
||||||
|
networks:
|
||||||
|
- immich-network
|
||||||
|
|
||||||
|
database:
|
||||||
|
# other config options
|
||||||
|
networks:
|
||||||
|
- immich-network
|
||||||
|
```
|
||||||
|
|
||||||
|
Save your changes. Synology will ask if you want to save changes only or rebuild containers. Select rebuild containers.
|
||||||
|
|
||||||
|
## Step 4. Update Firewall Rules, if necessary
|
||||||
|
|
||||||
|
If your firewall rules were not already set for this subnet, the firewall rules will need to be updated. See [Step 4 - Configure Firewall Settings](#step-4---configure-firewall-settings).
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|||||||
@@ -130,7 +130,3 @@ These storage mediums have different performance characteristics. As a result, t
|
|||||||
#### Can I use the new database image as a general PostgreSQL image outside of Immich?
|
#### Can I use the new database image as a general PostgreSQL image outside of Immich?
|
||||||
|
|
||||||
It’s a standard PostgreSQL container image that additionally contains the VectorChord, pgvector, and (optionally) pgvecto.rs extensions. If you were using the previous pgvecto.rs image for other purposes, you can similarly do so with this image.
|
It’s a standard PostgreSQL container image that additionally contains the VectorChord, pgvector, and (optionally) pgvecto.rs extensions. If you were using the previous pgvecto.rs image for other purposes, you can similarly do so with this image.
|
||||||
|
|
||||||
#### If pgvecto.rs and pgvector still work, why should I switch to VectorChord?
|
|
||||||
|
|
||||||
VectorChord is faster, more stable, uses less RAM, and (with the settings Immich uses) offers higher-quality results than pgvector and pgvecto.rs. This translates to better search and facial recognition experiences. In addition, pgvecto.rs support will be dropped in the future, so changing it sooner will avoid disruption.
|
|
||||||
|
|||||||
@@ -56,8 +56,5 @@
|
|||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=20"
|
"node": ">=20"
|
||||||
},
|
|
||||||
"volta": {
|
|
||||||
"node": "24.15.0"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
24.15.0
|
|
||||||
@@ -4,7 +4,7 @@ services:
|
|||||||
e2e-auth-server:
|
e2e-auth-server:
|
||||||
container_name: immich-e2e-auth-server
|
container_name: immich-e2e-auth-server
|
||||||
build:
|
build:
|
||||||
context: ../e2e-auth-server
|
context: ../packages/e2e-auth-server
|
||||||
ports:
|
ports:
|
||||||
- 2286:2286
|
- 2286:2286
|
||||||
|
|
||||||
@@ -44,7 +44,7 @@ services:
|
|||||||
|
|
||||||
redis:
|
redis:
|
||||||
container_name: immich-e2e-redis
|
container_name: immich-e2e-redis
|
||||||
image: docker.io/valkey/valkey:9@sha256:3b55fbaa0cd93cf0d9d961f405e4dfcc70efe325e2d84da207a0a8e6d8fde4f9
|
image: docker.io/valkey/valkey:9@sha256:8436e10bc65c94886a91d4415b6a6dfa9cb5a306fb3b996e5bb67cd2b4854193
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: redis-cli ping || exit 1
|
test: redis-cli ping || exit 1
|
||||||
|
|
||||||
|
|||||||
@@ -27,3 +27,18 @@ run = { task = "lint --fix" }
|
|||||||
[tasks.check]
|
[tasks.check]
|
||||||
env._.path = "./node_modules/.bin"
|
env._.path = "./node_modules/.bin"
|
||||||
run = "tsc --noEmit"
|
run = "tsc --noEmit"
|
||||||
|
|
||||||
|
|
||||||
|
[tasks.ci-setup]
|
||||||
|
depends = ["//:sdk:install", "//:sdk:build", "//cli:install", "//cli:build"]
|
||||||
|
run = { task = ":install" }
|
||||||
|
|
||||||
|
|
||||||
|
[tasks.ci-unit]
|
||||||
|
depends = ["//:sdk:install", "//:sdk:build"]
|
||||||
|
run = [
|
||||||
|
{ task = ":install" },
|
||||||
|
{ task = ":format" },
|
||||||
|
{ task = ":lint" },
|
||||||
|
{ task = ":check" },
|
||||||
|
]
|
||||||
|
|||||||
@@ -56,8 +56,5 @@
|
|||||||
"utimes": "^5.2.1",
|
"utimes": "^5.2.1",
|
||||||
"vite-tsconfig-paths": "^6.1.1",
|
"vite-tsconfig-paths": "^6.1.1",
|
||||||
"vitest": "^4.0.0"
|
"vitest": "^4.0.0"
|
||||||
},
|
|
||||||
"volta": {
|
|
||||||
"node": "24.15.0"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-42
@@ -2,82 +2,44 @@ import { expect } from 'vitest';
|
|||||||
|
|
||||||
export const errorDto = {
|
export const errorDto = {
|
||||||
unauthorized: {
|
unauthorized: {
|
||||||
error: 'Unauthorized',
|
|
||||||
statusCode: 401,
|
|
||||||
message: 'Authentication required',
|
message: 'Authentication required',
|
||||||
correlationId: expect.any(String),
|
|
||||||
},
|
},
|
||||||
unauthorizedWithMessage: (message: string) => ({
|
unauthorizedWithMessage: (message: string) => ({
|
||||||
error: 'Unauthorized',
|
|
||||||
statusCode: 401,
|
|
||||||
message,
|
message,
|
||||||
correlationId: expect.any(String),
|
|
||||||
}),
|
}),
|
||||||
forbidden: {
|
forbidden: {
|
||||||
error: 'Forbidden',
|
|
||||||
statusCode: 403,
|
|
||||||
message: expect.any(String),
|
message: expect.any(String),
|
||||||
correlationId: expect.any(String),
|
|
||||||
},
|
},
|
||||||
missingPermission: (permission: string) => ({
|
missingPermission: (permission: string) => ({
|
||||||
error: 'Forbidden',
|
|
||||||
statusCode: 403,
|
|
||||||
message: `Missing required permission: ${permission}`,
|
message: `Missing required permission: ${permission}`,
|
||||||
correlationId: expect.any(String),
|
|
||||||
}),
|
}),
|
||||||
wrongPassword: {
|
wrongPassword: {
|
||||||
error: 'Bad Request',
|
|
||||||
statusCode: 400,
|
|
||||||
message: 'Wrong password',
|
message: 'Wrong password',
|
||||||
correlationId: expect.any(String),
|
|
||||||
},
|
},
|
||||||
invalidToken: {
|
invalidToken: {
|
||||||
error: 'Unauthorized',
|
|
||||||
statusCode: 401,
|
|
||||||
message: 'Invalid user token',
|
message: 'Invalid user token',
|
||||||
correlationId: expect.any(String),
|
|
||||||
},
|
},
|
||||||
invalidShareKey: {
|
invalidShareKey: {
|
||||||
error: 'Unauthorized',
|
|
||||||
statusCode: 401,
|
|
||||||
message: 'Invalid share key',
|
message: 'Invalid share key',
|
||||||
correlationId: expect.any(String),
|
|
||||||
},
|
},
|
||||||
passwordRequired: {
|
passwordRequired: {
|
||||||
error: 'Unauthorized',
|
|
||||||
statusCode: 401,
|
|
||||||
message: 'Password required',
|
message: 'Password required',
|
||||||
correlationId: expect.any(String),
|
|
||||||
},
|
},
|
||||||
badRequest: (message: any = null) => ({
|
badRequest: (message: any = null) => ({
|
||||||
error: 'Bad Request',
|
|
||||||
statusCode: 400,
|
|
||||||
message: message ?? expect.anything(),
|
message: message ?? expect.anything(),
|
||||||
correlationId: expect.any(String),
|
}),
|
||||||
|
validationError: (errors?: ReadonlyArray<{ path: ReadonlyArray<string | number>; message: string }>) => ({
|
||||||
|
message: 'Validation failed',
|
||||||
|
errors: errors ? expect.arrayContaining(errors.map((e) => expect.objectContaining(e))) : expect.any(Array),
|
||||||
}),
|
}),
|
||||||
noPermission: {
|
noPermission: {
|
||||||
error: 'Bad Request',
|
|
||||||
statusCode: 400,
|
|
||||||
message: expect.stringContaining('Not found or no'),
|
message: expect.stringContaining('Not found or no'),
|
||||||
correlationId: expect.any(String),
|
|
||||||
},
|
},
|
||||||
incorrectLogin: {
|
incorrectLogin: {
|
||||||
error: 'Unauthorized',
|
|
||||||
statusCode: 401,
|
|
||||||
message: 'Incorrect email or password',
|
message: 'Incorrect email or password',
|
||||||
correlationId: expect.any(String),
|
|
||||||
},
|
},
|
||||||
alreadyHasAdmin: {
|
alreadyHasAdmin: {
|
||||||
error: 'Bad Request',
|
|
||||||
statusCode: 400,
|
|
||||||
message: 'The server already has an admin',
|
message: 'The server already has an admin',
|
||||||
correlationId: expect.any(String),
|
|
||||||
},
|
|
||||||
invalidEmail: {
|
|
||||||
error: 'Bad Request',
|
|
||||||
statusCode: 400,
|
|
||||||
message: ['email must be an email'],
|
|
||||||
correlationId: expect.any(String),
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { LoginResponseDto, ManualJobName } from '@immich/sdk';
|
|||||||
import { errorDto } from 'src/responses';
|
import { errorDto } from 'src/responses';
|
||||||
import { app, utils } from 'src/utils';
|
import { app, utils } from 'src/utils';
|
||||||
import request from 'supertest';
|
import request from 'supertest';
|
||||||
import { afterAll, beforeAll, describe, expect, it } from 'vitest';
|
import { afterAll, beforeAll, beforeEach, describe, expect, it } from 'vitest';
|
||||||
|
|
||||||
describe('/admin/database-backups', () => {
|
describe('/admin/database-backups', () => {
|
||||||
let cookie: string | undefined;
|
let cookie: string | undefined;
|
||||||
@@ -13,6 +13,9 @@ describe('/admin/database-backups', () => {
|
|||||||
admin = await utils.adminSetup({
|
admin = await utils.adminSetup({
|
||||||
onboarding: false,
|
onboarding: false,
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
await utils.resetBackups(admin.accessToken);
|
await utils.resetBackups(admin.accessToken);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -146,7 +146,7 @@ describe('/albums', () => {
|
|||||||
|
|
||||||
it('should not return shared albums with a deleted owner', async () => {
|
it('should not return shared albums with a deleted owner', async () => {
|
||||||
const { status, body } = await request(app)
|
const { status, body } = await request(app)
|
||||||
.get('/albums?shared=true')
|
.get('/albums?isShared=true')
|
||||||
.set('Authorization', `Bearer ${user1.accessToken}`);
|
.set('Authorization', `Bearer ${user1.accessToken}`);
|
||||||
|
|
||||||
expect(status).toBe(200);
|
expect(status).toBe(200);
|
||||||
@@ -188,7 +188,7 @@ describe('/albums', () => {
|
|||||||
it('should return the album collection including owned and shared', async () => {
|
it('should return the album collection including owned and shared', async () => {
|
||||||
const { status, body } = await request(app).get('/albums').set('Authorization', `Bearer ${user1.accessToken}`);
|
const { status, body } = await request(app).get('/albums').set('Authorization', `Bearer ${user1.accessToken}`);
|
||||||
expect(status).toBe(200);
|
expect(status).toBe(200);
|
||||||
expect(body).toHaveLength(4);
|
expect(body).toHaveLength(5);
|
||||||
expect(body).toEqual(
|
expect(body).toEqual(
|
||||||
expect.arrayContaining([
|
expect.arrayContaining([
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
@@ -219,13 +219,20 @@ describe('/albums', () => {
|
|||||||
]),
|
]),
|
||||||
shared: false,
|
shared: false,
|
||||||
}),
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
albumName: user2SharedUser,
|
||||||
|
albumUsers: expect.arrayContaining([
|
||||||
|
{ role: AlbumUserRole.Owner, user: expect.objectContaining({ id: user2.userId }) },
|
||||||
|
]),
|
||||||
|
shared: true,
|
||||||
|
}),
|
||||||
]),
|
]),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return the album collection filtered by shared', async () => {
|
it('should return the album collection filtered by isShared', async () => {
|
||||||
const { status, body } = await request(app)
|
const { status, body } = await request(app)
|
||||||
.get('/albums?shared=true')
|
.get('/albums?isShared=true')
|
||||||
.set('Authorization', `Bearer ${user1.accessToken}`);
|
.set('Authorization', `Bearer ${user1.accessToken}`);
|
||||||
expect(status).toBe(200);
|
expect(status).toBe(200);
|
||||||
expect(body).toHaveLength(4);
|
expect(body).toHaveLength(4);
|
||||||
@@ -263,9 +270,9 @@ describe('/albums', () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return the album collection filtered by NOT shared', async () => {
|
it('should return the album collection filtered by NOT isShared', async () => {
|
||||||
const { status, body } = await request(app)
|
const { status, body } = await request(app)
|
||||||
.get('/albums?shared=false')
|
.get('/albums?isShared=false')
|
||||||
.set('Authorization', `Bearer ${user1.accessToken}`);
|
.set('Authorization', `Bearer ${user1.accessToken}`);
|
||||||
expect(status).toBe(200);
|
expect(status).toBe(200);
|
||||||
expect(body).toHaveLength(1);
|
expect(body).toHaveLength(1);
|
||||||
@@ -282,6 +289,63 @@ describe('/albums', () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should return only owned albums when filtered by isOwned=true', async () => {
|
||||||
|
const { status, body } = await request(app)
|
||||||
|
.get('/albums?isOwned=true')
|
||||||
|
.set('Authorization', `Bearer ${user1.accessToken}`);
|
||||||
|
expect(status).toBe(200);
|
||||||
|
expect(body).toHaveLength(4);
|
||||||
|
expect(body).toEqual(
|
||||||
|
expect.arrayContaining([
|
||||||
|
expect.objectContaining({ albumName: user1SharedEditorUser }),
|
||||||
|
expect.objectContaining({ albumName: user1SharedViewerUser }),
|
||||||
|
expect.objectContaining({ albumName: user1SharedLink }),
|
||||||
|
expect.objectContaining({ albumName: user1NotShared }),
|
||||||
|
]),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return only shared-with-me albums when filtered by isOwned=false', async () => {
|
||||||
|
const { status, body } = await request(app)
|
||||||
|
.get('/albums?isOwned=false')
|
||||||
|
.set('Authorization', `Bearer ${user1.accessToken}`);
|
||||||
|
expect(status).toBe(200);
|
||||||
|
expect(body).toHaveLength(1);
|
||||||
|
expect(body).toEqual(
|
||||||
|
expect.arrayContaining([
|
||||||
|
expect.objectContaining({
|
||||||
|
albumName: user2SharedUser,
|
||||||
|
albumUsers: expect.arrayContaining([
|
||||||
|
{ role: AlbumUserRole.Owner, user: expect.objectContaining({ id: user2.userId }) },
|
||||||
|
]),
|
||||||
|
}),
|
||||||
|
]),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return owned shared-out albums when filtered by isOwned=true&ishared=true', async () => {
|
||||||
|
const { status, body } = await request(app)
|
||||||
|
.get('/albums?isOwned=true&isShared=true')
|
||||||
|
.set('Authorization', `Bearer ${user1.accessToken}`);
|
||||||
|
expect(status).toBe(200);
|
||||||
|
expect(body).toHaveLength(3);
|
||||||
|
expect(body).toEqual(
|
||||||
|
expect.arrayContaining([
|
||||||
|
expect.objectContaining({ albumName: user1SharedEditorUser }),
|
||||||
|
expect.objectContaining({ albumName: user1SharedViewerUser }),
|
||||||
|
expect.objectContaining({ albumName: user1SharedLink }),
|
||||||
|
]),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return empty list when filtered by isOwned=false&isShared=false', async () => {
|
||||||
|
const { status, body } = await request(app)
|
||||||
|
.get('/albums?isOwned=false&isShared=false')
|
||||||
|
.set('Authorization', `Bearer ${user1.accessToken}`);
|
||||||
|
expect(status).toBe(200);
|
||||||
|
expect(body).toHaveLength(0);
|
||||||
|
});
|
||||||
|
|
||||||
it('should return the album collection filtered by assetId', async () => {
|
it('should return the album collection filtered by assetId', async () => {
|
||||||
const { status, body } = await request(app)
|
const { status, body } = await request(app)
|
||||||
.get(`/albums?assetId=${user1Asset2.id}`)
|
.get(`/albums?assetId=${user1Asset2.id}`)
|
||||||
@@ -290,17 +354,17 @@ describe('/albums', () => {
|
|||||||
expect(body).toHaveLength(2);
|
expect(body).toHaveLength(2);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return the album collection filtered by assetId and ignores shared=true', async () => {
|
it('should return the album collection filtered by assetId and ignores isShared=true', async () => {
|
||||||
const { status, body } = await request(app)
|
const { status, body } = await request(app)
|
||||||
.get(`/albums?shared=true&assetId=${user1Asset1.id}`)
|
.get(`/albums?isShared=true&assetId=${user1Asset1.id}`)
|
||||||
.set('Authorization', `Bearer ${user1.accessToken}`);
|
.set('Authorization', `Bearer ${user1.accessToken}`);
|
||||||
expect(status).toBe(200);
|
expect(status).toBe(200);
|
||||||
expect(body).toHaveLength(5);
|
expect(body).toHaveLength(5);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return the album collection filtered by assetId and ignores shared=false', async () => {
|
it('should return the album collection filtered by assetId and ignores isShared=false', async () => {
|
||||||
const { status, body } = await request(app)
|
const { status, body } = await request(app)
|
||||||
.get(`/albums?shared=false&assetId=${user1Asset1.id}`)
|
.get(`/albums?isShared=false&assetId=${user1Asset1.id}`)
|
||||||
.set('Authorization', `Bearer ${user1.accessToken}`);
|
.set('Authorization', `Bearer ${user1.accessToken}`);
|
||||||
expect(status).toBe(200);
|
expect(status).toBe(200);
|
||||||
expect(body).toHaveLength(5);
|
expect(body).toHaveLength(5);
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import {
|
|||||||
getMyUser,
|
getMyUser,
|
||||||
LoginResponseDto,
|
LoginResponseDto,
|
||||||
SharedLinkType,
|
SharedLinkType,
|
||||||
updateConfig,
|
|
||||||
} from '@immich/sdk';
|
} from '@immich/sdk';
|
||||||
import { exiftool } from 'exiftool-vendored';
|
import { exiftool } from 'exiftool-vendored';
|
||||||
import { DateTime } from 'luxon';
|
import { DateTime } from 'luxon';
|
||||||
@@ -24,7 +23,6 @@ import { afterAll, beforeAll, describe, expect, it } from 'vitest';
|
|||||||
|
|
||||||
const locationAssetFilepath = `${testAssetDir}/metadata/gps-position/thompson-springs.jpg`;
|
const locationAssetFilepath = `${testAssetDir}/metadata/gps-position/thompson-springs.jpg`;
|
||||||
const ratingAssetFilepath = `${testAssetDir}/metadata/rating/mongolels.jpg`;
|
const ratingAssetFilepath = `${testAssetDir}/metadata/rating/mongolels.jpg`;
|
||||||
const facesAssetDir = `${testAssetDir}/metadata/faces`;
|
|
||||||
|
|
||||||
const readTags = async (bytes: Buffer, filename: string) => {
|
const readTags = async (bytes: Buffer, filename: string) => {
|
||||||
const filepath = join(tempDir, filename);
|
const filepath = join(tempDir, filename);
|
||||||
@@ -185,78 +183,6 @@ describe('/asset', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('faces', () => {
|
|
||||||
const metadataFaceTests = [
|
|
||||||
{
|
|
||||||
description: 'without orientation',
|
|
||||||
filename: 'portrait.jpg',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
description: 'adjusting face regions to orientation',
|
|
||||||
filename: 'portrait-orientation-6.jpg',
|
|
||||||
},
|
|
||||||
];
|
|
||||||
// should produce same resulting face region coordinates for any orientation
|
|
||||||
const expectedFaces = [
|
|
||||||
{
|
|
||||||
name: 'Marie Curie',
|
|
||||||
birthDate: null,
|
|
||||||
isHidden: false,
|
|
||||||
faces: [
|
|
||||||
{
|
|
||||||
imageHeight: 700,
|
|
||||||
imageWidth: 840,
|
|
||||||
boundingBoxX1: 261,
|
|
||||||
boundingBoxX2: 356,
|
|
||||||
boundingBoxY1: 146,
|
|
||||||
boundingBoxY2: 284,
|
|
||||||
sourceType: 'exif',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Pierre Curie',
|
|
||||||
birthDate: null,
|
|
||||||
isHidden: false,
|
|
||||||
faces: [
|
|
||||||
{
|
|
||||||
imageHeight: 700,
|
|
||||||
imageWidth: 840,
|
|
||||||
boundingBoxX1: 536,
|
|
||||||
boundingBoxX2: 618,
|
|
||||||
boundingBoxY1: 83,
|
|
||||||
boundingBoxY2: 252,
|
|
||||||
sourceType: 'exif',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
it.each(metadataFaceTests)('should get the asset faces from $filename $description', async ({ filename }) => {
|
|
||||||
const config = await utils.getSystemConfig(admin.accessToken);
|
|
||||||
config.metadata.faces.import = true;
|
|
||||||
await updateConfig({ systemConfigDto: config }, { headers: asBearerAuth(admin.accessToken) });
|
|
||||||
|
|
||||||
const facesAsset = await utils.createAsset(admin.accessToken, {
|
|
||||||
assetData: {
|
|
||||||
filename,
|
|
||||||
bytes: await readFile(`${facesAssetDir}/${filename}`),
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
await utils.waitForWebsocketEvent({ event: 'assetUpload', id: facesAsset.id });
|
|
||||||
|
|
||||||
const { status, body } = await request(app)
|
|
||||||
.get(`/assets/${facesAsset.id}`)
|
|
||||||
.set('Authorization', `Bearer ${admin.accessToken}`);
|
|
||||||
|
|
||||||
expect(status).toBe(200);
|
|
||||||
expect(body.id).toEqual(facesAsset.id);
|
|
||||||
const sortedPeople = body.people.toSorted((a: any, b: any) => a.name.localeCompare(b.name));
|
|
||||||
expect(sortedPeople).toMatchObject(expectedFaces);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should work with a shared link', async () => {
|
it('should work with a shared link', async () => {
|
||||||
const sharedLink = await utils.createSharedLink(user1.accessToken, {
|
const sharedLink = await utils.createSharedLink(user1.accessToken, {
|
||||||
type: SharedLinkType.Individual,
|
type: SharedLinkType.Individual,
|
||||||
|
|||||||
@@ -110,7 +110,9 @@ describe('/libraries', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
expect(status).toBe(400);
|
expect(status).toBe(400);
|
||||||
expect(body).toEqual(errorDto.badRequest(['[importPaths] Array must have unique items']));
|
expect(body).toEqual(
|
||||||
|
errorDto.validationError([{ path: ['importPaths'], message: 'Array must have unique items' }]),
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not create an external library with duplicate exclusion patterns', async () => {
|
it('should not create an external library with duplicate exclusion patterns', async () => {
|
||||||
@@ -125,7 +127,9 @@ describe('/libraries', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
expect(status).toBe(400);
|
expect(status).toBe(400);
|
||||||
expect(body).toEqual(errorDto.badRequest(['[exclusionPatterns] Array must have unique items']));
|
expect(body).toEqual(
|
||||||
|
errorDto.validationError([{ path: ['exclusionPatterns'], message: 'Array must have unique items' }]),
|
||||||
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -157,7 +161,9 @@ describe('/libraries', () => {
|
|||||||
.send({ name: '' });
|
.send({ name: '' });
|
||||||
|
|
||||||
expect(status).toBe(400);
|
expect(status).toBe(400);
|
||||||
expect(body).toEqual(errorDto.badRequest(['[name] Too small: expected string to have >=1 characters']));
|
expect(body).toEqual(
|
||||||
|
errorDto.validationError([{ path: ['name'], message: 'Too small: expected string to have >=1 characters' }]),
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should change the import paths', async () => {
|
it('should change the import paths', async () => {
|
||||||
@@ -181,7 +187,9 @@ describe('/libraries', () => {
|
|||||||
.send({ importPaths: [''] });
|
.send({ importPaths: [''] });
|
||||||
|
|
||||||
expect(status).toBe(400);
|
expect(status).toBe(400);
|
||||||
expect(body).toEqual(errorDto.badRequest(['[importPaths] Array items must not be empty']));
|
expect(body).toEqual(
|
||||||
|
errorDto.validationError([{ path: ['importPaths'], message: 'Array items must not be empty' }]),
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should reject duplicate import paths', async () => {
|
it('should reject duplicate import paths', async () => {
|
||||||
@@ -191,7 +199,9 @@ describe('/libraries', () => {
|
|||||||
.send({ importPaths: ['/path', '/path'] });
|
.send({ importPaths: ['/path', '/path'] });
|
||||||
|
|
||||||
expect(status).toBe(400);
|
expect(status).toBe(400);
|
||||||
expect(body).toEqual(errorDto.badRequest(['[importPaths] Array must have unique items']));
|
expect(body).toEqual(
|
||||||
|
errorDto.validationError([{ path: ['importPaths'], message: 'Array must have unique items' }]),
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should change the exclusion pattern', async () => {
|
it('should change the exclusion pattern', async () => {
|
||||||
@@ -215,7 +225,9 @@ describe('/libraries', () => {
|
|||||||
.send({ exclusionPatterns: ['**/*.jpg', '**/*.jpg'] });
|
.send({ exclusionPatterns: ['**/*.jpg', '**/*.jpg'] });
|
||||||
|
|
||||||
expect(status).toBe(400);
|
expect(status).toBe(400);
|
||||||
expect(body).toEqual(errorDto.badRequest(['[exclusionPatterns] Array must have unique items']));
|
expect(body).toEqual(
|
||||||
|
errorDto.validationError([{ path: ['exclusionPatterns'], message: 'Array must have unique items' }]),
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should reject an empty exclusion pattern', async () => {
|
it('should reject an empty exclusion pattern', async () => {
|
||||||
@@ -225,7 +237,9 @@ describe('/libraries', () => {
|
|||||||
.send({ exclusionPatterns: [''] });
|
.send({ exclusionPatterns: [''] });
|
||||||
|
|
||||||
expect(status).toBe(400);
|
expect(status).toBe(400);
|
||||||
expect(body).toEqual(errorDto.badRequest(['[exclusionPatterns] Array items must not be empty']));
|
expect(body).toEqual(
|
||||||
|
errorDto.validationError([{ path: ['exclusionPatterns'], message: 'Array items must not be empty' }]),
|
||||||
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -109,7 +109,9 @@ describe('/map', () => {
|
|||||||
.get('/map/reverse-geocode?lon=123')
|
.get('/map/reverse-geocode?lon=123')
|
||||||
.set('Authorization', `Bearer ${admin.accessToken}`);
|
.set('Authorization', `Bearer ${admin.accessToken}`);
|
||||||
expect(status).toBe(400);
|
expect(status).toBe(400);
|
||||||
expect(body).toEqual(errorDto.badRequest(['[lat] Invalid input: expected number, received NaN']));
|
expect(body).toEqual(
|
||||||
|
errorDto.validationError([{ path: ['lat'], message: 'Invalid input: expected number, received NaN' }]),
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw an error if a lat is not a number', async () => {
|
it('should throw an error if a lat is not a number', async () => {
|
||||||
@@ -117,7 +119,9 @@ describe('/map', () => {
|
|||||||
.get('/map/reverse-geocode?lat=abc&lon=123.456')
|
.get('/map/reverse-geocode?lat=abc&lon=123.456')
|
||||||
.set('Authorization', `Bearer ${admin.accessToken}`);
|
.set('Authorization', `Bearer ${admin.accessToken}`);
|
||||||
expect(status).toBe(400);
|
expect(status).toBe(400);
|
||||||
expect(body).toEqual(errorDto.badRequest(['[lat] Invalid input: expected number, received NaN']));
|
expect(body).toEqual(
|
||||||
|
errorDto.validationError([{ path: ['lat'], message: 'Invalid input: expected number, received NaN' }]),
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw an error if a lat is out of range', async () => {
|
it('should throw an error if a lat is out of range', async () => {
|
||||||
@@ -125,7 +129,9 @@ describe('/map', () => {
|
|||||||
.get('/map/reverse-geocode?lat=91&lon=123.456')
|
.get('/map/reverse-geocode?lat=91&lon=123.456')
|
||||||
.set('Authorization', `Bearer ${admin.accessToken}`);
|
.set('Authorization', `Bearer ${admin.accessToken}`);
|
||||||
expect(status).toBe(400);
|
expect(status).toBe(400);
|
||||||
expect(body).toEqual(errorDto.badRequest(['[lat] Too big: expected number to be <=90']));
|
expect(body).toEqual(
|
||||||
|
errorDto.validationError([{ path: ['lat'], message: 'Too big: expected number to be <=90' }]),
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw an error if a lon is not provided', async () => {
|
it('should throw an error if a lon is not provided', async () => {
|
||||||
@@ -133,7 +139,9 @@ describe('/map', () => {
|
|||||||
.get('/map/reverse-geocode?lat=75')
|
.get('/map/reverse-geocode?lat=75')
|
||||||
.set('Authorization', `Bearer ${admin.accessToken}`);
|
.set('Authorization', `Bearer ${admin.accessToken}`);
|
||||||
expect(status).toBe(400);
|
expect(status).toBe(400);
|
||||||
expect(body).toEqual(errorDto.badRequest(['[lon] Invalid input: expected number, received NaN']));
|
expect(body).toEqual(
|
||||||
|
errorDto.validationError([{ path: ['lon'], message: 'Invalid input: expected number, received NaN' }]),
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
const reverseGeocodeTestCases = [
|
const reverseGeocodeTestCases = [
|
||||||
|
|||||||
@@ -105,7 +105,11 @@ describe(`/oauth`, () => {
|
|||||||
it(`should throw an error if a redirect uri is not provided`, async () => {
|
it(`should throw an error if a redirect uri is not provided`, async () => {
|
||||||
const { status, body } = await request(app).post('/oauth/authorize').send({});
|
const { status, body } = await request(app).post('/oauth/authorize').send({});
|
||||||
expect(status).toBe(400);
|
expect(status).toBe(400);
|
||||||
expect(body).toEqual(errorDto.badRequest(['[redirectUri] Invalid input: expected string, received undefined']));
|
expect(body).toEqual(
|
||||||
|
errorDto.validationError([
|
||||||
|
{ path: ['redirectUri'], message: 'Invalid input: expected string, received undefined' },
|
||||||
|
]),
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return a redirect uri', async () => {
|
it('should return a redirect uri', async () => {
|
||||||
@@ -164,13 +168,17 @@ describe(`/oauth`, () => {
|
|||||||
it(`should throw an error if a url is not provided`, async () => {
|
it(`should throw an error if a url is not provided`, async () => {
|
||||||
const { status, body } = await request(app).post('/oauth/callback').send({});
|
const { status, body } = await request(app).post('/oauth/callback').send({});
|
||||||
expect(status).toBe(400);
|
expect(status).toBe(400);
|
||||||
expect(body).toEqual(errorDto.badRequest(['[url] Invalid input: expected string, received undefined']));
|
expect(body).toEqual(
|
||||||
|
errorDto.validationError([{ path: ['url'], message: 'Invalid input: expected string, received undefined' }]),
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it(`should throw an error if the url is empty`, async () => {
|
it(`should throw an error if the url is empty`, async () => {
|
||||||
const { status, body } = await request(app).post('/oauth/callback').send({ url: '' });
|
const { status, body } = await request(app).post('/oauth/callback').send({ url: '' });
|
||||||
expect(status).toBe(400);
|
expect(status).toBe(400);
|
||||||
expect(body).toEqual(errorDto.badRequest(['[url] Too small: expected string to have >=1 characters']));
|
expect(body).toEqual(
|
||||||
|
errorDto.validationError([{ path: ['url'], message: 'Too small: expected string to have >=1 characters' }]),
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it(`should throw an error if the state is not provided`, async () => {
|
it(`should throw an error if the state is not provided`, async () => {
|
||||||
@@ -332,9 +340,7 @@ describe(`/oauth`, () => {
|
|||||||
const { status, body } = await request(app).post('/oauth/callback').send(callbackParams);
|
const { status, body } = await request(app).post('/oauth/callback').send(callbackParams);
|
||||||
expect(status).toBe(500);
|
expect(status).toBe(500);
|
||||||
expect(body).toMatchObject({
|
expect(body).toMatchObject({
|
||||||
error: 'Internal Server Error',
|
|
||||||
message: 'Failed to finish oauth',
|
message: 'Failed to finish oauth',
|
||||||
statusCode: 500,
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -353,7 +359,7 @@ describe(`/oauth`, () => {
|
|||||||
const callbackParams = await loginWithOAuth('oauth-no-auto-register');
|
const callbackParams = await loginWithOAuth('oauth-no-auto-register');
|
||||||
const { status, body } = await request(app).post('/oauth/callback').send(callbackParams);
|
const { status, body } = await request(app).post('/oauth/callback').send(callbackParams);
|
||||||
expect(status).toBe(400);
|
expect(status).toBe(400);
|
||||||
expect(body).toEqual(errorDto.badRequest('User does not exist and auto registering is disabled.'));
|
expect(body).toEqual(errorDto.badRequest('OAuth authentication failed'));
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should link to an existing user by email', async () => {
|
it('should link to an existing user by email', async () => {
|
||||||
@@ -377,7 +383,11 @@ describe(`/oauth`, () => {
|
|||||||
it(`should throw an error if the logout_token is not provided`, async () => {
|
it(`should throw an error if the logout_token is not provided`, async () => {
|
||||||
const { status, body } = await request(app).post('/oauth/backchannel-logout').send({});
|
const { status, body } = await request(app).post('/oauth/backchannel-logout').send({});
|
||||||
expect(status).toBe(400);
|
expect(status).toBe(400);
|
||||||
expect(body).toEqual(errorDto.badRequest(['[logout_token] Invalid input: expected string, received undefined']));
|
expect(body).toEqual(
|
||||||
|
errorDto.validationError([
|
||||||
|
{ path: ['logout_token'], message: 'Invalid input: expected string, received undefined' },
|
||||||
|
]),
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it(`should throw an error if an invalid logout token is provided`, async () => {
|
it(`should throw an error if an invalid logout token is provided`, async () => {
|
||||||
@@ -495,11 +505,10 @@ describe(`/oauth`, () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should reject OAuth discovery over HTTP', async () => {
|
it('should reject OAuth discovery over HTTP', async () => {
|
||||||
const { status, body } = await request(app)
|
const { status } = await request(app)
|
||||||
.post('/oauth/authorize')
|
.post('/oauth/authorize')
|
||||||
.send({ redirectUri: 'http://127.0.0.1:2285/auth/login' });
|
.send({ redirectUri: 'http://127.0.0.1:2285/auth/login' });
|
||||||
expect(status).toBe(500);
|
expect(status).toBe(500);
|
||||||
expect(body).toMatchObject({ statusCode: 500 });
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -441,7 +441,18 @@ describe('/search', () => {
|
|||||||
.get('/search/explore')
|
.get('/search/explore')
|
||||||
.set('Authorization', `Bearer ${admin.accessToken}`);
|
.set('Authorization', `Bearer ${admin.accessToken}`);
|
||||||
expect(status).toBe(200);
|
expect(status).toBe(200);
|
||||||
expect(body).toEqual([{ fieldName: 'exifInfo.city', items: [] }]);
|
expect(Array.isArray(body)).toBe(true);
|
||||||
|
expect(body).toEqual(expect.arrayContaining([{ fieldName: 'exifInfo.city', items: [] }]));
|
||||||
|
expect(body).toEqual(
|
||||||
|
expect.arrayContaining([
|
||||||
|
{
|
||||||
|
fieldName: 'createdAt',
|
||||||
|
items: expect.arrayContaining([
|
||||||
|
expect.objectContaining({ data: expect.objectContaining({ id: assetLast.id }) }),
|
||||||
|
]),
|
||||||
|
},
|
||||||
|
]),
|
||||||
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -341,7 +341,9 @@ describe('/shared-links', () => {
|
|||||||
.set('Authorization', `Bearer ${user1.accessToken}`);
|
.set('Authorization', `Bearer ${user1.accessToken}`);
|
||||||
|
|
||||||
expect(status).toBe(400);
|
expect(status).toBe(400);
|
||||||
expect(body).toEqual(errorDto.badRequest());
|
expect(body).toEqual(
|
||||||
|
errorDto.validationError([{ path: [], message: 'Invalid input: expected object, received undefined' }]),
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should require an asset/album id', async () => {
|
it('should require an asset/album id', async () => {
|
||||||
|
|||||||
@@ -41,7 +41,9 @@ describe('/stacks', () => {
|
|||||||
.send({ assetIds: [asset.id] });
|
.send({ assetIds: [asset.id] });
|
||||||
|
|
||||||
expect(status).toBe(400);
|
expect(status).toBe(400);
|
||||||
expect(body).toEqual(errorDto.badRequest());
|
expect(body).toEqual(
|
||||||
|
errorDto.validationError([{ path: ['assetIds'], message: 'Too small: expected array to have >=2 items' }]),
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should require a valid id', async () => {
|
it('should require a valid id', async () => {
|
||||||
@@ -51,7 +53,12 @@ describe('/stacks', () => {
|
|||||||
.send({ assetIds: [uuidDto.invalid, uuidDto.invalid] });
|
.send({ assetIds: [uuidDto.invalid, uuidDto.invalid] });
|
||||||
|
|
||||||
expect(status).toBe(400);
|
expect(status).toBe(400);
|
||||||
expect(body).toEqual(errorDto.badRequest());
|
expect(body).toEqual(
|
||||||
|
errorDto.validationError([
|
||||||
|
{ path: ['assetIds', 0], message: 'Invalid UUID' },
|
||||||
|
{ path: ['assetIds', 1], message: 'Invalid UUID' },
|
||||||
|
]),
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should require access', async () => {
|
it('should require access', async () => {
|
||||||
|
|||||||
@@ -309,7 +309,7 @@ describe('/tags', () => {
|
|||||||
.get(`/tags/${uuidDto.invalid}`)
|
.get(`/tags/${uuidDto.invalid}`)
|
||||||
.set('Authorization', `Bearer ${admin.accessToken}`);
|
.set('Authorization', `Bearer ${admin.accessToken}`);
|
||||||
expect(status).toBe(400);
|
expect(status).toBe(400);
|
||||||
expect(body).toEqual(errorDto.badRequest(['[id] Invalid UUID']));
|
expect(body).toEqual(errorDto.validationError([{ path: ['id'], message: 'Invalid UUID' }]));
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should get tag details', async () => {
|
it('should get tag details', async () => {
|
||||||
@@ -427,7 +427,7 @@ describe('/tags', () => {
|
|||||||
.delete(`/tags/${uuidDto.invalid}`)
|
.delete(`/tags/${uuidDto.invalid}`)
|
||||||
.set('Authorization', `Bearer ${admin.accessToken}`);
|
.set('Authorization', `Bearer ${admin.accessToken}`);
|
||||||
expect(status).toBe(400);
|
expect(status).toBe(400);
|
||||||
expect(body).toEqual(errorDto.badRequest(['[id] Invalid UUID']));
|
expect(body).toEqual(errorDto.validationError([{ path: ['id'], message: 'Invalid UUID' }]));
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should delete a tag', async () => {
|
it('should delete a tag', async () => {
|
||||||
|
|||||||
@@ -108,14 +108,20 @@ describe('/admin/users', () => {
|
|||||||
expect(body).toEqual(errorDto.forbidden);
|
expect(body).toEqual(errorDto.forbidden);
|
||||||
});
|
});
|
||||||
|
|
||||||
for (const key of ['password', 'email', 'name', 'quotaSizeInBytes', 'shouldChangePassword', 'notify']) {
|
for (const [key, message] of [
|
||||||
|
['password', 'Invalid input: expected string, received null'],
|
||||||
|
['email', 'Invalid input: expected email, received object'],
|
||||||
|
['name', 'Invalid input: expected string, received null'],
|
||||||
|
['shouldChangePassword', 'Invalid input: expected boolean, received null'],
|
||||||
|
['notify', 'Invalid input: expected boolean, received null'],
|
||||||
|
] as const) {
|
||||||
it(`should not allow null ${key}`, async () => {
|
it(`should not allow null ${key}`, async () => {
|
||||||
const { status, body } = await request(app)
|
const { status, body } = await request(app)
|
||||||
.post(`/admin/users`)
|
.post(`/admin/users`)
|
||||||
.set('Authorization', `Bearer ${admin.accessToken}`)
|
.set('Authorization', `Bearer ${admin.accessToken}`)
|
||||||
.send({ ...createUserDto.user1, [key]: null });
|
.send({ ...createUserDto.user1, [key]: null });
|
||||||
expect(status).toBe(400);
|
expect(status).toBe(400);
|
||||||
expect(body).toEqual(errorDto.badRequest());
|
expect(body).toEqual(errorDto.validationError([{ path: [key], message }]));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -153,14 +159,19 @@ describe('/admin/users', () => {
|
|||||||
expect(body).toEqual(errorDto.forbidden);
|
expect(body).toEqual(errorDto.forbidden);
|
||||||
});
|
});
|
||||||
|
|
||||||
for (const key of ['password', 'email', 'name', 'shouldChangePassword']) {
|
for (const [key, message] of [
|
||||||
|
['password', 'Invalid input: expected string, received null'],
|
||||||
|
['email', 'Invalid input: expected email, received object'],
|
||||||
|
['name', 'Invalid input: expected string, received null'],
|
||||||
|
['shouldChangePassword', 'Invalid input: expected boolean, received null'],
|
||||||
|
] as const) {
|
||||||
it(`should not allow null ${key}`, async () => {
|
it(`should not allow null ${key}`, async () => {
|
||||||
const { status, body } = await request(app)
|
const { status, body } = await request(app)
|
||||||
.put(`/admin/users/${uuidDto.notFound}`)
|
.put(`/admin/users/${uuidDto.notFound}`)
|
||||||
.set('Authorization', `Bearer ${admin.accessToken}`)
|
.set('Authorization', `Bearer ${admin.accessToken}`)
|
||||||
.send({ [key]: null });
|
.send({ [key]: null });
|
||||||
expect(status).toBe(400);
|
expect(status).toBe(400);
|
||||||
expect(body).toEqual(errorDto.badRequest());
|
expect(body).toEqual(errorDto.validationError([{ path: [key], message }]));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -120,7 +120,7 @@ describe('/users', () => {
|
|||||||
.set('Authorization', `Bearer ${nonAdmin.accessToken}`);
|
.set('Authorization', `Bearer ${nonAdmin.accessToken}`);
|
||||||
|
|
||||||
expect(status).toBe(400);
|
expect(status).toBe(400);
|
||||||
expect(body).toMatchObject(errorDto.badRequest('Email already in use by another account'));
|
expect(body).toMatchObject(errorDto.badRequest('Email is not available'));
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should update my email', async () => {
|
it('should update my email', async () => {
|
||||||
@@ -179,7 +179,9 @@ describe('/users', () => {
|
|||||||
|
|
||||||
expect(status).toBe(400);
|
expect(status).toBe(400);
|
||||||
expect(body).toEqual(
|
expect(body).toEqual(
|
||||||
errorDto.badRequest(['[download.archiveSize] Invalid input: expected int, received number']),
|
errorDto.validationError([
|
||||||
|
{ path: ['download', 'archiveSize'], message: 'Invalid input: expected int, received number' },
|
||||||
|
]),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -207,7 +209,9 @@ describe('/users', () => {
|
|||||||
|
|
||||||
expect(status).toBe(400);
|
expect(status).toBe(400);
|
||||||
expect(body).toEqual(
|
expect(body).toEqual(
|
||||||
errorDto.badRequest(['[download.includeEmbeddedVideos] Invalid input: expected boolean, received number']),
|
errorDto.validationError([
|
||||||
|
{ path: ['download', 'includeEmbeddedVideos'], message: 'Invalid input: expected boolean, received number' },
|
||||||
|
]),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { readFileSync } from 'node:fs';
|
|||||||
import { immichCli } from 'src/utils';
|
import { immichCli } from 'src/utils';
|
||||||
import { describe, expect, it } from 'vitest';
|
import { describe, expect, it } from 'vitest';
|
||||||
|
|
||||||
const pkg = JSON.parse(readFileSync('../cli/package.json', 'utf8'));
|
const pkg = JSON.parse(readFileSync('../packages/cli/package.json', 'utf8'));
|
||||||
|
|
||||||
describe(`immich --version`, () => {
|
describe(`immich --version`, () => {
|
||||||
describe('immich --version', () => {
|
describe('immich --version', () => {
|
||||||
|
|||||||
@@ -32,8 +32,12 @@ export function generateThumbhash(rng: SeededRandom): string {
|
|||||||
return Array.from({ length: 10 }, () => rng.nextInt(0, 256).toString(16).padStart(2, '0')).join('');
|
return Array.from({ length: 10 }, () => rng.nextInt(0, 256).toString(16).padStart(2, '0')).join('');
|
||||||
}
|
}
|
||||||
|
|
||||||
export function generateDuration(rng: SeededRandom): string {
|
export function generateDuration(rng: SeededRandom): number {
|
||||||
return `${rng.nextInt(GENERATION_CONSTANTS.MIN_VIDEO_DURATION_SECONDS, GENERATION_CONSTANTS.MAX_VIDEO_DURATION_SECONDS)}.${rng.nextInt(0, 1000).toString().padStart(3, '0')}`;
|
return (
|
||||||
|
rng.nextInt(GENERATION_CONSTANTS.MIN_VIDEO_DURATION_SECONDS, GENERATION_CONSTANTS.MAX_VIDEO_DURATION_SECONDS) *
|
||||||
|
1000 +
|
||||||
|
rng.nextInt(0, 1000)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function generateUUID(): string {
|
export function generateUUID(): string {
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ export function toColumnarFormat(assets: MockTimelineAsset[]): TimeBucketAssetRe
|
|||||||
ownerId: [],
|
ownerId: [],
|
||||||
ratio: [],
|
ratio: [],
|
||||||
thumbhash: [],
|
thumbhash: [],
|
||||||
|
createdAt: [],
|
||||||
fileCreatedAt: [],
|
fileCreatedAt: [],
|
||||||
localOffsetHours: [],
|
localOffsetHours: [],
|
||||||
isFavorite: [],
|
isFavorite: [],
|
||||||
@@ -338,7 +339,6 @@ export function toAssetResponseDto(asset: MockTimelineAsset, owner?: UserRespons
|
|||||||
livePhotoVideoId: asset.livePhotoVideoId,
|
livePhotoVideoId: asset.livePhotoVideoId,
|
||||||
tags: [],
|
tags: [],
|
||||||
people: [],
|
people: [],
|
||||||
unassignedFaces: [],
|
|
||||||
stack: asset.stack,
|
stack: asset.stack,
|
||||||
isOffline: false,
|
isOffline: false,
|
||||||
hasMetadata: true,
|
hasMetadata: true,
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ export type MockTimelineAsset = {
|
|||||||
isTrashed: boolean;
|
isTrashed: boolean;
|
||||||
isVideo: boolean;
|
isVideo: boolean;
|
||||||
isImage: boolean;
|
isImage: boolean;
|
||||||
duration: string | null;
|
duration: number | null;
|
||||||
projectionType: string | null;
|
projectionType: string | null;
|
||||||
livePhotoVideoId: string | null;
|
livePhotoVideoId: string | null;
|
||||||
city: string | null;
|
city: string | null;
|
||||||
|
|||||||
@@ -240,7 +240,8 @@ export const setupBaseMockApiRoutes = async (context: BrowserContext, adminUserI
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
await context.route('**/api/albums*', async (route, request) => {
|
await context.route('**/api/albums*', async (route, request) => {
|
||||||
if (request.url().endsWith('albums?shared=true') || request.url().endsWith('albums')) {
|
const url = request.url();
|
||||||
|
if (url.endsWith('albums?isShared=true') || url.endsWith('albums?isOwned=true') || url.endsWith('albums')) {
|
||||||
return route.fulfill({
|
return route.fulfill({
|
||||||
status: 200,
|
status: 200,
|
||||||
contentType: 'application/json',
|
contentType: 'application/json',
|
||||||
|
|||||||
@@ -66,7 +66,6 @@ export const createMockStackAsset = (ownerId: string): AssetResponseDto => {
|
|||||||
livePhotoVideoId: null,
|
livePhotoVideoId: null,
|
||||||
tags: [],
|
tags: [],
|
||||||
people: [],
|
people: [],
|
||||||
unassignedFaces: [],
|
|
||||||
stack: undefined,
|
stack: undefined,
|
||||||
isOffline: false,
|
isOffline: false,
|
||||||
hasMetadata: true,
|
hasMetadata: true,
|
||||||
|
|||||||
@@ -304,7 +304,7 @@ test.describe('Timeline', () => {
|
|||||||
await page.keyboard.down('Shift');
|
await page.keyboard.down('Shift');
|
||||||
await thumbnailUtils.withAssetId(page, assets[2].id).hover();
|
await thumbnailUtils.withAssetId(page, assets[2].id).hover();
|
||||||
await expect(
|
await expect(
|
||||||
thumbnailUtils.locator(page).locator('.absolute.top-0.h-full.w-full.bg-immich-primary.opacity-40'),
|
thumbnailUtils.locator(page).locator('.absolute.top-0.size-full.bg-immich-primary.opacity-40'),
|
||||||
).toHaveCount(3);
|
).toHaveCount(3);
|
||||||
await thumbnailUtils.selectButton(page, assets[2].id).click();
|
await thumbnailUtils.selectButton(page, assets[2].id).click();
|
||||||
await page.keyboard.up('Shift');
|
await page.keyboard.up('Shift');
|
||||||
|
|||||||
+3
-1
@@ -90,7 +90,7 @@ export const tempDir = tmpdir();
|
|||||||
export const asBearerAuth = (accessToken: string) => ({ Authorization: `Bearer ${accessToken}` });
|
export const asBearerAuth = (accessToken: string) => ({ Authorization: `Bearer ${accessToken}` });
|
||||||
export const asKeyAuth = (key: string) => ({ 'x-api-key': key });
|
export const asKeyAuth = (key: string) => ({ 'x-api-key': key });
|
||||||
export const immichCli = (args: string[]) =>
|
export const immichCli = (args: string[]) =>
|
||||||
executeCommand('pnpm', ['exec', 'immich', '-d', `/${tempDir}/immich/`, ...args], { cwd: '../cli' }).promise;
|
executeCommand('pnpm', ['exec', 'immich', '-d', `/${tempDir}/immich/`, ...args], { cwd: '../packages/cli' }).promise;
|
||||||
export const dockerExec = (args: string[]) =>
|
export const dockerExec = (args: string[]) =>
|
||||||
executeCommand('docker', ['exec', '-i', 'immich-e2e-server', '/bin/bash', '-c', args.join(' ')]);
|
executeCommand('docker', ['exec', '-i', 'immich-e2e-server', '/bin/bash', '-c', args.join(' ')]);
|
||||||
export const immichAdmin = (args: string[]) => dockerExec([`immich-admin ${args.join(' ')}`]);
|
export const immichAdmin = (args: string[]) => dockerExec([`immich-admin ${args.join(' ')}`]);
|
||||||
@@ -568,6 +568,8 @@ export const utils = {
|
|||||||
name: ManualJobName.BackupDatabase,
|
name: ManualJobName.BackupDatabase,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
await utils.waitForQueueFinish(accessToken, 'backupDatabase');
|
||||||
|
|
||||||
return utils.poll(
|
return utils.poll(
|
||||||
() => request(app).get('/admin/database-backups').set('Authorization', `Bearer ${accessToken}`),
|
() => request(app).get('/admin/database-backups').set('Authorization', `Bearer ${accessToken}`),
|
||||||
({ status, body }) => status === 200 && body.backups.length === 1,
|
({ status, body }) => status === 200 && body.backups.length === 1,
|
||||||
|
|||||||
+1
-1
Submodule e2e/test-assets updated: 0eac5a3738...6742055402
@@ -5,8 +5,10 @@
|
|||||||
"acknowledge": "Neem kennis",
|
"acknowledge": "Neem kennis",
|
||||||
"action": "Aksie",
|
"action": "Aksie",
|
||||||
"action_common_update": "Werk by",
|
"action_common_update": "Werk by",
|
||||||
|
"action_description": "’n Stel van aksies om op die gefiltreerde bates uit te voer",
|
||||||
"actions": "Aksies",
|
"actions": "Aksies",
|
||||||
"active": "Aktief",
|
"active": "Aktief",
|
||||||
|
"active_count": "Aktief: {count}",
|
||||||
"activity": "Aktiwiteite",
|
"activity": "Aktiwiteite",
|
||||||
"activity_changed": "Aktiwiteit is {enabled, select, true {geaktiveer} other {gedeaktiveer}}",
|
"activity_changed": "Aktiwiteit is {enabled, select, true {geaktiveer} other {gedeaktiveer}}",
|
||||||
"add": "Voeg toe",
|
"add": "Voeg toe",
|
||||||
@@ -14,9 +16,14 @@
|
|||||||
"add_a_location": "Voeg ’n ligging toe",
|
"add_a_location": "Voeg ’n ligging toe",
|
||||||
"add_a_name": "Voeg ’n naam toe",
|
"add_a_name": "Voeg ’n naam toe",
|
||||||
"add_a_title": "Voeg ’n titel toe",
|
"add_a_title": "Voeg ’n titel toe",
|
||||||
|
"add_action": "Voeg aksie toe",
|
||||||
|
"add_action_description": "Klik om ’n aksie toe te voeg om uit te voer",
|
||||||
|
"add_assets": "Voeg bates by",
|
||||||
"add_birthday": "Voeg ’n verjaarsdag toe",
|
"add_birthday": "Voeg ’n verjaarsdag toe",
|
||||||
"add_endpoint": "Voeg eindpunt toe",
|
"add_endpoint": "Voeg eindpunt toe",
|
||||||
"add_exclusion_pattern": "Voeg uitsluitingspatroon toe",
|
"add_exclusion_pattern": "Voeg uitsluitingspatroon toe",
|
||||||
|
"add_filter": "Voeg filter by",
|
||||||
|
"add_filter_description": "Klik om ’n filtervoorwaarde toe te voeg",
|
||||||
"add_location": "Voeg ligging toe",
|
"add_location": "Voeg ligging toe",
|
||||||
"add_more_users": "Voeg meer gebruikers toe",
|
"add_more_users": "Voeg meer gebruikers toe",
|
||||||
"add_partner": "Voeg vennoot toe",
|
"add_partner": "Voeg vennoot toe",
|
||||||
@@ -27,9 +34,13 @@
|
|||||||
"add_to_album": "Voeg toe tot album",
|
"add_to_album": "Voeg toe tot album",
|
||||||
"add_to_album_bottom_sheet_added": "Tot {album} toegevoeg",
|
"add_to_album_bottom_sheet_added": "Tot {album} toegevoeg",
|
||||||
"add_to_album_bottom_sheet_already_exists": "Reeds in {album}",
|
"add_to_album_bottom_sheet_already_exists": "Reeds in {album}",
|
||||||
|
"add_to_album_bottom_sheet_some_local_assets": "Sommige plaaslike bates kon nie toe gevoeg word tot die album nie",
|
||||||
|
"add_to_album_toggle": "Wissel seleksie vir {album}",
|
||||||
"add_to_albums": "Voeg toe tot albums",
|
"add_to_albums": "Voeg toe tot albums",
|
||||||
"add_to_albums_count": "Voeg toe tot albums ({count})",
|
"add_to_albums_count": "Voeg toe tot albums ({count})",
|
||||||
|
"add_to_bottom_bar": "Voeg toe",
|
||||||
"add_to_shared_album": "Voeg toe tot gedeelde album",
|
"add_to_shared_album": "Voeg toe tot gedeelde album",
|
||||||
|
"add_upload_to_stack": "Voeg oplaai by stapel",
|
||||||
"add_url": "Voeg bronadres toe",
|
"add_url": "Voeg bronadres toe",
|
||||||
"added_to_archive": "Tot argief toegevoeg",
|
"added_to_archive": "Tot argief toegevoeg",
|
||||||
"added_to_favorites": "Tot gunstelinge toegevoeg",
|
"added_to_favorites": "Tot gunstelinge toegevoeg",
|
||||||
@@ -46,6 +57,7 @@
|
|||||||
"backup_database": "Skep Databasisstortlêer",
|
"backup_database": "Skep Databasisstortlêer",
|
||||||
"backup_database_enable_description": "Aktiveer databasisstortlêers",
|
"backup_database_enable_description": "Aktiveer databasisstortlêers",
|
||||||
"backup_keep_last_amount": "Aantal vorige stortlêers om te hou",
|
"backup_keep_last_amount": "Aantal vorige stortlêers om te hou",
|
||||||
|
"backup_onboarding_2_description": "plaaslike kopieë op verskillende toestelle. Dit sluit die hooflêers en ’n rugsteun van daardie lêers plaaslik in.",
|
||||||
"backup_onboarding_3_description": "totale kopieë van u data, insluitend die oorspronklike lêers. Dit sluit 1 kopie op ’n ander perseel en 2 lokale kopieë in.",
|
"backup_onboarding_3_description": "totale kopieë van u data, insluitend die oorspronklike lêers. Dit sluit 1 kopie op ’n ander perseel en 2 lokale kopieë in.",
|
||||||
"backup_onboarding_description": "’n <backblaze-link>3-2-1-rugsteunstrategie</backblaze-link> word sterk aanbeveel om u data veilig te hou. Hou kopieë van u foto’s/video’s sowel as die Immich-databasis vir ’n volledige rugsteunoplossing.",
|
"backup_onboarding_description": "’n <backblaze-link>3-2-1-rugsteunstrategie</backblaze-link> word sterk aanbeveel om u data veilig te hou. Hou kopieë van u foto’s/video’s sowel as die Immich-databasis vir ’n volledige rugsteunoplossing.",
|
||||||
"backup_onboarding_footer": "Lees hierdie <link>dokument</link> vir meer inligting oor hoe om ’n rugsteunkopie van Immich te maak.",
|
"backup_onboarding_footer": "Lees hierdie <link>dokument</link> vir meer inligting oor hoe om ’n rugsteunkopie van Immich te maak.",
|
||||||
@@ -61,6 +73,7 @@
|
|||||||
"confirm_reprocess_all_faces": "Is u seker u wil alle gesigte herverwerk? Dit sal ook genoemde mense skoonmaak.",
|
"confirm_reprocess_all_faces": "Is u seker u wil alle gesigte herverwerk? Dit sal ook genoemde mense skoonmaak.",
|
||||||
"confirm_user_password_reset": "Is u seker u wil {user} se wagwoord terugstel?",
|
"confirm_user_password_reset": "Is u seker u wil {user} se wagwoord terugstel?",
|
||||||
"confirm_user_pin_code_reset": "Is u seker u wil {user} se PIN-kode herstel?",
|
"confirm_user_pin_code_reset": "Is u seker u wil {user} se PIN-kode herstel?",
|
||||||
|
"copy_config_to_clipboard_description": "Kopieer die huidige stelselkonfigurasie as ’n JSON‑objek na die klipbord",
|
||||||
"create_job": "Skep taak",
|
"create_job": "Skep taak",
|
||||||
"cron_expression": "Cron-uitdrukking",
|
"cron_expression": "Cron-uitdrukking",
|
||||||
"cron_expression_description": "Stel die skanderingsinterval in met die cron-formaat. Kyk gerus na bv. <link>Crontab Guru</link> vir meer inligting",
|
"cron_expression_description": "Stel die skanderingsinterval in met die cron-formaat. Kyk gerus na bv. <link>Crontab Guru</link> vir meer inligting",
|
||||||
@@ -68,6 +81,8 @@
|
|||||||
"disable_login": "Deaktiveer aantekening",
|
"disable_login": "Deaktiveer aantekening",
|
||||||
"duplicate_detection_job_description": "Begin masjienleer op items om soortgelyke beelde op te spoor. Maak staat op Slimsoek",
|
"duplicate_detection_job_description": "Begin masjienleer op items om soortgelyke beelde op te spoor. Maak staat op Slimsoek",
|
||||||
"exclusion_pattern_description": "Met uitsluitingspatrone kan u lêers en vouers ignoreer wanneer u u biblioteek skandeer. Dit is nuttig as u vouers het wat lêers bevat wat u nie wil invoer nie, soos RAW-lêers.",
|
"exclusion_pattern_description": "Met uitsluitingspatrone kan u lêers en vouers ignoreer wanneer u u biblioteek skandeer. Dit is nuttig as u vouers het wat lêers bevat wat u nie wil invoer nie, soos RAW-lêers.",
|
||||||
|
"export_config_as_json_description": "Laai die huidige stelselkonfigurasie af as ’n JSON‑lêer",
|
||||||
|
"external_libraries_page_description": "Admin eksterne biblioteekbladsy",
|
||||||
"face_detection": "Gesigherkenning",
|
"face_detection": "Gesigherkenning",
|
||||||
"face_detection_description": "Identifiseer die gesigte in media d.m.v. masjienleer. Vir video’s word slegs die duimnael oorweeg. “Herlaai” (ver)werk al die media weer. “Stel terug” verwyder alle huidige gesigdata. “Onverwerk” plaas items in die ry wat nog nie verwerk is nie. Geïdentifiseerde gesigte sal ná voltooiing van Gesigidentifikasie vir Gesigherkenning in die ry geplaas word om hulle in bestaande of nuwe persone te groepeer.",
|
"face_detection_description": "Identifiseer die gesigte in media d.m.v. masjienleer. Vir video’s word slegs die duimnael oorweeg. “Herlaai” (ver)werk al die media weer. “Stel terug” verwyder alle huidige gesigdata. “Onverwerk” plaas items in die ry wat nog nie verwerk is nie. Geïdentifiseerde gesigte sal ná voltooiing van Gesigidentifikasie vir Gesigherkenning in die ry geplaas word om hulle in bestaande of nuwe persone te groepeer.",
|
||||||
"facial_recognition_job_description": "Groepeer gesigte in mense. Die stap is vinniger nadat Gesigherkenning klaar is. “Herstel” (her-)groepeer alle gesigte. “Vermiste” plaas gesigte in ry wat nie ’n persoon gekoppel het nie.",
|
"facial_recognition_job_description": "Groepeer gesigte in mense. Die stap is vinniger nadat Gesigherkenning klaar is. “Herstel” (her-)groepeer alle gesigte. “Vermiste” plaas gesigte in ry wat nie ’n persoon gekoppel het nie.",
|
||||||
|
|||||||
+13
-7
@@ -61,8 +61,8 @@
|
|||||||
"backup_onboarding_1_description": "نسخة خارج الموقع في موقع آخر.",
|
"backup_onboarding_1_description": "نسخة خارج الموقع في موقع آخر.",
|
||||||
"backup_onboarding_2_description": "نسخ محلية على أجهزة مختلفة. يشمل ذلك الملفات الرئيسية ونسخة احتياطية محلية منها.",
|
"backup_onboarding_2_description": "نسخ محلية على أجهزة مختلفة. يشمل ذلك الملفات الرئيسية ونسخة احتياطية محلية منها.",
|
||||||
"backup_onboarding_3_description": "إجمالي نُسخ بياناتك، بما في ذلك الملفات الأصلية. يشمل ذلك نسخةً واحدةً خارج الموقع ونسختين محليتين.",
|
"backup_onboarding_3_description": "إجمالي نُسخ بياناتك، بما في ذلك الملفات الأصلية. يشمل ذلك نسخةً واحدةً خارج الموقع ونسختين محليتين.",
|
||||||
"backup_onboarding_description": "يُنصح باتباع <backblaze-link>استراتيجية النسخ الاحتياطي 3-2- 1</backblaze-link> لحماية بياناتك. احتفظ بنسخ احتياطية من صورك/فيديوهاتك المحمّلة، بالإضافة إلى قاعدة بيانات Immich، لضمان حل نسخ احتياطي شامل.",
|
"backup_onboarding_description": "يُنصح باتباع <backblaze-link>استراتيجية النسخ الاحتياطي 3-2-1</backblaze-link> لحماية بياناتك. يجب عليك الاحتفاظ بنسخ من الصور والفيديوهات المرفوعة، بالإضافة إلى قاعدة بيانات Immich لضمان حل نسخ احتياطي شامل.",
|
||||||
"backup_onboarding_footer": "لمزيد من المعلومات حول النسخ الاحتياطي لـ <link>Immich</link>، يرجى الرجوع إلى <link>الوثائق</link>.",
|
"backup_onboarding_footer": "لمزيد من المعلومات حول النسخ الاحتياطي لـ Immich، يرجى الرجوع إلى <link>الوثائق</link>.",
|
||||||
"backup_onboarding_parts_title": "يتضمن النسخ الاحتياطي 3-2-1 ما يلي:",
|
"backup_onboarding_parts_title": "يتضمن النسخ الاحتياطي 3-2-1 ما يلي:",
|
||||||
"backup_onboarding_title": "النسخ الاحتياطية",
|
"backup_onboarding_title": "النسخ الاحتياطية",
|
||||||
"backup_settings": "إعدادات تفريغ قاعدة البيانات",
|
"backup_settings": "إعدادات تفريغ قاعدة البيانات",
|
||||||
@@ -267,6 +267,8 @@
|
|||||||
"notification_enable_email_notifications": "تفعيل إشعارات البريد الإلكتروني",
|
"notification_enable_email_notifications": "تفعيل إشعارات البريد الإلكتروني",
|
||||||
"notification_settings": "إعدادات الإشعارات",
|
"notification_settings": "إعدادات الإشعارات",
|
||||||
"notification_settings_description": "إدارة إعدادات الإشعارات، بما في ذلك البريد الإلكتروني",
|
"notification_settings_description": "إدارة إعدادات الإشعارات، بما في ذلك البريد الإلكتروني",
|
||||||
|
"oauth_allow_insecure_requests": "السماح بالطلبات الغير الآمنة",
|
||||||
|
"oauth_allow_insecure_requests_description": "تحذير: هذا يعطل التحقق من صحة شهادة أمن طبقة النقل لطلبات الترخيص المفتوح وقد يعرضك الهجمات الوسطية.",
|
||||||
"oauth_auto_launch": "التشغيل التلقائي",
|
"oauth_auto_launch": "التشغيل التلقائي",
|
||||||
"oauth_auto_launch_description": "ابدأ تدفق تسجيل الدخول OAuth تلقائيًا عند الانتقال إلى صفحة تسجيل الدخول",
|
"oauth_auto_launch_description": "ابدأ تدفق تسجيل الدخول OAuth تلقائيًا عند الانتقال إلى صفحة تسجيل الدخول",
|
||||||
"oauth_auto_register": "التسجيل التلقائي",
|
"oauth_auto_register": "التسجيل التلقائي",
|
||||||
@@ -274,6 +276,7 @@
|
|||||||
"oauth_button_text": "نص الزر",
|
"oauth_button_text": "نص الزر",
|
||||||
"oauth_client_secret_description": "مطلوب للعميل السري، او اذا PKCE(مفتاح الاثبات لتبادل الكود) ليس مدعوم من العميل العام.",
|
"oauth_client_secret_description": "مطلوب للعميل السري، او اذا PKCE(مفتاح الاثبات لتبادل الكود) ليس مدعوم من العميل العام.",
|
||||||
"oauth_enable_description": "تسجيل الدخول باستخدام OAuth",
|
"oauth_enable_description": "تسجيل الدخول باستخدام OAuth",
|
||||||
|
"oauth_end_session_url_description": "إعادة توجيه المستخدم إلى معرف الموارد الموحد (URI) هذا عند تسجيل الخروج.",
|
||||||
"oauth_mobile_redirect_uri": "عنوان URI لإعادة التوجيه على الهاتف",
|
"oauth_mobile_redirect_uri": "عنوان URI لإعادة التوجيه على الهاتف",
|
||||||
"oauth_mobile_redirect_uri_override": "تجاوز عنوان URI لإعادة التوجيه على الهاتف",
|
"oauth_mobile_redirect_uri_override": "تجاوز عنوان URI لإعادة التوجيه على الهاتف",
|
||||||
"oauth_mobile_redirect_uri_override_description": "قم بتفعيله عندما لا يسمح موفر OAuth بمعرف URI للجوال، مثل ''{callback}''",
|
"oauth_mobile_redirect_uri_override_description": "قم بتفعيله عندما لا يسمح موفر OAuth بمعرف URI للجوال، مثل ''{callback}''",
|
||||||
@@ -333,7 +336,7 @@
|
|||||||
"storage_template_migration_description": "قم بتطبيق القالب الحالي <link>{template}</link> على المحتويات التي تم رفعها سابقًا",
|
"storage_template_migration_description": "قم بتطبيق القالب الحالي <link>{template}</link> على المحتويات التي تم رفعها سابقًا",
|
||||||
"storage_template_migration_info": "تغييرات النموذج الخزني ستغير جميع الصيغ الى احرف صغيرة. تغييرات النموذج ستنطبق فقط على المحتويات الجديدة. لتطبيق النموذج على المحتويات التي تم رفعها سابقًا، قم بتشغيل <link>{job}</link>.",
|
"storage_template_migration_info": "تغييرات النموذج الخزني ستغير جميع الصيغ الى احرف صغيرة. تغييرات النموذج ستنطبق فقط على المحتويات الجديدة. لتطبيق النموذج على المحتويات التي تم رفعها سابقًا، قم بتشغيل <link>{job}</link>.",
|
||||||
"storage_template_migration_job": "وظيفة تهجير قالب التخزين",
|
"storage_template_migration_job": "وظيفة تهجير قالب التخزين",
|
||||||
"storage_template_more_details": "لمزيد من التفاصيل حول هذه الميزة، يرجى الرجوع إلى <template-link>Storage Template</template-link> و <implications-link>implications</implications-link>.",
|
"storage_template_more_details": "لمزيد من التفاصيل حول هذه الميزة، يرجى الرجوع إلى <template-link>Storage Template</template-link> و <implications-link>implications</implications-link>",
|
||||||
"storage_template_onboarding_description_v2": "عند التفعيل. هذه الخاصية ستقوم بالترتيب التلقائي للملفات بناء على نموذج معرف من قبل المستخدم. رجاء اطلع على <link>التوثيق</link>.",
|
"storage_template_onboarding_description_v2": "عند التفعيل. هذه الخاصية ستقوم بالترتيب التلقائي للملفات بناء على نموذج معرف من قبل المستخدم. رجاء اطلع على <link>التوثيق</link>.",
|
||||||
"storage_template_path_length": "الحد التقريبي لطول المسار: <b>{length, number}</b>/{limit, number}",
|
"storage_template_path_length": "الحد التقريبي لطول المسار: <b>{length, number}</b>/{limit, number}",
|
||||||
"storage_template_settings": "قالب التخزين",
|
"storage_template_settings": "قالب التخزين",
|
||||||
@@ -881,15 +884,12 @@
|
|||||||
"cutoff_date_description": "احتفظ بالصور من آخر…",
|
"cutoff_date_description": "احتفظ بالصور من آخر…",
|
||||||
"cutoff_day": "{count, plural, one {يوم} other {ايام}}",
|
"cutoff_day": "{count, plural, one {يوم} other {ايام}}",
|
||||||
"cutoff_year": "{count, plural, one {سنة} other {سنوات}}",
|
"cutoff_year": "{count, plural, one {سنة} other {سنوات}}",
|
||||||
"daily_title_text_date": "E ، MMM DD",
|
|
||||||
"daily_title_text_date_year": "E ، MMM DD ، yyyy",
|
|
||||||
"dark": "معتم",
|
"dark": "معتم",
|
||||||
"dark_theme": "تبديل المظهر إلى الداكن",
|
"dark_theme": "تبديل المظهر إلى الداكن",
|
||||||
"date": "تاريخ",
|
"date": "تاريخ",
|
||||||
"date_after": "التارخ بعد",
|
"date_after": "التارخ بعد",
|
||||||
"date_and_time": "التاريخ و الوقت",
|
"date_and_time": "التاريخ و الوقت",
|
||||||
"date_before": "التاريخ قبل",
|
"date_before": "التاريخ قبل",
|
||||||
"date_format": "E ، Lll D ، Y • H: MM A",
|
|
||||||
"date_of_birth_saved": "تم حفظ تاريخ الميلاد بنجاح",
|
"date_of_birth_saved": "تم حفظ تاريخ الميلاد بنجاح",
|
||||||
"date_range": "نطاق الموعد",
|
"date_range": "نطاق الموعد",
|
||||||
"day": "يوم",
|
"day": "يوم",
|
||||||
@@ -1392,6 +1392,7 @@
|
|||||||
"light_theme": "التبديل إلى المظهر الفاتح",
|
"light_theme": "التبديل إلى المظهر الفاتح",
|
||||||
"like": "اعجاب",
|
"like": "اعجاب",
|
||||||
"like_deleted": "تم حذف الإعجاب",
|
"like_deleted": "تم حذف الإعجاب",
|
||||||
|
"link": "رابط",
|
||||||
"link_motion_video": "رابط فيديو الحركة",
|
"link_motion_video": "رابط فيديو الحركة",
|
||||||
"link_to_docs": "لمزيد من المعلومات، يُرجى الرجوع إلى <link>الوثائق</link>.",
|
"link_to_docs": "لمزيد من المعلومات، يُرجى الرجوع إلى <link>الوثائق</link>.",
|
||||||
"link_to_oauth": "الربط مع OAuth",
|
"link_to_oauth": "الربط مع OAuth",
|
||||||
@@ -1544,7 +1545,6 @@
|
|||||||
"mobile_app_download_onboarding_note": "قم بتنزيل التطبيق المصاحب للهاتف المحمول باستخدام الخيارات التالية",
|
"mobile_app_download_onboarding_note": "قم بتنزيل التطبيق المصاحب للهاتف المحمول باستخدام الخيارات التالية",
|
||||||
"model": "نموذج",
|
"model": "نموذج",
|
||||||
"month": "شهر",
|
"month": "شهر",
|
||||||
"monthly_title_text_date_format": "ط ط ط",
|
|
||||||
"more": "المزيد",
|
"more": "المزيد",
|
||||||
"move": "تحريك",
|
"move": "تحريك",
|
||||||
"move_down": "انزل الى الاسفل",
|
"move_down": "انزل الى الاسفل",
|
||||||
@@ -1562,6 +1562,8 @@
|
|||||||
"multiselect_grid_edit_gps_err_read_only": "لا يمكن تعديل موقع الأصول (المواد) للقراءة فقط، سوف يتخطى",
|
"multiselect_grid_edit_gps_err_read_only": "لا يمكن تعديل موقع الأصول (المواد) للقراءة فقط، سوف يتخطى",
|
||||||
"mute_memories": "كتم الذكريات",
|
"mute_memories": "كتم الذكريات",
|
||||||
"my_albums": "ألبوماتي",
|
"my_albums": "ألبوماتي",
|
||||||
|
"my_immich_description": "نسخ الصفحة الحالية كرابط Immich الخاص بي",
|
||||||
|
"my_immich_title": "رابط Immich الخاص بي",
|
||||||
"name": "الاسم",
|
"name": "الاسم",
|
||||||
"name_or_nickname": "الاسم أو اللقب",
|
"name_or_nickname": "الاسم أو اللقب",
|
||||||
"name_required": "الاسم مطلوب",
|
"name_required": "الاسم مطلوب",
|
||||||
@@ -1926,6 +1928,8 @@
|
|||||||
"scan_settings": "إعدادات الفحص",
|
"scan_settings": "إعدادات الفحص",
|
||||||
"scanning": "جاري البحث",
|
"scanning": "جاري البحث",
|
||||||
"scanning_for_album": "جارٍ الفحص عن ألبوم...",
|
"scanning_for_album": "جارٍ الفحص عن ألبوم...",
|
||||||
|
"screencast_mode_description": "إظهار مؤشرات أحداث لوحة المفاتيح والماوس على الشاشة",
|
||||||
|
"screencast_mode_title": "تبديل وضع تسجيل الشاشة",
|
||||||
"search": "البحث",
|
"search": "البحث",
|
||||||
"search_albums": "البحث في الألبومات",
|
"search_albums": "البحث في الألبومات",
|
||||||
"search_by_context": "البحث حسب السياق",
|
"search_by_context": "البحث حسب السياق",
|
||||||
@@ -2214,6 +2218,8 @@
|
|||||||
"sync_status": "حالة النسخ المتزامن",
|
"sync_status": "حالة النسخ المتزامن",
|
||||||
"sync_status_subtitle": "عرض وإدارة نظام النسخ المتزامن",
|
"sync_status_subtitle": "عرض وإدارة نظام النسخ المتزامن",
|
||||||
"sync_upload_album_setting_subtitle": "انشئ و ارفع صورك و فديوهاتك الالبومات المختارة في Immich",
|
"sync_upload_album_setting_subtitle": "انشئ و ارفع صورك و فديوهاتك الالبومات المختارة في Immich",
|
||||||
|
"system_theme": "سمة النظام",
|
||||||
|
"system_theme_command_description": "استعمل سمة النظام ({value})",
|
||||||
"tag": "العلامة",
|
"tag": "العلامة",
|
||||||
"tag_assets": "أصول العلامة",
|
"tag_assets": "أصول العلامة",
|
||||||
"tag_created": "تم إنشاء العلامة: {tag}",
|
"tag_created": "تم إنشاء العلامة: {tag}",
|
||||||
|
|||||||
+27
-2
@@ -5,6 +5,7 @@
|
|||||||
"acknowledge": "Təsdiq et",
|
"acknowledge": "Təsdiq et",
|
||||||
"action": "Əməliyyat",
|
"action": "Əməliyyat",
|
||||||
"action_common_update": "Yenilə",
|
"action_common_update": "Yenilə",
|
||||||
|
"action_description": "Filtrlənmiş aktivliklər üzərində yerinə yetiriləcək əməliyyatlar toplusu",
|
||||||
"actions": "Əməliyyatlar",
|
"actions": "Əməliyyatlar",
|
||||||
"active": "Aktiv",
|
"active": "Aktiv",
|
||||||
"active_count": "Aktiv: {count}",
|
"active_count": "Aktiv: {count}",
|
||||||
@@ -15,9 +16,14 @@
|
|||||||
"add_a_location": "Məkan əlavə et",
|
"add_a_location": "Məkan əlavə et",
|
||||||
"add_a_name": "Ad əlavə et",
|
"add_a_name": "Ad əlavə et",
|
||||||
"add_a_title": "Başlıq əlavə et",
|
"add_a_title": "Başlıq əlavə et",
|
||||||
|
"add_action": "Yeni əməliyyat əlavə et",
|
||||||
|
"add_action_description": "Əməliyyat əlavə etmək üçün klikləyin",
|
||||||
|
"add_assets": "Aktivlik əlavə et",
|
||||||
"add_birthday": "Doğum günü əlavə et",
|
"add_birthday": "Doğum günü əlavə et",
|
||||||
"add_endpoint": "Son nöqtə əlavə et",
|
"add_endpoint": "Son nöqtə əlavə et",
|
||||||
"add_exclusion_pattern": "Çıxarma nümunəsi əlavə et",
|
"add_exclusion_pattern": "Çıxarma nümunəsi əlavə et",
|
||||||
|
"add_filter": "Filter əlavə et",
|
||||||
|
"add_filter_description": "Filtr şərti əlavə etmək üçün klik edin",
|
||||||
"add_location": "Məkan əlavə et",
|
"add_location": "Məkan əlavə et",
|
||||||
"add_more_users": "Daha çox istifadəçi əlavə et",
|
"add_more_users": "Daha çox istifadəçi əlavə et",
|
||||||
"add_partner": "Partnyor əlavə et",
|
"add_partner": "Partnyor əlavə et",
|
||||||
@@ -36,6 +42,7 @@
|
|||||||
"add_to_shared_album": "Paylaşılan alboma əlavə et",
|
"add_to_shared_album": "Paylaşılan alboma əlavə et",
|
||||||
"add_upload_to_stack": "Yeni yüklənmə əlavə et",
|
"add_upload_to_stack": "Yeni yüklənmə əlavə et",
|
||||||
"add_url": "URL əlavə et",
|
"add_url": "URL əlavə et",
|
||||||
|
"add_workflow_step": "İş axını addımı əlavə et",
|
||||||
"added_to_archive": "Arxivə əlavə edildi",
|
"added_to_archive": "Arxivə əlavə edildi",
|
||||||
"added_to_favorites": "Sevimlilələrə əlavə edildi",
|
"added_to_favorites": "Sevimlilələrə əlavə edildi",
|
||||||
"added_to_favorites_count": "{count, number} şəkil sevimlilələrə əlavə edildi",
|
"added_to_favorites_count": "{count, number} şəkil sevimlilələrə əlavə edildi",
|
||||||
@@ -46,7 +53,7 @@
|
|||||||
"authentication_settings": "Səlahiyyətləndirmə parametrləri",
|
"authentication_settings": "Səlahiyyətləndirmə parametrləri",
|
||||||
"authentication_settings_description": "Şifrə, OAuth və digər səlahiyyətləndirmə parametrləri",
|
"authentication_settings_description": "Şifrə, OAuth və digər səlahiyyətləndirmə parametrləri",
|
||||||
"authentication_settings_disable_all": "Bütün giriş etmə metodlarını söndürmək istədiyinizdən əminsinizmi? Giriş etmə funksiyası tamamilə söndürüləcəkdir.",
|
"authentication_settings_disable_all": "Bütün giriş etmə metodlarını söndürmək istədiyinizdən əminsinizmi? Giriş etmə funksiyası tamamilə söndürüləcəkdir.",
|
||||||
"authentication_settings_reenable": "Yenidən aktiv etmək üçün <link> Server Əmri</link> -ni istifadə edin.",
|
"authentication_settings_reenable": "Yenidən aktiv etmək üçün <link> Server Əmri</link>-ni istifadə edin.",
|
||||||
"background_task_job": "Arxa plan tapşırıqları",
|
"background_task_job": "Arxa plan tapşırıqları",
|
||||||
"backup_database": "Verilənlər bazasının dump-ını yaradın",
|
"backup_database": "Verilənlər bazasının dump-ını yaradın",
|
||||||
"backup_database_enable_description": "Verilənlər bazasının artıq nüsxələrini aktiv et",
|
"backup_database_enable_description": "Verilənlər bazasının artıq nüsxələrini aktiv et",
|
||||||
@@ -54,6 +61,7 @@
|
|||||||
"backup_onboarding_1_description": "buludda və ya başqa fiziki yerdə saytdan kənar surət.",
|
"backup_onboarding_1_description": "buludda və ya başqa fiziki yerdə saytdan kənar surət.",
|
||||||
"backup_onboarding_2_description": "müxtəlif cihazlarda yerli nüsxələr. Bura əsas fayllar və həmin faylların ehtiyat lokal nüsxəsi daxildir.",
|
"backup_onboarding_2_description": "müxtəlif cihazlarda yerli nüsxələr. Bura əsas fayllar və həmin faylların ehtiyat lokal nüsxəsi daxildir.",
|
||||||
"backup_onboarding_3_description": "orijinal fayllar da daxil olmaqla məlumatlarınızın ümumi surətləri. Buraya 1 kənar nüsxə və 2 lokal nüsxə daxildir.",
|
"backup_onboarding_3_description": "orijinal fayllar da daxil olmaqla məlumatlarınızın ümumi surətləri. Buraya 1 kənar nüsxə və 2 lokal nüsxə daxildir.",
|
||||||
|
"backup_onboarding_description": "<backblaze-link>3-2-1 yedəkləmə strategiyası</backblaze-link> məlumatlarınızı qorumaq üçün tövsiyə olunur. Yüklədiyiniz şəkil və videoların, həmçinin Immich verilənlər bazasının surətlərini saxlamalısınız ki, hərtərəfli yedəkləmə həlli əldə edəsiniz.",
|
||||||
"backup_onboarding_footer": "Immich-in ehtiyat nüsxəsini çıxarmaq haqqında ətraflı məlumat üçün <link>sənədlərə</link> müraciət edin.",
|
"backup_onboarding_footer": "Immich-in ehtiyat nüsxəsini çıxarmaq haqqında ətraflı məlumat üçün <link>sənədlərə</link> müraciət edin.",
|
||||||
"backup_onboarding_parts_title": "3-2-1 ehtiyat nüsxəsinə aşağıdakılar daxildir:",
|
"backup_onboarding_parts_title": "3-2-1 ehtiyat nüsxəsinə aşağıdakılar daxildir:",
|
||||||
"backup_onboarding_title": "Ehtiyat surətlər",
|
"backup_onboarding_title": "Ehtiyat surətlər",
|
||||||
@@ -61,14 +69,31 @@
|
|||||||
"backup_settings_description": "Verilənlər bazasının ehtiyat nüsxə parametrlərini idarə et",
|
"backup_settings_description": "Verilənlər bazasının ehtiyat nüsxə parametrlərini idarə et",
|
||||||
"cleared_jobs": "{job} üçün tapşırıqlar silindi",
|
"cleared_jobs": "{job} üçün tapşırıqlar silindi",
|
||||||
"config_set_by_file": "Konfiqurasiya hal-hazırda konfiqurasiya faylı ilə təyin olunub",
|
"config_set_by_file": "Konfiqurasiya hal-hazırda konfiqurasiya faylı ilə təyin olunub",
|
||||||
"confirm_delete_library": "{library} kitabxanasını silmək istədiyinizdən əminmisiniz?",
|
"confirm_delete_library": "{library} kitabxanasını silmək istədiyinizə əminmisiniz?",
|
||||||
"confirm_email_below": "Təsdiqləmək üçün aşağıya {email} yazın",
|
"confirm_email_below": "Təsdiqləmək üçün aşağıya {email} yazın",
|
||||||
|
"confirm_reprocess_all_faces": "Bütün üzləri yenidən emal etmək istədiyinizə əminsiniz? Bu, həmçinin adlandırılmış şəxsləri siləcək.",
|
||||||
"confirm_user_password_reset": "{user} adlı istifadəçinin şifrəsini sıfırlamaq istədiyinizdən əminmisiniz?",
|
"confirm_user_password_reset": "{user} adlı istifadəçinin şifrəsini sıfırlamaq istədiyinizdən əminmisiniz?",
|
||||||
|
"confirm_user_pin_code_reset": "{user} istifadəçisinin PIN kodunu sıfırlamaq istədiyinizə əminsiniz?",
|
||||||
|
"copy_config_to_clipboard_description": "Cari sistem konfiqurasiyasını JSON obyekt kimi mübadilə buferinə kopyalayın",
|
||||||
|
"create_job": "İş yarat",
|
||||||
|
"cron_expression": "Cron ifadəsi",
|
||||||
|
"cron_expression_description": "Cron formatından istifadə edərək skan intervalını təyin edin. Ətraflı məlumat üçün nümunələrə baxa bilərsiniz. <link>Crontab Guru</link>",
|
||||||
|
"cron_expression_presets": "Cron ifadəsi ön ayarları",
|
||||||
"disable_login": "Giriş etməni söndür",
|
"disable_login": "Giriş etməni söndür",
|
||||||
"duplicate_detection_job_description": "Bənzər şəkilləri tapmaq üçün maşın öyrənməsini işə salın. Bu prosses Smart Search funksiyasına əsaslanır",
|
"duplicate_detection_job_description": "Bənzər şəkilləri tapmaq üçün maşın öyrənməsini işə salın. Bu prosses Smart Search funksiyasına əsaslanır",
|
||||||
|
"exclusion_pattern_description": "İstisna nümunələri kitabxananızı skan edərkən faylları və qovluqları nəzərə almamağa imkan verir. Bu, RAW faylları kimi idxal etmək istəmədiyiniz faylları olan qovluqlarınız olduqda faydalıdır.",
|
||||||
|
"export_config_as_json_description": "Cari sistem konfiqurasiyasını JSON faylı kimi endirin",
|
||||||
|
"external_libraries_page_description": "Admin xarici kitabxana səhifəsi",
|
||||||
"face_detection": "Üz tanıma",
|
"face_detection": "Üz tanıma",
|
||||||
|
"failed_job_command": "{command} əmri {job} işi üçün uğursuz oldu",
|
||||||
"force_delete_user_warning": "XƏBƏRDARLIQ: Bu əməliyyat istifadəçi və bütün məlumatları siləcəkdir. Bu prossesi və silinən faylları geri qaytarmaq olmaz.",
|
"force_delete_user_warning": "XƏBƏRDARLIQ: Bu əməliyyat istifadəçi və bütün məlumatları siləcəkdir. Bu prossesi və silinən faylları geri qaytarmaq olmaz.",
|
||||||
|
"image_format": "Format",
|
||||||
"image_format_description": "WebP, JPEG faylına görə daha kiçik həcmə sahibdir, lakin onu kodlaşdırmaq daha çox vaxt alır.",
|
"image_format_description": "WebP, JPEG faylına görə daha kiçik həcmə sahibdir, lakin onu kodlaşdırmaq daha çox vaxt alır.",
|
||||||
|
"image_fullsize_description": "Böyüdülmüş halda istifadə edilən, metadata-sı silinmiş tam ölçülü şəkil",
|
||||||
|
"image_fullsize_enabled": "Tam ölçülü şəkil generasiyasını aktiv et",
|
||||||
|
"image_fullsize_enabled_description": "Veb üçün uyğun olmayan formatlar üçün tam ölçülü şəkil yaradın. “Daxili önizləməyə üstünlük ver” aktiv olduqda, daxili önizləmələr çevrilmədən birbaşa istifadə olunur. JPEG kimi veb üçün uyğun formatlara təsir etmir.",
|
||||||
|
"image_fullsize_quality_description": "Tam ölçülü şəkil keyfiyyəti (1-100). Daha yüksək dəyər daha yaxşı keyfiyyət verir, lakin daha böyük ölçülü fayl yaradır.",
|
||||||
|
"image_fullsize_title": "Tam ölçülü şəkil tənzimləmələri",
|
||||||
"image_preview_title": "Önizləmə parametrləri",
|
"image_preview_title": "Önizləmə parametrləri",
|
||||||
"image_quality": "Keyfiyyət",
|
"image_quality": "Keyfiyyət",
|
||||||
"image_resolution": "Çözümlülük",
|
"image_resolution": "Çözümlülük",
|
||||||
|
|||||||
+1899
-5
File diff suppressed because it is too large
Load Diff
+55
-4
@@ -267,6 +267,8 @@
|
|||||||
"notification_enable_email_notifications": "Включване на имейл известията",
|
"notification_enable_email_notifications": "Включване на имейл известията",
|
||||||
"notification_settings": "Настройки на известията",
|
"notification_settings": "Настройки на известията",
|
||||||
"notification_settings_description": "Управление на настройките за известия, вкл. имейл",
|
"notification_settings_description": "Управление на настройките за известия, вкл. имейл",
|
||||||
|
"oauth_allow_insecure_requests": "Разрешаване на несигурни заявки",
|
||||||
|
"oauth_allow_insecure_requests_description": "ПРЕДУПРЕЖДЕНИЕ: Това изключва проверката за валидност на TLS сертификата при OAuth заявки и отваря възможност за атака от типа \"човек по средата\".",
|
||||||
"oauth_auto_launch": "Автоматично стартиране",
|
"oauth_auto_launch": "Автоматично стартиране",
|
||||||
"oauth_auto_launch_description": "Автоматично стартиране на вход чрез OAuth, когато се отвори страницата за вход",
|
"oauth_auto_launch_description": "Автоматично стартиране на вход чрез OAuth, когато се отвори страницата за вход",
|
||||||
"oauth_auto_register": "Автоматична регистрация",
|
"oauth_auto_register": "Автоматична регистрация",
|
||||||
@@ -274,9 +276,11 @@
|
|||||||
"oauth_button_text": "Текст на бутона",
|
"oauth_button_text": "Текст на бутона",
|
||||||
"oauth_client_secret_description": "Задължително за поверителен клиент или когато не се поддържа PKCE (Proof Key for Code Exchange) за публичен клиент.",
|
"oauth_client_secret_description": "Задължително за поверителен клиент или когато не се поддържа PKCE (Proof Key for Code Exchange) за публичен клиент.",
|
||||||
"oauth_enable_description": "Влизане с OAuth",
|
"oauth_enable_description": "Влизане с OAuth",
|
||||||
|
"oauth_end_session_url_description": "Пренасочване на потребителя към този URI адрес, когато излезе от системата.",
|
||||||
"oauth_mobile_redirect_uri": "URI за мобилно пренасочване",
|
"oauth_mobile_redirect_uri": "URI за мобилно пренасочване",
|
||||||
"oauth_mobile_redirect_uri_override": "URI пренасочване за мобилни устройства",
|
"oauth_mobile_redirect_uri_override": "URI пренасочване за мобилни устройства",
|
||||||
"oauth_mobile_redirect_uri_override_description": "Разреши когато доставчика за OAuth удостоверяване не позволява за мобилни URI идентификатори, като ''{callback}''",
|
"oauth_mobile_redirect_uri_override_description": "Разреши когато доставчика за OAuth удостоверяване не позволява за мобилни URI идентификатори, като ''{callback}''",
|
||||||
|
"oauth_prompt_description": "Параметър за подкана (напр. select_account, login, consent)",
|
||||||
"oauth_role_claim": "Потвърждение на роля",
|
"oauth_role_claim": "Потвърждение на роля",
|
||||||
"oauth_role_claim_description": "Автоматично предоставяне на административни права при наличие на това потвържение. Потвърждението може да има стойност 'user' или 'admin'.",
|
"oauth_role_claim_description": "Автоматично предоставяне на административни права при наличие на това потвържение. Потвърждението може да има стойност 'user' или 'admin'.",
|
||||||
"oauth_settings": "OAuth",
|
"oauth_settings": "OAuth",
|
||||||
@@ -881,15 +885,13 @@
|
|||||||
"cutoff_date_description": "Запазване на снимки от последните…",
|
"cutoff_date_description": "Запазване на снимки от последните…",
|
||||||
"cutoff_day": "{count, plural, one {ден} other {дни}}",
|
"cutoff_day": "{count, plural, one {ден} other {дни}}",
|
||||||
"cutoff_year": "{count, plural, one {година} other {години}}",
|
"cutoff_year": "{count, plural, one {година} other {години}}",
|
||||||
"daily_title_text_date": "E, dd MMM",
|
|
||||||
"daily_title_text_date_year": "E, dd MMM yyyy",
|
|
||||||
"dark": "Тъмен",
|
"dark": "Тъмен",
|
||||||
"dark_theme": "Премини към тъмна тема",
|
"dark_theme": "Премини към тъмна тема",
|
||||||
"date": "Дата",
|
"date": "Дата",
|
||||||
"date_after": "Дата след",
|
"date_after": "Дата след",
|
||||||
"date_and_time": "Дата и час",
|
"date_and_time": "Дата и час",
|
||||||
"date_before": "Дата преди",
|
"date_before": "Дата преди",
|
||||||
"date_format": "E, d LLL y • h:mm a",
|
"date_of_birth": "Дата на раждане",
|
||||||
"date_of_birth_saved": "Дата на раждане е записана успешно",
|
"date_of_birth_saved": "Дата на раждане е записана успешно",
|
||||||
"date_range": "Период от време",
|
"date_range": "Период от време",
|
||||||
"day": "Ден",
|
"day": "Ден",
|
||||||
@@ -1236,6 +1238,7 @@
|
|||||||
"free_up_space_description": "Преместете архивираните снимки и видеа в кошчето на устройството, за да освободите място. Копията на сървъра ще бъдат запазени.",
|
"free_up_space_description": "Преместете архивираните снимки и видеа в кошчето на устройството, за да освободите място. Копията на сървъра ще бъдат запазени.",
|
||||||
"free_up_space_settings_subtitle": "Освобождаване на място за съхранение на устройството",
|
"free_up_space_settings_subtitle": "Освобождаване на място за съхранение на устройството",
|
||||||
"full_path": "Пълен път: {path}",
|
"full_path": "Пълен път: {path}",
|
||||||
|
"full_path_or_folder": "Пълен път или папка",
|
||||||
"gcast_enabled": "Gооgle Cast",
|
"gcast_enabled": "Gооgle Cast",
|
||||||
"gcast_enabled_description": "За да работи тази функция зарежда външни ресурси от Google.",
|
"gcast_enabled_description": "За да работи тази функция зарежда външни ресурси от Google.",
|
||||||
"general": "Общи",
|
"general": "Общи",
|
||||||
@@ -1392,11 +1395,13 @@
|
|||||||
"light_theme": "Премини към светла тема",
|
"light_theme": "Премини към светла тема",
|
||||||
"like": "Харесайте",
|
"like": "Харесайте",
|
||||||
"like_deleted": "Като изтрит",
|
"like_deleted": "Като изтрит",
|
||||||
|
"link": "Връзка",
|
||||||
"link_motion_video": "Линк към видео",
|
"link_motion_video": "Линк към видео",
|
||||||
"link_to_docs": "За повече информация вижте <link>документацията</link>.",
|
"link_to_docs": "За повече информация вижте <link>документацията</link>.",
|
||||||
"link_to_oauth": "Линк към OAuth",
|
"link_to_oauth": "Линк към OAuth",
|
||||||
"linked_oauth_account": "Свързан OAuth акаунт",
|
"linked_oauth_account": "Свързан OAuth акаунт",
|
||||||
"list": "Лист",
|
"list": "Лист",
|
||||||
|
"live": "Живот",
|
||||||
"loading": "Зареждане",
|
"loading": "Зареждане",
|
||||||
"loading_search_results_failed": "Зареждането на резултатите от търсенето е неуспешно",
|
"loading_search_results_failed": "Зареждането на резултатите от търсенето е неуспешно",
|
||||||
"local": "Локално",
|
"local": "Локално",
|
||||||
@@ -1518,6 +1523,38 @@
|
|||||||
"marked_all_as_read": "Всички маркирани като прочетени",
|
"marked_all_as_read": "Всички маркирани като прочетени",
|
||||||
"matches": "Съвпадения",
|
"matches": "Съвпадения",
|
||||||
"matching_assets": "Съвпадащи обекти",
|
"matching_assets": "Съвпадащи обекти",
|
||||||
|
"media_chrome": {
|
||||||
|
"auto": "Авто",
|
||||||
|
"captions": "Субтитри",
|
||||||
|
"captions_off": "Изключенo",
|
||||||
|
"closed_captions": "субтитри",
|
||||||
|
"decode_error": "Грешка при декодиране",
|
||||||
|
"disable_captions": "Изключи субтитри",
|
||||||
|
"enable_captions": "Включи субтитри",
|
||||||
|
"enter_fullscreen_mode": "На цял екран",
|
||||||
|
"exit_fullscreen_mode": "Изход от цял екран",
|
||||||
|
"loop": "Повтаряй",
|
||||||
|
"media_error_description": "Възпроизвеждането е спряно поради грешка във файла. Може би файлът е повреден или браузъра не поддържа този формат.",
|
||||||
|
"media_loading": "зареждане на медия",
|
||||||
|
"mute": "Без звук",
|
||||||
|
"network_error": "Грешка в мрежата",
|
||||||
|
"network_error_description": "Прекъсване на зареждането поради грешка в мрежата.",
|
||||||
|
"not_supported_error": "Този източник не се поддържа",
|
||||||
|
"playback_rate": "Скорост на възпроизвеждане",
|
||||||
|
"playback_rate_current": "текуща скорост на възпроизвеждане",
|
||||||
|
"playback_rate_value": "Скорост на възпроизвеждане {playbackRate}",
|
||||||
|
"playback_time": "продължителност",
|
||||||
|
"quality": "Качество",
|
||||||
|
"second": "секунда",
|
||||||
|
"seconds": "секунди",
|
||||||
|
"time_value_of_total_time": "{currentTime} от {totalTime}",
|
||||||
|
"time_value_remaining": "{time} остават",
|
||||||
|
"unmute": "Включи звук",
|
||||||
|
"unsupported_error_description": "Възникна непоправима грешка. Проблем в сървъра или мрежата, възможно е браузъра да не поддържа този формат.",
|
||||||
|
"video_not_loaded_unknown_time": "не е заредено видео, неизвестно време.",
|
||||||
|
"video_player": "видеоплеер",
|
||||||
|
"volume": "сила на звука"
|
||||||
|
},
|
||||||
"media_type": "Вид медия",
|
"media_type": "Вид медия",
|
||||||
"memories": "Спомени",
|
"memories": "Спомени",
|
||||||
"memories_all_caught_up": "Това е всичко за днес",
|
"memories_all_caught_up": "Това е всичко за днес",
|
||||||
@@ -1544,8 +1581,8 @@
|
|||||||
"mobile_app_download_onboarding_note": "Свалете мобилното приложение Immich с някоя от следните опции",
|
"mobile_app_download_onboarding_note": "Свалете мобилното приложение Immich с някоя от следните опции",
|
||||||
"model": "Модел",
|
"model": "Модел",
|
||||||
"month": "Месец",
|
"month": "Месец",
|
||||||
"monthly_title_text_date_format": "MMMM г",
|
|
||||||
"more": "Още",
|
"more": "Още",
|
||||||
|
"motion": "Движение",
|
||||||
"move": "Премести",
|
"move": "Премести",
|
||||||
"move_down": "Премести надолу",
|
"move_down": "Премести надолу",
|
||||||
"move_off_locked_folder": "Извади от заключената папка",
|
"move_off_locked_folder": "Извади от заключената папка",
|
||||||
@@ -1562,6 +1599,8 @@
|
|||||||
"multiselect_grid_edit_gps_err_read_only": "Не може да се редактира местоположението на обект само за четене, пропускане",
|
"multiselect_grid_edit_gps_err_read_only": "Не може да се редактира местоположението на обект само за четене, пропускане",
|
||||||
"mute_memories": "Изключване на звука на спомените",
|
"mute_memories": "Изключване на звука на спомените",
|
||||||
"my_albums": "Мои албуми",
|
"my_albums": "Мои албуми",
|
||||||
|
"my_immich_description": "Копирай адреса на текущата страница като връзка към моя Immich",
|
||||||
|
"my_immich_title": "Връзка към моя Immich",
|
||||||
"name": "Име",
|
"name": "Име",
|
||||||
"name_or_nickname": "Име или прякор",
|
"name_or_nickname": "Име или прякор",
|
||||||
"name_required": "Задължително е Име",
|
"name_required": "Задължително е Име",
|
||||||
@@ -1853,6 +1892,7 @@
|
|||||||
"remove_assets_title": "Премахване на елементите?",
|
"remove_assets_title": "Премахване на елементите?",
|
||||||
"remove_custom_date_range": "Премахни зададения диапазон от дати",
|
"remove_custom_date_range": "Премахни зададения диапазон от дати",
|
||||||
"remove_deleted_assets": "Премахни Изтритите Елементи",
|
"remove_deleted_assets": "Премахни Изтритите Елементи",
|
||||||
|
"remove_filter": "Премахни филтър",
|
||||||
"remove_from_album": "Премахни от албума",
|
"remove_from_album": "Премахни от албума",
|
||||||
"remove_from_album_action_prompt": "{count} са премахнати от албума",
|
"remove_from_album_action_prompt": "{count} са премахнати от албума",
|
||||||
"remove_from_favorites": "Премахни от Любими",
|
"remove_from_favorites": "Премахни от Любими",
|
||||||
@@ -1926,6 +1966,8 @@
|
|||||||
"scan_settings": "Сканирай настройките",
|
"scan_settings": "Сканирай настройките",
|
||||||
"scanning": "Сканиране",
|
"scanning": "Сканиране",
|
||||||
"scanning_for_album": "Сканирай за албум...",
|
"scanning_for_album": "Сканирай за албум...",
|
||||||
|
"screencast_mode_description": "Показване на екрана на индикатори за събития от клавиатурата и мишката",
|
||||||
|
"screencast_mode_title": "Превключване на режима на скрийнкаст",
|
||||||
"search": "Търсене",
|
"search": "Търсене",
|
||||||
"search_albums": "Търси албуми",
|
"search_albums": "Търси албуми",
|
||||||
"search_by_context": "Търси по контекст",
|
"search_by_context": "Търси по контекст",
|
||||||
@@ -1933,6 +1975,8 @@
|
|||||||
"search_by_description_example": "Разходка в Сапа",
|
"search_by_description_example": "Разходка в Сапа",
|
||||||
"search_by_filename": "Търси по име на файла или разширение",
|
"search_by_filename": "Търси по име на файла или разширение",
|
||||||
"search_by_filename_example": "например IMG_1234.JPG или PNG",
|
"search_by_filename_example": "например IMG_1234.JPG или PNG",
|
||||||
|
"search_by_full_path": "Търсене по пълен път или папка",
|
||||||
|
"search_by_full_path_example": "/John/Projects/3D_Printing/2026-07-01 - търсена за Projects, 3D, Printing, 2026 и т.н.",
|
||||||
"search_by_ocr": "Търсене на текст",
|
"search_by_ocr": "Търсене на текст",
|
||||||
"search_by_ocr_example": "Lattе",
|
"search_by_ocr_example": "Lattе",
|
||||||
"search_camera_lens_model": "Търсене на модел на обектива...",
|
"search_camera_lens_model": "Търсене на модел на обектива...",
|
||||||
@@ -2148,6 +2192,7 @@
|
|||||||
"show_schema": "Покажи схема",
|
"show_schema": "Покажи схема",
|
||||||
"show_search_options": "Показване на опциите за търсене",
|
"show_search_options": "Показване на опциите за търсене",
|
||||||
"show_shared_links": "Покажи споделени линкове",
|
"show_shared_links": "Покажи споделени линкове",
|
||||||
|
"show_slideshow_metadata_overlay": "Покажи информационния слой",
|
||||||
"show_slideshow_transition": "Покажи прехода на слайдшоуто",
|
"show_slideshow_transition": "Покажи прехода на слайдшоуто",
|
||||||
"show_supporter_badge": "Значка поддръжник",
|
"show_supporter_badge": "Значка поддръжник",
|
||||||
"show_supporter_badge_description": "Покажи значка поддръжник",
|
"show_supporter_badge_description": "Покажи значка поддръжник",
|
||||||
@@ -2163,6 +2208,9 @@
|
|||||||
"skip_to_folders": "Премини към папките",
|
"skip_to_folders": "Премини към папките",
|
||||||
"skip_to_tags": "Премини към етикетите",
|
"skip_to_tags": "Премини към етикетите",
|
||||||
"slideshow": "Слайдшоу",
|
"slideshow": "Слайдшоу",
|
||||||
|
"slideshow_metadata_overlay_mode": "Съдържание на слоя с информация",
|
||||||
|
"slideshow_metadata_overlay_mode_description_only": "Само описание",
|
||||||
|
"slideshow_metadata_overlay_mode_full": "Пълна",
|
||||||
"slideshow_repeat": "Повтаряй слайдшоуто",
|
"slideshow_repeat": "Повтаряй слайдшоуто",
|
||||||
"slideshow_repeat_description": "Започвай отново, когато слайдшоуто приключи",
|
"slideshow_repeat_description": "Започвай отново, когато слайдшоуто приключи",
|
||||||
"slideshow_settings": "Настройки за слайдшоу",
|
"slideshow_settings": "Настройки за слайдшоу",
|
||||||
@@ -2214,6 +2262,8 @@
|
|||||||
"sync_status": "Състояние на синхронизацията",
|
"sync_status": "Състояние на синхронизацията",
|
||||||
"sync_status_subtitle": "Преглед и управление на системата за синхронизация",
|
"sync_status_subtitle": "Преглед и управление на системата за синхронизация",
|
||||||
"sync_upload_album_setting_subtitle": "Създавайте и зареждайте снимки и видеа в избрани албуми в Immich",
|
"sync_upload_album_setting_subtitle": "Създавайте и зареждайте снимки и видеа в избрани албуми в Immich",
|
||||||
|
"system_theme": "Тема от системата",
|
||||||
|
"system_theme_command_description": "Използвай системната тема ({value})",
|
||||||
"tag": "Таг",
|
"tag": "Таг",
|
||||||
"tag_assets": "Тагни елементи",
|
"tag_assets": "Тагни елементи",
|
||||||
"tag_created": "Създаден етикет: {tag}",
|
"tag_created": "Създаден етикет: {tag}",
|
||||||
@@ -2425,6 +2475,7 @@
|
|||||||
"workflows": "Работни процеси",
|
"workflows": "Работни процеси",
|
||||||
"workflows_help_text": "Работните процеси автоматизират действията с вашите обекти чрез тригери и филтри",
|
"workflows_help_text": "Работните процеси автоматизират действията с вашите обекти чрез тригери и филтри",
|
||||||
"wrong_pin_code": "Грешен PIN код",
|
"wrong_pin_code": "Грешен PIN код",
|
||||||
|
"x_of_total": "{x}/{total}",
|
||||||
"year": "Година",
|
"year": "Година",
|
||||||
"years_ago": "преди {years, plural, one {# година} other {# години}}",
|
"years_ago": "преди {years, plural, one {# година} other {# години}}",
|
||||||
"yes": "Да",
|
"yes": "Да",
|
||||||
|
|||||||
+55
-4
@@ -267,6 +267,8 @@
|
|||||||
"notification_enable_email_notifications": "Habilita les notificacions de correu electrònic",
|
"notification_enable_email_notifications": "Habilita les notificacions de correu electrònic",
|
||||||
"notification_settings": "Configuració de notificacions",
|
"notification_settings": "Configuració de notificacions",
|
||||||
"notification_settings_description": "Gestiona la configuració de notificacions, incloent-hi el correu electrònic",
|
"notification_settings_description": "Gestiona la configuració de notificacions, incloent-hi el correu electrònic",
|
||||||
|
"oauth_allow_insecure_requests": "Permet sol·licituds no segures",
|
||||||
|
"oauth_allow_insecure_requests_description": "AVÍS: Això inhabilita la validació de certificats TLS per a les sol·licituds OAuth i us pot exposar a atacs MITM.",
|
||||||
"oauth_auto_launch": "Execució automàtica",
|
"oauth_auto_launch": "Execució automàtica",
|
||||||
"oauth_auto_launch_description": "Inicia el flux d'inici de sessió OAuth automàticament en accedir a la pàgina d'inici de sessió",
|
"oauth_auto_launch_description": "Inicia el flux d'inici de sessió OAuth automàticament en accedir a la pàgina d'inici de sessió",
|
||||||
"oauth_auto_register": "Registre automàtic",
|
"oauth_auto_register": "Registre automàtic",
|
||||||
@@ -274,9 +276,11 @@
|
|||||||
"oauth_button_text": "Text del botó",
|
"oauth_button_text": "Text del botó",
|
||||||
"oauth_client_secret_description": "Requerit per clients confidencials, o si PKCE (Proof Key for Code Exchange) no està suportat pel client públic.",
|
"oauth_client_secret_description": "Requerit per clients confidencials, o si PKCE (Proof Key for Code Exchange) no està suportat pel client públic.",
|
||||||
"oauth_enable_description": "Iniciar sessió amb OAuth",
|
"oauth_enable_description": "Iniciar sessió amb OAuth",
|
||||||
|
"oauth_end_session_url_description": "Redirigeix l'usuari a aquest URI quan tanqui la sessió.",
|
||||||
"oauth_mobile_redirect_uri": "URI de redirecció mòbil",
|
"oauth_mobile_redirect_uri": "URI de redirecció mòbil",
|
||||||
"oauth_mobile_redirect_uri_override": "Sobreescriu l'URI de redirecció mòbil",
|
"oauth_mobile_redirect_uri_override": "Sobreescriu l'URI de redirecció mòbil",
|
||||||
"oauth_mobile_redirect_uri_override_description": "Habilita quan el proveïdor d'OAuth no permet una URI mòbil, com ara ''{callback}''",
|
"oauth_mobile_redirect_uri_override_description": "Habilita quan el proveïdor d'OAuth no permet una URI mòbil, com ara ''{callback}''",
|
||||||
|
"oauth_prompt_description": "Paràmetre de sol·licitud (per exemple, select_account, login, consent)",
|
||||||
"oauth_role_claim": "Concessió de rol",
|
"oauth_role_claim": "Concessió de rol",
|
||||||
"oauth_role_claim_description": "Atorgar accés d'administrador automàticament segons la presència d'aquesta concessió. La concessió pot ser 'usuari' o 'admin'.",
|
"oauth_role_claim_description": "Atorgar accés d'administrador automàticament segons la presència d'aquesta concessió. La concessió pot ser 'usuari' o 'admin'.",
|
||||||
"oauth_settings": "OAuth",
|
"oauth_settings": "OAuth",
|
||||||
@@ -881,15 +885,13 @@
|
|||||||
"cutoff_date_description": "Manté fotos des de l'últim…",
|
"cutoff_date_description": "Manté fotos des de l'últim…",
|
||||||
"cutoff_day": "{count, plural, one {dia} other {dies}}",
|
"cutoff_day": "{count, plural, one {dia} other {dies}}",
|
||||||
"cutoff_year": "{count, plural, one {any} other {anys}}",
|
"cutoff_year": "{count, plural, one {any} other {anys}}",
|
||||||
"daily_title_text_date": "E, dd MMM",
|
|
||||||
"daily_title_text_date_year": "E, dd MMM, yyyy",
|
|
||||||
"dark": "Fosc",
|
"dark": "Fosc",
|
||||||
"dark_theme": "Canvia a tema fosc",
|
"dark_theme": "Canvia a tema fosc",
|
||||||
"date": "Data",
|
"date": "Data",
|
||||||
"date_after": "Data posterior a",
|
"date_after": "Data posterior a",
|
||||||
"date_and_time": "Data i hora",
|
"date_and_time": "Data i hora",
|
||||||
"date_before": "Data anterior a",
|
"date_before": "Data anterior a",
|
||||||
"date_format": "E, d LLL, y • hh:mm",
|
"date_of_birth": "Data de naixement",
|
||||||
"date_of_birth_saved": "Data de naixement guardada amb èxit",
|
"date_of_birth_saved": "Data de naixement guardada amb èxit",
|
||||||
"date_range": "Interval de dates",
|
"date_range": "Interval de dates",
|
||||||
"day": "Dia",
|
"day": "Dia",
|
||||||
@@ -1236,6 +1238,7 @@
|
|||||||
"free_up_space_description": "Mou fotos i videos que ja tinguen còpia al servidor a la paperera del teu dispositiu per alliberar espai. Les còpies del servidor no es modificaran.",
|
"free_up_space_description": "Mou fotos i videos que ja tinguen còpia al servidor a la paperera del teu dispositiu per alliberar espai. Les còpies del servidor no es modificaran.",
|
||||||
"free_up_space_settings_subtitle": "Alliberar espai del dispositiu",
|
"free_up_space_settings_subtitle": "Alliberar espai del dispositiu",
|
||||||
"full_path": "Ruta completa: {path}",
|
"full_path": "Ruta completa: {path}",
|
||||||
|
"full_path_or_folder": "Camí sencer o carpeta",
|
||||||
"gcast_enabled": "Google Cast",
|
"gcast_enabled": "Google Cast",
|
||||||
"gcast_enabled_description": "Aquesta funció carrega recursos externs de Google per funcionar.",
|
"gcast_enabled_description": "Aquesta funció carrega recursos externs de Google per funcionar.",
|
||||||
"general": "General",
|
"general": "General",
|
||||||
@@ -1392,11 +1395,13 @@
|
|||||||
"light_theme": "Canviar a tema clar",
|
"light_theme": "Canviar a tema clar",
|
||||||
"like": "M'agrada",
|
"like": "M'agrada",
|
||||||
"like_deleted": "M'agrada suprimit",
|
"like_deleted": "M'agrada suprimit",
|
||||||
|
"link": "Enllaç",
|
||||||
"link_motion_video": "Enllaçar vídeo en moviment",
|
"link_motion_video": "Enllaçar vídeo en moviment",
|
||||||
"link_to_docs": "Per més informació, mirar la <link>documentation</link>.",
|
"link_to_docs": "Per més informació, mirar la <link>documentation</link>.",
|
||||||
"link_to_oauth": "Enllaç a OAuth",
|
"link_to_oauth": "Enllaç a OAuth",
|
||||||
"linked_oauth_account": "Compte OAuth enllaçat",
|
"linked_oauth_account": "Compte OAuth enllaçat",
|
||||||
"list": "Llista",
|
"list": "Llista",
|
||||||
|
"live": "En viu",
|
||||||
"loading": "Carregant",
|
"loading": "Carregant",
|
||||||
"loading_search_results_failed": "No s'han pogut carregar els resultats de la cerca",
|
"loading_search_results_failed": "No s'han pogut carregar els resultats de la cerca",
|
||||||
"local": "Local",
|
"local": "Local",
|
||||||
@@ -1518,6 +1523,38 @@
|
|||||||
"marked_all_as_read": "Marcat tot com a llegit",
|
"marked_all_as_read": "Marcat tot com a llegit",
|
||||||
"matches": "Coincidències",
|
"matches": "Coincidències",
|
||||||
"matching_assets": "Recursos Coincidents",
|
"matching_assets": "Recursos Coincidents",
|
||||||
|
"media_chrome": {
|
||||||
|
"auto": "Auto",
|
||||||
|
"captions": "Llegendes",
|
||||||
|
"captions_off": "Desactivat",
|
||||||
|
"closed_captions": "Llegendes tancades",
|
||||||
|
"decode_error": "Error de decodificació",
|
||||||
|
"disable_captions": "Desactivar llegendes",
|
||||||
|
"enable_captions": "Activar llegendes",
|
||||||
|
"enter_fullscreen_mode": "Activar mode pantalla sencera",
|
||||||
|
"exit_fullscreen_mode": "Desactivar mode pantalla sencera",
|
||||||
|
"loop": "Bucle",
|
||||||
|
"media_error_description": "Un error dels mitjans ha provocat l'aturada de la reproducció. El mitjà pot estar corromput o el navegador no suporta el format.",
|
||||||
|
"media_loading": "carregant el mitjà",
|
||||||
|
"mute": "Silencia",
|
||||||
|
"network_error": "Error de xarxa",
|
||||||
|
"network_error_description": "Un error de xarxa ha provocat la fallada de la descarrega.",
|
||||||
|
"not_supported_error": "Font origen no suportada",
|
||||||
|
"playback_rate": "Velocitat de reproducció",
|
||||||
|
"playback_rate_current": "velocitat actual de reproducció",
|
||||||
|
"playback_rate_value": "Velocitat de reproducció {playbackRate}",
|
||||||
|
"playback_time": "temps de reproducció",
|
||||||
|
"quality": "Quallitat",
|
||||||
|
"second": "segon",
|
||||||
|
"seconds": "segons",
|
||||||
|
"time_value_of_total_time": "{currentTime} de {totalTime}",
|
||||||
|
"time_value_remaining": "{time} restant",
|
||||||
|
"unmute": "Activa so",
|
||||||
|
"unsupported_error_description": "Un error no suportat ha passat. El servidor o la xarxa han fallat, o el vostre navegador no accepta aquest format.",
|
||||||
|
"video_not_loaded_unknown_time": "vídeo no carregat, temps desconegut.",
|
||||||
|
"video_player": "reproductor de vídeo",
|
||||||
|
"volume": "volum"
|
||||||
|
},
|
||||||
"media_type": "Tipus de mitjà",
|
"media_type": "Tipus de mitjà",
|
||||||
"memories": "Records",
|
"memories": "Records",
|
||||||
"memories_all_caught_up": "Posat al dia",
|
"memories_all_caught_up": "Posat al dia",
|
||||||
@@ -1544,8 +1581,8 @@
|
|||||||
"mobile_app_download_onboarding_note": "Descarregar la App de mòbil fent servir les seguents opcions",
|
"mobile_app_download_onboarding_note": "Descarregar la App de mòbil fent servir les seguents opcions",
|
||||||
"model": "Model",
|
"model": "Model",
|
||||||
"month": "Mes",
|
"month": "Mes",
|
||||||
"monthly_title_text_date_format": "MMMM a",
|
|
||||||
"more": "Més",
|
"more": "Més",
|
||||||
|
"motion": "Moviment",
|
||||||
"move": "Moure",
|
"move": "Moure",
|
||||||
"move_down": "Moure cap avall",
|
"move_down": "Moure cap avall",
|
||||||
"move_off_locked_folder": "Moure fora de la carpeta bloquejada",
|
"move_off_locked_folder": "Moure fora de la carpeta bloquejada",
|
||||||
@@ -1562,6 +1599,8 @@
|
|||||||
"multiselect_grid_edit_gps_err_read_only": "No es pot canviar la localització de fitxers de només lectura, saltant",
|
"multiselect_grid_edit_gps_err_read_only": "No es pot canviar la localització de fitxers de només lectura, saltant",
|
||||||
"mute_memories": "Silenciar records",
|
"mute_memories": "Silenciar records",
|
||||||
"my_albums": "Els meus àlbums",
|
"my_albums": "Els meus àlbums",
|
||||||
|
"my_immich_description": "Copia la pàgina actual com a enllaç de My Immich",
|
||||||
|
"my_immich_title": "Enllaç My Immich",
|
||||||
"name": "Nom",
|
"name": "Nom",
|
||||||
"name_or_nickname": "Nom o sobrenom",
|
"name_or_nickname": "Nom o sobrenom",
|
||||||
"name_required": "El nom és obligatori",
|
"name_required": "El nom és obligatori",
|
||||||
@@ -1853,6 +1892,7 @@
|
|||||||
"remove_assets_title": "Eliminar els elements?",
|
"remove_assets_title": "Eliminar els elements?",
|
||||||
"remove_custom_date_range": "Elimina l'interval de dates personalitzat",
|
"remove_custom_date_range": "Elimina l'interval de dates personalitzat",
|
||||||
"remove_deleted_assets": "Suprimeix fitxers fora de línia",
|
"remove_deleted_assets": "Suprimeix fitxers fora de línia",
|
||||||
|
"remove_filter": "Elimina el filtre",
|
||||||
"remove_from_album": "Treu de l'àlbum",
|
"remove_from_album": "Treu de l'àlbum",
|
||||||
"remove_from_album_action_prompt": "{count} eliminats de l'àlbum",
|
"remove_from_album_action_prompt": "{count} eliminats de l'àlbum",
|
||||||
"remove_from_favorites": "Eliminar dels preferits",
|
"remove_from_favorites": "Eliminar dels preferits",
|
||||||
@@ -1926,6 +1966,8 @@
|
|||||||
"scan_settings": "Configuració d'escaneig",
|
"scan_settings": "Configuració d'escaneig",
|
||||||
"scanning": "Escanejant",
|
"scanning": "Escanejant",
|
||||||
"scanning_for_album": "S'està buscant l'àlbum...",
|
"scanning_for_album": "S'està buscant l'àlbum...",
|
||||||
|
"screencast_mode_description": "Mostra els indicadors d'esdeveniments del teclat i del ratolí a la pantalla",
|
||||||
|
"screencast_mode_title": "Activa/desactiva el mode de captura de pantalla",
|
||||||
"search": "Cerca",
|
"search": "Cerca",
|
||||||
"search_albums": "Buscar àlbums",
|
"search_albums": "Buscar àlbums",
|
||||||
"search_by_context": "Buscar per context",
|
"search_by_context": "Buscar per context",
|
||||||
@@ -1933,6 +1975,8 @@
|
|||||||
"search_by_description_example": "Jornada de senderisme a Sapa",
|
"search_by_description_example": "Jornada de senderisme a Sapa",
|
||||||
"search_by_filename": "Cerca per nom de fitxer o extensió",
|
"search_by_filename": "Cerca per nom de fitxer o extensió",
|
||||||
"search_by_filename_example": "per exemple IMG_1234.JPG o PNG",
|
"search_by_filename_example": "per exemple IMG_1234.JPG o PNG",
|
||||||
|
"search_by_full_path": "Cerca per camí complert o carpeta",
|
||||||
|
"search_by_full_path_example": "/John/Projects/3D_Printing/2026-07-01 - pots buscar Projectes, 3D, Impressió, 2026 etc.",
|
||||||
"search_by_ocr": "Buscar per OCR",
|
"search_by_ocr": "Buscar per OCR",
|
||||||
"search_by_ocr_example": "Després",
|
"search_by_ocr_example": "Després",
|
||||||
"search_camera_lens_model": "Buscar model de lents....",
|
"search_camera_lens_model": "Buscar model de lents....",
|
||||||
@@ -2148,6 +2192,7 @@
|
|||||||
"show_schema": "Mostrar esquema",
|
"show_schema": "Mostrar esquema",
|
||||||
"show_search_options": "Mostra opcions de cerca",
|
"show_search_options": "Mostra opcions de cerca",
|
||||||
"show_shared_links": "Mostra els enllaços compartits",
|
"show_shared_links": "Mostra els enllaços compartits",
|
||||||
|
"show_slideshow_metadata_overlay": "Mostra informació sobre la imatge",
|
||||||
"show_slideshow_transition": "Mostra la transició de la presentació de diapositives",
|
"show_slideshow_transition": "Mostra la transició de la presentació de diapositives",
|
||||||
"show_supporter_badge": "Insígnia de contribuent",
|
"show_supporter_badge": "Insígnia de contribuent",
|
||||||
"show_supporter_badge_description": "Mostra una insígnia de contributor",
|
"show_supporter_badge_description": "Mostra una insígnia de contributor",
|
||||||
@@ -2163,6 +2208,9 @@
|
|||||||
"skip_to_folders": "Anar a carpetes",
|
"skip_to_folders": "Anar a carpetes",
|
||||||
"skip_to_tags": "Anar a etiquetes",
|
"skip_to_tags": "Anar a etiquetes",
|
||||||
"slideshow": "Diapositives",
|
"slideshow": "Diapositives",
|
||||||
|
"slideshow_metadata_overlay_mode": "Contingut de superposició",
|
||||||
|
"slideshow_metadata_overlay_mode_description_only": "Descripció només",
|
||||||
|
"slideshow_metadata_overlay_mode_full": "Tot",
|
||||||
"slideshow_repeat": "Repeteix la presentació de diapositives",
|
"slideshow_repeat": "Repeteix la presentació de diapositives",
|
||||||
"slideshow_repeat_description": "Torna al principi quan acaba la presentació de diapositives",
|
"slideshow_repeat_description": "Torna al principi quan acaba la presentació de diapositives",
|
||||||
"slideshow_settings": "Configuració de diapositives",
|
"slideshow_settings": "Configuració de diapositives",
|
||||||
@@ -2214,6 +2262,8 @@
|
|||||||
"sync_status": "Estat de la incronització",
|
"sync_status": "Estat de la incronització",
|
||||||
"sync_status_subtitle": "Observa i administra el sistema de sincronització",
|
"sync_status_subtitle": "Observa i administra el sistema de sincronització",
|
||||||
"sync_upload_album_setting_subtitle": "Creeu i pugeu les seves fotos i vídeos als àlbums seleccionats a Immich",
|
"sync_upload_album_setting_subtitle": "Creeu i pugeu les seves fotos i vídeos als àlbums seleccionats a Immich",
|
||||||
|
"system_theme": "Tema del sistema",
|
||||||
|
"system_theme_command_description": "Utilitza el tema del sistema ({value})",
|
||||||
"tag": "Etiqueta",
|
"tag": "Etiqueta",
|
||||||
"tag_assets": "Etiquetar actius",
|
"tag_assets": "Etiquetar actius",
|
||||||
"tag_created": "Etiqueta creada: {tag}",
|
"tag_created": "Etiqueta creada: {tag}",
|
||||||
@@ -2425,6 +2475,7 @@
|
|||||||
"workflows": "Automatitzacions",
|
"workflows": "Automatitzacions",
|
||||||
"workflows_help_text": "Les automatitzacions realitzen accions automàticament sobre els teus mitjans basant-se en disparadors i filtres",
|
"workflows_help_text": "Les automatitzacions realitzen accions automàticament sobre els teus mitjans basant-se en disparadors i filtres",
|
||||||
"wrong_pin_code": "Codi PIN incorrecte",
|
"wrong_pin_code": "Codi PIN incorrecte",
|
||||||
|
"x_of_total": "{x}/{total}",
|
||||||
"year": "Any",
|
"year": "Any",
|
||||||
"years_ago": "Fa {years, plural, one {# any} other {# anys}}",
|
"years_ago": "Fa {years, plural, one {# any} other {# anys}}",
|
||||||
"yes": "Sí",
|
"yes": "Sí",
|
||||||
|
|||||||
+55
-4
@@ -267,6 +267,8 @@
|
|||||||
"notification_enable_email_notifications": "Povolení e-mailových oznámení",
|
"notification_enable_email_notifications": "Povolení e-mailových oznámení",
|
||||||
"notification_settings": "Oznámení",
|
"notification_settings": "Oznámení",
|
||||||
"notification_settings_description": "Správa nastavení oznámení včetně e-mailu",
|
"notification_settings_description": "Správa nastavení oznámení včetně e-mailu",
|
||||||
|
"oauth_allow_insecure_requests": "Povolit nezabezpečené požadavky",
|
||||||
|
"oauth_allow_insecure_requests_description": "VAROVÁNÍ: Toto zakáže ověřování TLS certifikátů u požadavků OAuth, což vás může vystavit riziku útoků typu MITM.",
|
||||||
"oauth_auto_launch": "Automatické zahájení",
|
"oauth_auto_launch": "Automatické zahájení",
|
||||||
"oauth_auto_launch_description": "Automatické zahájení přihlašovacího toku OAuth po přechodu na přihlašovací stránku",
|
"oauth_auto_launch_description": "Automatické zahájení přihlašovacího toku OAuth po přechodu na přihlašovací stránku",
|
||||||
"oauth_auto_register": "Automatická registrace",
|
"oauth_auto_register": "Automatická registrace",
|
||||||
@@ -274,9 +276,11 @@
|
|||||||
"oauth_button_text": "Text tlačítka",
|
"oauth_button_text": "Text tlačítka",
|
||||||
"oauth_client_secret_description": "Vyžadováno pro důvěrné klienty nebo pokud PKCE (Proof Key for Code Exchange) není podporováno pro veřejné klienty.",
|
"oauth_client_secret_description": "Vyžadováno pro důvěrné klienty nebo pokud PKCE (Proof Key for Code Exchange) není podporováno pro veřejné klienty.",
|
||||||
"oauth_enable_description": "Přihlásit pomocí OAuth",
|
"oauth_enable_description": "Přihlásit pomocí OAuth",
|
||||||
|
"oauth_end_session_url_description": "Přesměrovat uživatele po odhlášení na tuto adresu.",
|
||||||
"oauth_mobile_redirect_uri": "Mobilní přesměrování URI",
|
"oauth_mobile_redirect_uri": "Mobilní přesměrování URI",
|
||||||
"oauth_mobile_redirect_uri_override": "Přepsat mobilní přesměrování URI",
|
"oauth_mobile_redirect_uri_override": "Přepsat mobilní přesměrování URI",
|
||||||
"oauth_mobile_redirect_uri_override_description": "Povolit, pokud poskytovatel OAuth nepovoluje mobilní URI, například ''{callback}''",
|
"oauth_mobile_redirect_uri_override_description": "Povolit, pokud poskytovatel OAuth nepovoluje mobilní URI, například ''{callback}''",
|
||||||
|
"oauth_prompt_description": "Parametr dotazu (např. select_account, login, consent)",
|
||||||
"oauth_role_claim": "Deklarace Role",
|
"oauth_role_claim": "Deklarace Role",
|
||||||
"oauth_role_claim_description": "Automaticky udělit přístup správce na základě přítomnosti této deklarace. Deklarace může mít hodnotu 'user' nebo 'admin'.",
|
"oauth_role_claim_description": "Automaticky udělit přístup správce na základě přítomnosti této deklarace. Deklarace může mít hodnotu 'user' nebo 'admin'.",
|
||||||
"oauth_settings": "OAuth",
|
"oauth_settings": "OAuth",
|
||||||
@@ -881,15 +885,13 @@
|
|||||||
"cutoff_date_description": "Zanechat fotografie a videa z posledních…",
|
"cutoff_date_description": "Zanechat fotografie a videa z posledních…",
|
||||||
"cutoff_day": "{count, plural, one {den} few {dny} other {dnů}}",
|
"cutoff_day": "{count, plural, one {den} few {dny} other {dnů}}",
|
||||||
"cutoff_year": "{count, plural, one {rok} few {roky} other {let}}",
|
"cutoff_year": "{count, plural, one {rok} few {roky} other {let}}",
|
||||||
"daily_title_text_date": "EEEE, d. MMMM",
|
|
||||||
"daily_title_text_date_year": "EEEE, d. MMMM y",
|
|
||||||
"dark": "Tmavý",
|
"dark": "Tmavý",
|
||||||
"dark_theme": "Přepnout na tmavý motiv",
|
"dark_theme": "Přepnout na tmavý motiv",
|
||||||
"date": "Datum",
|
"date": "Datum",
|
||||||
"date_after": "Datum po",
|
"date_after": "Datum po",
|
||||||
"date_and_time": "Datum a čas",
|
"date_and_time": "Datum a čas",
|
||||||
"date_before": "Datum před",
|
"date_before": "Datum před",
|
||||||
"date_format": "EEEE, d. MMMM y • H:mm",
|
"date_of_birth": "Datum narození",
|
||||||
"date_of_birth_saved": "Datum narození úspěšně uloženo",
|
"date_of_birth_saved": "Datum narození úspěšně uloženo",
|
||||||
"date_range": "Rozsah dat",
|
"date_range": "Rozsah dat",
|
||||||
"day": "Den",
|
"day": "Den",
|
||||||
@@ -1236,6 +1238,7 @@
|
|||||||
"free_up_space_description": "Přesunout zálohované fotografie a videa do koše zařízení, abyste uvolnili místo. Vaše kopie na serveru zůstanou v bezpečí.",
|
"free_up_space_description": "Přesunout zálohované fotografie a videa do koše zařízení, abyste uvolnili místo. Vaše kopie na serveru zůstanou v bezpečí.",
|
||||||
"free_up_space_settings_subtitle": "Uvolnit úložiště zařízení",
|
"free_up_space_settings_subtitle": "Uvolnit úložiště zařízení",
|
||||||
"full_path": "Úplná cesta: {path}",
|
"full_path": "Úplná cesta: {path}",
|
||||||
|
"full_path_or_folder": "Celá cesta nebo složka",
|
||||||
"gcast_enabled": "Google Cast",
|
"gcast_enabled": "Google Cast",
|
||||||
"gcast_enabled_description": "Tato funkce načítá externí zdroje z Googlu, aby mohla fungovat.",
|
"gcast_enabled_description": "Tato funkce načítá externí zdroje z Googlu, aby mohla fungovat.",
|
||||||
"general": "Obecné",
|
"general": "Obecné",
|
||||||
@@ -1392,11 +1395,13 @@
|
|||||||
"light_theme": "Přepnout na světlý motiv",
|
"light_theme": "Přepnout na světlý motiv",
|
||||||
"like": "Líbí se mi",
|
"like": "Líbí se mi",
|
||||||
"like_deleted": "Oblíbení smazáno",
|
"like_deleted": "Oblíbení smazáno",
|
||||||
|
"link": "Odkaz",
|
||||||
"link_motion_video": "Připojit pohyblivé video",
|
"link_motion_video": "Připojit pohyblivé video",
|
||||||
"link_to_docs": "Další informace najdete v <link>dokumentaci</link>.",
|
"link_to_docs": "Další informace najdete v <link>dokumentaci</link>.",
|
||||||
"link_to_oauth": "Propojit s OAuth",
|
"link_to_oauth": "Propojit s OAuth",
|
||||||
"linked_oauth_account": "Propojený OAuth účet",
|
"linked_oauth_account": "Propojený OAuth účet",
|
||||||
"list": "Seznam",
|
"list": "Seznam",
|
||||||
|
"live": "Živý",
|
||||||
"loading": "Načítání",
|
"loading": "Načítání",
|
||||||
"loading_search_results_failed": "Načítání výsledků vyhledávání se nezdařilo",
|
"loading_search_results_failed": "Načítání výsledků vyhledávání se nezdařilo",
|
||||||
"local": "Místní",
|
"local": "Místní",
|
||||||
@@ -1518,6 +1523,38 @@
|
|||||||
"marked_all_as_read": "Vše označeno jako přečtené",
|
"marked_all_as_read": "Vše označeno jako přečtené",
|
||||||
"matches": "Shody",
|
"matches": "Shody",
|
||||||
"matching_assets": "Odpovídající položky",
|
"matching_assets": "Odpovídající položky",
|
||||||
|
"media_chrome": {
|
||||||
|
"auto": "Automaticky",
|
||||||
|
"captions": "Titulky",
|
||||||
|
"captions_off": "Vypnuto",
|
||||||
|
"closed_captions": "skryté titulky",
|
||||||
|
"decode_error": "Chyba dekódování",
|
||||||
|
"disable_captions": "Vypnout titulky",
|
||||||
|
"enable_captions": "Zapnout titulky",
|
||||||
|
"enter_fullscreen_mode": "Přepnout do režimu celé obrazovky",
|
||||||
|
"exit_fullscreen_mode": "Ukončit režim celé obrazovky",
|
||||||
|
"loop": "Smyčka",
|
||||||
|
"media_error_description": "K přerušení přehrávání došlo kvůli chybě souboru. Soubor může být poškozený, případně váš prohlížeč tento formát nepodporuje.",
|
||||||
|
"media_loading": "načítání médií",
|
||||||
|
"mute": "Ztlumit",
|
||||||
|
"network_error": "Chyba sítě",
|
||||||
|
"network_error_description": "K selhání stahování médií došlo kvůli síťové chybě.",
|
||||||
|
"not_supported_error": "Zdroj není podporován",
|
||||||
|
"playback_rate": "Rychlost přehrávání",
|
||||||
|
"playback_rate_current": "aktuální rychlost přehrávání",
|
||||||
|
"playback_rate_value": "Rychlost přehrávání {playbackRate}",
|
||||||
|
"playback_time": "doba přehrávání",
|
||||||
|
"quality": "Kvalita",
|
||||||
|
"second": "sekunda",
|
||||||
|
"seconds": "sekund",
|
||||||
|
"time_value_of_total_time": "{currentTime} z {totalTime}",
|
||||||
|
"time_value_remaining": "zbývá {time}",
|
||||||
|
"unmute": "Zrušit ztlumení",
|
||||||
|
"unsupported_error_description": "Došlo k chybě způsobené nepodporovaným formátem. Došlo k selhání serveru nebo sítě, případně váš prohlížeč tento formát nepodporuje.",
|
||||||
|
"video_not_loaded_unknown_time": "video se nenačetlo, známý čas.",
|
||||||
|
"video_player": "videopřehrávač",
|
||||||
|
"volume": "hlasitost"
|
||||||
|
},
|
||||||
"media_type": "Typ média",
|
"media_type": "Typ média",
|
||||||
"memories": "Vzpomínky",
|
"memories": "Vzpomínky",
|
||||||
"memories_all_caught_up": "To je všechno",
|
"memories_all_caught_up": "To je všechno",
|
||||||
@@ -1544,8 +1581,8 @@
|
|||||||
"mobile_app_download_onboarding_note": "Stáhněte si doprovodnou mobilní aplikaci pomocí následujících možností",
|
"mobile_app_download_onboarding_note": "Stáhněte si doprovodnou mobilní aplikaci pomocí následujících možností",
|
||||||
"model": "Model",
|
"model": "Model",
|
||||||
"month": "Měsíc",
|
"month": "Měsíc",
|
||||||
"monthly_title_text_date_format": "LLLL y",
|
|
||||||
"more": "Více",
|
"more": "Více",
|
||||||
|
"motion": "Pohyb",
|
||||||
"move": "Přesunout",
|
"move": "Přesunout",
|
||||||
"move_down": "Přesunout dolů",
|
"move_down": "Přesunout dolů",
|
||||||
"move_off_locked_folder": "Přesunout z uzamčené složky",
|
"move_off_locked_folder": "Přesunout z uzamčené složky",
|
||||||
@@ -1562,6 +1599,8 @@
|
|||||||
"multiselect_grid_edit_gps_err_read_only": "Nelze upravit polohu položek pouze pro čtení, přeskakuji",
|
"multiselect_grid_edit_gps_err_read_only": "Nelze upravit polohu položek pouze pro čtení, přeskakuji",
|
||||||
"mute_memories": "Ztlumit vzpomínky",
|
"mute_memories": "Ztlumit vzpomínky",
|
||||||
"my_albums": "Moje alba",
|
"my_albums": "Moje alba",
|
||||||
|
"my_immich_description": "Zkopírovat aktuální stránku jako odkaz na Můj Immich",
|
||||||
|
"my_immich_title": "Odkaz na Můj Immich",
|
||||||
"name": "Jméno",
|
"name": "Jméno",
|
||||||
"name_or_nickname": "Jméno nebo přezdívka",
|
"name_or_nickname": "Jméno nebo přezdívka",
|
||||||
"name_required": "Jméno je povinné",
|
"name_required": "Jméno je povinné",
|
||||||
@@ -1853,6 +1892,7 @@
|
|||||||
"remove_assets_title": "Odstranit položky?",
|
"remove_assets_title": "Odstranit položky?",
|
||||||
"remove_custom_date_range": "Odstranit vlastní rozsah dat",
|
"remove_custom_date_range": "Odstranit vlastní rozsah dat",
|
||||||
"remove_deleted_assets": "Odstranit offline soubory",
|
"remove_deleted_assets": "Odstranit offline soubory",
|
||||||
|
"remove_filter": "Odstranit filtr",
|
||||||
"remove_from_album": "Odstranit z alba",
|
"remove_from_album": "Odstranit z alba",
|
||||||
"remove_from_album_action_prompt": "{count} odstraněných z alba",
|
"remove_from_album_action_prompt": "{count} odstraněných z alba",
|
||||||
"remove_from_favorites": "Odstranit z oblíbených",
|
"remove_from_favorites": "Odstranit z oblíbených",
|
||||||
@@ -1926,6 +1966,8 @@
|
|||||||
"scan_settings": "Nastavení prohledávání",
|
"scan_settings": "Nastavení prohledávání",
|
||||||
"scanning": "Prohládává se",
|
"scanning": "Prohládává se",
|
||||||
"scanning_for_album": "Prohledávání alba...",
|
"scanning_for_album": "Prohledávání alba...",
|
||||||
|
"screencast_mode_description": "Zobrazit na obrazovce indikátory událostí klávesnice a myši",
|
||||||
|
"screencast_mode_title": "Přepnout režim screencastu",
|
||||||
"search": "Hledat",
|
"search": "Hledat",
|
||||||
"search_albums": "Vyhledávejte alba",
|
"search_albums": "Vyhledávejte alba",
|
||||||
"search_by_context": "Vyhledávání podle obsahu",
|
"search_by_context": "Vyhledávání podle obsahu",
|
||||||
@@ -1933,6 +1975,8 @@
|
|||||||
"search_by_description_example": "Pěší turistika v Sapě",
|
"search_by_description_example": "Pěší turistika v Sapě",
|
||||||
"search_by_filename": "Vyhledávání podle názvu nebo přípony souboru",
|
"search_by_filename": "Vyhledávání podle názvu nebo přípony souboru",
|
||||||
"search_by_filename_example": "např. IMG_1234.JPG nebo PNG",
|
"search_by_filename_example": "např. IMG_1234.JPG nebo PNG",
|
||||||
|
"search_by_full_path": "Hledat podle celé cesty nebo složky",
|
||||||
|
"search_by_full_path_example": "/Jan/Projekty/3D_tisk/2026-07-01 – můžete hledat Projekty, 3D, tisk, 2026 apod.",
|
||||||
"search_by_ocr": "Hledat pomocí OCR",
|
"search_by_ocr": "Hledat pomocí OCR",
|
||||||
"search_by_ocr_example": "Latte",
|
"search_by_ocr_example": "Latte",
|
||||||
"search_camera_lens_model": "Vyhledat model objektivu...",
|
"search_camera_lens_model": "Vyhledat model objektivu...",
|
||||||
@@ -2148,6 +2192,7 @@
|
|||||||
"show_schema": "Zobrazit schéma",
|
"show_schema": "Zobrazit schéma",
|
||||||
"show_search_options": "Zobrazit možnosti vyhledávání",
|
"show_search_options": "Zobrazit možnosti vyhledávání",
|
||||||
"show_shared_links": "Zobrazit sdílené odkazy",
|
"show_shared_links": "Zobrazit sdílené odkazy",
|
||||||
|
"show_slideshow_metadata_overlay": "Zobrazit překryvné informace k obrázku",
|
||||||
"show_slideshow_transition": "Zobrazit přechod prezentace",
|
"show_slideshow_transition": "Zobrazit přechod prezentace",
|
||||||
"show_supporter_badge": "Odznak podporovatele",
|
"show_supporter_badge": "Odznak podporovatele",
|
||||||
"show_supporter_badge_description": "Zobrazit odznak podporovatele",
|
"show_supporter_badge_description": "Zobrazit odznak podporovatele",
|
||||||
@@ -2163,6 +2208,9 @@
|
|||||||
"skip_to_folders": "Přeskočit na složky",
|
"skip_to_folders": "Přeskočit na složky",
|
||||||
"skip_to_tags": "Přeskočit na značky",
|
"skip_to_tags": "Přeskočit na značky",
|
||||||
"slideshow": "Prezentace",
|
"slideshow": "Prezentace",
|
||||||
|
"slideshow_metadata_overlay_mode": "Obsah překryvného panelu",
|
||||||
|
"slideshow_metadata_overlay_mode_description_only": "Pouze popis",
|
||||||
|
"slideshow_metadata_overlay_mode_full": "Úplný",
|
||||||
"slideshow_repeat": "Opakovat prezentaci",
|
"slideshow_repeat": "Opakovat prezentaci",
|
||||||
"slideshow_repeat_description": "Po skončení prezentace se vrátit na začátek",
|
"slideshow_repeat_description": "Po skončení prezentace se vrátit na začátek",
|
||||||
"slideshow_settings": "Nastavení prezentace",
|
"slideshow_settings": "Nastavení prezentace",
|
||||||
@@ -2214,6 +2262,8 @@
|
|||||||
"sync_status": "Stav synchronizace",
|
"sync_status": "Stav synchronizace",
|
||||||
"sync_status_subtitle": "Zobrazit a spravovat synchronizační systém",
|
"sync_status_subtitle": "Zobrazit a spravovat synchronizační systém",
|
||||||
"sync_upload_album_setting_subtitle": "Vytvořit a nahrát fotografie a videa do vybraných alb na Immich",
|
"sync_upload_album_setting_subtitle": "Vytvořit a nahrát fotografie a videa do vybraných alb na Immich",
|
||||||
|
"system_theme": "Vzhled systému",
|
||||||
|
"system_theme_command_description": "Použít systémové téma ({value})",
|
||||||
"tag": "Značka",
|
"tag": "Značka",
|
||||||
"tag_assets": "Přiřadit značku",
|
"tag_assets": "Přiřadit značku",
|
||||||
"tag_created": "Vytvořena značka: {tag}",
|
"tag_created": "Vytvořena značka: {tag}",
|
||||||
@@ -2425,6 +2475,7 @@
|
|||||||
"workflows": "Pracovní postupy",
|
"workflows": "Pracovní postupy",
|
||||||
"workflows_help_text": "Pracovní postupy automatizují akce týkající se vašich položek na základě spouštěčů a filtrů",
|
"workflows_help_text": "Pracovní postupy automatizují akce týkající se vašich položek na základě spouštěčů a filtrů",
|
||||||
"wrong_pin_code": "Chybný PIN kód",
|
"wrong_pin_code": "Chybný PIN kód",
|
||||||
|
"x_of_total": "{x}/{total}",
|
||||||
"year": "Rok",
|
"year": "Rok",
|
||||||
"years_ago": "Před {years, plural, one {rokem} other {# lety}}",
|
"years_ago": "Před {years, plural, one {rokem} other {# lety}}",
|
||||||
"yes": "Ano",
|
"yes": "Ano",
|
||||||
|
|||||||
+60
-9
@@ -267,6 +267,8 @@
|
|||||||
"notification_enable_email_notifications": "Slå emailnotifikationer til",
|
"notification_enable_email_notifications": "Slå emailnotifikationer til",
|
||||||
"notification_settings": "Notifikationsindstillinger",
|
"notification_settings": "Notifikationsindstillinger",
|
||||||
"notification_settings_description": "Administrer notifikationsindstillinger, inklusiv email",
|
"notification_settings_description": "Administrer notifikationsindstillinger, inklusiv email",
|
||||||
|
"oauth_allow_insecure_requests": "Tillad usikre anmodninger",
|
||||||
|
"oauth_allow_insecure_requests_description": "ADVARSEL: Dette deaktiverer TLS-certificering for OAuth anmodninger og kan udsætte dig for MITM angreb.",
|
||||||
"oauth_auto_launch": "Auto-opstart",
|
"oauth_auto_launch": "Auto-opstart",
|
||||||
"oauth_auto_launch_description": "Påbegynd OAuth login-flow automatisk når loginsiden tilgås",
|
"oauth_auto_launch_description": "Påbegynd OAuth login-flow automatisk når loginsiden tilgås",
|
||||||
"oauth_auto_register": "Autoregistrér",
|
"oauth_auto_register": "Autoregistrér",
|
||||||
@@ -274,9 +276,11 @@
|
|||||||
"oauth_button_text": "Knaptekst",
|
"oauth_button_text": "Knaptekst",
|
||||||
"oauth_client_secret_description": "Påkrævet for en fortrolig klient eller hvis PKCE (Proof Key for Code Exchange) ikke understøttes for en offentlig klient.",
|
"oauth_client_secret_description": "Påkrævet for en fortrolig klient eller hvis PKCE (Proof Key for Code Exchange) ikke understøttes for en offentlig klient.",
|
||||||
"oauth_enable_description": "Log ind med OAuth",
|
"oauth_enable_description": "Log ind med OAuth",
|
||||||
|
"oauth_end_session_url_description": "Omdiriger brugeren til denne URI, når de logger ud.",
|
||||||
"oauth_mobile_redirect_uri": "Mobilomdiregerings-URL",
|
"oauth_mobile_redirect_uri": "Mobilomdiregerings-URL",
|
||||||
"oauth_mobile_redirect_uri_override": "Tilsidesættelse af mobil omdiregerings-URL",
|
"oauth_mobile_redirect_uri_override": "Tilsidesættelse af mobil omdiregerings-URL",
|
||||||
"oauth_mobile_redirect_uri_override_description": "Aktiver, når OAuth-udbyderen ikke tillader en mobil URI, som ''{callback}''",
|
"oauth_mobile_redirect_uri_override_description": "Aktiver, når OAuth-udbyderen ikke tillader en mobil URI, som ''{callback}''",
|
||||||
|
"oauth_prompt_description": "Prompt-parameter (f.eks. select_account, login, consent)",
|
||||||
"oauth_role_claim": "Rolle attribut",
|
"oauth_role_claim": "Rolle attribut",
|
||||||
"oauth_role_claim_description": "Tildel automatisk admin adgang på basis af forekomst af denne påstand. Dén kan være enten 'user' eller 'admin'.",
|
"oauth_role_claim_description": "Tildel automatisk admin adgang på basis af forekomst af denne påstand. Dén kan være enten 'user' eller 'admin'.",
|
||||||
"oauth_settings": "OAuth",
|
"oauth_settings": "OAuth",
|
||||||
@@ -881,15 +885,13 @@
|
|||||||
"cutoff_date_description": "Behold fotos fra den sidste…",
|
"cutoff_date_description": "Behold fotos fra den sidste…",
|
||||||
"cutoff_day": "{count, plural, one {dag} other {dage}}",
|
"cutoff_day": "{count, plural, one {dag} other {dage}}",
|
||||||
"cutoff_year": "{count, plural, one {år} other {år}}",
|
"cutoff_year": "{count, plural, one {år} other {år}}",
|
||||||
"daily_title_text_date": "E, dd MMM",
|
|
||||||
"daily_title_text_date_year": "E, dd MMM, yyyy",
|
|
||||||
"dark": "Mørk",
|
"dark": "Mørk",
|
||||||
"dark_theme": "Skift til mørkt tema",
|
"dark_theme": "Skift til mørkt tema",
|
||||||
"date": "Dato",
|
"date": "Dato",
|
||||||
"date_after": "Dato efter",
|
"date_after": "Dato efter",
|
||||||
"date_and_time": "Dato og klokkeslæt",
|
"date_and_time": "Dato og klokkeslæt",
|
||||||
"date_before": "Dato før",
|
"date_before": "Dato før",
|
||||||
"date_format": "E d. LLL y • hh:mm",
|
"date_of_birth": "Fødselsdag",
|
||||||
"date_of_birth_saved": "Fødselsdatoen blev gemt korrekt",
|
"date_of_birth_saved": "Fødselsdatoen blev gemt korrekt",
|
||||||
"date_range": "Datointerval",
|
"date_range": "Datointerval",
|
||||||
"day": "Dag",
|
"day": "Dag",
|
||||||
@@ -972,7 +974,7 @@
|
|||||||
"downloading_media": "Download medier",
|
"downloading_media": "Download medier",
|
||||||
"drop_files_to_upload": "Slip filer hvor som helst for at uploade dem",
|
"drop_files_to_upload": "Slip filer hvor som helst for at uploade dem",
|
||||||
"duplicates": "Duplikater",
|
"duplicates": "Duplikater",
|
||||||
"duplicates_description": "Løs hver gruppe ved at angive hvilke, hvis nogen, er dubletter",
|
"duplicates_description": "Løs hver gruppe ved at angive hvilke, hvis nogen, er dubletter.",
|
||||||
"duration": "Varighed",
|
"duration": "Varighed",
|
||||||
"edit": "Rediger",
|
"edit": "Rediger",
|
||||||
"edit_album": "Redigér album",
|
"edit_album": "Redigér album",
|
||||||
@@ -998,7 +1000,7 @@
|
|||||||
"edit_title": "Redigér titel",
|
"edit_title": "Redigér titel",
|
||||||
"edit_user": "Redigér bruger",
|
"edit_user": "Redigér bruger",
|
||||||
"edit_workflow": "Rediger workflow",
|
"edit_workflow": "Rediger workflow",
|
||||||
"editor": "Redaktør",
|
"editor": "Rediger",
|
||||||
"editor_close_without_save_prompt": "Ændringerne vil ikke blive gemt",
|
"editor_close_without_save_prompt": "Ændringerne vil ikke blive gemt",
|
||||||
"editor_close_without_save_title": "Luk editor?",
|
"editor_close_without_save_title": "Luk editor?",
|
||||||
"editor_confirm_reset_all_changes": "Er du sikker på, at du vil nulstille alle ændringer?",
|
"editor_confirm_reset_all_changes": "Er du sikker på, at du vil nulstille alle ændringer?",
|
||||||
@@ -1236,6 +1238,7 @@
|
|||||||
"free_up_space_description": "Flyt sikkerhedskopierede fotos og videoer til din enheds skraldespand for at frigøre plads. Dine kopier på serveren forbliver sikre.",
|
"free_up_space_description": "Flyt sikkerhedskopierede fotos og videoer til din enheds skraldespand for at frigøre plads. Dine kopier på serveren forbliver sikre.",
|
||||||
"free_up_space_settings_subtitle": "Frigør enhedslagerplads",
|
"free_up_space_settings_subtitle": "Frigør enhedslagerplads",
|
||||||
"full_path": "Fuld sti: {path}",
|
"full_path": "Fuld sti: {path}",
|
||||||
|
"full_path_or_folder": "Fuld sti eller mappe",
|
||||||
"gcast_enabled": "Google Cast",
|
"gcast_enabled": "Google Cast",
|
||||||
"gcast_enabled_description": "Denne funktion indlæser eksterne ressourcer fra Google for at virke.",
|
"gcast_enabled_description": "Denne funktion indlæser eksterne ressourcer fra Google for at virke.",
|
||||||
"general": "Generel",
|
"general": "Generel",
|
||||||
@@ -1392,11 +1395,13 @@
|
|||||||
"light_theme": "Skift til lyst tema",
|
"light_theme": "Skift til lyst tema",
|
||||||
"like": "Synes om",
|
"like": "Synes om",
|
||||||
"like_deleted": "Ligesom slettet",
|
"like_deleted": "Ligesom slettet",
|
||||||
|
"link": "Link",
|
||||||
"link_motion_video": "Link bevægelsesvideo",
|
"link_motion_video": "Link bevægelsesvideo",
|
||||||
"link_to_docs": "For yderligere information, se <link>dokumentationen</link>.",
|
"link_to_docs": "For yderligere information, se <link>dokumentationen</link>.",
|
||||||
"link_to_oauth": "Link til OAuth",
|
"link_to_oauth": "Link til OAuth",
|
||||||
"linked_oauth_account": "Tilsluttet OAuth-konto",
|
"linked_oauth_account": "Tilsluttet OAuth-konto",
|
||||||
"list": "Liste",
|
"list": "Liste",
|
||||||
|
"live": "Live",
|
||||||
"loading": "Indlæser",
|
"loading": "Indlæser",
|
||||||
"loading_search_results_failed": "Indlæsning af søgeresultater fejlede",
|
"loading_search_results_failed": "Indlæsning af søgeresultater fejlede",
|
||||||
"local": "Lokal",
|
"local": "Lokal",
|
||||||
@@ -1518,7 +1523,39 @@
|
|||||||
"marked_all_as_read": "Markerede alle som læst",
|
"marked_all_as_read": "Markerede alle som læst",
|
||||||
"matches": "Parringer",
|
"matches": "Parringer",
|
||||||
"matching_assets": "Matchende objekter",
|
"matching_assets": "Matchende objekter",
|
||||||
"media_type": "Medietype",
|
"media_chrome": {
|
||||||
|
"auto": "Auto",
|
||||||
|
"captions": "Undertekster",
|
||||||
|
"captions_off": "Fra",
|
||||||
|
"closed_captions": "Undertekster for hørehæmmede",
|
||||||
|
"decode_error": "Fejl ved dekodning",
|
||||||
|
"disable_captions": "Slå undertekster fra",
|
||||||
|
"enable_captions": "Slå undertekster til",
|
||||||
|
"enter_fullscreen_mode": "Fuld skærm",
|
||||||
|
"exit_fullscreen_mode": "Luk fuld skærm",
|
||||||
|
"loop": "Gentag",
|
||||||
|
"media_error_description": "En mediefejl stoppede afspilningen. Filen kan være korrupt eller browseren understøtter ikke filtypen.",
|
||||||
|
"media_loading": "Loader medie",
|
||||||
|
"mute": "Sluk lyd",
|
||||||
|
"network_error": "Netværksfejl",
|
||||||
|
"network_error_description": "En netværksfejl fik download til at fejle.",
|
||||||
|
"not_supported_error": "Kilde er ikke understøttet",
|
||||||
|
"playback_rate": "Afspilningshastighed",
|
||||||
|
"playback_rate_current": "nuværende afspilningshastighed",
|
||||||
|
"playback_rate_value": "Afspilningshastighed {playbackRate}",
|
||||||
|
"playback_time": "afspilnings varighed",
|
||||||
|
"quality": "Kvalitet",
|
||||||
|
"second": "sekund",
|
||||||
|
"seconds": "sekunder",
|
||||||
|
"time_value_of_total_time": "{currentTime} af {totalTime}",
|
||||||
|
"time_value_remaining": "{time} tilbage",
|
||||||
|
"unmute": "Lyd til",
|
||||||
|
"unsupported_error_description": "En ukendt fejl opstod. Fejl på server, netværk eller din browser understøtter ikke formatet.",
|
||||||
|
"video_not_loaded_unknown_time": "video er ikke indlæst, ukendt tidspunkt.",
|
||||||
|
"video_player": "videoafspiller",
|
||||||
|
"volume": "lydstyrke"
|
||||||
|
},
|
||||||
|
"media_type": "Medieformat",
|
||||||
"memories": "Minder",
|
"memories": "Minder",
|
||||||
"memories_all_caught_up": "Ajour",
|
"memories_all_caught_up": "Ajour",
|
||||||
"memories_check_back_tomorrow": "Kom tilbage i morgen for at se nye minder",
|
"memories_check_back_tomorrow": "Kom tilbage i morgen for at se nye minder",
|
||||||
@@ -1544,8 +1581,8 @@
|
|||||||
"mobile_app_download_onboarding_note": "Hent den tilhørende mobilapp via en af følgende muligheder",
|
"mobile_app_download_onboarding_note": "Hent den tilhørende mobilapp via en af følgende muligheder",
|
||||||
"model": "Model",
|
"model": "Model",
|
||||||
"month": "Måned",
|
"month": "Måned",
|
||||||
"monthly_title_text_date_format": "MMMM å",
|
|
||||||
"more": "Mere",
|
"more": "Mere",
|
||||||
|
"motion": "Bevægelse",
|
||||||
"move": "Flyt",
|
"move": "Flyt",
|
||||||
"move_down": "Flyt ned",
|
"move_down": "Flyt ned",
|
||||||
"move_off_locked_folder": "Flyt ud af låst mappe",
|
"move_off_locked_folder": "Flyt ud af låst mappe",
|
||||||
@@ -1562,6 +1599,8 @@
|
|||||||
"multiselect_grid_edit_gps_err_read_only": "Kan ikke redigere lokation af skrivebeskyttet elementer. Springer over",
|
"multiselect_grid_edit_gps_err_read_only": "Kan ikke redigere lokation af skrivebeskyttet elementer. Springer over",
|
||||||
"mute_memories": "Dæmp minder",
|
"mute_memories": "Dæmp minder",
|
||||||
"my_albums": "Mine albummer",
|
"my_albums": "Mine albummer",
|
||||||
|
"my_immich_description": "Kopier aktuel side som et Mit Immich link",
|
||||||
|
"my_immich_title": "Mit Immich link",
|
||||||
"name": "Navn",
|
"name": "Navn",
|
||||||
"name_or_nickname": "Navn eller kaldenavn",
|
"name_or_nickname": "Navn eller kaldenavn",
|
||||||
"name_required": "Navn er påkrævet",
|
"name_required": "Navn er påkrævet",
|
||||||
@@ -1853,6 +1892,7 @@
|
|||||||
"remove_assets_title": "Fjern mediefiler?",
|
"remove_assets_title": "Fjern mediefiler?",
|
||||||
"remove_custom_date_range": "Fjern tilpasset datointerval",
|
"remove_custom_date_range": "Fjern tilpasset datointerval",
|
||||||
"remove_deleted_assets": "Fjern slettede mediefiler",
|
"remove_deleted_assets": "Fjern slettede mediefiler",
|
||||||
|
"remove_filter": "Fjern filter",
|
||||||
"remove_from_album": "Fjern fra album",
|
"remove_from_album": "Fjern fra album",
|
||||||
"remove_from_album_action_prompt": "{count} fjernet fra albummet",
|
"remove_from_album_action_prompt": "{count} fjernet fra albummet",
|
||||||
"remove_from_favorites": "Fjern fra favoritter",
|
"remove_from_favorites": "Fjern fra favoritter",
|
||||||
@@ -1908,7 +1948,7 @@
|
|||||||
"review_duplicates": "Gennemgå dubletter",
|
"review_duplicates": "Gennemgå dubletter",
|
||||||
"review_large_files": "Gennemgå store filer",
|
"review_large_files": "Gennemgå store filer",
|
||||||
"role": "Rolle",
|
"role": "Rolle",
|
||||||
"role_editor": "Redaktør",
|
"role_editor": "Rediger",
|
||||||
"role_viewer": "Seer",
|
"role_viewer": "Seer",
|
||||||
"running": "Kører",
|
"running": "Kører",
|
||||||
"save": "Gem",
|
"save": "Gem",
|
||||||
@@ -1926,6 +1966,8 @@
|
|||||||
"scan_settings": "Skanningsindstillinger",
|
"scan_settings": "Skanningsindstillinger",
|
||||||
"scanning": "Skanner",
|
"scanning": "Skanner",
|
||||||
"scanning_for_album": "Skanner efter albummer...",
|
"scanning_for_album": "Skanner efter albummer...",
|
||||||
|
"screencast_mode_description": "Vis indikatorer for tastatur- og musehændelse på skærmen",
|
||||||
|
"screencast_mode_title": "Skift skærmcast-tilstand",
|
||||||
"search": "Søg",
|
"search": "Søg",
|
||||||
"search_albums": "Søg i albummer",
|
"search_albums": "Søg i albummer",
|
||||||
"search_by_context": "Søg efter kontekst",
|
"search_by_context": "Søg efter kontekst",
|
||||||
@@ -1933,6 +1975,8 @@
|
|||||||
"search_by_description_example": "Vandredag i Paris",
|
"search_by_description_example": "Vandredag i Paris",
|
||||||
"search_by_filename": "Søg efter filnavn eller filtypenavn",
|
"search_by_filename": "Søg efter filnavn eller filtypenavn",
|
||||||
"search_by_filename_example": "dvs. IMG_1234.JPG eller PNG",
|
"search_by_filename_example": "dvs. IMG_1234.JPG eller PNG",
|
||||||
|
"search_by_full_path": "søg efter fuld sti eller mappe",
|
||||||
|
"search_by_full_path_example": "/John/Projects/3D_Printing/2026-07-01 - du kan søge efter Projects, 3D, Printing, 2026 osv.",
|
||||||
"search_by_ocr": "Søg via OCR",
|
"search_by_ocr": "Søg via OCR",
|
||||||
"search_by_ocr_example": "Søg efter tekst i dine billeder",
|
"search_by_ocr_example": "Søg efter tekst i dine billeder",
|
||||||
"search_camera_lens_model": "Søg objektiv model...",
|
"search_camera_lens_model": "Søg objektiv model...",
|
||||||
@@ -2101,7 +2145,7 @@
|
|||||||
"shared_link_edit_expire_after_option_year": "{count} år",
|
"shared_link_edit_expire_after_option_year": "{count} år",
|
||||||
"shared_link_edit_password_hint": "Indtast kodeordet",
|
"shared_link_edit_password_hint": "Indtast kodeordet",
|
||||||
"shared_link_edit_submit_button": "Opdater link",
|
"shared_link_edit_submit_button": "Opdater link",
|
||||||
"shared_link_error_server_url_fetch": "Kan ikke hente server URL",
|
"shared_link_error_server_url_fetch": "Kan ikke hente server url",
|
||||||
"shared_link_expires_day": "Udløber om {count} dag",
|
"shared_link_expires_day": "Udløber om {count} dag",
|
||||||
"shared_link_expires_days": "Udløber om {count} dage",
|
"shared_link_expires_days": "Udløber om {count} dage",
|
||||||
"shared_link_expires_hour": "Udløber om {count} time",
|
"shared_link_expires_hour": "Udløber om {count} time",
|
||||||
@@ -2148,6 +2192,7 @@
|
|||||||
"show_schema": "Vis skema",
|
"show_schema": "Vis skema",
|
||||||
"show_search_options": "Vis søgeindstillinger",
|
"show_search_options": "Vis søgeindstillinger",
|
||||||
"show_shared_links": "Vis delte links",
|
"show_shared_links": "Vis delte links",
|
||||||
|
"show_slideshow_metadata_overlay": "Vis billedinfo-overlay",
|
||||||
"show_slideshow_transition": "Vis overgang til diasshow",
|
"show_slideshow_transition": "Vis overgang til diasshow",
|
||||||
"show_supporter_badge": "Supporter skilt",
|
"show_supporter_badge": "Supporter skilt",
|
||||||
"show_supporter_badge_description": "Vis et supporter ikon",
|
"show_supporter_badge_description": "Vis et supporter ikon",
|
||||||
@@ -2163,6 +2208,9 @@
|
|||||||
"skip_to_folders": "Spring til mapper",
|
"skip_to_folders": "Spring til mapper",
|
||||||
"skip_to_tags": "Spring til tags",
|
"skip_to_tags": "Spring til tags",
|
||||||
"slideshow": "Diasshow",
|
"slideshow": "Diasshow",
|
||||||
|
"slideshow_metadata_overlay_mode": "Overlay indhold",
|
||||||
|
"slideshow_metadata_overlay_mode_description_only": "Kun beskrivelse",
|
||||||
|
"slideshow_metadata_overlay_mode_full": "Fuld",
|
||||||
"slideshow_repeat": "Gentag diasshow",
|
"slideshow_repeat": "Gentag diasshow",
|
||||||
"slideshow_repeat_description": "Hop tilbage til begyndelsen når diasshow stopper",
|
"slideshow_repeat_description": "Hop tilbage til begyndelsen når diasshow stopper",
|
||||||
"slideshow_settings": "Diasshowindstillinger",
|
"slideshow_settings": "Diasshowindstillinger",
|
||||||
@@ -2214,6 +2262,8 @@
|
|||||||
"sync_status": "Synkroniserings Status",
|
"sync_status": "Synkroniserings Status",
|
||||||
"sync_status_subtitle": "Se og administrér synkroniseringssystemet",
|
"sync_status_subtitle": "Se og administrér synkroniseringssystemet",
|
||||||
"sync_upload_album_setting_subtitle": "Opret og upload dine billeder og videoer til de valgte albummer i Immich",
|
"sync_upload_album_setting_subtitle": "Opret og upload dine billeder og videoer til de valgte albummer i Immich",
|
||||||
|
"system_theme": "Systemtema",
|
||||||
|
"system_theme_command_description": "Brug systemtemaet ({value})",
|
||||||
"tag": "Tag",
|
"tag": "Tag",
|
||||||
"tag_assets": "Tag mediefiler",
|
"tag_assets": "Tag mediefiler",
|
||||||
"tag_created": "Oprettet tag: {tag}",
|
"tag_created": "Oprettet tag: {tag}",
|
||||||
@@ -2425,6 +2475,7 @@
|
|||||||
"workflows": "Arbejdsgange",
|
"workflows": "Arbejdsgange",
|
||||||
"workflows_help_text": "Arbejdsgange automatiserer handlinger på dine filer baseret på udløsere og filtre",
|
"workflows_help_text": "Arbejdsgange automatiserer handlinger på dine filer baseret på udløsere og filtre",
|
||||||
"wrong_pin_code": "Forkert PIN kode",
|
"wrong_pin_code": "Forkert PIN kode",
|
||||||
|
"x_of_total": "{x}/{total}",
|
||||||
"year": "År",
|
"year": "År",
|
||||||
"years_ago": "{years, plural, one {# år} other {# år}} siden",
|
"years_ago": "{years, plural, one {# år} other {# år}} siden",
|
||||||
"yes": "Ja",
|
"yes": "Ja",
|
||||||
|
|||||||
+62
-11
@@ -1,8 +1,8 @@
|
|||||||
{
|
{
|
||||||
"about": "Über",
|
"about": "Über Immich",
|
||||||
"account": "Konto",
|
"account": "Konto",
|
||||||
"account_settings": "Kontoeinstellungen",
|
"account_settings": "Kontoeinstellungen",
|
||||||
"acknowledge": "Verstanden",
|
"acknowledge": "Schließen",
|
||||||
"action": "Aktion",
|
"action": "Aktion",
|
||||||
"action_common_update": "Aktualisieren",
|
"action_common_update": "Aktualisieren",
|
||||||
"action_description": "Eine Reihe von Aktionen, die an den gefilterten Assets ausgeführt werden sollen",
|
"action_description": "Eine Reihe von Aktionen, die an den gefilterten Assets ausgeführt werden sollen",
|
||||||
@@ -267,6 +267,8 @@
|
|||||||
"notification_enable_email_notifications": "E-Mail-Benachrichtigungen aktivieren",
|
"notification_enable_email_notifications": "E-Mail-Benachrichtigungen aktivieren",
|
||||||
"notification_settings": "Benachrichtigungseinstellungen",
|
"notification_settings": "Benachrichtigungseinstellungen",
|
||||||
"notification_settings_description": "Benachrichtigungseinstellungen (inkl. E-Mail) verwalten",
|
"notification_settings_description": "Benachrichtigungseinstellungen (inkl. E-Mail) verwalten",
|
||||||
|
"oauth_allow_insecure_requests": "Unsichere Anfragen erlauben",
|
||||||
|
"oauth_allow_insecure_requests_description": "WARNUNG: Dies deaktiviert die TLS-Zertifikatsvalidierung für OAuth-Anfragen und kann Sie MITM-Angriffen aussetzen.",
|
||||||
"oauth_auto_launch": "Auto-Start",
|
"oauth_auto_launch": "Auto-Start",
|
||||||
"oauth_auto_launch_description": "Automatischer Start des OAuth-Anmeldevorgangs beim Aufrufen der Anmeldeseite",
|
"oauth_auto_launch_description": "Automatischer Start des OAuth-Anmeldevorgangs beim Aufrufen der Anmeldeseite",
|
||||||
"oauth_auto_register": "Automatische Registrierung",
|
"oauth_auto_register": "Automatische Registrierung",
|
||||||
@@ -274,9 +276,11 @@
|
|||||||
"oauth_button_text": "Button-Text",
|
"oauth_button_text": "Button-Text",
|
||||||
"oauth_client_secret_description": "Erforderlich für Confidential Clients oder wenn PKCE (Proof Key for Code Exchange) nicht für Public Clients unterstützt wird.",
|
"oauth_client_secret_description": "Erforderlich für Confidential Clients oder wenn PKCE (Proof Key for Code Exchange) nicht für Public Clients unterstützt wird.",
|
||||||
"oauth_enable_description": "Anmeldung mit OAuth",
|
"oauth_enable_description": "Anmeldung mit OAuth",
|
||||||
|
"oauth_end_session_url_description": "Leite den Benutzer nach dem Abmelden zu dieser URI weiter.",
|
||||||
"oauth_mobile_redirect_uri": "Mobile Umleitungs-URI",
|
"oauth_mobile_redirect_uri": "Mobile Umleitungs-URI",
|
||||||
"oauth_mobile_redirect_uri_override": "Mobile Umleitungs-URI überschreiben",
|
"oauth_mobile_redirect_uri_override": "Mobile Umleitungs-URI überschreiben",
|
||||||
"oauth_mobile_redirect_uri_override_description": "Einschalten, wenn der OAuth-Anbieter keine mobile URI wie ''{callback}'' erlaubt",
|
"oauth_mobile_redirect_uri_override_description": "Einschalten, wenn der OAuth-Anbieter keine mobile URI wie ''{callback}'' erlaubt",
|
||||||
|
"oauth_prompt_description": "Eingabe Parameter (z. B. Konto auswählen, Login, Einwilligung)",
|
||||||
"oauth_role_claim": "Rollen-Claim",
|
"oauth_role_claim": "Rollen-Claim",
|
||||||
"oauth_role_claim_description": "Gewähre automatisch Admin-Zugriff basierend auf dem Vorhandensein dieses Claims. Der Claim kann entweder 'user' oder 'admin' sein.",
|
"oauth_role_claim_description": "Gewähre automatisch Admin-Zugriff basierend auf dem Vorhandensein dieses Claims. Der Claim kann entweder 'user' oder 'admin' sein.",
|
||||||
"oauth_settings": "OAuth",
|
"oauth_settings": "OAuth",
|
||||||
@@ -881,16 +885,14 @@
|
|||||||
"cutoff_date_description": "Behalte Fotos der letzten…",
|
"cutoff_date_description": "Behalte Fotos der letzten…",
|
||||||
"cutoff_day": "{count, plural, one {Tag} other {Tage}}",
|
"cutoff_day": "{count, plural, one {Tag} other {Tage}}",
|
||||||
"cutoff_year": "{count, plural, one {Jahr} other {Jahre}}",
|
"cutoff_year": "{count, plural, one {Jahr} other {Jahre}}",
|
||||||
"daily_title_text_date": "E, dd MMM",
|
|
||||||
"daily_title_text_date_year": "E, dd MMM, yyyy",
|
|
||||||
"dark": "Dunkel",
|
"dark": "Dunkel",
|
||||||
"dark_theme": "Auf dunkle Ansicht umschalten",
|
"dark_theme": "Auf dunkle Ansicht umschalten",
|
||||||
"date": "Datum",
|
"date": "Datum",
|
||||||
"date_after": "Datum nach",
|
"date_after": "Datum nach",
|
||||||
"date_and_time": "Datum und Zeit",
|
"date_and_time": "Datum und Zeit",
|
||||||
"date_before": "Datum vor",
|
"date_before": "Datum vor",
|
||||||
"date_format": "E d. LLL y • hh:mm",
|
"date_of_birth": "Geburtstag",
|
||||||
"date_of_birth_saved": "Das Geburtsdatum wurde erfolgreich gespeichert",
|
"date_of_birth_saved": "Der Geburtstag wurde erfolgreich gespeichert",
|
||||||
"date_range": "Datumsbereich",
|
"date_range": "Datumsbereich",
|
||||||
"day": "Tag",
|
"day": "Tag",
|
||||||
"days": "Tage",
|
"days": "Tage",
|
||||||
@@ -1236,6 +1238,7 @@
|
|||||||
"free_up_space_description": "Bewege Fotos und Videos, die bereits gesichert wurden, in den Papierkorb auf deinem Gerät. Die Kopie auf dem Server bleibt unberührt.",
|
"free_up_space_description": "Bewege Fotos und Videos, die bereits gesichert wurden, in den Papierkorb auf deinem Gerät. Die Kopie auf dem Server bleibt unberührt.",
|
||||||
"free_up_space_settings_subtitle": "Gerätespeicher freigeben",
|
"free_up_space_settings_subtitle": "Gerätespeicher freigeben",
|
||||||
"full_path": "Vollständiger Pfad: {path}",
|
"full_path": "Vollständiger Pfad: {path}",
|
||||||
|
"full_path_or_folder": "Voller Ordnerpfad oder Ordner",
|
||||||
"gcast_enabled": "Google Cast",
|
"gcast_enabled": "Google Cast",
|
||||||
"gcast_enabled_description": "Diese Funktion lädt externe Quellen von Google, um zu funktionieren.",
|
"gcast_enabled_description": "Diese Funktion lädt externe Quellen von Google, um zu funktionieren.",
|
||||||
"general": "Allgemein",
|
"general": "Allgemein",
|
||||||
@@ -1370,7 +1373,7 @@
|
|||||||
"last": "Letzte",
|
"last": "Letzte",
|
||||||
"last_months": "{count, plural, one {Letzter Monat} other {Letzte # Monate}}",
|
"last_months": "{count, plural, one {Letzter Monat} other {Letzte # Monate}}",
|
||||||
"last_seen": "Zuletzt gesehen",
|
"last_seen": "Zuletzt gesehen",
|
||||||
"latest_version": "Aktuelle Version",
|
"latest_version": "Neuste Version",
|
||||||
"latitude": "Breitengrad",
|
"latitude": "Breitengrad",
|
||||||
"leave": "Verlassen",
|
"leave": "Verlassen",
|
||||||
"leave_album": "Album verlassen",
|
"leave_album": "Album verlassen",
|
||||||
@@ -1392,11 +1395,13 @@
|
|||||||
"light_theme": "Auf helle Ansicht umschalten",
|
"light_theme": "Auf helle Ansicht umschalten",
|
||||||
"like": "Gefällt mir",
|
"like": "Gefällt mir",
|
||||||
"like_deleted": "Like gelöscht",
|
"like_deleted": "Like gelöscht",
|
||||||
|
"link": "Link",
|
||||||
"link_motion_video": "Bewegungsvideo verknüpfen",
|
"link_motion_video": "Bewegungsvideo verknüpfen",
|
||||||
"link_to_docs": "Weitere Informationen finden Sie in der <link>Dokumentation</link>.",
|
"link_to_docs": "Weitere Informationen finden Sie in der <link>Dokumentation</link>.",
|
||||||
"link_to_oauth": "Mit OAuth verknüpfen",
|
"link_to_oauth": "Mit OAuth verknüpfen",
|
||||||
"linked_oauth_account": "Verknüpftes OAuth-Konto",
|
"linked_oauth_account": "Verknüpftes OAuth-Konto",
|
||||||
"list": "Liste",
|
"list": "Liste",
|
||||||
|
"live": "Live",
|
||||||
"loading": "Laden",
|
"loading": "Laden",
|
||||||
"loading_search_results_failed": "Laden von Suchergebnissen fehlgeschlagen",
|
"loading_search_results_failed": "Laden von Suchergebnissen fehlgeschlagen",
|
||||||
"local": "Lokal",
|
"local": "Lokal",
|
||||||
@@ -1494,7 +1499,7 @@
|
|||||||
"map_assets_in_bounds": "{count, plural, =0 {Keine Fotos in diesem Gebiet} one {# Foto} other {# Fotos}}",
|
"map_assets_in_bounds": "{count, plural, =0 {Keine Fotos in diesem Gebiet} one {# Foto} other {# Fotos}}",
|
||||||
"map_cannot_get_user_location": "Standort konnte nicht ermittelt werden",
|
"map_cannot_get_user_location": "Standort konnte nicht ermittelt werden",
|
||||||
"map_location_dialog_yes": "Ja",
|
"map_location_dialog_yes": "Ja",
|
||||||
"map_location_picker_page_use_location": "Aufnahmeort verwenden",
|
"map_location_picker_page_use_location": "Diesen Standort verwenden",
|
||||||
"map_location_service_disabled_content": "Ortungsdienste müssen aktiviert sein, um Inhalte am aktuellen Standort anzuzeigen. Willst du die Ortungsdienste jetzt aktivieren?",
|
"map_location_service_disabled_content": "Ortungsdienste müssen aktiviert sein, um Inhalte am aktuellen Standort anzuzeigen. Willst du die Ortungsdienste jetzt aktivieren?",
|
||||||
"map_location_service_disabled_title": "Ortungsdienste deaktiviert",
|
"map_location_service_disabled_title": "Ortungsdienste deaktiviert",
|
||||||
"map_marker_for_images": "Kartenmarkierung für Bilder, die in {city}, {country} aufgenommen wurden",
|
"map_marker_for_images": "Kartenmarkierung für Bilder, die in {city}, {country} aufgenommen wurden",
|
||||||
@@ -1518,6 +1523,38 @@
|
|||||||
"marked_all_as_read": "Alle als gelesen markiert",
|
"marked_all_as_read": "Alle als gelesen markiert",
|
||||||
"matches": "Treffer",
|
"matches": "Treffer",
|
||||||
"matching_assets": "Passende Dateien",
|
"matching_assets": "Passende Dateien",
|
||||||
|
"media_chrome": {
|
||||||
|
"auto": "Auto",
|
||||||
|
"captions": "Untertitel",
|
||||||
|
"captions_off": "Aus",
|
||||||
|
"closed_captions": "Untertitel",
|
||||||
|
"decode_error": "Dekodierungsfehler",
|
||||||
|
"disable_captions": "Untertitel deaktivieren",
|
||||||
|
"enable_captions": "Untertitel aktivieren",
|
||||||
|
"enter_fullscreen_mode": "Vollbildmodus aktivieren",
|
||||||
|
"exit_fullscreen_mode": "Vollbildmodus beenden",
|
||||||
|
"loop": "Endlosschleife",
|
||||||
|
"media_error_description": "Ein Medienfehler hat die Wiedergabe abgebrochen. Das Medium könnte beschädigt sein oder Ihr Browser unterstützt dieses Format nicht.",
|
||||||
|
"media_loading": "Medien werden geladen",
|
||||||
|
"mute": "Stumm schalten",
|
||||||
|
"network_error": "Netzwerkfehler",
|
||||||
|
"network_error_description": "Ein Netzwerkfehler hat dazu geführt, dass der Medien-Download fehlgeschlagen ist.",
|
||||||
|
"not_supported_error": "Quelle nicht unterstützt",
|
||||||
|
"playback_rate": "Wiedergabegeschwindigkeit",
|
||||||
|
"playback_rate_current": "aktuelle Wiedergabegeschwindigkeit",
|
||||||
|
"playback_rate_value": "Wiedergabegeschwindigkeit {playbackRate}",
|
||||||
|
"playback_time": "Wiedergabezeit",
|
||||||
|
"quality": "Qualität",
|
||||||
|
"second": "Sekunde",
|
||||||
|
"seconds": "Sekunden",
|
||||||
|
"time_value_of_total_time": "{currentTime} von {totalTime}",
|
||||||
|
"time_value_remaining": "{time} verbleibend",
|
||||||
|
"unmute": "Stummschaltung aufheben",
|
||||||
|
"unsupported_error_description": "Ein nicht unterstützter Fehler ist aufgetreten. Der Server oder das Netzwerk ist fehlgeschlagen, oder Ihr Browser unterstützt dieses Format nicht.",
|
||||||
|
"video_not_loaded_unknown_time": "Video nicht geladen, unbekannte Zeit.",
|
||||||
|
"video_player": "Videoplayer",
|
||||||
|
"volume": "Lautstärke"
|
||||||
|
},
|
||||||
"media_type": "Medientyp",
|
"media_type": "Medientyp",
|
||||||
"memories": "Erinnerungen",
|
"memories": "Erinnerungen",
|
||||||
"memories_all_caught_up": "Alles aufgeholt",
|
"memories_all_caught_up": "Alles aufgeholt",
|
||||||
@@ -1544,8 +1581,8 @@
|
|||||||
"mobile_app_download_onboarding_note": "Herunterladen der mobilen Begleiter-App über einen der folgenden Möglichkeiten",
|
"mobile_app_download_onboarding_note": "Herunterladen der mobilen Begleiter-App über einen der folgenden Möglichkeiten",
|
||||||
"model": "Modell",
|
"model": "Modell",
|
||||||
"month": "Monat",
|
"month": "Monat",
|
||||||
"monthly_title_text_date_format": "MMMM y",
|
|
||||||
"more": "Mehr",
|
"more": "Mehr",
|
||||||
|
"motion": "Bewegung",
|
||||||
"move": "Verschieben",
|
"move": "Verschieben",
|
||||||
"move_down": "Nach unten",
|
"move_down": "Nach unten",
|
||||||
"move_off_locked_folder": "Aus dem gesperrten Ordner verschieben",
|
"move_off_locked_folder": "Aus dem gesperrten Ordner verschieben",
|
||||||
@@ -1562,6 +1599,8 @@
|
|||||||
"multiselect_grid_edit_gps_err_read_only": "Der Aufnahmeort von schreibgeschützten Inhalten kann nicht verändert werden, überspringen",
|
"multiselect_grid_edit_gps_err_read_only": "Der Aufnahmeort von schreibgeschützten Inhalten kann nicht verändert werden, überspringen",
|
||||||
"mute_memories": "Erinnerungen stumm schalten",
|
"mute_memories": "Erinnerungen stumm schalten",
|
||||||
"my_albums": "Meine Alben",
|
"my_albums": "Meine Alben",
|
||||||
|
"my_immich_description": "Diese Seite als „Mein Immich“-Link kopieren",
|
||||||
|
"my_immich_title": "Mein Immich-Link",
|
||||||
"name": "Name",
|
"name": "Name",
|
||||||
"name_or_nickname": "Name oder Nickname",
|
"name_or_nickname": "Name oder Nickname",
|
||||||
"name_required": "Name ist erforderlich",
|
"name_required": "Name ist erforderlich",
|
||||||
@@ -1749,7 +1788,7 @@
|
|||||||
"places_count": "{count, plural, one {{count, number} Ort} other {{count, number} Orte}}",
|
"places_count": "{count, plural, one {{count, number} Ort} other {{count, number} Orte}}",
|
||||||
"play": "Abspielen",
|
"play": "Abspielen",
|
||||||
"play_memories": "Erinnerungen abspielen",
|
"play_memories": "Erinnerungen abspielen",
|
||||||
"play_motion_photo": "Bewegte Bilder abspielen",
|
"play_motion_photo": "Live-Foto abspielen",
|
||||||
"play_or_pause_video": "Video abspielen oder pausieren",
|
"play_or_pause_video": "Video abspielen oder pausieren",
|
||||||
"play_original_video": "Originales Video abspielen",
|
"play_original_video": "Originales Video abspielen",
|
||||||
"play_original_video_setting_description": "Bevorzugen die Wiedergabe von Originalvideos gegenüber transkodierten Videos. Wenn das Original nicht kompatibel ist, wird es möglicherweise nicht korrekt wiedergegeben.",
|
"play_original_video_setting_description": "Bevorzugen die Wiedergabe von Originalvideos gegenüber transkodierten Videos. Wenn das Original nicht kompatibel ist, wird es möglicherweise nicht korrekt wiedergegeben.",
|
||||||
@@ -1853,6 +1892,7 @@
|
|||||||
"remove_assets_title": "Dateien entfernen?",
|
"remove_assets_title": "Dateien entfernen?",
|
||||||
"remove_custom_date_range": "Benutzerdefinierten Datumsbereich entfernen",
|
"remove_custom_date_range": "Benutzerdefinierten Datumsbereich entfernen",
|
||||||
"remove_deleted_assets": "Offline-Dateien entfernen",
|
"remove_deleted_assets": "Offline-Dateien entfernen",
|
||||||
|
"remove_filter": "Filter entfernen",
|
||||||
"remove_from_album": "Aus Album entfernen",
|
"remove_from_album": "Aus Album entfernen",
|
||||||
"remove_from_album_action_prompt": "{count} vom Album entfernt",
|
"remove_from_album_action_prompt": "{count} vom Album entfernt",
|
||||||
"remove_from_favorites": "Aus Favoriten entfernen",
|
"remove_from_favorites": "Aus Favoriten entfernen",
|
||||||
@@ -1926,6 +1966,8 @@
|
|||||||
"scan_settings": "Scan-Einstellungen",
|
"scan_settings": "Scan-Einstellungen",
|
||||||
"scanning": "Scanne",
|
"scanning": "Scanne",
|
||||||
"scanning_for_album": "Nach Alben scannen...",
|
"scanning_for_album": "Nach Alben scannen...",
|
||||||
|
"screencast_mode_description": "Tastatur- und Mausereignisindikatoren auf dem Bildschirm anzeigen",
|
||||||
|
"screencast_mode_title": "Bildschirmübertragungsmodus umschalten",
|
||||||
"search": "Suche",
|
"search": "Suche",
|
||||||
"search_albums": "Album suchen",
|
"search_albums": "Album suchen",
|
||||||
"search_by_context": "Suche nach Kontext",
|
"search_by_context": "Suche nach Kontext",
|
||||||
@@ -1933,6 +1975,8 @@
|
|||||||
"search_by_description_example": "Wandern in Sapa",
|
"search_by_description_example": "Wandern in Sapa",
|
||||||
"search_by_filename": "Suche nach Dateiname oder -erweiterung",
|
"search_by_filename": "Suche nach Dateiname oder -erweiterung",
|
||||||
"search_by_filename_example": "z.B. IMG_1234.JPG oder PNG",
|
"search_by_filename_example": "z.B. IMG_1234.JPG oder PNG",
|
||||||
|
"search_by_full_path": "Suchen nach Ordnerpfad oder Ordner",
|
||||||
|
"search_by_full_path_example": "/John/Projects/3D_Printing/2026-07-01 - Sie können nach Projekten, 3D, Drucken, 2026 usw. suchen.",
|
||||||
"search_by_ocr": "Suche per OCR",
|
"search_by_ocr": "Suche per OCR",
|
||||||
"search_by_ocr_example": "Latte",
|
"search_by_ocr_example": "Latte",
|
||||||
"search_camera_lens_model": "Suche nach Kameralinse...",
|
"search_camera_lens_model": "Suche nach Kameralinse...",
|
||||||
@@ -2148,6 +2192,7 @@
|
|||||||
"show_schema": "Schema anzeigen",
|
"show_schema": "Schema anzeigen",
|
||||||
"show_search_options": "Suchoptionen anzeigen",
|
"show_search_options": "Suchoptionen anzeigen",
|
||||||
"show_shared_links": "Zeige geteilte Links",
|
"show_shared_links": "Zeige geteilte Links",
|
||||||
|
"show_slideshow_metadata_overlay": "Bildinformationen anzeigen",
|
||||||
"show_slideshow_transition": "Slideshow-Übergang anzeigen",
|
"show_slideshow_transition": "Slideshow-Übergang anzeigen",
|
||||||
"show_supporter_badge": "Unterstützerabzeichen",
|
"show_supporter_badge": "Unterstützerabzeichen",
|
||||||
"show_supporter_badge_description": "Zeige Unterstützerabzeichen",
|
"show_supporter_badge_description": "Zeige Unterstützerabzeichen",
|
||||||
@@ -2163,6 +2208,9 @@
|
|||||||
"skip_to_folders": "Springe zu Ordnern",
|
"skip_to_folders": "Springe zu Ordnern",
|
||||||
"skip_to_tags": "Springe zu Tags",
|
"skip_to_tags": "Springe zu Tags",
|
||||||
"slideshow": "Diashow",
|
"slideshow": "Diashow",
|
||||||
|
"slideshow_metadata_overlay_mode": "Overlay Inhalt",
|
||||||
|
"slideshow_metadata_overlay_mode_description_only": "Nur Beschreibung",
|
||||||
|
"slideshow_metadata_overlay_mode_full": "Alles",
|
||||||
"slideshow_repeat": "Slideshow wiederholen",
|
"slideshow_repeat": "Slideshow wiederholen",
|
||||||
"slideshow_repeat_description": "Wenn Slideshow beendet, zum Anfang zurückkehren",
|
"slideshow_repeat_description": "Wenn Slideshow beendet, zum Anfang zurückkehren",
|
||||||
"slideshow_settings": "Diashow-Einstellungen",
|
"slideshow_settings": "Diashow-Einstellungen",
|
||||||
@@ -2189,7 +2237,7 @@
|
|||||||
"state": "Bundesland / Provinz",
|
"state": "Bundesland / Provinz",
|
||||||
"status": "Status",
|
"status": "Status",
|
||||||
"stop_casting": "Übertragung stoppen",
|
"stop_casting": "Übertragung stoppen",
|
||||||
"stop_motion_photo": "Stop-Motion-Foto",
|
"stop_motion_photo": "Live-Foto stoppen",
|
||||||
"stop_photo_sharing": "Deine Fotos nicht mehr teilen?",
|
"stop_photo_sharing": "Deine Fotos nicht mehr teilen?",
|
||||||
"stop_photo_sharing_description": "{partner} wird keinen Zugriff mehr auf deine Fotos haben.",
|
"stop_photo_sharing_description": "{partner} wird keinen Zugriff mehr auf deine Fotos haben.",
|
||||||
"stop_sharing_photos_with_user": "Aufhören Fotos mit diesem Benutzer zu teilen",
|
"stop_sharing_photos_with_user": "Aufhören Fotos mit diesem Benutzer zu teilen",
|
||||||
@@ -2214,6 +2262,8 @@
|
|||||||
"sync_status": "Synchronisierungstatus",
|
"sync_status": "Synchronisierungstatus",
|
||||||
"sync_status_subtitle": "Synchronisierungssystem anzeigen und bearbeiten",
|
"sync_status_subtitle": "Synchronisierungssystem anzeigen und bearbeiten",
|
||||||
"sync_upload_album_setting_subtitle": "Erstelle und lade deine ausgewählten Fotos und Videos in die ausgewählten Alben auf Immich hoch",
|
"sync_upload_album_setting_subtitle": "Erstelle und lade deine ausgewählten Fotos und Videos in die ausgewählten Alben auf Immich hoch",
|
||||||
|
"system_theme": "Systemthema",
|
||||||
|
"system_theme_command_description": "Systemdesign verwenden ({value})",
|
||||||
"tag": "Tag",
|
"tag": "Tag",
|
||||||
"tag_assets": "Dateien taggen",
|
"tag_assets": "Dateien taggen",
|
||||||
"tag_created": "Tag erstellt: {tag}",
|
"tag_created": "Tag erstellt: {tag}",
|
||||||
@@ -2425,6 +2475,7 @@
|
|||||||
"workflows": "Workflows",
|
"workflows": "Workflows",
|
||||||
"workflows_help_text": "Workflows automatisieren Aktionen auf deinen Dateien, basierend auf Auslösern und Filtern",
|
"workflows_help_text": "Workflows automatisieren Aktionen auf deinen Dateien, basierend auf Auslösern und Filtern",
|
||||||
"wrong_pin_code": "PIN-Code falsch",
|
"wrong_pin_code": "PIN-Code falsch",
|
||||||
|
"x_of_total": "{x}/{total}",
|
||||||
"year": "Jahr",
|
"year": "Jahr",
|
||||||
"years_ago": "Vor {years, plural, one {einem Jahr} other {# Jahren}}",
|
"years_ago": "Vor {years, plural, one {einem Jahr} other {# Jahren}}",
|
||||||
"yes": "Ja",
|
"yes": "Ja",
|
||||||
|
|||||||
+46
-14
@@ -1,19 +1,19 @@
|
|||||||
{
|
{
|
||||||
"about": "Über",
|
"about": "Über",
|
||||||
"account": "Konto",
|
"account": "Konto",
|
||||||
"account_settings": "Konto Einstellungen",
|
"account_settings": "Konto Istellige",
|
||||||
"acknowledge": "Bestätigä",
|
"acknowledge": "Bestätigä",
|
||||||
"action": "Aktion",
|
"action": "Aktion",
|
||||||
"action_common_update": "Update",
|
"action_common_update": "Update",
|
||||||
"action_description": "Aktionä, wo uf de gefilterti Mediä ausgführt werdä solled",
|
"action_description": "Aktionä, wo uf de gefilterti Mediä ausgführt werdä solled",
|
||||||
"actions": "Aktionen",
|
"actions": "Aktionä",
|
||||||
"active": "Aktiv",
|
"active": "Aktiv",
|
||||||
"active_count": "Aktiv: {count}",
|
"active_count": "Aktiv: {count}",
|
||||||
"activity": "Aktivität",
|
"activity": "Aktivität",
|
||||||
"activity_changed": "Aktivität ist {enabled, select, true {aktiviert} other {deaktiviert}}",
|
"activity_changed": "Aktivität ist {enabled, select, true {aktiviert} other {deaktiviert}}",
|
||||||
"add": "Hinzuefüge",
|
"add": "Hinzuefüge",
|
||||||
"add_a_description": "Beschreibung hinzufügen",
|
"add_a_description": "Beschribig afüege",
|
||||||
"add_a_location": "Standort hinzuefügä",
|
"add_a_location": "Standort afüege",
|
||||||
"add_a_name": "Namä hinzefügä",
|
"add_a_name": "Namä hinzefügä",
|
||||||
"add_a_title": "Titel hinzufeügä",
|
"add_a_title": "Titel hinzufeügä",
|
||||||
"add_action": "Aktion hinzuefügä",
|
"add_action": "Aktion hinzuefügä",
|
||||||
@@ -38,10 +38,10 @@
|
|||||||
"add_to_album_toggle": "Auswahl umschalten für {album}",
|
"add_to_album_toggle": "Auswahl umschalten für {album}",
|
||||||
"add_to_albums": "Zu Alben hinzufügen",
|
"add_to_albums": "Zu Alben hinzufügen",
|
||||||
"add_to_albums_count": "Zu Alben hinzufügen ({count})",
|
"add_to_albums_count": "Zu Alben hinzufügen ({count})",
|
||||||
"add_to_bottom_bar": "Hinzufügen zu",
|
"add_to_bottom_bar": "Däzuefüege zu",
|
||||||
"add_to_shared_album": "Zu geteiltem Album hinzufügen",
|
"add_to_shared_album": "Zu geteiltem Album hinzufügen",
|
||||||
"add_upload_to_stack": "Upload zum Stapel hinzufügen",
|
"add_upload_to_stack": "Upload zum Stapel hinzufügen",
|
||||||
"add_url": "URL hinzufügen",
|
"add_url": "URL däzuefüege",
|
||||||
"add_workflow_step": "Workflow-Schritt hinzufügen",
|
"add_workflow_step": "Workflow-Schritt hinzufügen",
|
||||||
"added_to_archive": "Zum Archiv hinzugefügt",
|
"added_to_archive": "Zum Archiv hinzugefügt",
|
||||||
"added_to_favorites": "Zu Favoriten hinzugefügt",
|
"added_to_favorites": "Zu Favoriten hinzugefügt",
|
||||||
@@ -54,7 +54,7 @@
|
|||||||
"authentication_settings_description": "Passwort-, OAuth- und andere Authentifizierungseinstellungen verwalten",
|
"authentication_settings_description": "Passwort-, OAuth- und andere Authentifizierungseinstellungen verwalten",
|
||||||
"authentication_settings_disable_all": "Bist du sicher, dass du alle Loginmethoden deaktivieren willst? Die Anmeldung wird vollständig deaktiviert.",
|
"authentication_settings_disable_all": "Bist du sicher, dass du alle Loginmethoden deaktivieren willst? Die Anmeldung wird vollständig deaktiviert.",
|
||||||
"authentication_settings_reenable": "Nutze einen <link>Server-Befehl</link> zur Reaktivierung.",
|
"authentication_settings_reenable": "Nutze einen <link>Server-Befehl</link> zur Reaktivierung.",
|
||||||
"background_task_job": "Hintergrundaufgaben",
|
"background_task_job": "Hintergrundfarbä",
|
||||||
"backup_database": "Datenbanksicherung erstellen",
|
"backup_database": "Datenbanksicherung erstellen",
|
||||||
"backup_database_enable_description": "Datenbank regelmässig sichern",
|
"backup_database_enable_description": "Datenbank regelmässig sichern",
|
||||||
"backup_keep_last_amount": "Anzahl der aufzubewahrenden früheren Sicherungen",
|
"backup_keep_last_amount": "Anzahl der aufzubewahrenden früheren Sicherungen",
|
||||||
@@ -64,7 +64,7 @@
|
|||||||
"backup_onboarding_description": "Eine <backblaze-link>3-2-1 Sicherungsstrategie</backblaze-link> wird empfohlen, um deine Daten zu schützen. Du solltest sowohl Kopien deiner hochgeladenen Fotos/Videos als auch der Immich-Datenbank aufbewahren, um eine umfassende Sicherungslösung zu haben.",
|
"backup_onboarding_description": "Eine <backblaze-link>3-2-1 Sicherungsstrategie</backblaze-link> wird empfohlen, um deine Daten zu schützen. Du solltest sowohl Kopien deiner hochgeladenen Fotos/Videos als auch der Immich-Datenbank aufbewahren, um eine umfassende Sicherungslösung zu haben.",
|
||||||
"backup_onboarding_footer": "Weitere Informationen zum Sichern von Immich findest du in der <link>Dokumentation</link>.",
|
"backup_onboarding_footer": "Weitere Informationen zum Sichern von Immich findest du in der <link>Dokumentation</link>.",
|
||||||
"backup_onboarding_parts_title": "Eine 3-2-1-Sicherung umfasst:",
|
"backup_onboarding_parts_title": "Eine 3-2-1-Sicherung umfasst:",
|
||||||
"backup_onboarding_title": "Backups",
|
"backup_onboarding_title": "Sicherige",
|
||||||
"backup_settings": "Einstellungen für Datenbanksicherung",
|
"backup_settings": "Einstellungen für Datenbanksicherung",
|
||||||
"backup_settings_description": "Einstellungen zur regelmässigen Sicherung der Datenbank.",
|
"backup_settings_description": "Einstellungen zur regelmässigen Sicherung der Datenbank.",
|
||||||
"cleared_jobs": "Folgende Aufgaben zurückgesetzt: {job}",
|
"cleared_jobs": "Folgende Aufgaben zurückgesetzt: {job}",
|
||||||
@@ -76,16 +76,16 @@
|
|||||||
"confirm_user_password_reset": "Bist du sicher, dass du das Passwort für {user} zurücksetzen möchtest?",
|
"confirm_user_password_reset": "Bist du sicher, dass du das Passwort für {user} zurücksetzen möchtest?",
|
||||||
"confirm_user_pin_code_reset": "Bist du sicher, dass du den PIN-Code von {user} zurücksetzen möchtest?",
|
"confirm_user_pin_code_reset": "Bist du sicher, dass du den PIN-Code von {user} zurücksetzen möchtest?",
|
||||||
"copy_config_to_clipboard_description": "Aktuelle Systemkonfiguration als JSON-Objekt in die Zwischenablage kopieren",
|
"copy_config_to_clipboard_description": "Aktuelle Systemkonfiguration als JSON-Objekt in die Zwischenablage kopieren",
|
||||||
"create_job": "Aufgabe erstellen",
|
"create_job": "Ufgab erstelle",
|
||||||
"cron_expression": "Cron-Ausdruck",
|
"cron_expression": "Cron-Ausdruck",
|
||||||
"cron_expression_description": "Setze das Scanintervall im Cron-Format. Für mehr Informationen, siehe z. B. <link>Crontab Guru</link>",
|
"cron_expression_description": "Setze das Scanintervall im Cron-Format. Für mehr Informationen, siehe z. B. <link>Crontab Guru</link>",
|
||||||
"cron_expression_presets": "Vorlagen für Cron-Ausdrücke",
|
"cron_expression_presets": "Vorlagen für Cron-Ausdrücke",
|
||||||
"disable_login": "Login deaktivieren",
|
"disable_login": "Login deaktivierä",
|
||||||
"duplicate_detection_job_description": "Verwendet maschinelles Lernen auf den Dateien, um Duplikate zu finden. Baut auf der intelligenten Suche auf",
|
"duplicate_detection_job_description": "Verwendet maschinelles Lernen auf den Dateien, um Duplikate zu finden. Baut auf der intelligenten Suche auf",
|
||||||
"exclusion_pattern_description": "Mit Ausschlussmustern können Dateien und Ordner beim Scannen deiner Bibliothek ignoriert werden. Dies ist nützlich, wenn du Ordner hast, die Dateien enthalten, die du nicht importieren möchtest, wie z. B. RAW-Dateien.",
|
"exclusion_pattern_description": "Mit Ausschlussmustern können Dateien und Ordner beim Scannen deiner Bibliothek ignoriert werden. Dies ist nützlich, wenn du Ordner hast, die Dateien enthalten, die du nicht importieren möchtest, wie z. B. RAW-Dateien.",
|
||||||
"export_config_as_json_description": "Aktuelle Systemkonfiguration als JSON-Datei herunterladen",
|
"export_config_as_json_description": "Aktuelle Systemkonfiguration als JSON-Datei herunterladen",
|
||||||
"external_libraries_page_description": "Externe Bibliotheksseite für Administratoren",
|
"external_libraries_page_description": "Externe Bibliotheksseite für Administratoren",
|
||||||
"face_detection": "Gesichtserkennung",
|
"face_detection": "Gsichtserkennig",
|
||||||
"face_detection_description": "Diese Aufgabe erkennt mit maschinellem Lernen Gesichter in Dateien. Bei Videos wird nur das Vorschaubild verwendet. „Aktualisieren“ verarbeitet alle Dateien neu. „Zurücksetzen“ setzt zusätzlich alle Gesichter zurück. „Fehlende“ fügt nur nicht verarbeitete Dateien in die Warteschlange ein. Erfasste Gesichter werden zur Gesichtsidentifizierung in die Warteschlange eingefügt, um sie in bestehende oder neue Personen zu gruppieren.",
|
"face_detection_description": "Diese Aufgabe erkennt mit maschinellem Lernen Gesichter in Dateien. Bei Videos wird nur das Vorschaubild verwendet. „Aktualisieren“ verarbeitet alle Dateien neu. „Zurücksetzen“ setzt zusätzlich alle Gesichter zurück. „Fehlende“ fügt nur nicht verarbeitete Dateien in die Warteschlange ein. Erfasste Gesichter werden zur Gesichtsidentifizierung in die Warteschlange eingefügt, um sie in bestehende oder neue Personen zu gruppieren.",
|
||||||
"facial_recognition_job_description": "Diese Aufgabe gruppiert im Anschluss an die Gesichtserkennung die erkannten Gesichter zu Personen. „Zurücksetzen“ gruppiert alle Gesichter neu, während „Fehlende“ Gesichter ohne Zuordnung in die Warteschlange stellt.",
|
"facial_recognition_job_description": "Diese Aufgabe gruppiert im Anschluss an die Gesichtserkennung die erkannten Gesichter zu Personen. „Zurücksetzen“ gruppiert alle Gesichter neu, während „Fehlende“ Gesichter ohne Zuordnung in die Warteschlange stellt.",
|
||||||
"failed_job_command": "Befehl {command} ist für Aufgabe {job} fehlgeschlagen",
|
"failed_job_command": "Befehl {command} ist für Aufgabe {job} fehlgeschlagen",
|
||||||
@@ -99,7 +99,7 @@
|
|||||||
"image_fullsize_title": "Hochauflösende Vorschaueinstellungen",
|
"image_fullsize_title": "Hochauflösende Vorschaueinstellungen",
|
||||||
"image_prefer_embedded_preview": "Eingebettete Vorschau bevorzugen",
|
"image_prefer_embedded_preview": "Eingebettete Vorschau bevorzugen",
|
||||||
"image_prefer_embedded_preview_setting_description": "Verwende eingebettete Vorschaubilder in RAW-Fotos als Grundlage für die Bildverarbeitung, sofern diese zur Verfügung stehen. Dies kann bei einigen Bildern genauere Farben erzeugen, allerdings ist die Qualität der Vorschau kameraabhängig und das Bild kann mehr Kompressionsartefakte aufweisen.",
|
"image_prefer_embedded_preview_setting_description": "Verwende eingebettete Vorschaubilder in RAW-Fotos als Grundlage für die Bildverarbeitung, sofern diese zur Verfügung stehen. Dies kann bei einigen Bildern genauere Farben erzeugen, allerdings ist die Qualität der Vorschau kameraabhängig und das Bild kann mehr Kompressionsartefakte aufweisen.",
|
||||||
"image_prefer_wide_gamut": "Breites Spektrum bevorzugen",
|
"image_prefer_wide_gamut": "weiterer Farbraum bevorzugen",
|
||||||
"image_prefer_wide_gamut_setting_description": "Display P3 (DCI-P3) für Vorschaubilder verwenden. Dadurch bleibt die Lebendigkeit von Bildern mit breiten Farbräumen besser erhalten, aber die Bilder können auf älteren Geräten mit einer älteren Browserversion etwas anders aussehen. sRGB-Bilder werden im sRGB-Format belassen, um Farbverschiebungen zu vermeiden.",
|
"image_prefer_wide_gamut_setting_description": "Display P3 (DCI-P3) für Vorschaubilder verwenden. Dadurch bleibt die Lebendigkeit von Bildern mit breiten Farbräumen besser erhalten, aber die Bilder können auf älteren Geräten mit einer älteren Browserversion etwas anders aussehen. sRGB-Bilder werden im sRGB-Format belassen, um Farbverschiebungen zu vermeiden.",
|
||||||
"image_preview_description": "Mittelgrosses Bild mit entfernten Metadaten, das bei der Betrachtung einer einzelnen Datei und für maschinelles Lernen verwendet wird",
|
"image_preview_description": "Mittelgrosses Bild mit entfernten Metadaten, das bei der Betrachtung einer einzelnen Datei und für maschinelles Lernen verwendet wird",
|
||||||
"image_preview_quality_description": "Vorschauqualität von 1-100. Ein höherer Wert ist besser, erzeugt dadurch aber grössere Dateien und kann die Reaktionsfähigkeit der App beeinträchtigen. Ein niedriger Wert kann dafür aber die Qualität des maschinellen Lernens beeinträchtigen.",
|
"image_preview_quality_description": "Vorschauqualität von 1-100. Ein höherer Wert ist besser, erzeugt dadurch aber grössere Dateien und kann die Reaktionsfähigkeit der App beeinträchtigen. Ein niedriger Wert kann dafür aber die Qualität des maschinellen Lernens beeinträchtigen.",
|
||||||
@@ -107,7 +107,7 @@
|
|||||||
"image_progressive": "Fortlaufend",
|
"image_progressive": "Fortlaufend",
|
||||||
"image_progressive_description": "JPEG-Bilder schrittweise kodieren, um ein stufenweises Laden zu ermöglichen. Dies hat keine Auswirkungen auf WebP-Bilder.",
|
"image_progressive_description": "JPEG-Bilder schrittweise kodieren, um ein stufenweises Laden zu ermöglichen. Dies hat keine Auswirkungen auf WebP-Bilder.",
|
||||||
"image_quality": "Qualität",
|
"image_quality": "Qualität",
|
||||||
"image_resolution": "Auflösung",
|
"image_resolution": "Uflösig",
|
||||||
"image_resolution_description": "Höhere Auflösungen können mehr Details erhalten, benötigen aber mehr Zeit für die Kodierung, haben grössere Dateigrössen und können die Reaktionsfähigkeit der App beeinträchtigen.",
|
"image_resolution_description": "Höhere Auflösungen können mehr Details erhalten, benötigen aber mehr Zeit für die Kodierung, haben grössere Dateigrössen und können die Reaktionsfähigkeit der App beeinträchtigen.",
|
||||||
"image_settings": "Bildeinstellungen",
|
"image_settings": "Bildeinstellungen",
|
||||||
"image_settings_description": "Qualität und Auflösung der generierten Bilder verwalten",
|
"image_settings_description": "Qualität und Auflösung der generierten Bilder verwalten",
|
||||||
@@ -120,6 +120,8 @@
|
|||||||
"job_not_concurrency_safe": "Diese Aufgabe kann nicht mehrmals parallel laufen gelassen werden.",
|
"job_not_concurrency_safe": "Diese Aufgabe kann nicht mehrmals parallel laufen gelassen werden.",
|
||||||
"job_settings": "Aufgabeneinstellungen",
|
"job_settings": "Aufgabeneinstellungen",
|
||||||
"job_settings_description": "Gleichzeitige Ausführung von Aufgaben verwalten",
|
"job_settings_description": "Gleichzeitige Ausführung von Aufgaben verwalten",
|
||||||
|
"jobs_delayed": "Qualität",
|
||||||
|
"jobs_failed": "{jobCount, plural, other {# failed}}",
|
||||||
"jobs_over_time": "Jobs im Laufe der Zeit",
|
"jobs_over_time": "Jobs im Laufe der Zeit",
|
||||||
"library_created": "Bibliothek erstellt: {library}",
|
"library_created": "Bibliothek erstellt: {library}",
|
||||||
"library_deleted": "Bibliothek gelöscht",
|
"library_deleted": "Bibliothek gelöscht",
|
||||||
@@ -127,6 +129,36 @@
|
|||||||
"library_folder_description": "Wähle einen Ordner zum Importieren. Dieser Ordner wird inklusive Unterordnern nach Bildern und Videos durchsucht.",
|
"library_folder_description": "Wähle einen Ordner zum Importieren. Dieser Ordner wird inklusive Unterordnern nach Bildern und Videos durchsucht.",
|
||||||
"library_remove_exclusion_pattern_prompt": "Bilst du sicher, dass du dieses Ausschlussmuster entfernen möchtest?",
|
"library_remove_exclusion_pattern_prompt": "Bilst du sicher, dass du dieses Ausschlussmuster entfernen möchtest?",
|
||||||
"library_remove_folder_prompt": "Bist du sicher, dass du diesen Import-Ordner entfernen möchtest?",
|
"library_remove_folder_prompt": "Bist du sicher, dass du diesen Import-Ordner entfernen möchtest?",
|
||||||
"library_scanning": "Regelmässiges Scannen"
|
"library_scanning": "Regelmässiges Scannen",
|
||||||
|
"library_scanning_description": "Regelmässiges Scannen der Bibliothek konfigurieren",
|
||||||
|
"library_scanning_enable_description": "Regelmässiges Scannen der Bibliothek aktivieren",
|
||||||
|
"library_settings": "Externe Bibliothek",
|
||||||
|
"library_settings_description": "Einstellungen für externe Bibliotheken verwalten",
|
||||||
|
"library_tasks_description": "Externe Bibliotheken nach neuen und/oder geänderten Assets durchsuchen",
|
||||||
|
"library_updated": "Aktualisierte Bibliothek",
|
||||||
|
"library_watching_enable_description": "Änderungen an Dateien in externen Bibliotheken überwachen",
|
||||||
|
"library_watching_settings": "Bibliothek beobachten [EXPERIMENTELL]",
|
||||||
|
"library_watching_settings_description": "Automatisch nach geänderten Dateien suchen",
|
||||||
|
"logging_enable_description": "Logging aktivieren",
|
||||||
|
"logging_level_description": "Wenn aktiviert, welches Logging-Level soll verwendet werden.",
|
||||||
|
"logging_settings": "Logging",
|
||||||
|
"machine_learning_availability_checks": "Verfügbarkeitsüberprüfungen",
|
||||||
|
"machine_learning_availability_checks_description": "Verfügbare Machine-Learning-Server automatisch erkennen und bevorzugen",
|
||||||
|
"machine_learning_availability_checks_enabled": "Verfügbarkeitsüberprüfungen aktivieren",
|
||||||
|
"machine_learning_availability_checks_interval": "Überprüfungsintervall",
|
||||||
|
"machine_learning_availability_checks_interval_description": "Intervall in Millisekunden zwischen Verfügbarkeitsüberprüfungen",
|
||||||
|
"machine_learning_availability_checks_timeout": "Zeitüberschreitung der Anfrage",
|
||||||
|
"machine_learning_availability_checks_timeout_description": "Timeout in Millisekunden für Verfügbarkeitsüberprüfungen",
|
||||||
|
"machine_learning_clip_model": "CLIP Model",
|
||||||
|
"machine_learning_clip_model_description": "Der Name eines der <link>hier</link> gelisteten CLIP-Modelle. Hinweis: Nach dem Ändern eines Modells muss der ‚Smart Search‘-Vorgang für alle Bilder erneut gestartet werden.",
|
||||||
|
"machine_learning_duplicate_detection": "Duplikatserkennung",
|
||||||
|
"machine_learning_duplicate_detection_enabled": "Duplikatserkennung aktivieren",
|
||||||
|
"machine_learning_duplicate_detection_enabled_description": "Falls deaktiviert, werden exakt identische Assets weiterhin dedupliziert.",
|
||||||
|
"machine_learning_duplicate_detection_setting_description": "Verwende CLIP embeddings um wahrscheinliche Dublikate zu finden",
|
||||||
|
"machine_learning_enabled": "Maschinelles Lernen aktivieren",
|
||||||
|
"machine_learning_enabled_description": "Falls deaktiviert, werden alle ML-Funktionen deaktiviert, unabhängig von den untenstehenden Einstellungen.",
|
||||||
|
"machine_learning_facial_recognition": "Gesichtserkennung",
|
||||||
|
"machine_learning_facial_recognition_description": "Gesichter in Bildern erkennen, identifizieren und gruppieren",
|
||||||
|
"machine_learning_facial_recognition_model": "Model für die Gesichtserkennung"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+11
-4
@@ -267,6 +267,8 @@
|
|||||||
"notification_enable_email_notifications": "Ενεργοποίηση ειδοποιήσεων μέσω email",
|
"notification_enable_email_notifications": "Ενεργοποίηση ειδοποιήσεων μέσω email",
|
||||||
"notification_settings": "Ρυθμίσεις ειδοποιήσεων",
|
"notification_settings": "Ρυθμίσεις ειδοποιήσεων",
|
||||||
"notification_settings_description": "Διαχείρηση ρυθμίσεων ειδοποιήσεων, συμπεριλαμβανομένου του email",
|
"notification_settings_description": "Διαχείρηση ρυθμίσεων ειδοποιήσεων, συμπεριλαμβανομένου του email",
|
||||||
|
"oauth_allow_insecure_requests": "Να επιτρέπονται μη ασφαλή αιτήματα",
|
||||||
|
"oauth_allow_insecure_requests_description": "ΠΡΟΕΙΔΟΠΟΙΗΣΗ: Αυτό απενεργοποιεί την επαλήθευση πιστοποιητικών TLS για αιτήματα OAuth και μπορεί να σας εκθέσει σε επιθέσεις MITM.",
|
||||||
"oauth_auto_launch": "Αυτόματη εκκίνηση",
|
"oauth_auto_launch": "Αυτόματη εκκίνηση",
|
||||||
"oauth_auto_launch_description": "Αυτόματη εκκίνιση της υπηρεσίας OAuth με την πλοήγηση στην σελίδα σύνδεσης",
|
"oauth_auto_launch_description": "Αυτόματη εκκίνιση της υπηρεσίας OAuth με την πλοήγηση στην σελίδα σύνδεσης",
|
||||||
"oauth_auto_register": "Αυτόματη καταχώρηση",
|
"oauth_auto_register": "Αυτόματη καταχώρηση",
|
||||||
@@ -274,9 +276,11 @@
|
|||||||
"oauth_button_text": "Κείμενο κουμπιού",
|
"oauth_button_text": "Κείμενο κουμπιού",
|
||||||
"oauth_client_secret_description": "Απαιτείται για έμπιστο πρόγραμμα πελάτη ή αν δεν υποστηρίζεται PKCE (Proof Key for Code Exchange) σε δημόσιο πρόγραμμα πελάτη.",
|
"oauth_client_secret_description": "Απαιτείται για έμπιστο πρόγραμμα πελάτη ή αν δεν υποστηρίζεται PKCE (Proof Key for Code Exchange) σε δημόσιο πρόγραμμα πελάτη.",
|
||||||
"oauth_enable_description": "Σύνδεση με OAuth",
|
"oauth_enable_description": "Σύνδεση με OAuth",
|
||||||
|
"oauth_end_session_url_description": "Ανακατεύθυνση του χρήστη σε αυτό το URI όταν αποσυνδέεται.",
|
||||||
"oauth_mobile_redirect_uri": "URI Ανακατεύθυνσης για κινητά τηλέφωνα",
|
"oauth_mobile_redirect_uri": "URI Ανακατεύθυνσης για κινητά τηλέφωνα",
|
||||||
"oauth_mobile_redirect_uri_override": "Προσπέλαση URI ανακατεύθυνσης για κινητά τηλέφωνα",
|
"oauth_mobile_redirect_uri_override": "Προσπέλαση URI ανακατεύθυνσης για κινητά τηλέφωνα",
|
||||||
"oauth_mobile_redirect_uri_override_description": "Ενεργοποιήστε το όταν ο πάροχος OAuth δεν επιτρέπει μια URI για κινητά, όπως το ''{callback}''",
|
"oauth_mobile_redirect_uri_override_description": "Ενεργοποιήστε το όταν ο πάροχος OAuth δεν επιτρέπει μια URI για κινητά, όπως το ''{callback}''",
|
||||||
|
"oauth_prompt_description": "Παράμετρος προτροπής (π.χ. επιλογή_λογαριασμού, σύνδεση, συναίνεση)",
|
||||||
"oauth_role_claim": "Ανάθεση ρόλου",
|
"oauth_role_claim": "Ανάθεση ρόλου",
|
||||||
"oauth_role_claim_description": "Αυτόματη παραχώρηση πρόσβασης διαχειριστή με βάση την ύπαρξη αυτής της ανάθεσης. Η ανάθεση μπορεί να είναι είτε 'χρήστης' είτε 'διαχειριστής'.",
|
"oauth_role_claim_description": "Αυτόματη παραχώρηση πρόσβασης διαχειριστή με βάση την ύπαρξη αυτής της ανάθεσης. Η ανάθεση μπορεί να είναι είτε 'χρήστης' είτε 'διαχειριστής'.",
|
||||||
"oauth_settings": "OAuth",
|
"oauth_settings": "OAuth",
|
||||||
@@ -881,15 +885,12 @@
|
|||||||
"cutoff_date_description": "Διατήρηση φωτογραφιών από τις τελευταίες…",
|
"cutoff_date_description": "Διατήρηση φωτογραφιών από τις τελευταίες…",
|
||||||
"cutoff_day": "{count, plural, one {ημέρα} other {ημέρες}}",
|
"cutoff_day": "{count, plural, one {ημέρα} other {ημέρες}}",
|
||||||
"cutoff_year": "{count, plural, one {έτος} other {έτη}}",
|
"cutoff_year": "{count, plural, one {έτος} other {έτη}}",
|
||||||
"daily_title_text_date": "Ε, MMM dd",
|
|
||||||
"daily_title_text_date_year": "Ε, MMM dd, yyyy",
|
|
||||||
"dark": "Σκούρο",
|
"dark": "Σκούρο",
|
||||||
"dark_theme": "Μετάβαση σε σκοτεινό θέμα",
|
"dark_theme": "Μετάβαση σε σκοτεινό θέμα",
|
||||||
"date": "Ημερομηνία",
|
"date": "Ημερομηνία",
|
||||||
"date_after": "Ημερομηνία μετά",
|
"date_after": "Ημερομηνία μετά",
|
||||||
"date_and_time": "Ημερομηνία και ώρα",
|
"date_and_time": "Ημερομηνία και ώρα",
|
||||||
"date_before": "Ημερομηνία πριν",
|
"date_before": "Ημερομηνία πριν",
|
||||||
"date_format": "Ε, LLL d, y • h:mm a",
|
|
||||||
"date_of_birth_saved": "Η ημερομηνία γέννησης αποθηκεύτηκε επιτυχώς",
|
"date_of_birth_saved": "Η ημερομηνία γέννησης αποθηκεύτηκε επιτυχώς",
|
||||||
"date_range": "Εύρος ημερομηνιών",
|
"date_range": "Εύρος ημερομηνιών",
|
||||||
"day": "Ημέρα",
|
"day": "Ημέρα",
|
||||||
@@ -1392,6 +1393,7 @@
|
|||||||
"light_theme": "Μετάβαση σε φωτεινό θέμα",
|
"light_theme": "Μετάβαση σε φωτεινό θέμα",
|
||||||
"like": "Μου αρέσει",
|
"like": "Μου αρέσει",
|
||||||
"like_deleted": "Το \"μου αρέσει\" διαγράφηκε",
|
"like_deleted": "Το \"μου αρέσει\" διαγράφηκε",
|
||||||
|
"link": "Σύνδεσμος",
|
||||||
"link_motion_video": "Σύνδεσε βίντεο κίνησης",
|
"link_motion_video": "Σύνδεσε βίντεο κίνησης",
|
||||||
"link_to_docs": "Για περισσότερες πληροφορίες, ανατρέξτε στην <link>τεκμηρίωση</link>.",
|
"link_to_docs": "Για περισσότερες πληροφορίες, ανατρέξτε στην <link>τεκμηρίωση</link>.",
|
||||||
"link_to_oauth": "Σύνδεση στον OAuth",
|
"link_to_oauth": "Σύνδεση στον OAuth",
|
||||||
@@ -1544,7 +1546,6 @@
|
|||||||
"mobile_app_download_onboarding_note": "Κατέβασε την συνοδευτική εφαρμογή για κινητά χρησιμοποιώντας τις παρακάτω επιλογές",
|
"mobile_app_download_onboarding_note": "Κατέβασε την συνοδευτική εφαρμογή για κινητά χρησιμοποιώντας τις παρακάτω επιλογές",
|
||||||
"model": "Μοντέλο",
|
"model": "Μοντέλο",
|
||||||
"month": "Μήνας",
|
"month": "Μήνας",
|
||||||
"monthly_title_text_date_format": "ΜΜΜΜ y",
|
|
||||||
"more": "Περισσότερα",
|
"more": "Περισσότερα",
|
||||||
"move": "Μετακίνηση",
|
"move": "Μετακίνηση",
|
||||||
"move_down": "Μετακίνηση προς τα κάτω",
|
"move_down": "Μετακίνηση προς τα κάτω",
|
||||||
@@ -1562,6 +1563,8 @@
|
|||||||
"multiselect_grid_edit_gps_err_read_only": "Δεν είναι δυνατή η επεξεργασία της τοποθεσίας των στοιχείων μόνο για ανάγνωση, παραλείπεται",
|
"multiselect_grid_edit_gps_err_read_only": "Δεν είναι δυνατή η επεξεργασία της τοποθεσίας των στοιχείων μόνο για ανάγνωση, παραλείπεται",
|
||||||
"mute_memories": "Σίγαση Αναμνήσεων",
|
"mute_memories": "Σίγαση Αναμνήσεων",
|
||||||
"my_albums": "Τα άλμπουμ μου",
|
"my_albums": "Τα άλμπουμ μου",
|
||||||
|
"my_immich_description": "Αντιγραφή της τρέχουσας σελίδας ως σύνδεσμος Το Immich μου",
|
||||||
|
"my_immich_title": "Σύνδεσμος Το Immich μου",
|
||||||
"name": "Όνομα",
|
"name": "Όνομα",
|
||||||
"name_or_nickname": "Όνομα ή ψευδώνυμο",
|
"name_or_nickname": "Όνομα ή ψευδώνυμο",
|
||||||
"name_required": "Απαιτείται όνομα",
|
"name_required": "Απαιτείται όνομα",
|
||||||
@@ -1926,6 +1929,8 @@
|
|||||||
"scan_settings": "Ρυθμίσεις Σάρωσης",
|
"scan_settings": "Ρυθμίσεις Σάρωσης",
|
||||||
"scanning": "Σαρώνεται",
|
"scanning": "Σαρώνεται",
|
||||||
"scanning_for_album": "Σάρωση για άλμπουμ...",
|
"scanning_for_album": "Σάρωση για άλμπουμ...",
|
||||||
|
"screencast_mode_description": "Εμφάνιση ενδείξεων συμβάντων πληκτρολογίου και ποντικιού στην οθόνη",
|
||||||
|
"screencast_mode_title": "Εναλλαγή λειτουργίας καταγραφής οθόνης",
|
||||||
"search": "Αναζήτηση",
|
"search": "Αναζήτηση",
|
||||||
"search_albums": "Αναζήτηση άλμπουμ",
|
"search_albums": "Αναζήτηση άλμπουμ",
|
||||||
"search_by_context": "Αναζήτηση με βάση το πλαίσιο",
|
"search_by_context": "Αναζήτηση με βάση το πλαίσιο",
|
||||||
@@ -2214,6 +2219,8 @@
|
|||||||
"sync_status": "Κατάσταση συγχρονισμού",
|
"sync_status": "Κατάσταση συγχρονισμού",
|
||||||
"sync_status_subtitle": "Προβολή και διαχείριση του συστήματος συγχρονισμού",
|
"sync_status_subtitle": "Προβολή και διαχείριση του συστήματος συγχρονισμού",
|
||||||
"sync_upload_album_setting_subtitle": "Δημιουργήστε και ανεβάστε τις φωτογραφίες και τα βίντεό σας στα επιλεγμένα άλμπουμ στο Immich",
|
"sync_upload_album_setting_subtitle": "Δημιουργήστε και ανεβάστε τις φωτογραφίες και τα βίντεό σας στα επιλεγμένα άλμπουμ στο Immich",
|
||||||
|
"system_theme": "Θέμα συστήματος",
|
||||||
|
"system_theme_command_description": "Χρήση θέματος από το σύστημα ({value})",
|
||||||
"tag": "Ετικέτα",
|
"tag": "Ετικέτα",
|
||||||
"tag_assets": "Ετικετοποίηση στοιχείων",
|
"tag_assets": "Ετικετοποίηση στοιχείων",
|
||||||
"tag_created": "Δημιουργήθηκε ετικέτα: {tag}",
|
"tag_created": "Δημιουργήθηκε ετικέτα: {tag}",
|
||||||
|
|||||||
+44
-4
@@ -885,15 +885,13 @@
|
|||||||
"cutoff_date_description": "Keep photos from the last…",
|
"cutoff_date_description": "Keep photos from the last…",
|
||||||
"cutoff_day": "{count, plural, one {day} other {days}}",
|
"cutoff_day": "{count, plural, one {day} other {days}}",
|
||||||
"cutoff_year": "{count, plural, one {year} other {years}}",
|
"cutoff_year": "{count, plural, one {year} other {years}}",
|
||||||
"daily_title_text_date": "E, MMM dd",
|
|
||||||
"daily_title_text_date_year": "E, MMM dd, yyyy",
|
|
||||||
"dark": "Dark",
|
"dark": "Dark",
|
||||||
"dark_theme": "Switch to dark theme",
|
"dark_theme": "Switch to dark theme",
|
||||||
"date": "Date",
|
"date": "Date",
|
||||||
"date_after": "Date after",
|
"date_after": "Date after",
|
||||||
"date_and_time": "Date and Time",
|
"date_and_time": "Date and Time",
|
||||||
"date_before": "Date before",
|
"date_before": "Date before",
|
||||||
"date_format": "E, LLL d, y • h:mm a",
|
"date_of_birth": "Date of birth",
|
||||||
"date_of_birth_saved": "Date of birth saved successfully",
|
"date_of_birth_saved": "Date of birth saved successfully",
|
||||||
"date_range": "Date range",
|
"date_range": "Date range",
|
||||||
"day": "Day",
|
"day": "Day",
|
||||||
@@ -1240,6 +1238,7 @@
|
|||||||
"free_up_space_description": "Move backed-up photos and videos to your device's trash to free up space. Your copies on the server remain safe.",
|
"free_up_space_description": "Move backed-up photos and videos to your device's trash to free up space. Your copies on the server remain safe.",
|
||||||
"free_up_space_settings_subtitle": "Free up device storage",
|
"free_up_space_settings_subtitle": "Free up device storage",
|
||||||
"full_path": "Full path: {path}",
|
"full_path": "Full path: {path}",
|
||||||
|
"full_path_or_folder": "Full path or folder",
|
||||||
"gcast_enabled": "Google Cast",
|
"gcast_enabled": "Google Cast",
|
||||||
"gcast_enabled_description": "This feature loads external resources from Google in order to work.",
|
"gcast_enabled_description": "This feature loads external resources from Google in order to work.",
|
||||||
"general": "General",
|
"general": "General",
|
||||||
@@ -1402,6 +1401,7 @@
|
|||||||
"link_to_oauth": "Link to OAuth",
|
"link_to_oauth": "Link to OAuth",
|
||||||
"linked_oauth_account": "Linked OAuth account",
|
"linked_oauth_account": "Linked OAuth account",
|
||||||
"list": "List",
|
"list": "List",
|
||||||
|
"live": "Live",
|
||||||
"loading": "Loading",
|
"loading": "Loading",
|
||||||
"loading_search_results_failed": "Loading search results failed",
|
"loading_search_results_failed": "Loading search results failed",
|
||||||
"local": "Local",
|
"local": "Local",
|
||||||
@@ -1523,6 +1523,38 @@
|
|||||||
"marked_all_as_read": "Marked all as read",
|
"marked_all_as_read": "Marked all as read",
|
||||||
"matches": "Matches",
|
"matches": "Matches",
|
||||||
"matching_assets": "Matching Assets",
|
"matching_assets": "Matching Assets",
|
||||||
|
"media_chrome": {
|
||||||
|
"auto": "Auto",
|
||||||
|
"captions": "Captions",
|
||||||
|
"captions_off": "Off",
|
||||||
|
"closed_captions": "closed captions",
|
||||||
|
"decode_error": "Decode error",
|
||||||
|
"disable_captions": "Disable captions",
|
||||||
|
"enable_captions": "Enable captions",
|
||||||
|
"enter_fullscreen_mode": "Enter fullscreen mode",
|
||||||
|
"exit_fullscreen_mode": "Exit fullscreen mode",
|
||||||
|
"loop": "Loop",
|
||||||
|
"media_error_description": "A media error caused playback to be aborted. The media could be corrupt or your browser does not support this format.",
|
||||||
|
"media_loading": "media loading",
|
||||||
|
"mute": "Mute",
|
||||||
|
"network_error": "Network error",
|
||||||
|
"network_error_description": "A network error caused the media download to fail.",
|
||||||
|
"not_supported_error": "Source Not Supported",
|
||||||
|
"playback_rate": "Playback rate",
|
||||||
|
"playback_rate_current": "current playback rate",
|
||||||
|
"playback_rate_value": "Playback rate {playbackRate}",
|
||||||
|
"playback_time": "playback time",
|
||||||
|
"quality": "Quality",
|
||||||
|
"second": "second",
|
||||||
|
"seconds": "seconds",
|
||||||
|
"time_value_of_total_time": "{currentTime} of {totalTime}",
|
||||||
|
"time_value_remaining": "{time} remaining",
|
||||||
|
"unmute": "Unmute",
|
||||||
|
"unsupported_error_description": "An unsupported error occurred. The server or network failed, or your browser does not support this format.",
|
||||||
|
"video_not_loaded_unknown_time": "video not loaded, unknown time.",
|
||||||
|
"video_player": "video player",
|
||||||
|
"volume": "volume"
|
||||||
|
},
|
||||||
"media_type": "Media type",
|
"media_type": "Media type",
|
||||||
"memories": "Memories",
|
"memories": "Memories",
|
||||||
"memories_all_caught_up": "All caught up",
|
"memories_all_caught_up": "All caught up",
|
||||||
@@ -1549,8 +1581,8 @@
|
|||||||
"mobile_app_download_onboarding_note": "Download the companion mobile app using the following options",
|
"mobile_app_download_onboarding_note": "Download the companion mobile app using the following options",
|
||||||
"model": "Model",
|
"model": "Model",
|
||||||
"month": "Month",
|
"month": "Month",
|
||||||
"monthly_title_text_date_format": "MMMM y",
|
|
||||||
"more": "More",
|
"more": "More",
|
||||||
|
"motion": "Motion",
|
||||||
"move": "Move",
|
"move": "Move",
|
||||||
"move_down": "Move down",
|
"move_down": "Move down",
|
||||||
"move_off_locked_folder": "Move out of locked folder",
|
"move_off_locked_folder": "Move out of locked folder",
|
||||||
@@ -1860,6 +1892,7 @@
|
|||||||
"remove_assets_title": "Remove assets?",
|
"remove_assets_title": "Remove assets?",
|
||||||
"remove_custom_date_range": "Remove custom date range",
|
"remove_custom_date_range": "Remove custom date range",
|
||||||
"remove_deleted_assets": "Remove Deleted Assets",
|
"remove_deleted_assets": "Remove Deleted Assets",
|
||||||
|
"remove_filter": "Remove filter",
|
||||||
"remove_from_album": "Remove from album",
|
"remove_from_album": "Remove from album",
|
||||||
"remove_from_album_action_prompt": "{count} removed from the album",
|
"remove_from_album_action_prompt": "{count} removed from the album",
|
||||||
"remove_from_favorites": "Remove from favorites",
|
"remove_from_favorites": "Remove from favorites",
|
||||||
@@ -1942,6 +1975,8 @@
|
|||||||
"search_by_description_example": "Hiking day in Sapa",
|
"search_by_description_example": "Hiking day in Sapa",
|
||||||
"search_by_filename": "Search by file name or extension",
|
"search_by_filename": "Search by file name or extension",
|
||||||
"search_by_filename_example": "i.e. IMG_1234.JPG or PNG",
|
"search_by_filename_example": "i.e. IMG_1234.JPG or PNG",
|
||||||
|
"search_by_full_path": "Search by full path or folder",
|
||||||
|
"search_by_full_path_example": "/John/Projects/3D_Printing/2026-07-01 - you can search for Projects, 3D, Printing, 2026 etc.",
|
||||||
"search_by_ocr": "Search by OCR",
|
"search_by_ocr": "Search by OCR",
|
||||||
"search_by_ocr_example": "Latte",
|
"search_by_ocr_example": "Latte",
|
||||||
"search_camera_lens_model": "Search lens model...",
|
"search_camera_lens_model": "Search lens model...",
|
||||||
@@ -2157,6 +2192,7 @@
|
|||||||
"show_schema": "Show schema",
|
"show_schema": "Show schema",
|
||||||
"show_search_options": "Show search options",
|
"show_search_options": "Show search options",
|
||||||
"show_shared_links": "Show shared links",
|
"show_shared_links": "Show shared links",
|
||||||
|
"show_slideshow_metadata_overlay": "Show image info overlay",
|
||||||
"show_slideshow_transition": "Show slideshow transition",
|
"show_slideshow_transition": "Show slideshow transition",
|
||||||
"show_supporter_badge": "Supporter badge",
|
"show_supporter_badge": "Supporter badge",
|
||||||
"show_supporter_badge_description": "Show a supporter badge",
|
"show_supporter_badge_description": "Show a supporter badge",
|
||||||
@@ -2172,6 +2208,9 @@
|
|||||||
"skip_to_folders": "Skip to folders",
|
"skip_to_folders": "Skip to folders",
|
||||||
"skip_to_tags": "Skip to tags",
|
"skip_to_tags": "Skip to tags",
|
||||||
"slideshow": "Slideshow",
|
"slideshow": "Slideshow",
|
||||||
|
"slideshow_metadata_overlay_mode": "Overlay content",
|
||||||
|
"slideshow_metadata_overlay_mode_description_only": "Description only",
|
||||||
|
"slideshow_metadata_overlay_mode_full": "Full",
|
||||||
"slideshow_repeat": "Repeat slideshow",
|
"slideshow_repeat": "Repeat slideshow",
|
||||||
"slideshow_repeat_description": "Loop back to beginning when slideshow ends",
|
"slideshow_repeat_description": "Loop back to beginning when slideshow ends",
|
||||||
"slideshow_settings": "Slideshow settings",
|
"slideshow_settings": "Slideshow settings",
|
||||||
@@ -2436,6 +2475,7 @@
|
|||||||
"workflows": "Workflows",
|
"workflows": "Workflows",
|
||||||
"workflows_help_text": "Workflows automate actions on your assets based on triggers and filters",
|
"workflows_help_text": "Workflows automate actions on your assets based on triggers and filters",
|
||||||
"wrong_pin_code": "Wrong PIN code",
|
"wrong_pin_code": "Wrong PIN code",
|
||||||
|
"x_of_total": "{x}/{total}",
|
||||||
"year": "Year",
|
"year": "Year",
|
||||||
"years_ago": "{years, plural, one {# year} other {# years}} ago",
|
"years_ago": "{years, plural, one {# year} other {# years}} ago",
|
||||||
"yes": "Yes",
|
"yes": "Yes",
|
||||||
|
|||||||
+249
-11
@@ -65,7 +65,7 @@
|
|||||||
"backup_onboarding_footer": "Por pli da informoj pri savkopioj kun Immich, bonvolu legi la <link>dokumentaron</link>.",
|
"backup_onboarding_footer": "Por pli da informoj pri savkopioj kun Immich, bonvolu legi la <link>dokumentaron</link>.",
|
||||||
"backup_onboarding_parts_title": "Sekur-kopioj laŭ strategio 3-2-1 inkluzivas:",
|
"backup_onboarding_parts_title": "Sekur-kopioj laŭ strategio 3-2-1 inkluzivas:",
|
||||||
"backup_onboarding_title": "Savkopioj",
|
"backup_onboarding_title": "Savkopioj",
|
||||||
"backup_settings": "Agordaĵoj de kopiado de datumbazo",
|
"backup_settings": "Agordoj pri kopiado de datumbazo",
|
||||||
"backup_settings_description": "Administri agordojn pri datumbazo-nekropsio.",
|
"backup_settings_description": "Administri agordojn pri datumbazo-nekropsio.",
|
||||||
"cleared_jobs": "Taskoj forigitaj por: {job}",
|
"cleared_jobs": "Taskoj forigitaj por: {job}",
|
||||||
"config_set_by_file": "La agordoj estas aktuale regitaj de agordo-dosiero",
|
"config_set_by_file": "La agordoj estas aktuale regitaj de agordo-dosiero",
|
||||||
@@ -118,7 +118,7 @@
|
|||||||
"job_concurrency": "{job}: nombro de samtempaj taskoj",
|
"job_concurrency": "{job}: nombro de samtempaj taskoj",
|
||||||
"job_created": "Tasko kreita",
|
"job_created": "Tasko kreita",
|
||||||
"job_not_concurrency_safe": "Estas nesekure fari tiun ĉi taskon samtempe kun aliaj.",
|
"job_not_concurrency_safe": "Estas nesekure fari tiun ĉi taskon samtempe kun aliaj.",
|
||||||
"job_settings": "Agordoj pri tasko",
|
"job_settings": "Agordoj pri taskoj",
|
||||||
"job_settings_description": "Administri samtempajn taskojn",
|
"job_settings_description": "Administri samtempajn taskojn",
|
||||||
"jobs_delayed": "{jobCount, plural, other {# prokrastitaj}}",
|
"jobs_delayed": "{jobCount, plural, other {# prokrastitaj}}",
|
||||||
"jobs_failed": "{jobCount, plural, other {# malsukesis}}",
|
"jobs_failed": "{jobCount, plural, other {# malsukesis}}",
|
||||||
@@ -212,7 +212,7 @@
|
|||||||
"map_enable_description": "Ŝalti map-funkciojn",
|
"map_enable_description": "Ŝalti map-funkciojn",
|
||||||
"map_gps_settings": "Agordaĵoj pri mapoj kaj GPS",
|
"map_gps_settings": "Agordaĵoj pri mapoj kaj GPS",
|
||||||
"map_gps_settings_description": "Administri agordojn pri mapoj kaj GPS",
|
"map_gps_settings_description": "Administri agordojn pri mapoj kaj GPS",
|
||||||
"map_implications": "Montri mapojn de dependas de ekstera servo (tiles.immich.cloud)",
|
"map_implications": "Montri mapojn dependas de ekstera servo (tiles.immich.cloud)",
|
||||||
"map_light_style": "Hela stilo",
|
"map_light_style": "Hela stilo",
|
||||||
"map_manage_reverse_geocoding_settings": "Administri agordojn pri <link>inversa geo-kodigo</link>",
|
"map_manage_reverse_geocoding_settings": "Administri agordojn pri <link>inversa geo-kodigo</link>",
|
||||||
"map_reverse_geocoding": "Inversa geo-kodigo",
|
"map_reverse_geocoding": "Inversa geo-kodigo",
|
||||||
@@ -267,6 +267,8 @@
|
|||||||
"notification_enable_email_notifications": "Ŝalti sciigojn per retmesaĝo",
|
"notification_enable_email_notifications": "Ŝalti sciigojn per retmesaĝo",
|
||||||
"notification_settings": "Agordoj pri sciigoj",
|
"notification_settings": "Agordoj pri sciigoj",
|
||||||
"notification_settings_description": "Administri agordojn pri sciigoj, inkluzive tiujn per retmesaĝoj",
|
"notification_settings_description": "Administri agordojn pri sciigoj, inkluzive tiujn per retmesaĝoj",
|
||||||
|
"oauth_allow_insecure_requests": "Permesi nesekurajn petojn",
|
||||||
|
"oauth_allow_insecure_requests_description": "ATENTU: tio ĉi malŝaltas validigon de TLS-atestiloj por OAuth-petoj, kaj lasas vin sendefenda kontraŭ kaŝa interkaptado de komunikado (man-in-the-middle).",
|
||||||
"oauth_auto_launch": "Startigi aŭtomate",
|
"oauth_auto_launch": "Startigi aŭtomate",
|
||||||
"oauth_auto_launch_description": "Aŭtomate startigi la OAuth-procezon tuj ĉe la ensaluta paĝo",
|
"oauth_auto_launch_description": "Aŭtomate startigi la OAuth-procezon tuj ĉe la ensaluta paĝo",
|
||||||
"oauth_auto_register": "Registri aŭtomate",
|
"oauth_auto_register": "Registri aŭtomate",
|
||||||
@@ -274,9 +276,11 @@
|
|||||||
"oauth_button_text": "Teksto de butono",
|
"oauth_button_text": "Teksto de butono",
|
||||||
"oauth_client_secret_description": "Bezonata por privata kliento, aŭ se PKCE (Proof Key for Code Exchange) ne estas subtenata de publika kliento.",
|
"oauth_client_secret_description": "Bezonata por privata kliento, aŭ se PKCE (Proof Key for Code Exchange) ne estas subtenata de publika kliento.",
|
||||||
"oauth_enable_description": "Ensaluti per OAuth",
|
"oauth_enable_description": "Ensaluti per OAuth",
|
||||||
|
"oauth_end_session_url_description": "Resendi uzanton al tiu ĉi URI post elsaluto.",
|
||||||
"oauth_mobile_redirect_uri": "Resenda URI por poŝ-aparatoj",
|
"oauth_mobile_redirect_uri": "Resenda URI por poŝ-aparatoj",
|
||||||
"oauth_mobile_redirect_uri_override": "Insisti pri resenda URI por poŝ-aparatoj",
|
"oauth_mobile_redirect_uri_override": "Insisti pri resenda URI por poŝ-aparatoj",
|
||||||
"oauth_mobile_redirect_uri_override_description": "Ŝaltu tion ĉi kiam la provizanto de OAuth ne permesas URI-on por poŝ-aparatoj, kiel \"{callback}\"",
|
"oauth_mobile_redirect_uri_override_description": "Ŝaltu tion ĉi kiam la provizanto de OAuth ne permesas URI-on por poŝ-aparatoj, kiel \"{callback}\"",
|
||||||
|
"oauth_prompt_description": "Parametro de invito (ekz. select_account, login, consent)",
|
||||||
"oauth_role_claim": "Petita rolo",
|
"oauth_role_claim": "Petita rolo",
|
||||||
"oauth_role_claim_description": "Aŭtomate doni rolon de administranto laŭ tiu ĉi peto. La peto povas esti aŭ 'user' (uzanto) aŭ 'admin' (administranto).",
|
"oauth_role_claim_description": "Aŭtomate doni rolon de administranto laŭ tiu ĉi peto. La peto povas esti aŭ 'user' (uzanto) aŭ 'admin' (administranto).",
|
||||||
"oauth_settings": "OAuth",
|
"oauth_settings": "OAuth",
|
||||||
@@ -314,7 +318,7 @@
|
|||||||
"server_external_domain_settings_description": "Domajno por eksteraj ligiloj",
|
"server_external_domain_settings_description": "Domajno por eksteraj ligiloj",
|
||||||
"server_public_users": "Publikaj uzantoj",
|
"server_public_users": "Publikaj uzantoj",
|
||||||
"server_public_users_description": "Nomo kaj retadreso de ĉiuj uzantoj estas listigitaj kiam oni aldonas uzanton al dividita albumo. Kiam malŝaltita, la listo de uzantoj estos videbla nur por administrantoj.",
|
"server_public_users_description": "Nomo kaj retadreso de ĉiuj uzantoj estas listigitaj kiam oni aldonas uzanton al dividita albumo. Kiam malŝaltita, la listo de uzantoj estos videbla nur por administrantoj.",
|
||||||
"server_settings": "Agordoj de servilo",
|
"server_settings": "Agordoj pri servilo",
|
||||||
"server_settings_description": "Administri agordojn pri servilo",
|
"server_settings_description": "Administri agordojn pri servilo",
|
||||||
"server_stats_page_description": "Paĝo de statistikoj pri la servilo",
|
"server_stats_page_description": "Paĝo de statistikoj pri la servilo",
|
||||||
"server_welcome_message": "Bonvena mesaĝo",
|
"server_welcome_message": "Bonvena mesaĝo",
|
||||||
@@ -436,7 +440,7 @@
|
|||||||
"user_password_reset_description": "Bonvolu sendi la dumtempan pasvorton al la uzanto, kaj informu ke ĝi devos esti ŝanĝita je la sekva ensaluto.",
|
"user_password_reset_description": "Bonvolu sendi la dumtempan pasvorton al la uzanto, kaj informu ke ĝi devos esti ŝanĝita je la sekva ensaluto.",
|
||||||
"user_restore_description": "La konto de <b>{user}</b> estos restaŭrita.",
|
"user_restore_description": "La konto de <b>{user}</b> estos restaŭrita.",
|
||||||
"user_restore_scheduled_removal": "Restaŭri uzanton - forviŝo planita je {date, date, long}",
|
"user_restore_scheduled_removal": "Restaŭri uzanton - forviŝo planita je {date, date, long}",
|
||||||
"user_settings": "Agordoj de uzanto",
|
"user_settings": "Agordoj pri uzantoj",
|
||||||
"user_settings_description": "Administri agordojn pri uzantoj",
|
"user_settings_description": "Administri agordojn pri uzantoj",
|
||||||
"user_successfully_removed": "La uzanto {email} estas forigita.",
|
"user_successfully_removed": "La uzanto {email} estas forigita.",
|
||||||
"users_page_description": "Paĝo por administri uzantojn",
|
"users_page_description": "Paĝo por administri uzantojn",
|
||||||
@@ -698,7 +702,7 @@
|
|||||||
"blurred_background": "Malklarigita fono",
|
"blurred_background": "Malklarigita fono",
|
||||||
"bugs_and_feature_requests": "Cimoj kaj petoj por novaj funkcioj",
|
"bugs_and_feature_requests": "Cimoj kaj petoj por novaj funkcioj",
|
||||||
"build": "Versio",
|
"build": "Versio",
|
||||||
"build_image": "Bildo de la versio",
|
"build_image": "Pakaĵo por instali tiun ĉi softvaron",
|
||||||
"bulk_delete_duplicates_confirmation": "Ĉu vi certas, ke vi volas amase forigi {count, plural, one {# duoblaĵon} other {# duoblaĵojn}}? Tiel, vi konservos la plej grandan elementon el ĉiu grupo kaj porĉiame forigos duoblaĵojn. Ne eblas malfari tion!",
|
"bulk_delete_duplicates_confirmation": "Ĉu vi certas, ke vi volas amase forigi {count, plural, one {# duoblaĵon} other {# duoblaĵojn}}? Tiel, vi konservos la plej grandan elementon el ĉiu grupo kaj porĉiame forigos duoblaĵojn. Ne eblas malfari tion!",
|
||||||
"bulk_keep_duplicates_confirmation": "Ĉu vi certas, ke vi volas konservi {count, plural, one {# duoblaĵon} other {# duoblaĵojn}}? Tio solvos ĉiujn duoblajn grupojn sen forigi ion ajn.",
|
"bulk_keep_duplicates_confirmation": "Ĉu vi certas, ke vi volas konservi {count, plural, one {# duoblaĵon} other {# duoblaĵojn}}? Tio solvos ĉiujn duoblajn grupojn sen forigi ion ajn.",
|
||||||
"bulk_trash_duplicates_confirmation": "Ĉu vi certas, ke vi volas amase forigi {count, plural, one {# duoblaĵon} other {# duoblaĵojn}}? Tiel, vi konservos la plej grandan elementon el ĉiu grupo kaj porĉiame forigos duoblaĵojn.",
|
"bulk_trash_duplicates_confirmation": "Ĉu vi certas, ke vi volas amase forigi {count, plural, one {# duoblaĵon} other {# duoblaĵojn}}? Tiel, vi konservos la plej grandan elementon el ĉiu grupo kaj porĉiame forigos duoblaĵojn.",
|
||||||
@@ -851,7 +855,7 @@
|
|||||||
"create_new": "KREI NOVAN",
|
"create_new": "KREI NOVAN",
|
||||||
"create_new_face": "Krei novan vizaĝon",
|
"create_new_face": "Krei novan vizaĝon",
|
||||||
"create_new_person": "Krei novan homon",
|
"create_new_person": "Krei novan homon",
|
||||||
"create_new_person_hint": "Atribui elektitajn elementojn al nova homo",
|
"create_new_person_hint": "Konekti elektitajn elementojn al nova homo",
|
||||||
"create_new_user": "Krei novan uzanton",
|
"create_new_user": "Krei novan uzanton",
|
||||||
"create_person": "Krei homon",
|
"create_person": "Krei homon",
|
||||||
"create_person_subtitle": "Aldoni nomon al la elektita vizaĝo por krei kaj etikedi novan homon",
|
"create_person_subtitle": "Aldoni nomon al la elektita vizaĝo por krei kaj etikedi novan homon",
|
||||||
@@ -881,15 +885,12 @@
|
|||||||
"cutoff_date_description": "Konservi fotojn el la lastaj…",
|
"cutoff_date_description": "Konservi fotojn el la lastaj…",
|
||||||
"cutoff_day": "{count, plural, one {tago} other {tagoj}}",
|
"cutoff_day": "{count, plural, one {tago} other {tagoj}}",
|
||||||
"cutoff_year": "{count, plural, one {jaro} other {jaroj}}",
|
"cutoff_year": "{count, plural, one {jaro} other {jaroj}}",
|
||||||
"daily_title_text_date": "E, dd MMM",
|
|
||||||
"daily_title_text_date_year": "E, dd MMM, yyyy",
|
|
||||||
"dark": "Malhela",
|
"dark": "Malhela",
|
||||||
"dark_theme": "Ŝanĝi al hela reĝimo",
|
"dark_theme": "Ŝanĝi al hela reĝimo",
|
||||||
"date": "Dato",
|
"date": "Dato",
|
||||||
"date_after": "Dato post",
|
"date_after": "Dato post",
|
||||||
"date_and_time": "Dato kaj horo",
|
"date_and_time": "Dato kaj horo",
|
||||||
"date_before": "Dato antaŭ",
|
"date_before": "Dato antaŭ",
|
||||||
"date_format": "E, LLL d, y • h:mm a",
|
|
||||||
"date_of_birth_saved": "Naskiĝdato sukcese registrita",
|
"date_of_birth_saved": "Naskiĝdato sukcese registrita",
|
||||||
"date_range": "Dato-intervalo",
|
"date_range": "Dato-intervalo",
|
||||||
"day": "Tago",
|
"day": "Tago",
|
||||||
@@ -1088,41 +1089,195 @@
|
|||||||
"unable_to_add_partners": "Ne eblas aldoni partnerojn",
|
"unable_to_add_partners": "Ne eblas aldoni partnerojn",
|
||||||
"unable_to_add_remove_archive": "Ne eblas {archived, select, true {forigi elementon de} other {aldoni elementon al}} la arĥivo",
|
"unable_to_add_remove_archive": "Ne eblas {archived, select, true {forigi elementon de} other {aldoni elementon al}} la arĥivo",
|
||||||
"unable_to_add_remove_favorites": "Ne eblas {favorite, select, true {aldoni elementon al} other {forigi elementon de}} preferataĵoj",
|
"unable_to_add_remove_favorites": "Ne eblas {favorite, select, true {aldoni elementon al} other {forigi elementon de}} preferataĵoj",
|
||||||
|
"unable_to_archive_unarchive": "Ne eblis {archived, select, true {enarĥivigi} other {elarĥivigi}}",
|
||||||
|
"unable_to_change_album_user_role": "Ne eblis ŝanĝi la rolon de la album-uzanto",
|
||||||
|
"unable_to_change_date": "Ne eblis ŝanĝi daton",
|
||||||
|
"unable_to_change_description": "Ne eblis ŝanĝi priskribon",
|
||||||
"unable_to_change_favorite": "Ne eblas ŝanĝi preferon por tiu elemento",
|
"unable_to_change_favorite": "Ne eblas ŝanĝi preferon por tiu elemento",
|
||||||
|
"unable_to_change_location": "Ne eblis ŝanĝi lokon",
|
||||||
|
"unable_to_change_password": "Ne eblis ŝanĝi pasvorton",
|
||||||
|
"unable_to_change_visibility": "Ne eblis ŝanĝi la videblecon por {count, plural, one {# homo} other {# homoj}}",
|
||||||
|
"unable_to_complete_oauth_login": "Ne eblis fini la ensaluto per OAuth",
|
||||||
|
"unable_to_connect": "Ne eblis konektiĝi",
|
||||||
|
"unable_to_copy_to_clipboard": "Ne eblas kopii al la tondujo; kontrolu ĉu vi konektiĝas per https",
|
||||||
"unable_to_create": "Ne eblis krei laborfluon",
|
"unable_to_create": "Ne eblis krei laborfluon",
|
||||||
|
"unable_to_create_admin_account": "Ne eblis krei konton de administranto",
|
||||||
|
"unable_to_create_api_key": "Ne eblis krei novan API-ŝlosilon",
|
||||||
|
"unable_to_create_library": "Ne eblis krei bibliotekon",
|
||||||
|
"unable_to_create_user": "Ne eblis krei uzanton",
|
||||||
|
"unable_to_delete_album": "Ne eblis forigi albumon",
|
||||||
|
"unable_to_delete_asset": "Ne eblis forigi elementon",
|
||||||
|
"unable_to_delete_assets": "Eraro okazis dum forigo de elementoj",
|
||||||
"unable_to_delete_exclusion_pattern": "Ne eblas forigi skemon de ekskludo",
|
"unable_to_delete_exclusion_pattern": "Ne eblas forigi skemon de ekskludo",
|
||||||
|
"unable_to_delete_shared_link": "Ne eblis forigi dividitan ligilon",
|
||||||
|
"unable_to_delete_user": "Ne eblis forigi uzanton",
|
||||||
"unable_to_delete_workflow": "Ne eblis forigi laborfluon",
|
"unable_to_delete_workflow": "Ne eblis forigi laborfluon",
|
||||||
|
"unable_to_download_files": "Ne eblis elŝuti dosierojn",
|
||||||
"unable_to_edit_exclusion_pattern": "Ne eblas redakti skemon de ekskludo",
|
"unable_to_edit_exclusion_pattern": "Ne eblas redakti skemon de ekskludo",
|
||||||
|
"unable_to_empty_trash": "Ne eblis malplenigi rubujon",
|
||||||
|
"unable_to_enter_fullscreen": "Ne eblis ŝalti plenekranan reĝimon",
|
||||||
|
"unable_to_exit_fullscreen": "Ne eblis eliĝi el plenekrana reĝimo",
|
||||||
|
"unable_to_get_comments_number": "Ne eblis trovi nombron da komentoj",
|
||||||
|
"unable_to_get_shared_link": "Ne eblis ekhavi dividitan ligilon",
|
||||||
|
"unable_to_hide_person": "Ne eblis kaŝi tiun homon",
|
||||||
|
"unable_to_link_motion_video": "Ne eblis ligi videon",
|
||||||
|
"unable_to_link_oauth_account": "Ne eblis ligi al OAuth-konto",
|
||||||
|
"unable_to_log_out_all_devices": "Ne eblis elsaluti el ĉiuj aparatoj",
|
||||||
|
"unable_to_log_out_device": "Ne eblis elsaluti el tiu aparato",
|
||||||
|
"unable_to_login_with_oauth": "Ne eblis ensaluti per OAuth",
|
||||||
|
"unable_to_play_video": "Ne eblis ludi videon",
|
||||||
|
"unable_to_reassign_assets_existing_person": "Ne eblis rekonekti elementojn al {name, select, null {ekzistanta homo} other {{name}}}",
|
||||||
|
"unable_to_reassign_assets_new_person": "Ne eblis konekti elementojn al nova homo",
|
||||||
|
"unable_to_refresh_user": "Ne eblis renovigi uzanton",
|
||||||
|
"unable_to_remove_album_users": "Ne eblis forigi uzantojn de albumo",
|
||||||
|
"unable_to_remove_api_key": "Ne eblis forigi API-ŝlosilo",
|
||||||
|
"unable_to_remove_assets_from_shared_link": "Ne eblis forigi elementojn el dividita ligilo",
|
||||||
|
"unable_to_remove_library": "Ne eblis forigi bibliotekon",
|
||||||
|
"unable_to_remove_partner": "Ne eblis forigi partneron",
|
||||||
|
"unable_to_remove_reaction": "Ne eblis forigi reagon",
|
||||||
|
"unable_to_reset_password": "Ne eblis restarigi pasvorton",
|
||||||
|
"unable_to_reset_pin_code": "Ne eblis restarigi PIN-kodon",
|
||||||
|
"unable_to_resolve_duplicate": "Ne eblis solvi tiun ĉi duoblaĵon",
|
||||||
|
"unable_to_restore_assets": "Ne eblis restaŭri elementojn",
|
||||||
|
"unable_to_restore_trash": "Ne eblis restaŭri rubaĵojn",
|
||||||
|
"unable_to_restore_user": "Ne eblis restaŭri uzanton",
|
||||||
|
"unable_to_save_album": "Ne eblis konservi albumon",
|
||||||
|
"unable_to_save_api_key": "Ne eblis konservi API-ŝlosilon",
|
||||||
|
"unable_to_save_date_of_birth": "Ne eblis konservi naskiĝdaton",
|
||||||
|
"unable_to_save_name": "Ne eblis konservi nomon",
|
||||||
|
"unable_to_save_profile": "Ne eblis konservi profilon",
|
||||||
|
"unable_to_save_settings": "Ne eblis konservi agordojn",
|
||||||
"unable_to_scan_libraries": "Ne eblas analizi biblitekojn",
|
"unable_to_scan_libraries": "Ne eblas analizi biblitekojn",
|
||||||
"unable_to_scan_library": "Ne eblas analizi biblitekon",
|
"unable_to_scan_library": "Ne eblas analizi biblitekon",
|
||||||
"unable_to_update_workflow": "Ne eblis ĝisdatigi laborfluon"
|
"unable_to_set_feature_photo": "Ne eblis agordi ĉap-foton",
|
||||||
|
"unable_to_set_profile_picture": "Ne eblis agordi profilbildon",
|
||||||
|
"unable_to_set_rating": "Ne eblis konservi pritakson",
|
||||||
|
"unable_to_submit_job": "Ne eblis plenumi taskon",
|
||||||
|
"unable_to_trash_asset": "Ne eblis forigi elementon",
|
||||||
|
"unable_to_unlink_account": "Ne eblis malligi konton",
|
||||||
|
"unable_to_unlink_motion_video": "Ne eblis malligi movbildon",
|
||||||
|
"unable_to_update_album_cover": "Ne eblis ŝanĝi kovrilon de albumo",
|
||||||
|
"unable_to_update_album_info": "Ne eblis ŝanĝi informojn pri albumo",
|
||||||
|
"unable_to_update_library": "Ne eblis ĝisdatigi bibliotekon",
|
||||||
|
"unable_to_update_location": "Ne eblis ŝanĝi lokon",
|
||||||
|
"unable_to_update_settings": "Ne eblis ĝisdatigi agordojn",
|
||||||
|
"unable_to_update_timeline_display_status": "Ne eblis ŝanĝi tiun agordon por la partnero",
|
||||||
|
"unable_to_update_user": "Ne eblis ĝisdatigi uzanton",
|
||||||
|
"unable_to_update_workflow": "Ne eblis ĝisdatigi laborfluon",
|
||||||
|
"unable_to_upload_file": "Ne eblis alŝuti dosieron"
|
||||||
},
|
},
|
||||||
|
"errors_text": "Eraroj",
|
||||||
"exclusion_pattern": "Skemo de ekskludo",
|
"exclusion_pattern": "Skemo de ekskludo",
|
||||||
|
"exif": "Exif",
|
||||||
|
"exif_bottom_sheet_description": "Aldoni priskribon...",
|
||||||
|
"exif_bottom_sheet_description_error": "Eraro dum ĝisdatigo de priskribo",
|
||||||
|
"exif_bottom_sheet_details": "DETALOJ",
|
||||||
|
"exif_bottom_sheet_location": "LOKO",
|
||||||
|
"exif_bottom_sheet_no_description": "Neniu priskribo",
|
||||||
|
"exif_bottom_sheet_people": "HOMOJ",
|
||||||
|
"exif_bottom_sheet_person_add_person": "Aldoni nomon",
|
||||||
|
"exit_slideshow": "Fini bildserion",
|
||||||
"expand": "Etendi",
|
"expand": "Etendi",
|
||||||
"expand_all": "Etendi ĉiujn",
|
"expand_all": "Etendi ĉiujn",
|
||||||
|
"experimental_settings_new_asset_list_subtitle": "Prilaborataĵoj",
|
||||||
|
"experimental_settings_new_asset_list_title": "Ŝalti eksperimentan foto-kradon",
|
||||||
|
"experimental_settings_subtitle": "Uzu je propra risko!",
|
||||||
|
"experimental_settings_title": "Eksperimenta",
|
||||||
|
"expire_after": "Eksvalidigi post",
|
||||||
|
"expired": "Eksvalida",
|
||||||
|
"expires_date": "Eksvalidiĝos je {date}",
|
||||||
"explore": "Esplori",
|
"explore": "Esplori",
|
||||||
"explorer": "Foliumilo",
|
"explorer": "Foliumilo",
|
||||||
|
"export": "Eksporti",
|
||||||
|
"export_as_json": "Eksporti kiel JSON",
|
||||||
|
"export_database": "Eksporti datumbazon",
|
||||||
|
"export_database_description": "Eksporti la SQLite-datumbazon",
|
||||||
|
"extension": "Sufikso",
|
||||||
|
"external": "Ekstera",
|
||||||
|
"external_libraries": "Eksteraj bibliotekoj",
|
||||||
|
"external_network": "Ekstera reto",
|
||||||
|
"external_network_sheet_info": "Kiam la preferata vifio estas netrovebla, la apo provos konektiĝi al la servilo per la ĉi-suba listo de URL-oj, ekde la unua",
|
||||||
|
"face_unassigned": "Ne konektitaj",
|
||||||
|
"failed": "Malsukcesis",
|
||||||
|
"failed_count": "Malsukcesis: {count}",
|
||||||
|
"failed_to_authenticate": "Malsukcesis ensaluti",
|
||||||
|
"failed_to_load_assets": "Malsukcesis ŝargi elementojn",
|
||||||
|
"failed_to_load_folder": "Malsukcesis ŝargi dosierujon",
|
||||||
"favorite": "Preferataĵo",
|
"favorite": "Preferataĵo",
|
||||||
"favorite_action_prompt": "{count} aldonita(j) al Preferataĵoj",
|
"favorite_action_prompt": "{count} aldonita(j) al Preferataĵoj",
|
||||||
"favorite_or_unfavorite_photo": "Aldoni/forigi foton al/de preferataĵoj",
|
"favorite_or_unfavorite_photo": "Aldoni/forigi foton al/de preferataĵoj",
|
||||||
"favorites": "Preferataĵoj",
|
"favorites": "Preferataĵoj",
|
||||||
"favorites_page_no_favorites": "Neniuj preferataj elementoj trovitaj",
|
"favorites_page_no_favorites": "Neniuj preferataj elementoj trovitaj",
|
||||||
|
"feature_photo_updated": "Ĉap-foto sukcese ŝanĝita",
|
||||||
|
"features": "Funkcioj",
|
||||||
|
"features_in_development": "Funkcioj ankoraŭ prilaborataj",
|
||||||
|
"features_setting_description": "Administri funkciojn de la apo",
|
||||||
|
"file_name_or_extension": "Dosiernomo aŭ sufikso",
|
||||||
|
"file_name_text": "Dosiernomo",
|
||||||
|
"file_name_with_value": "Dosiernomo: {file_name}",
|
||||||
|
"file_size": "Grandeco de dosiero",
|
||||||
|
"filename": "Dosiernomo",
|
||||||
|
"filetype": "Tipo de dosiero",
|
||||||
|
"filter": "Filtri",
|
||||||
|
"filter_description": "Kondiĉoj por trovi la celitajn elementojn",
|
||||||
|
"filter_people": "Filtri laŭ homoj",
|
||||||
|
"filter_places": "Filtri laŭ lokoj",
|
||||||
|
"filter_tags": "Filtri laŭ etikedoj",
|
||||||
|
"filters": "Filtriloj",
|
||||||
|
"find_them_fast": "Rapide retrovi la homon per ties nomo",
|
||||||
|
"first": "Unua",
|
||||||
|
"fix_incorrect_match": "Korekti malĝustan kongruiĝon",
|
||||||
|
"folder": "Dosierujo",
|
||||||
|
"folder_not_found": "Dosierujo netrovita",
|
||||||
|
"folders": "Dosierujoj",
|
||||||
|
"folders_feature_description": "Foliumado en dosierujoj por la fotoj kaj videoj en la sistemo",
|
||||||
|
"forgot_pin_code_question": "Ĉu vi forgesis vian PIN-kodon?",
|
||||||
|
"forward": "Antaŭen",
|
||||||
"free_up_space": "Liberigi spacon",
|
"free_up_space": "Liberigi spacon",
|
||||||
"free_up_space_description": "Vi forigos fotojn kaj/aŭ videojn, kiuj havas savkopiojn en la servilo, por liberigi spacon en via aparato. La kopioj en la servilo restos.",
|
"free_up_space_description": "Vi forigos fotojn kaj/aŭ videojn, kiuj havas savkopiojn en la servilo, por liberigi spacon en via aparato. La kopioj en la servilo restos.",
|
||||||
|
"free_up_space_settings_subtitle": "Liberigi spacon en aparato",
|
||||||
|
"full_path": "Plena dosiervojo: {path}",
|
||||||
|
"gcast_enabled": "Google Cast",
|
||||||
|
"gcast_enabled_description": "Tiu ĉi funkcio ŝargas eksterajn rimedojn de Google por sia funkciado.",
|
||||||
"general": "Ĝeneralaj",
|
"general": "Ĝeneralaj",
|
||||||
|
"geolocation_instruction_location": "Elektu elementon kun GPS-koordinatoj por uzi ĝian lokon, aŭ elektu lokon rekte sur la mapo",
|
||||||
|
"get_help": "Trovi helpon",
|
||||||
|
"get_people_error": "Eraro dum serĉo de homoj",
|
||||||
"home_page_favorite_err_local": "Ankoraŭ ne eblas aldoni lokajn elementojn al Preferataĵoj; ignorita(j)",
|
"home_page_favorite_err_local": "Ankoraŭ ne eblas aldoni lokajn elementojn al Preferataĵoj; ignorita(j)",
|
||||||
"home_page_favorite_err_partner": "Ankoraŭ ne eblas aldoni elementojn de partnero al Preferataĵoj; ignorita(j)",
|
"home_page_favorite_err_partner": "Ankoraŭ ne eblas aldoni elementojn de partnero al Preferataĵoj; ignorita(j)",
|
||||||
|
"include_shared_albums": "Inkluzivi dividitajn albumojn",
|
||||||
|
"include_shared_partner_assets": "Inkluzivi elementojn dividitajn de partnero",
|
||||||
"keep_favorites": "Konservi preferataĵojn",
|
"keep_favorites": "Konservi preferataĵojn",
|
||||||
|
"maintenance_action_restore": "Restaŭrado de datumbazo",
|
||||||
|
"maintenance_restore_from_backup": "Restaŭri el savkopio",
|
||||||
|
"maintenance_restore_library": "Restaŭri vian bibliotekon",
|
||||||
|
"maintenance_restore_library_confirm": "Se tio ŝajne bona, daŭrigu kaj restaŭru savkopion!",
|
||||||
|
"maintenance_restore_library_description": "Restaŭrado de datumbazo",
|
||||||
|
"maintenance_restore_library_folder_has_files": "{folder} enhavas {count} dosiero(j)n",
|
||||||
|
"maintenance_restore_library_folder_no_files": "{folder} ne enhavas ajnan dosieron!",
|
||||||
|
"maintenance_restore_library_folder_pass": "legebla(j) kaj skribebla(j)",
|
||||||
|
"maintenance_restore_library_folder_read_fail": "nelegebla(j)",
|
||||||
|
"maintenance_restore_library_folder_write_fail": "ne skribebla(j)",
|
||||||
|
"maintenance_restore_library_hint_missing_files": "Povus esti, ke mankas gravaj dosieroj",
|
||||||
|
"maintenance_restore_library_hint_regenerate_later": "Eblas poste regeneri ilin en Agordoj",
|
||||||
|
"maintenance_restore_library_hint_storage_template_missing_files": "Ĉu vi uzas ŝablonojn de stokado? Povus esti, ke mankas dosieroj",
|
||||||
|
"maintenance_restore_library_loading": "Ŝargiĝas heŭristikoj kaj kontroloj de integreco…",
|
||||||
|
"maintenance_task_restore": "Restaŭrado de elektita savkopio…",
|
||||||
|
"maintenance_task_rollback": "Malsukcesis la restaŭrado; malfariĝas la ŝanĝoj…",
|
||||||
"manage_media_access_settings": "Malfermi agordaĵaron",
|
"manage_media_access_settings": "Malfermi agordaĵaron",
|
||||||
|
"manage_shared_links": "Administri dividitajn ligilojn",
|
||||||
"manage_the_app_settings": "Agordi la apon",
|
"manage_the_app_settings": "Agordi la apon",
|
||||||
"map_settings_only_show_favorites": "Montri nur preferataĵojn",
|
"map_settings_only_show_favorites": "Montri nur preferataĵojn",
|
||||||
"missing": "Netraktitaj",
|
"missing": "Netraktitaj",
|
||||||
|
"mobile_app": "Apo por poŝtelefono",
|
||||||
|
"mobile_app_download_onboarding_note": "Elŝutu la poŝtelefonan apon de Immich per tiuj ebloj",
|
||||||
"networking_subtitle": "Administri agordojn pri finpunktoj de la servilo",
|
"networking_subtitle": "Administri agordojn pri finpunktoj de la servilo",
|
||||||
"no_devices": "Neniuj aprobitaj aparatoj",
|
"no_devices": "Neniuj aprobitaj aparatoj",
|
||||||
"no_explore_results_message": "Alŝutu pli da fotoj por esplori vian kolekton.",
|
"no_explore_results_message": "Alŝutu pli da fotoj por esplori vian kolekton.",
|
||||||
"no_favorites_message": "Aldoni al Preferataĵoj por rapide retrovi viajn plej bonajn bildojn kaj videojn",
|
"no_favorites_message": "Aldoni al Preferataĵoj por rapide retrovi viajn plej bonajn bildojn kaj videojn",
|
||||||
"no_notifications": "Neniuj sciigoj",
|
"no_notifications": "Neniuj sciigoj",
|
||||||
"no_results_description": "Provu sinonimon aŭ pli ĝeneralan ŝlosilvorton",
|
"no_results_description": "Provu sinonimon aŭ pli ĝeneralan ŝlosilvorton",
|
||||||
|
"no_shared_albums_message": "Krei albumon por dividi fotojn kaj videojn kun konatoj",
|
||||||
"notification_permission_dialog_content": "Por ŝalti sciigojn, iru al Agordoj kaj elektu 'permesi'.",
|
"notification_permission_dialog_content": "Por ŝalti sciigojn, iru al Agordoj kaj elektu 'permesi'.",
|
||||||
"notification_permission_list_tile_content": "Donu permeson por ŝalti sciigojn.",
|
"notification_permission_list_tile_content": "Donu permeson por ŝalti sciigojn.",
|
||||||
"notification_permission_list_tile_enable_button": "Ŝalti sciigojn",
|
"notification_permission_list_tile_enable_button": "Ŝalti sciigojn",
|
||||||
@@ -1130,12 +1285,28 @@
|
|||||||
"notification_toggle_setting_description": "Ŝalti sciigojn per retmesaĝo",
|
"notification_toggle_setting_description": "Ŝalti sciigojn per retmesaĝo",
|
||||||
"notifications": "Sciigoj",
|
"notifications": "Sciigoj",
|
||||||
"notifications_setting_description": "Administri sciigojn",
|
"notifications_setting_description": "Administri sciigojn",
|
||||||
|
"onboarding_privacy_description": "La ĉi-subaj (nedevigaj) funkcioj dependas de eksteraj servoj. Vi povas (mal)ŝalti ilin iam ajn.",
|
||||||
"only_favorites": "Nur preferataĵoj",
|
"only_favorites": "Nur preferataĵoj",
|
||||||
|
"owned": "Propraj",
|
||||||
|
"partner_page_empty_message": "Viaj fotoj ankoraŭ ne estas dividitaj kun ajna partnero.",
|
||||||
|
"partner_page_shared_to_title": "Dividita(j) kun",
|
||||||
|
"photo_shared_all_users": "Ŝajne vi dividis viajn fotojn kun ĉiuj uzantoj, aŭ povus esti ke ne ekzistas aliaj uzantoj.",
|
||||||
"preferences_settings_subtitle": "Administri agordojn pri la apo",
|
"preferences_settings_subtitle": "Administri agordojn pri la apo",
|
||||||
"purchase_settings_server_activated": "La administranto respondecas pri la ŝlosilo de aŭtentikeco por la servilo",
|
"purchase_settings_server_activated": "La administranto respondecas pri la ŝlosilo de aŭtentikeco por la servilo",
|
||||||
"rating_clear": "Forviŝi pritakson",
|
"rating_clear": "Forviŝi pritakson",
|
||||||
"refresh": "Denove",
|
"refresh": "Denove",
|
||||||
|
"refresh_encoded_videos": "Renovigi koditajn videojn",
|
||||||
|
"refresh_faces": "Renovigi vizaĝojn",
|
||||||
|
"refresh_metadata": "Renovigi metadatumojn",
|
||||||
|
"refresh_thumbnails": "Renovigi bildetojn",
|
||||||
|
"refreshed": "Renovigita(j)",
|
||||||
|
"refreshes_every_file": "Re-legas ĉiujn ekzistantajn kaj novajn dosierojn",
|
||||||
|
"refreshing_encoded_video": "Renovigado de koditaj videoj",
|
||||||
|
"refreshing_faces": "Renovigado de vizaĝoj",
|
||||||
|
"refreshing_metadata": "Renovigado de metadatumoj",
|
||||||
|
"remove_assets_shared_link_confirmation": "Ĉu vi certas, ke vi volas forigi {count, plural, one {# elementon} other {# elementojn}} de tiu dividita ligilo?",
|
||||||
"remove_from_favorites": "Forigi el preferataĵoj",
|
"remove_from_favorites": "Forigi el preferataĵoj",
|
||||||
|
"remove_from_shared_link": "Forigi el dividita ligilo",
|
||||||
"removed_from_favorites": "Forigita(j) el preferataĵoj",
|
"removed_from_favorites": "Forigita(j) el preferataĵoj",
|
||||||
"removed_from_favorites_count": "{count, plural, other {Forigis #}} el Preferataĵoj",
|
"removed_from_favorites_count": "{count, plural, other {Forigis #}} el Preferataĵoj",
|
||||||
"rescan": "Reanalizi",
|
"rescan": "Reanalizi",
|
||||||
@@ -1144,6 +1315,11 @@
|
|||||||
"reset_sqlite_confirmation": "Ĉu vi certas, ke vi volas forviŝi la datumojn de la apo? Tio forigos ĉiujn agordojn kaj elsalutigos vin.",
|
"reset_sqlite_confirmation": "Ĉu vi certas, ke vi volas forviŝi la datumojn de la apo? Tio forigos ĉiujn agordojn kaj elsalutigos vin.",
|
||||||
"reset_sqlite_confirmation_note": "Noto: vi devos relanĉi la apon por la forviŝo.",
|
"reset_sqlite_confirmation_note": "Noto: vi devos relanĉi la apon por la forviŝo.",
|
||||||
"reset_sqlite_done": "Datumoj de la apo estas forviŝitaj. Bonvolu relanĉi Immich kaj ensalutu denove.",
|
"reset_sqlite_done": "Datumoj de la apo estas forviŝitaj. Bonvolu relanĉi Immich kaj ensalutu denove.",
|
||||||
|
"restore": "Restaŭri",
|
||||||
|
"restore_all": "Restaŭri ĉiujn",
|
||||||
|
"restore_trash_action_prompt": "{count} restaŭrita(j) el rubujo",
|
||||||
|
"restore_user": "Restaŭri uzanton",
|
||||||
|
"restored_asset": "Restaŭri elementon",
|
||||||
"scaffold_body_error_unrecoverable": "Neriparebla eraro okazis. Bonvolu sendi al ni la eraron kaj la stakspuron per Discord aŭ per Github por ke ni povu helpi. Vi povas forviŝi la ĉi-subajn datumojn de la apo se vi volas.",
|
"scaffold_body_error_unrecoverable": "Neriparebla eraro okazis. Bonvolu sendi al ni la eraron kaj la stakspuron per Discord aŭ per Github por ke ni povu helpi. Vi povas forviŝi la ĉi-subajn datumojn de la apo se vi volas.",
|
||||||
"scan": "Analizi",
|
"scan": "Analizi",
|
||||||
"scan_all_libraries": "Analizi ĉiujn bibliotekojn",
|
"scan_all_libraries": "Analizi ĉiujn bibliotekojn",
|
||||||
@@ -1152,18 +1328,79 @@
|
|||||||
"scanning": "Analizado",
|
"scanning": "Analizado",
|
||||||
"scanning_for_album": "Serĉado de albumo...",
|
"scanning_for_album": "Serĉado de albumo...",
|
||||||
"search_suggestion_list_smart_search_hint_1": "Inteligenta serĉado defaŭlte estas ŝaltita. Por serĉi metadatumojn, uzu sintakson tiel ",
|
"search_suggestion_list_smart_search_hint_1": "Inteligenta serĉado defaŭlte estas ŝaltita. Por serĉi metadatumojn, uzu sintakson tiel ",
|
||||||
|
"server_privacy": "Privateco de servilo",
|
||||||
|
"server_restarting_description": "La paĝo baldaŭ reŝargiĝos.",
|
||||||
"setting_notifications_subtitle": "Redakti viajn preferojn pri sciigoj",
|
"setting_notifications_subtitle": "Redakti viajn preferojn pri sciigoj",
|
||||||
|
"share_action_prompt": "Dividis {count} elementojn",
|
||||||
|
"shared": "Dividitaj",
|
||||||
|
"shared_album_activities_input_disable": "Komentado estas malŝaltita",
|
||||||
|
"shared_album_activity_remove_content": "Ĉu vi volas forigi tiun ĉi agon?",
|
||||||
|
"shared_album_activity_remove_title": "Forigi agon",
|
||||||
|
"shared_album_section_people_action_error": "Okazis eraro dum forigo el la albumo",
|
||||||
|
"shared_album_section_people_action_leave": "Forigi uzanton de albumo",
|
||||||
|
"shared_album_section_people_action_remove_user": "Forigi uzanton de albumo",
|
||||||
|
"shared_album_section_people_title": "HOMOJ",
|
||||||
|
"shared_by": "Dividita de",
|
||||||
|
"shared_by_user": "Dividita de {user}",
|
||||||
|
"shared_by_you": "Dividita de vi",
|
||||||
|
"shared_from_partner": "Fotoj de {partner}",
|
||||||
|
"shared_intent_upload_button_progress_text": "{current} el {total} alŝutitaj",
|
||||||
|
"shared_link_app_bar_title": "Dividitaj ligiloj",
|
||||||
|
"shared_link_clipboard_copied_massage": "Kopiita al tondujo",
|
||||||
|
"shared_link_clipboard_text": "Ligilo: {link}\nPasvorto: {password}",
|
||||||
|
"shared_link_create_error": "Okazis eraro dum kreo de dividita ligilo",
|
||||||
|
"shared_link_custom_url_description": "Atingi la dividita ligilo per propra URL-o",
|
||||||
|
"shared_link_edit_description_hint": "Tajpu priskribon de la dividaĵaro",
|
||||||
|
"shared_link_edit_expire_after_option_day": "1 tago",
|
||||||
|
"shared_link_edit_expire_after_option_days": "{count} tagoj",
|
||||||
|
"shared_link_edit_expire_after_option_hour": "1 horo",
|
||||||
|
"shared_link_edit_expire_after_option_hours": "{count} horoj",
|
||||||
|
"shared_link_edit_expire_after_option_minute": "1 minuto",
|
||||||
|
"shared_link_edit_expire_after_option_minutes": "{count} minutoj",
|
||||||
|
"shared_link_edit_expire_after_option_months": "{count} monatoj",
|
||||||
|
"shared_link_edit_expire_after_option_year": "{count} jaro",
|
||||||
|
"shared_link_edit_password_hint": "Tajpu pasvorton por la dividaĵaro",
|
||||||
|
"shared_link_edit_submit_button": "Ĝisdatigi ligilon",
|
||||||
|
"shared_link_error_server_url_fetch": "Ne eblis trovi la URL-on de la servilo",
|
||||||
|
"shared_link_expires_day": "Eksvalidiĝos post {count} tago",
|
||||||
|
"shared_link_expires_days": "Eksvalidiĝos post {count} tagoj",
|
||||||
|
"shared_link_expires_hour": "Eksvalidiĝos post {count} horo",
|
||||||
|
"shared_link_expires_hours": "Eksvalidiĝos post {count} horoj",
|
||||||
|
"shared_link_expires_minute": "Eksvalidiĝos post {count} minuto",
|
||||||
|
"shared_link_expires_minutes": "Eksvalidiĝos post {count} minutoj",
|
||||||
|
"shared_link_expires_never": "Neniam eksvalidiĝos",
|
||||||
|
"shared_link_expires_second": "Eksvalidiĝos post {count} sekundo",
|
||||||
|
"shared_link_expires_seconds": "Eksvalidiĝos post {count} sekundoj",
|
||||||
|
"shared_link_info_chip_metadata": "EXIF",
|
||||||
|
"shared_link_manage_links": "Administri dividitajn ligilojn",
|
||||||
|
"shared_link_options": "Agordoj pri dividitaj ligiloj",
|
||||||
|
"shared_link_password_description": "Devigi uzon de pasvorto por uzi la ligilon",
|
||||||
|
"shared_links": "Dividitaj ligiloj",
|
||||||
|
"shared_links_description": "Dividi fotojn kaj videojn per ligilo",
|
||||||
|
"shared_photos_and_videos_count": "{assetCount, plural, other {# dividitaj fotoj kaj videoj.}}",
|
||||||
|
"shared_with_me": "Dividitaj kun mi",
|
||||||
|
"shared_with_partner": "Dividitaj kun {partner}",
|
||||||
|
"sharing_page_album": "Dividitaj albumoj",
|
||||||
|
"sharing_page_description": "Krei dividitajn albumojn por dividi fotojn kaj videojn kun konatoj.",
|
||||||
|
"sharing_silver_appbar_create_shared_album": "Nova dividita albumo",
|
||||||
|
"show_shared_links": "Montri dividitajn ligilojn",
|
||||||
"start_date": "Komenca dato",
|
"start_date": "Komenca dato",
|
||||||
"start_date_before_end_date": "Komenca dato devas esti antaŭ fina dato",
|
"start_date_before_end_date": "Komenca dato devas esti antaŭ fina dato",
|
||||||
"to_favorite": "Aldoni al preferataĵoj",
|
"to_favorite": "Aldoni al preferataĵoj",
|
||||||
|
"trash_page_restore_all": "Restaŭri ĉiujn",
|
||||||
"trigger_description": "Evento, kiu ekfunkciigas la laborfluon",
|
"trigger_description": "Evento, kiu ekfunkciigas la laborfluon",
|
||||||
"unfavorite": "Forigi el preferataĵoj",
|
"unfavorite": "Forigi el preferataĵoj",
|
||||||
"unfavorite_action_prompt": "{count} forigita(j) el Preferataĵoj",
|
"unfavorite_action_prompt": "{count} forigita(j) el Preferataĵoj",
|
||||||
"untitled_workflow": "Sentitola laborfluo",
|
"untitled_workflow": "Sentitola laborfluo",
|
||||||
"upload_concurrency": "Nombro da samtempaj alŝutoj",
|
"upload_concurrency": "Nombro da samtempaj alŝutoj",
|
||||||
|
"upload_errors": "Alŝuto finita kun {count, plural, one {# eraro} other {# eraroj}}. Reŝargu la paĝon por vidi novajn elementojn.",
|
||||||
|
"upload_success": "Alŝuto sukcese finita. Reŝargu la paĝon por vidi novajn elementojn.",
|
||||||
"user_pin_code_settings_description": "Administri vian PIN-kodon",
|
"user_pin_code_settings_description": "Administri vian PIN-kodon",
|
||||||
|
"user_privacy": "Privateco de uzanto",
|
||||||
"user_purchase_settings_description": "Administri vian aĉeton",
|
"user_purchase_settings_description": "Administri vian aĉeton",
|
||||||
"view_links": "Vidi ligilojn",
|
"view_links": "Vidi ligilojn",
|
||||||
|
"waiting": "En atendovico",
|
||||||
|
"waiting_count": "En atendovico: {count}",
|
||||||
"week": "Semajno",
|
"week": "Semajno",
|
||||||
"wifi_name": "Nomo de Vifireto",
|
"wifi_name": "Nomo de Vifireto",
|
||||||
"workflow_delete_prompt": "Ĉu vi certas, ke vi volas forigi tiun ĉi laborfluon?",
|
"workflow_delete_prompt": "Ĉu vi certas, ke vi volas forigi tiun ĉi laborfluon?",
|
||||||
@@ -1181,5 +1418,6 @@
|
|||||||
"workflows_help_text": "Laborfluo aŭtomatigas agojn pri elementoj, laŭ ekigiloj kaj filtriloj",
|
"workflows_help_text": "Laborfluo aŭtomatigas agojn pri elementoj, laŭ ekigiloj kaj filtriloj",
|
||||||
"year": "Jaro",
|
"year": "Jaro",
|
||||||
"yes": "Jes",
|
"yes": "Jes",
|
||||||
|
"you_dont_have_any_shared_links": "Vi ne havas ajnan dividitan ligilon",
|
||||||
"zero_to_clear_rating": "tuŝu 0 por forviŝi la pritakson de la elemento"
|
"zero_to_clear_rating": "tuŝu 0 por forviŝi la pritakson de la elemento"
|
||||||
}
|
}
|
||||||
|
|||||||
+57
-6
@@ -267,6 +267,8 @@
|
|||||||
"notification_enable_email_notifications": "Habilitar notificaciones por correo electrónico",
|
"notification_enable_email_notifications": "Habilitar notificaciones por correo electrónico",
|
||||||
"notification_settings": "Configuración de las notificaciones",
|
"notification_settings": "Configuración de las notificaciones",
|
||||||
"notification_settings_description": "Administrar la configuración de notificaciones, incluido el correo electrónico",
|
"notification_settings_description": "Administrar la configuración de notificaciones, incluido el correo electrónico",
|
||||||
|
"oauth_allow_insecure_requests": "Permitir solicitudes inseguras",
|
||||||
|
"oauth_allow_insecure_requests_description": "ADVERTENCIA: Esto deshabilita la validación de certificado TLS para peticiones OAuth y le puede exponer a ataques MITM.",
|
||||||
"oauth_auto_launch": "Lanzamiento automático",
|
"oauth_auto_launch": "Lanzamiento automático",
|
||||||
"oauth_auto_launch_description": "Inicie el flujo de inicio de sesión de OAuth automáticamente al acceder a la página de inicio de sesión",
|
"oauth_auto_launch_description": "Inicie el flujo de inicio de sesión de OAuth automáticamente al acceder a la página de inicio de sesión",
|
||||||
"oauth_auto_register": "Registro automático",
|
"oauth_auto_register": "Registro automático",
|
||||||
@@ -274,9 +276,11 @@
|
|||||||
"oauth_button_text": "Texto del botón",
|
"oauth_button_text": "Texto del botón",
|
||||||
"oauth_client_secret_description": "Requerido para clientes confidenciales, o si PKCE (Prueba de clave para el intercambio de códigos) no es compatible con clientes públicos.",
|
"oauth_client_secret_description": "Requerido para clientes confidenciales, o si PKCE (Prueba de clave para el intercambio de códigos) no es compatible con clientes públicos.",
|
||||||
"oauth_enable_description": "Iniciar sesión con OAuth",
|
"oauth_enable_description": "Iniciar sesión con OAuth",
|
||||||
|
"oauth_end_session_url_description": "Redirigir al usuario a esta URI cuando cierra sesión.",
|
||||||
"oauth_mobile_redirect_uri": "URI de redireccionamiento móvil",
|
"oauth_mobile_redirect_uri": "URI de redireccionamiento móvil",
|
||||||
"oauth_mobile_redirect_uri_override": "Sobreescribir URI de redirección móvil",
|
"oauth_mobile_redirect_uri_override": "Sobreescribir URI de redirección móvil",
|
||||||
"oauth_mobile_redirect_uri_override_description": "Habilitar cuando el proveedor de OAuth no permite una URI móvil, como ''{callback}''",
|
"oauth_mobile_redirect_uri_override_description": "Habilitar cuando el proveedor de OAuth no permite una URI móvil, como ''{callback}''",
|
||||||
|
"oauth_prompt_description": "Parámetro de solicitud (p. eje. select_account, login, consent)",
|
||||||
"oauth_role_claim": "Concesión de rol",
|
"oauth_role_claim": "Concesión de rol",
|
||||||
"oauth_role_claim_description": "Otorgar acceso de administrador automáticamente según la presencia de esta concesión. La concesión puede tener \"usuario\" o \"admin\".",
|
"oauth_role_claim_description": "Otorgar acceso de administrador automáticamente según la presencia de esta concesión. La concesión puede tener \"usuario\" o \"admin\".",
|
||||||
"oauth_settings": "OAuth",
|
"oauth_settings": "OAuth",
|
||||||
@@ -767,7 +771,7 @@
|
|||||||
"cleanup_found_assets_with_size": "Se encontraron {count} recursos respaldados ({size})",
|
"cleanup_found_assets_with_size": "Se encontraron {count} recursos respaldados ({size})",
|
||||||
"cleanup_icloud_shared_albums_excluded": "Los álbumes compartidos de iCloud están excluidos del escaneo",
|
"cleanup_icloud_shared_albums_excluded": "Los álbumes compartidos de iCloud están excluidos del escaneo",
|
||||||
"cleanup_no_assets_found": "No se encontraron recursos que coincidan con los criterios anteriores. Liberar espacio solo puede eliminar recursos respaldados en el servidor",
|
"cleanup_no_assets_found": "No se encontraron recursos que coincidan con los criterios anteriores. Liberar espacio solo puede eliminar recursos respaldados en el servidor",
|
||||||
"cleanup_preview_title": "{count} recursos a remover",
|
"cleanup_preview_title": "{count} recursos a eliminar",
|
||||||
"cleanup_step3_description": "Busque recursos respaldados que coincidan con su fecha y conserve la configuración.",
|
"cleanup_step3_description": "Busque recursos respaldados que coincidan con su fecha y conserve la configuración.",
|
||||||
"cleanup_step4_summary": "{count} recursos (creados antes del {date}) para eliminar de tu dispositivo local. Las fotos seguirán accesibles desde la app de Immich.",
|
"cleanup_step4_summary": "{count} recursos (creados antes del {date}) para eliminar de tu dispositivo local. Las fotos seguirán accesibles desde la app de Immich.",
|
||||||
"cleanup_trash_hint": "Para completar la liberación de espacio, abra la aplicación de fotos y vacíe la papelera",
|
"cleanup_trash_hint": "Para completar la liberación de espacio, abra la aplicación de fotos y vacíe la papelera",
|
||||||
@@ -881,15 +885,13 @@
|
|||||||
"cutoff_date_description": "Conserva fotos del último…",
|
"cutoff_date_description": "Conserva fotos del último…",
|
||||||
"cutoff_day": "{count, plural, one {día} other {días}}",
|
"cutoff_day": "{count, plural, one {día} other {días}}",
|
||||||
"cutoff_year": "{count, plural, one {año} other {años}}",
|
"cutoff_year": "{count, plural, one {año} other {años}}",
|
||||||
"daily_title_text_date": "E dd, MMM",
|
|
||||||
"daily_title_text_date_year": "E dd de MMM, yyyy",
|
|
||||||
"dark": "Oscuro",
|
"dark": "Oscuro",
|
||||||
"dark_theme": "Cambiar a tema oscuro",
|
"dark_theme": "Cambiar a tema oscuro",
|
||||||
"date": "Fecha",
|
"date": "Fecha",
|
||||||
"date_after": "Fecha posterior",
|
"date_after": "Fecha posterior",
|
||||||
"date_and_time": "Fecha y hora",
|
"date_and_time": "Fecha y hora",
|
||||||
"date_before": "Fecha anterior",
|
"date_before": "Fecha anterior",
|
||||||
"date_format": "E d, LLL y • h:mm a",
|
"date_of_birth": "Fecha de nacimiento",
|
||||||
"date_of_birth_saved": "Guardada con éxito la fecha de nacimiento",
|
"date_of_birth_saved": "Guardada con éxito la fecha de nacimiento",
|
||||||
"date_range": "Rango de fechas",
|
"date_range": "Rango de fechas",
|
||||||
"day": "Día",
|
"day": "Día",
|
||||||
@@ -1236,6 +1238,7 @@
|
|||||||
"free_up_space_description": "Elimina tus fotos y videos de tu dispositivo para liberar espacio. Los respaldos en el servidor se mantendrán seguros.",
|
"free_up_space_description": "Elimina tus fotos y videos de tu dispositivo para liberar espacio. Los respaldos en el servidor se mantendrán seguros.",
|
||||||
"free_up_space_settings_subtitle": "Liberar espacio del dispositivo",
|
"free_up_space_settings_subtitle": "Liberar espacio del dispositivo",
|
||||||
"full_path": "Ruta completa: {path}",
|
"full_path": "Ruta completa: {path}",
|
||||||
|
"full_path_or_folder": "Ruta completa o carpeta",
|
||||||
"gcast_enabled": "Google Cast",
|
"gcast_enabled": "Google Cast",
|
||||||
"gcast_enabled_description": "Esta funcionalidad carga recursos externos desde Google para poder funcionar.",
|
"gcast_enabled_description": "Esta funcionalidad carga recursos externos desde Google para poder funcionar.",
|
||||||
"general": "General",
|
"general": "General",
|
||||||
@@ -1392,11 +1395,13 @@
|
|||||||
"light_theme": "Cambiar a tema claro",
|
"light_theme": "Cambiar a tema claro",
|
||||||
"like": "Me gusta",
|
"like": "Me gusta",
|
||||||
"like_deleted": "Me gusta eliminado",
|
"like_deleted": "Me gusta eliminado",
|
||||||
|
"link": "Enlace",
|
||||||
"link_motion_video": "Enlazar vídeo en movimiento",
|
"link_motion_video": "Enlazar vídeo en movimiento",
|
||||||
"link_to_docs": "Para más información, consulta la <link>documentación</link>.",
|
"link_to_docs": "Para más información, consulta la <link>documentación</link>.",
|
||||||
"link_to_oauth": "Enlace a OAuth",
|
"link_to_oauth": "Enlace a OAuth",
|
||||||
"linked_oauth_account": "Cuenta OAuth vinculada",
|
"linked_oauth_account": "Cuenta OAuth vinculada",
|
||||||
"list": "Lista",
|
"list": "Lista",
|
||||||
|
"live": "En vivo",
|
||||||
"loading": "Cargando",
|
"loading": "Cargando",
|
||||||
"loading_search_results_failed": "Error al cargar los resultados de la búsqueda",
|
"loading_search_results_failed": "Error al cargar los resultados de la búsqueda",
|
||||||
"local": "Local",
|
"local": "Local",
|
||||||
@@ -1518,6 +1523,38 @@
|
|||||||
"marked_all_as_read": "Todos marcados como leídos",
|
"marked_all_as_read": "Todos marcados como leídos",
|
||||||
"matches": "Coincidencias",
|
"matches": "Coincidencias",
|
||||||
"matching_assets": "Recursos coincidentes",
|
"matching_assets": "Recursos coincidentes",
|
||||||
|
"media_chrome": {
|
||||||
|
"auto": "Auto",
|
||||||
|
"captions": "Subtítulos",
|
||||||
|
"captions_off": "Apagado",
|
||||||
|
"closed_captions": "subtítulos",
|
||||||
|
"decode_error": "Error de decodificación",
|
||||||
|
"disable_captions": "Desactivar subtítulos",
|
||||||
|
"enable_captions": "Activar subtítulos",
|
||||||
|
"enter_fullscreen_mode": "Entrar en modo pantalla completa",
|
||||||
|
"exit_fullscreen_mode": "Salir del modo pantalla completa",
|
||||||
|
"loop": "Bucle",
|
||||||
|
"media_error_description": "Un error de medios causó la interrupción de la reproducción. El contenido podría estar dañado o tu navegador no admite este formato.",
|
||||||
|
"media_loading": "cargando medios",
|
||||||
|
"mute": "Silenciar",
|
||||||
|
"network_error": "Error de red",
|
||||||
|
"network_error_description": "Un error de red causó la falla en la descarga del contenido.",
|
||||||
|
"not_supported_error": "Fuente no compatible",
|
||||||
|
"playback_rate": "Velocidad de reproducción",
|
||||||
|
"playback_rate_current": "velocidad de reproducción actual",
|
||||||
|
"playback_rate_value": "Velocidad de reproducción {playbackRate}",
|
||||||
|
"playback_time": "tiempo de reproducción",
|
||||||
|
"quality": "Calidad",
|
||||||
|
"second": "segundo",
|
||||||
|
"seconds": "segundos",
|
||||||
|
"time_value_of_total_time": "{currentTime} de {totalTime}",
|
||||||
|
"time_value_remaining": "{time} restante",
|
||||||
|
"unmute": "Reactivar sonido",
|
||||||
|
"unsupported_error_description": "Ocurrió un error de incompatibilidad. El servidor o la red fallaron, o tu navegador no admite este formato.",
|
||||||
|
"video_not_loaded_unknown_time": "video no cargado, tiempo desconocido.",
|
||||||
|
"video_player": "reproductor de video",
|
||||||
|
"volume": "volumen"
|
||||||
|
},
|
||||||
"media_type": "Tipo de medio",
|
"media_type": "Tipo de medio",
|
||||||
"memories": "Recuerdos",
|
"memories": "Recuerdos",
|
||||||
"memories_all_caught_up": "Puesto al día",
|
"memories_all_caught_up": "Puesto al día",
|
||||||
@@ -1544,8 +1581,8 @@
|
|||||||
"mobile_app_download_onboarding_note": "Descarga la aplicación móvil utilizando las siguientes opciones",
|
"mobile_app_download_onboarding_note": "Descarga la aplicación móvil utilizando las siguientes opciones",
|
||||||
"model": "Modelo",
|
"model": "Modelo",
|
||||||
"month": "Mes",
|
"month": "Mes",
|
||||||
"monthly_title_text_date_format": "MMMM a",
|
|
||||||
"more": "Mas",
|
"more": "Mas",
|
||||||
|
"motion": "En movimiento",
|
||||||
"move": "Mover",
|
"move": "Mover",
|
||||||
"move_down": "Bajar",
|
"move_down": "Bajar",
|
||||||
"move_off_locked_folder": "Sacar de la carpeta protegida",
|
"move_off_locked_folder": "Sacar de la carpeta protegida",
|
||||||
@@ -1562,6 +1599,8 @@
|
|||||||
"multiselect_grid_edit_gps_err_read_only": "No se puede editar la ubicación de recursos de solo lectura, omitiendo",
|
"multiselect_grid_edit_gps_err_read_only": "No se puede editar la ubicación de recursos de solo lectura, omitiendo",
|
||||||
"mute_memories": "Silenciar recuerdos",
|
"mute_memories": "Silenciar recuerdos",
|
||||||
"my_albums": "Mis álbumes",
|
"my_albums": "Mis álbumes",
|
||||||
|
"my_immich_description": "Copiar la página actual como enlace de Mi Immich",
|
||||||
|
"my_immich_title": "Enlace de Mi Immich",
|
||||||
"name": "Nombre",
|
"name": "Nombre",
|
||||||
"name_or_nickname": "Nombre o apodo",
|
"name_or_nickname": "Nombre o apodo",
|
||||||
"name_required": "El nombre es obligatorio",
|
"name_required": "El nombre es obligatorio",
|
||||||
@@ -1760,7 +1799,7 @@
|
|||||||
"preferences_settings_title": "Preferencias",
|
"preferences_settings_title": "Preferencias",
|
||||||
"preparing": "Preparando",
|
"preparing": "Preparando",
|
||||||
"preset": "Preestablecido",
|
"preset": "Preestablecido",
|
||||||
"preview": "Posterior",
|
"preview": "Previsualizar",
|
||||||
"previous": "Anterior",
|
"previous": "Anterior",
|
||||||
"previous_memory": "Recuerdo anterior",
|
"previous_memory": "Recuerdo anterior",
|
||||||
"previous_or_next_day": "Día posterior/anterior",
|
"previous_or_next_day": "Día posterior/anterior",
|
||||||
@@ -1853,6 +1892,7 @@
|
|||||||
"remove_assets_title": "¿Eliminar recursos?",
|
"remove_assets_title": "¿Eliminar recursos?",
|
||||||
"remove_custom_date_range": "Eliminar intervalo de fechas personalizado",
|
"remove_custom_date_range": "Eliminar intervalo de fechas personalizado",
|
||||||
"remove_deleted_assets": "Eliminar recursos sin conexión",
|
"remove_deleted_assets": "Eliminar recursos sin conexión",
|
||||||
|
"remove_filter": "Eliminar filtro",
|
||||||
"remove_from_album": "Eliminar del álbum",
|
"remove_from_album": "Eliminar del álbum",
|
||||||
"remove_from_album_action_prompt": "{count} eliminado del álbum",
|
"remove_from_album_action_prompt": "{count} eliminado del álbum",
|
||||||
"remove_from_favorites": "Quitar de favoritos",
|
"remove_from_favorites": "Quitar de favoritos",
|
||||||
@@ -1926,6 +1966,8 @@
|
|||||||
"scan_settings": "Configuración de escaneo",
|
"scan_settings": "Configuración de escaneo",
|
||||||
"scanning": "Escaneando",
|
"scanning": "Escaneando",
|
||||||
"scanning_for_album": "Buscando álbum...",
|
"scanning_for_album": "Buscando álbum...",
|
||||||
|
"screencast_mode_description": "Mostrar los indicadores de eventos del teclado y del ratón en la pantalla",
|
||||||
|
"screencast_mode_title": "Alternar modo de grabación de pantalla",
|
||||||
"search": "Buscar",
|
"search": "Buscar",
|
||||||
"search_albums": "Buscar álbumes",
|
"search_albums": "Buscar álbumes",
|
||||||
"search_by_context": "Buscar por contexto",
|
"search_by_context": "Buscar por contexto",
|
||||||
@@ -1933,6 +1975,8 @@
|
|||||||
"search_by_description_example": "Día de senderismo en Sapa",
|
"search_by_description_example": "Día de senderismo en Sapa",
|
||||||
"search_by_filename": "Buscar por nombre de archivo o extensión",
|
"search_by_filename": "Buscar por nombre de archivo o extensión",
|
||||||
"search_by_filename_example": "es decir IMG_1234.JPG o PNG",
|
"search_by_filename_example": "es decir IMG_1234.JPG o PNG",
|
||||||
|
"search_by_full_path": "Buscar por ruta completa o carpeta",
|
||||||
|
"search_by_full_path_example": "John/Proyectos/Impresión_3D/2026-07-01 Puedes buscar Proyectos, 3D, Impresión, 2026, etc.",
|
||||||
"search_by_ocr": "Buscar por OCR",
|
"search_by_ocr": "Buscar por OCR",
|
||||||
"search_by_ocr_example": "Café con leche",
|
"search_by_ocr_example": "Café con leche",
|
||||||
"search_camera_lens_model": "Buscar modelo de lente...",
|
"search_camera_lens_model": "Buscar modelo de lente...",
|
||||||
@@ -2148,6 +2192,7 @@
|
|||||||
"show_schema": "Mostrar esquema",
|
"show_schema": "Mostrar esquema",
|
||||||
"show_search_options": "Mostrar opciones de búsqueda",
|
"show_search_options": "Mostrar opciones de búsqueda",
|
||||||
"show_shared_links": "Mostrar enlaces compartidos",
|
"show_shared_links": "Mostrar enlaces compartidos",
|
||||||
|
"show_slideshow_metadata_overlay": "Mostrar información de la imagen por superposición",
|
||||||
"show_slideshow_transition": "Mostrar la transición de las diapositivas",
|
"show_slideshow_transition": "Mostrar la transición de las diapositivas",
|
||||||
"show_supporter_badge": "Insignia de colaborador",
|
"show_supporter_badge": "Insignia de colaborador",
|
||||||
"show_supporter_badge_description": "Mostrar una insignia de colaborador",
|
"show_supporter_badge_description": "Mostrar una insignia de colaborador",
|
||||||
@@ -2163,6 +2208,9 @@
|
|||||||
"skip_to_folders": "Ir a las carpetas",
|
"skip_to_folders": "Ir a las carpetas",
|
||||||
"skip_to_tags": "Ir a las etiquetas",
|
"skip_to_tags": "Ir a las etiquetas",
|
||||||
"slideshow": "Pase de diapositivas",
|
"slideshow": "Pase de diapositivas",
|
||||||
|
"slideshow_metadata_overlay_mode": "Contenido superpuesto",
|
||||||
|
"slideshow_metadata_overlay_mode_description_only": "Solo descripción",
|
||||||
|
"slideshow_metadata_overlay_mode_full": "Lleno",
|
||||||
"slideshow_repeat": "Repetir presentación de diapositivas",
|
"slideshow_repeat": "Repetir presentación de diapositivas",
|
||||||
"slideshow_repeat_description": "Volver al inicio cuando finaliza la presentación de diapositivas",
|
"slideshow_repeat_description": "Volver al inicio cuando finaliza la presentación de diapositivas",
|
||||||
"slideshow_settings": "Ajustes de diapositivas",
|
"slideshow_settings": "Ajustes de diapositivas",
|
||||||
@@ -2214,6 +2262,8 @@
|
|||||||
"sync_status": "Estado de la sincronización",
|
"sync_status": "Estado de la sincronización",
|
||||||
"sync_status_subtitle": "Ver y gestionar el estado de la sincronización",
|
"sync_status_subtitle": "Ver y gestionar el estado de la sincronización",
|
||||||
"sync_upload_album_setting_subtitle": "Crea y sube tus fotos y videos a los álbumes seleccionados en Immich",
|
"sync_upload_album_setting_subtitle": "Crea y sube tus fotos y videos a los álbumes seleccionados en Immich",
|
||||||
|
"system_theme": "Tema del sistema",
|
||||||
|
"system_theme_command_description": "Usar el tema del sistema ({value})",
|
||||||
"tag": "Etiqueta",
|
"tag": "Etiqueta",
|
||||||
"tag_assets": "Etiquetar recursos",
|
"tag_assets": "Etiquetar recursos",
|
||||||
"tag_created": "Etiqueta creada: {tag}",
|
"tag_created": "Etiqueta creada: {tag}",
|
||||||
@@ -2425,6 +2475,7 @@
|
|||||||
"workflows": "Flujos de trabajo",
|
"workflows": "Flujos de trabajo",
|
||||||
"workflows_help_text": "Los flujos de trabajo automatizan acciones en sus recursos según activadores y filtros",
|
"workflows_help_text": "Los flujos de trabajo automatizan acciones en sus recursos según activadores y filtros",
|
||||||
"wrong_pin_code": "Código PIN incorrecto",
|
"wrong_pin_code": "Código PIN incorrecto",
|
||||||
|
"x_of_total": "{x}/{total}",
|
||||||
"year": "Año",
|
"year": "Año",
|
||||||
"years_ago": "Hace {years, plural, one {# año} other {# años}}",
|
"years_ago": "Hace {years, plural, one {# año} other {# años}}",
|
||||||
"yes": "Sí",
|
"yes": "Sí",
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user