mirror of
https://github.com/immich-app/immich.git
synced 2025-12-09 14:21:02 -08:00
Compare commits
4 Commits
v1.130.1
...
feat/backu
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
04ce6b3bcb | ||
|
|
fc921fbe9f | ||
|
|
f588a609d9 | ||
|
|
1496627551 |
@@ -1,4 +1,4 @@
|
||||
ARG BASEIMAGE=mcr.microsoft.com/devcontainers/typescript-node:22@sha256:2ef23730ec68d8511ec8e6e0b82550ca728b256805d81f60ed890f3bfb21cfb9
|
||||
ARG BASEIMAGE=mcr.microsoft.com/devcontainers/typescript-node:22@sha256:9791f4aa527774bc370c6bd2f6705ce5a686f1e6f204badd8dfaacce28c631ae
|
||||
FROM ${BASEIMAGE}
|
||||
|
||||
# Flutter SDK
|
||||
|
||||
1
.github/.nvmrc
vendored
1
.github/.nvmrc
vendored
@@ -1 +0,0 @@
|
||||
22.14.0
|
||||
@@ -1,5 +1,5 @@
|
||||
title: '[Feature] feature-name-goes-here'
|
||||
labels: ['feature']
|
||||
title: "[Feature] feature-name-goes-here"
|
||||
labels: ["feature"]
|
||||
|
||||
body:
|
||||
- type: markdown
|
||||
@@ -13,7 +13,7 @@ body:
|
||||
attributes:
|
||||
label: I have searched the existing feature requests, both open and closed, to make sure this is not a duplicate request.
|
||||
options:
|
||||
- label: 'Yes'
|
||||
- label: "Yes"
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
|
||||
9
.github/ISSUE_TEMPLATE/bug_report.yaml
vendored
9
.github/ISSUE_TEMPLATE/bug_report.yaml
vendored
@@ -5,7 +5,7 @@ body:
|
||||
attributes:
|
||||
label: I have searched the existing issues, both open and closed, to make sure this is not a duplicate report.
|
||||
options:
|
||||
- label: 'Yes'
|
||||
- label: "Yes"
|
||||
required: true
|
||||
|
||||
- type: markdown
|
||||
@@ -84,7 +84,7 @@ body:
|
||||
id: repro
|
||||
attributes:
|
||||
label: Reproduction steps
|
||||
description: 'How do you trigger this bug? Please walk us through it step by step.'
|
||||
description: "How do you trigger this bug? Please walk us through it step by step."
|
||||
value: |
|
||||
1.
|
||||
2.
|
||||
@@ -97,13 +97,12 @@ body:
|
||||
id: logs
|
||||
attributes:
|
||||
label: Relevant log output
|
||||
description:
|
||||
Please copy and paste any relevant logs below. (code formatting is
|
||||
description: Please copy and paste any relevant logs below. (code formatting is
|
||||
enabled, no need for backticks)
|
||||
render: shell
|
||||
validations:
|
||||
required: false
|
||||
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Additional information
|
||||
|
||||
28
.github/package-lock.json
generated
vendored
28
.github/package-lock.json
generated
vendored
@@ -1,28 +0,0 @@
|
||||
{
|
||||
"name": ".github",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"devDependencies": {
|
||||
"prettier": "^3.5.3"
|
||||
}
|
||||
},
|
||||
"node_modules/prettier": {
|
||||
"version": "3.5.3",
|
||||
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.5.3.tgz",
|
||||
"integrity": "sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"prettier": "bin/prettier.cjs"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/prettier/prettier?sponsor=1"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
9
.github/package.json
vendored
9
.github/package.json
vendored
@@ -1,9 +0,0 @@
|
||||
{
|
||||
"scripts": {
|
||||
"format": "prettier --check .",
|
||||
"format:fix": "prettier --write ."
|
||||
},
|
||||
"devDependencies": {
|
||||
"prettier": "^3.5.3"
|
||||
}
|
||||
}
|
||||
66
.github/release.yml
vendored
66
.github/release.yml
vendored
@@ -1,33 +1,33 @@
|
||||
changelog:
|
||||
categories:
|
||||
- title: 🚨 Breaking Changes
|
||||
labels:
|
||||
- changelog:breaking-change
|
||||
|
||||
- title: 🫥 Deprecated Changes
|
||||
labels:
|
||||
- changelog:deprecated
|
||||
|
||||
- title: 🔒 Security
|
||||
labels:
|
||||
- changelog:security
|
||||
|
||||
- title: 🚀 Features
|
||||
labels:
|
||||
- changelog:feature
|
||||
|
||||
- title: 🌟 Enhancements
|
||||
labels:
|
||||
- changelog:enhancement
|
||||
|
||||
- title: 🐛 Bug fixes
|
||||
labels:
|
||||
- changelog:bugfix
|
||||
|
||||
- title: 📚 Documentation
|
||||
labels:
|
||||
- changelog:documentation
|
||||
|
||||
- title: 🌐 Translations
|
||||
labels:
|
||||
- changelog:translation
|
||||
changelog:
|
||||
categories:
|
||||
- title: 🚨 Breaking Changes
|
||||
labels:
|
||||
- changelog:breaking-change
|
||||
|
||||
- title: 🫥 Deprecated Changes
|
||||
labels:
|
||||
- changelog:deprecated
|
||||
|
||||
- title: 🔒 Security
|
||||
labels:
|
||||
- changelog:security
|
||||
|
||||
- title: 🚀 Features
|
||||
labels:
|
||||
- changelog:feature
|
||||
|
||||
- title: 🌟 Enhancements
|
||||
labels:
|
||||
- changelog:enhancement
|
||||
|
||||
- title: 🐛 Bug fixes
|
||||
labels:
|
||||
- changelog:bugfix
|
||||
|
||||
- title: 📚 Documentation
|
||||
labels:
|
||||
- changelog:documentation
|
||||
|
||||
- title: 🌐 Translations
|
||||
labels:
|
||||
- changelog:translation
|
||||
|
||||
12
.github/workflows/build-mobile.yml
vendored
12
.github/workflows/build-mobile.yml
vendored
@@ -22,9 +22,9 @@ jobs:
|
||||
should_run: ${{ steps.found_paths.outputs.mobile == 'true' || steps.should_force.outputs.should_force == 'true' }}
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
||||
uses: actions/checkout@v4
|
||||
- id: found_paths
|
||||
uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3
|
||||
uses: dorny/paths-filter@v3
|
||||
with:
|
||||
filters: |
|
||||
mobile:
|
||||
@@ -51,18 +51,18 @@ jobs:
|
||||
ref="${input_ref:-$github_ref}"
|
||||
echo "ref=$ref" >> $GITHUB_OUTPUT
|
||||
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ steps.get-ref.outputs.ref }}
|
||||
|
||||
- uses: actions/setup-java@3a4f6e1af504cf6a31855fa899c6aa5355ba6c12 # v4
|
||||
- uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: 'zulu'
|
||||
java-version: '17'
|
||||
cache: 'gradle'
|
||||
|
||||
- name: Setup Flutter SDK
|
||||
uses: subosito/flutter-action@e938fdf56512cc96ef2f93601a5a40bde3801046 # v2
|
||||
uses: subosito/flutter-action@v2
|
||||
with:
|
||||
channel: 'stable'
|
||||
flutter-version-file: ./mobile/pubspec.yaml
|
||||
@@ -89,7 +89,7 @@ jobs:
|
||||
flutter build apk --release --split-per-abi --target-platform android-arm,android-arm64,android-x64
|
||||
|
||||
- name: Publish Android Artifact
|
||||
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: release-apk-signed
|
||||
path: mobile/build/app/outputs/flutter-apk/*.apk
|
||||
|
||||
2
.github/workflows/cache-cleanup.yml
vendored
2
.github/workflows/cache-cleanup.yml
vendored
@@ -14,7 +14,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check out code
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Cleanup
|
||||
run: |
|
||||
|
||||
17
.github/workflows/cli.yml
vendored
17
.github/workflows/cli.yml
vendored
@@ -6,6 +6,7 @@ on:
|
||||
- 'cli/**'
|
||||
- '.github/workflows/cli.yml'
|
||||
pull_request:
|
||||
branches: [main]
|
||||
paths:
|
||||
- 'cli/**'
|
||||
- '.github/workflows/cli.yml'
|
||||
@@ -28,9 +29,9 @@ jobs:
|
||||
working-directory: ./cli
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
||||
- uses: actions/checkout@v4
|
||||
# Setup .npmrc file to publish to npm
|
||||
- uses: actions/setup-node@cdca7365b2dadb8aad0a33bc7601856ffabcc48e # v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: './cli/.nvmrc'
|
||||
registry-url: 'https://registry.npmjs.org'
|
||||
@@ -52,16 +53,16 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@29109295f81e9208d7d86ff1c6c12d2833863392 # v3.6.0
|
||||
uses: docker/setup-qemu-action@v3.6.0
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@b5ca514318bd6ebac0fb2aedd5d36ec1b5c232a2 # v3.10.0
|
||||
uses: docker/setup-buildx-action@v3.10.0
|
||||
|
||||
- name: Login to GitHub Container Registry
|
||||
uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3
|
||||
uses: docker/login-action@v3
|
||||
if: ${{ !github.event.pull_request.head.repo.fork }}
|
||||
with:
|
||||
registry: ghcr.io
|
||||
@@ -76,7 +77,7 @@ jobs:
|
||||
|
||||
- name: Generate docker image tags
|
||||
id: metadata
|
||||
uses: docker/metadata-action@902fa8ec7d6ecbf8d84d538b9b233a880e428804 # v5
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
flavor: |
|
||||
latest=false
|
||||
@@ -87,7 +88,7 @@ jobs:
|
||||
type=raw,value=latest,enable=${{ github.event_name == 'release' }}
|
||||
|
||||
- name: Build and push image
|
||||
uses: docker/build-push-action@471d1dc4e07e5cdedd4c2171150001c434f0b7a4 # v6.15.0
|
||||
uses: docker/build-push-action@v6.15.0
|
||||
with:
|
||||
file: cli/Dockerfile
|
||||
platforms: linux/amd64,linux/arm64
|
||||
|
||||
63
.github/workflows/codeql-analysis.yml
vendored
63
.github/workflows/codeql-analysis.yml
vendored
@@ -9,14 +9,14 @@
|
||||
# the `language` matrix defined below to confirm you have the correct set of
|
||||
# supported CodeQL languages.
|
||||
#
|
||||
name: 'CodeQL'
|
||||
name: "CodeQL"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: ['main']
|
||||
branches: [ "main" ]
|
||||
pull_request:
|
||||
# The branches below must be a subset of the branches above
|
||||
branches: ['main']
|
||||
branches: [ "main" ]
|
||||
schedule:
|
||||
- cron: '20 13 * * 1'
|
||||
|
||||
@@ -36,42 +36,43 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
language: ['javascript', 'python']
|
||||
language: [ 'javascript', 'python' ]
|
||||
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
|
||||
# Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@1b549b9259bda1cb5ddde3b41741a82a2d15a841 # v3
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||
# By default, queries listed here will override any specified in a config file.
|
||||
# Prefix the list here with "+" to use these queries and those in the config file.
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v3
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||
# By default, queries listed here will override any specified in a config file.
|
||||
# Prefix the list here with "+" to use these queries and those in the config file.
|
||||
|
||||
# Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
|
||||
# queries: security-extended,security-and-quality
|
||||
# Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
|
||||
# queries: security-extended,security-and-quality
|
||||
|
||||
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
||||
# If this step fails, then you should remove it and run the build manually (see below)
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@1b549b9259bda1cb5ddde3b41741a82a2d15a841 # v3
|
||||
|
||||
# ℹ️ 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
|
||||
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
||||
# If this step fails, then you should remove it and run the build manually (see below)
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@v3
|
||||
|
||||
# If the Autobuild fails above, remove it and uncomment the following three lines.
|
||||
# modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.
|
||||
# ℹ️ 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
|
||||
|
||||
# - run: |
|
||||
# echo "Run, Build Application using script"
|
||||
# ./location_of_script_within_repo/buildscript.sh
|
||||
# If the Autobuild fails above, remove it and uncomment the following three lines.
|
||||
# modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@1b549b9259bda1cb5ddde3b41741a82a2d15a841 # v3
|
||||
with:
|
||||
category: '/language:${{matrix.language}}'
|
||||
# - run: |
|
||||
# echo "Run, Build Application using script"
|
||||
# ./location_of_script_within_repo/buildscript.sh
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v3
|
||||
with:
|
||||
category: "/language:${{matrix.language}}"
|
||||
|
||||
98
.github/workflows/docker.yml
vendored
98
.github/workflows/docker.yml
vendored
@@ -23,9 +23,9 @@ jobs:
|
||||
should_run_ml: ${{ steps.found_paths.outputs.machine-learning == 'true' || steps.should_force.outputs.should_force == 'true' }}
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
||||
uses: actions/checkout@v4
|
||||
- id: found_paths
|
||||
uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3
|
||||
uses: dorny/paths-filter@v3
|
||||
with:
|
||||
filters: |
|
||||
server:
|
||||
@@ -49,23 +49,23 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
suffix: ['', '-cuda', '-rocm', '-openvino', '-armnn', '-rknn']
|
||||
suffix: ["", "-cuda", "-openvino", "-armnn"]
|
||||
steps:
|
||||
- name: Login to GitHub Container Registry
|
||||
uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.repository_owner }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Re-tag image
|
||||
run: |
|
||||
REGISTRY_NAME="ghcr.io"
|
||||
REPOSITORY=${{ github.repository_owner }}/immich-machine-learning
|
||||
TAG_OLD=main${{ matrix.suffix }}
|
||||
TAG_PR=${{ github.event.number == 0 && github.ref_name || format('pr-{0}', github.event.number) }}${{ matrix.suffix }}
|
||||
TAG_COMMIT=commit-${{ github.event_name != 'pull_request' && github.sha || github.event.pull_request.head.sha }}${{ matrix.suffix }}
|
||||
docker buildx imagetools create -t $REGISTRY_NAME/$REPOSITORY:$TAG_PR $REGISTRY_NAME/$REPOSITORY:$TAG_OLD
|
||||
docker buildx imagetools create -t $REGISTRY_NAME/$REPOSITORY:$TAG_COMMIT $REGISTRY_NAME/$REPOSITORY:$TAG_OLD
|
||||
- name: Login to GitHub Container Registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.repository_owner }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Re-tag image
|
||||
run: |
|
||||
REGISTRY_NAME="ghcr.io"
|
||||
REPOSITORY=${{ github.repository_owner }}/immich-machine-learning
|
||||
TAG_OLD=main${{ matrix.suffix }}
|
||||
TAG_PR=${{ github.event.number == 0 && github.ref_name || format('pr-{0}', github.event.number) }}${{ matrix.suffix }}
|
||||
TAG_COMMIT=commit-${{ github.event_name != 'pull_request' && github.sha || github.event.pull_request.head.sha }}${{ matrix.suffix }}
|
||||
docker buildx imagetools create -t $REGISTRY_NAME/$REPOSITORY:$TAG_PR $REGISTRY_NAME/$REPOSITORY:$TAG_OLD
|
||||
docker buildx imagetools create -t $REGISTRY_NAME/$REPOSITORY:$TAG_COMMIT $REGISTRY_NAME/$REPOSITORY:$TAG_OLD
|
||||
|
||||
retag_server:
|
||||
name: Re-Tag Server
|
||||
@@ -74,10 +74,10 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
suffix: ['']
|
||||
suffix: [""]
|
||||
steps:
|
||||
- name: Login to GitHub Container Registry
|
||||
uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.repository_owner }}
|
||||
@@ -120,11 +120,6 @@ jobs:
|
||||
device: cuda
|
||||
suffix: -cuda
|
||||
|
||||
- platform: linux/amd64
|
||||
runner: mich
|
||||
device: rocm
|
||||
suffix: -rocm
|
||||
|
||||
- platform: linux/amd64
|
||||
runner: ubuntu-latest
|
||||
device: openvino
|
||||
@@ -135,11 +130,6 @@ jobs:
|
||||
device: armnn
|
||||
suffix: -armnn
|
||||
|
||||
- platform: linux/arm64
|
||||
runner: ubuntu-24.04-arm
|
||||
device: rknn
|
||||
suffix: -rknn
|
||||
|
||||
steps:
|
||||
- name: Prepare
|
||||
run: |
|
||||
@@ -147,13 +137,13 @@ jobs:
|
||||
echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@b5ca514318bd6ebac0fb2aedd5d36ec1b5c232a2 # v3.10.0
|
||||
uses: docker/setup-buildx-action@v3.10.0
|
||||
|
||||
- name: Login to GitHub Container Registry
|
||||
uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3
|
||||
uses: docker/login-action@v3
|
||||
if: ${{ !github.event.pull_request.head.repo.fork }}
|
||||
with:
|
||||
registry: ghcr.io
|
||||
@@ -180,7 +170,7 @@ jobs:
|
||||
|
||||
- name: Build and push image
|
||||
id: build
|
||||
uses: docker/build-push-action@471d1dc4e07e5cdedd4c2171150001c434f0b7a4 # v6.15.0
|
||||
uses: docker/build-push-action@v6.15.0
|
||||
with:
|
||||
context: ${{ env.context }}
|
||||
file: ${{ env.file }}
|
||||
@@ -205,7 +195,7 @@ jobs:
|
||||
touch "${{ runner.temp }}/digests/${digest#sha256:}"
|
||||
|
||||
- name: Upload digest
|
||||
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: ml-digests-${{ matrix.device }}-${{ env.PLATFORM_PAIR }}
|
||||
path: ${{ runner.temp }}/digests/*
|
||||
@@ -225,19 +215,15 @@ jobs:
|
||||
- device: cpu
|
||||
- device: cuda
|
||||
suffix: -cuda
|
||||
- device: rocm
|
||||
suffix: -rocm
|
||||
- device: openvino
|
||||
suffix: -openvino
|
||||
- device: armnn
|
||||
suffix: -armnn
|
||||
- device: rknn
|
||||
suffix: -rknn
|
||||
needs:
|
||||
- build_and_push_ml
|
||||
steps:
|
||||
- name: Download digests
|
||||
uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
path: ${{ runner.temp }}/digests
|
||||
pattern: ml-digests-${{ matrix.device }}-*
|
||||
@@ -245,26 +231,26 @@ jobs:
|
||||
|
||||
- name: Login to Docker Hub
|
||||
if: ${{ github.event_name == 'release' }}
|
||||
uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
- name: Login to GHCR
|
||||
uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.repository_owner }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@b5ca514318bd6ebac0fb2aedd5d36ec1b5c232a2 # v3
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Generate docker image tags
|
||||
id: meta
|
||||
uses: docker/metadata-action@902fa8ec7d6ecbf8d84d538b9b233a880e428804 # v5
|
||||
uses: docker/metadata-action@v5
|
||||
env:
|
||||
DOCKER_METADATA_PR_HEAD_SHA: 'true'
|
||||
DOCKER_METADATA_PR_HEAD_SHA: "true"
|
||||
with:
|
||||
flavor: |
|
||||
# Disable latest tag
|
||||
@@ -315,13 +301,13 @@ jobs:
|
||||
echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@b5ca514318bd6ebac0fb2aedd5d36ec1b5c232a2 # v3
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Login to GitHub Container Registry
|
||||
uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3
|
||||
uses: docker/login-action@v3
|
||||
if: ${{ !github.event.pull_request.head.repo.fork }}
|
||||
with:
|
||||
registry: ghcr.io
|
||||
@@ -348,7 +334,7 @@ jobs:
|
||||
|
||||
- name: Build and push image
|
||||
id: build
|
||||
uses: docker/build-push-action@471d1dc4e07e5cdedd4c2171150001c434f0b7a4 # v6.15.0
|
||||
uses: docker/build-push-action@v6.15.0
|
||||
with:
|
||||
context: ${{ env.context }}
|
||||
file: ${{ env.file }}
|
||||
@@ -373,7 +359,7 @@ jobs:
|
||||
touch "${{ runner.temp }}/digests/${digest#sha256:}"
|
||||
|
||||
- name: Upload digest
|
||||
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: server-digests-${{ env.PLATFORM_PAIR }}
|
||||
path: ${{ runner.temp }}/digests/*
|
||||
@@ -391,7 +377,7 @@ jobs:
|
||||
- build_and_push_server
|
||||
steps:
|
||||
- name: Download digests
|
||||
uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
path: ${{ runner.temp }}/digests
|
||||
pattern: server-digests-*
|
||||
@@ -399,26 +385,26 @@ jobs:
|
||||
|
||||
- name: Login to Docker Hub
|
||||
if: ${{ github.event_name == 'release' }}
|
||||
uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
- name: Login to GHCR
|
||||
uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.repository_owner }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@b5ca514318bd6ebac0fb2aedd5d36ec1b5c232a2 # v3
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Generate docker image tags
|
||||
id: meta
|
||||
uses: docker/metadata-action@902fa8ec7d6ecbf8d84d538b9b233a880e428804 # v5
|
||||
uses: docker/metadata-action@v5
|
||||
env:
|
||||
DOCKER_METADATA_PR_HEAD_SHA: 'true'
|
||||
DOCKER_METADATA_PR_HEAD_SHA: "true"
|
||||
with:
|
||||
flavor: |
|
||||
# Disable latest tag
|
||||
|
||||
11
.github/workflows/docs-build.yml
vendored
11
.github/workflows/docs-build.yml
vendored
@@ -3,6 +3,7 @@ on:
|
||||
push:
|
||||
branches: [main]
|
||||
pull_request:
|
||||
branches: [main]
|
||||
release:
|
||||
types: [published]
|
||||
|
||||
@@ -17,9 +18,9 @@ jobs:
|
||||
should_run: ${{ steps.found_paths.outputs.docs == 'true' || steps.should_force.outputs.should_force == 'true' }}
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
||||
uses: actions/checkout@v4
|
||||
- id: found_paths
|
||||
uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3
|
||||
uses: dorny/paths-filter@v3
|
||||
with:
|
||||
filters: |
|
||||
docs:
|
||||
@@ -41,10 +42,10 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@cdca7365b2dadb8aad0a33bc7601856ffabcc48e # v4
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: './docs/.nvmrc'
|
||||
|
||||
@@ -58,7 +59,7 @@ jobs:
|
||||
run: npm run build
|
||||
|
||||
- name: Upload build output
|
||||
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: docs-build-output
|
||||
path: docs/build/
|
||||
|
||||
42
.github/workflows/docs-deploy.yml
vendored
42
.github/workflows/docs-deploy.yml
vendored
@@ -1,7 +1,7 @@
|
||||
name: Docs deploy
|
||||
on:
|
||||
workflow_run:
|
||||
workflows: ['Docs build']
|
||||
workflows: ["Docs build"]
|
||||
types:
|
||||
- completed
|
||||
|
||||
@@ -17,7 +17,7 @@ jobs:
|
||||
run: echo 'The triggering workflow did not succeed' && exit 1
|
||||
- name: Get artifact
|
||||
id: get-artifact
|
||||
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
let allArtifacts = await github.rest.actions.listWorkflowRunArtifacts({
|
||||
@@ -35,7 +35,7 @@ jobs:
|
||||
return { found: true, id: matchArtifact.id };
|
||||
- name: Determine deploy parameters
|
||||
id: parameters
|
||||
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const eventType = context.payload.workflow_run.event;
|
||||
@@ -98,11 +98,11 @@ jobs:
|
||||
if: ${{ fromJson(needs.checks.outputs.artifact).found && fromJson(needs.checks.outputs.parameters).shouldDeploy }}
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Load parameters
|
||||
id: parameters
|
||||
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const json = `${{ needs.checks.outputs.parameters }}`;
|
||||
@@ -115,7 +115,7 @@ jobs:
|
||||
echo "Starting docs deployment for ${{ steps.parameters.outputs.event }} ${{ steps.parameters.outputs.name }}"
|
||||
|
||||
- name: Download artifact
|
||||
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
let artifact = ${{ needs.checks.outputs.artifact }};
|
||||
@@ -138,12 +138,12 @@ jobs:
|
||||
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
|
||||
CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
|
||||
TF_STATE_POSTGRES_CONN_STR: ${{ secrets.TF_STATE_POSTGRES_CONN_STR }}
|
||||
uses: gruntwork-io/terragrunt-action@9559e51d05873b0ea467c42bbabcb5c067642ccc # v2
|
||||
uses: gruntwork-io/terragrunt-action@v2
|
||||
with:
|
||||
tg_version: '0.58.12'
|
||||
tofu_version: '1.7.1'
|
||||
tg_dir: 'deployment/modules/cloudflare/docs'
|
||||
tg_command: 'apply'
|
||||
tg_version: "0.58.12"
|
||||
tofu_version: "1.7.1"
|
||||
tg_dir: "deployment/modules/cloudflare/docs"
|
||||
tg_command: "apply"
|
||||
|
||||
- name: Deploy Docs Subdomain Output
|
||||
id: docs-output
|
||||
@@ -153,12 +153,12 @@ jobs:
|
||||
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
|
||||
CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
|
||||
TF_STATE_POSTGRES_CONN_STR: ${{ secrets.TF_STATE_POSTGRES_CONN_STR }}
|
||||
uses: gruntwork-io/terragrunt-action@9559e51d05873b0ea467c42bbabcb5c067642ccc # v2
|
||||
uses: gruntwork-io/terragrunt-action@v2
|
||||
with:
|
||||
tg_version: '0.58.12'
|
||||
tofu_version: '1.7.1'
|
||||
tg_dir: 'deployment/modules/cloudflare/docs'
|
||||
tg_command: 'output -json'
|
||||
tg_version: "0.58.12"
|
||||
tofu_version: "1.7.1"
|
||||
tg_dir: "deployment/modules/cloudflare/docs"
|
||||
tg_command: "output -json"
|
||||
|
||||
- name: Output Cleaning
|
||||
id: clean
|
||||
@@ -167,13 +167,13 @@ jobs:
|
||||
echo "output=$TG_OUT" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Publish to Cloudflare Pages
|
||||
uses: cloudflare/pages-action@f0a1cd58cd66095dee69bfa18fa5efd1dde93bca # v1
|
||||
uses: cloudflare/pages-action@v1
|
||||
with:
|
||||
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN_PAGES_UPLOAD }}
|
||||
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
|
||||
projectName: ${{ fromJson(steps.clean.outputs.output).pages_project_name.value }}
|
||||
workingDirectory: 'docs'
|
||||
directory: 'build'
|
||||
workingDirectory: "docs"
|
||||
directory: "build"
|
||||
branch: ${{ steps.parameters.outputs.name }}
|
||||
wranglerVersion: '3'
|
||||
|
||||
@@ -184,7 +184,7 @@ jobs:
|
||||
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
|
||||
CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
|
||||
TF_STATE_POSTGRES_CONN_STR: ${{ secrets.TF_STATE_POSTGRES_CONN_STR }}
|
||||
uses: gruntwork-io/terragrunt-action@9559e51d05873b0ea467c42bbabcb5c067642ccc # v2
|
||||
uses: gruntwork-io/terragrunt-action@v2
|
||||
with:
|
||||
tg_version: '0.58.12'
|
||||
tofu_version: '1.7.1'
|
||||
@@ -192,7 +192,7 @@ jobs:
|
||||
tg_command: 'apply'
|
||||
|
||||
- name: Comment
|
||||
uses: actions-cool/maintain-one-comment@4b2dbf086015f892dcb5e8c1106f5fccd6c1476b # v3
|
||||
uses: actions-cool/maintain-one-comment@v3
|
||||
if: ${{ steps.parameters.outputs.event == 'pr' }}
|
||||
with:
|
||||
number: ${{ fromJson(needs.checks.outputs.parameters).pr_number }}
|
||||
|
||||
18
.github/workflows/docs-destroy.yml
vendored
18
.github/workflows/docs-destroy.yml
vendored
@@ -9,24 +9,24 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Destroy Docs Subdomain
|
||||
env:
|
||||
TF_VAR_prefix_name: 'pr-${{ github.event.number }}'
|
||||
TF_VAR_prefix_event_type: 'pr'
|
||||
TF_VAR_prefix_name: "pr-${{ github.event.number }}"
|
||||
TF_VAR_prefix_event_type: "pr"
|
||||
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
|
||||
CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
|
||||
TF_STATE_POSTGRES_CONN_STR: ${{ secrets.TF_STATE_POSTGRES_CONN_STR }}
|
||||
uses: gruntwork-io/terragrunt-action@9559e51d05873b0ea467c42bbabcb5c067642ccc # v2
|
||||
uses: gruntwork-io/terragrunt-action@v2
|
||||
with:
|
||||
tg_version: '0.58.12'
|
||||
tofu_version: '1.7.1'
|
||||
tg_dir: 'deployment/modules/cloudflare/docs'
|
||||
tg_command: 'destroy -refresh=false'
|
||||
tg_version: "0.58.12"
|
||||
tofu_version: "1.7.1"
|
||||
tg_dir: "deployment/modules/cloudflare/docs"
|
||||
tg_command: "destroy -refresh=false"
|
||||
|
||||
- name: Comment
|
||||
uses: actions-cool/maintain-one-comment@4b2dbf086015f892dcb5e8c1106f5fccd6c1476b # v3
|
||||
uses: actions-cool/maintain-one-comment@v3
|
||||
with:
|
||||
number: ${{ github.event.number }}
|
||||
delete: true
|
||||
|
||||
11
.github/workflows/fix-format.yml
vendored
11
.github/workflows/fix-format.yml
vendored
@@ -13,19 +13,19 @@ jobs:
|
||||
steps:
|
||||
- name: Generate a token
|
||||
id: generate-token
|
||||
uses: actions/create-github-app-token@af35edadc00be37caa72ed9f3e6d5f7801bfdf09 # v1
|
||||
uses: actions/create-github-app-token@v1
|
||||
with:
|
||||
app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }}
|
||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||
|
||||
- name: 'Checkout'
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.ref }}
|
||||
token: ${{ steps.generate-token.outputs.token }}
|
||||
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@cdca7365b2dadb8aad0a33bc7601856ffabcc48e # v4
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: './server/.nvmrc'
|
||||
|
||||
@@ -33,13 +33,13 @@ jobs:
|
||||
run: make install-all && make format-all
|
||||
|
||||
- name: Commit and push
|
||||
uses: EndBug/add-and-commit@a94899bca583c204427a224a7af87c02f9b325d5 # v9
|
||||
uses: EndBug/add-and-commit@v9
|
||||
with:
|
||||
default_author: github_actions
|
||||
message: 'chore: fix formatting'
|
||||
|
||||
- name: Remove label
|
||||
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7
|
||||
uses: actions/github-script@v7
|
||||
if: always()
|
||||
with:
|
||||
script: |
|
||||
@@ -49,3 +49,4 @@ jobs:
|
||||
repo: context.repo.repo,
|
||||
name: 'fix:formatting'
|
||||
})
|
||||
|
||||
|
||||
6
.github/workflows/pr-label-validation.yml
vendored
6
.github/workflows/pr-label-validation.yml
vendored
@@ -12,11 +12,11 @@ jobs:
|
||||
pull-requests: write
|
||||
steps:
|
||||
- name: Require PR to have a changelog label
|
||||
uses: mheap/github-action-required-labels@388fd6af37b34cdfe5a23b37060e763217e58b03 # v5
|
||||
uses: mheap/github-action-required-labels@v5
|
||||
with:
|
||||
mode: exactly
|
||||
count: 1
|
||||
use_regex: true
|
||||
labels: 'changelog:.*'
|
||||
labels: "changelog:.*"
|
||||
add_comment: true
|
||||
message: 'Label error. Requires {{errorString}} {{count}} of: {{ provided }}. Found: {{ applied }}. A maintainer will add the required label.'
|
||||
message: "Label error. Requires {{errorString}} {{count}} of: {{ provided }}. Found: {{ applied }}. A maintainer will add the required label."
|
||||
|
||||
6
.github/workflows/pr-labeler.yml
vendored
6
.github/workflows/pr-labeler.yml
vendored
@@ -1,6 +1,6 @@
|
||||
name: 'Pull Request Labeler'
|
||||
name: "Pull Request Labeler"
|
||||
on:
|
||||
- pull_request_target
|
||||
- pull_request_target
|
||||
|
||||
jobs:
|
||||
labeler:
|
||||
@@ -9,4 +9,4 @@ jobs:
|
||||
pull-requests: write
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/labeler@8558fd74291d67161a8a78ce36a881fa63b766a9 # v5
|
||||
- uses: actions/labeler@v5
|
||||
|
||||
@@ -9,7 +9,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: PR Conventional Commit Validation
|
||||
uses: ytanikin/PRConventionalCommits@b628c5a234cc32513014b7bfdd1e47b532124d98 # 1.3.0
|
||||
uses: ytanikin/PRConventionalCommits@1.3.0
|
||||
with:
|
||||
task_types: '["feat","fix","docs","test","ci","refactor","perf","chore","revert"]'
|
||||
add_label: 'false'
|
||||
|
||||
16
.github/workflows/prepare-release.yml
vendored
16
.github/workflows/prepare-release.yml
vendored
@@ -31,25 +31,25 @@ jobs:
|
||||
steps:
|
||||
- name: Generate a token
|
||||
id: generate-token
|
||||
uses: actions/create-github-app-token@af35edadc00be37caa72ed9f3e6d5f7801bfdf09 # v1
|
||||
uses: actions/create-github-app-token@v1
|
||||
with:
|
||||
app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }}
|
||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
token: ${{ steps.generate-token.outputs.token }}
|
||||
|
||||
- name: Install uv
|
||||
uses: astral-sh/setup-uv@22695119d769bdb6f7032ad67b9bca0ef8c4a174 # v5
|
||||
uses: astral-sh/setup-uv@v5
|
||||
|
||||
- name: Bump version
|
||||
run: misc/release/pump-version.sh -s "${{ inputs.serverBump }}" -m "${{ inputs.mobileBump }}"
|
||||
|
||||
- name: Commit and tag
|
||||
id: push-tag
|
||||
uses: EndBug/add-and-commit@a94899bca583c204427a224a7af87c02f9b325d5 # v9
|
||||
uses: EndBug/add-and-commit@v9
|
||||
with:
|
||||
default_author: github_actions
|
||||
message: 'chore: version ${{ env.IMMICH_VERSION }}'
|
||||
@@ -70,23 +70,23 @@ jobs:
|
||||
steps:
|
||||
- name: Generate a token
|
||||
id: generate-token
|
||||
uses: actions/create-github-app-token@af35edadc00be37caa72ed9f3e6d5f7801bfdf09 # v1
|
||||
uses: actions/create-github-app-token@v1
|
||||
with:
|
||||
app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }}
|
||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
token: ${{ steps.generate-token.outputs.token }}
|
||||
|
||||
- name: Download APK
|
||||
uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: release-apk-signed
|
||||
|
||||
- name: Create draft release
|
||||
uses: softprops/action-gh-release@c95fe1489396fe8a9eb87c0abf8aa5b2ef267fda # v2
|
||||
uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
draft: true
|
||||
tag_name: ${{ env.IMMICH_VERSION }}
|
||||
|
||||
8
.github/workflows/preview-label.yaml
vendored
8
.github/workflows/preview-label.yaml
vendored
@@ -11,10 +11,10 @@ jobs:
|
||||
permissions:
|
||||
pull-requests: write
|
||||
steps:
|
||||
- uses: mshick/add-pr-comment@b8f338c590a895d50bcbfa6c5859251edc8952fc # v2
|
||||
- uses: mshick/add-pr-comment@v2
|
||||
with:
|
||||
message-id: 'preview-status'
|
||||
message: 'Deploying preview environment to https://pr-${{ github.event.pull_request.number }}.preview.internal.immich.cloud/'
|
||||
message-id: "preview-status"
|
||||
message: "Deploying preview environment to https://pr-${{ github.event.pull_request.number }}.preview.internal.immich.cloud/"
|
||||
|
||||
remove-label:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -22,7 +22,7 @@ jobs:
|
||||
permissions:
|
||||
pull-requests: write
|
||||
steps:
|
||||
- uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7
|
||||
- uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
github.rest.issues.removeLabel({
|
||||
|
||||
4
.github/workflows/sdk.yml
vendored
4
.github/workflows/sdk.yml
vendored
@@ -15,9 +15,9 @@ jobs:
|
||||
run:
|
||||
working-directory: ./open-api/typescript-sdk
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
||||
- uses: actions/checkout@v4
|
||||
# Setup .npmrc file to publish to npm
|
||||
- uses: actions/setup-node@cdca7365b2dadb8aad0a33bc7601856ffabcc48e # v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: './open-api/typescript-sdk/.nvmrc'
|
||||
registry-url: 'https://registry.npmjs.org'
|
||||
|
||||
10
.github/workflows/static_analysis.yml
vendored
10
.github/workflows/static_analysis.yml
vendored
@@ -16,9 +16,9 @@ jobs:
|
||||
should_run: ${{ steps.found_paths.outputs.mobile == 'true' || steps.should_force.outputs.should_force == 'true' }}
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
||||
uses: actions/checkout@v4
|
||||
- id: found_paths
|
||||
uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3
|
||||
uses: dorny/paths-filter@v3
|
||||
with:
|
||||
filters: |
|
||||
mobile:
|
||||
@@ -38,10 +38,10 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Flutter SDK
|
||||
uses: subosito/flutter-action@e938fdf56512cc96ef2f93601a5a40bde3801046 # v2
|
||||
uses: subosito/flutter-action@v2
|
||||
with:
|
||||
channel: 'stable'
|
||||
flutter-version-file: ./mobile/pubspec.yaml
|
||||
@@ -55,7 +55,7 @@ jobs:
|
||||
working-directory: ./mobile
|
||||
|
||||
- name: Find file changes
|
||||
uses: tj-actions/verify-changed-files@a1c6acee9df209257a246f2cc6ae8cb6581c1edf # v20
|
||||
uses: tj-actions/verify-changed-files@v20
|
||||
id: verify-changed-files
|
||||
with:
|
||||
files: |
|
||||
|
||||
90
.github/workflows/test.yml
vendored
90
.github/workflows/test.yml
vendored
@@ -21,12 +21,11 @@ jobs:
|
||||
should_run_ml: ${{ steps.found_paths.outputs.machine-learning == 'true' || steps.should_force.outputs.should_force == 'true' }}
|
||||
should_run_e2e_web: ${{ steps.found_paths.outputs.e2e == 'true' || steps.found_paths.outputs.web == 'true' || steps.should_force.outputs.should_force == 'true' }}
|
||||
should_run_e2e_server_cli: ${{ steps.found_paths.outputs.e2e == 'true' || steps.found_paths.outputs.server == 'true' || steps.found_paths.outputs.cli == 'true' || steps.should_force.outputs.should_force == 'true' }}
|
||||
should_run_.github: ${{ steps.found_paths.outputs['.github'] == 'true' || steps.should_force.outputs.should_force == 'true' }} # redundant to have should_force but if someone changes the trigger then this won't have to be changed
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
||||
uses: actions/checkout@v4
|
||||
- id: found_paths
|
||||
uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3
|
||||
uses: dorny/paths-filter@v3
|
||||
with:
|
||||
filters: |
|
||||
web:
|
||||
@@ -46,8 +45,6 @@ jobs:
|
||||
- 'machine-learning/**'
|
||||
workflow:
|
||||
- '.github/workflows/test.yml'
|
||||
.github:
|
||||
- '.github/**'
|
||||
|
||||
- name: Check if we should force jobs to run
|
||||
id: should_force
|
||||
@@ -64,10 +61,10 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@cdca7365b2dadb8aad0a33bc7601856ffabcc48e # v4
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: './server/.nvmrc'
|
||||
|
||||
@@ -101,10 +98,10 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@cdca7365b2dadb8aad0a33bc7601856ffabcc48e # v4
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: './cli/.nvmrc'
|
||||
|
||||
@@ -142,10 +139,10 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@cdca7365b2dadb8aad0a33bc7601856ffabcc48e # v4
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: './cli/.nvmrc'
|
||||
|
||||
@@ -176,10 +173,10 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@cdca7365b2dadb8aad0a33bc7601856ffabcc48e # v4
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: './web/.nvmrc'
|
||||
|
||||
@@ -221,10 +218,10 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@cdca7365b2dadb8aad0a33bc7601856ffabcc48e # v4
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: './e2e/.nvmrc'
|
||||
|
||||
@@ -260,10 +257,10 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@cdca7365b2dadb8aad0a33bc7601856ffabcc48e # v4
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: './server/.nvmrc'
|
||||
|
||||
@@ -285,12 +282,12 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: 'recursive'
|
||||
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@cdca7365b2dadb8aad0a33bc7601856ffabcc48e # v4
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: './e2e/.nvmrc'
|
||||
|
||||
@@ -327,12 +324,12 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: 'recursive'
|
||||
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@cdca7365b2dadb8aad0a33bc7601856ffabcc48e # v4
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: './e2e/.nvmrc'
|
||||
|
||||
@@ -363,9 +360,9 @@ jobs:
|
||||
if: ${{ needs.pre-job.outputs.should_run_mobile == 'true' }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
||||
- uses: actions/checkout@v4
|
||||
- name: Setup Flutter SDK
|
||||
uses: subosito/flutter-action@e938fdf56512cc96ef2f93601a5a40bde3801046 # v2
|
||||
uses: subosito/flutter-action@v2
|
||||
with:
|
||||
channel: 'stable'
|
||||
flutter-version-file: ./mobile/pubspec.yaml
|
||||
@@ -382,10 +379,10 @@ jobs:
|
||||
run:
|
||||
working-directory: ./machine-learning
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install uv
|
||||
uses: astral-sh/setup-uv@22695119d769bdb6f7032ad67b9bca0ef8c4a174 # v5
|
||||
- uses: actions/setup-python@8d9ed9ac5c53483de85588cdf95a591a75ab9f55 # v5
|
||||
uses: astral-sh/setup-uv@v5
|
||||
- uses: actions/setup-python@v5
|
||||
# TODO: add caching when supported (https://github.com/actions/setup-python/pull/818)
|
||||
# with:
|
||||
# python-version: 3.11
|
||||
@@ -406,36 +403,11 @@ jobs:
|
||||
run: |
|
||||
uv run pytest app --cov=app --cov-report term-missing
|
||||
|
||||
github-files-formatting:
|
||||
name: .github Files Formatting
|
||||
needs: pre-job
|
||||
if: ${{ needs.pre-job.outputs['should_run_.github'] == 'true' }}
|
||||
runs-on: ubuntu-latest
|
||||
defaults:
|
||||
run:
|
||||
working-directory: ./.github
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
||||
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@cdca7365b2dadb8aad0a33bc7601856ffabcc48e # v4
|
||||
with:
|
||||
node-version-file: './.github/.nvmrc'
|
||||
|
||||
- name: Run npm install
|
||||
run: npm ci
|
||||
|
||||
- name: Run formatter
|
||||
run: npm run format
|
||||
if: ${{ !cancelled() }}
|
||||
|
||||
shellcheck:
|
||||
name: ShellCheck
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
||||
- uses: actions/checkout@v4
|
||||
- name: Run ShellCheck
|
||||
uses: ludeeus/action-shellcheck@master
|
||||
with:
|
||||
@@ -449,10 +421,10 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@cdca7365b2dadb8aad0a33bc7601856ffabcc48e # v4
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: './server/.nvmrc'
|
||||
|
||||
@@ -466,7 +438,7 @@ jobs:
|
||||
run: make open-api
|
||||
|
||||
- name: Find file changes
|
||||
uses: tj-actions/verify-changed-files@a1c6acee9df209257a246f2cc6ae8cb6581c1edf # v20
|
||||
uses: tj-actions/verify-changed-files@v20
|
||||
id: verify-changed-files
|
||||
with:
|
||||
files: |
|
||||
@@ -504,10 +476,10 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@cdca7365b2dadb8aad0a33bc7601856ffabcc48e # v4
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: './server/.nvmrc'
|
||||
|
||||
@@ -528,7 +500,7 @@ jobs:
|
||||
run: npm run typeorm:migrations:generate ./src/migrations/TestMigration
|
||||
|
||||
- name: Find file changes
|
||||
uses: tj-actions/verify-changed-files@a1c6acee9df209257a246f2cc6ae8cb6581c1edf # v20
|
||||
uses: tj-actions/verify-changed-files@v20
|
||||
id: verify-changed-files
|
||||
with:
|
||||
files: |
|
||||
@@ -547,7 +519,7 @@ jobs:
|
||||
DB_URL: postgres://postgres:postgres@localhost:5432/immich
|
||||
|
||||
- name: Find file changes
|
||||
uses: tj-actions/verify-changed-files@a1c6acee9df209257a246f2cc6ae8cb6581c1edf # v20
|
||||
uses: tj-actions/verify-changed-files@v20
|
||||
id: verify-changed-sql-files
|
||||
with:
|
||||
files: |
|
||||
|
||||
16
.github/workflows/weblate-lock.yml
vendored
16
.github/workflows/weblate-lock.yml
vendored
@@ -11,22 +11,22 @@ jobs:
|
||||
should_run: ${{ steps.found_paths.outputs.i18n == 'true' && github.head_ref != 'chore/translations'}}
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
||||
uses: actions/checkout@v4
|
||||
- id: found_paths
|
||||
uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3
|
||||
uses: dorny/paths-filter@v3
|
||||
with:
|
||||
filters: |
|
||||
i18n:
|
||||
- 'i18n/!(en)**\.json'
|
||||
- name: Debug
|
||||
run: |
|
||||
echo "Should run: ${{ steps.found_paths.outputs.i18n == 'true' && github.head_ref != 'chore/translations'}}"
|
||||
echo "Found i18n paths: ${{ steps.found_paths.outputs.i18n }}"
|
||||
echo "Head ref: ${{ github.head_ref }}"
|
||||
echo "Should run: ${{ steps.found_paths.outputs.i18n == 'true' && github.head_ref != 'chore/translations'}}"
|
||||
echo "Found i18n paths: ${{ steps.found_paths.outputs.i18n }}"
|
||||
echo "Head ref: ${{ github.head_ref }}"
|
||||
|
||||
enforce-lock:
|
||||
name: Check Weblate Lock
|
||||
needs: [pre-job]
|
||||
needs: [ pre-job ]
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ needs.pre-job.outputs.should_run == 'true' }}
|
||||
steps:
|
||||
@@ -36,7 +36,7 @@ jobs:
|
||||
exit 1
|
||||
fi
|
||||
- name: Find Pull Request
|
||||
uses: juliangruber/find-pull-request-action@48b6133aa6c826f267ebd33aa2d29470f9d9e7d0 # v1
|
||||
uses: juliangruber/find-pull-request-action@v1
|
||||
id: find-pr
|
||||
with:
|
||||
branch: chore/translations
|
||||
@@ -45,7 +45,7 @@ jobs:
|
||||
run: exit 1
|
||||
success-check-lock:
|
||||
name: Weblate Lock Check Success
|
||||
needs: [enforce-lock]
|
||||
needs: [ enforce-lock ]
|
||||
runs-on: ubuntu-latest
|
||||
if: always()
|
||||
steps:
|
||||
|
||||
10
Makefile
10
Makefile
@@ -39,7 +39,7 @@ attach-server:
|
||||
renovate:
|
||||
LOG_LEVEL=debug npx renovate --platform=local --repository-cache=reset
|
||||
|
||||
MODULES = e2e server web cli sdk docs .github
|
||||
MODULES = e2e server web cli sdk docs
|
||||
|
||||
audit-%:
|
||||
npm --prefix $(subst sdk,open-api/typescript-sdk,$*) audit fix
|
||||
@@ -77,14 +77,14 @@ test-medium:
|
||||
test-medium-dev:
|
||||
docker exec -it immich_server /bin/sh -c "npm run test:medium"
|
||||
|
||||
build-all: $(foreach M,$(filter-out e2e .github,$(MODULES)),build-$M) ;
|
||||
build-all: $(foreach M,$(filter-out e2e,$(MODULES)),build-$M) ;
|
||||
install-all: $(foreach M,$(MODULES),install-$M) ;
|
||||
check-all: $(foreach M,$(filter-out sdk cli docs .github,$(MODULES)),check-$M) ;
|
||||
lint-all: $(foreach M,$(filter-out sdk docs .github,$(MODULES)),lint-$M) ;
|
||||
check-all: $(foreach M,$(filter-out sdk cli docs,$(MODULES)),check-$M) ;
|
||||
lint-all: $(foreach M,$(filter-out sdk docs,$(MODULES)),lint-$M) ;
|
||||
format-all: $(foreach M,$(filter-out sdk,$(MODULES)),format-$M) ;
|
||||
audit-all: $(foreach M,$(MODULES),audit-$M) ;
|
||||
hygiene-all: lint-all format-all check-all sql audit-all;
|
||||
test-all: $(foreach M,$(filter-out sdk docs .github,$(MODULES)),test-$M) ;
|
||||
test-all: $(foreach M,$(filter-out sdk docs,$(MODULES)),test-$M) ;
|
||||
|
||||
clean:
|
||||
find . -name "node_modules" -type d -prune -exec rm -rf '{}' +
|
||||
|
||||
133
cli/package-lock.json
generated
133
cli/package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "@immich/cli",
|
||||
"version": "2.2.55",
|
||||
"version": "2.2.53",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@immich/cli",
|
||||
"version": "2.2.55",
|
||||
"version": "2.2.53",
|
||||
"license": "GNU Affero General Public License version 3",
|
||||
"dependencies": {
|
||||
"chokidar": "^4.0.3",
|
||||
@@ -27,7 +27,7 @@
|
||||
"@types/lodash-es": "^4.17.12",
|
||||
"@types/micromatch": "^4.0.9",
|
||||
"@types/mock-fs": "^4.13.1",
|
||||
"@types/node": "^22.13.10",
|
||||
"@types/node": "^22.13.9",
|
||||
"@typescript-eslint/eslint-plugin": "^8.15.0",
|
||||
"@typescript-eslint/parser": "^8.15.0",
|
||||
"@vitest/coverage-v8": "^3.0.0",
|
||||
@@ -55,14 +55,14 @@
|
||||
},
|
||||
"../open-api/typescript-sdk": {
|
||||
"name": "@immich/sdk",
|
||||
"version": "1.130.1",
|
||||
"version": "1.129.0",
|
||||
"dev": true,
|
||||
"license": "GNU Affero General Public License version 3",
|
||||
"dependencies": {
|
||||
"@oazapfts/runtime": "^1.0.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^22.13.10",
|
||||
"@types/node": "^22.13.9",
|
||||
"typescript": "^5.3.3"
|
||||
}
|
||||
},
|
||||
@@ -809,16 +809,6 @@
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@eslint/config-helpers": {
|
||||
"version": "0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.1.0.tgz",
|
||||
"integrity": "sha512-kLrdPDJE1ckPo94kmPPf9Hfd0DU0Jw6oKYrhe+pwSC0iTUInmTa+w6fw8sGgcfkFJGNdWOUeOaDM4quW4a7OkA==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"engines": {
|
||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@eslint/core": {
|
||||
"version": "0.12.0",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.12.0.tgz",
|
||||
@@ -894,9 +884,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@eslint/js": {
|
||||
"version": "9.22.0",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.22.0.tgz",
|
||||
"integrity": "sha512-vLFajx9o8d1/oL2ZkpMYbkLv8nDB6yaIwFNt7nI4+I80U/z03SxmfOMsLbvWr3p7C+Wnoh//aOu2pQW8cS0HCQ==",
|
||||
"version": "9.21.0",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.21.0.tgz",
|
||||
"integrity": "sha512-BqStZ3HX8Yz6LvsF5ByXYrtigrV5AXADWLAGc7PH/1SxOb7/FIYYMszZZWiUou/GB9P2lXWk2SV4d+Z8h0nknw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
@@ -1528,17 +1518,17 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@typescript-eslint/eslint-plugin": {
|
||||
"version": "8.26.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.26.1.tgz",
|
||||
"integrity": "sha512-2X3mwqsj9Bd3Ciz508ZUtoQQYpOhU/kWoUqIf49H8Z0+Vbh6UF/y0OEYp0Q0axOGzaBGs7QxRwq0knSQ8khQNA==",
|
||||
"version": "8.26.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.26.0.tgz",
|
||||
"integrity": "sha512-cLr1J6pe56zjKYajK6SSSre6nl1Gj6xDp1TY0trpgPzjVbgDwd09v2Ws37LABxzkicmUjhEeg/fAUjPJJB1v5Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@eslint-community/regexpp": "^4.10.0",
|
||||
"@typescript-eslint/scope-manager": "8.26.1",
|
||||
"@typescript-eslint/type-utils": "8.26.1",
|
||||
"@typescript-eslint/utils": "8.26.1",
|
||||
"@typescript-eslint/visitor-keys": "8.26.1",
|
||||
"@typescript-eslint/scope-manager": "8.26.0",
|
||||
"@typescript-eslint/type-utils": "8.26.0",
|
||||
"@typescript-eslint/utils": "8.26.0",
|
||||
"@typescript-eslint/visitor-keys": "8.26.0",
|
||||
"graphemer": "^1.4.0",
|
||||
"ignore": "^5.3.1",
|
||||
"natural-compare": "^1.4.0",
|
||||
@@ -1558,16 +1548,16 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/parser": {
|
||||
"version": "8.26.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.26.1.tgz",
|
||||
"integrity": "sha512-w6HZUV4NWxqd8BdeFf81t07d7/YV9s7TCWrQQbG5uhuvGUAW+fq1usZ1Hmz9UPNLniFnD8GLSsDpjP0hm1S4lQ==",
|
||||
"version": "8.26.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.26.0.tgz",
|
||||
"integrity": "sha512-mNtXP9LTVBy14ZF3o7JG69gRPBK/2QWtQd0j0oH26HcY/foyJJau6pNUez7QrM5UHnSvwlQcJXKsk0I99B9pOA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@typescript-eslint/scope-manager": "8.26.1",
|
||||
"@typescript-eslint/types": "8.26.1",
|
||||
"@typescript-eslint/typescript-estree": "8.26.1",
|
||||
"@typescript-eslint/visitor-keys": "8.26.1",
|
||||
"@typescript-eslint/scope-manager": "8.26.0",
|
||||
"@typescript-eslint/types": "8.26.0",
|
||||
"@typescript-eslint/typescript-estree": "8.26.0",
|
||||
"@typescript-eslint/visitor-keys": "8.26.0",
|
||||
"debug": "^4.3.4"
|
||||
},
|
||||
"engines": {
|
||||
@@ -1583,14 +1573,14 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/scope-manager": {
|
||||
"version": "8.26.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.26.1.tgz",
|
||||
"integrity": "sha512-6EIvbE5cNER8sqBu6V7+KeMZIC1664d2Yjt+B9EWUXrsyWpxx4lEZrmvxgSKRC6gX+efDL/UY9OpPZ267io3mg==",
|
||||
"version": "8.26.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.26.0.tgz",
|
||||
"integrity": "sha512-E0ntLvsfPqnPwng8b8y4OGuzh/iIOm2z8U3S9zic2TeMLW61u5IH2Q1wu0oSTkfrSzwbDJIB/Lm8O3//8BWMPA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@typescript-eslint/types": "8.26.1",
|
||||
"@typescript-eslint/visitor-keys": "8.26.1"
|
||||
"@typescript-eslint/types": "8.26.0",
|
||||
"@typescript-eslint/visitor-keys": "8.26.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||
@@ -1601,14 +1591,14 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/type-utils": {
|
||||
"version": "8.26.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.26.1.tgz",
|
||||
"integrity": "sha512-Kcj/TagJLwoY/5w9JGEFV0dclQdyqw9+VMndxOJKtoFSjfZhLXhYjzsQEeyza03rwHx2vFEGvrJWJBXKleRvZg==",
|
||||
"version": "8.26.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.26.0.tgz",
|
||||
"integrity": "sha512-ruk0RNChLKz3zKGn2LwXuVoeBcUMh+jaqzN461uMMdxy5H9epZqIBtYj7UiPXRuOpaALXGbmRuZQhmwHhaS04Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@typescript-eslint/typescript-estree": "8.26.1",
|
||||
"@typescript-eslint/utils": "8.26.1",
|
||||
"@typescript-eslint/typescript-estree": "8.26.0",
|
||||
"@typescript-eslint/utils": "8.26.0",
|
||||
"debug": "^4.3.4",
|
||||
"ts-api-utils": "^2.0.1"
|
||||
},
|
||||
@@ -1625,9 +1615,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/types": {
|
||||
"version": "8.26.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.26.1.tgz",
|
||||
"integrity": "sha512-n4THUQW27VmQMx+3P+B0Yptl7ydfceUj4ON/AQILAASwgYdZ/2dhfymRMh5egRUrvK5lSmaOm77Ry+lmXPOgBQ==",
|
||||
"version": "8.26.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.26.0.tgz",
|
||||
"integrity": "sha512-89B1eP3tnpr9A8L6PZlSjBvnJhWXtYfZhECqlBl1D9Lme9mHO6iWlsprBtVenQvY1HMhax1mWOjhtL3fh/u+pA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
@@ -1639,14 +1629,14 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/typescript-estree": {
|
||||
"version": "8.26.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.26.1.tgz",
|
||||
"integrity": "sha512-yUwPpUHDgdrv1QJ7YQal3cMVBGWfnuCdKbXw1yyjArax3353rEJP1ZA+4F8nOlQ3RfS2hUN/wze3nlY+ZOhvoA==",
|
||||
"version": "8.26.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.26.0.tgz",
|
||||
"integrity": "sha512-tiJ1Hvy/V/oMVRTbEOIeemA2XoylimlDQ03CgPPNaHYZbpsc78Hmngnt+WXZfJX1pjQ711V7g0H7cSJThGYfPQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@typescript-eslint/types": "8.26.1",
|
||||
"@typescript-eslint/visitor-keys": "8.26.1",
|
||||
"@typescript-eslint/types": "8.26.0",
|
||||
"@typescript-eslint/visitor-keys": "8.26.0",
|
||||
"debug": "^4.3.4",
|
||||
"fast-glob": "^3.3.2",
|
||||
"is-glob": "^4.0.3",
|
||||
@@ -1666,16 +1656,16 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/utils": {
|
||||
"version": "8.26.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.26.1.tgz",
|
||||
"integrity": "sha512-V4Urxa/XtSUroUrnI7q6yUTD3hDtfJ2jzVfeT3VK0ciizfK2q/zGC0iDh1lFMUZR8cImRrep6/q0xd/1ZGPQpg==",
|
||||
"version": "8.26.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.26.0.tgz",
|
||||
"integrity": "sha512-2L2tU3FVwhvU14LndnQCA2frYC8JnPDVKyQtWFPf8IYFMt/ykEN1bPolNhNbCVgOmdzTlWdusCTKA/9nKrf8Ig==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@eslint-community/eslint-utils": "^4.4.0",
|
||||
"@typescript-eslint/scope-manager": "8.26.1",
|
||||
"@typescript-eslint/types": "8.26.1",
|
||||
"@typescript-eslint/typescript-estree": "8.26.1"
|
||||
"@typescript-eslint/scope-manager": "8.26.0",
|
||||
"@typescript-eslint/types": "8.26.0",
|
||||
"@typescript-eslint/typescript-estree": "8.26.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||
@@ -1690,13 +1680,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/visitor-keys": {
|
||||
"version": "8.26.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.26.1.tgz",
|
||||
"integrity": "sha512-AjOC3zfnxd6S4Eiy3jwktJPclqhFHNyd8L6Gycf9WUPoKZpgM5PjkxY1X7uSy61xVpiJDhhk7XT2NVsN3ALTWg==",
|
||||
"version": "8.26.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.26.0.tgz",
|
||||
"integrity": "sha512-2z8JQJWAzPdDd51dRQ/oqIJxe99/hoLIqmf8RMCAJQtYDc535W/Jt2+RTP4bP0aKeBG1F65yjIZuczOXCmbWwg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@typescript-eslint/types": "8.26.1",
|
||||
"@typescript-eslint/types": "8.26.0",
|
||||
"eslint-visitor-keys": "^4.2.0"
|
||||
},
|
||||
"engines": {
|
||||
@@ -2379,19 +2369,18 @@
|
||||
}
|
||||
},
|
||||
"node_modules/eslint": {
|
||||
"version": "9.22.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint/-/eslint-9.22.0.tgz",
|
||||
"integrity": "sha512-9V/QURhsRN40xuHXWjV64yvrzMjcz7ZyNoF2jJFmy9j/SLk0u1OLSZgXi28MrXjymnjEGSR80WCdab3RGMDveQ==",
|
||||
"version": "9.21.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint/-/eslint-9.21.0.tgz",
|
||||
"integrity": "sha512-KjeihdFqTPhOMXTt7StsDxriV4n66ueuF/jfPNC3j/lduHwr/ijDwJMsF+wyMJethgiKi5wniIE243vi07d3pg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@eslint-community/eslint-utils": "^4.2.0",
|
||||
"@eslint-community/regexpp": "^4.12.1",
|
||||
"@eslint/config-array": "^0.19.2",
|
||||
"@eslint/config-helpers": "^0.1.0",
|
||||
"@eslint/core": "^0.12.0",
|
||||
"@eslint/eslintrc": "^3.3.0",
|
||||
"@eslint/js": "9.22.0",
|
||||
"@eslint/js": "9.21.0",
|
||||
"@eslint/plugin-kit": "^0.2.7",
|
||||
"@humanfs/node": "^0.16.6",
|
||||
"@humanwhocodes/module-importer": "^1.0.1",
|
||||
@@ -2403,7 +2392,7 @@
|
||||
"cross-spawn": "^7.0.6",
|
||||
"debug": "^4.3.2",
|
||||
"escape-string-regexp": "^4.0.0",
|
||||
"eslint-scope": "^8.3.0",
|
||||
"eslint-scope": "^8.2.0",
|
||||
"eslint-visitor-keys": "^4.2.0",
|
||||
"espree": "^10.3.0",
|
||||
"esquery": "^1.5.0",
|
||||
@@ -2531,9 +2520,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-scope": {
|
||||
"version": "8.3.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.3.0.tgz",
|
||||
"integrity": "sha512-pUNxi75F8MJ/GdeKtVLSbYg4ZI34J6C0C7sbL4YOp2exGwen7ZsuBqKzUhXd0qMQ362yET3z+uPwKeg/0C2XCQ==",
|
||||
"version": "8.2.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.2.0.tgz",
|
||||
"integrity": "sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A==",
|
||||
"dev": true,
|
||||
"license": "BSD-2-Clause",
|
||||
"dependencies": {
|
||||
@@ -4360,9 +4349,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/vite": {
|
||||
"version": "6.2.3",
|
||||
"resolved": "https://registry.npmjs.org/vite/-/vite-6.2.3.tgz",
|
||||
"integrity": "sha512-IzwM54g4y9JA/xAeBPNaDXiBF8Jsgl3VBQ2YQ/wOY6fyW3xMdSoltIV3Bo59DErdqdE6RxUfv8W69DvUorE4Eg==",
|
||||
"version": "6.2.1",
|
||||
"resolved": "https://registry.npmjs.org/vite/-/vite-6.2.1.tgz",
|
||||
"integrity": "sha512-n2GnqDb6XPhlt9B8olZPrgMD/es/Nd1RdChF6CBD/fHW6pUyUTt2sQW2fPRX5GiD9XEa6+8A6A4f2vT6pSsE7Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@immich/cli",
|
||||
"version": "2.2.55",
|
||||
"version": "2.2.53",
|
||||
"description": "Command Line Interface (CLI) for Immich",
|
||||
"type": "module",
|
||||
"exports": "./dist/index.js",
|
||||
@@ -21,7 +21,7 @@
|
||||
"@types/lodash-es": "^4.17.12",
|
||||
"@types/micromatch": "^4.0.9",
|
||||
"@types/mock-fs": "^4.13.1",
|
||||
"@types/node": "^22.13.10",
|
||||
"@types/node": "^22.13.9",
|
||||
"@typescript-eslint/eslint-plugin": "^8.15.0",
|
||||
"@typescript-eslint/parser": "^8.15.0",
|
||||
"@vitest/coverage-v8": "^3.0.0",
|
||||
|
||||
@@ -95,12 +95,12 @@ services:
|
||||
image: immich-machine-learning-dev:latest
|
||||
# extends:
|
||||
# file: hwaccel.ml.yml
|
||||
# service: cpu # set to one of [armnn, cuda, rocm, openvino, openvino-wsl, rknn] for accelerated inference
|
||||
# service: cpu # set to one of [armnn, cuda, openvino, openvino-wsl] for accelerated inference
|
||||
build:
|
||||
context: ../machine-learning
|
||||
dockerfile: Dockerfile
|
||||
args:
|
||||
- DEVICE=cpu # set to one of [armnn, cuda, rocm, openvino, openvino-wsl, rknn] for accelerated inference
|
||||
- DEVICE=cpu # set to one of [armnn, cuda, openvino, openvino-wsl] for accelerated inference
|
||||
ports:
|
||||
- 3003:3003
|
||||
volumes:
|
||||
|
||||
@@ -38,12 +38,12 @@ services:
|
||||
image: immich-machine-learning:latest
|
||||
# extends:
|
||||
# file: hwaccel.ml.yml
|
||||
# service: cpu # set to one of [armnn, cuda, rocm, openvino, openvino-wsl, rknn] for accelerated inference
|
||||
# service: cpu # set to one of [armnn, cuda, openvino, openvino-wsl] for accelerated inference
|
||||
build:
|
||||
context: ../machine-learning
|
||||
dockerfile: Dockerfile
|
||||
args:
|
||||
- DEVICE=cpu # set to one of [armnn, cuda, rocm, openvino, openvino-wsl, rknn] for accelerated inference
|
||||
- DEVICE=cpu # set to one of [armnn, cuda, openvino, openvino-wsl] for accelerated inference
|
||||
ports:
|
||||
- 3003:3003
|
||||
volumes:
|
||||
@@ -77,12 +77,22 @@ services:
|
||||
- 5432:5432
|
||||
healthcheck:
|
||||
test: >-
|
||||
pg_isready --dbname="$${POSTGRES_DB}" --username="$${POSTGRES_USER}" || exit 1; Chksum="$$(psql --dbname="$${POSTGRES_DB}" --username="$${POSTGRES_USER}" --tuples-only --no-align --command='SELECT COALESCE(SUM(checksum_failures), 0) FROM pg_stat_database')"; echo "checksum failure count is $$Chksum"; [ "$$Chksum" = '0' ] || exit 1
|
||||
pg_isready --dbname="$${POSTGRES_DB}" --username="$${POSTGRES_USER}" || exit 1;
|
||||
Chksum="$$(psql --dbname="$${POSTGRES_DB}" --username="$${POSTGRES_USER}" --tuples-only --no-align
|
||||
--command='SELECT COALESCE(SUM(checksum_failures), 0) FROM pg_stat_database')";
|
||||
echo "checksum failure count is $$Chksum";
|
||||
[ "$$Chksum" = '0' ] || exit 1
|
||||
interval: 5m
|
||||
start_interval: 30s
|
||||
start_period: 5m
|
||||
command: >-
|
||||
postgres -c shared_preload_libraries=vectors.so -c 'search_path="$$user", public, vectors' -c logging_collector=on -c max_wal_size=2GB -c shared_buffers=512MB -c wal_compression=on
|
||||
postgres
|
||||
-c shared_preload_libraries=vectors.so
|
||||
-c 'search_path="$$user", public, vectors'
|
||||
-c logging_collector=on
|
||||
-c max_wal_size=2GB
|
||||
-c shared_buffers=512MB
|
||||
-c wal_compression=on
|
||||
restart: always
|
||||
|
||||
# set IMMICH_TELEMETRY_INCLUDE=all in .env to enable metrics
|
||||
@@ -90,7 +100,7 @@ services:
|
||||
container_name: immich_prometheus
|
||||
ports:
|
||||
- 9090:9090
|
||||
image: prom/prometheus@sha256:502ad90314c7485892ce696cb14a99fceab9fc27af29f4b427f41bd39701a199
|
||||
image: prom/prometheus@sha256:6927e0919a144aa7616fd0137d4816816d42f6b816de3af269ab065250859a62
|
||||
volumes:
|
||||
- ./prometheus.yml:/etc/prometheus/prometheus.yml
|
||||
- prometheus-data:/prometheus
|
||||
@@ -99,7 +109,7 @@ services:
|
||||
# add data source for http://immich-prometheus:9090 to get started
|
||||
immich-grafana:
|
||||
container_name: immich_grafana
|
||||
command: [ './run.sh', '-disable-reporting' ]
|
||||
command: ['./run.sh', '-disable-reporting']
|
||||
ports:
|
||||
- 3000:3000
|
||||
image: grafana/grafana:11.5.2-ubuntu@sha256:8b5858c447e06fd7a89006b562ba7bba7c4d5813600c7982374c41852adefaeb
|
||||
|
||||
@@ -33,12 +33,12 @@ services:
|
||||
|
||||
immich-machine-learning:
|
||||
container_name: immich_machine_learning
|
||||
# For hardware acceleration, add one of -[armnn, cuda, rocm, openvino, rknn] to the image tag.
|
||||
# For hardware acceleration, add one of -[armnn, cuda, openvino] to the image tag.
|
||||
# Example tag: ${IMMICH_VERSION:-release}-cuda
|
||||
image: ghcr.io/immich-app/immich-machine-learning:${IMMICH_VERSION:-release}
|
||||
# extends: # uncomment this section for hardware acceleration - see https://immich.app/docs/features/ml-hardware-acceleration
|
||||
# file: hwaccel.ml.yml
|
||||
# service: cpu # set to one of [armnn, cuda, rocm, openvino, openvino-wsl, rknn] for accelerated inference - use the `-wsl` version for WSL2 where applicable
|
||||
# service: cpu # set to one of [armnn, cuda, openvino, openvino-wsl] for accelerated inference - use the `-wsl` version for WSL2 where applicable
|
||||
volumes:
|
||||
- model-cache:/cache
|
||||
env_file:
|
||||
@@ -67,12 +67,22 @@ services:
|
||||
- ${DB_DATA_LOCATION}:/var/lib/postgresql/data
|
||||
healthcheck:
|
||||
test: >-
|
||||
pg_isready --dbname="$${POSTGRES_DB}" --username="$${POSTGRES_USER}" || exit 1; Chksum="$$(psql --dbname="$${POSTGRES_DB}" --username="$${POSTGRES_USER}" --tuples-only --no-align --command='SELECT COALESCE(SUM(checksum_failures), 0) FROM pg_stat_database')"; echo "checksum failure count is $$Chksum"; [ "$$Chksum" = '0' ] || exit 1
|
||||
pg_isready --dbname="$${POSTGRES_DB}" --username="$${POSTGRES_USER}" || exit 1;
|
||||
Chksum="$$(psql --dbname="$${POSTGRES_DB}" --username="$${POSTGRES_USER}" --tuples-only --no-align
|
||||
--command='SELECT COALESCE(SUM(checksum_failures), 0) FROM pg_stat_database')";
|
||||
echo "checksum failure count is $$Chksum";
|
||||
[ "$$Chksum" = '0' ] || exit 1
|
||||
interval: 5m
|
||||
start_interval: 30s
|
||||
start_period: 5m
|
||||
command: >-
|
||||
postgres -c shared_preload_libraries=vectors.so -c 'search_path="$$user", public, vectors' -c logging_collector=on -c max_wal_size=2GB -c shared_buffers=512MB -c wal_compression=on
|
||||
postgres
|
||||
-c shared_preload_libraries=vectors.so
|
||||
-c 'search_path="$$user", public, vectors'
|
||||
-c logging_collector=on
|
||||
-c max_wal_size=2GB
|
||||
-c shared_buffers=512MB
|
||||
-c wal_compression=on
|
||||
restart: always
|
||||
|
||||
volumes:
|
||||
|
||||
@@ -13,13 +13,6 @@ services:
|
||||
volumes:
|
||||
- /lib/firmware/mali_csffw.bin:/lib/firmware/mali_csffw.bin:ro # Mali firmware for your chipset (not always required depending on the driver)
|
||||
- /usr/lib/libmali.so:/usr/lib/libmali.so:ro # Mali driver for your chipset (always required)
|
||||
|
||||
rknn:
|
||||
security_opt:
|
||||
- systempaths=unconfined
|
||||
- apparmor=unconfined
|
||||
devices:
|
||||
- /dev/dri:/dev/dri
|
||||
|
||||
cpu: {}
|
||||
|
||||
@@ -33,13 +26,6 @@ services:
|
||||
capabilities:
|
||||
- gpu
|
||||
|
||||
rocm:
|
||||
group_add:
|
||||
- video
|
||||
devices:
|
||||
- /dev/dri:/dev/dri
|
||||
- /dev/kfd:/dev/kfd
|
||||
|
||||
openvino:
|
||||
device_cgroup_rules:
|
||||
- 'c 189:* rmw'
|
||||
|
||||
@@ -262,7 +262,7 @@ No, this is not supported. Only models listed in the [Hugging Face][huggingface]
|
||||
|
||||
### I want to be able to search in other languages besides English. How can I do that?
|
||||
|
||||
You can change to a multilingual CLIP model. See [here](/docs/features/searching#clip-models) for instructions.
|
||||
You can change to a multilingual CLIP model. See [here](/docs/features/searching#clip-model) for instructions.
|
||||
|
||||
### Does Immich support Facial Recognition for videos?
|
||||
|
||||
|
||||
@@ -11,7 +11,6 @@ The `immich-server` docker image comes preinstalled with an administrative CLI (
|
||||
| `enable-oauth-login` | Enable OAuth login |
|
||||
| `disable-oauth-login` | Disable OAuth login |
|
||||
| `list-users` | List Immich users |
|
||||
| `version` | Print Immich version |
|
||||
|
||||
## How to run a command
|
||||
|
||||
@@ -81,10 +80,3 @@ immich-admin list-users
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
Print Immich Version
|
||||
|
||||
```
|
||||
immich-admin version
|
||||
v1.129.0
|
||||
```
|
||||
|
||||
@@ -95,7 +95,7 @@ The `immich-server` container will need access to the gallery. Modify your docke
|
||||
+ - /mnt/nas/christmas-trip:/mnt/media/christmas-trip:ro
|
||||
+ - /home/user/old-pics:/mnt/media/old-pics:ro
|
||||
+ - /mnt/media/videos:/mnt/media/videos:ro
|
||||
+ - /mnt/media/videos2:/mnt/media/videos2 # WARNING: Immich will be able to delete the files in this folder, as it does not end with :ro
|
||||
+ - /mnt/media/videos2:/mnt/media/videos2 # the files in this folder can be deleted, as it does not end with :ro
|
||||
+ - "C:/Users/user_name/Desktop/my media:/mnt/media/my-media:ro" # import path in Windows system.
|
||||
```
|
||||
|
||||
|
||||
@@ -11,9 +11,7 @@ You do not need to redo any machine learning jobs after enabling hardware accele
|
||||
|
||||
- ARM NN (Mali)
|
||||
- CUDA (NVIDIA GPUs with [compute capability](https://developer.nvidia.com/cuda-gpus) 5.2 or higher)
|
||||
- ROCm (AMD GPUs)
|
||||
- OpenVINO (Intel GPUs such as Iris Xe and Arc)
|
||||
- RKNN (Rockchip)
|
||||
|
||||
## Limitations
|
||||
|
||||
@@ -21,7 +19,6 @@ You do not need to redo any machine learning jobs after enabling hardware accele
|
||||
- Only Linux and Windows (through WSL2) servers are supported.
|
||||
- ARM NN is only supported on devices with Mali GPUs. Other Arm devices are not supported.
|
||||
- Some models may not be compatible with certain backends. CUDA is the most reliable.
|
||||
- Search latency isn't improved by ARM NN due to model compatibility issues preventing its use. However, smart search jobs do make use of ARM NN.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
@@ -36,7 +33,6 @@ You do not need to redo any machine learning jobs after enabling hardware accele
|
||||
- The `hwaccel.ml.yml` file assumes the path to it is `/usr/lib/libmali.so`, so update accordingly if it is elsewhere
|
||||
- The `hwaccel.ml.yml` file assumes an additional file `/lib/firmware/mali_csffw.bin`, so update accordingly if your device's driver does not require this file
|
||||
- Optional: Configure your `.env` file, see [environment variables](/docs/install/environment-variables) for ARM NN specific settings
|
||||
- In particular, the `MACHINE_LEARNING_ANN_FP16_TURBO` can significantly improve performance at the cost of very slightly lower accuracy
|
||||
|
||||
#### CUDA
|
||||
|
||||
@@ -45,38 +41,22 @@ You do not need to redo any machine learning jobs after enabling hardware accele
|
||||
- The installed driver must be >= 535 (it must support CUDA 12.2).
|
||||
- On Linux (except for WSL2), you also need to have [NVIDIA Container Toolkit][nvct] installed.
|
||||
|
||||
#### ROCm
|
||||
|
||||
- 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.
|
||||
- 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](/docs/install/environment-variables) setting).
|
||||
|
||||
#### OpenVINO
|
||||
|
||||
- Integrated GPUs are more likely to experience issues than discrete GPUs, especially for older processors or servers with low RAM.
|
||||
- Ensure the server's kernel version is new enough to use the device for hardware accceleration.
|
||||
- Expect higher RAM usage when using OpenVINO compared to CPU processing.
|
||||
|
||||
#### RKNN
|
||||
|
||||
- You must have a supported Rockchip SoC: only RK3566, RK3568, RK3576 and RK3588 are supported at this moment.
|
||||
- Make sure you have the appropriate linux kernel driver installed
|
||||
- This is usually pre-installed on the device vendor's Linux images
|
||||
- RKNPU driver V0.9.8 or later must be available in the host server
|
||||
- You may confirm this by running `cat /sys/kernel/debug/rknpu/version` to check the version
|
||||
- Optional: Configure your `.env` file, see [environment variables](/docs/install/environment-variables) for RKNN specific settings
|
||||
- In particular, setting `MACHINE_LEARNING_RKNN_THREADS` to 2 or 3 can _dramatically_ improve performance for RK3576 and RK3588 compared to the default of 1, at the expense of multiplying the amount of RAM each model uses by that amount.
|
||||
|
||||
## Setup
|
||||
|
||||
1. If you do not already have it, download the latest [`hwaccel.ml.yml`][hw-file] file and ensure it's in the same folder as the `docker-compose.yml`.
|
||||
2. In the `docker-compose.yml` under `immich-machine-learning`, uncomment the `extends` section and change `cpu` to the appropriate backend.
|
||||
3. Still in `immich-machine-learning`, add one of -[armnn, cuda, rocm, openvino] to the `image` section's tag at the end of the line.
|
||||
3. Still in `immich-machine-learning`, add one of -[armnn, cuda, openvino] to the `image` section's tag at the end of the line.
|
||||
4. Redeploy the `immich-machine-learning` container with these updated settings.
|
||||
|
||||
### Confirming Device Usage
|
||||
|
||||
You can confirm the device is being recognized and used by checking its utilization. There are many tools to display this, such as `nvtop` for NVIDIA or Intel, `intel_gpu_top` for Intel, and `radeontop` for AMD.
|
||||
You can confirm the device is being recognized and used by checking its utilization. There are many tools to display this, such as `nvtop` for NVIDIA or Intel and `intel_gpu_top` for Intel.
|
||||
|
||||
You can also check the logs of the `immich-machine-learning` container. When a Smart Search or Face Detection job begins, or when you search with text in Immich, you should either see a log for `Available ORT providers` containing the relevant provider (e.g. `CUDAExecutionProvider` in the case of CUDA), or a `Loaded ANN model` log entry without errors in the case of ARM NN.
|
||||
|
||||
@@ -147,12 +127,3 @@ Note that you should increase job concurrencies to increase overall utilization
|
||||
- If you encounter an error when a model is running, try a different model to see if the issue is model-specific.
|
||||
- You may want to increase concurrency past the default for higher utilization. However, keep in mind that this will also increase VRAM consumption.
|
||||
- Larger models benefit more from hardware acceleration, if you have the VRAM for them.
|
||||
- Compared to ARM NN, RKNPU has:
|
||||
- Wider model support (including for search, which ARM NN does not accelerate)
|
||||
- Less heat generation
|
||||
- Very slightly lower accuracy (RKNPU always uses FP16, while ARM NN by default uses higher precision FP32 unless `MACHINE_LEARNING_ANN_FP16_TURBO` is enabled)
|
||||
- Varying speed (tested on RK3588):
|
||||
- If `MACHINE_LEARNING_RKNN_THREADS` is at the default of 1, RKNPU will have substantially lower throughput for ML jobs than ARM NN in most cases, but similar latency (such as when searching)
|
||||
- If `MACHINE_LEARNING_RKNN_THREADS` is set to 3, it will be somewhat faster than ARM NN at FP32, but somewhat slower than ARM NN if `MACHINE_LEARNING_ANN_FP16_TURBO` is enabled
|
||||
- When other tasks also use the GPU (like transcoding), RKNPU has a significant advantage over ARM NN as it uses the otherwise idle NPU instead of competing for GPU usage
|
||||
- Lower RAM usage if `MACHINE_LEARNING_RKNN_THREADS` is at the default of 1, but significantly higher if greater than 1 (which is necessary for it to fully utilize the NPU and hence be comparable in speed to ARM NN)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -23,12 +23,12 @@ name: immich_remote_ml
|
||||
services:
|
||||
immich-machine-learning:
|
||||
container_name: immich_machine_learning
|
||||
# For hardware acceleration, add one of -[armnn, cuda, rocm, openvino] to the image tag.
|
||||
# For hardware acceleration, add one of -[armnn, cuda, openvino] to the image tag.
|
||||
# Example tag: ${IMMICH_VERSION:-release}-cuda
|
||||
image: ghcr.io/immich-app/immich-machine-learning:${IMMICH_VERSION:-release}
|
||||
# extends:
|
||||
# file: hwaccel.ml.yml
|
||||
# service: # set to one of [armnn, cuda, rocm, openvino, openvino-wsl] for accelerated inference - use the `-wsl` version for WSL2 where applicable
|
||||
# service: # set to one of [armnn, cuda, openvino, openvino-wsl] for accelerated inference - use the `-wsl` version for WSL2 where applicable
|
||||
volumes:
|
||||
- model-cache:/cache
|
||||
restart: always
|
||||
|
||||
@@ -170,8 +170,6 @@ Redis (Sentinel) URL example JSON before encoding:
|
||||
| `MACHINE_LEARNING_MAX_BATCH_SIZE__FACIAL_RECOGNITION` | Set the maximum number of faces that will be processed at once by the facial recognition model | None (`1` if using OpenVINO) | machine learning |
|
||||
| `MACHINE_LEARNING_PING_TIMEOUT` | How long (ms) to wait for a PING response when checking if an ML server is available | `2000` | server |
|
||||
| `MACHINE_LEARNING_AVAILABILITY_BACKOFF_TIME` | How long to ignore ML servers that are offline before trying again | `30000` | server |
|
||||
| `MACHINE_LEARNING_RKNN` | Enable RKNN hardware acceleration if supported | `True` | machine learning |
|
||||
| `MACHINE_LEARNING_RKNN_THREADS` | How many threads of RKNN runtime should be spinned up while inferencing. | `1` | machine learning |
|
||||
|
||||
\*1: It is recommended to begin with this parameter when changing the concurrency levels of the machine learning service and then tune the other ones.
|
||||
|
||||
|
||||
18
docs/package-lock.json
generated
18
docs/package-lock.json
generated
@@ -5308,9 +5308,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/autoprefixer": {
|
||||
"version": "10.4.21",
|
||||
"resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.21.tgz",
|
||||
"integrity": "sha512-O+A6LWV5LDHSJD3LjHYoNi4VLsj/Whi7k6zG12xTYaU4cQ8oxQGckXNX8cRHK5yOZ/ppVHe0ZBXGzSV9jXdVbQ==",
|
||||
"version": "10.4.20",
|
||||
"resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.20.tgz",
|
||||
"integrity": "sha512-XY25y5xSv/wEoqzDyXXME4AFfkZI0P23z6Fs3YgymDnKJkCGOnkL0iTxCa85UTqaSgfcqyf3UA6+c7wUvx/16g==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "opencollective",
|
||||
@@ -5327,11 +5327,11 @@
|
||||
],
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"browserslist": "^4.24.4",
|
||||
"caniuse-lite": "^1.0.30001702",
|
||||
"browserslist": "^4.23.3",
|
||||
"caniuse-lite": "^1.0.30001646",
|
||||
"fraction.js": "^4.3.7",
|
||||
"normalize-range": "^0.1.2",
|
||||
"picocolors": "^1.1.1",
|
||||
"picocolors": "^1.0.1",
|
||||
"postcss-value-parser": "^4.2.0"
|
||||
},
|
||||
"bin": {
|
||||
@@ -5781,9 +5781,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/caniuse-lite": {
|
||||
"version": "1.0.30001706",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001706.tgz",
|
||||
"integrity": "sha512-3ZczoTApMAZwPKYWmwVbQMFpXBDds3/0VciVoUwPUbldlYyVLmRVuRs/PcUZtHpbLRpzzDvrvnFuREsGt6lUug==",
|
||||
"version": "1.0.30001695",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001695.tgz",
|
||||
"integrity": "sha512-vHyLade6wTgI2u1ec3WQBxv+2BrTERV28UXQu9LO6lZ9pYeMk34vjXFLOxo1A4UBA8XTL4njRQZdno/yYaSmWw==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "opencollective",
|
||||
|
||||
8
docs/static/archived-versions.json
vendored
8
docs/static/archived-versions.json
vendored
@@ -1,12 +1,4 @@
|
||||
[
|
||||
{
|
||||
"label": "v1.130.1",
|
||||
"url": "https://v1.130.1.archive.immich.app"
|
||||
},
|
||||
{
|
||||
"label": "v1.130.0",
|
||||
"url": "https://v1.130.0.archive.immich.app"
|
||||
},
|
||||
{
|
||||
"label": "v1.129.0",
|
||||
"url": "https://v1.129.0.archive.immich.app"
|
||||
|
||||
159
e2e/package-lock.json
generated
159
e2e/package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "immich-e2e",
|
||||
"version": "1.130.1",
|
||||
"version": "1.129.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "immich-e2e",
|
||||
"version": "1.130.1",
|
||||
"version": "1.129.0",
|
||||
"license": "GNU Affero General Public License version 3",
|
||||
"devDependencies": {
|
||||
"@eslint/eslintrc": "^3.1.0",
|
||||
@@ -15,7 +15,7 @@
|
||||
"@immich/sdk": "file:../open-api/typescript-sdk",
|
||||
"@playwright/test": "^1.44.1",
|
||||
"@types/luxon": "^3.4.2",
|
||||
"@types/node": "^22.13.10",
|
||||
"@types/node": "^22.13.9",
|
||||
"@types/oidc-provider": "^8.5.1",
|
||||
"@types/pg": "^8.11.0",
|
||||
"@types/pngjs": "^6.0.4",
|
||||
@@ -45,7 +45,7 @@
|
||||
},
|
||||
"../cli": {
|
||||
"name": "@immich/cli",
|
||||
"version": "2.2.55",
|
||||
"version": "2.2.53",
|
||||
"dev": true,
|
||||
"license": "GNU Affero General Public License version 3",
|
||||
"dependencies": {
|
||||
@@ -67,7 +67,7 @@
|
||||
"@types/lodash-es": "^4.17.12",
|
||||
"@types/micromatch": "^4.0.9",
|
||||
"@types/mock-fs": "^4.13.1",
|
||||
"@types/node": "^22.13.10",
|
||||
"@types/node": "^22.13.9",
|
||||
"@typescript-eslint/eslint-plugin": "^8.15.0",
|
||||
"@typescript-eslint/parser": "^8.15.0",
|
||||
"@vitest/coverage-v8": "^3.0.0",
|
||||
@@ -95,14 +95,14 @@
|
||||
},
|
||||
"../open-api/typescript-sdk": {
|
||||
"name": "@immich/sdk",
|
||||
"version": "1.130.1",
|
||||
"version": "1.129.0",
|
||||
"dev": true,
|
||||
"license": "GNU Affero General Public License version 3",
|
||||
"dependencies": {
|
||||
"@oazapfts/runtime": "^1.0.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^22.13.10",
|
||||
"@types/node": "^22.13.9",
|
||||
"typescript": "^5.3.3"
|
||||
}
|
||||
},
|
||||
@@ -828,16 +828,6 @@
|
||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@eslint/config-helpers": {
|
||||
"version": "0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.1.0.tgz",
|
||||
"integrity": "sha512-kLrdPDJE1ckPo94kmPPf9Hfd0DU0Jw6oKYrhe+pwSC0iTUInmTa+w6fw8sGgcfkFJGNdWOUeOaDM4quW4a7OkA==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"engines": {
|
||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@eslint/core": {
|
||||
"version": "0.12.0",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.12.0.tgz",
|
||||
@@ -889,9 +879,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@eslint/js": {
|
||||
"version": "9.22.0",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.22.0.tgz",
|
||||
"integrity": "sha512-vLFajx9o8d1/oL2ZkpMYbkLv8nDB6yaIwFNt7nI4+I80U/z03SxmfOMsLbvWr3p7C+Wnoh//aOu2pQW8cS0HCQ==",
|
||||
"version": "9.21.0",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.21.0.tgz",
|
||||
"integrity": "sha512-BqStZ3HX8Yz6LvsF5ByXYrtigrV5AXADWLAGc7PH/1SxOb7/FIYYMszZZWiUou/GB9P2lXWk2SV4d+Z8h0nknw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
@@ -1743,9 +1733,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/oidc-provider": {
|
||||
"version": "8.8.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/oidc-provider/-/oidc-provider-8.8.1.tgz",
|
||||
"integrity": "sha512-Yi/OJ7s0CFJ1AWAQrY2EO/zkV9uppLtiGAzrA07lBDveUOvxtYh7GflnHFXcgufVaPxVAjdykizjTYTMNVhdJw==",
|
||||
"version": "8.8.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/oidc-provider/-/oidc-provider-8.8.0.tgz",
|
||||
"integrity": "sha512-9Jtutw4dyAz0PN8EWlxqeNrGHsEZ9EH4QZjfkZIbhmKuiuHIrzoz/S1zHNXX8ogfhWtPp1swMyzXBSo6RTTj1Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -1892,17 +1882,17 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/eslint-plugin": {
|
||||
"version": "8.26.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.26.1.tgz",
|
||||
"integrity": "sha512-2X3mwqsj9Bd3Ciz508ZUtoQQYpOhU/kWoUqIf49H8Z0+Vbh6UF/y0OEYp0Q0axOGzaBGs7QxRwq0knSQ8khQNA==",
|
||||
"version": "8.26.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.26.0.tgz",
|
||||
"integrity": "sha512-cLr1J6pe56zjKYajK6SSSre6nl1Gj6xDp1TY0trpgPzjVbgDwd09v2Ws37LABxzkicmUjhEeg/fAUjPJJB1v5Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@eslint-community/regexpp": "^4.10.0",
|
||||
"@typescript-eslint/scope-manager": "8.26.1",
|
||||
"@typescript-eslint/type-utils": "8.26.1",
|
||||
"@typescript-eslint/utils": "8.26.1",
|
||||
"@typescript-eslint/visitor-keys": "8.26.1",
|
||||
"@typescript-eslint/scope-manager": "8.26.0",
|
||||
"@typescript-eslint/type-utils": "8.26.0",
|
||||
"@typescript-eslint/utils": "8.26.0",
|
||||
"@typescript-eslint/visitor-keys": "8.26.0",
|
||||
"graphemer": "^1.4.0",
|
||||
"ignore": "^5.3.1",
|
||||
"natural-compare": "^1.4.0",
|
||||
@@ -1922,16 +1912,16 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/parser": {
|
||||
"version": "8.26.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.26.1.tgz",
|
||||
"integrity": "sha512-w6HZUV4NWxqd8BdeFf81t07d7/YV9s7TCWrQQbG5uhuvGUAW+fq1usZ1Hmz9UPNLniFnD8GLSsDpjP0hm1S4lQ==",
|
||||
"version": "8.26.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.26.0.tgz",
|
||||
"integrity": "sha512-mNtXP9LTVBy14ZF3o7JG69gRPBK/2QWtQd0j0oH26HcY/foyJJau6pNUez7QrM5UHnSvwlQcJXKsk0I99B9pOA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@typescript-eslint/scope-manager": "8.26.1",
|
||||
"@typescript-eslint/types": "8.26.1",
|
||||
"@typescript-eslint/typescript-estree": "8.26.1",
|
||||
"@typescript-eslint/visitor-keys": "8.26.1",
|
||||
"@typescript-eslint/scope-manager": "8.26.0",
|
||||
"@typescript-eslint/types": "8.26.0",
|
||||
"@typescript-eslint/typescript-estree": "8.26.0",
|
||||
"@typescript-eslint/visitor-keys": "8.26.0",
|
||||
"debug": "^4.3.4"
|
||||
},
|
||||
"engines": {
|
||||
@@ -1947,14 +1937,14 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/scope-manager": {
|
||||
"version": "8.26.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.26.1.tgz",
|
||||
"integrity": "sha512-6EIvbE5cNER8sqBu6V7+KeMZIC1664d2Yjt+B9EWUXrsyWpxx4lEZrmvxgSKRC6gX+efDL/UY9OpPZ267io3mg==",
|
||||
"version": "8.26.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.26.0.tgz",
|
||||
"integrity": "sha512-E0ntLvsfPqnPwng8b8y4OGuzh/iIOm2z8U3S9zic2TeMLW61u5IH2Q1wu0oSTkfrSzwbDJIB/Lm8O3//8BWMPA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@typescript-eslint/types": "8.26.1",
|
||||
"@typescript-eslint/visitor-keys": "8.26.1"
|
||||
"@typescript-eslint/types": "8.26.0",
|
||||
"@typescript-eslint/visitor-keys": "8.26.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||
@@ -1965,14 +1955,14 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/type-utils": {
|
||||
"version": "8.26.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.26.1.tgz",
|
||||
"integrity": "sha512-Kcj/TagJLwoY/5w9JGEFV0dclQdyqw9+VMndxOJKtoFSjfZhLXhYjzsQEeyza03rwHx2vFEGvrJWJBXKleRvZg==",
|
||||
"version": "8.26.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.26.0.tgz",
|
||||
"integrity": "sha512-ruk0RNChLKz3zKGn2LwXuVoeBcUMh+jaqzN461uMMdxy5H9epZqIBtYj7UiPXRuOpaALXGbmRuZQhmwHhaS04Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@typescript-eslint/typescript-estree": "8.26.1",
|
||||
"@typescript-eslint/utils": "8.26.1",
|
||||
"@typescript-eslint/typescript-estree": "8.26.0",
|
||||
"@typescript-eslint/utils": "8.26.0",
|
||||
"debug": "^4.3.4",
|
||||
"ts-api-utils": "^2.0.1"
|
||||
},
|
||||
@@ -1989,9 +1979,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/types": {
|
||||
"version": "8.26.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.26.1.tgz",
|
||||
"integrity": "sha512-n4THUQW27VmQMx+3P+B0Yptl7ydfceUj4ON/AQILAASwgYdZ/2dhfymRMh5egRUrvK5lSmaOm77Ry+lmXPOgBQ==",
|
||||
"version": "8.26.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.26.0.tgz",
|
||||
"integrity": "sha512-89B1eP3tnpr9A8L6PZlSjBvnJhWXtYfZhECqlBl1D9Lme9mHO6iWlsprBtVenQvY1HMhax1mWOjhtL3fh/u+pA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
@@ -2003,14 +1993,14 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/typescript-estree": {
|
||||
"version": "8.26.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.26.1.tgz",
|
||||
"integrity": "sha512-yUwPpUHDgdrv1QJ7YQal3cMVBGWfnuCdKbXw1yyjArax3353rEJP1ZA+4F8nOlQ3RfS2hUN/wze3nlY+ZOhvoA==",
|
||||
"version": "8.26.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.26.0.tgz",
|
||||
"integrity": "sha512-tiJ1Hvy/V/oMVRTbEOIeemA2XoylimlDQ03CgPPNaHYZbpsc78Hmngnt+WXZfJX1pjQ711V7g0H7cSJThGYfPQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@typescript-eslint/types": "8.26.1",
|
||||
"@typescript-eslint/visitor-keys": "8.26.1",
|
||||
"@typescript-eslint/types": "8.26.0",
|
||||
"@typescript-eslint/visitor-keys": "8.26.0",
|
||||
"debug": "^4.3.4",
|
||||
"fast-glob": "^3.3.2",
|
||||
"is-glob": "^4.0.3",
|
||||
@@ -2056,16 +2046,16 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/utils": {
|
||||
"version": "8.26.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.26.1.tgz",
|
||||
"integrity": "sha512-V4Urxa/XtSUroUrnI7q6yUTD3hDtfJ2jzVfeT3VK0ciizfK2q/zGC0iDh1lFMUZR8cImRrep6/q0xd/1ZGPQpg==",
|
||||
"version": "8.26.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.26.0.tgz",
|
||||
"integrity": "sha512-2L2tU3FVwhvU14LndnQCA2frYC8JnPDVKyQtWFPf8IYFMt/ykEN1bPolNhNbCVgOmdzTlWdusCTKA/9nKrf8Ig==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@eslint-community/eslint-utils": "^4.4.0",
|
||||
"@typescript-eslint/scope-manager": "8.26.1",
|
||||
"@typescript-eslint/types": "8.26.1",
|
||||
"@typescript-eslint/typescript-estree": "8.26.1"
|
||||
"@typescript-eslint/scope-manager": "8.26.0",
|
||||
"@typescript-eslint/types": "8.26.0",
|
||||
"@typescript-eslint/typescript-estree": "8.26.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||
@@ -2080,13 +2070,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/visitor-keys": {
|
||||
"version": "8.26.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.26.1.tgz",
|
||||
"integrity": "sha512-AjOC3zfnxd6S4Eiy3jwktJPclqhFHNyd8L6Gycf9WUPoKZpgM5PjkxY1X7uSy61xVpiJDhhk7XT2NVsN3ALTWg==",
|
||||
"version": "8.26.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.26.0.tgz",
|
||||
"integrity": "sha512-2z8JQJWAzPdDd51dRQ/oqIJxe99/hoLIqmf8RMCAJQtYDc535W/Jt2+RTP4bP0aKeBG1F65yjIZuczOXCmbWwg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@typescript-eslint/types": "8.26.1",
|
||||
"@typescript-eslint/types": "8.26.0",
|
||||
"eslint-visitor-keys": "^4.2.0"
|
||||
},
|
||||
"engines": {
|
||||
@@ -3167,19 +3157,18 @@
|
||||
}
|
||||
},
|
||||
"node_modules/eslint": {
|
||||
"version": "9.22.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint/-/eslint-9.22.0.tgz",
|
||||
"integrity": "sha512-9V/QURhsRN40xuHXWjV64yvrzMjcz7ZyNoF2jJFmy9j/SLk0u1OLSZgXi28MrXjymnjEGSR80WCdab3RGMDveQ==",
|
||||
"version": "9.21.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint/-/eslint-9.21.0.tgz",
|
||||
"integrity": "sha512-KjeihdFqTPhOMXTt7StsDxriV4n66ueuF/jfPNC3j/lduHwr/ijDwJMsF+wyMJethgiKi5wniIE243vi07d3pg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@eslint-community/eslint-utils": "^4.2.0",
|
||||
"@eslint-community/regexpp": "^4.12.1",
|
||||
"@eslint/config-array": "^0.19.2",
|
||||
"@eslint/config-helpers": "^0.1.0",
|
||||
"@eslint/core": "^0.12.0",
|
||||
"@eslint/eslintrc": "^3.3.0",
|
||||
"@eslint/js": "9.22.0",
|
||||
"@eslint/js": "9.21.0",
|
||||
"@eslint/plugin-kit": "^0.2.7",
|
||||
"@humanfs/node": "^0.16.6",
|
||||
"@humanwhocodes/module-importer": "^1.0.1",
|
||||
@@ -3191,7 +3180,7 @@
|
||||
"cross-spawn": "^7.0.6",
|
||||
"debug": "^4.3.2",
|
||||
"escape-string-regexp": "^4.0.0",
|
||||
"eslint-scope": "^8.3.0",
|
||||
"eslint-scope": "^8.2.0",
|
||||
"eslint-visitor-keys": "^4.2.0",
|
||||
"espree": "^10.3.0",
|
||||
"esquery": "^1.5.0",
|
||||
@@ -3319,9 +3308,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-scope": {
|
||||
"version": "8.3.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.3.0.tgz",
|
||||
"integrity": "sha512-pUNxi75F8MJ/GdeKtVLSbYg4ZI34J6C0C7sbL4YOp2exGwen7ZsuBqKzUhXd0qMQ362yET3z+uPwKeg/0C2XCQ==",
|
||||
"version": "8.2.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.2.0.tgz",
|
||||
"integrity": "sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A==",
|
||||
"dev": true,
|
||||
"license": "BSD-2-Clause",
|
||||
"dependencies": {
|
||||
@@ -5222,15 +5211,15 @@
|
||||
}
|
||||
},
|
||||
"node_modules/pg": {
|
||||
"version": "8.14.0",
|
||||
"resolved": "https://registry.npmjs.org/pg/-/pg-8.14.0.tgz",
|
||||
"integrity": "sha512-nXbVpyoaXVmdqlKEzToFf37qzyeeh7mbiXsnoWvstSqohj88yaa/I/Rq/HEVn2QPSZEuLIJa/jSpRDyzjEx4FQ==",
|
||||
"version": "8.13.3",
|
||||
"resolved": "https://registry.npmjs.org/pg/-/pg-8.13.3.tgz",
|
||||
"integrity": "sha512-P6tPt9jXbL9HVu/SSRERNYaYG++MjnscnegFh9pPHihfoBSujsrka0hyuymMzeJKFWrcG8wvCKy8rCe8e5nDUQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"pg-connection-string": "^2.7.0",
|
||||
"pg-pool": "^3.8.0",
|
||||
"pg-protocol": "^1.8.0",
|
||||
"pg-pool": "^3.7.1",
|
||||
"pg-protocol": "^1.7.1",
|
||||
"pg-types": "^2.1.0",
|
||||
"pgpass": "1.x"
|
||||
},
|
||||
@@ -5282,9 +5271,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/pg-pool": {
|
||||
"version": "3.8.0",
|
||||
"resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.8.0.tgz",
|
||||
"integrity": "sha512-VBw3jiVm6ZOdLBTIcXLNdSotb6Iy3uOCwDGFAksZCXmi10nyRvnP2v3jl4d+IsLYRyXf6o9hIm/ZtUzlByNUdw==",
|
||||
"version": "3.7.1",
|
||||
"resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.7.1.tgz",
|
||||
"integrity": "sha512-xIOsFoh7Vdhojas6q3596mXFsR8nwBQBXX5JiV7p9buEVAGqYL4yFzclON5P9vFrpu1u7Zwl2oriyDa89n0wbw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
@@ -5292,9 +5281,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/pg-protocol": {
|
||||
"version": "1.8.0",
|
||||
"resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.8.0.tgz",
|
||||
"integrity": "sha512-jvuYlEkL03NRvOoyoRktBK7+qU5kOvlAwvmrH8sr3wbLrOdVWsRxQfz8mMy9sZFsqJ1hEWNfdWKI4SAmoL+j7g==",
|
||||
"version": "1.7.1",
|
||||
"resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.7.1.tgz",
|
||||
"integrity": "sha512-gjTHWGYWsEgy9MsY0Gp6ZJxV24IjDqdpTW7Eh0x+WfJLFsm/TJx1MzL6T0D88mBvkpxotCQ6TwW6N+Kko7lhgQ==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "immich-e2e",
|
||||
"version": "1.130.1",
|
||||
"version": "1.129.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"type": "module",
|
||||
@@ -25,7 +25,7 @@
|
||||
"@immich/sdk": "file:../open-api/typescript-sdk",
|
||||
"@playwright/test": "^1.44.1",
|
||||
"@types/luxon": "^3.4.2",
|
||||
"@types/node": "^22.13.10",
|
||||
"@types/node": "^22.13.9",
|
||||
"@types/oidc-provider": "^8.5.1",
|
||||
"@types/pg": "^8.11.0",
|
||||
"@types/pngjs": "^6.0.4",
|
||||
|
||||
@@ -633,6 +633,7 @@ describe('/search', () => {
|
||||
.set('Authorization', `Bearer ${admin.accessToken}`);
|
||||
expect(body).toEqual([
|
||||
'Andalusia',
|
||||
'Berlin',
|
||||
'Glarus',
|
||||
'Greater Accra',
|
||||
'Havana',
|
||||
@@ -641,7 +642,6 @@ describe('/search', () => {
|
||||
'Mississippi',
|
||||
'New York',
|
||||
'Shanghai',
|
||||
'State of Berlin',
|
||||
'St.-Petersburg',
|
||||
'Tbilisi',
|
||||
'Tokyo',
|
||||
@@ -657,6 +657,7 @@ describe('/search', () => {
|
||||
.set('Authorization', `Bearer ${admin.accessToken}`);
|
||||
expect(body).toEqual([
|
||||
'Andalusia',
|
||||
'Berlin',
|
||||
'Glarus',
|
||||
'Greater Accra',
|
||||
'Havana',
|
||||
@@ -665,7 +666,6 @@ describe('/search', () => {
|
||||
'Mississippi',
|
||||
'New York',
|
||||
'Shanghai',
|
||||
'State of Berlin',
|
||||
'St.-Petersburg',
|
||||
'Tbilisi',
|
||||
'Tokyo',
|
||||
|
||||
@@ -493,7 +493,7 @@ export const utils = {
|
||||
value: accessToken,
|
||||
domain,
|
||||
path: '/',
|
||||
expires: 2_058_028_213,
|
||||
expires: 1_742_402_728,
|
||||
httpOnly: true,
|
||||
secure: false,
|
||||
sameSite: 'Lax',
|
||||
@@ -503,7 +503,7 @@ export const utils = {
|
||||
value: 'password',
|
||||
domain,
|
||||
path: '/',
|
||||
expires: 2_058_028_213,
|
||||
expires: 1_742_402_728,
|
||||
httpOnly: true,
|
||||
secure: false,
|
||||
sameSite: 'Lax',
|
||||
@@ -513,7 +513,7 @@ export const utils = {
|
||||
value: 'true',
|
||||
domain,
|
||||
path: '/',
|
||||
expires: 2_058_028_213,
|
||||
expires: 1_742_402_728,
|
||||
httpOnly: false,
|
||||
secure: false,
|
||||
sameSite: 'Lax',
|
||||
|
||||
@@ -45,7 +45,7 @@ test.describe('Shared Links', () => {
|
||||
await page.goto(`/share/${sharedLink.key}`);
|
||||
await page.getByRole('heading', { name: 'Test Album' }).waitFor();
|
||||
await page.locator(`[data-asset-id="${asset.id}"]`).hover();
|
||||
await page.waitForSelector('[data-group] svg');
|
||||
await page.waitForSelector('#asset-group-by-date svg');
|
||||
await page.getByRole('checkbox').click();
|
||||
await page.getByRole('button', { name: 'Download' }).click();
|
||||
await page.getByText('DOWNLOADING', { exact: true }).waitFor();
|
||||
|
||||
16
i18n/af.json
16
i18n/af.json
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"about": "Oor",
|
||||
"about": "Verfris",
|
||||
"account": "Rekening",
|
||||
"account_settings": "Rekeninginstellings",
|
||||
"acknowledge": "Erken",
|
||||
@@ -56,7 +56,7 @@
|
||||
"duplicate_detection_job_description": "Begin masjienleer op bates om soortgelyke beelde op te spoor. Maak staat op Smart Search",
|
||||
"exclusion_pattern_description": "Met uitsluitingspatrone kan jy lêers en vouers ignoreer wanneer jy jou biblioteek skandeer. Dit is nuttig as jy vouers het wat lêers bevat wat jy nie wil invoer nie, soos RAW-lêers.",
|
||||
"external_library_created_at": "Eksterne biblioteek (geskep op {date})",
|
||||
"external_library_management": "Eksterne Biblioteekbestuur",
|
||||
"external_library_management": "Eksterne Biblioteek-opsies",
|
||||
"face_detection": "Gesig deteksie",
|
||||
"failed_job_command": "Opdrag {command} het misluk vir werk: {job}",
|
||||
"force_delete_user_warning": "WAARSKUWING: Dit sal onmiddellik die gebruiker en alle bates verwyder. Dit kan nie ontdoen word nie en die lêers kan nie herstel word nie.",
|
||||
@@ -64,8 +64,7 @@
|
||||
"image_format": "Formaat",
|
||||
"image_format_description": "WebP produseer kleiner lêers as JPEG, maar is stadiger om te enkodeer.",
|
||||
"image_prefer_embedded_preview": "Verkies ingebedde voorskou",
|
||||
"image_prefer_wide_gamut": "Verkies wide gamut",
|
||||
"image_prefer_wide_gamut_setting_description": "Gebruik Display P3 vir kleinkiekies. Dit behou die lewendheid van beelde met wye kleurruimtes beter, maar beelde kan anders verskyn op ou apparate met 'n ou blaaierweergawe. sRGB-beelde gebruik steeds sRGB om kleurverskuiwings te voorkom.",
|
||||
"image_prefer_wide_gamut": "Verkies wye spektrum",
|
||||
"image_preview_description": "Mediumgrootte prent met gestroopte metadata, wat gebruik word wanneer 'n enkele bate bekyk word en vir masjienleer",
|
||||
"image_preview_quality_description": "Voorskou kwaliteit van 1-100. Hoër is beter, maar produseer groter lêers en kan app-reaksie verminder. Die stel van 'n lae waarde kan masjienleerkwaliteit beïnvloed.",
|
||||
"image_preview_title": "Voorskou Instellings",
|
||||
@@ -73,14 +72,7 @@
|
||||
"image_resolution": "Resolusie",
|
||||
"image_resolution_description": "Hoër resolusies kan meer detail bewaar, maar neem langer om te enkodeer, het groter lêergroottes en kan app-reaksie verminder.",
|
||||
"image_settings": "Prent Instellings",
|
||||
"image_settings_description": "Bestuur die kwaliteit en resolusie van gegenereerde beelde",
|
||||
"image_thumbnail_description": "Klein kleinkiekies sonder metadata, gebruik om groepe foto's soos die tydlyn te bekyk",
|
||||
"image_thumbnail_quality_description": "Kleinkiekiekwaliteit van 1-100. Hoër is beter, maar produseer groter lêers en kan die toepassing vertraag.",
|
||||
"image_thumbnail_title": "Kleinkiekie-instellings",
|
||||
"job_concurrency": "{job} gelyktydigheid",
|
||||
"job_created": "Taak gemaak",
|
||||
"job_not_concurrency_safe": "Hierdie taak kan nie gelyktydig uitgevoer word nie.",
|
||||
"job_settings": "Agtergrondtaakinstellings"
|
||||
"image_settings_description": "Bestuur die kwaliteit en resolusie van gegenereerde beelde"
|
||||
},
|
||||
"search_by_description": "Soek by beskrywing",
|
||||
"search_by_description_example": "Stapdag in Sapa"
|
||||
|
||||
@@ -1079,8 +1079,6 @@
|
||||
"remove_from_album": "Odstranit z alba",
|
||||
"remove_from_favorites": "Odstranit z oblíbených",
|
||||
"remove_from_shared_link": "Odstranit ze sdíleného odkazu",
|
||||
"remove_memory": "Odstranit vzpomínku",
|
||||
"remove_photo_from_memory": "Odstranit fotografii z této vzpomínky",
|
||||
"remove_url": "Odstranit URL",
|
||||
"remove_user": "Odebrat uživatele",
|
||||
"removed_api_key": "Odstraněn API klíč: {name}",
|
||||
@@ -1151,7 +1149,6 @@
|
||||
"searching_locales": "Vyhledávání jazyků...",
|
||||
"second": "Sekunda",
|
||||
"see_all_people": "Zobrazit všechny lidi",
|
||||
"select": "Vybrat",
|
||||
"select_album_cover": "Vybrat obal alba",
|
||||
"select_all": "Vybrat vše",
|
||||
"select_all_duplicates": "Vybrat všechny duplicity",
|
||||
@@ -1378,4 +1375,4 @@
|
||||
"yes": "Ano",
|
||||
"you_dont_have_any_shared_links": "Nemáte žádné sdílené odkazy",
|
||||
"zoom_image": "Zvětšit obrázek"
|
||||
}
|
||||
}
|
||||
16
i18n/da.json
16
i18n/da.json
@@ -41,7 +41,6 @@
|
||||
"backup_settings": "Backup-indstillinger",
|
||||
"backup_settings_description": "Administrer backupindstillinger for database",
|
||||
"check_all": "Tjek Alle",
|
||||
"cleanup": "Ryd op",
|
||||
"cleared_jobs": "Ryddet jobs til: {job}",
|
||||
"config_set_by_file": "konfigurationen er i øjeblikket indstillet af en konfigurations fil",
|
||||
"confirm_delete_library": "Er du sikker på, at du vil slette {library} bibliotek?",
|
||||
@@ -97,7 +96,7 @@
|
||||
"library_scanning_enable_description": "Aktiver periodisk biblioteksscanning",
|
||||
"library_settings": "Eksternt bibliotek",
|
||||
"library_settings_description": "Administrer eksterne biblioteksindstillinger",
|
||||
"library_tasks_description": "Scan eksterne biblioteker for nye og/eller ændrede mediefiler",
|
||||
"library_tasks_description": "Udfør biblioteksopgaver",
|
||||
"library_watching_enable_description": "Overvåg eksterne biblioteker for filændringer",
|
||||
"library_watching_settings": "Biblioteks overvågning (EKSPERIMENTEL)",
|
||||
"library_watching_settings_description": "Tjek automatisk for ændrede filer",
|
||||
@@ -132,7 +131,7 @@
|
||||
"machine_learning_smart_search_description": "Søg semantisk efter billeder ved hjælp af CLIP-indlejringer",
|
||||
"machine_learning_smart_search_enabled": "Aktiver smart søgning",
|
||||
"machine_learning_smart_search_enabled_description": "Hvis deaktiveret, vil billeder ikke blive kodet til smart søgning.",
|
||||
"machine_learning_url_description": "URL’en for maskinlæringsserveren. Hvis mere end én URL angives, vil hver server blive forsøgt én ad gangen, indtil en svarer succesfuldt, i rækkefølge fra første til sidste. Servere, der ikke svarer, vil midlertidigt blive ignoreret, indtil de kommer online igen.",
|
||||
"machine_learning_url_description": "URL på maskinlæringsserveren. Hvis der er angivet mere end én URL, hver server vil blive forsøgt en ad gangen, indtil en reagerer med succes, i rækkefølge fra første til sidste.",
|
||||
"manage_concurrency": "Administrer antallet af samtidige opgaver",
|
||||
"manage_log_settings": "Administrer logindstillinger",
|
||||
"map_dark_style": "Mørk tema",
|
||||
@@ -243,7 +242,7 @@
|
||||
"storage_template_hash_verification_enabled_description": "Slår hash-verifikation til, slå ikke dette fra med mindre du er sikker på dets konsekvenser",
|
||||
"storage_template_migration": "Lagringsskabelonmigration",
|
||||
"storage_template_migration_description": "Anvend den nuværende <link>{template}</link> på tidligere uploadede mediefiler",
|
||||
"storage_template_migration_info": "Lager-skabelonen vil konvertere alle filendelser til små bogstaver. Skabelonændringer vil kun gælde for nye mediefiler. For at anvende skabelonen retroaktivt på tidligere uploadede mediefiler skal du køre <link>{job}</link>.",
|
||||
"storage_template_migration_info": "Skabelonændringer vil kun gælde for nye mediefiler. For at anvende skabelonen retroaktivt på tidligere uploadede mediefiler skal du køre <link>{job}</link>.",
|
||||
"storage_template_migration_job": "Lager Skabelon Migreringsjob",
|
||||
"storage_template_more_details": "For flere detaljer om denne funktion, referer til <template-link>Lager Skabelonen</template-link> og dens <implications-link>implikationer</implications-link>",
|
||||
"storage_template_onboarding_description": "Når denne funktion er aktiveret, vil den automatisk organisere filer baseret på en brugerdefineret skabelon. På grund af stabilitetsproblemer er funktionen som standard slået fra. For mere information, se <link>dokumentation</link>.",
|
||||
@@ -394,7 +393,6 @@
|
||||
"allow_edits": "Tillad redigeringer",
|
||||
"allow_public_user_to_download": "Tillad offentlige brugere til at hente",
|
||||
"allow_public_user_to_upload": "Tillad offentlige brugere til at uploade",
|
||||
"alt_text_qr_code": "QR-kode billede",
|
||||
"anti_clockwise": "Mod uret",
|
||||
"api_key": "API-nøgle",
|
||||
"api_key_description": "Denne værdi vises kun én gang. Venligst kopiér den før du lukker vinduet.",
|
||||
@@ -891,7 +889,6 @@
|
||||
"month": "Måned",
|
||||
"more": "Mere",
|
||||
"moved_to_trash": "Flyttet til skraldespand",
|
||||
"mute_memories": "Dæmp minder",
|
||||
"my_albums": "Mine albummer",
|
||||
"name": "Navn",
|
||||
"name_or_nickname": "Navn eller kælenavn",
|
||||
@@ -987,7 +984,6 @@
|
||||
"permanently_deleted_asset": "Permanent slettet medie",
|
||||
"permanently_deleted_assets_count": "{count, plural, one {# aktiv} other {# aktiver}} permanent slettet",
|
||||
"person": "Person",
|
||||
"person_birthdate": "Født den {date}",
|
||||
"person_hidden": "{name}{hidden, select, true { (skjult)} other {}}",
|
||||
"photo_shared_all_users": "Det ser ud til, at du har delt dine billeder med alle brugere, eller også har du ikke nogen bruger at dele med.",
|
||||
"photos": "Billeder",
|
||||
@@ -1079,8 +1075,6 @@
|
||||
"remove_from_album": "Fjern fra album",
|
||||
"remove_from_favorites": "Fjern fra favoritter",
|
||||
"remove_from_shared_link": "Fjern fra delt link",
|
||||
"remove_memory": "Fjern minde",
|
||||
"remove_photo_from_memory": "Fjern foto fra dette minde",
|
||||
"remove_url": "Fjern URL",
|
||||
"remove_user": "Fjern bruger",
|
||||
"removed_api_key": "Fjernede API-nøgle: {name}",
|
||||
@@ -1151,7 +1145,6 @@
|
||||
"searching_locales": "Søger lokaler...",
|
||||
"second": "Sekund",
|
||||
"see_all_people": "Se alle personer",
|
||||
"select": "Vælg",
|
||||
"select_album_cover": "Vælg albumcover",
|
||||
"select_all": "Vælg alle",
|
||||
"select_all_duplicates": "Vælg alle dubletter",
|
||||
@@ -1307,7 +1300,6 @@
|
||||
"unlink_motion_video": "Fjern link til bevægelsesvideo",
|
||||
"unlink_oauth": "Frakobl OAuth",
|
||||
"unlinked_oauth_account": "Frakoblede OAuth-konto",
|
||||
"unmute_memories": "Ophæv dæmpning af minder",
|
||||
"unnamed_album": "Unavngivet album",
|
||||
"unnamed_album_delete_confirmation": "Er du sikker på, at du vil slette dette album?",
|
||||
"unnamed_share": "Unavngivet deling",
|
||||
@@ -1378,4 +1370,4 @@
|
||||
"yes": "Ja",
|
||||
"you_dont_have_any_shared_links": "Du har ikke nogen delte links",
|
||||
"zoom_image": "Zoom billede"
|
||||
}
|
||||
}
|
||||
@@ -1079,8 +1079,6 @@
|
||||
"remove_from_album": "Aus Album entfernen",
|
||||
"remove_from_favorites": "Aus Favoriten entfernen",
|
||||
"remove_from_shared_link": "Aus geteiltem Link entfernen",
|
||||
"remove_memory": "Erinnerung entfernen",
|
||||
"remove_photo_from_memory": "Foto aus dieser Erinnerung entfernen",
|
||||
"remove_url": "URL entfernen",
|
||||
"remove_user": "Nutzer entfernen",
|
||||
"removed_api_key": "API-Schlüssel {name} wurde entfernt",
|
||||
@@ -1151,7 +1149,6 @@
|
||||
"searching_locales": "Suche nach Orten...",
|
||||
"second": "Sekunde",
|
||||
"see_all_people": "Alle Personen anzeigen",
|
||||
"select": "Auswählen",
|
||||
"select_album_cover": "Album-Cover auswählen",
|
||||
"select_all": "Alles auswählen",
|
||||
"select_all_duplicates": "Alle Duplikate auswählen",
|
||||
@@ -1378,4 +1375,4 @@
|
||||
"yes": "Ja",
|
||||
"you_dont_have_any_shared_links": "Du hast keine geteilten Links",
|
||||
"zoom_image": "Bild vergrößern"
|
||||
}
|
||||
}
|
||||
11
i18n/el.json
11
i18n/el.json
@@ -41,7 +41,6 @@
|
||||
"backup_settings": "Ρυθμίσεις Αντιγράφων Ασφαλείας",
|
||||
"backup_settings_description": "Διαχείρηση ρυθμίσεων των αντιγράφων ασφαλείας της βάσης δεδομένων",
|
||||
"check_all": "Έλεγχος Όλων",
|
||||
"cleanup": "Εκκαθάριση",
|
||||
"cleared_jobs": "Εκκαθαρίστηκαν οι εργασίες για: {job}",
|
||||
"config_set_by_file": "Η παραμετροποίηση γίνεται, προς το παρόν, μέσω ενός αρχείου παραμέτρων",
|
||||
"confirm_delete_library": "Είστε βέβαιοι ότι θέλετε να διαγράψετε τη βιβλιοθήκη {library};",
|
||||
@@ -394,7 +393,6 @@
|
||||
"allow_edits": "Επιτρέψτε τις τροποποιήσεις",
|
||||
"allow_public_user_to_download": "Επιτρέψτε σε δημόσιο χρήστη να κατεβάσει",
|
||||
"allow_public_user_to_upload": "Επιτρέψτε στον δημόσιο χρήστη να ανεβάσει",
|
||||
"alt_text_qr_code": "Εικόνα κωδικού QR",
|
||||
"anti_clockwise": "Αντίθετα με τη φορά του ρολογιού",
|
||||
"api_key": "Κλειδί API",
|
||||
"api_key_description": "Αυτή η τιμή θα εμφανιστεί μόνο μία φορά. Παρακαλώ βεβαιωθείτε ότι την έχετε αντιγράψει πριν κλείσετε το παράθυρο.",
|
||||
@@ -891,7 +889,6 @@
|
||||
"month": "Μήνας",
|
||||
"more": "Περισσότερα",
|
||||
"moved_to_trash": "Μετακινήθηκε στον κάδο απορριμμάτων",
|
||||
"mute_memories": "Σίγαση Αναμνήσεων",
|
||||
"my_albums": "Τα άλμπουμ μου",
|
||||
"name": "Όνομα",
|
||||
"name_or_nickname": "Όνομα ή ψευδώνυμο",
|
||||
@@ -987,7 +984,6 @@
|
||||
"permanently_deleted_asset": "Οριστικά διαγραμμένο στοιχείο",
|
||||
"permanently_deleted_assets_count": "Οριστική διαγραφή {count, plural, one {# στοιχείου} other {# στοιχείων}}",
|
||||
"person": "Άτομο",
|
||||
"person_birthdate": "Γεννηθείς στις {date}",
|
||||
"person_hidden": "{name}{hidden, select, true { (κρυφό)} other {}}",
|
||||
"photo_shared_all_users": "Φαίνεται ότι μοιραστήκατε τις φωτογραφίες σας με όλους τους χρήστες ή δεν έχετε κανέναν χρήστη για κοινή χρήση.",
|
||||
"photos": "Φωτογραφίες",
|
||||
@@ -1079,8 +1075,6 @@
|
||||
"remove_from_album": "Αφαίρεση από το άλμπουμ",
|
||||
"remove_from_favorites": "Αφαίρεση από τα αγαπημένα",
|
||||
"remove_from_shared_link": "Αφαίρεση από τον κοινόχρηστο σύνδεσμο",
|
||||
"remove_memory": "Αφαίρεση ανάμνησης",
|
||||
"remove_photo_from_memory": "Αφαίρεση φωτογραφίας από την ανάμνηση",
|
||||
"remove_url": "Αφαίρεση Συνδέσμου",
|
||||
"remove_user": "Αφαίρεση χρήστη",
|
||||
"removed_api_key": "Αφαιρέθηκε το API Key: {name}",
|
||||
@@ -1097,7 +1091,6 @@
|
||||
"repository": "Αποθετήριο",
|
||||
"require_password": "Απαιτείται κωδικός πρόσβασης",
|
||||
"require_user_to_change_password_on_first_login": "Ο χρήστης απαιτείται να αλλάξει τον κωδικό πρόσβασής του κατά την πρώτη σύνδεση",
|
||||
"rescan": "Εκ νέου σάρωση",
|
||||
"reset": "Επαναφορά",
|
||||
"reset_password": "Επαναφορά κωδικού πρόσβασης",
|
||||
"reset_people_visibility": "Επαναφορά προβολής ατόμων",
|
||||
@@ -1151,7 +1144,6 @@
|
||||
"searching_locales": "Αναζήτηση τοποθεσιών...",
|
||||
"second": "Δευτερόλεπτο",
|
||||
"see_all_people": "Προβολή όλων των ατόμων",
|
||||
"select": "Επιλογή",
|
||||
"select_album_cover": "Επιλέξτε εξώφυλλο άλμπουμ",
|
||||
"select_all": "Επιλογή όλων",
|
||||
"select_all_duplicates": "Επιλογή όλων των διπλότυπων",
|
||||
@@ -1360,7 +1352,6 @@
|
||||
"view_all": "Προβολή Όλων",
|
||||
"view_all_users": "Προβολή όλων των χρηστών",
|
||||
"view_in_timeline": "Προβολή στο χρονοδιάγραμμα",
|
||||
"view_link": "Προβολή σύνδεσμου",
|
||||
"view_links": "Προβολή συνδέσμων",
|
||||
"view_name": "Προβολή",
|
||||
"view_next_asset": "Προβολή επόμενου στοιχείου",
|
||||
@@ -1377,4 +1368,4 @@
|
||||
"yes": "Ναι",
|
||||
"you_dont_have_any_shared_links": "Δεν έχετε κοινόχρηστους συνδέσμους",
|
||||
"zoom_image": "Ζουμ Εικόνας"
|
||||
}
|
||||
}
|
||||
@@ -1082,9 +1082,7 @@
|
||||
"remove_url": "Remove URL",
|
||||
"remove_user": "Remove user",
|
||||
"removed_api_key": "Removed API Key: {name}",
|
||||
"remove_memory": "Remove memory",
|
||||
"removed_memory": "Removed memory",
|
||||
"remove_photo_from_memory": "Remove photo from this memory",
|
||||
"removed_photo_from_memory": "Removed photo from memory",
|
||||
"removed_from_archive": "Removed from archive",
|
||||
"removed_from_favorites": "Removed from favorites",
|
||||
|
||||
@@ -1079,8 +1079,6 @@
|
||||
"remove_from_album": "Eliminar del álbum",
|
||||
"remove_from_favorites": "Quitar de favoritos",
|
||||
"remove_from_shared_link": "Eliminar desde enlace compartido",
|
||||
"remove_memory": "Quitar memoria",
|
||||
"remove_photo_from_memory": "Quitar foto de esta memoria",
|
||||
"remove_url": "Eliminar URL",
|
||||
"remove_user": "Eliminar usuario",
|
||||
"removed_api_key": "Clave API eliminada: {name}",
|
||||
@@ -1151,7 +1149,6 @@
|
||||
"searching_locales": "Buscando sitios...",
|
||||
"second": "Segundo",
|
||||
"see_all_people": "Ver todas las personas",
|
||||
"select": "Selecciona",
|
||||
"select_album_cover": "Seleccionar portada del álbum",
|
||||
"select_all": "Seleccionar todo",
|
||||
"select_all_duplicates": "Seleccionar todos los duplicados",
|
||||
@@ -1378,4 +1375,4 @@
|
||||
"yes": "Sí",
|
||||
"you_dont_have_any_shared_links": "No tienes ningún enlace compartido",
|
||||
"zoom_image": "Acercar Imagen"
|
||||
}
|
||||
}
|
||||
@@ -1079,8 +1079,6 @@
|
||||
"remove_from_album": "Eemalda albumist",
|
||||
"remove_from_favorites": "Eemalda lemmikutest",
|
||||
"remove_from_shared_link": "Eemalda jagatud lingist",
|
||||
"remove_memory": "Eemalda mälestus",
|
||||
"remove_photo_from_memory": "Eemalda foto sellest mälestusest",
|
||||
"remove_url": "Eemalda URL",
|
||||
"remove_user": "Eemalda kasutaja",
|
||||
"removed_api_key": "API võti eemaldatud: {name}",
|
||||
@@ -1151,7 +1149,6 @@
|
||||
"searching_locales": "Lokaatide otsimine...",
|
||||
"second": "Sekund",
|
||||
"see_all_people": "Vaata kõiki isikuid",
|
||||
"select": "Vali",
|
||||
"select_album_cover": "Vali albumi kaanepilt",
|
||||
"select_all": "Vali kõik",
|
||||
"select_all_duplicates": "Vali kõik duplikaadid",
|
||||
@@ -1378,4 +1375,4 @@
|
||||
"yes": "Jah",
|
||||
"you_dont_have_any_shared_links": "Sul pole ühtegi jagatud linki",
|
||||
"zoom_image": "Suumi pilti"
|
||||
}
|
||||
}
|
||||
@@ -987,7 +987,6 @@
|
||||
"permanently_deleted_asset": "Média supprimé définitivement",
|
||||
"permanently_deleted_assets_count": "{count, plural, one {# média définitivement supprimé} other {# médias définitivement supprimés}}",
|
||||
"person": "Personne",
|
||||
"person_birthdate": "Né(e) le {date}",
|
||||
"person_hidden": "{name}{hidden, select, true { (caché)} other {}}",
|
||||
"photo_shared_all_users": "Il semble que vous ayez partagé vos photos avec tous les utilisateurs ou que vous n'ayez aucun utilisateur avec qui les partager.",
|
||||
"photos": "Photos",
|
||||
@@ -1079,8 +1078,6 @@
|
||||
"remove_from_album": "Supprimer de l'album",
|
||||
"remove_from_favorites": "Supprimer des favoris",
|
||||
"remove_from_shared_link": "Supprimer des liens partagés",
|
||||
"remove_memory": "Supprimer le souvenir",
|
||||
"remove_photo_from_memory": "Supprimer la photo de ce souvenir",
|
||||
"remove_url": "Supprimer l'URL",
|
||||
"remove_user": "Supprimer l'utilisateur",
|
||||
"removed_api_key": "Clé API supprimée : {name}",
|
||||
@@ -1151,7 +1148,6 @@
|
||||
"searching_locales": "Recherche des paramètres régionaux...",
|
||||
"second": "Seconde",
|
||||
"see_all_people": "Voir toutes les personnes",
|
||||
"select": "Sélectionner",
|
||||
"select_album_cover": "Sélectionner la couverture d'album",
|
||||
"select_all": "Tout sélectionner",
|
||||
"select_all_duplicates": "Sélectionner tous les doublons",
|
||||
@@ -1378,4 +1374,4 @@
|
||||
"yes": "Oui",
|
||||
"you_dont_have_any_shared_links": "Vous n'avez aucun lien partagé",
|
||||
"zoom_image": "Zoomer"
|
||||
}
|
||||
}
|
||||
@@ -987,7 +987,6 @@
|
||||
"permanently_deleted_asset": "נכס נמחק לצמיתות",
|
||||
"permanently_deleted_assets_count": "{count, plural, one {נכס # נמחק} other {# נכסים נמחקו}} לצמיתות",
|
||||
"person": "אדם",
|
||||
"person_birthdate": "נולד בתאריך {date}",
|
||||
"person_hidden": "{name}{hidden, select, true { (מוסתר)} other {}}",
|
||||
"photo_shared_all_users": "נראה שאת/ה שיתפת את התמונות שלך עם כל המשתמשים או שאין לך אף משתמש לשתף איתו.",
|
||||
"photos": "תמונות",
|
||||
@@ -1079,8 +1078,6 @@
|
||||
"remove_from_album": "הסר מאלבום",
|
||||
"remove_from_favorites": "הסר מהמועדפים",
|
||||
"remove_from_shared_link": "הסר מקישור משותף",
|
||||
"remove_memory": "הסר זיכרון",
|
||||
"remove_photo_from_memory": "הסר תמונה מזיכרון זה",
|
||||
"remove_url": "הסר URL",
|
||||
"remove_user": "הסר משתמש",
|
||||
"removed_api_key": "מפתח API הוסר: {name}",
|
||||
@@ -1151,7 +1148,6 @@
|
||||
"searching_locales": "מחפש אזורי שפה...",
|
||||
"second": "שנייה",
|
||||
"see_all_people": "ראה את כל האנשים",
|
||||
"select": "בחר",
|
||||
"select_album_cover": "בחר עטיפת אלבום",
|
||||
"select_all": "בחר הכל",
|
||||
"select_all_duplicates": "בחר את כל הכפילויות",
|
||||
@@ -1378,4 +1374,4 @@
|
||||
"yes": "כן",
|
||||
"you_dont_have_any_shared_links": "אין לך קישורים משותפים",
|
||||
"zoom_image": "זום לתמונה"
|
||||
}
|
||||
}
|
||||
@@ -29,17 +29,11 @@
|
||||
"added_to_favorites_count": "पसंदीदा में {count, number} जोड़ा गया",
|
||||
"admin": {
|
||||
"add_exclusion_pattern_description": "बहिष्करण पैटर्न जोड़ें. *, **, और ? का उपयोग करके ग्लोबिंग करना समर्थित है। \"Raw\" नामक किसी भी निर्देशिका की सभी फ़ाइलों को अनदेखा करने के लिए, \"**/Raw/**\" का उपयोग करें। \".tif\" से समाप्त होने वाली सभी फ़ाइलों को अनदेखा करने के लिए, \"**/*.tif\" का उपयोग करें। किसी पूर्ण पथ को अनदेखा करने के लिए, \"/path/to/ignore/**\" का उपयोग करें।",
|
||||
"asset_offline_description": "यह बाहरी लाइब्रेरी एसेट अब डिस्क पर मौजूद नहीं है और इसे ट्रैश में डाल दिया गया है। यदि फ़ाइल को लाइब्रेरी के भीतर कहीं ले जाया गया था, तो नई संबंधित एसेट के लिए अपनी टाइमलाइन देखें। इस एसेट को वापस पाने के लिए, कृपया सुनिश्चित करें कि नीचे दिए गए फ़ाइल पथ को इम्मिच द्वारा एक्सेस किया जा सकता है और फिर लाइब्रेरी को स्कैन करें।",
|
||||
"authentication_settings": "प्रमाणीकरण सेटिंग्स",
|
||||
"authentication_settings_description": "पासवर्ड, OAuth और अन्य प्रमाणीकरण सेटिंग्स प्रबंधित करें",
|
||||
"authentication_settings_disable_all": "क्या आप वाकई सभी लॉगिन विधियों को अक्षम करना चाहते हैं? लॉगिन पूरी तरह से अक्षम कर दिया जाएगा।",
|
||||
"authentication_settings_reenable": "पुनः सक्षम करने के लिए, <link>Server Command</link> का प्रयोग करे।",
|
||||
"background_task_job": "पृष्ठभूमि कार्य",
|
||||
"backup_database": "बैकअप डाटाबेस",
|
||||
"backup_database_enable_description": "बैकअप डेटाबेस सक्रिय करें",
|
||||
"backup_keep_last_amount": "पूर्व बैकअप क्षमता",
|
||||
"backup_settings": "बैकअप सेटिंग्स",
|
||||
"backup_settings_description": "डेटाबेस बैकअप सेटिंग्स प्रबंधन",
|
||||
"check_all": "सभी चेक करें",
|
||||
"cleared_jobs": "{job}: के लिए कार्य साफ़ कर दिए गए",
|
||||
"config_set_by_file": "Config वर्तमान में एक config फ़ाइल द्वारा सेट किया गया है",
|
||||
@@ -48,8 +42,6 @@
|
||||
"confirm_email_below": "पुष्टि करने के लिए नीचे \"{email}\" टाइप करें",
|
||||
"confirm_reprocess_all_faces": "क्या आप वाकई सभी चेहरों को दोबारा संसाधित करना चाहते हैं? इससे नामित लोग भी साफ हो जायेंगे।",
|
||||
"confirm_user_password_reset": "क्या आप वाकई {user} का पासवर्ड रीसेट करना चाहते हैं?",
|
||||
"create_job": "जॉब बनाएँ",
|
||||
"cron_expression": "क्रॉन अभिव्यक्ति",
|
||||
"disable_login": "लॉगिन अक्षम करें",
|
||||
"duplicate_detection_job_description": "समान छवियों का पता लगाने के लिए संपत्तियों पर मशीन लर्निंग चलाएं। यह कार्यक्षमता स्मार्ट खोज पर निर्भर करती है",
|
||||
"exclusion_pattern_description": "Exclusion पैटर्न आपको अपनी लाइब्रेरी को स्कैन करते समय फ़ाइलों और फ़ोल्डरों को अनदेखा करने देता है। यह उपयोगी है यदि आपके पास ऐसे फ़ोल्डर हैं जिनमें ऐसी फ़ाइलें हैं जिन्हें आप आयात नहीं करना चाहते हैं, जैसे RAW फ़ाइलें।",
|
||||
@@ -1101,7 +1093,6 @@
|
||||
"view_album": "एल्बम देखें",
|
||||
"view_all": "सभी को देखें",
|
||||
"view_all_users": "सभी उपयोगकर्ताओं को देखें",
|
||||
"view_in_timeline": "टाइमलाइन में देखें",
|
||||
"view_links": "लिंक देखें",
|
||||
"view_next_asset": "अगली संपत्ति देखें",
|
||||
"view_previous_asset": "पिछली संपत्ति देखें",
|
||||
|
||||
10
i18n/hu.json
10
i18n/hu.json
@@ -149,7 +149,7 @@
|
||||
"map_settings_description": "Térkép beállítások kezelése",
|
||||
"map_style_description": "Egy style.json térképtémára mutató URL cím",
|
||||
"memory_cleanup_job": "Memória takarítás",
|
||||
"memory_generate_job": "Emlék generálálsa",
|
||||
"memory_generate_job": "Emlék létrehozása",
|
||||
"metadata_extraction_job": "Metaadatok kinyerése",
|
||||
"metadata_extraction_job_description": "Metaadat információk (pl. GPS, arcok és felbontás) kinyerése minden elemből",
|
||||
"metadata_faces_import_setting": "Arc importálás engedélyezése",
|
||||
@@ -243,7 +243,7 @@
|
||||
"storage_template_hash_verification_enabled_description": "Engedélyezi a hash-érték ellenőrzést - csak akkor kapcsold ki, ha tisztában vagy a következményekkel",
|
||||
"storage_template_migration": "Tárhely sablon migrálása",
|
||||
"storage_template_migration_description": "A jelenlegi <link>{template}</link> alkalmazása a már feltöltött elemekre",
|
||||
"storage_template_migration_info": "A sablon az összes kiterjesztést kisbetűssé alakítja át. A megváltozott sablon csak az újonnan feltöltött elemekre vonatkozik. A korábbi elemek visszamenőleges áthelyezéséhez ezt futtasd: <link>{job}</link>.",
|
||||
"storage_template_migration_info": "A megváltozott sablon csak az újonnan feltöltött elemekre vonatkozik. A korábbi elemek visszamenőleges áthelyezéséhez ezt futtasd: <link>{job}</link>.",
|
||||
"storage_template_migration_job": "Tárhely Sablon Migrációja",
|
||||
"storage_template_more_details": "További részletekért erről a funkcióról lásd a <template-link>Tárhely Sablon</template-link> és annak <implications-link>következményeit</implications-link> a dokumentációban",
|
||||
"storage_template_onboarding_description": "Ha ez a funkció engedélyezve van, akkor a fájlokat automatikusan az egyéni sablon alapján rendszerezi el. Stabilitási problémák miatt a funkció alapértelmezés szerint ki van kapcsolva. További információkért lásd a <link>dokumentációt</link>.",
|
||||
@@ -987,7 +987,6 @@
|
||||
"permanently_deleted_asset": "Elem véglegesen törölve",
|
||||
"permanently_deleted_assets_count": "{count, plural, other {# elem}} véglegesen törölve",
|
||||
"person": "Személy",
|
||||
"person_birthdate": "Született: {date}",
|
||||
"person_hidden": "{name}{hidden, select, true { (rejtett)} other {}}",
|
||||
"photo_shared_all_users": "Úgy tűnik, hogy már mindenkivel megosztottad a fényképeidet, vagy nincs senki, akivel meg tudnád osztani.",
|
||||
"photos": "Fényképek",
|
||||
@@ -1079,8 +1078,6 @@
|
||||
"remove_from_album": "Eltávolítás az albumból",
|
||||
"remove_from_favorites": "Eltávolítás a kedvencekből",
|
||||
"remove_from_shared_link": "Eltávolítás a megosztott linkből",
|
||||
"remove_memory": "Emlék eltávolítása",
|
||||
"remove_photo_from_memory": "Kép eltávolítása az emlékből",
|
||||
"remove_url": "URL eltávolítása",
|
||||
"remove_user": "Felhasználó eltávolítása",
|
||||
"removed_api_key": "API Kulcs eltávolítva: {name}",
|
||||
@@ -1151,7 +1148,6 @@
|
||||
"searching_locales": "Helyszín keresése...",
|
||||
"second": "Másodperc",
|
||||
"see_all_people": "Minden személy megtekintése",
|
||||
"select": "Kiválsztás",
|
||||
"select_album_cover": "Albumborító kiválasztása",
|
||||
"select_all": "Összes kijelölése",
|
||||
"select_all_duplicates": "Minden duplikátum kijelölése",
|
||||
@@ -1378,4 +1374,4 @@
|
||||
"yes": "Igen",
|
||||
"you_dont_have_any_shared_links": "Nincsenek megosztott linkjeid",
|
||||
"zoom_image": "Kép Nagyítása"
|
||||
}
|
||||
}
|
||||
@@ -987,7 +987,6 @@
|
||||
"permanently_deleted_asset": "Aset dihapus secara permanen",
|
||||
"permanently_deleted_assets_count": "{count, plural, one {# aset} other {# aset}} dihapus secara permanen",
|
||||
"person": "Orang",
|
||||
"person_birthdate": "Lahir pada {date}",
|
||||
"person_hidden": "{name}{hidden, select, true { (tersembunyi)} other {}}",
|
||||
"photo_shared_all_users": "Sepertinya Anda membagikan foto Anda dengan semua pengguna atau Anda tidak memiliki pengguna siapa pun untuk dibagikan.",
|
||||
"photos": "Foto",
|
||||
@@ -1079,8 +1078,6 @@
|
||||
"remove_from_album": "Hapus dari album",
|
||||
"remove_from_favorites": "Hapus dari favorit",
|
||||
"remove_from_shared_link": "Hapus dari tautan terbagi",
|
||||
"remove_memory": "Hapus kenangan",
|
||||
"remove_photo_from_memory": "Hapus foto dari kenangan ini",
|
||||
"remove_url": "Hapus URL",
|
||||
"remove_user": "Keluarkan pengguna",
|
||||
"removed_api_key": "Kunci API Dihapus: {name}",
|
||||
@@ -1151,7 +1148,6 @@
|
||||
"searching_locales": "Mencari lokal...",
|
||||
"second": "Detik",
|
||||
"see_all_people": "Lihat semua orang",
|
||||
"select": "Pilih",
|
||||
"select_album_cover": "Pilih kover album",
|
||||
"select_all": "Pilih semua",
|
||||
"select_all_duplicates": "Pilih semua duplikat",
|
||||
@@ -1378,4 +1374,4 @@
|
||||
"yes": "Ya",
|
||||
"you_dont_have_any_shared_links": "Anda tidak memiliki tautan terbagi",
|
||||
"zoom_image": "Perbesar Gambar"
|
||||
}
|
||||
}
|
||||
12
i18n/it.json
12
i18n/it.json
@@ -886,7 +886,7 @@
|
||||
"merged_people_count": "{count, plural, one {Unita # persona} other {Unite # persone}}",
|
||||
"minimize": "Minimizza",
|
||||
"minute": "Minuto",
|
||||
"missing": "Mancanti",
|
||||
"missing": "Mancante",
|
||||
"model": "Modello",
|
||||
"month": "Mese",
|
||||
"more": "Di più",
|
||||
@@ -987,7 +987,6 @@
|
||||
"permanently_deleted_asset": "Asset eliminato definitivamente",
|
||||
"permanently_deleted_assets_count": "Cancellati {count, plural, one {# asset} other {# assets}} definitivamente",
|
||||
"person": "Persona",
|
||||
"person_birthdate": "Nato il {date}",
|
||||
"person_hidden": "{name}{hidden, select, true { (nascosto)} other {}}",
|
||||
"photo_shared_all_users": "Sembra che tu abbia condiviso le foto con tutti gli utenti, oppure che non ci siano utenti con i quali condividerle.",
|
||||
"photos": "Foto",
|
||||
@@ -998,7 +997,7 @@
|
||||
"place": "Posizione",
|
||||
"places": "Luoghi",
|
||||
"places_count": "{count, plural, one {{count, number} Luogo} other {{count, number} Places}}",
|
||||
"play": "Riproduci",
|
||||
"play": "Avvia",
|
||||
"play_memories": "Avvia ricordi",
|
||||
"play_motion_photo": "Avvia Foto in movimento",
|
||||
"play_or_pause_video": "Avvia o metti in pausa il video",
|
||||
@@ -1079,8 +1078,6 @@
|
||||
"remove_from_album": "Rimuovere dall'album",
|
||||
"remove_from_favorites": "Rimuovi dai preferiti",
|
||||
"remove_from_shared_link": "Rimuovi dal link condiviso",
|
||||
"remove_memory": "Rimuovi ricordo",
|
||||
"remove_photo_from_memory": "Rimuovi foto da questo ricordo",
|
||||
"remove_url": "Rimuovi URL",
|
||||
"remove_user": "Rimuovi utente",
|
||||
"removed_api_key": "Rimossa chiave API: {name}",
|
||||
@@ -1151,7 +1148,6 @@
|
||||
"searching_locales": "Cerca localizzazioni...",
|
||||
"second": "Secondo",
|
||||
"see_all_people": "Vedi tutte le persone",
|
||||
"select": "Seleziona",
|
||||
"select_album_cover": "Seleziona copertina album",
|
||||
"select_all": "Seleziona tutto",
|
||||
"select_all_duplicates": "Seleziona tutti i duplicati",
|
||||
@@ -1242,7 +1238,7 @@
|
||||
"stack_selected_photos": "Impila foto selezionate",
|
||||
"stacked_assets_count": "{count, plural, one {Raggruppato # asset} other {Raggruppati # asset}}",
|
||||
"stacktrace": "Traccia dell'errore",
|
||||
"start": "Avvia",
|
||||
"start": "Inizio",
|
||||
"start_date": "Data di inizio",
|
||||
"state": "Provincia",
|
||||
"status": "Stato",
|
||||
@@ -1378,4 +1374,4 @@
|
||||
"yes": "Si",
|
||||
"you_dont_have_any_shared_links": "Non è presente alcun link condiviso",
|
||||
"zoom_image": "Ingrandisci immagine"
|
||||
}
|
||||
}
|
||||
68
i18n/lv.json
68
i18n/lv.json
@@ -13,7 +13,7 @@
|
||||
"add_a_location": "Pievienot atrašanās vietu",
|
||||
"add_a_name": "Pievienot vārdu",
|
||||
"add_a_title": "Pievienot virsrakstu",
|
||||
"add_exclusion_pattern": "Pievienot izslēgšanas šablonu",
|
||||
"add_exclusion_pattern": "Pievienot izņēmuma šablonu",
|
||||
"add_import_path": "Pievienot importa ceļu",
|
||||
"add_location": "Pievienot lokāciju",
|
||||
"add_more_users": "Pievienot vēl lietotājus",
|
||||
@@ -30,11 +30,10 @@
|
||||
"admin": {
|
||||
"add_exclusion_pattern_description": "Pievienojiet izlaišanas shēmas. Aizstājējzīmju izmantoša *, **, un ? tiek atbalstīta. Lai ignorētu visus failus jebkurā direktorijā ar nosaukumu “RAW”, izmantojiet “**/RAW/**”. Lai ignorētu visus failus, kas beidzas ar “. tif”, izmantojiet “**/*. tif”. Lai ignorētu absolūto ceļu, izmantojiet “/path/to/ignore/**”.",
|
||||
"authentication_settings": "Autentifikācijas iestatījumi",
|
||||
"authentication_settings_description": "Paroļu, OAuth un citu autentifikācijas iestatījumu pārvaldība",
|
||||
"authentication_settings_description": "Pārvaldīt paroles, OAuth un citus autentifikācijas iestatījumus",
|
||||
"authentication_settings_disable_all": "Vai tiešām vēlaties atspējot visas pieteikšanās metodes? Pieteikšanās tiks pilnībā atspējota.",
|
||||
"authentication_settings_reenable": "Lai atkārtoti iespējotu, izmantojiet <link>Servera Komandu</link>.",
|
||||
"background_task_job": "Fona Uzdevumi",
|
||||
"backup_settings_description": "Datubāzes dublēšanas iestatījumu pārvaldība",
|
||||
"check_all": "Pārbaudīt Visu",
|
||||
"cleared_jobs": "Notīrīti uzdevumi priekš: {job}",
|
||||
"config_set_by_file": "Konfigurāciju pašlaik iestata konfigurācijas fails",
|
||||
@@ -62,14 +61,14 @@
|
||||
"image_thumbnail_title": "Sīktēlu iestatījumi",
|
||||
"job_created": "Uzdevums izveidots",
|
||||
"job_settings": "Uzdevumu iestatījumi",
|
||||
"job_settings_description": "Uzdevumu izpildes vienlaicīguma pārvaldība",
|
||||
"job_settings_description": "Pārvaldīt uzdevumu izpildes vienlaicīgumu",
|
||||
"job_status": "Uzdevumu statuss",
|
||||
"library_deleted": "Bibliotēka dzēsta",
|
||||
"library_scanning": "",
|
||||
"library_scanning_description": "",
|
||||
"library_scanning_enable_description": "",
|
||||
"library_settings": "",
|
||||
"library_settings_description": "Ārējo bibliotēku iestatījumu pārvaldība",
|
||||
"library_settings_description": "",
|
||||
"library_tasks_description": "",
|
||||
"library_watching_enable_description": "",
|
||||
"library_watching_settings": "",
|
||||
@@ -96,33 +95,28 @@
|
||||
"machine_learning_min_recognized_faces": "",
|
||||
"machine_learning_min_recognized_faces_description": "",
|
||||
"machine_learning_settings": "Mašīnmācīšanās iestatījumi",
|
||||
"machine_learning_settings_description": "Mašīnmācīšanās funkciju un iestatījumu pārvaldība",
|
||||
"machine_learning_settings_description": "",
|
||||
"machine_learning_smart_search": "Viedā meklēšana",
|
||||
"machine_learning_smart_search_description": "",
|
||||
"machine_learning_smart_search_enabled_description": "",
|
||||
"machine_learning_url_description": "Mašīnmācīšanās servera URL",
|
||||
"manage_concurrency": "Vienlaicīgas darbības pārvaldība",
|
||||
"manage_log_settings": "Žurnāla iestatījumu pārvaldība",
|
||||
"manage_log_settings": "",
|
||||
"map_dark_style": "",
|
||||
"map_enable_description": "",
|
||||
"map_gps_settings": "Kartes un GPS iestatījumi",
|
||||
"map_gps_settings_description": "Karšu un GPS (apgrieztās ģeokodēšanas) iestatījumu pārvaldība",
|
||||
"map_gps_settings_description": "Pārvaldīt karšu un GPS (apgrieztās ģeokodēšanas) iestatījumus",
|
||||
"map_light_style": "",
|
||||
"map_manage_reverse_geocoding_settings": "<link>Reversās ģeokodēšanas</link> iestatījumu pārvaldība",
|
||||
"map_reverse_geocoding": "",
|
||||
"map_reverse_geocoding_enable_description": "",
|
||||
"map_reverse_geocoding_settings": "",
|
||||
"map_settings": "Karte",
|
||||
"map_settings_description": "Kartes iestatījumu pārvaldība",
|
||||
"map_settings_description": "",
|
||||
"map_style_description": "",
|
||||
"metadata_extraction_job": "Metadatu iegūšana",
|
||||
"metadata_extraction_job_description": "",
|
||||
"metadata_settings": "Metadatu iestatījumi",
|
||||
"metadata_settings_description": "Metadatu iestatījumu pārvaldība",
|
||||
"migration_job": "Migrācija",
|
||||
"migration_job_description": "",
|
||||
"no_paths_added": "Nav pievienots neviens ceļš",
|
||||
"no_pattern_added": "Nav pievienots neviens izslēgšanas šablons",
|
||||
"note_cannot_be_changed_later": "PIEZĪME: Vēlāk to vairs nevar mainīt!",
|
||||
"notification_email_from_address": "No adreses",
|
||||
"notification_email_from_address_description": "Sūtītāja e-pasta adrese, piemēram: “Immich foto serveris <noreply@example.com>”",
|
||||
@@ -139,7 +133,7 @@
|
||||
"notification_email_username_description": "",
|
||||
"notification_enable_email_notifications": "",
|
||||
"notification_settings": "Paziņojumu iestatījumi",
|
||||
"notification_settings_description": "Paziņojumu iestatījumu, tostarp e-pasta, pārvaldība",
|
||||
"notification_settings_description": "",
|
||||
"oauth_auto_launch": "",
|
||||
"oauth_auto_launch_description": "",
|
||||
"oauth_auto_register": "",
|
||||
@@ -156,17 +150,17 @@
|
||||
"oauth_profile_signing_algorithm_description": "Lietotāja profila parakstīšanai izmantotais algoritms.",
|
||||
"oauth_scope": "",
|
||||
"oauth_settings": "OAuth",
|
||||
"oauth_settings_description": "OAuth pieteikšanās iestatījumu pārvaldība",
|
||||
"oauth_settings_description": "",
|
||||
"oauth_signing_algorithm": "Parakstīšanas algoritms",
|
||||
"oauth_storage_label_claim": "",
|
||||
"oauth_storage_label_claim_description": "",
|
||||
"oauth_storage_quota_claim": "",
|
||||
"oauth_storage_quota_claim_description": "",
|
||||
"oauth_storage_quota_default": "Noklusējuma krātuves kvota (GiB)",
|
||||
"oauth_storage_quota_default": "",
|
||||
"oauth_storage_quota_default_description": "",
|
||||
"password_enable_description": "Pieteikšanās ar e-pasta adresi un paroli",
|
||||
"password_settings": "Pieteikšanās ar paroli",
|
||||
"password_settings_description": "Pieteikšanās ar paroli iestatījumu pārvaldība",
|
||||
"password_settings_description": "Pārvaldīt pieteikšanās ar paroli iestatījumus",
|
||||
"person_cleanup_job": "Personu tīrīšana",
|
||||
"quota_size_gib": "Kvotas izmērs (GiB)",
|
||||
"registration": "Administratora reģistrācija",
|
||||
@@ -177,27 +171,23 @@
|
||||
"server_external_domain_settings": "",
|
||||
"server_external_domain_settings_description": "",
|
||||
"server_settings": "Servera iestatījumi",
|
||||
"server_settings_description": "Servera iestatījumu pārvaldība",
|
||||
"server_settings_description": "Pārvaldīt servera iestatījumus",
|
||||
"server_welcome_message": "",
|
||||
"server_welcome_message_description": "",
|
||||
"sidecar_job_description": "",
|
||||
"slideshow_duration_description": "",
|
||||
"smart_search_job_description": "",
|
||||
"storage_template_date_time_sample": "Laika paraugs {date}",
|
||||
"storage_template_enable_description": "",
|
||||
"storage_template_hash_verification_enabled": "",
|
||||
"storage_template_hash_verification_enabled_description": "",
|
||||
"storage_template_migration": "Krātuves veidņu migrācija",
|
||||
"storage_template_migration_job": "Krātuves veidņu migrācijas uzdevums",
|
||||
"storage_template_settings": "Krātuves veidne",
|
||||
"storage_template_migration_job": "",
|
||||
"storage_template_settings": "",
|
||||
"storage_template_settings_description": "",
|
||||
"system_settings": "Sistēmas iestatījumi",
|
||||
"template_email_settings_description": "Pielāgotu e-pasta paziņojumu veidņu pārvaldība",
|
||||
"template_settings_description": "Pielāgotu paziņojumu veidņu pārvaldība",
|
||||
"theme_custom_css_settings": "Pielāgots CSS",
|
||||
"theme_custom_css_settings_description": "",
|
||||
"theme_settings": "",
|
||||
"theme_settings_description": "Immich tīmekļa saskarnes pielāgojumu pārvaldība",
|
||||
"theme_settings_description": "",
|
||||
"thumbnail_generation_job_description": "",
|
||||
"transcoding_acceleration_api": "",
|
||||
"transcoding_acceleration_api_description": "",
|
||||
@@ -256,14 +246,14 @@
|
||||
"trash_number_of_days": "Dienu skaits",
|
||||
"trash_number_of_days_description": "",
|
||||
"trash_settings": "",
|
||||
"trash_settings_description": "Atkritnes iestatījumu pārvaldība",
|
||||
"trash_settings_description": "",
|
||||
"user_delete_delay_settings": "",
|
||||
"user_delete_delay_settings_description": "",
|
||||
"user_management": "Lietotāju pārvaldība",
|
||||
"user_password_has_been_reset": "Lietotāja parole ir atiestatīta:",
|
||||
"user_restore_description": "<b>{user}</b> konts tiks atjaunots.",
|
||||
"user_settings": "",
|
||||
"user_settings_description": "Lietotāju iestatījumu pārvaldība",
|
||||
"user_settings_description": "",
|
||||
"version_check_enabled_description": "Ieslēgt versijas pārbaudi",
|
||||
"version_check_implications": "Versiju pārbaudes funkcija ir atkarīga no periodiskas saziņas ar github.com",
|
||||
"version_check_settings": "Versijas pārbaude",
|
||||
@@ -408,7 +398,6 @@
|
||||
"done": "Gatavs",
|
||||
"download": "Lejupielādēt",
|
||||
"download_settings": "Lejupielāde",
|
||||
"download_settings_description": "Ar failu lejupielādi saistīto iestatījumu pārvaldība",
|
||||
"downloading": "",
|
||||
"duplicates": "Dublikāti",
|
||||
"duration": "",
|
||||
@@ -501,7 +490,6 @@
|
||||
"favorite_or_unfavorite_photo": "",
|
||||
"favorites": "Izlase",
|
||||
"feature_photo_updated": "",
|
||||
"features_setting_description": "Lietotnes funkciju pārvaldība",
|
||||
"file_name": "",
|
||||
"file_name_or_extension": "",
|
||||
"filename": "",
|
||||
@@ -571,13 +559,13 @@
|
||||
"loop_videos": "",
|
||||
"loop_videos_description": "Iespējot, lai automātiski videoklips tiktu cikliski palaists detaļu skatītājā.",
|
||||
"make": "Firma",
|
||||
"manage_shared_links": "Kopīgoto saišu pārvaldība",
|
||||
"manage_sharing_with_partners": "Koplietošanas ar partneriem pārvaldība",
|
||||
"manage_the_app_settings": "Lietotnes iestatījumu pārvaldība",
|
||||
"manage_your_account": "Sava konta pārvaldība",
|
||||
"manage_your_api_keys": "API atslēgu pārvaldība",
|
||||
"manage_your_devices": "Pieslēgto ierīču pārvaldība",
|
||||
"manage_your_oauth_connection": "OAuth savienojumu pārvaldība",
|
||||
"manage_shared_links": "Pārvaldīt Kopīgotās saites",
|
||||
"manage_sharing_with_partners": "",
|
||||
"manage_the_app_settings": "",
|
||||
"manage_your_account": "",
|
||||
"manage_your_api_keys": "",
|
||||
"manage_your_devices": "",
|
||||
"manage_your_oauth_connection": "",
|
||||
"map": "Karte",
|
||||
"map_marker_for_images": "Kartes marķieris attēliem, kas uzņemti {city}, {country}",
|
||||
"map_marker_with_image": "Kartes marķieris ar attēlu",
|
||||
@@ -631,7 +619,7 @@
|
||||
"notes": "Piezīmes",
|
||||
"notification_toggle_setting_description": "Ieslēgt e-pasta paziņojumus",
|
||||
"notifications": "Paziņojumi",
|
||||
"notifications_setting_description": "Paziņojumu pārvaldība",
|
||||
"notifications_setting_description": "",
|
||||
"oauth": "OAuth",
|
||||
"official_immich_resources": "Oficiālie Immich resursi",
|
||||
"offline": "Bezsaistē",
|
||||
@@ -701,7 +689,6 @@
|
||||
"purchase_server_description_1": "Visam serverim",
|
||||
"purchase_server_description_2": "Atbalstītāja statuss",
|
||||
"purchase_server_title": "Serveris",
|
||||
"purchase_settings_server_activated": "Servera produkta atslēgu pārvalda administrators",
|
||||
"reaction_options": "",
|
||||
"read_changelog": "Lasīt izmaiņu sarakstu",
|
||||
"recent": "",
|
||||
@@ -833,7 +820,7 @@
|
||||
"status": "Statuss",
|
||||
"stop_motion_photo": "",
|
||||
"stop_photo_sharing": "Beigt kopīgot jūsu fotogrāfijas?",
|
||||
"storage": "Vieta krātuvē",
|
||||
"storage": "Uzglabāšanas vieta",
|
||||
"storage_label": "",
|
||||
"storage_usage": "{used} no {available} izmantoti",
|
||||
"submit": "Iesniegt",
|
||||
@@ -883,7 +870,6 @@
|
||||
"usage": "Lietojums",
|
||||
"user": "Lietotājs",
|
||||
"user_id": "Lietotāja ID",
|
||||
"user_purchase_settings_description": "Pirkuma pārvaldība",
|
||||
"user_usage_detail": "Informācija par lietotāju lietojumu",
|
||||
"username": "Lietotājvārds",
|
||||
"users": "Lietotāji",
|
||||
|
||||
@@ -987,7 +987,6 @@
|
||||
"permanently_deleted_asset": "Filen har blitt permanent slettet",
|
||||
"permanently_deleted_assets_count": "Permanent slett {count, plural, one {# asset} other {# assets}}",
|
||||
"person": "Person",
|
||||
"person_birthdate": "Født den {date}",
|
||||
"person_hidden": "{name}{hidden, select, true { (skjult)} other {}}",
|
||||
"photo_shared_all_users": "Det ser ut som om du deler bildene med alle brukere eller det er ingen brukere å dele med.",
|
||||
"photos": "Bilder",
|
||||
@@ -1079,8 +1078,6 @@
|
||||
"remove_from_album": "Fjern fra album",
|
||||
"remove_from_favorites": "Fjern fra favoritter",
|
||||
"remove_from_shared_link": "Fjern fra delt lenke",
|
||||
"remove_memory": "Slett minne",
|
||||
"remove_photo_from_memory": "Slett bilde fra dette minne",
|
||||
"remove_url": "Fjern URL",
|
||||
"remove_user": "Fjern bruker",
|
||||
"removed_api_key": "Fjernet API-nøkkel: {name}",
|
||||
@@ -1151,7 +1148,6 @@
|
||||
"searching_locales": "Søker lokaler...",
|
||||
"second": "Sekund",
|
||||
"see_all_people": "Vis alle mennesker",
|
||||
"select": "Velg",
|
||||
"select_album_cover": "Velg albumomslag",
|
||||
"select_all": "Velg alle",
|
||||
"select_all_duplicates": "Velg alle duplikater",
|
||||
@@ -1378,4 +1374,4 @@
|
||||
"yes": "Ja",
|
||||
"you_dont_have_any_shared_links": "Du har ingen delte lenker",
|
||||
"zoom_image": "Zoom Bilde"
|
||||
}
|
||||
}
|
||||
10
i18n/nl.json
10
i18n/nl.json
@@ -987,7 +987,6 @@
|
||||
"permanently_deleted_asset": "Asset permanent verwijderd",
|
||||
"permanently_deleted_assets_count": "{count, plural, one {# asset} other {# assets}} permanent verwijderd",
|
||||
"person": "Persoon",
|
||||
"person_birthdate": "Geboren op {date}",
|
||||
"person_hidden": "{name}{hidden, select, true { (verborgen)} other {}}",
|
||||
"photo_shared_all_users": "Het lijkt erop dat je foto's met alle gebruikers zijn gedeeld, of dat je geen gebruikers hebt om mee te delen.",
|
||||
"photos": "Foto's",
|
||||
@@ -1079,16 +1078,14 @@
|
||||
"remove_from_album": "Verwijder uit album",
|
||||
"remove_from_favorites": "Verwijderen uit favorieten",
|
||||
"remove_from_shared_link": "Verwijderen uit gedeelde link",
|
||||
"remove_memory": "Herinnering verwijderen",
|
||||
"remove_photo_from_memory": "Foto uit deze herinnering verwijderen",
|
||||
"remove_url": "Verwijder URL",
|
||||
"remove_user": "Gebruiker verwijderen",
|
||||
"removed_api_key": "API sleutel verwijderd: {name}",
|
||||
"removed_from_archive": "Verwijderd uit archief",
|
||||
"removed_from_favorites": "Verwijderd uit favorieten",
|
||||
"removed_from_favorites_count": "{count, plural, other {# verwijderd}} uit favorieten",
|
||||
"removed_memory": "Herinnering verwijderd",
|
||||
"removed_photo_from_memory": "Foto verwijderd uit herinnering",
|
||||
"removed_memory": "Geheugen verwijderd",
|
||||
"removed_photo_from_memory": "Foto verwijderd uit geheugen",
|
||||
"removed_tagged_assets": "Tag verwijderd van {count, plural, one {# asset} other {# assets}}",
|
||||
"rename": "Hernoemen",
|
||||
"repair": "Repareren",
|
||||
@@ -1151,7 +1148,6 @@
|
||||
"searching_locales": "Zoeken naar landinstellingen...",
|
||||
"second": "Seconde",
|
||||
"see_all_people": "Bekijk alle mensen",
|
||||
"select": "Selecteer",
|
||||
"select_album_cover": "Selecteer album cover",
|
||||
"select_all": "Alles selecteren",
|
||||
"select_all_duplicates": "Selecteer alle duplicaten",
|
||||
@@ -1378,4 +1374,4 @@
|
||||
"yes": "Ja",
|
||||
"you_dont_have_any_shared_links": "Je hebt geen gedeelde links",
|
||||
"zoom_image": "Inzoomen"
|
||||
}
|
||||
}
|
||||
12
i18n/pl.json
12
i18n/pl.json
@@ -243,7 +243,7 @@
|
||||
"storage_template_hash_verification_enabled_description": "Włącza weryfikację sumy kontrolnej. Nie wyłączaj tej opcji, jeśli nie jesteś pewien konsekwencji",
|
||||
"storage_template_migration": "Migracja szablonu magazynu",
|
||||
"storage_template_migration_description": "Zastosuj aktualny szablon <link>{template}</link> do wcześniej przesłanych zasobów",
|
||||
"storage_template_migration_info": "Szablon Magazynu przekonwertuje wszystkie rozszerzenia na pisane małą literą. Zmiany w szablonie zostaną zastosowane tylko do nowych zasobów. Aby wstecznie zastosować szablon do wcześniej przesłanych zasobów, uruchom zadanie <link>{job}</link>.",
|
||||
"storage_template_migration_info": "Zmiany w szablonie zostaną zastosowane tylko do nowych zasobów. Aby wstecznie zastosować szablon do wcześniej przesłanych zasobów, uruchom zadanie <link>{job}</link>.",
|
||||
"storage_template_migration_job": "Zadanie migracji szablonu przechowywania",
|
||||
"storage_template_more_details": "Aby uzyskać więcej szczegółów na temat tej funkcji, odwiedź <template-link>Szablon Przechowywania</template-link> oraz jego <implications-link>implikacje</implications-link>",
|
||||
"storage_template_onboarding_description": "Po włączeniu tej funkcji pliki będą organizowane automatycznie na podstawie szablonu zdefiniowanego przez użytkownika. Obecnie domyślnie wyłączona przez problemy ze stabilnością. Więcej informacji znajdziesz w <link>dokumentacji</link>.",
|
||||
@@ -829,7 +829,7 @@
|
||||
"language": "Język",
|
||||
"language_setting_description": "Wybierz swój preferowany język",
|
||||
"last_seen": "Ostatnio widziane",
|
||||
"latest_version": "Najnowsza Wersja",
|
||||
"latest_version": "Ostatnia Wersja",
|
||||
"latitude": "Szerokość geograficzna",
|
||||
"leave": "Opuść",
|
||||
"lens_model": "Model obiektywu",
|
||||
@@ -987,7 +987,6 @@
|
||||
"permanently_deleted_asset": "Pomyślnie trwale usunięto zasób",
|
||||
"permanently_deleted_assets_count": "Trwale usunięto {count, plural, one {# zasób} other {# zasobów}}",
|
||||
"person": "Osoba",
|
||||
"person_birthdate": "Urodzony {date}",
|
||||
"person_hidden": "{name}{hidden, select, true { (ukryty)} other {}}",
|
||||
"photo_shared_all_users": "Wygląda na to, że udostępniłeś swoje zdjęcia wszystkim użytkownikom lub nie masz żadnego użytkownika, z którym można by było je udostępnić.",
|
||||
"photos": "Zdjęcia",
|
||||
@@ -1149,7 +1148,6 @@
|
||||
"searching_locales": "Wyszukaj region...",
|
||||
"second": "Sekunda",
|
||||
"see_all_people": "Zobacz wszystkie osoby",
|
||||
"select": "Wybierz",
|
||||
"select_album_cover": "Wybierz okładkę albumu",
|
||||
"select_all": "Zaznacz wszystko",
|
||||
"select_all_duplicates": "Wybierz wszystkie duplikaty",
|
||||
@@ -1320,13 +1318,13 @@
|
||||
"updated_password": "Pomyślnie zaktualizowano hasło",
|
||||
"upload": "Prześlij",
|
||||
"upload_concurrency": "Współbieżność wysyłania",
|
||||
"upload_errors": "Przesyłanie zakończone z {count, plural, one {# błąd} other {# błędy}}. Odśwież stronę, aby zobaczyć nowo przesłane zasoby.",
|
||||
"upload_errors": "Przesyłanie zakończone z {count, plural, one {# błąd} other {# błędy}}. Odśwież stronę, aby zobaczyć nowe przesłane zasoby.",
|
||||
"upload_progress": "Pozostałe {remaining, number} - Przetworzone {processed, number}/{total, number}",
|
||||
"upload_skipped_duplicates": "Pominięte {count, plural, one {# zduplikowany zasób} other {# zduplikowane zasoby}}",
|
||||
"upload_status_duplicates": "Duplikaty",
|
||||
"upload_status_errors": "Błędy",
|
||||
"upload_status_uploaded": "Przesłano",
|
||||
"upload_success": "Przesyłanie powiodło się, odśwież stronę, aby zobaczyć nowo przesłane zasoby.",
|
||||
"upload_success": "Przesyłanie powiodło się, odśwież stronę, aby zobaczyć nowe przesłane zasoby.",
|
||||
"url": "URL",
|
||||
"usage": "Użycie",
|
||||
"use_custom_date_range": "Zamiast tego użyj niestandardowego zakresu dat",
|
||||
@@ -1376,4 +1374,4 @@
|
||||
"yes": "Tak",
|
||||
"you_dont_have_any_shared_links": "Nie masz żadnych udostępnionych linków",
|
||||
"zoom_image": "Powiększ obraz"
|
||||
}
|
||||
}
|
||||
@@ -302,7 +302,7 @@
|
||||
"transcoding_max_b_frames": "Máximo de quadros B",
|
||||
"transcoding_max_b_frames_description": "Valores mais altos melhoram a eficiência da compressão, mas tornam a codificação mais lenta. Pode não ser compatível com aceleração de hardware em dispositivos mais antigos. 0 desativa os quadros B, enquanto -1 define esse valor automaticamente.",
|
||||
"transcoding_max_bitrate": "Taxa de bits máxima",
|
||||
"transcoding_max_bitrate_description": "Definir uma taxa de bits máxima pode tornar os tamanhos dos ficheiros mais previsíveis com um custo menor de qualidade. Em 720p, os valores típicos são 2600 kbit/s para VP9 ou HEVC, ou 4500 kbit/s para H.264. Desativado se definido como 0.",
|
||||
"transcoding_max_bitrate_description": "Definir uma taxa de bits máxima pode tornar os tamanhos dos ficheiros mais previsíveis com um custo menor de qualidade. Em 720p, os valores típicos são 2.600k para VP9 ou HEVC, ou 4.500k para H.264. Desativado se definido como 0.",
|
||||
"transcoding_max_keyframe_interval": "Intervalo máximo de quadro-chave",
|
||||
"transcoding_max_keyframe_interval_description": "Define a distância máxima do quadro entre os quadros-chave. Valores mais baixos pioram a eficiência da compressão, mas melhoram os tempos de procura e podem melhorar a qualidade em cenas com movimento rápido. 0 define esse valor automaticamente.",
|
||||
"transcoding_optimal_description": "Vídeos com resolução superior à desejada ou num formato não aceite",
|
||||
@@ -987,7 +987,6 @@
|
||||
"permanently_deleted_asset": "Ficheiro eliminado permanentemente",
|
||||
"permanently_deleted_assets_count": "{count, plural, one {# Ficheiro eliminado} other {# Ficheiros eliminados}} permanentemente",
|
||||
"person": "Pessoa",
|
||||
"person_birthdate": "Nasceu a {date}",
|
||||
"person_hidden": "{name}{hidden, select, true { (oculto)} other {}}",
|
||||
"photo_shared_all_users": "Parece que partilhou as suas fotos com todos os utilizadores ou não tem nenhum utilizador para partilhar.",
|
||||
"photos": "Fotos",
|
||||
@@ -1079,8 +1078,6 @@
|
||||
"remove_from_album": "Remover do álbum",
|
||||
"remove_from_favorites": "Remover dos favoritos",
|
||||
"remove_from_shared_link": "Remover do link partilhado",
|
||||
"remove_memory": "Remover memória",
|
||||
"remove_photo_from_memory": "Remover foto desta memória",
|
||||
"remove_url": "Remover URL",
|
||||
"remove_user": "Remover utilizador",
|
||||
"removed_api_key": "Foi removida a Chave de API: {name}",
|
||||
@@ -1097,7 +1094,7 @@
|
||||
"repository": "Repositório",
|
||||
"require_password": "Proteger com palavra-passe",
|
||||
"require_user_to_change_password_on_first_login": "Obrigar utilizador a alterar a palavra-passe após o primeiro início de sessão",
|
||||
"rescan": "Reanalisar",
|
||||
"rescan": "Reescanear",
|
||||
"reset": "Redefinir",
|
||||
"reset_password": "Redefinir palavra-passe",
|
||||
"reset_people_visibility": "Redefinir pessoas ocultas",
|
||||
@@ -1151,7 +1148,6 @@
|
||||
"searching_locales": "A pesquisar Lugares....",
|
||||
"second": "Segundo",
|
||||
"see_all_people": "Ver todas as pessoas",
|
||||
"select": "Selecionar",
|
||||
"select_album_cover": "Escolher capa do álbum",
|
||||
"select_all": "Selecionar todos",
|
||||
"select_all_duplicates": "Selecionar todos os itens duplicados",
|
||||
|
||||
@@ -252,7 +252,7 @@
|
||||
"storage_template_settings_description": "Gerencie a estrutura de pasta e o nome do arquivo carregado",
|
||||
"storage_template_user_label": "<code>{label}</code> é o Rótulo de Armazenamento do usuário",
|
||||
"system_settings": "Configurações do Sistema",
|
||||
"tag_cleanup_job": "Limpeza de marcadores",
|
||||
"tag_cleanup_job": "Limpeza de tags",
|
||||
"template_email_available_tags": "Você pode usar as seguintes variáveis no modelo: {tags}",
|
||||
"template_email_if_empty": "Se o modelo estiver em branco, o modelo de e-mail padrão será usado.",
|
||||
"template_email_invite_album": "Modelo do e-mail de convite para álbum",
|
||||
@@ -302,7 +302,7 @@
|
||||
"transcoding_max_b_frames": "Máximo de quadros B",
|
||||
"transcoding_max_b_frames_description": "Valores mais altos melhoram a eficiência da compactação, mas retardam a codificação. Pode não ser compatível com aceleração de hardware em dispositivos mais antigos. 0 desativa os quadros B, enquanto -1 define esse valor automaticamente.",
|
||||
"transcoding_max_bitrate": "Taxa de bits máxima",
|
||||
"transcoding_max_bitrate_description": "Definir uma taxa de bits máxima pode tornar os tamanhos dos arquivos mais previsíveis com um custo menor de qualidade. Em 720p, os valores típicos são 2.600 kbit/s para VP9 ou HEVC, ou 4.500 kbit/s para H.264. Desativado se definido como 0.",
|
||||
"transcoding_max_bitrate_description": "Definir uma taxa de bits máxima pode tornar os tamanhos dos arquivos mais previsíveis com um custo menor de qualidade. Em 720p, os valores típicos são 2.600k para VP9 ou HEVC, ou 4.500k para H.264. Desativado se definido como 0.",
|
||||
"transcoding_max_keyframe_interval": "Intervalo máximo de quadro-chave",
|
||||
"transcoding_max_keyframe_interval_description": "Define a distância máxima do quadro entre os quadros-chave. Valores mais baixos pioram a eficiência da compressão, mas melhoram os tempos de busca e podem melhorar a qualidade em cenas com movimento rápido. 0 define esse valor automaticamente.",
|
||||
"transcoding_optimal_description": "Vídeos com resolução superior à desejada ou em formato não aceito",
|
||||
@@ -513,8 +513,8 @@
|
||||
"create_new_person": "Criar nova pessoa",
|
||||
"create_new_person_hint": "Atribuir arquivos selecionados a uma nova pessoa",
|
||||
"create_new_user": "Criar novo usuário",
|
||||
"create_tag": "Criar marcador",
|
||||
"create_tag_description": "Cria um novo marcador. Para marcadores multi nível, digite o caminho completo do marcador, inclusive as barras.",
|
||||
"create_tag": "Criar tag",
|
||||
"create_tag_description": "Crie uma nova tag. Para tags compostas, digite o caminho completo da tag, inclusive as barras.",
|
||||
"create_user": "Criar usuário",
|
||||
"created": "Criado",
|
||||
"current_device": "Dispositivo atual",
|
||||
@@ -544,8 +544,8 @@
|
||||
"delete_link": "Excluir link",
|
||||
"delete_others": "Excluir restante",
|
||||
"delete_shared_link": "Excluir link de compartilhamento",
|
||||
"delete_tag": "Remover marcador",
|
||||
"delete_tag_confirmation_prompt": "Tem certeza que deseja excluir o marcador {tagName} ?",
|
||||
"delete_tag": "Remover tag",
|
||||
"delete_tag_confirmation_prompt": "Tem certeza que deseja excluir a tag {tagName} ?",
|
||||
"delete_user": "Excluir usuário",
|
||||
"deleted_shared_link": "Link de compartilhamento excluído",
|
||||
"deletes_missing_assets": "Excluir arquivos não encontrados",
|
||||
@@ -590,7 +590,7 @@
|
||||
"edit_location": "Editar Localização",
|
||||
"edit_name": "Editar nome",
|
||||
"edit_people": "Editar pessoas",
|
||||
"edit_tag": "Editar marcador",
|
||||
"edit_tag": "Editar tag",
|
||||
"edit_title": "Editar Título",
|
||||
"edit_user": "Editar usuário",
|
||||
"edited": "Editado",
|
||||
@@ -778,7 +778,7 @@
|
||||
"group_owner": "Agrupar por dono",
|
||||
"group_places_by": "Agrupar lugares por...",
|
||||
"group_year": "Agrupar por ano",
|
||||
"has_quota": "Cota",
|
||||
"has_quota": "Há cota",
|
||||
"hi_user": "Olá {name} ({email})",
|
||||
"hide_all_people": "Esconder todas as pessoas",
|
||||
"hide_gallery": "Ocultar galeria",
|
||||
@@ -987,7 +987,6 @@
|
||||
"permanently_deleted_asset": "Arquivo deletado permanentemente",
|
||||
"permanently_deleted_assets_count": "{count, plural, one {# arquivo permanentemente excluído} other {# arquivos permanentemente excluídos}}",
|
||||
"person": "Pessoa",
|
||||
"person_birthdate": "Nasceu em {date}",
|
||||
"person_hidden": "{name}{hidden, select, true { (oculto)} other {}}",
|
||||
"photo_shared_all_users": "Parece que você compartilhou suas fotos com todos os usuários ou não tem nenhum usuário com quem compartilhar.",
|
||||
"photos": "Fotos",
|
||||
@@ -1079,8 +1078,6 @@
|
||||
"remove_from_album": "Remover do álbum",
|
||||
"remove_from_favorites": "Remover dos favoritos",
|
||||
"remove_from_shared_link": "Remover do link compartilhado",
|
||||
"remove_memory": "Remover memória",
|
||||
"remove_photo_from_memory": "Remover foto desta memória",
|
||||
"remove_url": "Remover URL",
|
||||
"remove_user": "Remover usuário",
|
||||
"removed_api_key": "Removido a Chave de API: {name}",
|
||||
@@ -1089,7 +1086,7 @@
|
||||
"removed_from_favorites_count": "{count, plural, one {# Removido} other {# Removidos}} dos favoritos",
|
||||
"removed_memory": "Memória removida",
|
||||
"removed_photo_from_memory": "Foto removida da memória",
|
||||
"removed_tagged_assets": "Marcador removido de {count, plural, one {# arquivo} other {# arquivos}}",
|
||||
"removed_tagged_assets": "Tag removida de {count, plural, one {# arquivo} other {# arquivos}}",
|
||||
"rename": "Renomear",
|
||||
"repair": "Reparar",
|
||||
"repair_no_results_message": "Arquivos perdidos ou não rastreados aparecem aqui",
|
||||
@@ -1120,7 +1117,7 @@
|
||||
"saved_settings": "Configurações salvas",
|
||||
"say_something": "Diga algo",
|
||||
"scan_all_libraries": "Escanear Todas Bibliotecas",
|
||||
"scan_library": "Escanear",
|
||||
"scan_library": "Analisar",
|
||||
"scan_settings": "Opções de escanear",
|
||||
"scanning_for_album": "Escaneando por álbum...",
|
||||
"search": "Pesquisar",
|
||||
@@ -1144,14 +1141,13 @@
|
||||
"search_rating": "Pesquisar por classificação...",
|
||||
"search_settings": "Configurações de pesquisa",
|
||||
"search_state": "Pesquisar estado...",
|
||||
"search_tags": "Procurar marcadores...",
|
||||
"search_tags": "Procurar tags...",
|
||||
"search_timezone": "Pesquisar fuso horário...",
|
||||
"search_type": "Pesquisar tipo",
|
||||
"search_your_photos": "Pesquisar fotos",
|
||||
"searching_locales": "Pesquisar Lugares....",
|
||||
"second": "Segundo",
|
||||
"see_all_people": "Ver todas as pessoas",
|
||||
"select": "Selecionar",
|
||||
"select_album_cover": "Escolher capa do álbum",
|
||||
"select_all": "Selecionar todos",
|
||||
"select_all_duplicates": "Selecionar todas as duplicatas",
|
||||
@@ -1224,7 +1220,7 @@
|
||||
"size": "Tamanho",
|
||||
"skip_to_content": "Pular para o conteúdo",
|
||||
"skip_to_folders": "Ir para pastas",
|
||||
"skip_to_tags": "Ir para os marcadores",
|
||||
"skip_to_tags": "Ir para as tags",
|
||||
"slideshow": "Apresentação",
|
||||
"slideshow_settings": "Opções de apresentação",
|
||||
"sort_albums_by": "Ordenar álbuns por...",
|
||||
@@ -1261,15 +1257,15 @@
|
||||
"support_third_party_description": "Sua instalação do Immich é fornecida por terceiros. É possível que problemas sejam causados por eles, por isso, se tiver problemas, procure primeiro ajuda com eles utilizando os links abaixo.",
|
||||
"swap_merge_direction": "Alternar direção da mesclagem",
|
||||
"sync": "Sincronizar",
|
||||
"tag": "Marcador",
|
||||
"tag_assets": "Marcar arquivos",
|
||||
"tag_created": "Marcador criado: {tag}",
|
||||
"tag_feature_description": "Visualizar fotos e videos agrupados pelo tópico do marcador",
|
||||
"tag_not_found_question": "Não consegue encontrar o marcador? <link>Crie uma novo aqui.</link>",
|
||||
"tag": "Tag",
|
||||
"tag_assets": "Marcar com tag",
|
||||
"tag_created": "Tag foi criada: {tag}",
|
||||
"tag_feature_description": "Visualizar fotos e videos agrupados pelo tópico da tag",
|
||||
"tag_not_found_question": "Não consegue encontrar a tag? <link>Crie uma tag nova aqui.</link>",
|
||||
"tag_people": "Marcar pessoas",
|
||||
"tag_updated": "Marcador foi atualizado: {tag}",
|
||||
"tagged_assets": "{count, plural, one {# arquivo marcado} other {# arquivos marcados}}",
|
||||
"tags": "Marcadores",
|
||||
"tag_updated": "Tag foi atualizada: {tag}",
|
||||
"tagged_assets": "{count, plural, one {# arquivo marcado} other {# arquivos marcados}} com a tag",
|
||||
"tags": "Tags",
|
||||
"template": "Modelo",
|
||||
"theme": "Tema",
|
||||
"theme_selection": "Selecionar tema",
|
||||
|
||||
@@ -1079,16 +1079,14 @@
|
||||
"remove_from_album": "Удалить из альбома",
|
||||
"remove_from_favorites": "Удалить из избранного",
|
||||
"remove_from_shared_link": "Удалить из публичной ссылки",
|
||||
"remove_memory": "Удалить воспоминание",
|
||||
"remove_photo_from_memory": "Удалить фото из воспоминания",
|
||||
"remove_url": "Удалить URL",
|
||||
"remove_user": "Удалить пользователя",
|
||||
"removed_api_key": "Удален ключ API: {name}",
|
||||
"removed_from_archive": "Удален из архива",
|
||||
"removed_from_favorites": "Удалено из избранного",
|
||||
"removed_from_favorites_count": "{count, plural, other {Удалено #}} из избранного",
|
||||
"removed_memory": "Воспоминание удалено",
|
||||
"removed_photo_from_memory": "Фото удалено из воспоминания",
|
||||
"removed_memory": "Удалить воспоминание",
|
||||
"removed_photo_from_memory": "Удалить фото из воспоминания",
|
||||
"removed_tagged_assets": "Тег для {count, plural, one {# объекта} other {# объектов}} удален",
|
||||
"rename": "Переименовать",
|
||||
"repair": "Ремонт",
|
||||
@@ -1151,7 +1149,6 @@
|
||||
"searching_locales": "Идет поиск переводов...",
|
||||
"second": "Секунда",
|
||||
"see_all_people": "Посмотреть всех людей",
|
||||
"select": "Выбрать",
|
||||
"select_album_cover": "Выбрать обложку альбома",
|
||||
"select_all": "Выбрать все",
|
||||
"select_all_duplicates": "Выбрать все дубликаты",
|
||||
@@ -1378,4 +1375,4 @@
|
||||
"yes": "Да",
|
||||
"you_dont_have_any_shared_links": "У вас нет публичных ссылок",
|
||||
"zoom_image": "Приблизить"
|
||||
}
|
||||
}
|
||||
@@ -243,7 +243,7 @@
|
||||
"storage_template_hash_verification_enabled_description": "Povolí overenie hash, nezakazujte to, pokiaľ si nie ste istí dôsledkami",
|
||||
"storage_template_migration": "Migrácia šablóny úložiska",
|
||||
"storage_template_migration_description": "Použite aktuálnu <link>{template}</link> na predtým nahrané médiá",
|
||||
"storage_template_migration_info": "Šablóna úložiska skonvertuje všetky prípony na malé písmená. Zmeny šablón sa budú vzťahovať iba na nové diela. Ak chcete šablónu spätne použiť na predtým nahrané médiá, spustite <link>{job}</link>.",
|
||||
"storage_template_migration_info": "Zmeny šablón sa budú vzťahovať iba na nové diela. Ak chcete šablónu spätne použiť na predtým nahrané médiá, spustite <link>{job}</link>.",
|
||||
"storage_template_migration_job": "Úloha migrácie šablóny úložiska",
|
||||
"storage_template_more_details": "Ďalšie podrobnosti o tejto funkcii nájdete v <template-link>Šablóna úložiska</template-link> a jej <implications-link>dôsledky</implications-link>",
|
||||
"storage_template_onboarding_description": "Keď je táto funkcia povolená, automaticky usporiada súbory na základe šablóny definovanej používateľom. Kvôli problémom so stabilitou bola funkcia predvolene vypnutá. Viac informácií nájdete v <link>dokumentácii</link>.",
|
||||
@@ -987,7 +987,6 @@
|
||||
"permanently_deleted_asset": "Navždy odstránená položka",
|
||||
"permanently_deleted_assets_count": "Navždy {count, plural, one {odstránená # položka} other {odstránené # položky}}",
|
||||
"person": "Osoba",
|
||||
"person_birthdate": "Narodený dňa {date}",
|
||||
"person_hidden": "{name}{hidden, select, true { (skryté)} other {}}",
|
||||
"photo_shared_all_users": "Vyzerá, že zdieľate svoje fotky so všetkými používateľmi alebo nemáte žiadnych používateľov.",
|
||||
"photos": "Fotografie",
|
||||
@@ -1149,7 +1148,6 @@
|
||||
"searching_locales": "Hľadám lokality...",
|
||||
"second": "Sekundy",
|
||||
"see_all_people": "Pozrieť všetky osoby",
|
||||
"select": "Vybrať",
|
||||
"select_album_cover": "Vyberte obal albumu",
|
||||
"select_all": "Vybrať všetko",
|
||||
"select_all_duplicates": "Vybrať všetky duplikáty",
|
||||
@@ -1376,4 +1374,4 @@
|
||||
"yes": "Áno",
|
||||
"you_dont_have_any_shared_links": "Nemáte žiadne zdielané linky",
|
||||
"zoom_image": "Priblížiť obrázok"
|
||||
}
|
||||
}
|
||||
@@ -1079,8 +1079,6 @@
|
||||
"remove_from_album": "Odstrani iz albuma",
|
||||
"remove_from_favorites": "Odstrani iz priljubljenih",
|
||||
"remove_from_shared_link": "Odstrani iz skupne povezave",
|
||||
"remove_memory": "Odstrani spomin",
|
||||
"remove_photo_from_memory": "Odstrani fotografijo iz tega spomina",
|
||||
"remove_url": "Odstrani URL",
|
||||
"remove_user": "Odstrani uporabnika",
|
||||
"removed_api_key": "Odstranjen ključ API-ja: {name}",
|
||||
@@ -1151,7 +1149,6 @@
|
||||
"searching_locales": "Iskanje krajev...",
|
||||
"second": "Sekunda",
|
||||
"see_all_people": "Oglejte si vse ljudi",
|
||||
"select": "Izberi",
|
||||
"select_album_cover": "Izberi naslovnico albuma",
|
||||
"select_all": "Izberi vse",
|
||||
"select_all_duplicates": "Izberi vse dvojnike",
|
||||
@@ -1378,4 +1375,4 @@
|
||||
"yes": "Da",
|
||||
"you_dont_have_any_shared_links": "Nimate nobenih skupnih povezav",
|
||||
"zoom_image": "Povečava slike"
|
||||
}
|
||||
}
|
||||
@@ -302,7 +302,7 @@
|
||||
"transcoding_max_b_frames": "Максимални Б-кадри",
|
||||
"transcoding_max_b_frames_description": "Више вредности побољшавају ефикасност компресије, али успоравају кодирање. Можда није компатибилно са хардверским убрзањем на старијим уређајима. 0 oneмогућава Б-кадре, док -1 аутоматски поставља ову вредност.",
|
||||
"transcoding_max_bitrate": "Максимални битрате",
|
||||
"transcoding_max_bitrate_description": "Подешавање максималног битрате-а може учинити величине датотека предвидљивијим уз мању цену квалитета. При 720п, типичне вредности су 2600kbit/s за ВП9 или ХЕВЦ, или 4500kbit/s за Х.264. oneмогућено ако је постављено на 0.",
|
||||
"transcoding_max_bitrate_description": "Подешавање максималног битрате-а може учинити величине датотека предвидљивијим уз мању цену квалитета. При 720п, типичне вредности су 2600к за ВП9 или ХЕВЦ, или 4500к за Х.264. oneмогућено ако је постављено на 0.",
|
||||
"transcoding_max_keyframe_interval": "Максимални интервал keyframe-a",
|
||||
"transcoding_max_keyframe_interval_description": "Поставља максималну удаљеност кадрова између кључних кадрова. Ниже вредности погоршавају ефикасност компресије, али побољшавају време тражења и могу побољшати квалитет сцена са брзим кретањем. 0 аутоматски поставља ову вредност.",
|
||||
"transcoding_optimal_description": "Видео снимци већи од циљне резолуције или нису у прихваћеном формату",
|
||||
@@ -987,7 +987,6 @@
|
||||
"permanently_deleted_asset": "Трајно избрисана датотека",
|
||||
"permanently_deleted_assets_count": "Трајно избрисано {count, plural, one {# датотека} other {# датотеке}}",
|
||||
"person": "Особа",
|
||||
"person_birthdate": "Рођен(a) {date}",
|
||||
"person_hidden": "{name}{hidden, select, true { (скривено)} other {}}",
|
||||
"photo_shared_all_users": "Изгледа да сте поделили своје фотографије са свим корисницима или да немате ниједног корисника са којим бисте делили.",
|
||||
"photos": "Слике",
|
||||
@@ -1079,8 +1078,6 @@
|
||||
"remove_from_album": "Обриши из албума",
|
||||
"remove_from_favorites": "Уклони из фаворита",
|
||||
"remove_from_shared_link": "Уклоните са дељене везе",
|
||||
"remove_memory": "Уклоните меморију",
|
||||
"remove_photo_from_memory": "Уклоните фотографију из ове меморије",
|
||||
"remove_url": "Уклони URL",
|
||||
"remove_user": "Уклони корисника",
|
||||
"removed_api_key": "Уклоњен АПИ кључ (key): {name}",
|
||||
@@ -1151,7 +1148,6 @@
|
||||
"searching_locales": "Претраживање превода...",
|
||||
"second": "Секунда",
|
||||
"see_all_people": "Види све особе",
|
||||
"select": "Изаберите",
|
||||
"select_album_cover": "Изаберите омот албума",
|
||||
"select_all": "Изабери све",
|
||||
"select_all_duplicates": "Изаберите све дупликате",
|
||||
|
||||
@@ -987,7 +987,6 @@
|
||||
"permanently_deleted_asset": "Trajno izbrisana datoteka",
|
||||
"permanently_deleted_assets_count": "Trajno izbrisano {count, plural, one {# datoteka} other {# datoteke}}",
|
||||
"person": "Osoba",
|
||||
"person_birthdate": "Rođen(a) {date}",
|
||||
"person_hidden": "{name}{hidden, select, true { (skriveno)} other {}}",
|
||||
"photo_shared_all_users": "Izgleda da ste podelili svoje fotografije sa svim korisnicima ili da nemate nijednog korisnika sa kojim biste delili.",
|
||||
"photos": "Slike",
|
||||
@@ -1079,8 +1078,6 @@
|
||||
"remove_from_album": "Obriši iz albuma",
|
||||
"remove_from_favorites": "Ukloni iz favorita",
|
||||
"remove_from_shared_link": "Uklonite sa deljene veze",
|
||||
"remove_memory": "Uklonite memoriju",
|
||||
"remove_photo_from_memory": "Uklonite fotografiju iz ove memorije",
|
||||
"remove_url": "Ukloni URL",
|
||||
"remove_user": "Ukloni korisnika",
|
||||
"removed_api_key": "Uklonjen API ključ (key): {name}",
|
||||
@@ -1151,7 +1148,6 @@
|
||||
"searching_locales": "Pretraživanje prevoda...",
|
||||
"second": "Sekunda",
|
||||
"see_all_people": "Vidi sve osobe",
|
||||
"select": "Izaberite",
|
||||
"select_album_cover": "Izaberite omot albuma",
|
||||
"select_all": "Izaberi sve",
|
||||
"select_all_duplicates": "Izaberite sve duplikate",
|
||||
@@ -1378,4 +1374,4 @@
|
||||
"yes": "Da",
|
||||
"you_dont_have_any_shared_links": "Nemate nijedno deljenje veze",
|
||||
"zoom_image": "Zumiraj sliku"
|
||||
}
|
||||
}
|
||||
49
i18n/sv.json
49
i18n/sv.json
@@ -28,7 +28,7 @@
|
||||
"added_to_favorites": "Tillagd till favoriter",
|
||||
"added_to_favorites_count": "{count, number} tillagda till favoriter",
|
||||
"admin": {
|
||||
"add_exclusion_pattern_description": "Lägg till exkluderande mönster. Matchning med jokertecken *, ** samt ? stödjs. För att ignorera alla filer i samtliga mappar som heter \"Raw\", använd \"**/Raw/**\". För att ignorera alla filer som slutar med \".tif\", använd \"**/*.tif\". För att ignorera en absolut sökväg, använd \"/sökväg/att/ignorera/**\".",
|
||||
"add_exclusion_pattern_description": "Lägg till exkluderande mönster. Matchning med jokertecken *, ** samt ? är supporterat. För att ignorera alla filer i samtliga mappar som heter \"Raw\", använd \"**/Raw/**\". För att ignorera alla filer som slutar med \".tif\", använd \"**/*.tif\". För att ignorera en absolut sökväg, använd \"/sökväg/att/ignorera/**\".",
|
||||
"asset_offline_description": "Denna externa bibliotekstillgång finns inte längre på disken och har flyttats till papperskorgen. Om filen flyttades inom biblioteket, kontrollera din tidslinje för den nya motsvarande tillgången. För att återställa denna tillgång, se till att filsökvägen nedan kan nås av Immich och skanna biblioteket.",
|
||||
"authentication_settings": "Autentiseringsinställningar",
|
||||
"authentication_settings_description": "Hantera lösenord, OAuth, och andra autentiseringsinställningar",
|
||||
@@ -36,7 +36,7 @@
|
||||
"authentication_settings_reenable": "För att återaktivera, använd <link>Server Command</link>.",
|
||||
"background_task_job": "Bakgrundsaktiviteter",
|
||||
"backup_database": "Databassäkerhetskopia",
|
||||
"backup_database_enable_description": "Aktivera säkerhetskopiering av databas",
|
||||
"backup_database_enable_description": "Slå på säkerhetskopia",
|
||||
"backup_keep_last_amount": "Antal säkerhetskopior att behålla",
|
||||
"backup_settings": "Säkerhetskopieringsinställningar",
|
||||
"backup_settings_description": "Hantera inställningar för säkerhetskopiering av databas",
|
||||
@@ -48,19 +48,19 @@
|
||||
"confirm_delete_library_assets": "Är du säker på att du vill radera detta album? {count, plural, one {# objekt} other {Samtliga # objekt}} kommer att tas bort från Immich och åtgärden kan inte ångras. Filerna kommer att behållas på hårddisken.",
|
||||
"confirm_email_below": "För att bekräfta, skriv ”{email}” nedan",
|
||||
"confirm_reprocess_all_faces": "Är du säker på att du vill återprocessa alla ansikten? Detta kommer också rensa namngivna personer.",
|
||||
"confirm_user_password_reset": "Är du säker på att du vill återställa lösenordet för {user}?",
|
||||
"confirm_user_password_reset": "Är du säker på att du vill återställa {user}’s lösenord?",
|
||||
"create_job": "Skapa jobb",
|
||||
"cron_expression": "Cron uttryck",
|
||||
"cron_expression_description": "Sätt skanningsintervall genom att använda cron-format. För mer information se <link>Crontab Guru</link>",
|
||||
"cron_expression_presets": "Cron-uttryck förinställningar",
|
||||
"cron_expression_description": "Sätt skanningsintervall genom att använda cron format. För mer information se <link>Crontab Guru</link>",
|
||||
"cron_expression_presets": "Cron uttryck förinställningar",
|
||||
"disable_login": "Inaktivera inloggning",
|
||||
"duplicate_detection_job_description": "Kör maskininlärning på objekt för att upptäcka liknande bilder. Bygger på Smart Search",
|
||||
"exclusion_pattern_description": "Exkluderingsmönster tillåter dig att ignorera filer och mappar när skanning görs av ditt album. Detta är användbart om du har mappar som innehåller filer som du inte vill importera, t.ex. RAW-filer.",
|
||||
"external_library_created_at": "Externt bibliotek (skapat {date})",
|
||||
"external_library_created_at": "Externt bibliotek (skapat den {date})",
|
||||
"external_library_management": "Hantera externa bibliotek",
|
||||
"face_detection": "Ansiktsdetektering",
|
||||
"face_detection_description": "Identifiera ansikten i foton med hjälp av maskininlärning. För videor används endast miniatyrbilden. \"Ladda om\" gör om sökningen för alla objekt. \"Återställ\" rensar all gällande ansikts-data. \"Saknade\" letar i de objekt som ännu inte sökts igenom. Alla identifierade ansikten läggs sedan i jobbkön för ansiktsigenkänning där de mappas till nya eller befintliga personer.",
|
||||
"facial_recognition_job_description": "Gruppera upptäckta ansikten till personer. Det här steget körs efter att ansiktsdetektering är klar. \"Återställ\" (åter-)grupperar alla ansikten. \"Saknade\" köar ansikten som inte har en person tilldelad.",
|
||||
"face_detection_description": "Identifiera ansikten i foton med hjälp av maskininlärning. För videor används endast miniatyrbilden. \"Alla\" gör om sökningen för alla objekt. \"Saknade\" letar i de objekt som ännu inte sökts igenom. Alla ansikten som identifierats läggs sedan i jobbkön för ansiktsigenkänning där de mappas till nya eller befintliga personer.",
|
||||
"facial_recognition_job_description": "Gruppera upptäckta ansikten till personer. Det här steget körs efter att ansiktsdetektering är klar. \"Alla\" (åter-) grupperar alla ansikten. \"Saknade\" köer ansikten som inte har en person tilldelad.",
|
||||
"failed_job_command": "Kommando {command} misslyckades för jobb: {job}",
|
||||
"force_delete_user_warning": "VARNING: Detta tar omedelbart bort användaren och alla mediafiler. Detta kan inte ångras och filerna kan inte återställas.",
|
||||
"forcing_refresh_library_files": "Tvingar uppdatering av alla biblioteksfiler",
|
||||
@@ -69,25 +69,25 @@
|
||||
"image_prefer_embedded_preview": "Föredra inbäddad förhandsgranskning",
|
||||
"image_prefer_embedded_preview_setting_description": "Använd inbäddade förhandsvisningar i RAW-foton som indata till bildbehandling när det är tillgängligt. Detta kan ge mer exakta färger för vissa bilder, men kvaliteten på förhandsgranskningen är kameraberoende och bilden kan ha fler komprimeringsartefakter.",
|
||||
"image_prefer_wide_gamut": "Föredrar brett spektrum",
|
||||
"image_prefer_wide_gamut_setting_description": "Använd Display P3 för miniatyrer. Detta bevarar livfullheten bättre hos bilder med bred färgrymd, men bilder kan se annorlunda ut på gamla enheter med en gammal webbläsarversion. sRGB-bilder behålls som sRGB för att undvika färgskiftningar.",
|
||||
"image_prefer_wide_gamut_setting_description": "Använd Display P3 för miniatyrer. Detta bevarar livfullheten bättre hos bilder med bred färgrymd, men bilder kan se annorlunda ut på gamla enheter med en gammal webbläsarversion. Med sRGB-bilder behålls i sitt format sRGB för att undvika färgskiftningar.",
|
||||
"image_preview_description": "Mellanstor bild med avskalad metadata, används vid visning av en enskild tillgång och för maskininlärning",
|
||||
"image_preview_quality_description": "Förhandsgranskningskvalitet från 1-100. Högre är bättre, men ger större filer och kan göra appen mindre följsam. Att ställa in ett lågt värde kan påverka kvaliteten på maskininlärning.",
|
||||
"image_preview_quality_description": "Förhandsgranska kvalitet från 1-100. Högre är bättre, men ger större filer och kan minska appens känslighet. Att ställa in ett lågt värde kan påverka kvaliteten på maskininlärning.",
|
||||
"image_preview_title": "Förhandsvisningsinställningar",
|
||||
"image_quality": "Kvalitet",
|
||||
"image_resolution": "Upplösning",
|
||||
"image_resolution_description": "Högre upplösningar kan bevara fler detaljer men tar längre tid att koda, har större filstorlekar och kan minska appens följsamhet.",
|
||||
"image_resolution_description": "Högre upplösningar kan bevara fler detaljer men tar längre tid att koda, har större filstorlekar och kan minska appens känslighet.",
|
||||
"image_settings": "Bildinställningar",
|
||||
"image_settings_description": "Hantera kvalitet och upplösning på genererade bilder",
|
||||
"image_thumbnail_description": "Liten miniatyrbild med avskalad metadata, används när du tittar på grupper av foton som huvudtidslinjen",
|
||||
"image_thumbnail_quality_description": "Miniatyrkvalitet från 1-100. Högre är bättre, men ger större filer och kan minska appens följsamhet.",
|
||||
"image_thumbnail_quality_description": "Miniatyrkvalitet från 1-100. Högre är bättre, men ger större filer och kan minska appens känslighet.",
|
||||
"image_thumbnail_title": "Miniatyrbildsinställningar",
|
||||
"job_concurrency": "{job} samtidighet",
|
||||
"job_concurrency": "{job} Samtidighet",
|
||||
"job_created": "Jobb skapat",
|
||||
"job_not_concurrency_safe": "Det här jobbet är inte samtidighetssäkert.",
|
||||
"job_settings": "Jobbinställningar",
|
||||
"job_settings_description": "Hantera samtidiga jobb",
|
||||
"job_status": "Jobbstatus",
|
||||
"jobs_delayed": "{jobCount, plural, one{# försenad} other {# försenade}}",
|
||||
"jobs_delayed": "{jobCount, plural, other {# försenad}}",
|
||||
"jobs_failed": "{jobCount, plural, other {# misslyckades}}",
|
||||
"library_created": "Skapat bibliotek: {library}",
|
||||
"library_deleted": "Biblioteket har tagits bort",
|
||||
@@ -98,16 +98,16 @@
|
||||
"library_settings": "Externa bibliotek",
|
||||
"library_settings_description": "Hantera inställningar för externa bibliotek",
|
||||
"library_tasks_description": "Sök igenom externa bibliotek efter nya och/eller ändrade objekt",
|
||||
"library_watching_enable_description": "Bevaka externa bibliotek för filändringar",
|
||||
"library_watching_settings": "Bevaka bibliotek (EXPERIMENTELLT)",
|
||||
"library_watching_settings_description": "Bevaka automatiskt filförändringar",
|
||||
"library_watching_enable_description": "Titta på externa bibliotek för filändringar",
|
||||
"library_watching_settings": "Titta på bibliotek (EXPERIMENTELLT)",
|
||||
"library_watching_settings_description": "Titta automatiskt efter ändrade filer",
|
||||
"logging_enable_description": "Aktivera loggning",
|
||||
"logging_level_description": "Vilken loggnivå som ska användas vid aktivering.",
|
||||
"logging_level_description": "När aktiverad, vilken loggnivå som ska användas.",
|
||||
"logging_settings": "Loggning",
|
||||
"machine_learning_clip_model": "CLIP-modell",
|
||||
"machine_learning_clip_model_description": "Namnet på en CLIP-modell listad <link> här </link>. Observera att du måste köra ett \"Smart Sökning\" jobb för alla bilder när du ändrar modell.",
|
||||
"machine_learning_clip_model": "CLIP modell",
|
||||
"machine_learning_clip_model_description": "Namnet på en CLIP-modell listad <link> här </link>. Observera att du måste köra ett \"Smart Search\" jobb för alla bilder när du ändrar en modell.",
|
||||
"machine_learning_duplicate_detection": "Dubblettdetektering",
|
||||
"machine_learning_duplicate_detection_enabled": "Aktivera dubblettdetektion",
|
||||
"machine_learning_duplicate_detection_enabled": "Aktivera dubblett detektion",
|
||||
"machine_learning_duplicate_detection_enabled_description": "Om den inaktiveras kommer exakt identiska tillgångar fortfarande att dedupliceras.",
|
||||
"machine_learning_duplicate_detection_setting_description": "Använd CLIP-inbäddningar för att hitta troliga dubbletter",
|
||||
"machine_learning_enabled": "Aktivera maskininlärning",
|
||||
@@ -1079,8 +1079,6 @@
|
||||
"remove_from_album": "Ta bort från album",
|
||||
"remove_from_favorites": "Ta bort från favoriter",
|
||||
"remove_from_shared_link": "Ta bort från delad länk",
|
||||
"remove_memory": "Ta bort minne",
|
||||
"remove_photo_from_memory": "Ta bort fotot från detta minnet",
|
||||
"remove_url": "Ta bort URL",
|
||||
"remove_user": "Ta bort användare",
|
||||
"removed_api_key": "Tog bort API nyckel: {name}",
|
||||
@@ -1151,7 +1149,6 @@
|
||||
"searching_locales": "Söker efter språk...",
|
||||
"second": "Sekund",
|
||||
"see_all_people": "Se alla personer",
|
||||
"select": "Välj",
|
||||
"select_album_cover": "Välj albumomslag",
|
||||
"select_all": "Välj alla",
|
||||
"select_all_duplicates": "Välj alla dubletter",
|
||||
@@ -1297,7 +1294,7 @@
|
||||
"trashed_items_will_be_permanently_deleted_after": "Objekt i papperskorgen raderas permanent efter {days, plural, one {# dag} other {# dagar}}.",
|
||||
"type": "Typ",
|
||||
"unarchive": "Ångra arkivering",
|
||||
"unarchived_count": "{count, plural, one {# borttagen från arkiv} other {# borttagna från arkiv}}",
|
||||
"unarchived_count": "{count, plural, other {Unarchived #}}",
|
||||
"unfavorite": "Avfavorisera",
|
||||
"unhide_person": "Visa person",
|
||||
"unknown": "Okänd",
|
||||
@@ -1378,4 +1375,4 @@
|
||||
"yes": "Ja",
|
||||
"you_dont_have_any_shared_links": "Du har inga delade länkar",
|
||||
"zoom_image": "Zooma bild"
|
||||
}
|
||||
}
|
||||
13
i18n/te.json
13
i18n/te.json
@@ -29,17 +29,11 @@
|
||||
"added_to_favorites_count": "ఇష్టమైన వాటికి {count, number} జోడించబడింది",
|
||||
"admin": {
|
||||
"add_exclusion_pattern_description": "మినహాయింపు నమూనాలను జోడించండి. *, ** మరియు ?ని ఉపయోగించి గ్లోబింగ్కు మద్దతు ఉంది. \"Raw\" అనే పేరు గల ఏదైనా డైరెక్టరీలోని అన్ని ఫైల్లను విస్మరించడానికి, \"**/Raw/**\"ని ఉపయోగించండి. \".tif\"తో ముగిసే అన్ని ఫైల్లను విస్మరించడానికి, \"**/*.tif\"ని ఉపయోగించండి. సంపూర్ణ మార్గాన్ని విస్మరించడానికి, \"/path/to/ignore/**\"ని ఉపయోగించండి.",
|
||||
"asset_offline_description": "ఈ బాహ్య లైబ్రరీ ఫైల్ ఇకపై డిస్క్లో కనుగొనబడలేదు మరియు ట్రాష్కు తరలించబడింది. ఫైల్ లైబ్రరీలోకి తరలించబడితే, కొత్త సంబంధిత ఫైల్ కోసం మీ టైమ్లైన్ను తనిఖీ చేయండి. ఈ ఫైల్ని పునరుద్ధరించడానికి, దయచేసి దిగువన ఉన్న ఫైల్ పాత్ను Immich యాక్సెస్ చేయగలదని నిర్ధారించుకోండి మరియు లైబ్రరీని స్కాన్ చేయండి.",
|
||||
"authentication_settings": "ప్రమాణీకరణ సెట్టింగ్లు",
|
||||
"authentication_settings_description": "పాస్వర్డ్, OAuth మరియు ఇతర ప్రమాణీకరణ సెట్టింగ్లను నిర్వహించండి",
|
||||
"authentication_settings_disable_all": "మీరు ఖచ్చితంగా అన్ని లాగిన్ పద్ధతులను నిలిపివేయాలనుకుంటున్నారా? లాగిన్ పూర్తిగా నిలిపివేయబడుతుంది.",
|
||||
"authentication_settings_reenable": "మళ్లీ ప్రారంబించటానికి, <link>Server Command</link>ని ఉపయోగించండి.",
|
||||
"background_task_job": "నేపథ్య పనులు",
|
||||
"backup_database": "బ్యాకప్ డేటాబేస్",
|
||||
"backup_database_enable_description": "డేటాబేస్ బ్యాకప్లను ప్రారంభించండి",
|
||||
"backup_keep_last_amount": "ఉంచుకోవాల్సిన మునుపటి బ్యాకప్ల మొత్తం",
|
||||
"backup_settings": "బ్యాకప్ సెట్టింగ్లు",
|
||||
"backup_settings_description": "డేటాబేస్ బ్యాకప్ సెట్టింగ్లను నిర్వహించండి",
|
||||
"check_all": "అన్నీ తనిఖీ చేయండి",
|
||||
"cleared_jobs": "దీని కోసం ఉద్యోగాలు క్లియర్ చేయబడ్డాయి: {job}",
|
||||
"config_set_by_file": "కాన్ఫిగరేషన్ ప్రస్తుతం కాన్ఫిగరేషన్ ఫైల్ ద్వారా సెట్ చేయబడింది",
|
||||
@@ -48,10 +42,6 @@
|
||||
"confirm_email_below": "నిర్ధారించడానికి, క్రింద \"{email}\" టైప్ చేయండి",
|
||||
"confirm_reprocess_all_faces": "మీరు ఖచ్చితంగా అన్ని ముఖాలను రీప్రాసెస్ చేయాలనుకుంటున్నారా? ఇది పేరున్న వ్యక్తులను కూడా క్లియర్ చేస్తుంది.",
|
||||
"confirm_user_password_reset": "మీరు ఖచ్చితంగా {user} పాస్వర్డ్ని రీసెట్ చేయాలనుకుంటున్నారా?",
|
||||
"create_job": "పనిని సృష్టించండి",
|
||||
"cron_expression": "క్రాన్ వ్యక్తీకరణ",
|
||||
"cron_expression_description": "క్రాన్ ఫార్మాట్ ఉపయోగించి స్కానింగ్ విరామాన్ని సెట్ చేయండి. మరిన్ని వివరాల కోసం దయచేసి ఉదా. <link>క్రోంటాబ్ గురు</link> చూడండి",
|
||||
"cron_expression_presets": "ముందేచేసిన క్రాన్ వ్యక్తీకరణలు",
|
||||
"disable_login": "లాగిన్ను నిలిపివేయండి",
|
||||
"duplicate_detection_job_description": "సారూప్య చిత్రాలను గుర్తించడానికి ఆస్తులపై యంత్ర అభ్యాసాన్ని అమలు చేయండి. స్మార్ట్ శోధనపై ఆధారపడుతుంది",
|
||||
"exclusion_pattern_description": "మినహాయింపు నమూనాలు మీ లైబ్రరీని స్కాన్ చేస్తున్నప్పుడు ఫైల్లు మరియు ఫోల్డర్లను విస్మరించడానికి మిమ్మల్ని అనుమతిస్తాయి. మీరు దిగుమతి చేయకూడదనుకునే RAW ఫైల్లు వంటి ఫోల్డర్లను కలిగి ఉన్నట్లయితే ఇది ఉపయోగకరంగా ఉంటుంది.",
|
||||
@@ -63,14 +53,11 @@
|
||||
"failed_job_command": "ఉద్యోగం కోసం కమాండ్ {command} విఫలమైంది: {job}",
|
||||
"force_delete_user_warning": "హెచ్చరిక: ఇది వినియోగదారుని మరియు అన్ని ఆస్తులను వెంటనే తీసివేస్తుంది. ఇది రద్దు చేయబడదు మరియు ఫైల్లను తిరిగి పొందడం సాధ్యం కాదు.",
|
||||
"forcing_refresh_library_files": "అన్ని లైబ్రరీ ఫైల్లను రిఫ్రెష్ చేయమని బలవంతం చేస్తోంది",
|
||||
"image_format": "ఫార్మాట్",
|
||||
"image_format_description": "WebP JPEG కంటే చిన్న ఫైల్లను ఉత్పత్తి చేస్తుంది, కానీ ఎన్కోడ్ చేయడం నెమ్మదిగా ఉంటుంది.",
|
||||
"image_prefer_embedded_preview": "పొందుపరిచిన పరిదృశ్యానికి ప్రాధాన్యత ఇవ్వండి",
|
||||
"image_prefer_embedded_preview_setting_description": "అందుబాటులో ఉన్నప్పుడు ఇమేజ్ ప్రాసెసింగ్కు ఇన్పుట్గా RAW ఫోటోలలో ఎంబెడెడ్ ప్రివ్యూలను ఉపయోగించండి. ఇది కొన్ని చిత్రాలకు మరింత ఖచ్చితమైన రంగులను ఉత్పత్తి చేయగలదు, అయితే ప్రివ్యూ నాణ్యత కెమెరాపై ఆధారపడి ఉంటుంది మరియు చిత్రం మరిన్ని కుదింపు కళాఖండాలను కలిగి ఉండవచ్చు.",
|
||||
"image_prefer_wide_gamut": "విస్తృత స్వరసప్తకానికి ప్రాధాన్యత ఇవ్వండి",
|
||||
"image_prefer_wide_gamut_setting_description": "థంబ్నెయిల్ల కోసం డిస్ప్లే P3ని ఉపయోగించండి. ఇది విస్తృత రంగుల ఖాళీలతో చిత్రాల వైబ్రెన్స్ను మెరుగ్గా భద్రపరుస్తుంది, అయితే పాత బ్రౌజర్ వెర్షన్తో పాత పరికరాల్లో చిత్రాలు విభిన్నంగా కనిపించవచ్చు. రంగు మార్పులను నివారించడానికి sRGB చిత్రాలు sRGB వలె ఉంచబడతాయి.",
|
||||
"image_preview_description": "ఒకే ఆస్తిని వీక్షించేటప్పుడు మరియు యంత్ర అభ్యాసం కోసం మెటాడేటా లేని మధ్యస్థ-పరిమాణ చిత్రం ఉపయోగించబడుతుంది",
|
||||
"image_preview_quality_description": "1-100 వరకు ప్రివ్యూ నాణ్యత. ఎక్కువ ఉంటే మంచిది, కానీ పెద్ద ఫైళ్లను ఉత్పత్తి చేస్తుంది మరియు యాప్ ప్రతిస్పందనను తగ్గిస్తుంది. తక్కువ విలువను సెట్ చేయడం వల్ల మెషిన్ లెర్నింగ్ నాణ్యత ప్రభావితం కావచ్చు.",
|
||||
"image_quality": "నాణ్యత",
|
||||
"image_settings": "చిత్రం సెట్టింగ్లు",
|
||||
"image_settings_description": "రూపొందించబడిన చిత్రాల నాణ్యత మరియు రిజల్యూషన్ను నిర్వహించండి",
|
||||
|
||||
@@ -96,7 +96,7 @@
|
||||
"library_scanning_enable_description": "เปิดการสแกนคลังภาพเป็นระยะ",
|
||||
"library_settings": "คลังภาพภายนอก",
|
||||
"library_settings_description": "จัดการการตั้งค่าคลังภาพภายนอก",
|
||||
"library_tasks_description": "สแกนคลังภาพภายนอกสำหรับทรัพยากรใหม่และ/หรือที่เปลี่ยนแปลง",
|
||||
"library_tasks_description": "ทำงานคลังภาพ",
|
||||
"library_watching_enable_description": "ดูคลังภาพภายนอกสำหรับการเปลี่ยนแปลงของไฟล์",
|
||||
"library_watching_settings": "การดูคลังภาพภายนอก (ฟีเจอร์ทดลอง)",
|
||||
"library_watching_settings_description": "หาไฟล์ที่เปลี่ยนแปลงโดยอัตโนมัติ",
|
||||
@@ -1311,4 +1311,4 @@
|
||||
"yes": "ใช่",
|
||||
"you_dont_have_any_shared_links": "คุณไม่ได้มีลิงก์ที่แชร์",
|
||||
"zoom_image": "ซูมรูปภาพ"
|
||||
}
|
||||
}
|
||||
@@ -302,7 +302,7 @@
|
||||
"transcoding_max_b_frames": "Максимальна кількість проміжних кадрів",
|
||||
"transcoding_max_b_frames_description": "Вищі значення покращують ефективність стиснення, але збільшують час кодування. Можуть бути несумісні з апаратним прискоренням на старих пристроях. Значення 0 вимикає B-фрейми, а -1 автоматично налаштовує це значення.",
|
||||
"transcoding_max_bitrate": "Максимальний бітрейт",
|
||||
"transcoding_max_bitrate_description": "Встановлення максимального бітрейту дозволяє зробити розміри файлів більш передбачуваними за мінорну вартість якості. Наприклад, для 720p типові значення: 2600 кбіт/с для VP9 або HEVC, або 4500 кбіт/с для H.264. Вимикається, якщо встановлено 0.",
|
||||
"transcoding_max_bitrate_description": "Встановлення максимального бітрейту дозволяє зробити розміри файлів більш передбачуваними за мінорну вартість якості. Наприклад, для 720p типові значення: 2600к для VP9 або HEVC, або 4500к для H.264. Вимикається, якщо встановлено 0.",
|
||||
"transcoding_max_keyframe_interval": "Максимальний інтервал ключових кадрів",
|
||||
"transcoding_max_keyframe_interval_description": "Встановлює максимальну відстань між ключовими кадрами. Нижчі значення погіршують ефективність стиснення, але покращують час пошуку і можуть покращити якість в сценах з швидкими рухами. Значення 0 автоматично встановлює це значення.",
|
||||
"transcoding_optimal_description": "Відео з роздільною здатністю вище цільової або не в прийнятому форматі",
|
||||
@@ -1079,8 +1079,6 @@
|
||||
"remove_from_album": "Видалити з альбому",
|
||||
"remove_from_favorites": "Видалити з обраного",
|
||||
"remove_from_shared_link": "Видалити зі спільного посилання",
|
||||
"remove_memory": "Видалити спогад",
|
||||
"remove_photo_from_memory": "Видалити фото з цього спогаду",
|
||||
"remove_url": "Видалити URL",
|
||||
"remove_user": "Видалити користувача",
|
||||
"removed_api_key": "Видалено ключ API: {name}",
|
||||
@@ -1151,7 +1149,6 @@
|
||||
"searching_locales": "Триває пошук перекладів...",
|
||||
"second": "Секунда",
|
||||
"see_all_people": "Переглянути всіх людей",
|
||||
"select": "Виберіть",
|
||||
"select_album_cover": "Обрати обкладинку альбому",
|
||||
"select_all": "Вибрати все",
|
||||
"select_all_duplicates": "Вибрати всі дублікати",
|
||||
|
||||
19
i18n/ur.json
19
i18n/ur.json
@@ -1,20 +1,3 @@
|
||||
{
|
||||
"about": "متعلق",
|
||||
"account": "اکاؤنٹ",
|
||||
"account_settings": "اکاؤنٹ کی ترتیبات",
|
||||
"action": "عمل",
|
||||
"actions": "اعمال",
|
||||
"active": "فعال",
|
||||
"activity": "سرگرمی",
|
||||
"add": "شامل کریں",
|
||||
"add_a_description": "تفصیل شامل کریں",
|
||||
"add_a_location": "مقام شامل کریں",
|
||||
"add_a_name": "نام شامل کریں",
|
||||
"add_a_title": "عنوان شامل کریں",
|
||||
"add_exclusion_pattern": "خارج کرنے کا نمونہ شامل کریں",
|
||||
"add_import_path": "درآمد کا راستہ شامل کریں",
|
||||
"add_location": "مقام شامل کریں",
|
||||
"add_more_users": "مزید صارفین شامل کریں",
|
||||
"add_partner": "ساتھی شامل کریں",
|
||||
"add_path": "راستہ شامل کریں"
|
||||
"about": "متعلق"
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"about": "关于",
|
||||
"account": "账户",
|
||||
"account_settings": "账户设置",
|
||||
"acknowledge": "我知道了",
|
||||
"acknowledge": "确认",
|
||||
"action": "操作",
|
||||
"actions": "操作",
|
||||
"active": "正在处理",
|
||||
@@ -893,7 +893,7 @@
|
||||
"moved_to_trash": "已放入回收站",
|
||||
"mute_memories": "静音回忆",
|
||||
"my_albums": "我的相册",
|
||||
"name": "名称",
|
||||
"name": "姓名",
|
||||
"name_or_nickname": "名称或昵称",
|
||||
"never": "永不过期",
|
||||
"new_album": "新相册",
|
||||
@@ -987,7 +987,6 @@
|
||||
"permanently_deleted_asset": "永久删除的项目",
|
||||
"permanently_deleted_assets_count": "{count, plural, one {#个项目} other {#个项目}}已删除",
|
||||
"person": "人物",
|
||||
"person_birthdate": "出生于{date}",
|
||||
"person_hidden": "{name}{hidden, select, true {(已隐藏)} other {}}",
|
||||
"photo_shared_all_users": "看起来您已与所有用户共享了此相册,或者您根本没有任何用户可共享。",
|
||||
"photos": "照片",
|
||||
@@ -1067,20 +1066,18 @@
|
||||
"refreshed": "已刷新",
|
||||
"refreshes_every_file": "重新扫描所有现有文件和新文件",
|
||||
"refreshing_encoded_video": "正在刷新已编码视频",
|
||||
"refreshing_faces": "正在面部重新识别",
|
||||
"refreshing_faces": "正在刷新人脸",
|
||||
"refreshing_metadata": "正在刷新元数据",
|
||||
"regenerating_thumbnails": "正在重新生成缩略图",
|
||||
"remove": "移除",
|
||||
"remove_assets_album_confirmation": "确定要从图库中移除{count, plural, one {#个项目} other {#个项目}}?",
|
||||
"remove_assets_album_confirmation": "确定要从项目中移除{count, plural, one {#个项目} other {#个项目}}?",
|
||||
"remove_assets_shared_link_confirmation": "确定要从共享链接中移除{count, plural, one {#个项目} other {#个项目}}?",
|
||||
"remove_assets_title": "移除项目?",
|
||||
"remove_custom_date_range": "取消自定义日期范围",
|
||||
"remove_deleted_assets": "彻底删除文件",
|
||||
"remove_deleted_assets": "删除离线文件",
|
||||
"remove_from_album": "从相册中移除",
|
||||
"remove_from_favorites": "移出收藏",
|
||||
"remove_from_shared_link": "从共享链接中移除",
|
||||
"remove_memory": "移出回忆区",
|
||||
"remove_photo_from_memory": "从当前回忆区移除照片",
|
||||
"remove_url": "移除 URL",
|
||||
"remove_user": "移除用户",
|
||||
"removed_api_key": "已移除 API Key:{name}",
|
||||
@@ -1088,32 +1085,32 @@
|
||||
"removed_from_favorites": "从收藏中移除",
|
||||
"removed_from_favorites_count": "从收藏中移除{count, plural, other {#项}}",
|
||||
"removed_memory": "已删除的回忆",
|
||||
"removed_photo_from_memory": "从回忆区中删除的照片",
|
||||
"removed_photo_from_memory": "从回忆中删除的照片",
|
||||
"removed_tagged_assets": "从 {count, plural, one {# 个项目} other {# 个项目}}中删除标签",
|
||||
"rename": "重命名",
|
||||
"repair": "修复",
|
||||
"repair_no_results_message": "未跟踪和缺失的文件将在此处显示",
|
||||
"replace_with_upload": "上传并替换",
|
||||
"replace_with_upload": "上传以替换",
|
||||
"repository": "库",
|
||||
"require_password": "需要密码",
|
||||
"require_user_to_change_password_on_first_login": "用户在首次登录时必须更改密码",
|
||||
"require_user_to_change_password_on_first_login": "要求用户在首次登录时更改密码",
|
||||
"rescan": "重新扫描",
|
||||
"reset": "重置",
|
||||
"reset_password": "重置密码",
|
||||
"reset_people_visibility": "重置人物识别",
|
||||
"reset_people_visibility": "重置人物可见性",
|
||||
"reset_to_default": "恢复默认值",
|
||||
"resolve_duplicates": "处理重复项",
|
||||
"resolved_all_duplicates": "处理所有重复项",
|
||||
"resolved_all_duplicates": "解决所有重复问题",
|
||||
"restore": "恢复",
|
||||
"restore_all": "恢复全部",
|
||||
"restore_all": "恢复所有",
|
||||
"restore_user": "恢复用户",
|
||||
"restored_asset": "已恢复项目",
|
||||
"resume": "继续",
|
||||
"retry_upload": "重新上传",
|
||||
"review_duplicates": "检查重复项",
|
||||
"role": "选择用户权限",
|
||||
"role_editor": "可编辑",
|
||||
"role_viewer": "仅查看",
|
||||
"role": "角色",
|
||||
"role_editor": "编辑者",
|
||||
"role_viewer": "查看者",
|
||||
"save": "保存",
|
||||
"saved_api_key": "已保存的 API Key",
|
||||
"saved_profile": "已保存资料",
|
||||
@@ -1125,39 +1122,38 @@
|
||||
"scanning_for_album": "扫描相册中...",
|
||||
"search": "搜索",
|
||||
"search_albums": "搜索相册",
|
||||
"search_by_context": "通过描述的场景查找",
|
||||
"search_by_description": "通过描述查找",
|
||||
"search_by_context": "按照片情景搜索",
|
||||
"search_by_description": "按描述搜索",
|
||||
"search_by_description_example": "在沙巴徒步的日子",
|
||||
"search_by_filename": "按文件名或扩展名查找",
|
||||
"search_by_filename": "按文件名搜索",
|
||||
"search_by_filename_example": "如 IMG_1234.JPG 或 PNG",
|
||||
"search_camera_make": "按相机品牌查找...",
|
||||
"search_camera_model": "按相机型号查找...",
|
||||
"search_city": "按城市查找...",
|
||||
"search_country": "按国家查找...",
|
||||
"search_for": "查找",
|
||||
"search_for_existing_person": "查找已有人物",
|
||||
"search_camera_make": "搜索相机品牌...",
|
||||
"search_camera_model": "搜索相机型号...",
|
||||
"search_city": "搜索城市...",
|
||||
"search_country": "搜索国家...",
|
||||
"search_for": "搜索",
|
||||
"search_for_existing_person": "搜索已有人物",
|
||||
"search_no_people": "找不到人物",
|
||||
"search_no_people_named": "人物“{name}”不存在",
|
||||
"search_options": "搜索选项",
|
||||
"search_people": "按人物查找",
|
||||
"search_places": "按地点查找",
|
||||
"search_rating": "按星级查找...",
|
||||
"search_people": "搜索人物",
|
||||
"search_places": "搜索地点",
|
||||
"search_rating": "按星级搜索...",
|
||||
"search_settings": "搜索设置",
|
||||
"search_state": "按省份查找...",
|
||||
"search_tags": "按标签查找…",
|
||||
"search_timezone": "按时区查找...",
|
||||
"search_type": "按类型查找",
|
||||
"search_your_photos": "查找您的照片",
|
||||
"searching_locales": "根据地区查找...",
|
||||
"search_state": "搜索省份...",
|
||||
"search_tags": "搜索标签…",
|
||||
"search_timezone": "搜索时区...",
|
||||
"search_type": "搜索类型",
|
||||
"search_your_photos": "搜索您的照片",
|
||||
"searching_locales": "搜索地区...",
|
||||
"second": "秒",
|
||||
"see_all_people": "查看所有人物",
|
||||
"select": "选择",
|
||||
"select_album_cover": "选择相册封面",
|
||||
"select_all": "全选",
|
||||
"select_all_duplicates": "选择所有重复项",
|
||||
"select_avatar_color": "选择头像颜色",
|
||||
"select_face": "选择人脸",
|
||||
"select_featured_photo": "选择个性头像",
|
||||
"select_featured_photo": "选择人物头像",
|
||||
"select_from_computer": "从计算机中选择",
|
||||
"select_keep_all": "全部保留",
|
||||
"select_library_owner": "选择图库所有者",
|
||||
@@ -1170,7 +1166,7 @@
|
||||
"send_welcome_email": "发送欢迎邮件",
|
||||
"server_offline": "服务器离线",
|
||||
"server_online": "服务器在线",
|
||||
"server_stats": "服务器状态",
|
||||
"server_stats": "服务统计",
|
||||
"server_version": "服务器版本",
|
||||
"set": "设置",
|
||||
"set_as_album_cover": "设为相册封面",
|
||||
@@ -1378,4 +1374,4 @@
|
||||
"yes": "是",
|
||||
"you_dont_have_any_shared_links": "您没有任何共享链接",
|
||||
"zoom_image": "缩放图像"
|
||||
}
|
||||
}
|
||||
22
machine-learning/.gitignore
vendored
22
machine-learning/.gitignore
vendored
@@ -1,27 +1,5 @@
|
||||
*.zip
|
||||
*.onnx
|
||||
*.rknn
|
||||
*.npy
|
||||
*_attr__value
|
||||
*.weight
|
||||
*.bias
|
||||
onnx__*
|
||||
*in_proj_bias
|
||||
*.proj
|
||||
*.latent
|
||||
*.pos_embed
|
||||
vocab.txt
|
||||
export/immich_model_exporter/models/**/README.md
|
||||
export/**/results/*.json
|
||||
export/**/root
|
||||
*.armnn
|
||||
tokenizer.json
|
||||
tokenizer_config.json
|
||||
special_tokens_map.json
|
||||
preprocess_cfg.json
|
||||
config.json
|
||||
merges.txt
|
||||
vocab.json
|
||||
upload/
|
||||
venv/
|
||||
__pycache__/
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
ARG DEVICE=cpu
|
||||
|
||||
FROM python:3.11-bookworm@sha256:d270285656e8f061ae0004297df62ac4b26d5cef9408b9cc9a5bf08c2cd8d60c AS builder-cpu
|
||||
FROM python:3.11-bookworm@sha256:68a8863d0625f42d47e0684f33ca02f19d6094ef859a8af237aaf645195ed477 AS builder-cpu
|
||||
|
||||
FROM builder-cpu AS builder-openvino
|
||||
|
||||
@@ -15,36 +15,6 @@ RUN mkdir /opt/armnn && \
|
||||
cd /opt/ann && \
|
||||
sh build.sh
|
||||
|
||||
FROM builder-cpu AS builder-rknn
|
||||
|
||||
# Warning: 25GiB+ disk space required to pull this image
|
||||
# TODO: find a way to reduce the image size
|
||||
FROM rocm/dev-ubuntu-22.04:6.3.4-complete@sha256:1f7e92ca7e3a3785680473329ed1091fc99db3e90fcb3a1688f2933e870ed76b AS builder-rocm
|
||||
|
||||
WORKDIR /code
|
||||
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends wget git python3.10-venv
|
||||
RUN wget -nv https://github.com/Kitware/CMake/releases/download/v3.30.1/cmake-3.30.1-linux-x86_64.sh && \
|
||||
chmod +x cmake-3.30.1-linux-x86_64.sh && \
|
||||
mkdir -p /code/cmake-3.30.1-linux-x86_64 && \
|
||||
./cmake-3.30.1-linux-x86_64.sh --skip-license --prefix=/code/cmake-3.30.1-linux-x86_64 && \
|
||||
rm cmake-3.30.1-linux-x86_64.sh
|
||||
|
||||
ENV PATH=/code/cmake-3.30.1-linux-x86_64/bin:${PATH}
|
||||
|
||||
RUN git clone --single-branch --branch v1.20.1 --recursive "https://github.com/Microsoft/onnxruntime" onnxruntime
|
||||
WORKDIR /code/onnxruntime
|
||||
# Fix for multi-threading based on comments in https://github.com/microsoft/onnxruntime/pull/19567
|
||||
# TODO: find a way to fix this without disabling algo caching
|
||||
COPY ./patches/* /tmp/
|
||||
RUN git apply /tmp/*.patch
|
||||
|
||||
RUN /bin/sh ./dockerfiles/scripts/install_common_deps.sh
|
||||
# Note: the `parallel` setting uses a substantial amount of RAM
|
||||
RUN ./build.sh --allow_running_as_root --config Release --build_wheel --update --build --parallel 17 --cmake_extra_defines\
|
||||
ONNXRUNTIME_VERSION=1.20.1 --skip_tests --use_rocm --rocm_home=/opt/rocm
|
||||
RUN mv /code/onnxruntime/build/Linux/Release/dist/*.whl /opt/
|
||||
|
||||
FROM builder-${DEVICE} AS builder
|
||||
|
||||
ARG DEVICE
|
||||
@@ -55,25 +25,22 @@ WORKDIR /usr/src/app
|
||||
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends g++
|
||||
|
||||
COPY --from=ghcr.io/astral-sh/uv:latest@sha256:cb641b1979723dc5ab87d61f079000009edc107d30ae7cbb6e7419fdac044e9f /uv /uvx /bin/
|
||||
COPY --from=ghcr.io/astral-sh/uv:latest@sha256:562193a4a9d398f8aedddcb223e583da394ee735de36b5815f8f1d22cb49be15 /uv /uvx /bin/
|
||||
RUN --mount=type=cache,target=/root/.cache/uv \
|
||||
--mount=type=bind,source=uv.lock,target=uv.lock \
|
||||
--mount=type=bind,source=pyproject.toml,target=pyproject.toml \
|
||||
uv sync --frozen --extra ${DEVICE} --no-dev --no-editable --no-install-project --compile-bytecode --no-progress --active --link-mode copy
|
||||
RUN if [ "$DEVICE" = "rocm" ]; then \
|
||||
uv pip install /opt/onnxruntime_rocm-*.whl; \
|
||||
fi
|
||||
|
||||
FROM python:3.11-slim-bookworm@sha256:7029b00486ac40bed03e36775b864d3f3d39dcbdf19cd45e6a52d541e6c178f0 AS prod-cpu
|
||||
FROM python:3.11-slim-bookworm@sha256:614c8691ab74150465ec9123378cd4dde7a6e57be9e558c3108df40664667a4c AS prod-cpu
|
||||
|
||||
FROM prod-cpu AS prod-openvino
|
||||
|
||||
RUN apt-get update && \
|
||||
apt-get install --no-install-recommends -yqq ocl-icd-libopencl1 wget && \
|
||||
wget -nv https://github.com/intel/intel-graphics-compiler/releases/download/igc-1.0.17384.11/intel-igc-core_1.0.17384.11_amd64.deb && \
|
||||
wget -nv https://github.com/intel/intel-graphics-compiler/releases/download/igc-1.0.17384.11/intel-igc-opencl_1.0.17384.11_amd64.deb && \
|
||||
wget -nv https://github.com/intel/compute-runtime/releases/download/24.31.30508.7/intel-opencl-icd_24.31.30508.7_amd64.deb && \
|
||||
wget -nv https://github.com/intel/compute-runtime/releases/download/24.31.30508.7/libigdgmm12_22.4.1_amd64.deb && \
|
||||
wget https://github.com/intel/intel-graphics-compiler/releases/download/igc-1.0.17384.11/intel-igc-core_1.0.17384.11_amd64.deb && \
|
||||
wget https://github.com/intel/intel-graphics-compiler/releases/download/igc-1.0.17384.11/intel-igc-opencl_1.0.17384.11_amd64.deb && \
|
||||
wget https://github.com/intel/compute-runtime/releases/download/24.31.30508.7/intel-opencl-icd_24.31.30508.7_amd64.deb && \
|
||||
wget https://github.com/intel/compute-runtime/releases/download/24.31.30508.7/libigdgmm12_22.4.1_amd64.deb && \
|
||||
dpkg -i *.deb && \
|
||||
rm *.deb && \
|
||||
apt-get remove wget -yqq && \
|
||||
@@ -90,8 +57,6 @@ COPY --from=builder-cuda /usr/local/bin/python3 /usr/local/bin/python3
|
||||
COPY --from=builder-cuda /usr/local/lib/python3.11 /usr/local/lib/python3.11
|
||||
COPY --from=builder-cuda /usr/local/lib/libpython3.11.so /usr/local/lib/libpython3.11.so
|
||||
|
||||
FROM rocm/dev-ubuntu-22.04:6.3.4-complete@sha256:1f7e92ca7e3a3785680473329ed1091fc99db3e90fcb3a1688f2933e870ed76b AS prod-rocm
|
||||
|
||||
FROM prod-cpu AS prod-armnn
|
||||
|
||||
ENV LD_LIBRARY_PATH=/opt/armnn
|
||||
@@ -112,16 +77,11 @@ COPY --from=builder-armnn \
|
||||
/opt/ann/build.sh \
|
||||
/opt/armnn/
|
||||
|
||||
FROM prod-cpu AS prod-rknn
|
||||
|
||||
ADD --checksum=sha256:73993ed4b440460825f21611731564503cc1d5a0c123746477da6cd574f34885 https://github.com/airockchip/rknn-toolkit2/raw/refs/tags/v2.3.0/rknpu2/runtime/Linux/librknn_api/aarch64/librknnrt.so /usr/lib/
|
||||
|
||||
FROM prod-${DEVICE} AS prod
|
||||
|
||||
ARG DEVICE
|
||||
|
||||
RUN apt-get update && \
|
||||
apt-get install -y --no-install-recommends tini $(if ! [ "$DEVICE" = "openvino" ] && ! [ "$DEVICE" = "rocm" ]; then echo "libmimalloc2.0"; fi) && \
|
||||
apt-get install -y --no-install-recommends tini $(if ! [ "$DEVICE" = "openvino" ]; then echo "libmimalloc2.0"; fi) && \
|
||||
apt-get autoremove -yqq && \
|
||||
apt-get clean && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
@@ -163,4 +123,4 @@ ENV IMMICH_SOURCE_URL=https://github.com/immich-app/immich/commit/${BUILD_SOURCE
|
||||
ENTRYPOINT ["tini", "--"]
|
||||
CMD ["./start.sh"]
|
||||
|
||||
HEALTHCHECK CMD python3 healthcheck.py
|
||||
HEALTHCHECK CMD python3 healthcheck.py
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
This project uses [uv](https://docs.astral.sh/uv/getting-started/installation/), so be sure to install it first.
|
||||
Running `uv sync --extra cpu` will install everything you need in an isolated virtual environment.
|
||||
CUDA, ROCM and OpenVINO are supported as acceleration APIs. To use them, you can replace `--extra cpu` with either of `--extra cuda`, `--extra rocm` or `--extra openvino`. In the case of CUDA, a [compute capability](https://developer.nvidia.com/cuda-gpus) of 5.2 or higher is required.
|
||||
CUDA and OpenVINO are supported as acceleration APIs. To use them, you can replace `--group cpu` with either of `--group cuda` or `--group openvino`. In the case of CUDA, a [compute capability](https://developer.nvidia.com/cuda-gpus) of 5.2 or higher is required.
|
||||
|
||||
To add or remove dependencies, you can use the commands `uv add $PACKAGE_NAME` and `uv remove $PACKAGE_NAME`, respectively.
|
||||
Be sure to commit the `uv.lock` and `pyproject.toml` files with `uv lock` to reflect any changes in dependencies.
|
||||
|
||||
@@ -64,8 +64,6 @@ class Settings(BaseSettings):
|
||||
ann: bool = True
|
||||
ann_fp16_turbo: bool = False
|
||||
ann_tuning_level: int = 2
|
||||
rknn: bool = True
|
||||
rknn_threads: int = 1
|
||||
preload: PreloadModelData | None = None
|
||||
max_batch_size: MaxBatchSize | None = None
|
||||
|
||||
|
||||
@@ -136,12 +136,6 @@ def ann_session() -> Iterator[mock.Mock]:
|
||||
yield mocked
|
||||
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
def rknn_session() -> Iterator[mock.Mock]:
|
||||
with mock.patch("app.sessions.rknn.RknnPoolExecutor") as mocked:
|
||||
yield mocked
|
||||
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
def rmtree() -> Iterator[mock.Mock]:
|
||||
with mock.patch("app.models.base.rmtree", autospec=True) as mocked:
|
||||
|
||||
@@ -226,9 +226,9 @@ async def load(model: InferenceModel) -> InferenceModel:
|
||||
except FileNotFoundError as e:
|
||||
if model.model_format == ModelFormat.ONNX:
|
||||
raise e
|
||||
log.exception(e)
|
||||
log.warning(
|
||||
f"{model.model_format.upper()} is available, but model '{model.model_name}' does not support it.",
|
||||
exc_info=e,
|
||||
f"{model.model_format.upper()} is available, but model '{model.model_name}' does not support it."
|
||||
)
|
||||
model.model_format = ModelFormat.ONNX
|
||||
model.load()
|
||||
|
||||
@@ -8,7 +8,6 @@ from typing import Any, ClassVar
|
||||
from huggingface_hub import snapshot_download
|
||||
|
||||
import ann.ann
|
||||
import app.sessions.rknn as rknn
|
||||
from app.sessions.ort import OrtSession
|
||||
|
||||
from ..config import clean_name, log, settings
|
||||
@@ -67,17 +66,12 @@ class InferenceModel(ABC):
|
||||
pass
|
||||
|
||||
def _download(self) -> None:
|
||||
ignored_patterns: dict[ModelFormat, list[str]] = {
|
||||
ModelFormat.ONNX: ["*.armnn", "*.rknn"],
|
||||
ModelFormat.ARMNN: ["*.rknn"],
|
||||
ModelFormat.RKNN: ["*.armnn"],
|
||||
}
|
||||
|
||||
ignore_patterns = [] if self.model_format == ModelFormat.ARMNN else ["*.armnn"]
|
||||
snapshot_download(
|
||||
f"immich-app/{clean_name(self.model_name)}",
|
||||
cache_dir=self.cache_dir,
|
||||
local_dir=self.cache_dir,
|
||||
ignore_patterns=ignored_patterns.get(self.model_format, []),
|
||||
ignore_patterns=ignore_patterns,
|
||||
)
|
||||
|
||||
def _load(self) -> ModelSession:
|
||||
@@ -114,25 +108,17 @@ class InferenceModel(ABC):
|
||||
session: ModelSession = AnnSession(model_path)
|
||||
case ".onnx":
|
||||
session = OrtSession(model_path)
|
||||
case ".rknn":
|
||||
session = rknn.RknnSession(model_path)
|
||||
case _:
|
||||
raise ValueError(f"Unsupported model file type: {model_path.suffix}")
|
||||
return session
|
||||
|
||||
def model_path_for_format(self, model_format: ModelFormat) -> Path:
|
||||
model_path_prefix = rknn.model_prefix if model_format == ModelFormat.RKNN else None
|
||||
if model_path_prefix:
|
||||
return self.model_dir / model_path_prefix / f"model.{model_format}"
|
||||
return self.model_dir / f"model.{model_format}"
|
||||
|
||||
@property
|
||||
def model_dir(self) -> Path:
|
||||
return self.cache_dir / self.model_type.value
|
||||
|
||||
@property
|
||||
def model_path(self) -> Path:
|
||||
return self.model_path_for_format(self.model_format)
|
||||
return self.model_dir / f"model.{self.model_format}"
|
||||
|
||||
@property
|
||||
def model_task(self) -> ModelTask:
|
||||
@@ -169,9 +155,4 @@ class InferenceModel(ABC):
|
||||
|
||||
@property
|
||||
def _model_format_default(self) -> ModelFormat:
|
||||
if rknn.is_available:
|
||||
return ModelFormat.RKNN
|
||||
elif ann.ann.is_available and settings.ann:
|
||||
return ModelFormat.ARMNN
|
||||
else:
|
||||
return ModelFormat.ONNX
|
||||
return ModelFormat.ARMNN if ann.ann.is_available and settings.ann else ModelFormat.ONNX
|
||||
|
||||
@@ -44,18 +44,6 @@ _OPENCLIP_MODELS = {
|
||||
"nllb-clip-base-siglip__v1",
|
||||
"nllb-clip-large-siglip__mrl",
|
||||
"nllb-clip-large-siglip__v1",
|
||||
"ViT-B-16-SigLIP2__webli",
|
||||
"ViT-B-32-SigLIP2-256__webli",
|
||||
"ViT-L-16-SigLIP2-256__webli",
|
||||
"ViT-L-16-SigLIP2-384__webli",
|
||||
"ViT-L-16-SigLIP2-512__webli",
|
||||
"ViT-SO400M-14-SigLIP2-378__webli",
|
||||
"ViT-SO400M-14-SigLIP2__webli",
|
||||
"ViT-SO400M-16-SigLIP2-256__webli",
|
||||
"ViT-SO400M-16-SigLIP2-384__webli",
|
||||
"ViT-SO400M-16-SigLIP2-512__webli",
|
||||
"ViT-gopt-16-SigLIP2-256__webli",
|
||||
"ViT-gopt-16-SigLIP2-384__webli",
|
||||
}
|
||||
|
||||
|
||||
@@ -75,15 +63,7 @@ _INSIGHTFACE_MODELS = {
|
||||
}
|
||||
|
||||
|
||||
SUPPORTED_PROVIDERS = [
|
||||
"CUDAExecutionProvider",
|
||||
"ROCMExecutionProvider",
|
||||
"OpenVINOExecutionProvider",
|
||||
"CPUExecutionProvider",
|
||||
]
|
||||
|
||||
RKNN_SUPPORTED_SOCS = ["rk3566", "rk3568", "rk3576", "rk3588"]
|
||||
RKNN_COREMASK_SUPPORTED_SOCS = ["rk3576", "rk3588"]
|
||||
SUPPORTED_PROVIDERS = ["CUDAExecutionProvider", "OpenVINOExecutionProvider", "CPUExecutionProvider"]
|
||||
|
||||
|
||||
def get_model_source(model_name: str) -> ModelSource | None:
|
||||
|
||||
@@ -31,7 +31,7 @@ class FaceRecognizer(InferenceModel):
|
||||
self._add_batch_axis(self.model_path)
|
||||
session = self._make_session(self.model_path)
|
||||
self.model = ArcFaceONNX(
|
||||
self.model_path_for_format(ModelFormat.ONNX).as_posix(),
|
||||
self.model_path.with_suffix(".onnx").as_posix(),
|
||||
session=session,
|
||||
)
|
||||
return session
|
||||
|
||||
@@ -35,7 +35,6 @@ class ModelType(StrEnum):
|
||||
class ModelFormat(StrEnum):
|
||||
ARMNN = "armnn"
|
||||
ONNX = "onnx"
|
||||
RKNN = "rknn"
|
||||
|
||||
|
||||
class ModelSource(StrEnum):
|
||||
|
||||
@@ -88,7 +88,7 @@ class OrtSession:
|
||||
match provider:
|
||||
case "CPUExecutionProvider":
|
||||
options = {"arena_extend_strategy": "kSameAsRequested"}
|
||||
case "CUDAExecutionProvider" | "ROCMExecutionProvider":
|
||||
case "CUDAExecutionProvider":
|
||||
options = {"arena_extend_strategy": "kSameAsRequested", "device_id": settings.device_id}
|
||||
case "OpenVINOExecutionProvider":
|
||||
options = {
|
||||
|
||||
@@ -1,76 +0,0 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from pathlib import Path
|
||||
from typing import Any, NamedTuple
|
||||
|
||||
import numpy as np
|
||||
from numpy.typing import NDArray
|
||||
|
||||
from app.config import log, settings
|
||||
from app.schemas import SessionNode
|
||||
|
||||
from .rknnpool import RknnPoolExecutor, is_available, soc_name
|
||||
|
||||
is_available = is_available and settings.rknn
|
||||
model_prefix = Path("rknpu") / soc_name if is_available and soc_name is not None else None
|
||||
|
||||
|
||||
def run_inference(rknn_lite: Any, input: list[NDArray[np.float32]]) -> list[NDArray[np.float32]]:
|
||||
outputs: list[NDArray[np.float32]] = rknn_lite.inference(inputs=input, data_format="nchw")
|
||||
return outputs
|
||||
|
||||
|
||||
input_output_mapping: dict[str, dict[str, Any]] = {
|
||||
"detection": {
|
||||
"input": {"norm_tensor:0": (1, 3, 640, 640)},
|
||||
"output": {
|
||||
"norm_tensor:1": (12800, 1),
|
||||
"norm_tensor:2": (3200, 1),
|
||||
"norm_tensor:3": (800, 1),
|
||||
"norm_tensor:4": (12800, 4),
|
||||
"norm_tensor:5": (3200, 4),
|
||||
"norm_tensor:6": (800, 4),
|
||||
"norm_tensor:7": (12800, 10),
|
||||
"norm_tensor:8": (3200, 10),
|
||||
"norm_tensor:9": (800, 10),
|
||||
},
|
||||
},
|
||||
"recognition": {"input": {"norm_tensor:0": (1, 3, 112, 112)}, "output": {"norm_tensor:1": (1, 512)}},
|
||||
}
|
||||
|
||||
|
||||
class RknnSession:
|
||||
def __init__(self, model_path: Path) -> None:
|
||||
self.model_type = "detection" if "detection" in model_path.parts else "recognition"
|
||||
self.tpe = settings.rknn_threads
|
||||
|
||||
log.info(f"Loading RKNN model from {model_path} with {self.tpe} threads.")
|
||||
self.rknnpool = RknnPoolExecutor(model_path=model_path.as_posix(), tpes=self.tpe, func=run_inference)
|
||||
log.info(f"Loaded RKNN model from {model_path} with {self.tpe} threads.")
|
||||
|
||||
def get_inputs(self) -> list[SessionNode]:
|
||||
return [RknnNode(name=k, shape=v) for k, v in input_output_mapping[self.model_type]["input"].items()]
|
||||
|
||||
def get_outputs(self) -> list[SessionNode]:
|
||||
return [RknnNode(name=k, shape=v) for k, v in input_output_mapping[self.model_type]["output"].items()]
|
||||
|
||||
def run(
|
||||
self,
|
||||
output_names: list[str] | None,
|
||||
input_feed: dict[str, NDArray[np.float32]] | dict[str, NDArray[np.int32]],
|
||||
run_options: Any = None,
|
||||
) -> list[NDArray[np.float32]]:
|
||||
input_data: list[NDArray[np.float32]] = [np.ascontiguousarray(v) for v in input_feed.values()]
|
||||
self.rknnpool.put(input_data)
|
||||
res = self.rknnpool.get()
|
||||
if res is None:
|
||||
raise RuntimeError("RKNN inference failed!")
|
||||
return res
|
||||
|
||||
|
||||
class RknnNode(NamedTuple):
|
||||
name: str | None
|
||||
shape: tuple[int, ...]
|
||||
|
||||
|
||||
__all__ = ["RknnSession", "RknnNode", "is_available", "soc_name", "model_prefix"]
|
||||
@@ -1,91 +0,0 @@
|
||||
# This code is from leafqycc/rknn-multi-threaded
|
||||
# Following Apache License 2.0
|
||||
|
||||
import logging
|
||||
from concurrent.futures import Future, ThreadPoolExecutor
|
||||
from pathlib import Path
|
||||
from queue import Queue
|
||||
from typing import Callable
|
||||
|
||||
import numpy as np
|
||||
from numpy.typing import NDArray
|
||||
|
||||
from app.config import log
|
||||
from app.models.constants import RKNN_COREMASK_SUPPORTED_SOCS, RKNN_SUPPORTED_SOCS
|
||||
|
||||
|
||||
def get_soc(device_tree_path: Path | str) -> str | None:
|
||||
try:
|
||||
with Path(device_tree_path).open() as f:
|
||||
device_compatible_str = f.read()
|
||||
for soc in RKNN_SUPPORTED_SOCS:
|
||||
if soc in device_compatible_str:
|
||||
return soc
|
||||
log.warning("Device is not supported for RKNN")
|
||||
except OSError as e:
|
||||
log.warning(f"Could not read {device_tree_path}. Reason: %s", e)
|
||||
return None
|
||||
|
||||
|
||||
soc_name = None
|
||||
is_available = False
|
||||
try:
|
||||
from rknnlite.api import RKNNLite
|
||||
|
||||
soc_name = get_soc("/proc/device-tree/compatible")
|
||||
is_available = soc_name is not None
|
||||
except ImportError:
|
||||
log.debug("RKNN is not available")
|
||||
|
||||
|
||||
def init_rknn(model_path: str) -> "RKNNLite":
|
||||
if not is_available:
|
||||
raise RuntimeError("rknn is not available!")
|
||||
rknn_lite = RKNNLite()
|
||||
rknn_lite.rknn_log.logger.setLevel(logging.ERROR)
|
||||
ret = rknn_lite.load_rknn(model_path)
|
||||
if ret != 0:
|
||||
raise RuntimeError("Failed to load RKNN model")
|
||||
|
||||
if soc_name in RKNN_COREMASK_SUPPORTED_SOCS:
|
||||
ret = rknn_lite.init_runtime(core_mask=RKNNLite.NPU_CORE_AUTO)
|
||||
else:
|
||||
ret = rknn_lite.init_runtime() # Please do not set this parameter on other platforms.
|
||||
|
||||
if ret != 0:
|
||||
raise RuntimeError("Failed to inititalize RKNN runtime environment")
|
||||
|
||||
return rknn_lite
|
||||
|
||||
|
||||
class RknnPoolExecutor:
|
||||
def __init__(
|
||||
self,
|
||||
model_path: str,
|
||||
tpes: int,
|
||||
func: Callable[["RKNNLite", list[NDArray[np.float32]]], list[NDArray[np.float32]]],
|
||||
) -> None:
|
||||
self.tpes = tpes
|
||||
self.queue: Queue[Future[list[NDArray[np.float32]]]] = Queue()
|
||||
self.rknn_pool = [init_rknn(model_path) for _ in range(tpes)]
|
||||
self.pool = ThreadPoolExecutor(max_workers=tpes)
|
||||
self.func = func
|
||||
self.num = 0
|
||||
|
||||
def put(self, inputs: list[NDArray[np.float32]]) -> None:
|
||||
self.queue.put(self.pool.submit(self.func, self.rknn_pool[self.num % self.tpes], inputs))
|
||||
self.num += 1
|
||||
|
||||
def get(self) -> list[NDArray[np.float32]] | None:
|
||||
if self.queue.empty():
|
||||
return None
|
||||
fut = self.queue.get()
|
||||
return fut.result()
|
||||
|
||||
def release(self) -> None:
|
||||
self.pool.shutdown()
|
||||
for rknn_lite in self.rknn_pool:
|
||||
rknn_lite.release()
|
||||
|
||||
def __del__(self) -> None:
|
||||
self.release()
|
||||
@@ -25,7 +25,6 @@ from app.models.facial_recognition.detection import FaceDetector
|
||||
from app.models.facial_recognition.recognition import FaceRecognizer
|
||||
from app.sessions.ann import AnnSession
|
||||
from app.sessions.ort import OrtSession
|
||||
from app.sessions.rknn import RknnSession, run_inference
|
||||
|
||||
from .config import Settings, settings
|
||||
from .models.base import InferenceModel
|
||||
@@ -70,14 +69,6 @@ class TestBase:
|
||||
|
||||
assert encoder.model_format == ModelFormat.ARMNN
|
||||
|
||||
def test_sets_default_model_format_to_rknn_if_available(self, mocker: MockerFixture) -> None:
|
||||
mocker.patch.object(settings, "rknn", True)
|
||||
mocker.patch("app.sessions.rknn.is_available", True)
|
||||
|
||||
encoder = OpenClipTextualEncoder("ViT-B-32__openai")
|
||||
|
||||
assert encoder.model_format == ModelFormat.RKNN
|
||||
|
||||
def test_casts_cache_dir_string_to_path(self) -> None:
|
||||
cache_dir = "/test_cache"
|
||||
encoder = OpenClipTextualEncoder("ViT-B-32__openai", cache_dir=cache_dir)
|
||||
@@ -134,7 +125,7 @@ class TestBase:
|
||||
"immich-app/ViT-B-32__openai",
|
||||
cache_dir=encoder.cache_dir,
|
||||
local_dir=encoder.cache_dir,
|
||||
ignore_patterns=["*.armnn", "*.rknn"],
|
||||
ignore_patterns=["*.armnn"],
|
||||
)
|
||||
|
||||
def test_download_downloads_armnn_if_preferred_format(self, snapshot_download: mock.Mock) -> None:
|
||||
@@ -145,18 +136,7 @@ class TestBase:
|
||||
"immich-app/ViT-B-32__openai",
|
||||
cache_dir=encoder.cache_dir,
|
||||
local_dir=encoder.cache_dir,
|
||||
ignore_patterns=["*.rknn"],
|
||||
)
|
||||
|
||||
def test_download_downloads_rknn_if_preferred_format(self, snapshot_download: mock.Mock) -> None:
|
||||
encoder = OpenClipTextualEncoder("ViT-B-32__openai", model_format=ModelFormat.RKNN)
|
||||
encoder.download()
|
||||
|
||||
snapshot_download.assert_called_once_with(
|
||||
"immich-app/ViT-B-32__openai",
|
||||
cache_dir=encoder.cache_dir,
|
||||
local_dir=encoder.cache_dir,
|
||||
ignore_patterns=["*.armnn"],
|
||||
ignore_patterns=[],
|
||||
)
|
||||
|
||||
def test_throws_exception_if_model_path_does_not_exist(
|
||||
@@ -180,7 +160,6 @@ class TestOrtSession:
|
||||
OV_EP = ["OpenVINOExecutionProvider", "CPUExecutionProvider"]
|
||||
CUDA_EP_OUT_OF_ORDER = ["CPUExecutionProvider", "CUDAExecutionProvider"]
|
||||
TRT_EP = ["TensorrtExecutionProvider", "CUDAExecutionProvider", "CPUExecutionProvider"]
|
||||
ROCM_EP = ["ROCMExecutionProvider", "CPUExecutionProvider"]
|
||||
|
||||
@pytest.mark.providers(CPU_EP)
|
||||
def test_sets_cpu_provider(self, providers: list[str]) -> None:
|
||||
@@ -220,12 +199,6 @@ class TestOrtSession:
|
||||
|
||||
assert session.providers == self.CUDA_EP
|
||||
|
||||
@pytest.mark.providers(ROCM_EP)
|
||||
def test_uses_rocm(self, providers: list[str]) -> None:
|
||||
session = OrtSession("ViT-B-32__openai")
|
||||
|
||||
assert session.providers == self.ROCM_EP
|
||||
|
||||
def test_sets_provider_kwarg(self) -> None:
|
||||
providers = ["CUDAExecutionProvider"]
|
||||
session = OrtSession("ViT-B-32__openai", providers=providers)
|
||||
@@ -242,33 +215,19 @@ class TestOrtSession:
|
||||
{"arena_extend_strategy": "kSameAsRequested"},
|
||||
]
|
||||
|
||||
def test_sets_provider_options_for_openvino(self) -> None:
|
||||
model_path = "/cache/ViT-B-32__openai/textual/model.onnx"
|
||||
def test_sets_device_id_for_openvino(self) -> None:
|
||||
os.environ["MACHINE_LEARNING_DEVICE_ID"] = "1"
|
||||
|
||||
session = OrtSession(model_path, providers=["OpenVINOExecutionProvider"])
|
||||
session = OrtSession("ViT-B-32__openai", providers=["OpenVINOExecutionProvider"])
|
||||
|
||||
assert session.provider_options == [
|
||||
{
|
||||
"device_type": "GPU.1",
|
||||
"precision": "FP32",
|
||||
"cache_dir": "/cache/ViT-B-32__openai/textual/openvino",
|
||||
}
|
||||
]
|
||||
assert session.provider_options[0]["device_type"] == "GPU.1"
|
||||
|
||||
def test_sets_provider_options_for_cuda(self) -> None:
|
||||
def test_sets_device_id_for_cuda(self) -> None:
|
||||
os.environ["MACHINE_LEARNING_DEVICE_ID"] = "1"
|
||||
|
||||
session = OrtSession("ViT-B-32__openai", providers=["CUDAExecutionProvider"])
|
||||
|
||||
assert session.provider_options == [{"arena_extend_strategy": "kSameAsRequested", "device_id": "1"}]
|
||||
|
||||
def test_sets_provider_options_for_rocm(self) -> None:
|
||||
os.environ["MACHINE_LEARNING_DEVICE_ID"] = "1"
|
||||
|
||||
session = OrtSession("ViT-B-32__openai", providers=["ROCMExecutionProvider"])
|
||||
|
||||
assert session.provider_options == [{"arena_extend_strategy": "kSameAsRequested", "device_id": "1"}]
|
||||
assert session.provider_options[0]["device_id"] == "1"
|
||||
|
||||
def test_sets_provider_options_kwarg(self) -> None:
|
||||
session = OrtSession(
|
||||
@@ -369,33 +328,6 @@ class TestAnnSession:
|
||||
np_spy.assert_has_calls([mock.call(input1), mock.call(input2)])
|
||||
|
||||
|
||||
class TestRknnSession:
|
||||
def test_creates_rknn_session(self, rknn_session: mock.Mock, info: mock.Mock, mocker: MockerFixture) -> None:
|
||||
model_path = mock.MagicMock(spec=Path)
|
||||
tpe = 1
|
||||
mocker.patch("app.sessions.rknn.soc_name", "rk3566")
|
||||
mocker.patch("app.sessions.rknn.is_available", True)
|
||||
RknnSession(model_path)
|
||||
|
||||
rknn_session.assert_called_once_with(model_path=model_path.as_posix(), tpes=tpe, func=run_inference)
|
||||
|
||||
info.assert_has_calls([mock.call(f"Loaded RKNN model from {model_path} with {tpe} threads.")])
|
||||
|
||||
def test_run_rknn(self, rknn_session: mock.Mock, mocker: MockerFixture) -> None:
|
||||
rknn_session.return_value.load.return_value = 123
|
||||
np_spy = mocker.spy(np, "ascontiguousarray")
|
||||
mocker.patch("app.sessions.rknn.soc_name", "rk3566")
|
||||
session = RknnSession(Path("ViT-B-32__openai"))
|
||||
[input1, input2] = [np.random.rand(1, 3, 224, 224).astype(np.float32) for _ in range(2)]
|
||||
input_feed = {"input.1": input1, "input.2": input2}
|
||||
|
||||
session.run(None, input_feed)
|
||||
|
||||
rknn_session.return_value.put.assert_called_once_with([input1, input2])
|
||||
np_spy.call_count == 2
|
||||
np_spy.assert_has_calls([mock.call(input1), mock.call(input2)])
|
||||
|
||||
|
||||
class TestCLIP:
|
||||
embedding = np.random.rand(512).astype(np.float32)
|
||||
cache_dir = Path("test_cache")
|
||||
@@ -897,7 +829,9 @@ class TestLoad:
|
||||
mock_model.clear_cache.assert_not_called()
|
||||
mock_model.load.assert_not_called()
|
||||
|
||||
async def test_falls_back_to_onnx_if_other_format_does_not_exist(self, warning: mock.Mock) -> None:
|
||||
async def test_falls_back_to_onnx_if_other_format_does_not_exist(
|
||||
self, exception: mock.Mock, warning: mock.Mock
|
||||
) -> None:
|
||||
mock_model = mock.Mock(spec=InferenceModel)
|
||||
mock_model.model_name = "test_model_name"
|
||||
mock_model.model_type = ModelType.VISUAL
|
||||
@@ -912,9 +846,8 @@ class TestLoad:
|
||||
|
||||
mock_model.clear_cache.assert_not_called()
|
||||
assert mock_model.load.call_count == 2
|
||||
warning.assert_called_once_with(
|
||||
"ARMNN is available, but model 'test_model_name' does not support it.", exc_info=error
|
||||
)
|
||||
exception.assert_called_once_with(error)
|
||||
warning.assert_called_once_with("ARMNN is available, but model 'test_model_name' does not support it.")
|
||||
mock_model.model_format = ModelFormat.ONNX
|
||||
|
||||
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
3.12
|
||||
20
machine-learning/export/Dockerfile
Normal file
20
machine-learning/export/Dockerfile
Normal file
@@ -0,0 +1,20 @@
|
||||
FROM mambaorg/micromamba:bookworm-slim@sha256:e3797091302382ea841498bc93a7b0a50f7c1448333d5e946d2d1608d0c5f43d AS builder
|
||||
|
||||
ENV TRANSFORMERS_CACHE=/cache \
|
||||
PYTHONDONTWRITEBYTECODE=1 \
|
||||
PYTHONUNBUFFERED=1 \
|
||||
PATH="/opt/venv/bin:$PATH" \
|
||||
PYTHONPATH=/usr/src
|
||||
|
||||
COPY --chown=$MAMBA_USER:$MAMBA_USER conda-lock.yml /tmp/conda-lock.yml
|
||||
RUN micromamba install -y -n base -f /tmp/conda-lock.yml && \
|
||||
micromamba remove -y -n base cxx-compiler && \
|
||||
micromamba clean --all --yes
|
||||
|
||||
WORKDIR /usr/src/app
|
||||
|
||||
COPY --chown=$MAMBA_USER:$MAMBA_USER start.sh .
|
||||
COPY --chown=$MAMBA_USER:$MAMBA_USER app .
|
||||
|
||||
ENTRYPOINT ["/usr/local/bin/_entrypoint.sh"]
|
||||
CMD ["./start.sh"]
|
||||
4328
machine-learning/export/conda-lock.yml
Normal file
4328
machine-learning/export/conda-lock.yml
Normal file
File diff suppressed because it is too large
Load Diff
15
machine-learning/export/env.dev.yaml
Normal file
15
machine-learning/export/env.dev.yaml
Normal file
@@ -0,0 +1,15 @@
|
||||
name: base
|
||||
channels:
|
||||
- conda-forge
|
||||
platforms:
|
||||
- linux-64
|
||||
- linux-aarch64
|
||||
dependencies:
|
||||
- black
|
||||
- conda-lock
|
||||
- mypy
|
||||
- pytest
|
||||
- pytest-cov
|
||||
- pytest-mock
|
||||
- ruff
|
||||
category: dev
|
||||
25
machine-learning/export/env.yaml
Normal file
25
machine-learning/export/env.yaml
Normal file
@@ -0,0 +1,25 @@
|
||||
name: base
|
||||
channels:
|
||||
- conda-forge
|
||||
- nvidia
|
||||
- pytorch
|
||||
platforms:
|
||||
- linux-64
|
||||
dependencies:
|
||||
- cxx-compiler
|
||||
- onnx==1.*
|
||||
- onnxruntime==1.*
|
||||
- open-clip-torch==2.*
|
||||
- orjson==3.*
|
||||
- pip
|
||||
- python==3.11.*
|
||||
- pytorch>=2.3
|
||||
- rich==13.*
|
||||
- safetensors==0.*
|
||||
- setuptools==68.*
|
||||
- torchvision
|
||||
- transformers==4.*
|
||||
- pip:
|
||||
- multilingual-clip
|
||||
- onnxsim
|
||||
category: main
|
||||
@@ -1,165 +0,0 @@
|
||||
import json
|
||||
import resource
|
||||
from pathlib import Path
|
||||
|
||||
import typer
|
||||
from tenacity import retry, stop_after_attempt, wait_fixed
|
||||
from typing_extensions import Annotated
|
||||
|
||||
from .exporters.constants import DELETE_PATTERNS, SOURCE_TO_METADATA, ModelSource, ModelTask
|
||||
from .exporters.onnx import export as onnx_export
|
||||
from .exporters.rknn import export as rknn_export
|
||||
|
||||
app = typer.Typer(pretty_exceptions_show_locals=False)
|
||||
|
||||
|
||||
def generate_readme(model_name: str, model_source: ModelSource) -> str:
|
||||
(name, link, type) = SOURCE_TO_METADATA[model_source]
|
||||
match model_source:
|
||||
case ModelSource.MCLIP:
|
||||
tags = ["immich", "clip", "multilingual"]
|
||||
case ModelSource.OPENCLIP:
|
||||
tags = ["immich", "clip"]
|
||||
lowered = model_name.lower()
|
||||
if "xlm" in lowered or "nllb" in lowered:
|
||||
tags.append("multilingual")
|
||||
case ModelSource.INSIGHTFACE:
|
||||
tags = ["immich", "facial-recognition"]
|
||||
case _:
|
||||
raise ValueError(f"Unsupported model source {model_source}")
|
||||
|
||||
return f"""---
|
||||
tags:
|
||||
{" - " + "\n - ".join(tags)}
|
||||
---
|
||||
# Model Description
|
||||
|
||||
This repo contains ONNX exports for the associated {type} model by {name}. See the [{name}]({link}) repo for more info.
|
||||
|
||||
This repo is specifically intended for use with [Immich](https://immich.app/), a self-hosted photo library.
|
||||
"""
|
||||
|
||||
|
||||
def clean_name(model_name: str) -> str:
|
||||
hf_model_name = model_name.split("/")[-1]
|
||||
hf_model_name = hf_model_name.replace("xlm-roberta-large", "XLM-Roberta-Large")
|
||||
hf_model_name = hf_model_name.replace("xlm-roberta-base", "XLM-Roberta-Base")
|
||||
return hf_model_name
|
||||
|
||||
|
||||
@app.command()
|
||||
def export(model_name: str, model_source: ModelSource, output_dir: Path = Path("models"), cache: bool = True) -> None:
|
||||
hf_model_name = clean_name(model_name)
|
||||
output_dir = output_dir / hf_model_name
|
||||
match model_source:
|
||||
case ModelSource.MCLIP | ModelSource.OPENCLIP:
|
||||
output_dir.mkdir(parents=True, exist_ok=True)
|
||||
onnx_export(model_name, model_source, output_dir, cache=cache)
|
||||
case ModelSource.INSIGHTFACE:
|
||||
from huggingface_hub import snapshot_download
|
||||
|
||||
# TODO: start from insightface dump instead of downloading from HF
|
||||
snapshot_download(f"immich-app/{hf_model_name}", local_dir=output_dir)
|
||||
case _:
|
||||
raise ValueError(f"Unsupported model source {model_source}")
|
||||
|
||||
try:
|
||||
rknn_export(output_dir, cache=cache)
|
||||
except Exception as e:
|
||||
print(f"Failed to export model {model_name} to rknn: {e}")
|
||||
(output_dir / "rknpu").unlink(missing_ok=True)
|
||||
|
||||
readme_path = output_dir / "README.md"
|
||||
if not (cache or readme_path.exists()):
|
||||
with open(readme_path, "w") as f:
|
||||
f.write(generate_readme(model_name, model_source))
|
||||
|
||||
|
||||
@app.command()
|
||||
def profile(model_dir: Path, model_task: ModelTask, output_path: Path) -> None:
|
||||
from timeit import timeit
|
||||
|
||||
import numpy as np
|
||||
import onnxruntime as ort
|
||||
|
||||
np.random.seed(0)
|
||||
|
||||
sess_options = ort.SessionOptions()
|
||||
sess_options.enable_cpu_mem_arena = False
|
||||
providers = ["CPUExecutionProvider"]
|
||||
provider_options = [{"arena_extend_strategy": "kSameAsRequested"}]
|
||||
match model_task:
|
||||
case ModelTask.SEARCH:
|
||||
textual = ort.InferenceSession(
|
||||
model_dir / "textual" / "model.onnx",
|
||||
sess_options=sess_options,
|
||||
providers=providers,
|
||||
provider_options=provider_options,
|
||||
)
|
||||
tokens = {node.name: np.random.rand(*node.shape).astype(np.int32) for node in textual.get_inputs()}
|
||||
|
||||
visual = ort.InferenceSession(
|
||||
model_dir / "visual" / "model.onnx",
|
||||
sess_options=sess_options,
|
||||
providers=providers,
|
||||
provider_options=provider_options,
|
||||
)
|
||||
image = {node.name: np.random.rand(*node.shape).astype(np.float32) for node in visual.get_inputs()}
|
||||
|
||||
def predict() -> None:
|
||||
textual.run(None, tokens)
|
||||
visual.run(None, image)
|
||||
|
||||
case ModelTask.FACIAL_RECOGNITION:
|
||||
detection = ort.InferenceSession(
|
||||
model_dir / "detection" / "model.onnx",
|
||||
sess_options=sess_options,
|
||||
providers=providers,
|
||||
provider_options=provider_options,
|
||||
)
|
||||
image = {node.name: np.random.rand(1, 3, 640, 640).astype(np.float32) for node in detection.get_inputs()}
|
||||
|
||||
recognition = ort.InferenceSession(
|
||||
model_dir / "recognition" / "model.onnx",
|
||||
sess_options=sess_options,
|
||||
providers=providers,
|
||||
provider_options=provider_options,
|
||||
)
|
||||
face = {node.name: np.random.rand(1, 3, 112, 112).astype(np.float32) for node in recognition.get_inputs()}
|
||||
|
||||
def predict() -> None:
|
||||
detection.run(None, image)
|
||||
recognition.run(None, face)
|
||||
|
||||
case _:
|
||||
raise ValueError(f"Unsupported model task {model_task}")
|
||||
predict()
|
||||
ms = timeit(predict, number=100)
|
||||
rss = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss
|
||||
json.dump({"pretrained_model": model_dir.name, "peak_rss": rss, "exec_time_ms": ms}, output_path.open("w"))
|
||||
print(f"Model {model_dir.name} took {ms:.2f}ms per iteration using {rss / 1024:.2f}MiB of memory")
|
||||
|
||||
|
||||
@app.command()
|
||||
def upload(
|
||||
model_dir: Path,
|
||||
hf_organization: str = "immich-app",
|
||||
hf_auth_token: Annotated[str | None, typer.Option(envvar="HF_AUTH_TOKEN")] = None,
|
||||
) -> None:
|
||||
from huggingface_hub import create_repo, upload_folder
|
||||
|
||||
repo_id = f"{hf_organization}/{model_dir.name}"
|
||||
|
||||
@retry(stop=stop_after_attempt(5), wait=wait_fixed(5))
|
||||
def upload_model() -> None:
|
||||
create_repo(repo_id, exist_ok=True, token=hf_auth_token)
|
||||
upload_folder(
|
||||
repo_id=repo_id,
|
||||
folder_path=model_dir,
|
||||
# remote repo files to be deleted before uploading
|
||||
# deletion is in the same commit as the upload, so it's atomic
|
||||
delete_patterns=DELETE_PATTERNS,
|
||||
token=hf_auth_token,
|
||||
)
|
||||
|
||||
upload_model()
|
||||
@@ -1,3 +0,0 @@
|
||||
from immich_model_exporter import app
|
||||
|
||||
app()
|
||||
@@ -1,54 +0,0 @@
|
||||
from enum import StrEnum
|
||||
from typing import NamedTuple
|
||||
|
||||
|
||||
class ModelSource(StrEnum):
|
||||
INSIGHTFACE = "insightface"
|
||||
MCLIP = "mclip"
|
||||
OPENCLIP = "openclip"
|
||||
|
||||
|
||||
class ModelTask(StrEnum):
|
||||
FACIAL_RECOGNITION = "facial-recognition"
|
||||
SEARCH = "clip"
|
||||
|
||||
|
||||
class SourceMetadata(NamedTuple):
|
||||
name: str
|
||||
link: str
|
||||
type: str
|
||||
|
||||
|
||||
SOURCE_TO_METADATA = {
|
||||
ModelSource.MCLIP: SourceMetadata("M-CLIP", "https://huggingface.co/M-CLIP", "CLIP"),
|
||||
ModelSource.OPENCLIP: SourceMetadata("OpenCLIP", "https://github.com/mlfoundations/open_clip", "CLIP"),
|
||||
ModelSource.INSIGHTFACE: SourceMetadata(
|
||||
"InsightFace", "https://github.com/deepinsight/insightface/tree/master", "facial recognition"
|
||||
),
|
||||
}
|
||||
|
||||
|
||||
SOURCE_TO_TASK = {
|
||||
ModelSource.MCLIP: ModelTask.SEARCH,
|
||||
ModelSource.OPENCLIP: ModelTask.SEARCH,
|
||||
ModelSource.INSIGHTFACE: ModelTask.FACIAL_RECOGNITION,
|
||||
}
|
||||
|
||||
RKNN_SOCS = ["rk3566", "rk3568", "rk3576", "rk3588"]
|
||||
|
||||
|
||||
# glob to delete old UUID blobs when reuploading models
|
||||
_uuid_char = "[a-fA-F0-9]"
|
||||
_uuid_glob = _uuid_char * 8 + "-" + _uuid_char * 4 + "-" + _uuid_char * 4 + "-" + _uuid_char * 4 + "-" + _uuid_char * 12
|
||||
DELETE_PATTERNS = [
|
||||
"**/*onnx*",
|
||||
"**/Constant*",
|
||||
"**/*.weight",
|
||||
"**/*.bias",
|
||||
"**/*.proj",
|
||||
"**/*in_proj_bias",
|
||||
"**/*.npy",
|
||||
"**/*.latent",
|
||||
"**/*.pos_embed",
|
||||
f"**/{_uuid_glob}",
|
||||
]
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user