Compare commits

...

135 Commits

Author SHA1 Message Date
github-actions
3be8e265cd chore: version v2.5.6 2026-02-10 18:24:40 +00:00
Weblate (bot)
e3c4e0197a chore(web): update translations (#25947)
Translate-URL: https://hosted.weblate.org/projects/immich/immich/ar/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/bg/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/bn/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/ca/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/cs/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/da/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/de/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/de_CH/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/el/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/eo/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/es/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/et/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/fr/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/ga/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/gl/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/hr/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/id/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/it/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/ja/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/ka/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/kn/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/lt/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/lv/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/nb_NO/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/nl/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/nn/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/pl/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/pt/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/pt_BR/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/ru/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/sk/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/sl/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/sq/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/sv/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/th/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/tr/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/uk/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/vi/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/yue_Hant/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/zh_Hant/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/zh_SIMPLIFIED/
Translation: Immich/immich

Co-authored-by: Adam Havránek <adamhavra@seznam.cz>
Co-authored-by: Ahmed Khaleel Shihab <ahmed91shihab@gmail.com>
Co-authored-by: Aindriú Mac Giolla Eoin <aindriu80@gmail.com>
Co-authored-by: Arif Budiman <arifpedia@gmail.com>
Co-authored-by: Arnie97 <arnie97@gmail.com>
Co-authored-by: David Krizak <lavidk@icloud.com>
Co-authored-by: DevServs <bonov@mail.ru>
Co-authored-by: Gautam Pai <gautam.gp4207@gmail.com>
Co-authored-by: Gilgalard Elendil <Gilgalard11@gmail.com>
Co-authored-by: Gisle-Andre Larsen <gisleandre@hotmail.com>
Co-authored-by: Guillaume Petit <gpetit@edelzone.fr>
Co-authored-by: Guillermo Ramos Santos <guillermo.ramosantos@gmail.com>
Co-authored-by: HackingAll <hacking.all.YT@gmail.com>
Co-authored-by: Hans Cats <hanscats@gmail.com>
Co-authored-by: Happy <59247878+happy2452354@users.noreply.github.com>
Co-authored-by: Haru Ijima <haruijimakun@gmail.com>
Co-authored-by: Hurricane_32 <rodrigorimo@hotmail.com>
Co-authored-by: Indrek Haav <indrek.haav@hotmail.com>
Co-authored-by: Ivan Dimitrov <idimitrov08@gmail.com>
Co-authored-by: Jozef Gaal <preklady@mayday.sk>
Co-authored-by: Julius Lehmann <julius.lehmann.privat@gmail.com>
Co-authored-by: Luuk Heijnen <luukheijnen1@gmail.com>
Co-authored-by: MarcSerraPeralta <marcserraperalta@gmail.com>
Co-authored-by: Masani Amin Yasin <langugetranslategay.taps663@silomails.com>
Co-authored-by: Matjaž T. <matjaz@moj-svet.si>
Co-authored-by: Mārtiņš Bruņenieks <martinsb@gmail.com>
Co-authored-by: Olaf Nielsen <solluh@mail.de>
Co-authored-by: Oleksandr Yurov <oyurov@icloud.com>
Co-authored-by: Philipp Frauenfelder <philipp.frauenfelder@gmail.com>
Co-authored-by: Reetryyy <kaxa.kikalishvili.kk@gmail.com>
Co-authored-by: Romo <romo@romo.al>
Co-authored-by: Shawn <xiaxinx@gmail.com>
Co-authored-by: Skanda <skillwiz94@gmail.com>
Co-authored-by: Sylvain Pichon <service@spichon.fr>
Co-authored-by: TV Box <realceday.tvbox@gmail.com>
Co-authored-by: Tage Lauritsen <tage@tunenet.dk>
Co-authored-by: Tim Morley <weblate.3919org@timsk.org>
Co-authored-by: Ulices <hasecilu@tuta.io>
Co-authored-by: User 123456789 <user123456789@users.noreply.hosted.weblate.org>
Co-authored-by: Veerasak Kritsanapraphan <veerasak.kritsanapraphan@gmail.com>
Co-authored-by: albanobattistella <albano_battistella@hotmail.com>
Co-authored-by: bittin1ddc447d824349b2 <bittin@reimu.nl>
Co-authored-by: chamdim <chamdim@protonmail.com>
Co-authored-by: dvbthien <dvbthien@users.noreply.hosted.weblate.org>
Co-authored-by: ea stanley <hang4ea@gmail.com>
Co-authored-by: muziqaz <muziqaz@users.noreply.hosted.weblate.org>
Co-authored-by: nobo73 <noboru.tanaka@gmail.com>
Co-authored-by: pyccl <changcongliang@163.com>
Co-authored-by: waclaw66 <waclaw66@seznam.cz>
Co-authored-by: Óscar Fernández Díaz <42654671+oscfdezdz@users.noreply.github.com>
2026-02-10 18:22:41 +00:00
Nicolò Maria Semprini
1ddb8f0667 feat: jxl browser support detection (#25599) 2026-02-10 12:49:09 -05:00
Alex
adfb003d03 fix: local date time group fall back (#26110)
* fix: local date time group fall back

* remove else clause
2026-02-10 11:47:13 -06:00
Brandon Wees
8c8b11f80c fix: person thumbnail generation on edited assets (#26112)
* fix: person thumbnail generation on edited assets

* chore: sql sync
2026-02-10 11:38:43 -06:00
Claudio
90d554947f docs: update ml-hardware-acceleration.md (#25755)
Update ml-hardware-acceleration.md

Invert the lines about editing the docker-compose.yml file to have users add the tag to the image first, then uncomment the extends section. This should help users follow the instructions as they flow through the YAML file.
2026-02-10 12:28:21 -05:00
Paul Makles
caeba5063b refactor(server): move database restores code into a service (#25918)
* fix(server): use provided database name/username for restore & ensure name is not mangled

fixes #25633

Signed-off-by: izzy <me@insrt.uk>

* chore: add db switch back but with comments

Signed-off-by: izzy <me@insrt.uk>

* refactor: no need to restore database since it's not technically possible
chore: late fallback for username in parameter builder

Signed-off-by: izzy <me@insrt.uk>

* chore: type fix

Signed-off-by: izzy <me@insrt.uk>

* refactor: move db backup code into service

* test: check SQL sent to psql

* chore: remove todo

Signed-off-by: izzy <me@insrt.uk>

---------

Signed-off-by: izzy <me@insrt.uk>
2026-02-10 12:12:27 -05:00
Matthew Momjian
280174026f feat(deployment): rootless compose file (#25931)
rootless deployment
2026-02-10 12:11:44 -05:00
Michel Heusschen
a9e0fa43fa fix: correctly cancel select all assets (#26067) 2026-02-10 11:47:23 -05:00
Jason Rasmussen
e6e56d75e2 fix(web): refresh text (#26071) 2026-02-10 16:42:03 +00:00
Brandon Wees
0886281dd8 fix: create face exif orientation handling (#26108)
* fix: handle exif orientation when creating face

* chore: tests
2026-02-10 11:30:34 -05:00
renovate[bot]
32dea76a92 chore(deps): update dependency @types/node to ^24.10.11 (#26088)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-02-10 11:24:33 -05:00
Min Idzelis
6af534fe4c feat: run maintenance tests in isolation, share containers between all … (#25856)
* feat: run maintance tests in isolation, share containers between all serial test suites

* refactor: organize files

---------

Co-authored-by: Jason Rasmussen <jason@rasm.me>
2026-02-10 11:05:06 -05:00
Daniel Dietzler
71fe9192fd chore: metadata extraction date test (#26102) 2026-02-10 10:05:05 -05:00
Mert
7fa6f617f5 fix(server): thumbnail queueing (#26077)
* fix thumbnail queueing

* add bmp

* other isEdited column
2026-02-10 09:04:03 -06:00
Thomas
c3730c8eab chore(mobile): enable high refresh rate in debug builds (#26085)
I'm testing changes to animations and app performance, and noticed it
felt quite sluggish on a 120hz display. It turns out that high refresh
is disabled in debug builds. It's probably a good idea to enable it so
that it more closely mirrors the production build.
2026-02-10 03:51:33 +00:00
Luis Nachtigall
3462fc434e fix: evict image from cache on error during image loading (#26078) 2026-02-09 17:01:10 -05:00
Luis Nachtigall
561469b826 fix(mobile): handle image stream completion when no image is emitted (#25984)
* Fix image cancellation to be stream-scoped instead of widget-scoped

* fix(OneFramePlaceholderImageStreamCompleter): make onLastListenerRemoved callback synchronous with removing the last listener

* fix(OneFrameMultiImageStreamCompleter): remove unnecessary blank line in code

* fix(OneFramePlaceholderImageStreamCompleter): cancel pending requests when only cache listener remains

* fix(OneFrameMultiImageStreamCompleter): ensure onLastListenerRemoved callback is invoked only once
2026-02-09 16:59:29 -05:00
bo0tzz
937bef9a4d fix: run rocm builds on pokedex (#26062)
* fix: run rocm builds on pokedex

* fix: --parallel 48 (#26065)
2026-02-09 15:06:05 -05:00
dolfje
5f18110e97 fix(web): removing a person in an asset, doesn't remove the asset in … (#26068)
* fix(web): removing a person in an asset, doesn't remove the asset in the persons view (without refresh)

* prettier

---------

Co-authored-by: Nikos Verschore <nikos@uwsoftware.be>
2026-02-09 11:51:02 -06:00
Alex
57485023ae fix: free up space using small batch size to reliably work on Android (#26047)
* fix: free up space delete in small batch

* fix: free up space delete in small batch
2026-02-09 11:48:55 -06:00
Michel Heusschen
8a9b541dd0 fix: slideshow setting dropdown overflow (#26066) 2026-02-09 09:28:47 -06:00
Justin Xiao
25be5fc22d fix(web): prevent context menu from overflowing viewport (#26041)
* fix(web): prevent context menu from overflowing viewport

The context menu used `max-h-dvh` (100% viewport height) as its max height,
but did not account for the menu's top position. When the menu opens at
y > 0, its bottom extends beyond the viewport.

Compute `maxHeight` dynamically based on the menu's top position and apply
it as an inline style, so the menu always fits within the viewport and
scrolls when content exceeds the available space.

* fix: linting

* fix: overflow

---------

Co-authored-by: Jason Rasmussen <jason@rasm.me>
2026-02-09 09:26:25 -06:00
Alex
906c38273f fix: profile dialog auto dismiss after opening on iPad (#26046) 2026-02-08 17:30:57 -06:00
Alex
10b2bf7970 fix: iOS slow start (#26043) 2026-02-08 16:28:51 -06:00
Kolin
7cf8a9936a fix(web): display storage unit next to value instead of absolute positioning in admin user page (#25985)
* fix(web): display storage unit next to value instead of absolute positioning in admin user page

* chore: styling

---------

Co-authored-by: Alex Tran <alex.tran1502@gmail.com>
2026-02-08 17:22:42 +00:00
Michel Heusschen
59c4a49ffd fix: scroll jump when opening show & hide people (#25932) 2026-02-08 11:19:35 -06:00
Yaros
00486cbcc8 fix(web): toast fixed location (#25966)
fix: toast fixed location
2026-02-08 11:15:09 -06:00
Michel Heusschen
b524d7b6fd fix: reduce queue graph jitter and include paused count (#26023)
fix: reduce queue graph jitter and show paused count
2026-02-08 11:03:59 -06:00
Michel Heusschen
5b705cb723 fix: improve albums page load time on firefox (#26025) 2026-02-08 11:03:17 -06:00
Luis Nachtigall
354dd3cc3c feat(mobile): enhance album sorting functionality with order handling (#24816)
* feat: enhance album sorting functionality with effective order handling

* mobile: formatting

* test: align album sorting order in unit tests with defaultSortOrder

* test(mobile): add reverse order validation for album sorting

* chore(PR): remove OppositeSortOrder Extension and move it directly into SortOrder enum

* refactor: return sorted list directly in album sorting function

* refactor: remove sort_order_extensions.dart
2026-02-07 10:11:37 +05:30
shenlong
57483a1e7f fix: user profile refetched each time on opening app dialog (#25992)
fix: user profile on opening app dialog

Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com>
2026-02-07 10:10:17 +05:30
Romo
bcea64875f fix: image and video download complete notification shows "file_name" (#25975)
* fix: image and video download complete notification shows "file_name"

* fix lint

---------

Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com>
2026-02-07 02:56:14 +00:00
Matthew Momjian
84e30abe5d feat(docs): version policy (#25979)
version policy
2026-02-06 20:31:57 -05:00
Jason Rasmussen
e3e243fa2b refactor: tests (#25987) 2026-02-07 00:47:54 +01:00
Jason Rasmussen
b3820c259e refactor: test factories (#25977) 2026-02-06 16:32:50 -05:00
Daniel Dietzler
a356497d96 refactor: album service small tests (#25640) 2026-02-06 08:56:46 -05:00
Michel Heusschen
16fe828913 fix: revert "fix(web): Ensure profile picture is cropped to 1:1 ratio (#25892)" (#25956)
Revert "fix(web): Ensure profile picture is cropped to 1:1 ratio (#25892)"

This reverts commit 3c77c724c5.
2026-02-06 08:21:56 -05:00
Michel Heusschen
211dc3c056 fix: add missing translations for image editor (#25957) 2026-02-06 13:08:24 +01:00
github-actions
ff9052f7f5 chore: version v2.5.5 2026-02-06 03:49:02 +00:00
Aditya Gaurav
999ce34251 fix(web): avoid transparent pixels from rounded-full during profile picture capture (#25950)
The cropContainer has rounded-full class which creates transparent
corners when captured by domtoimage.toBlob(). Override border-radius
and border to 0/none during capture to produce a clean square image.

Co-authored-by: Aditya Gaurav <aditya-ai-architect@users.noreply.github.com>
2026-02-06 03:21:27 +00:00
Vahant Sharma
491ed3d927 fix(cli): suppress startup messages for immich-admin (#25928)
fix(server): suppress startup messages for immich-admin CLI Introduce a log_message() helper function with QUIET flag to suppress informational startup output when running immich-admin. This prevents both shell messages and Node.js WASI experimental warnings from interfering with CLI help output. Fixes: #25909
2026-02-05 18:34:15 -05:00
Jason Rasmussen
94e86c6e76 fix: dedupe version announcement modal (#25946)
fix: version announcement modal
2026-02-05 16:24:10 -05:00
github-actions
8581b4f350 chore: version v2.5.4 2026-02-05 21:16:52 +00:00
Weblate (bot)
4835d5f97f chore(web): update translations (#25585)
Translate-URL: https://hosted.weblate.org/projects/immich/immich/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/ar/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/bg/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/bn/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/ca/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/de/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/eo/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/es/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/et/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/fr/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/ga/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/hu/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/id/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/it/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/ja/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/ka/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/ko/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/lv/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/nb_NO/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/nl/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/pl/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/pt/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/pt_BR/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/ro/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/sk/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/sl/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/sv/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/ta/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/th/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/tr/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/uk/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/yue_Hant/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/zh_Hant/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/zh_SIMPLIFIED/
Translation: Immich/immich

Co-authored-by: Ahmed Khaleel Shihab <ahmed91shihab@gmail.com>
Co-authored-by: Aindriú Mac Giolla Eoin <aindriu80@gmail.com>
Co-authored-by: Alan Lai <alanlai22@outlook.com>
Co-authored-by: Aldi Maulana <aldim222@gmail.com>
Co-authored-by: Andrei P <darkandrei197@gmail.com>
Co-authored-by: Ari Selseng <ari@selseng.net>
Co-authored-by: Beans <leey0818@gmail.com>
Co-authored-by: Bryan Tank <perso@bryantank.fr>
Co-authored-by: Cheng Chien <jamesqian1999@gmail.com>
Co-authored-by: Chun-Hei Lam <chun.lam18@imperial.ac.uk>
Co-authored-by: Ciprriann <cipriannebeja@gmail.com>
Co-authored-by: Damien Doumax <damien@orfaon.net>
Co-authored-by: Fran Sánchez <mrurkaz@gmail.com>
Co-authored-by: Hans Cats <hanscats@gmail.com>
Co-authored-by: Happy <59247878+happy2452354@users.noreply.github.com>
Co-authored-by: Hurricane_32 <rodrigorimo@hotmail.com>
Co-authored-by: Indrek Haav <indrek.haav@hotmail.com>
Co-authored-by: Ivan Dimitrov <idimitrov08@gmail.com>
Co-authored-by: Jordy H <jordy@hoebergen.net>
Co-authored-by: Jozef Gaal <preklady@mayday.sk>
Co-authored-by: Junghyuk Kwon <kwon@junghy.uk>
Co-authored-by: KecskeTech <teonyitas@gmail.com>
Co-authored-by: Kim Hokyeong <manmen.mi1375@gmail.com>
Co-authored-by: Marc Casillas <mcasillassu@gmail.com>
Co-authored-by: Masani Amin Yasin <langugetranslategay.taps663@silomails.com>
Co-authored-by: Masani Amin Yasin <masaniamin@proton.me>
Co-authored-by: Matjaž T. <matjaz@moj-svet.si>
Co-authored-by: Melih Ozkan <malihozkan156@gmail.com>
Co-authored-by: Mārtiņš Bruņenieks <martinsb@gmail.com>
Co-authored-by: Nicolò <nicosemp@gmail.com>
Co-authored-by: Nik Grebovšek <nikigre@gmail.com>
Co-authored-by: Oleksandr Yurov <oyurov@icloud.com>
Co-authored-by: PPNplus <ppnplus@protonmail.com>
Co-authored-by: Phantom0174 <darrenhsiou@gmail.com>
Co-authored-by: Pieter Lexis <pieter@plexis.eu>
Co-authored-by: Rey <x46puy43k@mozmail.com>
Co-authored-by: Roman Fedorchuk <roma.fedorchuk@gmail.com>
Co-authored-by: Samuel Medeiros <steixeiramedeiros@gmail.com>
Co-authored-by: Shawn <xiaxinx@gmail.com>
Co-authored-by: Stan P <g97d6liib@mozmail.com>
Co-authored-by: Taiki M. <vexingly-many-mace@duck.com>
Co-authored-by: Temuri Doghonadze <temuri.doghonadze@gmail.com>
Co-authored-by: Tim Morley <weblate.3919org@timsk.org>
Co-authored-by: Tim Müller <info@timxllr.de>
Co-authored-by: User 123456789 <user123456789@users.noreply.hosted.weblate.org>
Co-authored-by: balc11 <balc11@gmail.com>
Co-authored-by: bittin1ddc447d824349b2 <bittin@reimu.nl>
Co-authored-by: john family <tyutee09@gmail.com>
Co-authored-by: kellogcheung <kellogcheung@gmail.com>
Co-authored-by: liimee <git.taaa@fedora.email>
Co-authored-by: millallo <millallo@tiscali.it>
Co-authored-by: pyccl <changcongliang@163.com>
Co-authored-by: shiuh67 <shiuh.cheng@gmail.com>
Co-authored-by: stesoma <soma.steltzer@gmail.com>
Co-authored-by: Óscar Fernández Díaz <42654671+oscfdezdz@users.noreply.github.com>
Co-authored-by: გიორგი კუცია <giorgi.kucia@gmail.com>
2026-02-05 21:14:41 +00:00
Aram Akhavan
435565be1b docs: remove writeTimeout on traefik example (#25837)
Don't recommend writeTimeout: 600s for traefik example
2026-02-05 20:58:10 +00:00
Jason Rasmussen
94d3039606 fix: prettier not found (#25941) 2026-02-05 20:44:09 +00:00
Min Idzelis
092ebe01a5 fix: queue assets missing fullsize files for thumbnail regeneration (#25794)
* fix: queue assets missing fullsize files for thumbnail regeneration

* refactor: query

---------

Co-authored-by: Jason Rasmussen <jason@rasm.me>
2026-02-05 19:31:13 +00:00
Brandon Wees
37e5968a7a fix: face and edit handling (#25738)
* fix: handle edits when creating face
2026-02-05 19:29:46 +00:00
Dion de Koning
cfc5ed5997 fix: timezone issue in tests (#25937)
* Fixed an issue where time tests fail in some timezones

* Revert previous fix and add TZ env variable to fix the issue

* Revert other changes and align TZ fix between server and web

* Revert package lock file

---------

Co-authored-by: Dion de Koning <dion@DionK01.local>
2026-02-05 19:24:23 +00:00
Romo
1b3c0e4f65 fix: image download complete notification shows an extra {file_name} template tag (#25936)
* [fix] Image download complete notification shows an extra {file_name} template tag

fixes https://github.com/immich-app/immich/issues/25690
added

```dart
final FileName = 'file_name'.t( args: {'file_name': '{filename}', }, );
```

* chore: fix formatting

---------

Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com>
2026-02-05 19:19:33 +00:00
Mert
fd49d7d566 chore(mobile): skip macro validation (#25744)
* use podfile

* update deps
2026-02-05 14:16:21 -05:00
cmdPromptCritical
ad9f3cfa05 fix(mobile): cancel share download when dialog is dismissed (#25466)
* fix(mobile): cancel share download when dialog is dismissed

* refactor: centralize temporary file cleanup logic

* refactor: replace `CancellationToken` with `Completer<void>` for asset sharing cancellation

---------

Co-authored-by: cmdpromptcritical <cmdpromptcritical@github.com>
2026-02-05 19:08:35 +00:00
Dane
9d8efe2685 fix(docs): add missing --json-output arg to CLI example (#25870) 2026-02-05 14:00:27 -05:00
Paul Makles
ed4d9abdae fix(server): use provided database username for restore & ensure name is not mangled (#25679)
* fix(server): use provided database name/username for restore & ensure name is not mangled

fixes #25633

Signed-off-by: izzy <me@insrt.uk>

* chore: add db switch back but with comments

Signed-off-by: izzy <me@insrt.uk>

* refactor: no need to restore database since it's not technically possible
chore: late fallback for username in parameter builder

Signed-off-by: izzy <me@insrt.uk>

* chore: type fix

Signed-off-by: izzy <me@insrt.uk>

* chore: re-use the username we just pulled out

---------

Signed-off-by: izzy <me@insrt.uk>
2026-02-05 13:59:05 -05:00
Vahant Sharma
ac9f6921cc fix(server): add missing history metadata to getAuthStatus endpoint (#25927)
* fix(server): add missing history metadata to getAuthStatus endpoint

* chore: regenerate openapi specs
2026-02-05 18:56:44 +00:00
shenlong
f0da875e37 fix: allow clear text traffic on android (#25933)
Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com>
2026-02-06 00:15:33 +05:30
Peter Ombodi
b0e1a425b3 fix(mobile): jump to previous asset when last asset is deleted (#25563)
* fix(mobile): fix wrong index, update pageController

* fix(mobile): refactor code

---------

Co-authored-by: Peter Ombodi <peter.ombodi@gmail.com>
Co-authored-by: shenlong <139912620+shenlong-tanwen@users.noreply.github.com>
2026-02-05 18:19:40 +00:00
Yaros
7211d80e5f docs: update mobile setup to use mise (#25847)
docs: update mobile setup to mise
2026-02-05 12:55:38 -05:00
shenlong
92c79a7122 chore: increase cache_size and use memory temp store (#25930)
Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com>
2026-02-05 11:55:07 -06:00
renovate[bot]
7580521a76 chore(deps): update grafana/grafana docker tag to v12.3.2 (#25840)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-02-05 12:52:07 -05:00
shenlong
2dd3a764ae fix: timezone in timeline bucketing (#25894)
Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com>
2026-02-05 11:47:16 -06:00
Thomas
a42c08ed84 fix(mobile): reset asset index on timeline refresh (#25729)
The current asset changes when the timeline refreshes, which can be
quite jarring. Assets are tracked by their index, and that index becomes
stale when the timeline refreshes. This can be resolved by updating the
index of asset based on a unique identifier (like the hero tag).
2026-02-05 11:46:38 -06:00
Aditya Gaurav
3c77c724c5 fix(web): Ensure profile picture is cropped to 1:1 ratio (#25892)
* fix(web): Ensure profile picture is cropped to 1:1 ratio

Fixes #20097

The profile picture was being captured from the PhotoViewer element
which could have non-square dimensions based on the original image.

Changed to capture from the crop container element which has the
aspect-square class, ensuring the output is always 1:1 ratio.

* fix: remove trailing whitespace to pass prettier check

---------

Co-authored-by: Aditya Gaurav <aditya-ai-architect@users.noreply.github.com>
2026-02-05 11:45:06 -06:00
Yaros
84b2979485 docs: non-code contributing (datasets) (#25850)
docs: datasets
2026-02-05 11:44:35 -06:00
Paul Makles
e9c2ca008a docs: update manual backup/restore to match the automatic process (#25924)
* docs: update manual backup/restore to match automatic process

closes #25772

* docs: update DB_NAME to DB_DATABASE_NAME
2026-02-05 12:43:33 -05:00
Daniel Dietzler
9c098109e0 fix: time zone upserts (#25889) 2026-02-05 12:43:03 -05:00
Mert
27a2808470 fix(mobile): mtls on native clients (#25802)
* handle mtls on ios

* update android impl

* ui improvements

* dead code

* no need to store data separately

* improve concurrency

* dead code

* add migration

* remove unused dependency

* trust user-installed certs

* removed print statement

* fix ios

* improve android styling

* outdated comments

* update lock file

* handle translation

* fix prompt cancellation

* fix video playback

* Apply suggestion from @shenlong-tanwen

Co-authored-by: shenlong <139912620+shenlong-tanwen@users.noreply.github.com>

* Apply suggestion from @shenlong-tanwen

Co-authored-by: shenlong <139912620+shenlong-tanwen@users.noreply.github.com>

* formatting

---------

Co-authored-by: shenlong <139912620+shenlong-tanwen@users.noreply.github.com>
2026-02-05 17:42:53 +00:00
Alex
0a8a65a45e fix: file name search label (#25916) 2026-02-05 17:24:58 +00:00
shenlong
2b6055e830 chore: do not process cloud ids during sync & hash (#25914)
Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com>
2026-02-05 11:23:50 -06:00
Mert
ba2dfa7df6 refactor(mobile): consolidate image requests (#25743)
remote url image provider

remove cached_network_image

formatting

linting

remove thumb provider

formatting
2026-02-05 12:16:42 -05:00
Jason Rasmussen
237ea3aedd chore: update oauth documentation (#25907)
* chore: prefer lowercase for non i18n labels

* chore: update documentation
2026-02-05 09:00:00 -05:00
Michel Heusschen
810e9254f3 fix: preserve hidden people state across pagination (#25886)
* fix: preserve hidden people state across pagination

* track overrides instead

* use event instead of bind:people

* update test
2026-02-05 08:51:30 -05:00
Michel Heusschen
57e0835b46 fix: ensure theme stays in sync with @immich/ui (#25922) 2026-02-05 08:36:20 -05:00
Michel Heusschen
e97030a7ae fix: make switch labels properly clickable (#25898) 2026-02-05 12:09:27 +01:00
Michel Heusschen
fdf06a91cc fix: improve asset editor exit handling (#25917) 2026-02-05 12:01:54 +01:00
Michel Heusschen
732303661b fix: allow null tagIds in search dto (#25920) 2026-02-05 11:52:35 +01:00
Alex
e9f8521a50 fix: date time picker text color in dark mode (#25883) 2026-02-04 18:45:56 +00:00
Michel Heusschen
6bd60270b4 fix: correctly sync shared link download with metadata toggle (#25885) 2026-02-04 12:38:42 -05:00
Michel Heusschen
5a6fd7af06 fix: close tag modal after tagging assets (#25884) 2026-02-04 12:35:00 -05:00
Jason Rasmussen
6cdebdd3b3 fix(server): deleting stacked assets (#25874)
* fix(server): deleting stacked assets

* fix: log a warning when removing an empty directory fails
2026-02-04 17:33:37 +00:00
Jason Rasmussen
9dddccd831 fix: null validation (#25891) 2026-02-04 12:27:52 -05:00
Min Idzelis
440b3b4c6f chore: move devcontainer specific tasks to devcontainer.json (#25881)
refactor: move devcontainer specific tasks to devcontainer.json
2026-02-03 23:04:09 -05:00
Jason Rasmussen
3ea65f8d27 fix: album dto docs (#25873) 2026-02-03 21:05:18 +00:00
github-actions
38c1f0b1fd chore: version v2.5.3 2026-02-03 18:14:21 +00:00
Michel Heusschen
5212bca3d0 fix: reset zoom when navigating between assets (#25863) 2026-02-03 11:07:06 -06:00
Daniel Dietzler
2990bde0bb fix: metadata extraction race condition (#25866) 2026-02-03 11:03:27 -06:00
Michel Heusschen
af1ecaf5cc fix: prevent backspace from accidentally triggering delete modals (#25858)
* fix: prevent backspace from accidentally triggering delete modals

* ignore input fields instead of removing shortcut
2026-02-03 16:42:46 +00:00
Alex
3870ebc3c6 fix: prevent album page get rebuilt when resuming app (#25862) 2026-02-03 16:35:53 +00:00
Michel Heusschen
0a9d969b47 fix: prevent stale values in edit user form after save (#25859) 2026-02-03 17:29:01 +01:00
Daniel Dietzler
94965f6d66 chore: rework tags sidebar (#25855) 2026-02-03 16:06:26 +00:00
Alex
8872d2c7ae chore: remove swift logs (#25857) 2026-02-03 16:00:17 +00:00
Alex
23445fdcc1 fix: upload progress bar flickering (#25829)
* fix: upload progress bar flickering

* pr feedback and more logs
2026-02-03 09:28:29 -06:00
renovate[bot]
25f2273e24 chore(deps): update redis:6.2-alpine docker digest to 46884be (#25839)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-02-03 12:56:56 +01:00
Min Idzelis
95e8e474b8 fix(web): enable asset viewer navigation across memory boundaries (#25741) 2026-02-02 10:12:08 -06:00
Timon
9f52d864cf chore(ml): replace black with ruff format (#25578) 2026-02-02 09:02:06 -05:00
Mees Frensel
0273dcb0cf fix(web): user settings styling (#25775) 2026-02-02 08:47:28 -05:00
Matthew Momjian
1436e2a75f fix(docs): clarify supported vector version (#25753)
clarify supported version
2026-01-31 11:46:51 -05:00
Thomas
855817514c fix(mobile): hide latest version if disabled (#25691)
* fix(mobile): hide latest version if disabled

If the version check feature is disabled, the server will currently send
stale data to the client. In addition to no longer sending stale data,
the client should also not show the latest version if the feature is
disabled.

This complements the server PR #25688.

* lint

---------

Co-authored-by: Alex <alex.tran1502@gmail.com>
2026-01-30 16:17:03 +00:00
Thomas
d5ad35ea52 chore(mobile): remove references to fvm, add mise docs, use java 21 (#25703) 2026-01-29 23:03:56 -06:00
shenlong
e63213d774 fix(mobile): do not autocorrect on endpoint input (#25696)
Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com>
2026-01-29 23:03:26 -06:00
Jason Rasmussen
0be1ffade6 fix: no notification if release check is disabled (#25688) 2026-01-29 18:31:11 -05:00
Brandon Wees
1a04caee29 fix: reset and unsaved change states in editor (#25588) 2026-01-29 15:18:30 -06:00
renovate[bot]
3ace578fc0 chore(deps): update dependency opentofu to v1.11.4 (#24609)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-01-29 12:14:44 -05:00
Jason Rasmussen
25c573bc7a chore: remove random code snippet (#25677) 2026-01-29 16:11:25 +00:00
renovate[bot]
10bb83cf75 chore(deps): update dependency terragrunt to v0.98.0 (#24328)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-01-29 08:55:42 -05:00
Jason Rasmussen
10b53b525d refactor: event manager (#25565) 2026-01-29 08:52:18 -05:00
Timon
8db61d341f docs(openapi): add descriptions to OpenAPI specification (#25185)
* faces

* add openapi descriptions

* remove dto descriptions

* gen openapi

* dtos

* fix dtos

* fix more

* fix build

* more

* complete dtos

* descriptions on rebase

* gen rebase

* revert correct integer type conversion

* gen after revert

* revert correct nullables

* regen after revert

* actually incorrect adding default here

* revert correct number type conversion

* regen after revert

* revert nullable usage

* regen fully

* readd some comments

* one more

* one more

* use enum

* add missing

* add missing controllers

* add missing dtos

* complete it

* more

* describe global key and slug

* add remaining body and param descriptions

* lint and format

* cleanup

* response and schema descriptions

* test patch according to suggestion

* revert added api response objects

* revert added api body objects

* revert added api param object

* revert added api query objects

* revert reorganized http code objects

* revert reorganize ApiOkResponse objects

* revert added api response objects (2)

* revert added api tag object

* revert added api schema objects

* migrate missing asset.dto.ts

* regenerate openapi builds

* delete generated mustache files

* remove descriptions from properties that are schemas

* lint

* revert nullable type changes

* revert int/num type changes

* remove explicit default

* readd comment

* lint

* pr fixes

* last bits and pieces

* lint and format

* chore: remove rejected patches

* fix: deleting asset from asset-viewer on search results (#25596)

* fix: escape handling in search asset viewer (#25621)

* fix: correctly show owner in album options modal (#25618)

* fix: validation issues

* fix: validation issues

---------

Co-authored-by: Jason Rasmussen <jason@rasm.me>
Co-authored-by: Min Idzelis <min123@gmail.com>
Co-authored-by: Daniel Dietzler <36593685+danieldietzler@users.noreply.github.com>
Co-authored-by: Paul Makles <me@insrt.uk>
2026-01-29 08:49:15 -05:00
github-actions
eadb2f89af chore: version v2.5.2 2026-01-28 22:05:10 +00:00
Marius
f2f11b1924 fix(mobile): tall image scrolling (#25649)
Add cross-axis gesture detection in PhotoView so vertical scrolling works on tall images that don't fill the screen width (have black bars)
2026-01-28 17:03:11 -05:00
Jason Rasmussen
141be5cbc9 fix: memory generation (#25650) 2026-01-28 15:51:24 -06:00
Jason Rasmussen
e81faa1dbf fix: memory lane (#25652) 2026-01-28 15:51:13 -06:00
Alex
0beb1f9e7a fix: width and height migration issue (#25643)
* fix: width and height migration issue

* chore: sync stream migration tests

* lint and test

---------

Co-authored-by: bwees <brandonwees@gmail.com>
2026-01-28 15:14:50 -06:00
Mert
e07a91f9c2 fix(mobile): actually load original image (#25646)
fix decoding
2026-01-28 15:14:37 -06:00
Noel S
c6defd453b fix(mobile): set correct system-ui mode on asset viewer init (#25610)
fix: set correct systemui mode on asset viewer init
2026-01-28 15:14:23 -06:00
Daniel Dietzler
4e0e1b2c5c fix: escape handling (#25627) 2026-01-28 15:05:21 -05:00
Noel S
84c3980844 fix(mobile): show controls by default on motion photos (#25638)
fix: show controls by default on motion photos
2026-01-28 13:46:29 -06:00
Daniel Dietzler
e50579eefc fix: album card ranges (#25639) 2026-01-28 14:38:09 -05:00
Timon
0cb153a971 chore: update uv version setting command in release script (#25583) 2026-01-28 13:56:25 +00:00
Alex
12d23e987b chore: post release tasks (#25582) 2026-01-28 08:55:58 -05:00
Timon
9486eed97e chore(mise): use explicit monorepo config (#25575)
chore(mise): add monorepo configuration with multiple config roots
2026-01-28 08:55:11 -05:00
Paul Makles
913e939606 fix(server): don't assume maintenance action is set (#25622) 2026-01-28 13:55:18 +01:00
Daniel Dietzler
9be01e79f7 fix: correctly show owner in album options modal (#25618) 2026-01-28 06:24:02 -06:00
Daniel Dietzler
2d09853c3d fix: escape handling in search asset viewer (#25621) 2026-01-28 06:23:15 -06:00
Min Idzelis
91831f68e2 fix: deleting asset from asset-viewer on search results (#25596) 2026-01-28 12:31:23 +01:00
github-actions
41e2ed3754 chore: version v2.5.1 2026-01-27 23:10:13 +00:00
Alex
1319ad373f chore: increase build iOS timeout (#25593) 2026-01-27 23:04:00 +00:00
Alex
97df9fd53f chore: prevent going into sleep mode for large deletion (#25592) 2026-01-27 22:50:28 +00:00
Jason Rasmussen
4707821451 chore: replace patch doc links (#25591)
chore: automatically use the latest patch release
2026-01-27 17:36:38 -05:00
Jason Rasmussen
20c4d375b1 chore: update pump script (#25586) 2026-01-27 17:33:12 -05:00
shenlong
46d2238431 fix: migration on trash source column (#25590)
Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com>
2026-01-27 16:25:35 -06:00
Jason Rasmussen
f7291c3a0b fix: npm publish (#25584)
chore(web): update translations (#25576)

* chore(web): update translations























































































































































































Translate-URL: https://hosted.weblate.org/projects/immich/immich/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/ar/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/be/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/bg/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/bn/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/ca/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/cs/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/cv/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/da/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/de/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/de_CH/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/el/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/eo/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/es/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/et/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/fa/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/fi/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/fil/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/fr/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/ga/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/gl/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/gsw/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/he/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/hi/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/hu/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/id/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/it/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/ja/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/ka/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/kn/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/ko/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/lt/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/lv/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/ml/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/mr/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/ms/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/nb_NO/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/nl/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/pl/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/pt/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/pt_BR/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/ro/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/ru/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/sk/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/sl/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/sq/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/sr_Latn/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/sv/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/ta/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/th/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/tr/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/uk/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/ur/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/vi/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/zh_Hant/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/zh_SIMPLIFIED/
Translation: Immich/immich

* fix: revert package.json

---------

Co-authored-by: Weblate (bot) <hosted@weblate.org>
Co-authored-by: 0v0 <0v0tvs@gmail.com>
Co-authored-by: 100daysummer <bobbydochev@gmail.com>
Co-authored-by: Adam Havránek <adamhavra@seznam.cz>
Co-authored-by: Adrián Nieto Rodríguez <adrian.nieto7@gmail.com>
Co-authored-by: Agostino Pit <scheccia@gmail.com>
Co-authored-by: Ahmed Khaleel Shihab <ahmed91shihab@gmail.com>
Co-authored-by: Aindriú Mac Giolla Eoin <aindriu80@gmail.com>
Co-authored-by: Alexandre <alexandre.tressel@icloud.com>
Co-authored-by: Alexandre <pikpakpik@users.noreply.hosted.weblate.org>
Co-authored-by: Alin T <amin4fun@yahoo.com>
Co-authored-by: Ameer Hamza <ah75102@gmail.com>
Co-authored-by: Amir <amirikmel@gmail.com>
Co-authored-by: Antoine Maalouf <atmaalouf@gmail.com>
Co-authored-by: Anton Palmqvist <apq@users.noreply.hosted.weblate.org>
Co-authored-by: Aravinth <aravinth@tuta.io>
Co-authored-by: Arnau Mora <arnyminer.z@gmail.com>
Co-authored-by: Artem Grauberger <graubergerartem@gmail.com>
Co-authored-by: AtmosphericIgnition <dev@prusa.net>
Co-authored-by: Bagas Dwi <bagasdwin15@gmail.com>
Co-authored-by: Balázs R <nvi9@outlook.hu>
Co-authored-by: BarMan <weblate.barman632@simplelogin.com>
Co-authored-by: Bart Simons <bart2jes@gmail.com>
Co-authored-by: Bartłomiej <20731216+Jarsey45@users.noreply.github.com>
Co-authored-by: Beans <leey0818@gmail.com>
Co-authored-by: Branden S <schrenk.br@gmail.com>
Co-authored-by: Bruno Antunes <antunes.dll@gmail.com>
Co-authored-by: CHUNG, Jin-ho <doctorjinho@gmail.com>
Co-authored-by: CanbiZ <mickey.leskowitz@gmail.com>
Co-authored-by: Carl Bergan <carl.bergan@gmail.com>
Co-authored-by: Carl Hansson <carlhansson677@gmail.com>
Co-authored-by: Cem TURKER <forumcemturker@gmail.com>
Co-authored-by: Collignon-Ducret Rémi <remi+github@collignon-ducret.fr>
Co-authored-by: Constantin <lulu195@users.noreply.hosted.weblate.org>
Co-authored-by: Cédric <cedric@laubacher.io>
Co-authored-by: Damian Krysta <krypton9208@gmail.com>
Co-authored-by: Daniel Pätzold <weblate.labrador503@passmail.net>
Co-authored-by: Degani Giancarlo <giancarlo@degani.eu>
Co-authored-by: Denis Pacquier <denis.pacquier@gmail.com>
Co-authored-by: DevServs <bonov@mail.ru>
Co-authored-by: Don't use my name <maxabmeyer@gmail.com>
Co-authored-by: Dusan Hlavaty <dhlavaty@gmail.com>
Co-authored-by: Dániel Gál <galdaniel.school@gmail.com>
Co-authored-by: Eduardo Maciel <edumaciel1221@gmail.com>
Co-authored-by: Emil <emil.ca.carls+weblate@gmail.com>
Co-authored-by: Eric Hebert <ericheb@gmail.com>
Co-authored-by: Federico Cervelli <federicocervelli01@gmail.com>
Co-authored-by: Felipe Cury <weblate@flpcury.com>
Co-authored-by: Fjuro <fjuro@alius.cz>
Co-authored-by: Gabriel <jellyfin.sensitize624@passmail.net>
Co-authored-by: Gary <zgr0629@gmail.com>
Co-authored-by: George Tsotsos <geoxor123@outlook.com>
Co-authored-by: Giorgio M <giorgio.maulu@gmail.com>
Co-authored-by: Guillermo Ramos Santos <guillermo.ramosantos@gmail.com>
Co-authored-by: HackingAll <hacking.all.YT@gmail.com>
Co-authored-by: Haki Bardhi <hakibardhi7@gmail.com>
Co-authored-by: HaoSs07 <haoss07@gmail.com>
Co-authored-by: Haru Ijima <haruijimakun@gmail.com>
Co-authored-by: Hurricane_32 <rodrigorimo@hotmail.com>
Co-authored-by: Hồ Nhất Duy <axicenia@gmail.com>
Co-authored-by: Ilya <vlk.ilya@users.noreply.hosted.weblate.org>
Co-authored-by: Immich <weblate@immich.app>
Co-authored-by: Indrek Haav <indrek.haav@hotmail.com>
Co-authored-by: Ivan Dimitrov <idimitrov08@gmail.com>
Co-authored-by: JM Garcia <jmgrc1626@gmail.com>
Co-authored-by: Jadde <Jasper@pgpmail.dk>
Co-authored-by: Jason Song <songpeiheng@gmail.com>
Co-authored-by: Jeppe Nellemann <jepnel@proton.me>
Co-authored-by: Jiri Grönroos <jiri.gronroos@iki.fi>
Co-authored-by: Joel <octavianporsche@gmail.com>
Co-authored-by: John denar <weblate.direct@privacyshield.online>
Co-authored-by: Jordy H <jordy@hoebergen.net>
Co-authored-by: Jozef Gaal <preklady@mayday.sk>
Co-authored-by: Julian Poidevin <poidevin.julian@gmail.com>
Co-authored-by: K Emil <kristianemilmadsen@gmail.com>
Co-authored-by: Katherine <kate.schumacher@gmail.com>
Co-authored-by: Kuba <kubaant@gmail.com>
Co-authored-by: Lemon Cat <lmncat3@gmail.com>
Co-authored-by: Leo Bottaro <github@leobottaro.com>
Co-authored-by: Liviu Roman <contact@liviuroman.com>
Co-authored-by: Lluís Forns <enboig@disroot.org>
Co-authored-by: Lorenzo <artale.lorenzo@outlook.it>
Co-authored-by: Loris Sambinelli <loriss84@gmail.com>
Co-authored-by: Lucas Jaksys <lucas3033@gmail.com>
Co-authored-by: Lucas Manzke <lmprogg@gmail.com>
Co-authored-by: Luuk Heijnen <luukheijnen1@gmail.com>
Co-authored-by: M4th12 <mattia.caldera04@gmail.com>
Co-authored-by: MSDNicrosoft <i@msdnicrosoft.work>
Co-authored-by: MSDNicrosoft <wang3311835119@hotmail.com>
Co-authored-by: MaBeniu <runnerm@gmail.com>
Co-authored-by: Macgyver <macgyver@users.noreply.hosted.weblate.org>
Co-authored-by: Mads Bojesen <madsrbojesen@gmail.com>
Co-authored-by: Marc Casillas <mcasillassu@gmail.com>
Co-authored-by: MarcSerraPeralta <marcserraperalta@gmail.com>
Co-authored-by: Marian Wolf <marian.wolf2008@gmail.com>
Co-authored-by: Martynas <kingsizekebab@protonmail.com>
Co-authored-by: Marwan Jalaleddine <marwanjalaleddine@gmail.com>
Co-authored-by: Mateusz Filipowicz <matfilipowicz@gmail.com>
Co-authored-by: Matjaž T. <matjaz@moj-svet.si>
Co-authored-by: Matt Peperell <mattp@users.noreply.hosted.weblate.org>
Co-authored-by: Mees Frensel <meesfrensel@gmail.com>
Co-authored-by: Michael <mail@michaelhofer.ch>
Co-authored-by: Mihailo Gostiljac <gostiljaccc99@gmail.com>
Co-authored-by: Mohammed Khan <weblate@mkodify.org>
Co-authored-by: Muhammad Ghassan Ihsan Kamil <heysans.kamil@gmail.com>
Co-authored-by: Mārtiņš Bruņenieks <martinsb@gmail.com>
Co-authored-by: Naim Hasim <ainadanaim@gmail.com>
Co-authored-by: Niccolò Cocchi <nicco.r.cocchi@gmail.com>
Co-authored-by: Nico Kaiser <nico@kaiser.me>
Co-authored-by: Olaf Nielsen <solluh@mail.de>
Co-authored-by: Oleksandr Yurov <oyurov@icloud.com>
Co-authored-by: Peer Ewald <pulse-charger-open@duck.com>
Co-authored-by: PhillyMay <mein.alias@outlook.com>
Co-authored-by: PontusÖsterlindh <pontus@osterlindh.com>
Co-authored-by: Putthimedh Jarusirisoonthorn <toto.jaru@gmail.com>
Co-authored-by: ROCK TAKEY <rocktakey@gmail.com>
Co-authored-by: Remco <remco@pander.io>
Co-authored-by: Rey <x46puy43k@mozmail.com>
Co-authored-by: Riccardo Parise <riccardo@parise.space>
Co-authored-by: Roberto Burchi <elburchio@gmail.com>
Co-authored-by: Roger Veciana Rovira <rveciana@gmail.com>
Co-authored-by: Rohama <32406304+dev-mkm@users.noreply.github.com>
Co-authored-by: Romo <romo@romo.al>
Co-authored-by: Rune J. <runekj@duck.com>
Co-authored-by: Saba Sakvarelidze <cal1b4nnn@gmail.com>
Co-authored-by: Sait Furkan Selçuk <sait574577@gmail.com>
Co-authored-by: Samhar Hijazi <semokoda@keemail.me>
Co-authored-by: Sami Cooper (CYB3ROID694) <sami.mhatre756@gmail.com>
Co-authored-by: Sergio <svillar@igalia.com>
Co-authored-by: Sergio Espada Rubio <espadauni@gmail.com>
Co-authored-by: Shawn <xiaxinx@gmail.com>
Co-authored-by: Shjosan <shjosan@kakmix.co>
Co-authored-by: Simon L. B. Sørensen <simonxarro@gmail.com>
Co-authored-by: Sjoerd van Daal <sjoerd.van.daal@proton.me>
Co-authored-by: Skanda <skillwiz94@gmail.com>
Co-authored-by: Sonny Saul Aguilar Alvarez (sonnyano909) <aguilarsaulsonny@gmail.com>
Co-authored-by: Sophie <mail@sopht.li>
Co-authored-by: Stan P <g97d6liib@mozmail.com>
Co-authored-by: Stanly Swagato Halder <stanlyhalder@gmail.com>
Co-authored-by: Sylvain Pichon <service@spichon.fr>
Co-authored-by: Szymon Kucharski <szymon.kucharski5@gmail.com>
Co-authored-by: TV Box <realceday.tvbox@gmail.com>
Co-authored-by: Taiki M. <vexingly-many-mace@duck.com>
Co-authored-by: Takayuki Maeda <takoyaki0316@gmail.com>
Co-authored-by: Temuri Doghonadze <temuri.doghonadze@gmail.com>
Co-authored-by: Tim Morley <weblate.3919org@timsk.org>
Co-authored-by: Tomasz Rzymyszkiewicz <tomasz@rzymyszkiewicz.com>
Co-authored-by: Tomo Tomov <tomotomov92@gmail.com>
Co-authored-by: User 123456789 <user123456789@users.noreply.hosted.weblate.org>
Co-authored-by: Vaja Benidze <luvared@gmail.com>
Co-authored-by: Vegard Fladby <vegard@fladby.org>
Co-authored-by: Wolfgang Schwendtbauer <wolfgang.schwendtbauer@gmail.com>
Co-authored-by: Wout Van den Bossche <woutvdb@icloud.com>
Co-authored-by: anton garcias <isaga.percompartir@gmail.com>
Co-authored-by: binnichtaktiv <jonasbradley06@gmail.com>
Co-authored-by: bittin1ddc447d824349b2 <bittin@reimu.nl>
Co-authored-by: chamdim <chamdim@protonmail.com>
Co-authored-by: dionjoshualobo <23h13.joshua@sjec.ac.in>
Co-authored-by: dvbthien <dvbthien@users.noreply.hosted.weblate.org>
Co-authored-by: eav5jhl0 <eav5jhl0@users.noreply.hosted.weblate.org>
Co-authored-by: kgerg <kgergelyzs@gmail.com>
Co-authored-by: koffevar <koffevar@users.noreply.github.com>
Co-authored-by: kylo32 <kylo32@gmail.com>
Co-authored-by: lulala <sap777@msn.com>
Co-authored-by: lumppu <saukkolanerkki@gmail.com>
Co-authored-by: miiyuh <itsazripp2@gmail.com>
Co-authored-by: millallo <millallo@tiscali.it>
Co-authored-by: muziqaz <muziqaz@users.noreply.hosted.weblate.org>
Co-authored-by: muziqaz <weblate.scapegoat467@passmail.net>
Co-authored-by: otterstedt <otterstedt@gmail.com>
Co-authored-by: pyccl <changcongliang@163.com>
Co-authored-by: rohamaa <rohamaa@outlook.com>
Co-authored-by: shiuh67 <shiuh.cheng@gmail.com>
Co-authored-by: stesoma <soma.steltzer@gmail.com>
Co-authored-by: theCataclysm808 <mail@sebastiangeithner.de>
Co-authored-by: twkim <angelos0424@gmail.com>
Co-authored-by: userrand6 <info@mh0.eu>
Co-authored-by: waclaw66 <waclaw66@seznam.cz>
Co-authored-by: Мĕтри Сантăр ывалĕ Упа-Миччи <mefisteron@gmail.com>
Co-authored-by: Максим Горпиніч <gorpinicmaksim0@gmail.com>
Co-authored-by: 안세훈 <on9686@gmail.com>
Co-authored-by: Daniel Dietzler <mail@ddietzler.dev>
2026-01-27 16:11:08 -05:00
Weblate (bot)
b5a3334e30 chore(web): update translations (#25576)
* chore(web): update translations

Co-authored-by: 0v0 <0v0tvs@gmail.com>
Co-authored-by: 100daysummer <bobbydochev@gmail.com>
Co-authored-by: Adam Havránek <adamhavra@seznam.cz>
Co-authored-by: Adrián Nieto Rodríguez <adrian.nieto7@gmail.com>
Co-authored-by: Agostino Pit <scheccia@gmail.com>
Co-authored-by: Ahmed Khaleel Shihab <ahmed91shihab@gmail.com>
Co-authored-by: Aindriú Mac Giolla Eoin <aindriu80@gmail.com>
Co-authored-by: Alexandre <alexandre.tressel@icloud.com>
Co-authored-by: Alexandre <pikpakpik@users.noreply.hosted.weblate.org>
Co-authored-by: Alin T <amin4fun@yahoo.com>
Co-authored-by: Ameer Hamza <ah75102@gmail.com>
Co-authored-by: Amir <amirikmel@gmail.com>
Co-authored-by: Antoine Maalouf <atmaalouf@gmail.com>
Co-authored-by: Anton Palmqvist <apq@users.noreply.hosted.weblate.org>
Co-authored-by: Aravinth <aravinth@tuta.io>
Co-authored-by: Arnau Mora <arnyminer.z@gmail.com>
Co-authored-by: Artem Grauberger <graubergerartem@gmail.com>
Co-authored-by: AtmosphericIgnition <dev@prusa.net>
Co-authored-by: Bagas Dwi <bagasdwin15@gmail.com>
Co-authored-by: Balázs R <nvi9@outlook.hu>
Co-authored-by: BarMan <weblate.barman632@simplelogin.com>
Co-authored-by: Bart Simons <bart2jes@gmail.com>
Co-authored-by: Bartłomiej <20731216+Jarsey45@users.noreply.github.com>
Co-authored-by: Beans <leey0818@gmail.com>
Co-authored-by: Branden S <schrenk.br@gmail.com>
Co-authored-by: Bruno Antunes <antunes.dll@gmail.com>
Co-authored-by: CHUNG, Jin-ho <doctorjinho@gmail.com>
Co-authored-by: CanbiZ <mickey.leskowitz@gmail.com>
Co-authored-by: Carl Bergan <carl.bergan@gmail.com>
Co-authored-by: Carl Hansson <carlhansson677@gmail.com>
Co-authored-by: Cem TURKER <forumcemturker@gmail.com>
Co-authored-by: Collignon-Ducret Rémi <remi+github@collignon-ducret.fr>
Co-authored-by: Constantin <lulu195@users.noreply.hosted.weblate.org>
Co-authored-by: Cédric <cedric@laubacher.io>
Co-authored-by: Damian Krysta <krypton9208@gmail.com>
Co-authored-by: Daniel Pätzold <weblate.labrador503@passmail.net>
Co-authored-by: Degani Giancarlo <giancarlo@degani.eu>
Co-authored-by: Denis Pacquier <denis.pacquier@gmail.com>
Co-authored-by: DevServs <bonov@mail.ru>
Co-authored-by: Don't use my name <maxabmeyer@gmail.com>
Co-authored-by: Dusan Hlavaty <dhlavaty@gmail.com>
Co-authored-by: Dániel Gál <galdaniel.school@gmail.com>
Co-authored-by: Eduardo Maciel <edumaciel1221@gmail.com>
Co-authored-by: Emil <emil.ca.carls+weblate@gmail.com>
Co-authored-by: Eric Hebert <ericheb@gmail.com>
Co-authored-by: Federico Cervelli <federicocervelli01@gmail.com>
Co-authored-by: Felipe Cury <weblate@flpcury.com>
Co-authored-by: Fjuro <fjuro@alius.cz>
Co-authored-by: Gabriel <jellyfin.sensitize624@passmail.net>
Co-authored-by: Gary <zgr0629@gmail.com>
Co-authored-by: George Tsotsos <geoxor123@outlook.com>
Co-authored-by: Georgios Tsotsos <geoxor123@outlook.com>
Co-authored-by: Giorgio M <giorgio.maulu@gmail.com>
Co-authored-by: Guillermo Ramos Santos <guillermo.ramosantos@gmail.com>
Co-authored-by: HackingAll <hacking.all.YT@gmail.com>
Co-authored-by: Haki Bardhi <hakibardhi7@gmail.com>
Co-authored-by: HaoSs07 <haoss07@gmail.com>
Co-authored-by: Haru Ijima <haruijimakun@gmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Hurricane_32 <rodrigorimo@hotmail.com>
Co-authored-by: Hồ Nhất Duy <axicenia@gmail.com>
Co-authored-by: Ilya <vlk.ilya@users.noreply.hosted.weblate.org>
Co-authored-by: Immich <weblate@immich.app>
Co-authored-by: Indrek Haav <indrek.haav@hotmail.com>
Co-authored-by: Ivan Dimitrov <idimitrov08@gmail.com>
Co-authored-by: JM Garcia <jmgrc1626@gmail.com>
Co-authored-by: Jadde <Jasper@pgpmail.dk>
Co-authored-by: Jason Song <songpeiheng@gmail.com>
Co-authored-by: Jeppe Nellemann <jepnel@proton.me>
Co-authored-by: Jiri Grönroos <jiri.gronroos@iki.fi>
Co-authored-by: Joel <octavianporsche@gmail.com>
Co-authored-by: John denar <weblate.direct@privacyshield.online>
Co-authored-by: Jordy H <jordy@hoebergen.net>
Co-authored-by: Jozef Gaal <preklady@mayday.sk>
Co-authored-by: Julian Poidevin <poidevin.julian@gmail.com>
Co-authored-by: K Emil <kristianemilmadsen@gmail.com>
Co-authored-by: Katherine <kate.schumacher@gmail.com>
Co-authored-by: Kuba <kubaant@gmail.com>
Co-authored-by: Lemon Cat <lmncat3@gmail.com>
Co-authored-by: Leo Bottaro <github@leobottaro.com>
Co-authored-by: Liviu Roman <contact@liviuroman.com>
Co-authored-by: Lluís Forns <enboig@disroot.org>
Co-authored-by: Lorenzo <artale.lorenzo@outlook.it>
Co-authored-by: Loris Sambinelli <loriss84@gmail.com>
Co-authored-by: Lucas Jaksys <lucas3033@gmail.com>
Co-authored-by: Lucas Manzke <lmprogg@gmail.com>
Co-authored-by: Luuk Heijnen <luukheijnen1@gmail.com>
Co-authored-by: M4th12 <mattia.caldera04@gmail.com>
Co-authored-by: MSDNicrosoft <i@msdnicrosoft.work>
Co-authored-by: MSDNicrosoft <wang3311835119@hotmail.com>
Co-authored-by: MaBeniu <runnerm@gmail.com>
Co-authored-by: Macgyver <macgyver@users.noreply.hosted.weblate.org>
Co-authored-by: Mads Bojesen <madsrbojesen@gmail.com>
Co-authored-by: Marc Casillas <mcasillassu@gmail.com>
Co-authored-by: MarcSerraPeralta <marcserraperalta@gmail.com>
Co-authored-by: Marian Wolf <marian.wolf2008@gmail.com>
Co-authored-by: Martynas <kingsizekebab@protonmail.com>
Co-authored-by: Marwan Jalaleddine <marwanjalaleddine@gmail.com>
Co-authored-by: Mateusz Filipowicz <matfilipowicz@gmail.com>
Co-authored-by: Matjaž T. <matjaz@moj-svet.si>
Co-authored-by: Matt Peperell <mattp@users.noreply.hosted.weblate.org>
Co-authored-by: Mees Frensel <meesfrensel@gmail.com>
Co-authored-by: Michael <mail@michaelhofer.ch>
Co-authored-by: Mihailo Gostiljac <gostiljaccc99@gmail.com>
Co-authored-by: Mohammed Khan <weblate@mkodify.org>
Co-authored-by: Muhammad Ghassan Ihsan Kamil <heysans.kamil@gmail.com>
Co-authored-by: Mārtiņš Bruņenieks <martinsb@gmail.com>
Co-authored-by: Naim Hasim <ainadanaim@gmail.com>
Co-authored-by: Niccolò Cocchi <nicco.r.cocchi@gmail.com>
Co-authored-by: Nico Kaiser <nico@kaiser.me>
Co-authored-by: Olaf Nielsen <solluh@mail.de>
Co-authored-by: Oleksandr Yurov <oyurov@icloud.com>
Co-authored-by: Peer Ewald <pulse-charger-open@duck.com>
Co-authored-by: PhillyMay <mein.alias@outlook.com>
Co-authored-by: PontusÖsterlindh <pontus@osterlindh.com>
Co-authored-by: Putthimedh Jarusirisoonthorn <toto.jaru@gmail.com>
Co-authored-by: ROCK TAKEY <rocktakey@gmail.com>
Co-authored-by: Remco <remco@pander.io>
Co-authored-by: Rey <x46puy43k@mozmail.com>
Co-authored-by: Riccardo Parise <riccardo@parise.space>
Co-authored-by: Roberto Burchi <elburchio@gmail.com>
Co-authored-by: Roger Veciana Rovira <rveciana@gmail.com>
Co-authored-by: Rohama <32406304+dev-mkm@users.noreply.github.com>
Co-authored-by: Romo <romo@romo.al>
Co-authored-by: Rune J. <runekj@duck.com>
Co-authored-by: Saba Sakvarelidze <cal1b4nnn@gmail.com>
Co-authored-by: Sait Furkan Selçuk <sait574577@gmail.com>
Co-authored-by: Samhar Hijazi <semokoda@keemail.me>
Co-authored-by: Sami Cooper (CYB3ROID694) <sami.mhatre756@gmail.com>
Co-authored-by: Sergio <svillar@igalia.com>
Co-authored-by: Sergio Espada Rubio <espadauni@gmail.com>
Co-authored-by: Shawn <xiaxinx@gmail.com>
Co-authored-by: Shjosan <shjosan@kakmix.co>
Co-authored-by: Simon L. B. Sørensen <simonxarro@gmail.com>
Co-authored-by: Sjoerd van Daal <sjoerd.van.daal@proton.me>
Co-authored-by: Skanda <skillwiz94@gmail.com>
Co-authored-by: Sonny Saul Aguilar Alvarez (sonnyano909) <aguilarsaulsonny@gmail.com>
Co-authored-by: Sophie <mail@sopht.li>
Co-authored-by: Stan P <g97d6liib@mozmail.com>
Co-authored-by: Stanly Swagato Halder <stanlyhalder@gmail.com>
Co-authored-by: Sylvain Pichon <service@spichon.fr>
Co-authored-by: Szymon Kucharski <szymon.kucharski5@gmail.com>
Co-authored-by: TV Box <realceday.tvbox@gmail.com>
Co-authored-by: Taiki M. <vexingly-many-mace@duck.com>
Co-authored-by: Takayuki Maeda <takoyaki0316@gmail.com>
Co-authored-by: Temuri Doghonadze <temuri.doghonadze@gmail.com>
Co-authored-by: Tim Morley <weblate.3919org@timsk.org>
Co-authored-by: Tomasz Rzymyszkiewicz <tomasz@rzymyszkiewicz.com>
Co-authored-by: Tomo Tomov <tomotomov92@gmail.com>
Co-authored-by: User 123456789 <user123456789@users.noreply.hosted.weblate.org>
Co-authored-by: Vaja Benidze <luvared@gmail.com>
Co-authored-by: Vegard Fladby <vegard@fladby.org>
Co-authored-by: Wolfgang Schwendtbauer <wolfgang.schwendtbauer@gmail.com>
Co-authored-by: Wout Van den Bossche <woutvdb@icloud.com>
Co-authored-by: anton garcias <isaga.percompartir@gmail.com>
Co-authored-by: binnichtaktiv <jonasbradley06@gmail.com>
Co-authored-by: bittin1ddc447d824349b2 <bittin@reimu.nl>
Co-authored-by: chamdim <chamdim@protonmail.com>
Co-authored-by: dionjoshualobo <23h13.joshua@sjec.ac.in>
Co-authored-by: dvbthien <dvbthien@users.noreply.hosted.weblate.org>
Co-authored-by: eav5jhl0 <eav5jhl0@users.noreply.hosted.weblate.org>
Co-authored-by: kgerg <kgergelyzs@gmail.com>
Co-authored-by: koffevar <koffevar@users.noreply.github.com>
Co-authored-by: kylo32 <kylo32@gmail.com>
Co-authored-by: lulala <sap777@msn.com>
Co-authored-by: lumppu <saukkolanerkki@gmail.com>
Co-authored-by: miiyuh <itsazripp2@gmail.com>
Co-authored-by: millallo <millallo@tiscali.it>
Co-authored-by: muziqaz <muziqaz@users.noreply.hosted.weblate.org>
Co-authored-by: muziqaz <weblate.scapegoat467@passmail.net>
Co-authored-by: otterstedt <otterstedt@gmail.com>
Co-authored-by: pyccl <changcongliang@163.com>
Co-authored-by: rohamaa <rohamaa@outlook.com>
Co-authored-by: shiuh67 <shiuh.cheng@gmail.com>
Co-authored-by: stesoma <soma.steltzer@gmail.com>
Co-authored-by: theCataclysm808 <mail@sebastiangeithner.de>
Co-authored-by: twkim <angelos0424@gmail.com>
Co-authored-by: userrand6 <info@mh0.eu>
Co-authored-by: waclaw66 <waclaw66@seznam.cz>
Co-authored-by: Мĕтри Сантăр ывалĕ Упа-Миччи <mefisteron@gmail.com>
Co-authored-by: Максим Горпиніч <gorpinicmaksim0@gmail.com>
Co-authored-by: 안세훈 <on9686@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/immich/immich/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/ar/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/be/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/bg/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/bn/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/ca/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/cs/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/cv/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/da/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/de/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/de_CH/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/el/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/eo/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/es/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/et/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/fa/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/fi/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/fil/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/fr/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/ga/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/gl/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/gsw/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/he/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/hi/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/hu/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/id/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/it/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/ja/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/ka/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/kn/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/ko/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/lt/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/lv/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/ml/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/mr/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/ms/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/nb_NO/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/nl/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/pl/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/pt/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/pt_BR/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/ro/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/ru/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/sk/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/sl/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/sq/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/sr_Latn/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/sv/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/ta/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/th/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/tr/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/uk/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/ur/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/vi/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/zh_Hant/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/zh_SIMPLIFIED/
Translation: Immich/immich

* fix: revert package.json

---------

Co-authored-by: 0v0 <0v0tvs@gmail.com>
Co-authored-by: 100daysummer <bobbydochev@gmail.com>
Co-authored-by: Adam Havránek <adamhavra@seznam.cz>
Co-authored-by: Adrián Nieto Rodríguez <adrian.nieto7@gmail.com>
Co-authored-by: Agostino Pit <scheccia@gmail.com>
Co-authored-by: Ahmed Khaleel Shihab <ahmed91shihab@gmail.com>
Co-authored-by: Aindriú Mac Giolla Eoin <aindriu80@gmail.com>
Co-authored-by: Alexandre <alexandre.tressel@icloud.com>
Co-authored-by: Alexandre <pikpakpik@users.noreply.hosted.weblate.org>
Co-authored-by: Alin T <amin4fun@yahoo.com>
Co-authored-by: Ameer Hamza <ah75102@gmail.com>
Co-authored-by: Amir <amirikmel@gmail.com>
Co-authored-by: Antoine Maalouf <atmaalouf@gmail.com>
Co-authored-by: Anton Palmqvist <apq@users.noreply.hosted.weblate.org>
Co-authored-by: Aravinth <aravinth@tuta.io>
Co-authored-by: Arnau Mora <arnyminer.z@gmail.com>
Co-authored-by: Artem Grauberger <graubergerartem@gmail.com>
Co-authored-by: AtmosphericIgnition <dev@prusa.net>
Co-authored-by: Bagas Dwi <bagasdwin15@gmail.com>
Co-authored-by: Balázs R <nvi9@outlook.hu>
Co-authored-by: BarMan <weblate.barman632@simplelogin.com>
Co-authored-by: Bart Simons <bart2jes@gmail.com>
Co-authored-by: Bartłomiej <20731216+Jarsey45@users.noreply.github.com>
Co-authored-by: Beans <leey0818@gmail.com>
Co-authored-by: Branden S <schrenk.br@gmail.com>
Co-authored-by: Bruno Antunes <antunes.dll@gmail.com>
Co-authored-by: CHUNG, Jin-ho <doctorjinho@gmail.com>
Co-authored-by: CanbiZ <mickey.leskowitz@gmail.com>
Co-authored-by: Carl Bergan <carl.bergan@gmail.com>
Co-authored-by: Carl Hansson <carlhansson677@gmail.com>
Co-authored-by: Cem TURKER <forumcemturker@gmail.com>
Co-authored-by: Collignon-Ducret Rémi <remi+github@collignon-ducret.fr>
Co-authored-by: Constantin <lulu195@users.noreply.hosted.weblate.org>
Co-authored-by: Cédric <cedric@laubacher.io>
Co-authored-by: Damian Krysta <krypton9208@gmail.com>
Co-authored-by: Daniel Pätzold <weblate.labrador503@passmail.net>
Co-authored-by: Degani Giancarlo <giancarlo@degani.eu>
Co-authored-by: Denis Pacquier <denis.pacquier@gmail.com>
Co-authored-by: DevServs <bonov@mail.ru>
Co-authored-by: Don't use my name <maxabmeyer@gmail.com>
Co-authored-by: Dusan Hlavaty <dhlavaty@gmail.com>
Co-authored-by: Dániel Gál <galdaniel.school@gmail.com>
Co-authored-by: Eduardo Maciel <edumaciel1221@gmail.com>
Co-authored-by: Emil <emil.ca.carls+weblate@gmail.com>
Co-authored-by: Eric Hebert <ericheb@gmail.com>
Co-authored-by: Federico Cervelli <federicocervelli01@gmail.com>
Co-authored-by: Felipe Cury <weblate@flpcury.com>
Co-authored-by: Fjuro <fjuro@alius.cz>
Co-authored-by: Gabriel <jellyfin.sensitize624@passmail.net>
Co-authored-by: Gary <zgr0629@gmail.com>
Co-authored-by: George Tsotsos <geoxor123@outlook.com>
Co-authored-by: Giorgio M <giorgio.maulu@gmail.com>
Co-authored-by: Guillermo Ramos Santos <guillermo.ramosantos@gmail.com>
Co-authored-by: HackingAll <hacking.all.YT@gmail.com>
Co-authored-by: Haki Bardhi <hakibardhi7@gmail.com>
Co-authored-by: HaoSs07 <haoss07@gmail.com>
Co-authored-by: Haru Ijima <haruijimakun@gmail.com>
Co-authored-by: Hurricane_32 <rodrigorimo@hotmail.com>
Co-authored-by: Hồ Nhất Duy <axicenia@gmail.com>
Co-authored-by: Ilya <vlk.ilya@users.noreply.hosted.weblate.org>
Co-authored-by: Immich <weblate@immich.app>
Co-authored-by: Indrek Haav <indrek.haav@hotmail.com>
Co-authored-by: Ivan Dimitrov <idimitrov08@gmail.com>
Co-authored-by: JM Garcia <jmgrc1626@gmail.com>
Co-authored-by: Jadde <Jasper@pgpmail.dk>
Co-authored-by: Jason Song <songpeiheng@gmail.com>
Co-authored-by: Jeppe Nellemann <jepnel@proton.me>
Co-authored-by: Jiri Grönroos <jiri.gronroos@iki.fi>
Co-authored-by: Joel <octavianporsche@gmail.com>
Co-authored-by: John denar <weblate.direct@privacyshield.online>
Co-authored-by: Jordy H <jordy@hoebergen.net>
Co-authored-by: Jozef Gaal <preklady@mayday.sk>
Co-authored-by: Julian Poidevin <poidevin.julian@gmail.com>
Co-authored-by: K Emil <kristianemilmadsen@gmail.com>
Co-authored-by: Katherine <kate.schumacher@gmail.com>
Co-authored-by: Kuba <kubaant@gmail.com>
Co-authored-by: Lemon Cat <lmncat3@gmail.com>
Co-authored-by: Leo Bottaro <github@leobottaro.com>
Co-authored-by: Liviu Roman <contact@liviuroman.com>
Co-authored-by: Lluís Forns <enboig@disroot.org>
Co-authored-by: Lorenzo <artale.lorenzo@outlook.it>
Co-authored-by: Loris Sambinelli <loriss84@gmail.com>
Co-authored-by: Lucas Jaksys <lucas3033@gmail.com>
Co-authored-by: Lucas Manzke <lmprogg@gmail.com>
Co-authored-by: Luuk Heijnen <luukheijnen1@gmail.com>
Co-authored-by: M4th12 <mattia.caldera04@gmail.com>
Co-authored-by: MSDNicrosoft <i@msdnicrosoft.work>
Co-authored-by: MSDNicrosoft <wang3311835119@hotmail.com>
Co-authored-by: MaBeniu <runnerm@gmail.com>
Co-authored-by: Macgyver <macgyver@users.noreply.hosted.weblate.org>
Co-authored-by: Mads Bojesen <madsrbojesen@gmail.com>
Co-authored-by: Marc Casillas <mcasillassu@gmail.com>
Co-authored-by: MarcSerraPeralta <marcserraperalta@gmail.com>
Co-authored-by: Marian Wolf <marian.wolf2008@gmail.com>
Co-authored-by: Martynas <kingsizekebab@protonmail.com>
Co-authored-by: Marwan Jalaleddine <marwanjalaleddine@gmail.com>
Co-authored-by: Mateusz Filipowicz <matfilipowicz@gmail.com>
Co-authored-by: Matjaž T. <matjaz@moj-svet.si>
Co-authored-by: Matt Peperell <mattp@users.noreply.hosted.weblate.org>
Co-authored-by: Mees Frensel <meesfrensel@gmail.com>
Co-authored-by: Michael <mail@michaelhofer.ch>
Co-authored-by: Mihailo Gostiljac <gostiljaccc99@gmail.com>
Co-authored-by: Mohammed Khan <weblate@mkodify.org>
Co-authored-by: Muhammad Ghassan Ihsan Kamil <heysans.kamil@gmail.com>
Co-authored-by: Mārtiņš Bruņenieks <martinsb@gmail.com>
Co-authored-by: Naim Hasim <ainadanaim@gmail.com>
Co-authored-by: Niccolò Cocchi <nicco.r.cocchi@gmail.com>
Co-authored-by: Nico Kaiser <nico@kaiser.me>
Co-authored-by: Olaf Nielsen <solluh@mail.de>
Co-authored-by: Oleksandr Yurov <oyurov@icloud.com>
Co-authored-by: Peer Ewald <pulse-charger-open@duck.com>
Co-authored-by: PhillyMay <mein.alias@outlook.com>
Co-authored-by: PontusÖsterlindh <pontus@osterlindh.com>
Co-authored-by: Putthimedh Jarusirisoonthorn <toto.jaru@gmail.com>
Co-authored-by: ROCK TAKEY <rocktakey@gmail.com>
Co-authored-by: Remco <remco@pander.io>
Co-authored-by: Rey <x46puy43k@mozmail.com>
Co-authored-by: Riccardo Parise <riccardo@parise.space>
Co-authored-by: Roberto Burchi <elburchio@gmail.com>
Co-authored-by: Roger Veciana Rovira <rveciana@gmail.com>
Co-authored-by: Rohama <32406304+dev-mkm@users.noreply.github.com>
Co-authored-by: Romo <romo@romo.al>
Co-authored-by: Rune J. <runekj@duck.com>
Co-authored-by: Saba Sakvarelidze <cal1b4nnn@gmail.com>
Co-authored-by: Sait Furkan Selçuk <sait574577@gmail.com>
Co-authored-by: Samhar Hijazi <semokoda@keemail.me>
Co-authored-by: Sami Cooper (CYB3ROID694) <sami.mhatre756@gmail.com>
Co-authored-by: Sergio <svillar@igalia.com>
Co-authored-by: Sergio Espada Rubio <espadauni@gmail.com>
Co-authored-by: Shawn <xiaxinx@gmail.com>
Co-authored-by: Shjosan <shjosan@kakmix.co>
Co-authored-by: Simon L. B. Sørensen <simonxarro@gmail.com>
Co-authored-by: Sjoerd van Daal <sjoerd.van.daal@proton.me>
Co-authored-by: Skanda <skillwiz94@gmail.com>
Co-authored-by: Sonny Saul Aguilar Alvarez (sonnyano909) <aguilarsaulsonny@gmail.com>
Co-authored-by: Sophie <mail@sopht.li>
Co-authored-by: Stan P <g97d6liib@mozmail.com>
Co-authored-by: Stanly Swagato Halder <stanlyhalder@gmail.com>
Co-authored-by: Sylvain Pichon <service@spichon.fr>
Co-authored-by: Szymon Kucharski <szymon.kucharski5@gmail.com>
Co-authored-by: TV Box <realceday.tvbox@gmail.com>
Co-authored-by: Taiki M. <vexingly-many-mace@duck.com>
Co-authored-by: Takayuki Maeda <takoyaki0316@gmail.com>
Co-authored-by: Temuri Doghonadze <temuri.doghonadze@gmail.com>
Co-authored-by: Tim Morley <weblate.3919org@timsk.org>
Co-authored-by: Tomasz Rzymyszkiewicz <tomasz@rzymyszkiewicz.com>
Co-authored-by: Tomo Tomov <tomotomov92@gmail.com>
Co-authored-by: User 123456789 <user123456789@users.noreply.hosted.weblate.org>
Co-authored-by: Vaja Benidze <luvared@gmail.com>
Co-authored-by: Vegard Fladby <vegard@fladby.org>
Co-authored-by: Wolfgang Schwendtbauer <wolfgang.schwendtbauer@gmail.com>
Co-authored-by: Wout Van den Bossche <woutvdb@icloud.com>
Co-authored-by: anton garcias <isaga.percompartir@gmail.com>
Co-authored-by: binnichtaktiv <jonasbradley06@gmail.com>
Co-authored-by: bittin1ddc447d824349b2 <bittin@reimu.nl>
Co-authored-by: chamdim <chamdim@protonmail.com>
Co-authored-by: dionjoshualobo <23h13.joshua@sjec.ac.in>
Co-authored-by: dvbthien <dvbthien@users.noreply.hosted.weblate.org>
Co-authored-by: eav5jhl0 <eav5jhl0@users.noreply.hosted.weblate.org>
Co-authored-by: kgerg <kgergelyzs@gmail.com>
Co-authored-by: koffevar <koffevar@users.noreply.github.com>
Co-authored-by: kylo32 <kylo32@gmail.com>
Co-authored-by: lulala <sap777@msn.com>
Co-authored-by: lumppu <saukkolanerkki@gmail.com>
Co-authored-by: miiyuh <itsazripp2@gmail.com>
Co-authored-by: millallo <millallo@tiscali.it>
Co-authored-by: muziqaz <muziqaz@users.noreply.hosted.weblate.org>
Co-authored-by: muziqaz <weblate.scapegoat467@passmail.net>
Co-authored-by: otterstedt <otterstedt@gmail.com>
Co-authored-by: pyccl <changcongliang@163.com>
Co-authored-by: rohamaa <rohamaa@outlook.com>
Co-authored-by: shiuh67 <shiuh.cheng@gmail.com>
Co-authored-by: stesoma <soma.steltzer@gmail.com>
Co-authored-by: theCataclysm808 <mail@sebastiangeithner.de>
Co-authored-by: twkim <angelos0424@gmail.com>
Co-authored-by: userrand6 <info@mh0.eu>
Co-authored-by: waclaw66 <waclaw66@seznam.cz>
Co-authored-by: Мĕтри Сантăр ывалĕ Упа-Миччи <mefisteron@gmail.com>
Co-authored-by: Максим Горпиніч <gorpinicmaksim0@gmail.com>
Co-authored-by: 안세훈 <on9686@gmail.com>
Co-authored-by: Daniel Dietzler <mail@ddietzler.dev>
2026-01-27 19:42:55 +00:00
Weblate (bot)
53718f01bb chore(web): update translations (#25574)
Translate-URL: https://hosted.weblate.org/projects/immich/immich/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/ar/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/be/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/bg/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/bn/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/ca/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/cs/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/cv/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/da/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/de/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/de_CH/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/el/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/eo/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/es/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/et/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/fa/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/fi/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/fil/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/fr/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/ga/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/gl/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/gsw/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/he/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/hi/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/hu/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/id/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/it/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/ja/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/ka/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/kn/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/ko/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/lt/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/lv/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/ml/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/mr/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/ms/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/nb_NO/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/nl/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/pl/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/pt/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/pt_BR/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/ro/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/ru/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/sk/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/sl/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/sq/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/sr_Latn/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/sv/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/ta/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/th/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/tr/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/uk/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/ur/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/vi/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/zh_Hant/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/zh_SIMPLIFIED/
Translation: Immich/immich

Co-authored-by: 0v0 <0v0tvs@gmail.com>
Co-authored-by: 100daysummer <bobbydochev@gmail.com>
Co-authored-by: Adam Havránek <adamhavra@seznam.cz>
Co-authored-by: Adrián Nieto Rodríguez <adrian.nieto7@gmail.com>
Co-authored-by: Agostino Pit <scheccia@gmail.com>
Co-authored-by: Ahmed Khaleel Shihab <ahmed91shihab@gmail.com>
Co-authored-by: Aindriú Mac Giolla Eoin <aindriu80@gmail.com>
Co-authored-by: Alexandre <alexandre.tressel@icloud.com>
Co-authored-by: Alexandre <pikpakpik@users.noreply.hosted.weblate.org>
Co-authored-by: Alin T <amin4fun@yahoo.com>
Co-authored-by: Ameer Hamza <ah75102@gmail.com>
Co-authored-by: Amir <amirikmel@gmail.com>
Co-authored-by: Antoine Maalouf <atmaalouf@gmail.com>
Co-authored-by: Anton Palmqvist <apq@users.noreply.hosted.weblate.org>
Co-authored-by: Aravinth <aravinth@tuta.io>
Co-authored-by: Arnau Mora <arnyminer.z@gmail.com>
Co-authored-by: Artem Grauberger <graubergerartem@gmail.com>
Co-authored-by: AtmosphericIgnition <dev@prusa.net>
Co-authored-by: Bagas Dwi <bagasdwin15@gmail.com>
Co-authored-by: Balázs R <nvi9@outlook.hu>
Co-authored-by: BarMan <weblate.barman632@simplelogin.com>
Co-authored-by: Bart Simons <bart2jes@gmail.com>
Co-authored-by: Bartłomiej <20731216+Jarsey45@users.noreply.github.com>
Co-authored-by: Beans <leey0818@gmail.com>
Co-authored-by: Branden S <schrenk.br@gmail.com>
Co-authored-by: Bruno Antunes <antunes.dll@gmail.com>
Co-authored-by: CHUNG, Jin-ho <doctorjinho@gmail.com>
Co-authored-by: CanbiZ <mickey.leskowitz@gmail.com>
Co-authored-by: Carl Bergan <carl.bergan@gmail.com>
Co-authored-by: Carl Hansson <carlhansson677@gmail.com>
Co-authored-by: Cem TURKER <forumcemturker@gmail.com>
Co-authored-by: Collignon-Ducret Rémi <remi+github@collignon-ducret.fr>
Co-authored-by: Constantin <lulu195@users.noreply.hosted.weblate.org>
Co-authored-by: Cédric <cedric@laubacher.io>
Co-authored-by: Damian Krysta <krypton9208@gmail.com>
Co-authored-by: Daniel Pätzold <weblate.labrador503@passmail.net>
Co-authored-by: Degani Giancarlo <giancarlo@degani.eu>
Co-authored-by: Denis Pacquier <denis.pacquier@gmail.com>
Co-authored-by: DevServs <bonov@mail.ru>
Co-authored-by: Don't use my name <maxabmeyer@gmail.com>
Co-authored-by: Dusan Hlavaty <dhlavaty@gmail.com>
Co-authored-by: Dániel Gál <galdaniel.school@gmail.com>
Co-authored-by: Eduardo Maciel <edumaciel1221@gmail.com>
Co-authored-by: Emil <emil.ca.carls+weblate@gmail.com>
Co-authored-by: Eric Hebert <ericheb@gmail.com>
Co-authored-by: Federico Cervelli <federicocervelli01@gmail.com>
Co-authored-by: Felipe Cury <weblate@flpcury.com>
Co-authored-by: Fjuro <fjuro@alius.cz>
Co-authored-by: Gabriel <jellyfin.sensitize624@passmail.net>
Co-authored-by: Gary <zgr0629@gmail.com>
Co-authored-by: George Tsotsos <geoxor123@outlook.com>
Co-authored-by: Giorgio M <giorgio.maulu@gmail.com>
Co-authored-by: Guillermo Ramos Santos <guillermo.ramosantos@gmail.com>
Co-authored-by: HackingAll <hacking.all.YT@gmail.com>
Co-authored-by: Haki Bardhi <hakibardhi7@gmail.com>
Co-authored-by: HaoSs07 <haoss07@gmail.com>
Co-authored-by: Haru Ijima <haruijimakun@gmail.com>
Co-authored-by: Hurricane_32 <rodrigorimo@hotmail.com>
Co-authored-by: Hồ Nhất Duy <axicenia@gmail.com>
Co-authored-by: Ilya <vlk.ilya@users.noreply.hosted.weblate.org>
Co-authored-by: Immich <weblate@immich.app>
Co-authored-by: Indrek Haav <indrek.haav@hotmail.com>
Co-authored-by: Ivan Dimitrov <idimitrov08@gmail.com>
Co-authored-by: JM Garcia <jmgrc1626@gmail.com>
Co-authored-by: Jadde <Jasper@pgpmail.dk>
Co-authored-by: Jason Song <songpeiheng@gmail.com>
Co-authored-by: Jeppe Nellemann <jepnel@proton.me>
Co-authored-by: Jiri Grönroos <jiri.gronroos@iki.fi>
Co-authored-by: Joel <octavianporsche@gmail.com>
Co-authored-by: John denar <weblate.direct@privacyshield.online>
Co-authored-by: Jordy H <jordy@hoebergen.net>
Co-authored-by: Jozef Gaal <preklady@mayday.sk>
Co-authored-by: Julian Poidevin <poidevin.julian@gmail.com>
Co-authored-by: K Emil <kristianemilmadsen@gmail.com>
Co-authored-by: Katherine <kate.schumacher@gmail.com>
Co-authored-by: Kuba <kubaant@gmail.com>
Co-authored-by: Lemon Cat <lmncat3@gmail.com>
Co-authored-by: Leo Bottaro <github@leobottaro.com>
Co-authored-by: Liviu Roman <contact@liviuroman.com>
Co-authored-by: Lluís Forns <enboig@disroot.org>
Co-authored-by: Lorenzo <artale.lorenzo@outlook.it>
Co-authored-by: Loris Sambinelli <loriss84@gmail.com>
Co-authored-by: Lucas Jaksys <lucas3033@gmail.com>
Co-authored-by: Lucas Manzke <lmprogg@gmail.com>
Co-authored-by: Luuk Heijnen <luukheijnen1@gmail.com>
Co-authored-by: M4th12 <mattia.caldera04@gmail.com>
Co-authored-by: MSDNicrosoft <i@msdnicrosoft.work>
Co-authored-by: MSDNicrosoft <wang3311835119@hotmail.com>
Co-authored-by: MaBeniu <runnerm@gmail.com>
Co-authored-by: Macgyver <macgyver@users.noreply.hosted.weblate.org>
Co-authored-by: Mads Bojesen <madsrbojesen@gmail.com>
Co-authored-by: Marc Casillas <mcasillassu@gmail.com>
Co-authored-by: MarcSerraPeralta <marcserraperalta@gmail.com>
Co-authored-by: Marian Wolf <marian.wolf2008@gmail.com>
Co-authored-by: Martynas <kingsizekebab@protonmail.com>
Co-authored-by: Marwan Jalaleddine <marwanjalaleddine@gmail.com>
Co-authored-by: Mateusz Filipowicz <matfilipowicz@gmail.com>
Co-authored-by: Matjaž T. <matjaz@moj-svet.si>
Co-authored-by: Matt Peperell <mattp@users.noreply.hosted.weblate.org>
Co-authored-by: Mees Frensel <meesfrensel@gmail.com>
Co-authored-by: Michael <mail@michaelhofer.ch>
Co-authored-by: Mihailo Gostiljac <gostiljaccc99@gmail.com>
Co-authored-by: Mohammed Khan <weblate@mkodify.org>
Co-authored-by: Muhammad Ghassan Ihsan Kamil <heysans.kamil@gmail.com>
Co-authored-by: Mārtiņš Bruņenieks <martinsb@gmail.com>
Co-authored-by: Naim Hasim <ainadanaim@gmail.com>
Co-authored-by: Niccolò Cocchi <nicco.r.cocchi@gmail.com>
Co-authored-by: Nico Kaiser <nico@kaiser.me>
Co-authored-by: Olaf Nielsen <solluh@mail.de>
Co-authored-by: Oleksandr Yurov <oyurov@icloud.com>
Co-authored-by: Peer Ewald <pulse-charger-open@duck.com>
Co-authored-by: PhillyMay <mein.alias@outlook.com>
Co-authored-by: PontusÖsterlindh <pontus@osterlindh.com>
Co-authored-by: Putthimedh Jarusirisoonthorn <toto.jaru@gmail.com>
Co-authored-by: ROCK TAKEY <rocktakey@gmail.com>
Co-authored-by: Remco <remco@pander.io>
Co-authored-by: Rey <x46puy43k@mozmail.com>
Co-authored-by: Riccardo Parise <riccardo@parise.space>
Co-authored-by: Roberto Burchi <elburchio@gmail.com>
Co-authored-by: Roger Veciana Rovira <rveciana@gmail.com>
Co-authored-by: Rohama <32406304+dev-mkm@users.noreply.github.com>
Co-authored-by: Romo <romo@romo.al>
Co-authored-by: Rune J. <runekj@duck.com>
Co-authored-by: Saba Sakvarelidze <cal1b4nnn@gmail.com>
Co-authored-by: Sait Furkan Selçuk <sait574577@gmail.com>
Co-authored-by: Samhar Hijazi <semokoda@keemail.me>
Co-authored-by: Sami Cooper (CYB3ROID694) <sami.mhatre756@gmail.com>
Co-authored-by: Sergio <svillar@igalia.com>
Co-authored-by: Sergio Espada Rubio <espadauni@gmail.com>
Co-authored-by: Shawn <xiaxinx@gmail.com>
Co-authored-by: Shjosan <shjosan@kakmix.co>
Co-authored-by: Simon L. B. Sørensen <simonxarro@gmail.com>
Co-authored-by: Sjoerd van Daal <sjoerd.van.daal@proton.me>
Co-authored-by: Skanda <skillwiz94@gmail.com>
Co-authored-by: Sonny Saul Aguilar Alvarez (sonnyano909) <aguilarsaulsonny@gmail.com>
Co-authored-by: Sophie <mail@sopht.li>
Co-authored-by: Stan P <g97d6liib@mozmail.com>
Co-authored-by: Stanly Swagato Halder <stanlyhalder@gmail.com>
Co-authored-by: Sylvain Pichon <service@spichon.fr>
Co-authored-by: Szymon Kucharski <szymon.kucharski5@gmail.com>
Co-authored-by: TV Box <realceday.tvbox@gmail.com>
Co-authored-by: Taiki M. <vexingly-many-mace@duck.com>
Co-authored-by: Takayuki Maeda <takoyaki0316@gmail.com>
Co-authored-by: Temuri Doghonadze <temuri.doghonadze@gmail.com>
Co-authored-by: Tim Morley <weblate.3919org@timsk.org>
Co-authored-by: Tomasz Rzymyszkiewicz <tomasz@rzymyszkiewicz.com>
Co-authored-by: Tomo Tomov <tomotomov92@gmail.com>
Co-authored-by: User 123456789 <user123456789@users.noreply.hosted.weblate.org>
Co-authored-by: Vaja Benidze <luvared@gmail.com>
Co-authored-by: Vegard Fladby <vegard@fladby.org>
Co-authored-by: Wolfgang Schwendtbauer <wolfgang.schwendtbauer@gmail.com>
Co-authored-by: Wout Van den Bossche <woutvdb@icloud.com>
Co-authored-by: anton garcias <isaga.percompartir@gmail.com>
Co-authored-by: binnichtaktiv <jonasbradley06@gmail.com>
Co-authored-by: bittin1ddc447d824349b2 <bittin@reimu.nl>
Co-authored-by: chamdim <chamdim@protonmail.com>
Co-authored-by: dionjoshualobo <23h13.joshua@sjec.ac.in>
Co-authored-by: dvbthien <dvbthien@users.noreply.hosted.weblate.org>
Co-authored-by: eav5jhl0 <eav5jhl0@users.noreply.hosted.weblate.org>
Co-authored-by: kgerg <kgergelyzs@gmail.com>
Co-authored-by: koffevar <koffevar@users.noreply.github.com>
Co-authored-by: kylo32 <kylo32@gmail.com>
Co-authored-by: lulala <sap777@msn.com>
Co-authored-by: lumppu <saukkolanerkki@gmail.com>
Co-authored-by: miiyuh <itsazripp2@gmail.com>
Co-authored-by: millallo <millallo@tiscali.it>
Co-authored-by: muziqaz <muziqaz@users.noreply.hosted.weblate.org>
Co-authored-by: muziqaz <weblate.scapegoat467@passmail.net>
Co-authored-by: otterstedt <otterstedt@gmail.com>
Co-authored-by: pyccl <changcongliang@163.com>
Co-authored-by: rohamaa <rohamaa@outlook.com>
Co-authored-by: shiuh67 <shiuh.cheng@gmail.com>
Co-authored-by: stesoma <soma.steltzer@gmail.com>
Co-authored-by: theCataclysm808 <mail@sebastiangeithner.de>
Co-authored-by: twkim <angelos0424@gmail.com>
Co-authored-by: userrand6 <info@mh0.eu>
Co-authored-by: waclaw66 <waclaw66@seznam.cz>
Co-authored-by: Мĕтри Сантăр ывалĕ Упа-Миччи <mefisteron@gmail.com>
Co-authored-by: Максим Горпиніч <gorpinicmaksim0@gmail.com>
Co-authored-by: 안세훈 <on9686@gmail.com>
2026-01-27 19:33:22 +00:00
Jason Rasmussen
b51e0f1007 chore: npm oidc publish (#25573) 2026-01-27 14:00:49 -05:00
843 changed files with 17616 additions and 6930 deletions

View File

@@ -26,7 +26,81 @@
"vitest.explorer",
"ms-playwright.playwright",
"ms-azuretools.vscode-docker"
]
],
"settings": {
"tasks": {
"version": "2.0.0",
"tasks": [
{
"label": "Fix Permissions, Install Dependencies",
"type": "shell",
"command": "[ -f /immich-devcontainer/container-start.sh ] && /immich-devcontainer/container-start.sh || exit 0",
"isBackground": true,
"presentation": {
"echo": true,
"reveal": "always",
"focus": false,
"panel": "dedicated",
"showReuseMessage": true,
"clear": false,
"group": "Devcontainer tasks",
"close": true
},
"runOptions": {
"runOn": "default"
},
"problemMatcher": []
},
{
"label": "Immich API Server (Nest)",
"dependsOn": ["Fix Permissions, Install Dependencies"],
"type": "shell",
"command": "[ -f /immich-devcontainer/container-start-backend.sh ] && /immich-devcontainer/container-start-backend.sh || exit 0",
"isBackground": true,
"presentation": {
"echo": true,
"reveal": "always",
"focus": false,
"panel": "dedicated",
"showReuseMessage": true,
"clear": false,
"group": "Devcontainer tasks",
"close": true
},
"runOptions": {
"runOn": "folderOpen"
},
"problemMatcher": []
},
{
"label": "Immich Web Server (Vite)",
"dependsOn": ["Fix Permissions, Install Dependencies"],
"type": "shell",
"command": "[ -f /immich-devcontainer/container-start-frontend.sh ] && /immich-devcontainer/container-start-frontend.sh || exit 0",
"isBackground": true,
"presentation": {
"echo": true,
"reveal": "always",
"focus": false,
"panel": "dedicated",
"showReuseMessage": true,
"clear": false,
"group": "Devcontainer tasks",
"close": true
},
"runOptions": {
"runOn": "folderOpen"
},
"problemMatcher": []
},
{
"label": "Build Immich CLI",
"type": "shell",
"command": "pnpm --filter cli build:dev"
}
]
}
}
}
},
"features": {

View File

@@ -269,6 +269,8 @@ jobs:
ENVIRONMENT: ${{ inputs.environment || 'development' }}
BUNDLE_ID_SUFFIX: ${{ inputs.environment == 'production' && '' || 'development' }}
GITHUB_REF: ${{ github.ref }}
FASTLANE_XCODEBUILD_SETTINGS_TIMEOUT: 120
FASTLANE_XCODEBUILD_SETTINGS_RETRIES: 6
working-directory: ./mobile/ios
run: |
# Only upload to TestFlight on main branch

View File

@@ -24,10 +24,11 @@ jobs:
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write
packages: write
defaults:
run:
working-directory: ./cli
steps:
- id: token
uses: immich-app/devtools/actions/create-workflow-token@da177fa133657503ddb7503f8ba53dccefec5da1 # create-workflow-token-action-v1.0.0
@@ -57,10 +58,8 @@ jobs:
- run: pnpm install --frozen-lockfile
- run: pnpm build
- run: pnpm publish --no-git-checks
- run: pnpm publish --provenance --no-git-checks
if: ${{ github.event_name == 'release' }}
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
docker:
name: Docker

View File

@@ -131,7 +131,7 @@ jobs:
- device: rocm
suffixes: '-rocm'
platforms: linux/amd64
runner-mapping: '{"linux/amd64": "mich"}'
runner-mapping: '{"linux/amd64": "pokedex-giant"}'
uses: immich-app/devtools/.github/workflows/multi-runner-build.yml@0477486d82313fba68f7c82c034120a4b8981297 # multi-runner-build-workflow-v2.1.0
permissions:
contents: read

View File

@@ -12,6 +12,8 @@ jobs:
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write
packages: write
defaults:
run:
working-directory: ./open-api/typescript-sdk
@@ -42,6 +44,4 @@ jobs:
- name: Build
run: pnpm build
- name: Publish
run: pnpm publish --no-git-checks
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
run: pnpm publish --provenance --no-git-checks

View File

@@ -497,14 +497,15 @@ jobs:
run: npx playwright install chromium --only-shell
if: ${{ !cancelled() }}
- name: Docker build
run: docker compose build
run: docker compose up -d --build --renew-anon-volumes --force-recreate --remove-orphans --wait --wait-timeout 300
if: ${{ !cancelled() }}
- name: Run e2e tests (web)
env:
CI: true
run: npx playwright test --project=chromium
PLAYWRIGHT_DISABLE_WEBSERVER: true
run: npx playwright test --project=web
if: ${{ !cancelled() }}
- name: Archive web results
- name: Archive e2e test (web) results
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
if: success() || failure()
with:
@@ -513,14 +514,37 @@ jobs:
- name: Run ui tests (web)
env:
CI: true
PLAYWRIGHT_DISABLE_WEBSERVER: true
run: npx playwright test --project=ui
if: ${{ !cancelled() }}
- name: Archive ui results
- name: Archive ui test (web) results
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
if: success() || failure()
with:
name: e2e-ui-test-results-${{ matrix.runner }}
path: e2e/playwright-report/
- name: Run maintenance tests
env:
CI: true
PLAYWRIGHT_DISABLE_WEBSERVER: true
run: npx playwright test --project=maintenance
if: ${{ !cancelled() }}
- name: Archive maintenance tests (web) results
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
if: success() || failure()
with:
name: e2e-maintenance-isolated-test-results-${{ matrix.runner }}
path: e2e/playwright-report/
- name: Capture Docker logs
if: always()
run: docker compose logs --no-color > docker-compose-logs.txt
working-directory: ./e2e
- name: Archive Docker logs
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
if: always()
with:
name: docker-compose-logs-${{ matrix.runner }}
path: e2e/docker-compose-logs.txt
success-check-e2e:
name: End-to-End Tests Success
needs: [e2e-tests-server-cli, e2e-tests-web]
@@ -591,9 +615,9 @@ jobs:
- name: Lint with ruff
run: |
uv run ruff check --output-format=github immich_ml
- name: Check black formatting
- name: Format with ruff
run: |
uv run black --check immich_ml
uv run ruff format --check immich_ml
- name: Run mypy type checking
run: |
uv run mypy --strict immich_ml/

View File

@@ -36,7 +36,7 @@ jobs:
github-token: ${{ steps.token.outputs.token }}
filters: |
i18n:
- modified: 'i18n/!(en)**\.json'
- modified: 'i18n/!(en|package)**\.json'
skip-force-logic: 'true'
enforce-lock:

80
.vscode/tasks.json vendored
View File

@@ -1,80 +0,0 @@
{
"version": "2.0.0",
"tasks": [
{
"label": "Fix Permissions, Install Dependencies",
"type": "shell",
"command": "[ -f /immich-devcontainer/container-start.sh ] && /immich-devcontainer/container-start.sh || exit 0",
"isBackground": true,
"presentation": {
"echo": true,
"reveal": "always",
"focus": false,
"panel": "dedicated",
"showReuseMessage": true,
"clear": false,
"group": "Devcontainer tasks",
"close": true
},
"runOptions": {
"runOn": "default"
},
"problemMatcher": []
},
{
"label": "Immich API Server (Nest)",
"dependsOn": ["Fix Permissions, Install Dependencies"],
"type": "shell",
"command": "[ -f /immich-devcontainer/container-start-backend.sh ] && /immich-devcontainer/container-start-backend.sh || exit 0",
"isBackground": true,
"presentation": {
"echo": true,
"reveal": "always",
"focus": false,
"panel": "dedicated",
"showReuseMessage": true,
"clear": false,
"group": "Devcontainer tasks",
"close": true
},
"runOptions": {
"runOn": "default"
},
"problemMatcher": []
},
{
"label": "Immich Web Server (Vite)",
"dependsOn": ["Fix Permissions, Install Dependencies"],
"type": "shell",
"command": "[ -f /immich-devcontainer/container-start-frontend.sh ] && /immich-devcontainer/container-start-frontend.sh || exit 0",
"isBackground": true,
"presentation": {
"echo": true,
"reveal": "always",
"focus": false,
"panel": "dedicated",
"showReuseMessage": true,
"clear": false,
"group": "Devcontainer tasks",
"close": true
},
"runOptions": {
"runOn": "default"
},
"problemMatcher": []
},
{
"label": "Immich Server and Web",
"dependsOn": ["Immich Web Server (Vite)", "Immich API Server (Nest)"],
"runOptions": {
"runOn": "folderOpen"
},
"problemMatcher": []
},
{
"label": "Build Immich CLI",
"type": "shell",
"command": "pnpm --filter cli build:dev"
}
]
}

View File

@@ -23,9 +23,21 @@ We generally discourage PRs entirely generated by an LLM. For any part generated
From time to time, we put a feature freeze on parts of the codebase. For us, this means we won't accept most PRs that make changes in that area. Exempted from this are simple bug fixes that require only minor changes. We will close feature PRs that target a feature-frozen area, even if that feature is highly requested and you put a lot of work into it. Please keep that in mind, and if you're ever uncertain if a PR would be accepted, reach out to us first (e.g., in the aforementioned `#contributing` channel). We hate to throw away work. Currently, we have feature freezes on:
* Sharing/Asset ownership
* (External) libraries
- Sharing/Asset ownership
- (External) libraries
## Non-code contributions
If you want to contribute to Immich but you don't feel comfortable programming in our tech stack, there are other ways you can help the team. All our translations are done through [Weblate](https://hosted.weblate.org/projects/immich). These rely entirely on the community; if you speak a language that isn't fully translated yet, submitting translations there is greatly appreciated! If you like helping others, answering Q&A discussions here on GitHub and replying to people on our Discord is also always appreciated.
If you want to contribute to Immich but you don't feel comfortable programming in our tech stack, there are other ways you can help the team.
### Translations
All our translations are done through [Weblate](https://hosted.weblate.org/projects/immich). These rely entirely on the community; if you speak a language that isn't fully translated yet, submitting translations there is greatly appreciated!
### Datasets
Help us improve our [Immich Datasets](https://datasets.immich.app) by submitting photos and videos taken from a variety of devices, including smartphones, DSLRs, and action cameras, as well as photos with unique features, such as panoramas, burst photos, and photo spheres. These datasets will be publically available for anyone to use, do not submit private/sensitive photos.
### Community support
If you like helping others, answering Q&A discussions here on GitHub and replying to people on our Discord is also always appreciated.

View File

@@ -1,6 +1,6 @@
{
"name": "@immich/cli",
"version": "2.2.106",
"version": "2.5.6",
"description": "Command Line Interface (CLI) for Immich",
"type": "module",
"exports": "./dist/index.js",
@@ -20,7 +20,7 @@
"@types/lodash-es": "^4.17.12",
"@types/micromatch": "^4.0.9",
"@types/mock-fs": "^4.13.1",
"@types/node": "^24.10.9",
"@types/node": "^24.10.11",
"@vitest/coverage-v8": "^3.0.0",
"byte-size": "^9.0.0",
"cli-progress": "^3.12.0",

View File

@@ -1,6 +1,6 @@
[tools]
terragrunt = "0.93.10"
opentofu = "1.10.7"
terragrunt = "0.98.0"
opentofu = "1.11.4"
[tasks."tg:fmt"]
run = "terragrunt hclfmt"

View File

@@ -97,7 +97,7 @@ services:
command: ['./run.sh', '-disable-reporting']
ports:
- 3000:3000
image: grafana/grafana:12.3.1-ubuntu@sha256:d57f1365197aec34c4d80869d8ca45bb7787c7663904950dab214dfb40c1c2fd
image: grafana/grafana:12.3.2-ubuntu@sha256:6cca4b429a1dc0d37d401dee54825c12d40056c3c6f3f56e3f0d6318ce77749b
volumes:
- grafana-data:/var/lib/grafana

View File

@@ -0,0 +1,100 @@
#
# WARNING: To install Immich, follow our guide: https://docs.immich.app/install/docker-compose
#
# Make sure to use the docker-compose.yml of the current release:
#
# https://github.com/immich-app/immich/releases/latest/download/docker-compose.yml
#
# The compose file on main may not be compatible with the latest release.
name: immich
services:
immich-server:
container_name: immich_server
image: ghcr.io/immich-app/immich-server:${IMMICH_VERSION:-release}
# extends:
# file: hwaccel.transcoding.yml
# service: cpu # set to one of [nvenc, quicksync, rkmpp, vaapi, vaapi-wsl] for accelerated transcoding
user: '1000:1000'
security_opt:
- no-new-privileges:true
cap_drop:
- NET_RAW
volumes:
# Do not edit the next line. If you want to change the media storage location on your system, edit the value of UPLOAD_LOCATION in the .env file
- ${UPLOAD_LOCATION}:/data
- /etc/localtime:/etc/localtime:ro
env_file:
- .env
ports:
- '2283:2283'
depends_on:
- redis
- database
restart: always
healthcheck:
disable: false
immich-machine-learning:
container_name: immich_machine_learning
# For hardware acceleration, add one of -[armnn, cuda, rocm, openvino, rknn] 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://docs.immich.app/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
user: '1000:1000'
security_opt:
- no-new-privileges:true
cap_drop:
- NET_RAW
volumes:
- ./ml-model-cache:/cache
- ./ml-dotcache:/.cache
- ./ml-config:/.config
env_file:
- .env
restart: always
healthcheck:
disable: false
redis:
container_name: immich_redis
image: docker.io/valkey/valkey:9@sha256:546304417feac0874c3dd576e0952c6bb8f06bb4093ea0c9ca303c73cf458f63
user: '1000:1000'
security_opt:
- no-new-privileges:true
cap_drop:
- NET_RAW
volumes:
- ./redis:/data
healthcheck:
test: redis-cli ping || exit 1
restart: always
database:
container_name: immich_postgres
image: ghcr.io/immich-app/postgres:14-vectorchord0.4.3-pgvectors0.2.0@sha256:bcf63357191b76a916ae5eb93464d65c07511da41e3bf7a8416db519b40b1c23
user: '1000:1000'
security_opt:
- no-new-privileges:true
cap_drop:
- NET_RAW
environment:
POSTGRES_PASSWORD: ${DB_PASSWORD}
POSTGRES_USER: ${DB_USERNAME}
POSTGRES_DB: ${DB_DATABASE_NAME}
POSTGRES_INITDB_ARGS: '--data-checksums'
# Uncomment the DB_STORAGE_TYPE: 'HDD' var if your database isn't stored on SSDs
# DB_STORAGE_TYPE: 'HDD'
volumes:
# Do not edit the next line. If you want to change the database storage location on your system, edit the value of DB_DATA_LOCATION in the .env file
- ${DB_DATA_LOCATION}:/var/lib/postgresql/data
shm_size: 128mb
restart: always
healthcheck:
disable: false
volumes:
model-cache:

View File

@@ -402,6 +402,9 @@ To decrease Redis logs, you can add the following line to the `redis:` section o
### How can I run Immich as a non-root user?
You can change the user in the container by setting the `user` argument in `docker-compose.yml` for each service.
[Example docker-compose.yml file](https://github.com/immich-app/immich/blob/main/docker/docker-compose.rootless.yml)
You may need to add mount points or docker volumes for the following internal container paths:
- `immich-machine-learning:/.config`

View File

@@ -140,7 +140,8 @@ For advanced users or automated recovery scenarios, you can restore a database b
```bash title='Backup'
# Replace <DB_USERNAME> with the database username - usually postgres unless you have changed it.
docker exec -t immich_postgres pg_dumpall --clean --if-exists --username=<DB_USERNAME> | gzip > "/path/to/backup/dump.sql.gz"
# Replace <DB_DATABASE_NAME> with the database name - usually immich unless you have changed it.
docker exec -t immich_postgres pg_dump --clean --if-exists --dbname=<DB_DATABASE_NAME> --username=<DB_USERNAME> | gzip > "/path/to/backup/dump.sql.gz"
```
```bash title='Restore'
@@ -153,9 +154,10 @@ docker start immich_postgres # Start Postgres server
sleep 10 # Wait for Postgres server to start up
# Check the database user if you deviated from the default
# Replace <DB_USERNAME> with the database username - usually postgres unless you have changed it.
# Replace <DB_DATABASE_NAME> with the database name - usually immich unless you have changed it.
gunzip --stdout "/path/to/backup/dump.sql.gz" \
| sed "s/SELECT pg_catalog.set_config('search_path', '', false);/SELECT pg_catalog.set_config('search_path', 'public, pg_catalog', true);/g" \
| docker exec -i immich_postgres psql --dbname=postgres --username=<DB_USERNAME> # Restore Backup
| docker exec -i immich_postgres psql --dbname=<DB_DATABASE_NAME> --username=<DB_USERNAME> --single-transaction --set ON_ERROR_STOP=on # Restore Backup
docker compose up -d # Start remainder of Immich apps
```
@@ -164,7 +166,8 @@ docker compose up -d # Start remainder of Immich apps
```powershell title='Backup'
# Replace <DB_USERNAME> with the database username - usually postgres unless you have changed it.
[System.IO.File]::WriteAllLines("C:\absolute\path\to\backup\dump.sql", (docker exec -t immich_postgres pg_dumpall --clean --if-exists --username=<DB_USERNAME>))
# Replace <DB_DATABASE_NAME> with the database name - usually immich unless you have changed it.
[System.IO.File]::WriteAllLines("C:\absolute\path\to\backup\dump.sql", (docker exec -t immich_postgres pg_dump --clean --if-exists --dbname=<DB_DATABASE_NAME> --username=<DB_USERNAME>))
```
```powershell title='Restore'
@@ -179,8 +182,9 @@ sleep 10 # Wait for Postgres server to
docker exec -it immich_postgres bash # Enter the Docker shell and run the following command
# If your backup ends in `.gz`, replace `cat` with `gunzip --stdout`
# Replace <DB_USERNAME> with the database username - usually postgres unless you have changed it.
# Replace <DB_DATABASE_NAME> with the database name - usually immich unless you have changed it.
cat "/dump.sql" | sed "s/SELECT pg_catalog.set_config('search_path', '', false);/SELECT pg_catalog.set_config('search_path', 'public, pg_catalog', true);/g" | psql --dbname=postgres --username=<DB_USERNAME>
cat "/dump.sql" | sed "s/SELECT pg_catalog.set_config('search_path', '', false);/SELECT pg_catalog.set_config('search_path', 'public, pg_catalog', true);/g" | psql --dbname=<DB_DATABASE_NAME> --username=<DB_USERNAME> --single-transaction --set ON_ERROR_STOP=on
exit # Exit the Docker shell
docker compose up -d # Start remainder of Immich apps
```
@@ -188,6 +192,10 @@ docker compose up -d # Start remainder of Immich ap
</TabItem>
</Tabs>
:::warning
The backup and restore process changed in v2.5.0, if you have a backup created with an older version of Immich, use the documentation version selector to find manual restore instructions for your backup.
:::
:::note
For the database restore to proceed properly, it requires a completely fresh install (i.e., the Immich server has never run since creating the Docker containers). If the Immich app has run, you may encounter Postgres conflicts (relation already exists, violated foreign key constraints, etc.). In this case, delete the `DB_DATA_LOCATION` folder to reset the database.
:::
@@ -196,6 +204,10 @@ For the database restore to proceed properly, it requires a completely fresh ins
Some deployment methods make it difficult to start the database without also starting the server. In these cases, set the environment variable `DB_SKIP_MIGRATIONS=true` before starting the services. This prevents the server from running migrations that interfere with the restore process. Remove this variable and restart services after the database is restored.
:::
:::tip
The provided restore process ensures your database is never in a broken state by committing all changes in one transaction. This may be undesirable behaviour in some circumstances, you can disable it by removing `--single-transaction --set ON_ERROR_STOP=on` from the command.
:::
## Filesystem
Immich stores two types of content in the filesystem: (a) original, unmodified assets (photos and videos), and (b) generated content. We recommend backing up the entire contents of `UPLOAD_LOCATION`, but only the original content is critical, which is stored in the following folders:

View File

@@ -56,11 +56,13 @@ Once you have a new OAuth client application configured, Immich can be configure
| Setting | Type | Default | Description |
| ---------------------------------------------------- | ------- | -------------------- | ----------------------------------------------------------------------------------- |
| Enabled | boolean | false | Enable/disable OAuth |
| Issuer URL | URL | (required) | Required. Self-discovery URL for client (from previous step) |
| Client ID | string | (required) | Required. Client ID (from previous step) |
| Client Secret | string | (required) | Required. Client Secret (previous step) |
| Scope | string | openid email profile | Full list of scopes to send with the request (space delimited) |
| Signing Algorithm | string | RS256 | The algorithm used to sign the id token (examples: RS256, HS256) |
| `issuer_url` | URL | (required) | Required. Self-discovery URL for client (from previous step) |
| `client_id` | string | (required) | Required. Client ID (from previous step) |
| `client_secret` | string | (required) | Required. Client Secret (previous step) |
| `scope` | string | openid email profile | Full list of scopes to send with the request (space delimited) |
| `id_token_signed_response_alg` | string | RS256 | The algorithm used to sign the id token (examples: RS256, HS256) |
| `userinfo_signed_response_alg` | string | none | The algorithm used to sign the userinfo response (examples: RS256, HS256) |
| Request timeout | string | 30,000 (30 seconds) | Number of milliseconds to wait for http requests to complete before giving up |
| Storage Label Claim | string | preferred_username | Claim mapping for the user's storage label**¹** |
| Role Claim | string | immich_role | Claim mapping for the user's role. (should return "user" or "admin")**¹** |
| Storage Quota Claim | string | immich_quota | Claim mapping for the user's storage**¹** |

View File

@@ -88,7 +88,7 @@ The easiest option is to have both extensions installed during the migration:
<details>
<summary>Migration steps (automatic)</summary>
1. Ensure you still have pgvecto.rs installed
2. Install `pgvector` (`>= 0.7.0, < 1.0.0`). The easiest way to do this is on Debian/Ubuntu by adding the [PostgreSQL Apt repository][pg-apt] and then running `apt install postgresql-NN-pgvector`, where `NN` is your Postgres version (e.g., `16`)
2. Install `pgvector` (`>= 0.7, < 0.9`). The easiest way to do this is on Debian/Ubuntu by adding the [PostgreSQL Apt repository][pg-apt] and then running `apt install postgresql-NN-pgvector`, where `NN` is your Postgres version (e.g., `16`)
3. [Install VectorChord][vchord-install]
4. Add `shared_preload_libraries= 'vchord.so, vectors.so'` to your `postgresql.conf`, making sure to include _both_ `vchord.so` and `vectors.so`. You may include other libraries here as well if needed
5. Restart the Postgres database

View File

@@ -98,7 +98,6 @@ entryPoints:
respondingTimeouts:
readTimeout: 600s
idleTimeout: 600s
writeTimeout: 600s
```
The second part is in the `docker-compose.yml` file where immich is in. Add the Traefik specific labels like in the example.

View File

@@ -90,10 +90,13 @@ To see local changes to `@immich/ui` in Immich, do the following:
#### Setup
1. Setup Flutter toolchain using FVM.
2. Run `flutter pub get` to install the dependencies.
3. Run `make translation` to generate the translation file.
4. Run `fvm flutter run` to start the app.
1. [Install mise](https://mise.jdx.dev/installing-mise.html).
2. Change to the immich (root) directory and trust the mise config with `mise trust`.
3. Install tools with mise: `mise install`.
4. Change to the `mobile/` directory.
5. Run `flutter pub get` to install the dependencies.
6. Run `make translation` to generate the translation file.
7. Run `flutter run` to start the app.
#### Translation

View File

@@ -183,7 +183,7 @@ For example to get a list of files that would be uploaded for further
processing:
```bash
immich upload --dry-run . | tail -n +6 | jq .newFiles[]
immich upload --dry-run --json-output . | tail -n +6 | jq .newFiles[]
```
### Obtain the API Key

View File

@@ -86,8 +86,8 @@ You do not need to redo any machine learning jobs after enabling hardware accele
## 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, rknn] to the `image` section's tag at the end of the line.
2. In `immich-machine-learning`, add one of -[armnn, cuda, rocm, openvino, rknn] to the `image` section's tag at the end of the line.
3. Still in the `docker-compose.yml` under `immich-machine-learning`, uncomment the `extends` section and change `cpu` to the appropriate backend.
4. Redeploy the `immich-machine-learning` container with these updated settings.
### Confirming Device Usage

View File

@@ -66,7 +66,7 @@ Now make sure that the local album is selected in the backup screen (steps 1-2 a
- **Keep on device:** You can choose to restrict removal to `Always keep` **All photos** or **All videos**, regardless of other settings. This setting can hamper freeing up space significantly — with 80 GB of videos and 40 GB photos, selecting `Always keep photos` retains thousands of photos on your device.
2. **Scan & Review:** Before any files are removed, you are presented with a review screen to verify which items will be deleted and how much storage is reclamable.
3. **Deletion:** Confirmed items are moved to your device's native Trash/Recycle Bin.
3. **Deletion:** Confirmed items are moved to your device's native Trash/Recycle Bin. For large queues, Immich processes deletion in batches for stability (`2000` assets per batch on Android, `10000` per batch on iOS).
:::info reclaim storage
To use the reclaimed space right away, you must empty the system/gallery trash manually outside of Immich.

View File

@@ -26,6 +26,16 @@ docker image prune
[breaking]: https://github.com/immich-app/immich/discussions?discussions_q=label%3Achangelog%3Abreaking-change+sort%3Adate_created
[releases]: https://github.com/immich-app/immich/releases
## Versioning Policy
Immich follows [semantic versioning][semver], which tags releases in the format `<major>.<minor>.<patch>`. We intend for breaking changes to be limited to major version releases.
You can configure your Docker image to point to the current major version by using a metatag, such as `:v2`.
Currently, we have no plans to backport patches to earlier versions. We encourage all users to run the most recent release of Immich.
Switching back to an earlier version, even within the same minor release tag, is not supported.
[semver]: https://semver.org/
## Migrating to VectorChord
:::info

View File

@@ -1,40 +1,20 @@
[
{
"label": "v2.5.0",
"url": "https://docs.v2.5.0.archive.immich.app"
"label": "v2.5.6",
"url": "https://docs.v2.5.6.archive.immich.app"
},
{
"label": "v2.4.1",
"url": "https://docs.v2.4.1.archive.immich.app"
},
{
"label": "v2.4.0",
"url": "https://docs.v2.4.0.archive.immich.app"
},
{
"label": "v2.3.1",
"url": "https://docs.v2.3.1.archive.immich.app"
},
{
"label": "v2.3.0",
"url": "https://docs.v2.3.0.archive.immich.app"
},
{
"label": "v2.2.3",
"url": "https://docs.v2.2.3.archive.immich.app"
},
{
"label": "v2.2.2",
"url": "https://docs.v2.2.2.archive.immich.app"
},
{
"label": "v2.2.1",
"url": "https://docs.v2.2.1.archive.immich.app"
},
{
"label": "v2.2.0",
"url": "https://docs.v2.2.0.archive.immich.app"
},
{
"label": "v2.1.0",
"url": "https://docs.v2.1.0.archive.immich.app"
@@ -43,18 +23,10 @@
"label": "v2.0.1",
"url": "https://docs.v2.0.1.archive.immich.app"
},
{
"label": "v2.0.0",
"url": "https://docs.v2.0.0.archive.immich.app"
},
{
"label": "v1.144.1",
"url": "https://docs.v1.144.1.archive.immich.app"
},
{
"label": "v1.144.0",
"url": "https://docs.v1.144.0.archive.immich.app"
},
{
"label": "v1.143.1",
"url": "https://docs.v1.143.1.archive.immich.app"

View File

@@ -70,7 +70,7 @@ services:
restart: unless-stopped
redis:
image: redis:6.2-alpine@sha256:37e002448575b32a599109664107e374c8709546905c372a34d64919043b9ceb
image: redis:6.2-alpine@sha256:46884be93652d02a96a176ccf173d1040bef365c5706aa7b6a1931caec8bfeef
database:
image: ghcr.io/immich-app/postgres:14-vectorchord0.3.0@sha256:6f3e9d2c2177af16c2988ff71425d79d89ca630ec2f9c8db03209ab716542338

View File

@@ -42,7 +42,7 @@ services:
- 2285:2285
redis:
image: redis:6.2-alpine@sha256:37e002448575b32a599109664107e374c8709546905c372a34d64919043b9ceb
image: redis:6.2-alpine@sha256:46884be93652d02a96a176ccf173d1040bef365c5706aa7b6a1931caec8bfeef
database:
image: ghcr.io/immich-app/postgres:14-vectorchord0.3.0@sha256:6f3e9d2c2177af16c2988ff71425d79d89ca630ec2f9c8db03209ab716542338

View File

@@ -1,6 +1,6 @@
{
"name": "immich-e2e",
"version": "2.5.0",
"version": "2.5.6",
"description": "",
"main": "index.js",
"type": "module",
@@ -27,7 +27,7 @@
"@playwright/test": "^1.44.1",
"@socket.io/component-emitter": "^3.1.2",
"@types/luxon": "^3.4.2",
"@types/node": "^24.10.9",
"@types/node": "^24.10.11",
"@types/pg": "^8.15.1",
"@types/pngjs": "^6.0.4",
"@types/supertest": "^6.0.2",

View File

@@ -14,7 +14,8 @@ export const playwrightDisableWebserver = process.env.PLAYWRIGHT_DISABLE_WEBSERV
process.env.PW_EXPERIMENTAL_SERVICE_WORKER_NETWORK_EVENTS = '1';
const config: PlaywrightTestConfig = {
testDir: './src/web/specs',
testDir: './src/specs/server',
testMatch: /.*\.e2e-spec\.ts/,
fullyParallel: false,
forbidOnly: !!process.env.CI,
retries: process.env.CI ? 4 : 0,
@@ -28,54 +29,28 @@ const config: PlaywrightTestConfig = {
},
},
testMatch: /.*\.e2e-spec\.ts/,
workers: process.env.CI ? 4 : Math.round(cpus().length * 0.75),
projects: [
{
name: 'chromium',
name: 'web',
use: { ...devices['Desktop Chrome'] },
testMatch: /.*\.e2e-spec\.ts/,
testDir: './src/specs/web',
workers: 1,
},
{
name: 'ui',
use: { ...devices['Desktop Chrome'] },
testMatch: /.*\.ui-spec\.ts/,
testDir: './src/ui/specs',
fullyParallel: true,
workers: process.env.CI ? 3 : Math.max(1, Math.round(cpus().length * 0.75) - 1),
},
// {
// name: 'firefox',
// use: { ...devices['Desktop Firefox'] },
// },
// {
// name: 'webkit',
// use: { ...devices['Desktop Safari'] },
// },
/* Test against mobile viewports. */
// {
// name: 'Mobile Chrome',
// use: { ...devices['Pixel 5'] },
// },
// {
// name: 'Mobile Safari',
// use: { ...devices['iPhone 12'] },
// },
/* Test against branded browsers. */
// {
// name: 'Microsoft Edge',
// use: { ...devices['Desktop Edge'], channel: 'msedge' },
// },
// {
// name: 'Google Chrome',
// use: { ...devices['Desktop Chrome'], channel: 'chrome' },
// },
{
name: 'maintenance',
use: { ...devices['Desktop Chrome'] },
testDir: './src/specs/maintenance',
workers: 1,
},
],
/* Run your local dev server before starting the tests */

View File

@@ -473,6 +473,7 @@ describe('/asset', () => {
id: user1Assets[0].id,
exifInfo: expect.objectContaining({
dateTimeOriginal: '2023-11-20T01:11:00+00:00',
timeZone: 'UTC-7',
}),
});
expect(status).toEqual(200);

View File

@@ -0,0 +1,2 @@
export { generateMemoriesFromTimeline, generateMemory } from './memory/model-objects';
export type { MemoryConfig, MemoryYearConfig } from './memory/model-objects';

View File

@@ -0,0 +1,84 @@
import { faker } from '@faker-js/faker';
import { MemoryType, type MemoryResponseDto, type OnThisDayDto } from '@immich/sdk';
import { DateTime } from 'luxon';
import { toAssetResponseDto } from 'src/ui/generators/timeline/rest-response';
import type { MockTimelineAsset } from 'src/ui/generators/timeline/timeline-config';
import { SeededRandom, selectRandomMultiple } from 'src/ui/generators/timeline/utils';
export type MemoryConfig = {
id?: string;
ownerId: string;
year: number;
memoryAt: string;
isSaved?: boolean;
};
export type MemoryYearConfig = {
year: number;
assetCount: number;
};
export function generateMemory(config: MemoryConfig, assets: MockTimelineAsset[]): MemoryResponseDto {
const now = new Date().toISOString();
const memoryId = config.id ?? faker.string.uuid();
return {
id: memoryId,
assets: assets.map((asset) => toAssetResponseDto(asset)),
data: { year: config.year } as OnThisDayDto,
memoryAt: config.memoryAt,
createdAt: now,
updatedAt: now,
isSaved: config.isSaved ?? false,
ownerId: config.ownerId,
type: MemoryType.OnThisDay,
};
}
export function generateMemoriesFromTimeline(
timelineAssets: MockTimelineAsset[],
ownerId: string,
memoryConfigs: MemoryYearConfig[],
seed: number = 42,
): MemoryResponseDto[] {
const rng = new SeededRandom(seed);
const memories: MemoryResponseDto[] = [];
const usedAssetIds = new Set<string>();
for (const config of memoryConfigs) {
const yearAssets = timelineAssets.filter((asset) => {
const assetYear = DateTime.fromISO(asset.fileCreatedAt).year;
return assetYear === config.year && !usedAssetIds.has(asset.id);
});
if (yearAssets.length === 0) {
continue;
}
const countToSelect = Math.min(config.assetCount, yearAssets.length);
const selectedAssets = selectRandomMultiple(yearAssets, countToSelect, rng);
for (const asset of selectedAssets) {
usedAssetIds.add(asset.id);
}
selectedAssets.sort(
(a, b) => DateTime.fromISO(b.fileCreatedAt).diff(DateTime.fromISO(a.fileCreatedAt)).milliseconds,
);
const memoryAt = DateTime.now().set({ year: config.year }).toISO()!;
memories.push(
generateMemory(
{
ownerId,
year: config.year,
memoryAt,
},
selectedAssets,
),
);
}
return memories;
}

View File

@@ -1,5 +1,5 @@
import { generateConsecutiveDays, generateDayAssets } from 'src/generators/timeline/model-objects';
import { SeededRandom, selectRandomDays } from 'src/generators/timeline/utils';
import { generateConsecutiveDays, generateDayAssets } from 'src/ui/generators/timeline/model-objects';
import { SeededRandom, selectRandomDays } from 'src/ui/generators/timeline/utils';
import type { MockTimelineAsset } from './timeline-config';
import { GENERATION_CONSTANTS } from './timeline-config';

View File

@@ -1,5 +1,5 @@
import sharp from 'sharp';
import { SeededRandom } from 'src/generators/timeline/utils';
import { SeededRandom } from 'src/ui/generators/timeline/utils';
export const randomThumbnail = async (seed: string, ratio: number) => {
const height = 235;

View File

@@ -6,7 +6,7 @@ import { faker } from '@faker-js/faker';
import { AssetVisibility } from '@immich/sdk';
import { DateTime } from 'luxon';
import { writeFileSync } from 'node:fs';
import { SeededRandom } from 'src/generators/timeline/utils';
import { SeededRandom } from 'src/ui/generators/timeline/utils';
import type { DayPattern, MonthDistribution } from './distribution-patterns';
import { ASSET_DISTRIBUTION, DAY_DISTRIBUTION } from './distribution-patterns';
import type { MockTimelineAsset, MockTimelineData, SerializedTimelineData, TimelineConfig } from './timeline-config';

View File

@@ -15,7 +15,7 @@ import {
} from '@immich/sdk';
import { DateTime } from 'luxon';
import { signupDto } from 'src/fixtures';
import { parseTimeBucketKey } from 'src/generators/timeline/utils';
import { parseTimeBucketKey } from 'src/ui/generators/timeline/utils';
import type { MockTimelineAsset, MockTimelineData } from './timeline-config';
/**

View File

@@ -1,5 +1,5 @@
import type { AssetVisibility } from '@immich/sdk';
import { DayPattern, MonthDistribution } from 'src/generators/timeline/distribution-patterns';
import { DayPattern, MonthDistribution } from 'src/ui/generators/timeline/distribution-patterns';
// Constants for generation parameters
export const GENERATION_CONSTANTS = {

View File

@@ -1,5 +1,5 @@
import { DateTime } from 'luxon';
import { GENERATION_CONSTANTS, MockTimelineAsset } from 'src/generators/timeline/timeline-config';
import { GENERATION_CONSTANTS, MockTimelineAsset } from 'src/ui/generators/timeline/timeline-config';
/**
* Linear Congruential Generator for deterministic pseudo-random numbers

View File

@@ -0,0 +1,65 @@
import type { MemoryResponseDto } from '@immich/sdk';
import { BrowserContext } from '@playwright/test';
export type MemoryChanges = {
memoryDeletions: string[];
assetRemovals: Map<string, string[]>;
};
export const setupMemoryMockApiRoutes = async (
context: BrowserContext,
memories: MemoryResponseDto[],
changes: MemoryChanges,
) => {
await context.route('**/api/memories*', async (route, request) => {
const url = new URL(request.url());
const pathname = url.pathname;
if (pathname === '/api/memories' && request.method() === 'GET') {
const activeMemories = memories
.filter((memory) => !changes.memoryDeletions.includes(memory.id))
.map((memory) => {
const removedAssets = changes.assetRemovals.get(memory.id) ?? [];
return {
...memory,
assets: memory.assets.filter((asset) => !removedAssets.includes(asset.id)),
};
})
.filter((memory) => memory.assets.length > 0);
return route.fulfill({
status: 200,
contentType: 'application/json',
json: activeMemories,
});
}
const memoryMatch = pathname.match(/\/api\/memories\/([^/]+)$/);
if (memoryMatch && request.method() === 'GET') {
const memoryId = memoryMatch[1];
const memory = memories.find((m) => m.id === memoryId);
if (!memory || changes.memoryDeletions.includes(memoryId)) {
return route.fulfill({ status: 404 });
}
const removedAssets = changes.assetRemovals.get(memoryId) ?? [];
return route.fulfill({
status: 200,
contentType: 'application/json',
json: {
...memory,
assets: memory.assets.filter((asset) => !removedAssets.includes(asset.id)),
},
});
}
if (/\/api\/memories\/([^/]+)$/.test(pathname) && request.method() === 'DELETE') {
const memoryId = pathname.split('/').pop()!;
changes.memoryDeletions.push(memoryId);
return route.fulfill({ status: 204 });
}
await route.fallback();
});
};

View File

@@ -10,8 +10,8 @@ import {
randomPreview,
randomThumbnail,
TimelineData,
} from 'src/generators/timeline';
import { sleep } from 'src/web/specs/timeline/utils';
} from 'src/ui/generators/timeline';
import { sleep } from 'src/ui/specs/timeline/utils';
export class TimelineTestContext {
slowBucket = false;

View File

@@ -8,11 +8,11 @@ import {
selectRandom,
TimelineAssetConfig,
TimelineData,
} from 'src/generators/timeline';
import { setupBaseMockApiRoutes } from 'src/mock-network/base-network';
import { setupTimelineMockApiRoutes, TimelineTestContext } from 'src/mock-network/timeline-network';
} from 'src/ui/generators/timeline';
import { setupBaseMockApiRoutes } from 'src/ui/mock-network/base-network';
import { setupTimelineMockApiRoutes, TimelineTestContext } from 'src/ui/mock-network/timeline-network';
import { utils } from 'src/utils';
import { assetViewerUtils } from 'src/web/specs/timeline/utils';
import { assetViewerUtils } from '../timeline/utils';
test.describe.configure({ mode: 'parallel' });
test.describe('asset-viewer', () => {

View File

@@ -0,0 +1,289 @@
import { faker } from '@faker-js/faker';
import type { MemoryResponseDto } from '@immich/sdk';
import { test } from '@playwright/test';
import { generateMemoriesFromTimeline } from 'src/ui/generators/memory';
import {
Changes,
createDefaultTimelineConfig,
generateTimelineData,
TimelineAssetConfig,
TimelineData,
} from 'src/ui/generators/timeline';
import { setupBaseMockApiRoutes } from 'src/ui/mock-network/base-network';
import { MemoryChanges, setupMemoryMockApiRoutes } from 'src/ui/mock-network/memory-network';
import { setupTimelineMockApiRoutes, TimelineTestContext } from 'src/ui/mock-network/timeline-network';
import { memoryAssetViewerUtils, memoryGalleryUtils, memoryViewerUtils } from './utils';
test.describe.configure({ mode: 'parallel' });
test.describe('Memory Viewer - Gallery Asset Viewer Navigation', () => {
let adminUserId: string;
let timelineRestData: TimelineData;
let memories: MemoryResponseDto[];
const assets: TimelineAssetConfig[] = [];
const testContext = new TimelineTestContext();
const changes: Changes = {
albumAdditions: [],
assetDeletions: [],
assetArchivals: [],
assetFavorites: [],
};
const memoryChanges: MemoryChanges = {
memoryDeletions: [],
assetRemovals: new Map(),
};
test.beforeAll(async () => {
adminUserId = faker.string.uuid();
testContext.adminId = adminUserId;
timelineRestData = generateTimelineData({
...createDefaultTimelineConfig(),
ownerId: adminUserId,
});
for (const timeBucket of timelineRestData.buckets.values()) {
assets.push(...timeBucket);
}
memories = generateMemoriesFromTimeline(
assets,
adminUserId,
[
{ year: 2024, assetCount: 3 },
{ year: 2023, assetCount: 2 },
{ year: 2022, assetCount: 4 },
],
42,
);
});
test.beforeEach(async ({ context }) => {
await setupBaseMockApiRoutes(context, adminUserId);
await setupTimelineMockApiRoutes(context, timelineRestData, changes, testContext);
await setupMemoryMockApiRoutes(context, memories, memoryChanges);
});
test.afterEach(() => {
testContext.slowBucket = false;
changes.albumAdditions = [];
changes.assetDeletions = [];
changes.assetArchivals = [];
changes.assetFavorites = [];
memoryChanges.memoryDeletions = [];
memoryChanges.assetRemovals.clear();
});
test.describe('Asset viewer navigation from gallery', () => {
test('shows both prev/next buttons for middle asset within a memory', async ({ page }) => {
const firstMemory = memories[0];
const middleAsset = firstMemory.assets[1];
await memoryViewerUtils.openMemoryPageWithAsset(page, middleAsset.id);
await memoryGalleryUtils.clickThumbnail(page, middleAsset.id);
await memoryAssetViewerUtils.waitForViewerOpen(page);
await memoryAssetViewerUtils.waitForAssetLoad(page, middleAsset);
await memoryAssetViewerUtils.expectPreviousButtonVisible(page);
await memoryAssetViewerUtils.expectNextButtonVisible(page);
});
test('shows next button when at last asset of first memory (next memory exists)', async ({ page }) => {
const firstMemory = memories[0];
const lastAssetOfFirstMemory = firstMemory.assets.at(-1)!;
await memoryViewerUtils.openMemoryPageWithAsset(page, lastAssetOfFirstMemory.id);
await memoryGalleryUtils.clickThumbnail(page, lastAssetOfFirstMemory.id);
await memoryAssetViewerUtils.waitForViewerOpen(page);
await memoryAssetViewerUtils.waitForAssetLoad(page, lastAssetOfFirstMemory);
await memoryAssetViewerUtils.expectNextButtonVisible(page);
await memoryAssetViewerUtils.expectPreviousButtonVisible(page);
});
test('shows prev button when at first asset of last memory (prev memory exists)', async ({ page }) => {
const lastMemory = memories.at(-1)!;
const firstAssetOfLastMemory = lastMemory.assets[0];
await memoryViewerUtils.openMemoryPageWithAsset(page, firstAssetOfLastMemory.id);
await memoryGalleryUtils.clickThumbnail(page, firstAssetOfLastMemory.id);
await memoryAssetViewerUtils.waitForViewerOpen(page);
await memoryAssetViewerUtils.waitForAssetLoad(page, firstAssetOfLastMemory);
await memoryAssetViewerUtils.expectPreviousButtonVisible(page);
await memoryAssetViewerUtils.expectNextButtonVisible(page);
});
test('can navigate from last asset of memory to first asset of next memory', async ({ page }) => {
const firstMemory = memories[0];
const secondMemory = memories[1];
const lastAssetOfFirst = firstMemory.assets.at(-1)!;
const firstAssetOfSecond = secondMemory.assets[0];
await memoryViewerUtils.openMemoryPageWithAsset(page, lastAssetOfFirst.id);
await memoryGalleryUtils.clickThumbnail(page, lastAssetOfFirst.id);
await memoryAssetViewerUtils.waitForViewerOpen(page);
await memoryAssetViewerUtils.waitForAssetLoad(page, lastAssetOfFirst);
await memoryAssetViewerUtils.clickNextButton(page);
await memoryAssetViewerUtils.waitForAssetLoad(page, firstAssetOfSecond);
await memoryAssetViewerUtils.expectCurrentAssetId(page, firstAssetOfSecond.id);
});
test('can navigate from first asset of memory to last asset of previous memory', async ({ page }) => {
const firstMemory = memories[0];
const secondMemory = memories[1];
const lastAssetOfFirst = firstMemory.assets.at(-1)!;
const firstAssetOfSecond = secondMemory.assets[0];
await memoryViewerUtils.openMemoryPageWithAsset(page, firstAssetOfSecond.id);
await memoryGalleryUtils.clickThumbnail(page, firstAssetOfSecond.id);
await memoryAssetViewerUtils.waitForViewerOpen(page);
await memoryAssetViewerUtils.waitForAssetLoad(page, firstAssetOfSecond);
await memoryAssetViewerUtils.clickPreviousButton(page);
await memoryAssetViewerUtils.waitForAssetLoad(page, lastAssetOfFirst);
});
test('hides prev button at very first asset (first memory, first asset, no prev memory)', async ({ page }) => {
const firstMemory = memories[0];
const veryFirstAsset = firstMemory.assets[0];
await memoryViewerUtils.openMemoryPageWithAsset(page, veryFirstAsset.id);
await memoryGalleryUtils.clickThumbnail(page, veryFirstAsset.id);
await memoryAssetViewerUtils.waitForViewerOpen(page);
await memoryAssetViewerUtils.waitForAssetLoad(page, veryFirstAsset);
await memoryAssetViewerUtils.expectPreviousButtonNotVisible(page);
await memoryAssetViewerUtils.expectNextButtonVisible(page);
});
test('hides next button at very last asset (last memory, last asset, no next memory)', async ({ page }) => {
const lastMemory = memories.at(-1)!;
const veryLastAsset = lastMemory.assets.at(-1)!;
await memoryViewerUtils.openMemoryPageWithAsset(page, veryLastAsset.id);
await memoryGalleryUtils.clickThumbnail(page, veryLastAsset.id);
await memoryAssetViewerUtils.waitForViewerOpen(page);
await memoryAssetViewerUtils.waitForAssetLoad(page, veryLastAsset);
await memoryAssetViewerUtils.expectNextButtonNotVisible(page);
await memoryAssetViewerUtils.expectPreviousButtonVisible(page);
});
});
test.describe('Keyboard navigation', () => {
test('ArrowLeft navigates to previous asset across memory boundary', async ({ page }) => {
const firstMemory = memories[0];
const secondMemory = memories[1];
const lastAssetOfFirst = firstMemory.assets.at(-1)!;
const firstAssetOfSecond = secondMemory.assets[0];
await memoryViewerUtils.openMemoryPageWithAsset(page, firstAssetOfSecond.id);
await memoryGalleryUtils.clickThumbnail(page, firstAssetOfSecond.id);
await memoryAssetViewerUtils.waitForViewerOpen(page);
await memoryAssetViewerUtils.waitForAssetLoad(page, firstAssetOfSecond);
await page.keyboard.press('ArrowLeft');
await memoryAssetViewerUtils.waitForAssetLoad(page, lastAssetOfFirst);
});
test('ArrowRight navigates to next asset across memory boundary', async ({ page }) => {
const firstMemory = memories[0];
const secondMemory = memories[1];
const lastAssetOfFirst = firstMemory.assets.at(-1)!;
const firstAssetOfSecond = secondMemory.assets[0];
await memoryViewerUtils.openMemoryPageWithAsset(page, lastAssetOfFirst.id);
await memoryGalleryUtils.clickThumbnail(page, lastAssetOfFirst.id);
await memoryAssetViewerUtils.waitForViewerOpen(page);
await memoryAssetViewerUtils.waitForAssetLoad(page, lastAssetOfFirst);
await page.keyboard.press('ArrowRight');
await memoryAssetViewerUtils.waitForAssetLoad(page, firstAssetOfSecond);
});
});
});
test.describe('Memory Viewer - Single Asset Memory Edge Cases', () => {
let adminUserId: string;
let timelineRestData: TimelineData;
let memories: MemoryResponseDto[];
const assets: TimelineAssetConfig[] = [];
const testContext = new TimelineTestContext();
const changes: Changes = {
albumAdditions: [],
assetDeletions: [],
assetArchivals: [],
assetFavorites: [],
};
const memoryChanges: MemoryChanges = {
memoryDeletions: [],
assetRemovals: new Map(),
};
test.beforeAll(async () => {
adminUserId = faker.string.uuid();
testContext.adminId = adminUserId;
timelineRestData = generateTimelineData({
...createDefaultTimelineConfig(),
ownerId: adminUserId,
});
for (const timeBucket of timelineRestData.buckets.values()) {
assets.push(...timeBucket);
}
memories = generateMemoriesFromTimeline(
assets,
adminUserId,
[
{ year: 2024, assetCount: 2 },
{ year: 2023, assetCount: 1 },
{ year: 2022, assetCount: 2 },
],
123,
);
});
test.beforeEach(async ({ context }) => {
await setupBaseMockApiRoutes(context, adminUserId);
await setupTimelineMockApiRoutes(context, timelineRestData, changes, testContext);
await setupMemoryMockApiRoutes(context, memories, memoryChanges);
});
test.afterEach(() => {
testContext.slowBucket = false;
changes.albumAdditions = [];
changes.assetDeletions = [];
changes.assetArchivals = [];
changes.assetFavorites = [];
memoryChanges.memoryDeletions = [];
memoryChanges.assetRemovals.clear();
});
test('single asset memory shows both prev/next when surrounded by other memories', async ({ page }) => {
const singleAssetMemory = memories[1];
const singleAsset = singleAssetMemory.assets[0];
await memoryViewerUtils.openMemoryPageWithAsset(page, singleAsset.id);
await memoryGalleryUtils.clickThumbnail(page, singleAsset.id);
await memoryAssetViewerUtils.waitForViewerOpen(page);
await memoryAssetViewerUtils.waitForAssetLoad(page, singleAsset);
await memoryAssetViewerUtils.expectPreviousButtonVisible(page);
await memoryAssetViewerUtils.expectNextButtonVisible(page);
});
});

View File

@@ -0,0 +1,123 @@
import type { AssetResponseDto } from '@immich/sdk';
import { expect, Page } from '@playwright/test';
function getAssetIdFromUrl(url: URL): string | null {
const pathMatch = url.pathname.match(/\/memory\/photos\/([^/]+)/);
if (pathMatch) {
return pathMatch[1];
}
return url.searchParams.get('id');
}
export const memoryViewerUtils = {
locator(page: Page) {
return page.locator('#memory-viewer');
},
async waitForMemoryLoad(page: Page) {
await expect(this.locator(page)).toBeVisible();
await expect(page.locator('#memory-viewer img').first()).toBeVisible();
},
async openMemoryPage(page: Page) {
await page.goto('/memory');
await this.waitForMemoryLoad(page);
},
async openMemoryPageWithAsset(page: Page, assetId: string) {
await page.goto(`/memory?id=${assetId}`);
await this.waitForMemoryLoad(page);
},
};
export const memoryGalleryUtils = {
locator(page: Page) {
return page.locator('#gallery-memory');
},
thumbnailWithAssetId(page: Page, assetId: string) {
return page.locator(`#gallery-memory [data-thumbnail-focus-container][data-asset="${assetId}"]`);
},
async scrollToGallery(page: Page) {
const showGalleryButton = page.getByLabel('Show gallery');
if (await showGalleryButton.isVisible()) {
await showGalleryButton.click();
}
await expect(this.locator(page)).toBeInViewport();
},
async clickThumbnail(page: Page, assetId: string) {
await this.scrollToGallery(page);
await this.thumbnailWithAssetId(page, assetId).click();
},
async getAllThumbnails(page: Page) {
await this.scrollToGallery(page);
return page.locator('#gallery-memory [data-thumbnail-focus-container]');
},
};
export const memoryAssetViewerUtils = {
locator(page: Page) {
return page.locator('#immich-asset-viewer');
},
async waitForViewerOpen(page: Page) {
await expect(this.locator(page)).toBeVisible();
},
async waitForAssetLoad(page: Page, asset: AssetResponseDto) {
const viewer = this.locator(page);
const imgLocator = viewer.locator(`img[draggable="false"][src*="/api/assets/${asset.id}/thumbnail?size=preview"]`);
const videoLocator = viewer.locator(`video[poster*="/api/assets/${asset.id}/thumbnail?size=preview"]`);
await imgLocator.or(videoLocator).waitFor({ timeout: 10_000 });
},
nextButton(page: Page) {
return page.getByLabel('View next asset');
},
previousButton(page: Page) {
return page.getByLabel('View previous asset');
},
async expectNextButtonVisible(page: Page) {
await expect(this.nextButton(page)).toBeVisible();
},
async expectNextButtonNotVisible(page: Page) {
await expect(this.nextButton(page)).toHaveCount(0);
},
async expectPreviousButtonVisible(page: Page) {
await expect(this.previousButton(page)).toBeVisible();
},
async expectPreviousButtonNotVisible(page: Page) {
await expect(this.previousButton(page)).toHaveCount(0);
},
async clickNextButton(page: Page) {
await this.nextButton(page).click();
},
async clickPreviousButton(page: Page) {
await this.previousButton(page).click();
},
async closeViewer(page: Page) {
await page.keyboard.press('Escape');
await expect(this.locator(page)).not.toBeVisible();
},
getCurrentAssetId(page: Page): string | null {
const url = new URL(page.url());
return getAssetIdFromUrl(url);
},
async expectCurrentAssetId(page: Page, expectedAssetId: string) {
await expect.poll(() => this.getCurrentAssetId(page)).toBe(expectedAssetId);
},
};

View File

@@ -0,0 +1,116 @@
import { faker } from '@faker-js/faker';
import { expect, test } from '@playwright/test';
import {
Changes,
createDefaultTimelineConfig,
generateTimelineData,
TimelineAssetConfig,
TimelineData,
} from 'src/ui/generators/timeline';
import { setupBaseMockApiRoutes } from 'src/ui/mock-network/base-network';
import { setupTimelineMockApiRoutes, TimelineTestContext } from 'src/ui/mock-network/timeline-network';
import { assetViewerUtils } from '../timeline/utils';
const buildSearchUrl = (assetId: string) => {
const searchQuery = encodeURIComponent(JSON.stringify({ originalFileName: 'test' }));
return `/search/photos/${assetId}?query=${searchQuery}`;
};
test.describe.configure({ mode: 'parallel' });
test.describe('search gallery-viewer', () => {
let adminUserId: string;
let timelineRestData: TimelineData;
const assets: TimelineAssetConfig[] = [];
const testContext = new TimelineTestContext();
const changes: Changes = {
albumAdditions: [],
assetDeletions: [],
assetArchivals: [],
assetFavorites: [],
};
test.beforeAll(async () => {
adminUserId = faker.string.uuid();
testContext.adminId = adminUserId;
timelineRestData = generateTimelineData({ ...createDefaultTimelineConfig(), ownerId: adminUserId });
for (const timeBucket of timelineRestData.buckets.values()) {
assets.push(...timeBucket);
}
});
test.beforeEach(async ({ context }) => {
await setupBaseMockApiRoutes(context, adminUserId);
await setupTimelineMockApiRoutes(context, timelineRestData, changes, testContext);
await context.route('**/api/search/metadata', async (route, request) => {
if (request.method() === 'POST') {
const searchAssets = assets.slice(0, 5).filter((asset) => !changes.assetDeletions.includes(asset.id));
return route.fulfill({
status: 200,
contentType: 'application/json',
json: {
albums: { total: 0, count: 0, items: [], facets: [] },
assets: {
total: searchAssets.length,
count: searchAssets.length,
items: searchAssets,
facets: [],
nextPage: null,
},
},
});
}
await route.fallback();
});
});
test.afterEach(() => {
testContext.slowBucket = false;
changes.albumAdditions = [];
changes.assetDeletions = [];
changes.assetArchivals = [];
changes.assetFavorites = [];
});
test.describe('/search/photos/:id', () => {
test('Deleting a photo advances to the next photo', async ({ page }) => {
const asset = assets[0];
await page.goto(buildSearchUrl(asset.id));
await assetViewerUtils.waitForViewerLoad(page, asset);
await page.getByLabel('Delete').click();
await assetViewerUtils.waitForViewerLoad(page, assets[1]);
});
test('Deleting two photos in a row advances to the next photo each time', async ({ page }) => {
const asset = assets[0];
await page.goto(buildSearchUrl(asset.id));
await assetViewerUtils.waitForViewerLoad(page, asset);
await page.getByLabel('Delete').click();
await assetViewerUtils.waitForViewerLoad(page, assets[1]);
await page.getByLabel('Delete').click();
await assetViewerUtils.waitForViewerLoad(page, assets[2]);
});
test('Navigating backward then deleting advances to the next photo', async ({ page }) => {
const asset = assets[1];
await page.goto(buildSearchUrl(asset.id));
await assetViewerUtils.waitForViewerLoad(page, asset);
await page.getByLabel('View previous asset').click();
await assetViewerUtils.waitForViewerLoad(page, assets[0]);
await page.getByLabel('View next asset').click();
await assetViewerUtils.waitForViewerLoad(page, asset);
await page.getByLabel('Delete').click();
await assetViewerUtils.waitForViewerLoad(page, assets[2]);
});
test('Deleting the last photo advances to the previous photo', async ({ page }) => {
const lastAsset = assets[4];
await page.goto(buildSearchUrl(lastAsset.id));
await assetViewerUtils.waitForViewerLoad(page, lastAsset);
await expect(page.getByLabel('View next asset')).toHaveCount(0);
await page.getByLabel('Delete').click();
await assetViewerUtils.waitForViewerLoad(page, assets[3]);
await expect(page.getByLabel('View previous asset')).toBeVisible();
});
});
});

View File

@@ -12,18 +12,15 @@ import {
selectRandomMultiple,
TimelineAssetConfig,
TimelineData,
} from 'src/generators/timeline';
import { setupBaseMockApiRoutes } from 'src/mock-network/base-network';
import { pageRoutePromise, setupTimelineMockApiRoutes, TimelineTestContext } from 'src/mock-network/timeline-network';
import { utils } from 'src/utils';
} from 'src/ui/generators/timeline';
import { setupBaseMockApiRoutes } from 'src/ui/mock-network/base-network';
import {
assetViewerUtils,
padYearMonth,
pageUtils,
poll,
thumbnailUtils,
timelineUtils,
} from 'src/web/specs/timeline/utils';
pageRoutePromise,
setupTimelineMockApiRoutes,
TimelineTestContext,
} from 'src/ui/mock-network/timeline-network';
import { utils } from 'src/utils';
import { assetViewerUtils, padYearMonth, pageUtils, poll, thumbnailUtils, timelineUtils } from './utils';
test.describe.configure({ mode: 'parallel' });
test.describe('Timeline', () => {

View File

@@ -1,6 +1,6 @@
import { BrowserContext, expect, Page } from '@playwright/test';
import { DateTime } from 'luxon';
import { TimelineAssetConfig } from 'src/generators/timeline';
import { TimelineAssetConfig } from 'src/ui/generators/timeline';
export const sleep = (ms: number) => {
return new Promise((resolve) => setTimeout(resolve, ms));

View File

@@ -15,7 +15,6 @@
"incremental": true,
"skipLibCheck": true,
"esModuleInterop": true,
"rootDirs": ["src"],
"baseUrl": "./"
},
"include": ["src/**/*.ts"],

View File

@@ -3,14 +3,14 @@ import { defineConfig } from 'vitest/config';
// skip `docker compose up` if `make e2e` was already run
const globalSetup: string[] = [];
try {
await fetch('http://127.0.0.1:2285/api/server-info/ping');
await fetch('http://127.0.0.1:2285/api/server/ping');
} catch {
globalSetup.push('src/setup/docker-compose.ts');
globalSetup.push('src/docker-compose.ts');
}
export default defineConfig({
test: {
include: ['src/{api,cli,immich-admin}/specs/*.e2e-spec.ts'],
include: ['src/specs/server/**/*.e2e-spec.ts'],
globalSetup,
testTimeout: 15_000,
pool: 'threads',

View File

@@ -5,7 +5,7 @@
"acknowledge": "أُدرك ذلك",
"action": "عملية",
"action_common_update": "تحديث",
"action_description": "مجموعة من الفعاليات التي يجب تنفيذها على الأصول التي تم تصفيتها",
"action_description": "مجموعة من الفعاليات التي ستنفذ على الأصول التي تم تصفيتها",
"actions": "عمليات",
"active": "نشط",
"active_count": "فعال: {count}",
@@ -272,7 +272,7 @@
"oauth_auto_register": "التسجيل التلقائي",
"oauth_auto_register_description": "التسجيل التلقائي للمستخدمين الجدد بعد تسجيل الدخول باستخدام OAuth",
"oauth_button_text": "نص الزر",
"oauth_client_secret_description": "مطلوب اذاPKCE(مفتاح الاثبات لتبادل الكود) لم يتم توفيره من مزود OAuth",
"oauth_client_secret_description": "مطلوب للعميل السري، او اذا PKCE(مفتاح الاثبات لتبادل الكود) ليس مدعوم من العميل العام.",
"oauth_enable_description": "تسجيل الدخول باستخدام OAuth",
"oauth_mobile_redirect_uri": "عنوان URI لإعادة التوجيه على الهاتف",
"oauth_mobile_redirect_uri_override": "تجاوز عنوان URI لإعادة التوجيه على الهاتف",
@@ -572,6 +572,9 @@
"asset_list_layout_sub_title": "تصميم",
"asset_list_settings_subtitle": "إعدادات تخطيط شبكة الصور",
"asset_list_settings_title": "شبكة الصور",
"asset_not_found_on_device_android": "الاصل لم يتم ايجاده في الجهاز",
"asset_not_found_on_device_ios": "الأصل لم يتم ايجاده في الجهاز. اذا تستخدم خدمة iCloud, فالأصل قد لا يتم الوصول له بسبب ملف متضارب مخزون في iCloud",
"asset_not_found_on_icloud": "الأصل لم يتم ايجاده في الجهاز, الأصل قد لا يتم الوصول له بسبب ملف متضارب مخزون في iCloud",
"asset_offline": "المحتوى غير اتصال",
"asset_offline_description": "لم يعد هذا الأصل الخارجي موجودًا على القرص. يرجى الاتصال بمسؤول Immich للحصول على المساعدة.",
"asset_restored_successfully": "تم استعادة الاصل بنجاح",
@@ -650,7 +653,7 @@
"backup_controller_page_background_turn_off": "قم بإيقاف تشغيل خدمة الخلفية",
"backup_controller_page_background_turn_on": "قم بتشغيل خدمة الخلفية",
"backup_controller_page_background_wifi": "فقط على Wi-Fi",
"backup_controller_page_backup": "دعم",
"backup_controller_page_backup": "نسخ احتياطي",
"backup_controller_page_backup_selected": "المحدد: ",
"backup_controller_page_backup_sub": "النسخ الاحتياطي للصور ومقاطع الفيديو",
"backup_controller_page_created": "انشئ في :{date}",
@@ -779,6 +782,8 @@
"client_cert_import": "استيراد",
"client_cert_import_success_msg": "تم استيراد شهادة العميل",
"client_cert_invalid_msg": "ملف شهادة عميل غير صالحة او كلمة سر غير صحيحة",
"client_cert_password_message": "أدخل كلمة المرور الخاصة بهذه الشهادة",
"client_cert_password_title": "كلمة المرور الخاصة بالشهادة",
"client_cert_remove_msg": "تم ازالة شهادة العميل",
"client_cert_subtitle": "يدعم صيغ PKCS12 (.p12, .pfx)فقط. استيراد/ازالة الشهادات متاح فقط قبل تسجيل الدخول",
"client_cert_title": "شهادة مستخدم SSL [تجريبية]",
@@ -992,6 +997,11 @@
"editor_close_without_save_prompt": "لن يتم حفظ التغييرات",
"editor_close_without_save_title": "إغلاق المحرر؟",
"editor_confirm_reset_all_changes": "هل أنت متأكد من إعادة ضبط جميع التغييرات؟",
"editor_discard_edits_confirm": "تجاهل التعديلات",
"editor_discard_edits_prompt": "لديك تعديلات غير محفوظة. هل أنت متأكد من رغبتك في تجاهلها؟",
"editor_discard_edits_title": "تجاهل التعديلات؟",
"editor_edits_applied_error": "فشل تطبيق التعديلات",
"editor_edits_applied_success": "تم تطبيق التعديلات بنجاح",
"editor_flip_horizontal": "اقلب أفقيًا",
"editor_flip_vertical": "اقلب عموديًا",
"editor_orientation": "اتجاه",
@@ -1192,8 +1202,9 @@
"features": "الميزات",
"features_in_development": "الميزات قيد التطوير",
"features_setting_description": "إدارة ميزات التطبيق",
"file_name": "اسم الملف: {file_name}",
"file_name_or_extension": "اسم الملف أو امتداده",
"file_name_text": "أسم الملف",
"file_name_with_value": "اسم الملف: {file_name}",
"file_size": "حجم الملف",
"filename": "اسم الملف",
"filetype": "نوع الملف",
@@ -2295,6 +2306,7 @@
"upload_details": "تفاصيل الرفع",
"upload_dialog_info": "هل تريد النسخ الاحتياطي للأصول (الأصول) المحددة إلى الخادم؟",
"upload_dialog_title": "تحميل الأصول",
"upload_error_with_count": "خطأ في رفع {count, plural, one {# اصل} other {# اصول}}",
"upload_errors": "إكتمل الرفع مع {count, plural, one {# خطأ} other {# أخطاء}}, قم بتحديث الصفحة لرؤية المحتويات الجديدة التي تم رفعها.",
"upload_finished": "تم الانتهاء من الرفع",
"upload_progress": "متبقية {remaining, number} - معالجة {processed, number}/{total, number}",

View File

@@ -380,7 +380,6 @@
"favorite": "У абраным",
"favorite_or_unfavorite_photo": "Дадаць або выдаліць фота з абранага",
"favorites": "Абраныя",
"file_name": "Назва файла: {file_name}",
"filename": "Назва файла",
"filetype": "Тып файла",
"filter": "Фільтр",

View File

@@ -272,7 +272,7 @@
"oauth_auto_register": "Автоматична регистрация",
"oauth_auto_register_description": "Автоматично регистриране на нови потребители след влизане с OAuth",
"oauth_button_text": "Текст на бутона",
"oauth_client_secret_description": "Изисква се, когато доставчика на OAuth не поддържа PKCE (Proof Key for Code Exchange)",
"oauth_client_secret_description": "Задължително за поверителен клиент или когато не се поддържа PKCE (Proof Key for Code Exchange) за публичен клиент.",
"oauth_enable_description": "Влизане с OAuth",
"oauth_mobile_redirect_uri": "URI за мобилно пренасочване",
"oauth_mobile_redirect_uri_override": "URI пренасочване за мобилни устройства",
@@ -383,7 +383,7 @@
"transcoding_hardware_acceleration": "Хардуерно ускорение",
"transcoding_hardware_acceleration_description": "Експериментално: много по-бързо транскодиране, но може да понижи качеството при същия битрейт",
"transcoding_hardware_decoding": "Хардуерно декодиране",
"transcoding_hardware_decoding_setting_description": "Прилага се само за NVENC, QSV и RKMPP. Активира ускорение от край до край, вместо само да ускорява кодирането. Може да не работи с всички видеоклипове.",
"transcoding_hardware_decoding_setting_description": "Активира ускорение от край до край, вместо само да ускорява кодирането. Може да не работи с всички видеоклипове.",
"transcoding_max_b_frames": "Максимални B-фрейма",
"transcoding_max_b_frames_description": "По-високите стойности подобряват ефективността на компресията, но забавят разкодирането. Може да не е съвместим с хардуерното ускорение на по-стари устройства. 0 деактивира B-фрейма, докато -1 задава тази стойност автоматично.",
"transcoding_max_bitrate": "Максимален битрейт",
@@ -572,6 +572,9 @@
"asset_list_layout_sub_title": "Разположение",
"asset_list_settings_subtitle": "Настройки на мрежата на разполагане на снимки",
"asset_list_settings_title": "Разполагане на снимки",
"asset_not_found_on_device_android": "Обектът не е намерен на устройството",
"asset_not_found_on_device_ios": "Обектът не е намерен на устройството. Ако използвате iCloud, обектът може да е недостъпен поради повреден файл, съхранен в iCloud",
"asset_not_found_on_icloud": "Обектът не е намерен в iCloud. Обектът може да е недостъпен поради повреден файл, съхранен в iCloud",
"asset_offline": "Елементът е офлайн",
"asset_offline_description": "Този външен актив вече не се намира на диска. Моля, свържете се с администратора на Immich за помощ.",
"asset_restored_successfully": "Успешно възстановен обект",
@@ -779,6 +782,8 @@
"client_cert_import": "Импорт",
"client_cert_import_success_msg": "Клиентския сертификат е импортиран",
"client_cert_invalid_msg": "Невалиден сертификат или грешна парола",
"client_cert_password_message": "Въведете парола за този сертификат",
"client_cert_password_title": "Парола за сертификат",
"client_cert_remove_msg": "Клиентския сертификат е премахнат",
"client_cert_subtitle": "Поддържа се само формат PKCS12 (.p12, .pfx). Импорт/премахване на сертификат може само преди вписване в системата",
"client_cert_title": "Клиентски SSL сертификат [ЕКСПЕРИМЕНТАЛНО]",
@@ -992,6 +997,11 @@
"editor_close_without_save_prompt": "Промените няма да бъдат запазени",
"editor_close_without_save_title": "Затваряне на редактора?",
"editor_confirm_reset_all_changes": "Сигурни ли сте, че искате да възстановите всички промени?",
"editor_discard_edits_confirm": "Отхвърли промените",
"editor_discard_edits_prompt": "Имате незапазени промени. Наистина ли искате да ги отхвърлите?",
"editor_discard_edits_title": "Отхвърляме ли промените?",
"editor_edits_applied_error": "Неуспешно прилагане на промените",
"editor_edits_applied_success": "Успешно прилагане на промените",
"editor_flip_horizontal": "Обърни хоризонтално",
"editor_flip_vertical": "Обърни вертикално",
"editor_orientation": "Ориентация",
@@ -1149,7 +1159,7 @@
},
"errors_text": "Грешки",
"exclusion_pattern": "Шаблон за изключение",
"exif": "Exif",
"exif": "Еxif",
"exif_bottom_sheet_description": "Добави Описание...",
"exif_bottom_sheet_description_error": "Неуспешно обновяване на описание",
"exif_bottom_sheet_details": "ПОДРОБНОСТИ",
@@ -1192,8 +1202,9 @@
"features": "Функции",
"features_in_development": "Функции в процес на разработка",
"features_setting_description": "Управление на функциите на приложението",
"file_name": "Име на файла: {file_name}",
"file_name_or_extension": "Име на файл или разширение",
"file_name_text": "Имe на файл",
"file_name_with_value": "Име на файл: {file_name}",
"file_size": "Размер на файла",
"filename": "Име на файл",
"filetype": "Тип на файл",
@@ -1215,7 +1226,7 @@
"free_up_space_description": "Преместете архивираните снимки и видеа в кошчето на устройството, за да освободите място. Копията на сървъра ще бъдат запазени.",
"free_up_space_settings_subtitle": "Освобождаване на място за съхранение на устройството",
"full_path": "Пълен път: {path}",
"gcast_enabled": "Google Cast",
"gcast_enabled": "Gооgle Cast",
"gcast_enabled_description": "За да работи тази функция зарежда външни ресурси от Google.",
"general": "Общи",
"geolocation_instruction_location": "Изберете обект с GPS координати за да използвате тях или изберете място директно от картата",
@@ -1404,7 +1415,7 @@
"login_form_api_exception": "Грешка в комуникацията. Моля, провери URL на сървъра и опитай пак.",
"login_form_back_button_text": "Обратно",
"login_form_email_hint": "youremail@email.com",
"login_form_endpoint_hint": "http://your-server-ip:port",
"login_form_endpoint_hint": "http://yоur-server-ip:port",
"login_form_endpoint_url": "URL адрес на сървъра",
"login_form_err_http": "Моля, определи протокола http:// или https://",
"login_form_err_invalid_email": "Невалиден имейл адрес",
@@ -2070,7 +2081,7 @@
"shared_link_edit_expire_after_option_year": "{count} години",
"shared_link_edit_password_hint": "Въведи парола за достъп до споделен ресурс",
"shared_link_edit_submit_button": "Обнови връзката",
"shared_link_error_server_url_fetch": "Не може да се извлече URL адресът на сървъра",
"shared_link_error_server_url_fetch": "Не може да се извлече url-адресът на сървъра",
"shared_link_expires_day": "Изтича след {count} ден",
"shared_link_expires_days": "Изтича след {count} дни",
"shared_link_expires_hour": "Изтича след {count} час",
@@ -2295,6 +2306,7 @@
"upload_details": "Детайли за качването",
"upload_dialog_info": "Искате ли да архивирате на сървъра избраните обекти?",
"upload_dialog_title": "Качи обект",
"upload_error_with_count": "Грешка при зареждане на {count, plural, one {# обект} other {# обекта}}",
"upload_errors": "Качването е завъшено с {count, plural, one {# грешка} other {# грешки}}, обновете страницата за да видите новите елементи.",
"upload_finished": "Качването завърши",
"upload_progress": "Остават {remaining, number} - Обработени {processed, number}/{total, number}",

View File

@@ -40,7 +40,9 @@
"add_to_albums_count": "অ্যালবামে যোগ করুন ({count})",
"add_to_bottom_bar": "এ যোগ করুন",
"add_to_shared_album": "শেয়ার করা অ্যালবামে যোগ করুন",
"add_upload_to_stack": "আপলোড স্ট্যাকে যোগ করুন",
"add_url": "লিঙ্ক যোগ করুন",
"add_workflow_step": "কাজের ধাপ যোগ করুন",
"added_to_archive": "আর্কাইভ এ যোগ করা হয়েছে",
"added_to_favorites": "ফেভারিটে যোগ করা হয়েছে",
"added_to_favorites_count": "পছন্দের তালিকায় {count, number} যোগ করা হয়েছে",
@@ -73,6 +75,7 @@
"confirm_reprocess_all_faces": "আপনি কি নিশ্চিত যে আপনি সমস্ত মুখ পুনরায় প্রক্রিয়া করতে চান? এটি নামযুক্ত ব্যক্তিদেরও মুছে ফেলবে।",
"confirm_user_password_reset": "আপনি কি নিশ্চিত যে আপনি {user} এর পাসওয়ার্ড রিসেট করতে চান?",
"confirm_user_pin_code_reset": "আপনি কি নিশ্চিত যে আপনি {user} এর পিন কোড রিসেট করতে চান?",
"copy_config_to_clipboard_description": "বর্তমান সিস্টেম কনফিগারেশন একটি JSON অবজেক্ট হিসেবে ক্লিপবোর্ডে কপি করুন",
"create_job": "job তৈরি করুন",
"cron_expression": "ক্রোন এক্সপ্রেশন",
"cron_expression_description": "ক্রোন ফর্ম্যাট ব্যবহার করে স্ক্যানিং ব্যবধান সেট করুন। আরও তথ্যের জন্য দয়া করে দেখুন যেমন <link>Crontab Guru</link>",
@@ -80,6 +83,8 @@
"disable_login": "লগইন অক্ষম করুন",
"duplicate_detection_job_description": "অনুরূপ ছবি সনাক্ত করতে সম্পদগুলিতে মেশিন লার্নিং চালান। স্মার্ট অনুসন্ধানের উপর নির্ভর করে",
"exclusion_pattern_description": "এক্সক্লুশন প্যাটার্ন ব্যবহার করে আপনি আপনার লাইব্রেরি স্ক্যান করার সময় ফাইল এবং ফোল্ডারগুলিকে উপেক্ষা করতে পারবেন। যদি আপনার এমন ফোল্ডার থাকে যেখানে এমন ফাইল থাকে যা আপনি আমদানি করতে চান না, যেমন RAW ফাইল।",
"export_config_as_json_description": "বর্তমান সিস্টেম কনফিগারেশন একটি JSON ফাইল হিসেবে ডাউনলোড করুন",
"external_libraries_page_description": "অ্যাডমিন external লাইব্রেরি পেজ",
"face_detection": "মুখ সনাক্তকরণ",
"face_detection_description": "মেশিন লার্নিং ব্যবহার করে অ্যাসেটে থাকা মুখ/চেহারা গুলি সনাক্ত করুন। ভিডিও গুলির জন্য, শুধুমাত্র থাম্বনেইল বিবেচনা করা হয়। \"রিফ্রেশ\" (পুনরায়) সমস্ত অ্যাসেট প্রক্রিয়া করে। \"রিসেট\" করার মাধ্যমে অতিরিক্তভাবে সমস্ত বর্তমান মুখের ডেটা সাফ করে। \"অনুপস্থিত\" অ্যাসেটগুলিকে সারিবদ্ধ করে যা এখনও প্রক্রিয়া করা হয়নি। সনাক্ত করা মুখগুলিকে ফেসিয়াল রিকগনিশনের জন্য সারিবদ্ধ করা হবে, ফেসিয়াল ডিটেকশন সম্পূর্ণ হওয়ার পরে, বিদ্যমান বা নতুন ব্যক্তিদের মধ্যে গোষ্ঠীবদ্ধ করে।",
"facial_recognition_job_description": "শনাক্ত করা মুখগুলিকে মানুষের মধ্যে গোষ্ঠীভুক্ত/গ্রুপ করুন। মুখ সনাক্তকরণ সম্পূর্ণ হওয়ার পরে এই ধাপটি চলে। \"রিসেট\" (পুনরায়) সমস্ত মুখকে ক্লাস্টার করে। \"অনুপস্থিত/মিসিং\" মুখগুলিকে সারিতে রাখে যেগুলো কোনও ব্যক্তিকে এসাইন/বরাদ্দ করা হয়নি।",
@@ -99,6 +104,8 @@
"image_preview_description": "স্ট্রিপড মেটাডেটা সহ মাঝারি আকারের ছবি, একটি একক সম্পদ দেখার সময় এবং মেশিন লার্নিংয়ের জন্য ব্যবহৃত হয়",
"image_preview_quality_description": "১-১০০ এর মধ্যে প্রিভিউ কোয়ালিটি। বেশি হলে ভালো, কিন্তু বড় ফাইল তৈরি হয় এবং অ্যাপের প্রতিক্রিয়াশীলতা কমাতে পারে। কম মান সেট করলে মেশিন লার্নিং কোয়ালিটির উপর প্রভাব পড়তে পারে।",
"image_preview_title": "প্রিভিউ সেটিংস",
"image_progressive": "প্রগ্রেসিভ",
"image_progressive_description": "ধীরে ধীরে লোড হওয়ার সুবিধার্থে JPEG ছবিগুলো প্রগ্রেসিভভাবে এনকোড করুন। WebP ছবির ক্ষেত্রে এটি কোনো প্রভাব ফেলবে না",
"image_quality": "গুণমান",
"image_resolution": "রেজোলিউশন",
"image_resolution_description": "উচ্চ রেজোলিউশনের ক্ষেত্রে আরও বিস্তারিত তথ্য সংরক্ষণ করা সম্ভব কিন্তু এনকোড করতে বেশি সময় লাগে, ফাইলের আকার বড় হয় এবং অ্যাপের প্রতিক্রিয়াশীলতা কমাতে পারে।",
@@ -107,6 +114,7 @@
"image_thumbnail_description": "মেটাডেটা বাদ দেওয়া ছোট থাম্বনেইল, মূল টাইমলাইনের মতো ছবির গ্রুপ দেখার সময় ব্যবহৃত হয়",
"image_thumbnail_quality_description": "থাম্বনেইলের মান ১-১০০। বেশি হলে ভালো, কিন্তু বড় ফাইল তৈরি হয় এবং অ্যাপের প্রতিক্রিয়াশীলতা কমাতে পারে।",
"image_thumbnail_title": "থাম্বনেল সেটিংস",
"import_config_from_json_description": "একটি JSON কনফিগ ফাইল আপলোড করে সিস্টেম কনফিগারেশন ইমপোর্ট করুন।",
"job_concurrency": "{job} কনকারেন্সি",
"job_created": "Job তৈরি হয়েছে",
"job_not_concurrency_safe": "এই কাজটি সমান্তরালভাবে চালানো নিরাপদ নয়",
@@ -114,14 +122,20 @@
"job_settings_description": "কাজের সমান্তরালতা পরিচালনা করুন",
"jobs_delayed": "{jobCount, plural, other {# বিলম্বিত}}",
"jobs_failed": "{jobCount, plural, other {# ব্যর্থ}}",
"jobs_over_time": "সময় অনুযায়ী কাজসমূহ",
"library_created": "লাইব্রেরি তৈরি করা হয়েছেঃ {library}",
"library_deleted": "লাইব্রেরি মুছে ফেলা হয়েছে",
"library_details": "লাইব্রেরির বিবরণ",
"library_folder_description": "ইমপোর্ট করার জন্য একটি ফোল্ডার নির্দিষ্ট করুন। এই ফোল্ডার এবং এর ভেতরের সমস্ত ফোল্ডার ছবি ও ভিডিওর জন্য স্ক্যান করা হবে।",
"library_remove_exclusion_pattern_prompt": "আপনি কি নিশ্চিত যে আপনি এই এক্সক্লুশন প্যাটার্নটি মুছে ফেলতে চান?",
"library_remove_folder_prompt": "আপনি কি নিশ্চিত যে আপনি এই ইমপোর্ট ফোল্ডারটি মুছে ফেলতে চান?",
"library_scanning": "পর্যায়ক্রমিক স্ক্যানিং",
"library_scanning_description": "পর্যায়ক্রমিক লাইব্রেরি স্ক্যানিং কনফিগার করুন",
"library_scanning_enable_description": "পর্যায়ক্রমিক লাইব্রেরি স্ক্যানিং সক্ষম করুন",
"library_settings": "বহিরাগত লাইব্রেরি",
"library_settings_description": "বহিরাগত লাইব্রেরি সেটিংস পরিচালনা করুন",
"library_tasks_description": "নতুন এবং/অথবা পরিবর্তিত সম্পদের জন্য বহিরাগত লাইব্রেরি স্ক্যান করুন",
"library_updated": "আপডেটকৃত লাইব্রেরি।",
"library_watching_enable_description": "ফাইল পরিবর্তনের জন্য বহিরাগত লাইব্রেরিগুলি দেখুন",
"library_watching_settings": "লাইব্রেরি দেখা (পরীক্ষামূলক)",
"library_watching_settings_description": "পরিবর্তিত ফাইলগুলির জন্য স্বয়ংক্রিয়ভাবে নজর রাখুন",
@@ -133,9 +147,199 @@
"machine_learning_availability_checks_enabled": "প্রাপ্যতা পরীক্ষা সক্ষম করুন",
"machine_learning_availability_checks_interval": "চেক ব্যবধান",
"machine_learning_availability_checks_interval_description": "প্রাপ্যতা পরীক্ষাগুলির মধ্যে ব্যবধান মিলিসেকেন্ডে",
"machine_learning_availability_checks_timeout": "অনুরোধের সময়সীমা শেষ",
"machine_learning_availability_checks_timeout_description": "প্রাপ্যতার পরীক্ষার জন্য মিলিসেকেন্ডে সময়সীমা।",
"machine_learning_clip_model": "CLIP মডেল",
"machine_learning_clip_model_description": "<link>এখানে</link> তালিকাভুক্ত একটি CLIP মডেলের নাম। মনে রাখবেন, মডেল পরিবর্তনের পর সব ছবির জন্য অবশ্যই Smart Search কাজটি আবার চালাতে হবে।",
"machine_learning_duplicate_detection": "পুনরাবৃত্তি সনাক্তকরণ",
"machine_learning_duplicate_detection_enabled": "পুনরাবৃত্তি শনাক্তকরণ চালু করুন"
}
"machine_learning_duplicate_detection_enabled": "পুনরাবৃত্তি শনাক্তকরণ চালু করুন",
"machine_learning_duplicate_detection_enabled_description": "নিষ্ক্রিয় থাকলেও হুবহু একই সম্পদগুলোর ডুপ্লিকেট সরিয়ে ফেলা হবে।",
"machine_learning_duplicate_detection_setting_description": "সম্ভাব্য ডুপ্লিকেট খুঁজে বের করতে CLIP এম্বেডিং ব্যবহার করুন।",
"machine_learning_enabled": "Machine Learning সক্ষম করুন",
"machine_learning_enabled_description": "নিষ্ক্রিয় থাকলে নিচের সেটিংস নির্বিশেষে সমস্ত ML বৈশিষ্ট্য নিষ্ক্রিয় করা হবে।",
"machine_learning_facial_recognition": "ফেসিয়াল রিকগনিশন",
"machine_learning_facial_recognition_description": "ছবিতে মুখ সনাক্ত করুন, চিনুন এবং গ্রুপ করুন।",
"machine_learning_facial_recognition_model": "ফেসিয়াল রিকগনিশন মডেল",
"machine_learning_facial_recognition_model_description": "মডেলগুলি আকারের অধঃক্রম অনুযায়ী তালিকাভুক্ত করা হয়েছে। বড় মডেলগুলি ধীরগতির এবং বেশি মেমরি ব্যবহার করে, তবে উন্নত ফলাফল প্রদান করে। মনে রাখবেন যে একটি মডেল পরিবর্তন করার পর আপনাকে সমস্ত ছবির জন্য ফেস ডিটেকশন (Face Detection) কাজটি পুনরায় চালাতে হবে।",
"machine_learning_facial_recognition_setting": "ফেসিয়াল রিকগনিশন সক্ষম করুন",
"machine_learning_facial_recognition_setting_description": "নিষ্ক্রিয় থাকলে, ফেসিয়াল রিকগনিশনের জন্য ছবিগুলো এনকোড করা হবে না এবং এক্সপ্লোর পেজের পিপল (People) সেকশনটি পূর্ণ হবে না।",
"machine_learning_max_detection_distance": "সর্বোচ্চ শনাক্তকরণ দূরত্ব",
"machine_learning_max_detection_distance_description": "দুটি ছবিকে ডুপ্লিকেট হিসেবে গণ্য করার জন্য তাদের মধ্যকার সর্বোচ্চ দূরত্ব, যার পরিসীমা .০০১-.১। মান যত বেশি হবে তত বেশি ডুপ্লিকেট শনাক্ত হবে, তবে এতে ভুল শনাক্তকরণের (false positives) সম্ভাবনা থাকতে পারে।",
"machine_learning_max_recognition_distance": "সর্বোচ্চ চিহ্নিতকরণ দূরত্ব",
"machine_learning_max_recognition_distance_description": "দুটি মুখকে একই ব্যক্তি হিসেবে গণ্য করার জন্য তাদের মধ্যকার সর্বোচ্চ দূরত্ব, যার পরিসীমা -২। এই মান কমালে দু’জন ভিন্ন ব্যক্তিকে একই ব্যক্তি হিসেবে চিহ্নিত করার সম্ভাবনা কমে, আর মান বাড়ালে একই ব্যক্তিকে দু’জন ভিন্ন ব্যক্তি হিসেবে চিহ্নিত করার সম্ভাবনা কমে। মনে রাখবেন যে, দু’জন ব্যক্তিকে একত্রিত করা (merge) অপেক্ষাকৃত সহজ কিন্তু একজনকে দু’ভাগে ভাগ করা কঠিন, তাই সম্ভব হলে থ্রেশহোল্ড (threshold) কম রাখাই ভালো।",
"machine_learning_min_detection_score": "সর্বনিম্ন শনাক্তকরণ স্কোর",
"machine_learning_min_detection_score_description": "ছবিতে মুখ শনাক্ত করার জন্য -১ এর মধ্যে সর্বনিম্ন কনফিডেন্স স্কোর। মান যত কম হবে তত বেশি মুখ শনাক্ত হবে, তবে এতে ভুল শনাক্তকরণের (false positives) সম্ভাবনা থাকতে পারে।",
"machine_learning_min_recognized_faces": "সর্বনিম্ন স্বীকৃত মুখের সংখ্যা",
"machine_learning_min_recognized_faces_description": "একজন ব্যক্তি হিসেবে তৈরি হওয়ার জন্য স্বীকৃত মুখের সর্বনিম্ন সংখ্যা। এটি বাড়ালে ফেসিয়াল রিকগনিশন আরও নিখুঁত হয়, তবে এতে কোনো মুখ কোনো ব্যক্তির সাথে সংযুক্ত না হওয়ার সম্ভাবনাও বৃদ্ধি পায়।",
"machine_learning_ocr": "OCR",
"machine_learning_ocr_description": "ছবিতে টেক্সট (Text) শনাক্ত করতে মেশিন লার্নিং ব্যবহার করুন।",
"machine_learning_ocr_enabled": "OCR সক্ষম করুন",
"machine_learning_ocr_enabled_description": "নিষ্ক্রিয় থাকলে, ছবিগুলোতে টেক্সট শনাক্তকরণ করা হবে না।",
"machine_learning_ocr_max_resolution": "সর্বোচ্চ রেজোলিউশন(Resolution)",
"machine_learning_ocr_max_resolution_description": "এই রেজোলিউশনের উপরের প্রিভিউগুলোর অ্যাসপেক্ট রেশিও (আকার ও অনুপাত) ঠিক রেখে রিসাইজ করা হবে। মান যত বেশি হবে ফলাফল তত বেশি নিখুঁত হবে, তবে এটি প্রসেস করতে সময় বেশি লাগবে এবং মেমরি বেশি ব্যবহার করবে।",
"machine_learning_ocr_min_detection_score": "সর্বনিম্ন শনাক্তকরণ স্কোর",
"machine_learning_ocr_min_detection_score_description": "টেক্সট শনাক্ত করার জন্য -১ এর মধ্যে ন্যূনতম কনফিডেন্স স্কোর। মান যত কম হবে তত বেশি টেক্সট শনাক্ত হবে, তবে এতে ভুল শনাক্তকরণের (false positives) সম্ভাবনা থাকতে পারে।",
"machine_learning_ocr_min_recognition_score": "সর্বনিম্ন চিহ্নিতকরণ (Recognition)স্কোর",
"machine_learning_ocr_min_score_recognition_description": "শনাক্তকৃত টেক্সট চিহ্নিত করার জন্য -১ এর মধ্যে ন্যূনতম কনফিডেন্স স্কোর। মান যত কম হবে তত বেশি টেক্সট চিহ্নিত হবে, তবে এতে ভুল শনাক্তকরণের (false positives) সম্ভাবনা থাকতে পারে।",
"machine_learning_ocr_model": "OCR মডেল",
"machine_learning_ocr_model_description": "সার্ভার মডেলগুলো মোবাইল মডেলের তুলনায় বেশি নির্ভুল, তবে এগুলো প্রসেস করতে সময় বেশি লাগে এবং মেমরি বেশি ব্যবহার করে।",
"machine_learning_settings": "মেশিন লার্নিং সেটিংস (Machine Learning Settings)",
"machine_learning_settings_description": "মেশিন লার্নিং বৈশিষ্ট্য এবং সেটিংস পরিচালনা করুন",
"machine_learning_smart_search": "স্মার্ট সার্চ (Smart Search)",
"machine_learning_smart_search_description": "CLIP এমবেডিং (embeddings) ব্যবহার করে ছবির বিষয়বস্তু অনুযায়ী অনুসন্ধান করুন",
"machine_learning_smart_search_enabled": "স্মার্ট সার্চ সক্ষম করুন",
"machine_learning_smart_search_enabled_description": "নিষ্ক্রিয় থাকলে, স্মার্ট সার্চের জন্য ছবিগুলো এনকোড (encode) করা হবে না।",
"machine_learning_url_description": "মেশিন লার্নিং সার্ভারের URL। যদি একের বেশি URL প্রদান করা হয়, তবে একটি সফলভাবে সাড়া না দেওয়া পর্যন্ত প্রতিটি সার্ভারে এক এক করে চেষ্টা করা হবে (প্রথম থেকে শেষ ক্রমানুসারে)। যে সার্ভারগুলো সাড়া দেবে না, সেগুলো পুনরায় সচল হওয়া পর্যন্ত সাময়িকভাবে উপেক্ষা করা হবে।",
"maintenance_delete_backup": "ব্যাকআপ (Backup)মুছুন",
"maintenance_delete_backup_description": "এই ফাইলটি চিরতরে মুছে ফেলা হবে।",
"maintenance_delete_error": "ব্যাকআপ মুছতে ব্যর্থ হয়েছে।",
"maintenance_restore_backup": "ব্যাকআপ পুনরুদ্ধার(Restore) করুন",
"maintenance_restore_backup_description": "Immich মুছে ফেলা হবে এবং নির্বাচিত ব্যাকআপ থেকে পুনরুদ্ধার করা হবে। কার্যক্রম চালিয়ে যাওয়ার আগে একটি ব্যাকআপ তৈরি করা হবে।",
"maintenance_restore_backup_different_version": "এই ব্যাকআপটি Immich-এর একটি ভিন্ন সংস্করণের মাধ্যমে তৈরি করা হয়েছিল!",
"maintenance_restore_backup_unknown_version": "ব্যাকআপ সংস্করণ নির্ধারণ করা সম্ভব হয়নি।",
"maintenance_restore_database_backup": "ডেটাবেস ব্যাকআপ পুনরুদ্ধার করুন",
"maintenance_restore_database_backup_description": "একটি ব্যাকআপ ফাইল ব্যবহার করে ডেটাবেসকে পূর্ববর্তী অবস্থায় ফিরিয়ে আনুন।",
"maintenance_settings": "রক্ষণাবেক্ষণ (Maintenance)",
"maintenance_settings_description": "Immich-কে রক্ষণাবেক্ষণ মোডে (maintenance mode) রাখুন।",
"maintenance_start": "রক্ষণাবেক্ষণ মোডে পরিবর্তন করুন",
"maintenance_start_error": "রক্ষণাবেক্ষণ মোড চালু করতে ব্যর্থ হয়েছে।",
"maintenance_upload_backup": "ডেটাবেস ব্যাকআপ ফাইল আপলোড করুন",
"maintenance_upload_backup_error": "ব্যাকআপ আপলোড করা যায়নি, এটি কি কোনো .sql/.sql.gz ফাইল?",
"manage_concurrency": "কনকারেন্সি পরিচালনা করুন (Manage Concurrency)",
"manage_concurrency_description": "জব কনকারেন্সি পরিচালনা করতে 'জবস' (Jobs) পাতায় যান।",
"manage_log_settings": "লগ সেটিংস পরিচালনা করুন",
"map_dark_style": "ডার্ক স্টাইল (Dark style)",
"map_enable_description": "ম্যাপ ফিচারগুলো সক্রিয় করুন (Enable map features)",
"map_gps_settings": "ম্যাপ এবং জিপিএস সেটিংস (Map & GPS Settings)",
"map_gps_settings_description": "ম্যাপ এবং জিপিএস (রিভার্স জিওকোডিং) সেটিংস পরিচালনা করুন (Manage Map & GPS (Reverse Geocoding) Settings)",
"map_implications": "ম্যাপ ফিচারটি একটি এক্সটার্নাল টাইল সার্ভিসের (tiles.immich.cloud) ওপর নির্ভর করে।",
"map_light_style": "লাইট স্টাইল (Light style)",
"map_manage_reverse_geocoding_settings": "<link>রিভার্স জিওকোডিং</link> সেটিংস পরিচালনা করুন",
"map_reverse_geocoding": "রিভার্স জিওকোডিং (Reverse Geocoding)",
"map_reverse_geocoding_enable_description": "রিভার্স জিওকোডিং সক্রিয় করুন (Enable reverse geocoding)",
"map_reverse_geocoding_settings": "রিভার্স জিওকোডিং সেটিংস (Reverse Geocoding Settings)",
"map_settings": "মানচিত্র (Map)",
"map_settings_description": "মানচিত্রের সেটিংস পরিচালনা করুন (Manage map settings)",
"map_style_description": "একটি style.json ম্যাপ থিমের URL (URL to a style.json map theme)",
"memory_cleanup_job": "মেমরি ক্লিনআপ (Memory cleanup)",
"memory_generate_job": "স্মৃতি তৈরি করা(Memory generation)",
"metadata_extraction_job": "মেটাডেটা এক্সট্র্যাক্ট করুন (Extract metadata)",
"metadata_extraction_job_description": "প্রতিটি অ্যাসেট (Asset) থেকে মেটাডেটা তথ্য এক্সট্র্যাক্ট করুন, যেমন: জিপিএস (GPS), চেহারা (faces) এবং রেজোলিউশন (resolution)।",
"metadata_faces_import_setting": "ফেস ইম্পোর্ট সক্রিয় করুন (Enable face import)",
"metadata_faces_import_setting_description": "ছবির EXIF ডেটা এবং সাইডকার (sidecar) ফাইল থেকে চেহারা (faces) ইম্পোর্ট করুন।",
"metadata_settings": "মেটাডেটা সেটিংস (Metadata Settings)",
"metadata_settings_description": "মেটাডেটা সেটিংস পরিচালনা করুন (Manage metadata settings)",
"migration_job": "মাইগ্রেশন (Migration)",
"migration_job_description": "অ্যাসেট এবং ফেস থাম্বনেইলগুলোকে সর্বশেষ ফোল্ডার স্ট্রাকচারে মাইগ্রেট করুন। (Migrate thumbnails for assets and faces to the latest folder structure)",
"nightly_tasks_database_cleanup_setting": "ডেটাবেস ক্লিনআপ টাস্কসমূহ (Database cleanup tasks)",
"nightly_tasks_database_cleanup_setting_description": "ডেটাবেস থেকে পুরোনো এবং মেয়াদোত্তীর্ণ ডেটা মুছে ফেলুন",
"nightly_tasks_generate_memories_setting": "মেমোরিজ তৈরি করুন (Generate memories)",
"nightly_tasks_generate_memories_setting_description": "অ্যাসেটগুলো থেকে নতুন মেমোরিজ তৈরি করুন",
"nightly_tasks_missing_thumbnails_setting": "হারিয়ে যাওয়া থাম্বনেইলগুলো তৈরি করুন",
"nightly_tasks_missing_thumbnails_setting_description": "থাম্বনেইল নেই এমন ফাইলগুলোকে কিউতে (Queue) যোগ করুন",
"nightly_tasks_settings": "নাইটলি টাস্ক সেটিংস (Nightly Tasks Settings)",
"nightly_tasks_settings_description": "নাইটলি টাস্ক পরিচালনা করুন (Manage nightly tasks)",
"nightly_tasks_start_time_setting": "শুরু করার সময় (Start time)",
"nightly_tasks_start_time_setting_description": "সার্ভার যখন নাইটলি টাস্ক (nightly tasks) চালানো শুরু করে সেই সময়",
"nightly_tasks_sync_quota_usage_setting": "কোটা ব্যবহারের তথ্য সিঙ্ক করুন (Sync quota usage)",
"nightly_tasks_sync_quota_usage_setting_description": "বর্তমান ব্যবহারের ওপর ভিত্তি করে ব্যবহারকারীর স্টোরেজ কোটা আপডেট করুন।",
"no_paths_added": "কোনো পাথ যোগ করা হয়নি (No paths added)",
"no_pattern_added": "কোনো প্যাটার্ন যোগ করা হয়নি (No pattern added)",
"note_apply_storage_label_previous_assets": "দ্রষ্টব্য: পূর্বে আপলোড করা অ্যাসেটগুলোতে স্টোরেজ লেবেল (Storage Label) প্রয়োগ করতে নিচের কমান্ডটি রান করুন—",
"note_cannot_be_changed_later": "সতর্কবার্তা: এটি পরবর্তীতে পরিবর্তন করা যাবে না!",
"notification_email_from_address": "প্রেরকের ঠিকানা (From address)",
"notification_email_from_address_description": "প্রেরকের ইমেল ঠিকানা, উদাহরণস্বরূপ: \"Immich Photo Server noreply@example.com\"। নিশ্চিত করুন যে আপনি এমন একটি ঠিকানা ব্যবহার করছেন যা থেকে ইমেল পাঠানোর অনুমতি আপনার আছে।",
"notification_email_host_description": "ইমেল সার্ভারের হোস্ট (যেমন: smtp.immich.app)",
"notification_email_ignore_certificate_errors": "সার্টিফিকেট ত্রুটিগুলো উপেক্ষা করুন (Ignore certificate errors)",
"notification_email_ignore_certificate_errors_description": "TLS সার্টিফিকেট ভ্যালিডেশন ত্রুটিগুলো উপেক্ষা করুন (প্রস্তাবিত নয়)",
"notification_email_password_description": "ইমেল সার্ভারে অথেন্টিকেশন বা সত্যতা যাচাইয়ের জন্য ব্যবহৃত পাসওয়ার্ড",
"notification_email_port_description": "ইমেল সার্ভারের পোর্ট (যেমন: ২৫, ৪৬৫, অথবা ৫৮৭)",
"notification_email_secure": "SMTPS (স্মার্ট মেইল ট্রান্সফার প্রোটোকল সিকিউর)",
"notification_email_secure_description": "SMTPS (SMTP over TLS) ব্যবহার করুন",
"notification_email_sent_test_email_button": "টেস্ট ইমেল পাঠান এবং সেভ করুন",
"oauth_enable_description": "OAuth-এর মাধ্যমে লগইন করুন",
"oauth_mobile_redirect_uri": "মোবাইল রিডাইরেক্ট ইউআরআই (URI)",
"oauth_mobile_redirect_uri_override": "মোবাইল রিডাইরেক্ট ইউআরআই (URI) ওভাররাইড",
"oauth_mobile_redirect_uri_override_description": "যখন OAuth প্রোভাইডার মোবাইল ইউআরআই (URI) অনুমতি দেয় না, যেমন ''{callback}'', তখন এটি সক্রিয় করুন।",
"oauth_role_claim": "রোল ক্লেইম (Role Claim)",
"oauth_role_claim_description": "এই ক্লেইমটির উপস্থিতির ওপর ভিত্তি করে স্বয়ংক্রিয়ভাবে অ্যাডমিন অ্যাক্সেস প্রদান করুন। ক্লেইমটিতে 'user' অথবা 'admin' যেকোনো একটি থাকতে পারে।",
"oauth_settings": "OAuth",
"oauth_settings_description": "OAuth লগইন সেটিংস ম্যানেজ করুন",
"oauth_settings_more_details": "এই ফিচারের ব্যাপারে আরও বিস্তারিত জানতে, <link>ডকুমেন্টস</link> দেখুন।",
"oauth_storage_label_claim": "স্টোরেজ লেবেল ক্লেইম (Storage label claim)",
"oauth_storage_label_claim_description": "এই ক্লেইম-এর ভ্যালু অনুযায়ী ব্যবহারকারীর স্টোরেজ লেবেল স্বয়ংক্রিয়ভাবে সেট করুন।",
"oauth_storage_quota_claim": "স্টোরেজ কোটা ক্লেইম (Storage quota claim)",
"oauth_storage_quota_claim_description": "এই ক্লেইম-এর ভ্যালু অনুযায়ী ব্যবহারকারীর স্টোরেজ কোটা স্বয়ংক্রিয়ভাবে সেট করুন।",
"oauth_storage_quota_default": "ডিফল্ট স্টোরেজ কোটা (GiB)",
"oauth_storage_quota_default_description": "ক্লেইম না দেওয়া থাকলে যে স্টোরেজ কোটা (GiB-তে) ব্যবহার করা হবে।",
"oauth_timeout": "রিকোয়েস্ট টাইম-আউট (Request Timeout)",
"oauth_timeout_description": "মিলিসেকেন্ডে রিকোয়েস্টের টাইম-আউট (Timeout for requests in milliseconds)",
"ocr_job_description": "ছবি থেকে টেক্সট শনাক্ত করতে মেশিন লার্নিং ব্যবহার করুন",
"password_enable_description": "ইমেল এবং পাসওয়ার্ড দিয়ে লগইন করুন",
"password_settings": "পাসওয়ার্ড লগইন (Password Login)",
"password_settings_description": "পাসওয়ার্ড লগইন সেটিংস ম্যানেজ করুন",
"paths_validated_successfully": "সবগুলো পাথ (path) সফলভাবে যাচাই করা হয়েছে",
"person_cleanup_job": "পারসন ক্লিনআপ (Person Cleanup)",
"queue_details": "কিউ ডিটেইলস (Queue Details)",
"queues": "জব কিউ (Job Queues)",
"queues_page_description": "অ্যাডমিন জব কিউ (Job Queues) পেজ",
"quota_size_gib": "কোটা সাইজ (GiB)",
"refreshing_all_libraries": "সবগুলো লাইব্রেরি রিফ্রেশ করা হচ্ছে",
"registration": "অ্যাডমিন রেজিস্ট্রেশন (Admin Registration)",
"registration_description": "যেহেতু আপনি এই সিস্টেমের প্রথম ব্যবহারকারী, তাই আপনাকে অ্যাডমিন (Admin) হিসেবে নিযুক্ত করা হবে। আপনি সমস্ত প্রশাসনিক কাজের জন্য দায়ী থাকবেন এবং পরবর্তী ব্যবহারকারীরা আপনার মাধ্যমেই তৈরি হবে।",
"remove_failed_jobs": "ব্যর্থ হওয়া কাজগুলো মুছে ফেলুন (Remove failed jobs)",
"require_password_change_on_login": "প্রথমবার লগইন করার সময় ব্যবহারকারীর পাসওয়ার্ড পরিবর্তন করা বাধ্যতামূলক করুন",
"reset_settings_to_default": "সেটিংস রিসেট করে ডিফল্ট অবস্থায় ফিরিয়ে আনুন (Reset settings to default)",
"reset_settings_to_recent_saved": "সম্প্রতি সেভ করা সেটিংসে রিসেট করুন (Reset settings to the recent saved settings)",
"scanning_library": "লাইব্রেরি স্ক্যান করা হচ্ছে (Scanning library)",
"search_jobs": "জব সার্চ করুন…",
"send_welcome_email": "স্বাগত ইমেল পাঠান",
"server_external_domain_settings": "এক্সটার্নাল ডোমেইন (External Domain)",
"server_external_domain_settings_description": "পাবলিক শেয়ারিং লিঙ্কের জন্য ডোমেইন (http(s):// সহ)",
"server_public_users": "পাবলিক ইউজার (Public Users)",
"server_public_users_description": "শেয়ার করা অ্যালবামে কোনো ব্যবহারকারীকে যোগ করার সময় সমস্ত ব্যবহারকারীর (নাম এবং ইমেল) তালিকা দেখানো হয়। এটি নিষ্ক্রিয় (Disabled) করা হলে, ব্যবহারকারীর তালিকা শুধুমাত্র অ্যাডমিনদের জন্য উপলব্ধ হবে।",
"server_settings": "সার্ভার সেটিংস (Server Settings)",
"server_settings_description": "সার্ভার সেটিংস ম্যানেজ করুন (Manage server settings)",
"server_stats_page_description": "অ্যাডমিন সার্ভার স্ট্যাটিস্টিকস (Server Statistics) পেজ",
"server_welcome_message": "স্বাগত বার্তা (Welcome message)",
"server_welcome_message_description": "লগইন পেজে প্রদর্শিত একটি বার্তা।",
"settings_page_description": "অ্যাডমিন সেটিংস পেজ",
"sidecar_job": "সাইডকার মেটাডেটা (Sidecar Metadata)",
"sidecar_job_description": "ফাইলসিস্টেম থেকে সাইডকার মেটাডেটা অনুসন্ধান বা সিঙ্ক্রোনাইজ করুন",
"slideshow_duration_description": "প্রতিটি ছবি দেখানোর সময়কাল (সেকেন্ডে)",
"smart_search_job_description": "স্মার্ট সার্চের সুবিধার্থে অ্যাসেটগুলোর ওপর মেশিন লার্নিং পরিচালনা করুন",
"storage_template_date_time_description": "অ্যাসেট তৈরির সময়কাল (Timestamp) তারিখ ও সময়ের তথ্যের জন্য ব্যবহৃত হয়",
"storage_template_date_time_sample": "নমুনা সময় {date}",
"storage_template_enable_description": "স্টোরেজ টেমপ্লেট ইঞ্জিন সক্রিয় করুন",
"storage_template_hash_verification_enabled": "হ্যাশ ভেরিফিকেশন (Hash Verification) সক্রিয় করা হয়েছে",
"storage_template_hash_verification_enabled_description": "হ্যাশ ভেরিফিকেশন (Hash Verification) সক্রিয় করে; এর প্রভাব সম্পর্কে নিশ্চিত না হয়ে এটি নিষ্ক্রিয় করবেন না",
"storage_template_migration": "স্টোরেজ টেমপ্লেট মাইগ্রেশন (Storage Template Migration)",
"storage_template_migration_description": "পূর্বে আপলোড করা অ্যাসেটগুলোতে বর্তমান <link>{template}</link> প্রয়োগ করুন",
"storage_template_migration_info": "স্টোরেজ টেমপ্লেটটি সমস্ত এক্সটেনশনকে ছোট হাতের অক্ষরে (lowercase) রূপান্তর করবে। টেমপ্লেটের পরিবর্তনগুলো কেবল নতুন অ্যাসেটগুলোর ক্ষেত্রে প্রযোজ্য হবে। পূর্বে আপলোড করা অ্যাসেটগুলোতে এই টেমপ্লেটটি ভূতাপেক্ষভাবে (retroactively) প্রয়োগ করতে <link>{job}</link> রান করুন।",
"storage_template_migration_job": "স্টোরেজ টেমপ্লেট মাইগ্রেশন জব",
"storage_template_more_details": "এই ফিচারটি সম্পর্কে আরও বিস্তারিত জানতে, <template-link>Storage Template</template-link> এবং এর <implications-link>প্রভাবগুলো (implications)</implications-link> দেখুন।",
"storage_template_onboarding_description_v2": "এটি সক্রিয় থাকলে, ফিচারটি ব্যবহারকারীর নির্ধারিত টেমপ্লেট অনুযায়ী ফাইলগুলোকে স্বয়ংক্রিয়ভাবে অর্গানাইজ (Auto-organize) করবে। আরও তথ্যের জন্য অনুগ্রহ করে <link>ডকুমেন্টেশন</link> দেখুন।",
"storage_template_path_length": "আনুমানিক পাথ লেন্থ লিমিট (Path length limit): <b>{length, number}</b>/{limit, number}",
"storage_template_settings": "স্টোরেজ টেমপ্লেট (Storage Template)",
"storage_template_settings_description": "আপলোড করা অ্যাসেটের ফোল্ডার স্ট্রাকচার এবং ফাইল নেম ম্যানেজ করুন",
"storage_template_user_label": "<code>{label}</code> হলো ব্যবহারকারীর স্টোরেজ লেবেল (Storage Label)",
"theme_settings_description": "ইমিচ (Immich) ওয়েব ইন্টারফেসের কাস্টমাইজেশন ম্যানেজ করুন",
"thumbnail_generation_job": "থাম্বনেইল তৈরি করুন (Generate Thumbnails)",
"thumbnail_generation_job_description": "প্রতিটি অ্যাসেটের জন্য বড়, ছোট এবং ব্লার (অস্পষ্ট) থাম্বনেইল তৈরি করুন, সেই সাথে প্রতিটি ব্যক্তির জন্যও থাম্বনেইল তৈরি করুন।",
"transcoding_acceleration_api": "অ্যাক্সিলারেট এপিআই (Acceleration API)",
"transcoding_acceleration_api_description": "ট্রানসকোডিং (transcoding) দ্রুত করার জন্য আপনার ডিভাইসের সাথে যে API ইন্টারঅ্যাক্ট করবে। এই সেটিংসটি 'সাধ্যমতো' (best effort) কাজ করবে: ব্যর্থ হলে এটি পুনরায় সফটওয়্যার ট্রানসকোডিংয়ে ফিরে আসবে। হার্ডওয়্যারের ওপর ভিত্তি করে VP9 কাজ করতেও পারে, আবার নাও করতে পারে।",
"transcoding_acceleration_nvenc": "NVENC (NVIDIA GPU প্রয়োজন)",
"transcoding_acceleration_qsv": "Quick Sync (৭ম প্রজন্মের ইনটেল CPU বা পরবর্তী ভার্সন প্রয়োজন)",
"transcoding_acceleration_rkmpp": "RKMPP (শুধুমাত্র Rockchip SOC-এর জন্য)",
"transcoding_acceleration_vaapi": "VA-API (ভিডিও অ্যাক্সিলারেশন এপিআই)",
"transcoding_accepted_audio_codecs": "গ্রহণযোগ্য অডিও কোডেকসমূহ (Accepted audio codecs)",
"transcoding_accepted_audio_codecs_description": "কোন অডিও কোডেকগুলো ট্রানসকোড করার প্রয়োজন নেই তা নির্বাচন করুন। এটি শুধুমাত্র নির্দিষ্ট ট্রানসকোড পলিসির (transcode policies) জন্য ব্যবহৃত হয়।",
"transcoding_accepted_containers": "গ্রহণযোগ্য কন্টেইনারসমূহ (Accepted containers)"
},
"yes": "হ্যাঁ",
"you_dont_have_any_shared_links": "আপনার কোনো শেয়ার করা লিঙ্ক নেই (You don't have any shared links)",
"your_wifi_name": "আপনার ওয়াই-ফাই এর নাম (Your Wi-Fi name)",
"zero_to_clear_rating": "অ্যাসেট রেটিং মুছে ফেলতে চাপুন",
"zoom_image": "ছবি জুম করুন (Zoom Image)",
"zoom_to_bounds": "বাউন্ডস অনুযায়ী জুম করুন (Zoom to bounds)"
}

View File

@@ -572,6 +572,9 @@
"asset_list_layout_sub_title": "Disseny",
"asset_list_settings_subtitle": "Configuració del disseny de la graella de fotos",
"asset_list_settings_title": "Graella de fotos",
"asset_not_found_on_device_android": "No s'ha trobat l'actiu al dispositiu",
"asset_not_found_on_device_ios": "No s'ha trobat l'element al dispositiu. Si utilitzes l'iCloud, pot ser que no s'hi pugui accedir perquè el fitxer guardat a l'iCloud és corrupte",
"asset_not_found_on_icloud": "No s'ha trobat l'element a l'iCloud. Pot ser que no s'hi pugui accedir perquè el fitxer guardat a l'iCloud és corrupte",
"asset_offline": "Element fora de línia",
"asset_offline_description": "Aquest recurs extern ja no es troba al disc. Poseu-vos en contacte amb el vostre administrador d'Immich per obtenir ajuda.",
"asset_restored_successfully": "Element recuperat correctament",
@@ -779,6 +782,8 @@
"client_cert_import": "Importar",
"client_cert_import_success_msg": "S'ha importat el certificat del client",
"client_cert_invalid_msg": "Fitxer de certificat no vàlid o contrasenya incorrecta",
"client_cert_password_message": "Introdueix la contrasenya per a aquest certificat",
"client_cert_password_title": "Contrasenya del certificat",
"client_cert_remove_msg": "S'ha eliminat el certificat del client",
"client_cert_subtitle": "Només admet el format PKCS12 (.p12, .pfx). La importació/eliminació de certificats només està disponible abans d'iniciar sessió",
"client_cert_title": "Certificat de client SSL",
@@ -992,6 +997,11 @@
"editor_close_without_save_prompt": "No es desaran els canvis",
"editor_close_without_save_title": "Tancar l'editor?",
"editor_confirm_reset_all_changes": "Segur que vols reiniciar tots els canvis?",
"editor_discard_edits_confirm": "Descarta les modificacions",
"editor_discard_edits_prompt": "Tens modificacions sense desar. Estàs segur que les vols descartar?",
"editor_discard_edits_title": "Vols descartar les modificacions?",
"editor_edits_applied_error": "No s'han pogut aplicar les modificacions",
"editor_edits_applied_success": "Les modificacions s'han aplicat correctament",
"editor_flip_horizontal": "Capgira horitzontalment",
"editor_flip_vertical": "Capgira verticalment",
"editor_orientation": "Orientació",
@@ -1192,8 +1202,9 @@
"features": "Característiques",
"features_in_development": "Funcions en desenvolupament",
"features_setting_description": "Administrar les funcions de l'aplicació",
"file_name": "Nom de l'arxiu: {file_name}",
"file_name_or_extension": "Nom de l'arxiu o extensió",
"file_name_text": "Nom del fitxer",
"file_name_with_value": "Nom del fitxer: {file_name}",
"file_size": "Mida del fitxer",
"filename": "Nom del fitxer",
"filetype": "Tipus d'arxiu",
@@ -2295,6 +2306,7 @@
"upload_details": "Detalls de la Pujada",
"upload_dialog_info": "Vols fer còpia de seguretat dels elements seleccionats al servidor?",
"upload_dialog_title": "Puja elements",
"upload_error_with_count": "Error en la càrrega de {count, plural, one {# actiu} other {# actius}}",
"upload_errors": "Càrrega completada amb {count, plural, one {# error} other {# errors}}, actualitzeu la pàgina per veure els nous elements carregats.",
"upload_finished": "Pujada finalitzada",
"upload_progress": "Restant {remaining, number} - Processat {processed, number}/{total, number}",

View File

@@ -572,6 +572,9 @@
"asset_list_layout_sub_title": "Rozložení",
"asset_list_settings_subtitle": "Nastavení rozložení mřížky fotografií",
"asset_list_settings_title": "Mřížka fotografií",
"asset_not_found_on_device_android": "Položka nebyla nalezena na zařízení",
"asset_not_found_on_device_ios": "Položka nebyla nalezena na zařízení. Pokud používáte iCloud, položka může být nepřístupná kvůli poškozenému souboru uloženému na iCloudu",
"asset_not_found_on_icloud": "Položka nebyla nalezena na iCloudu. Položka může být nepřístupná kvůli poškozenému souboru uloženému na iCloudu",
"asset_offline": "Offline položka",
"asset_offline_description": "Toto externí položka se již na disku nenachází. Obraťte se na správce Immich a požádejte o pomoc.",
"asset_restored_successfully": "Položka úspěšně obnovena",
@@ -779,6 +782,8 @@
"client_cert_import": "Importovat",
"client_cert_import_success_msg": "Klientský certifikát je importován",
"client_cert_invalid_msg": "Neplatný soubor certifikátu nebo špatné heslo",
"client_cert_password_message": "Zadejte heslo pro tento certifikát",
"client_cert_password_title": "Heslo certifikátu",
"client_cert_remove_msg": "Klientský certifikát je odstraněn",
"client_cert_subtitle": "Podporuje pouze formát PKCS12 (.p12, .pfx). Import/odstranění certifikátu je možné pouze před přihlášením",
"client_cert_title": "Klientský SSL certifikát [EXPERIMENTÁLNÍ]",
@@ -992,6 +997,11 @@
"editor_close_without_save_prompt": "Změny nebudou uloženy",
"editor_close_without_save_title": "Zavřít editor?",
"editor_confirm_reset_all_changes": "Opravdu chcete zrušit všechny změny?",
"editor_discard_edits_confirm": "Zrušit úpravy",
"editor_discard_edits_prompt": "Máte neuložené úpravy. Opravdu je chcete smazat?",
"editor_discard_edits_title": "Zrušit úpravy?",
"editor_edits_applied_error": "Nepodařilo se použít úpravy",
"editor_edits_applied_success": "Úpravy byly úspěšně provedeny",
"editor_flip_horizontal": "Otočit vodorovně",
"editor_flip_vertical": "Otočit svisle",
"editor_orientation": "Orientace",
@@ -1192,8 +1202,9 @@
"features": "Funkce",
"features_in_development": "Funkce ve vývoji",
"features_setting_description": "Správa funkcí aplikace",
"file_name": "Název souboru: {file_name}",
"file_name_or_extension": "Název nebo přípona souboru",
"file_name_text": "Název souboru",
"file_name_with_value": "Název souboru: {file_name}",
"file_size": "Velikost souboru",
"filename": "Název souboru",
"filetype": "Typ souboru",
@@ -2295,6 +2306,7 @@
"upload_details": "Detaily nahrávání",
"upload_dialog_info": "Chcete zálohovat vybrané položky na server?",
"upload_dialog_title": "Nahrát položku",
"upload_error_with_count": "Chyba při nahrávání {count, plural, one {# položky} other {# položek}}",
"upload_errors": "Nahrávání bylo dokončeno s {count, plural, one {# chybou} other {# chybami}}, obnovte stránku pro zobrazení nových položek.",
"upload_finished": "Nahrávání dokončeno",
"upload_progress": "Zbývá {remaining, number} - Zpracováno {processed, number}/{total, number}",

View File

@@ -201,7 +201,7 @@
"maintenance_restore_database_backup_description": "Gendan en tidligere databasetilstand ved hjælp af en sikkerhedskopifil",
"maintenance_settings": "Vedligeholdelse",
"maintenance_settings_description": "Sæt Immich i vedligeholdelsestilstand.",
"maintenance_start": "Start vedligeholdelsestilstand",
"maintenance_start": "Skift til vedligeholdelsestilstand",
"maintenance_start_error": "Vedligeholdelsestilstand kunne ikke startes.",
"maintenance_upload_backup": "Upload databasebackupfil",
"maintenance_upload_backup_error": "Kunne ikke uploade backup, er det en .sql/.sql.gz fil?",
@@ -272,7 +272,7 @@
"oauth_auto_register": "Autoregistrér",
"oauth_auto_register_description": "Registrér automatisk nye brugere efter at have logget ind med OAuth",
"oauth_button_text": "Knaptekst",
"oauth_client_secret_description": "Påkrævet hvis PKCE (Proof Key for Code Exchange) ikke er supporteret af OAuth-udbyderen",
"oauth_client_secret_description": "Påkrævet for en fortrolig klient eller hvis PKCE (Proof Key for Code Exchange) ikke understøttes for en offentlig klient.",
"oauth_enable_description": "Log ind med OAuth",
"oauth_mobile_redirect_uri": "Mobilomdiregerings-URL",
"oauth_mobile_redirect_uri_override": "Tilsidesættelse af mobil omdiregerings-URL",
@@ -383,7 +383,7 @@
"transcoding_hardware_acceleration": "Hardwareacceleration",
"transcoding_hardware_acceleration_description": "Eksperimentel: hurtigere transkodning men kan sænke kvaliteten ved samme bitrate",
"transcoding_hardware_decoding": "Hardware-afkodning",
"transcoding_hardware_decoding_setting_description": "Gælder kun NVENC, QSV og RKMPP. Slår ende-til-ende acceleration til i stedet for kun at accelerere indkodning. Virker måske ikke på alle videoer.",
"transcoding_hardware_decoding_setting_description": "Slår endetilendeacceleration til i stedet for kun at accelerere indkodning. Virker muligvis ikke på alle videoer.",
"transcoding_max_b_frames": "Maksimum B-frames",
"transcoding_max_b_frames_description": "Højere værdier forbedrer kompressionseffektivitet, men kan gøre indkodning langsommere. Er måske ikke kompatibelt med hardware-acceleration på ældre enheder. 0 slår B-frames fra, mens -1 sætter denne værdi automatisk.",
"transcoding_max_bitrate": "Maksimal bitrate",
@@ -537,7 +537,7 @@
"app_bar_signout_dialog_content": "Er du sikker på, du vil logge ud?",
"app_bar_signout_dialog_ok": "Ja",
"app_bar_signout_dialog_title": "Log ud",
"app_download_links": "App Download Links",
"app_download_links": "Links til app download",
"app_settings": "Appindstillinger",
"app_stores": "App Butikker",
"app_update_available": "App opdatering er tilgængelig",
@@ -572,6 +572,9 @@
"asset_list_layout_sub_title": "Udseende",
"asset_list_settings_subtitle": "Indstillinger for billedgitterlayout",
"asset_list_settings_title": "Billedgitter",
"asset_not_found_on_device_android": "Kan ikke finde elementet på enheden",
"asset_not_found_on_device_ios": "Mediet blev ikke fundet på enheden. Hvis du bruger iCloud, kan mediet være utilgængeligt, hvis en fejlagtig fil ligger på iCloud",
"asset_not_found_on_icloud": "Mediet blev ikke fundet på iCloud. Det kan være utilgængeligt, hvis det er en fejlagtig fil, der ligger på iCloud",
"asset_offline": "Mediefil offline",
"asset_offline_description": "Denne eksterne mediefil kan ikke længere findes på drevet. Kontakt venligst din Immich-administrator for hjælp.",
"asset_restored_successfully": "Elementet blev gendannet succesfuldt",
@@ -763,10 +766,10 @@
"cleanup_found_assets": "Fandt {count} sikkerhedskopierede filer",
"cleanup_found_assets_with_size": "Fundet {count} sikkerhedskopierede objekter ({size})",
"cleanup_icloud_shared_albums_excluded": "iCloud delte albummer er udelukket fra scanningen",
"cleanup_no_assets_found": "Ingen sikkerhedskopierede filer fundet der matcher dine kriterier",
"cleanup_no_assets_found": "Ingen elementer matcher kriterierne ovenfor. Frigiv plads kan kun fjerne elementer, der er sikkerhedskopieret til serveren",
"cleanup_preview_title": "Filer at fjerne ({count})",
"cleanup_step3_description": "Scan efter fotos og videoer, der er blevet sikkerhedskopieret til serveren med den valgte stop-dato og filtermuligheder",
"cleanup_step4_summary": "{count} filer lavet før {date} er i kø for at blive fjernet fra denne enhed",
"cleanup_step3_description": "Skan efter sikkerhedskopierede elementer, som matcher dine dato- og indstillingsvalg.",
"cleanup_step4_summary": "{count, plural, one {element} other {elementer}} oprettet før {date} står til at blive fjernet fra denne enhed. Billeder vil stadig være tilgængelige i Immichappen.",
"cleanup_trash_hint": "For at genvinde lagringsplads helt, skal du åbne din indbyggede galleriapp og tømme papirkurven",
"clear": "Ryd",
"clear_all": "Ryd alle",
@@ -779,6 +782,8 @@
"client_cert_import": "Importer",
"client_cert_import_success_msg": "Klient certifikat er importeret",
"client_cert_invalid_msg": "Invalid certifikat fil eller forkert adgangskode",
"client_cert_password_message": "Skriv kodeord til dette certifikat",
"client_cert_password_title": "Kodeord til certifikat",
"client_cert_remove_msg": "Klient certifikat er fjernet",
"client_cert_subtitle": "Supportere kun PKCS12 (.p12, .pfx) format. Certifikat importering/fjernelse er kun tilgængeligt før login",
"client_cert_title": "SSL Klient Certifikat [EKSPERIMENTAL]",
@@ -864,8 +869,9 @@
"custom_locale": "Brugerdefineret lokale",
"custom_locale_description": "Formatér datoer og tal baseret på sproget og regionen",
"custom_url": "Tilpasset URL",
"cutoff_date_description": "Fjern fotos og videoer ældre end",
"cutoff_day": "{antal, flertal, en {day} andre {days}}",
"cutoff_date_description": "Behold fotos fra den sidste…",
"cutoff_day": "{count, plural, one {dag} other {dage}}",
"cutoff_year": "{count, plural, one {år} other {år}}",
"daily_title_text_date": "E, dd MMM",
"daily_title_text_date_year": "E, dd MMM, yyyy",
"dark": "Mørk",
@@ -919,7 +925,7 @@
"description_input_hint_text": "Tilføj en beskrivelse...",
"description_input_submit_error": "Fejl med at opdatere beskrivelsen. Tjek loggen for flere detaljer",
"deselect_all": "Afmarkér alt",
"details": "DETALJER",
"details": "Detaljer",
"direction": "Retning",
"disable": "Deaktiver",
"disabled": "Deaktiveret",
@@ -991,6 +997,11 @@
"editor_close_without_save_prompt": "Ændringerne vil ikke blive gemt",
"editor_close_without_save_title": "Luk editor?",
"editor_confirm_reset_all_changes": "Er du sikker på, at du vil nulstille alle ændringer?",
"editor_discard_edits_confirm": "Kassér redigeringer",
"editor_discard_edits_prompt": "Du har ikkegemte redigeringer. Er du sikker på, at du vil kassere dem?",
"editor_discard_edits_title": "Kassér ændringer?",
"editor_edits_applied_error": "Kunne ikke gemme redigeringer",
"editor_edits_applied_success": "Redigeringer gemt",
"editor_flip_horizontal": "Vend horisontalt",
"editor_flip_vertical": "Flip vertikal",
"editor_orientation": "Orientering",
@@ -1018,9 +1029,11 @@
"error_loading_albums": "Fejl ved indlæsning af album",
"error_loading_image": "Fejl ved indlæsning af billede",
"error_loading_partners": "Fejl ved indlæsning af partnere: {error}",
"error_retrieving_asset_information": "Fejl ved hentning af objekt-data",
"error_saving_image": "Fejl: {error}",
"error_tag_face_bounding_box": "Fejl ved tagging af ansigt - kan ikke finde koordinator for afgrænsningskasse",
"error_title": "Fejl - Noget gik galt",
"error_while_navigating": "Fejl ved navigering til objekt",
"errors": {
"cannot_navigate_next_asset": "Kan ikke navigere til næste mediefil",
"cannot_navigate_previous_asset": "Kan ikke navigere til forrige mediefil",
@@ -1189,8 +1202,9 @@
"features": "Funktioner",
"features_in_development": "Funktioner under udvikling",
"features_setting_description": "Administrer app-funktioner",
"file_name": "Filnavn: {file_name}",
"file_name_or_extension": "Filnavn eller filtype",
"file_name_text": "Filnavn",
"file_name_with_value": "Filnavn: {file_name}",
"file_size": "Fil størrelse",
"filename": "Filnavn",
"filetype": "Filtype",
@@ -1209,7 +1223,7 @@
"forgot_pin_code_question": "Har du glemt PIN-koden?",
"forward": "Fremad",
"free_up_space": "Frigør plads",
"free_up_space_description": "Flyt sikkerhedskopierede fotos og videoer til din enheds skraldepapir for at frigøre plads. Dine kopier på serveren forbliver sikre",
"free_up_space_description": "Flyt sikkerhedskopierede fotos og videoer til din enheds skraldespand for at frigøre plads. Dine kopier på serveren forbliver sikre.",
"free_up_space_settings_subtitle": "Frigør enhedslagerplads",
"full_path": "Fuld sti: {path}",
"gcast_enabled": "Google Cast",
@@ -1326,9 +1340,15 @@
"json_editor": "JSON editor",
"json_error": "JSON fejl",
"keep": "Behold",
"keep_albums": "Behold albums",
"keep_albums_count": "Beholder {count} {count, plural, one {album} other {albums}}",
"keep_all": "Behold alle",
"keep_description": "Vælg hvad der skal forblive på din enhed efter oprydning af plads.",
"keep_favorites": "Behold favoritter",
"keep_on_device": "Behold på enheden",
"keep_on_device_hint": "Vælg elementer, der skal beholdes på denne enhed",
"keep_this_delete_others": "Behold dette, slet andre",
"keeping": "Beholder: {items}",
"kept_this_deleted_others": "Beholdt denne mediefil og slettede {count, plural, one {# aktiv} other {# aktiver}}",
"keyboard_shortcuts": "Tastaturgenveje",
"language": "Sprog",
@@ -1422,10 +1442,28 @@
"loop_videos_description": "Aktivér for at genafspille videoer automatisk i detaljeret visning.",
"main_branch_warning": "Du bruger en udviklingsversion; vi anbefaler kraftigt at bruge en udgivelsesversion!",
"main_menu": "Hovedmenu",
"maintenance_action_restore": "Genopretter database",
"maintenance_description": "Immich er blevet sat i <link>vedligeholdelsestilstand</link>.",
"maintenance_end": "Afslut vedligeholdelsestilstand",
"maintenance_end_error": "Vedligeholdelsestilstand kunne ikke afsluttes.",
"maintenance_logged_in_as": "Aktuelt logget ind som {user}",
"maintenance_restore_from_backup": "Genskab fra sikkerhedskopi",
"maintenance_restore_library": "Genskab dit bibliotek",
"maintenance_restore_library_confirm": "Hvis dette ser korrekt ud, så fortsæt for at genoprette fra en sikkerhedskopi!",
"maintenance_restore_library_description": "Genopretter database",
"maintenance_restore_library_folder_has_files": "{folder} har {count, plural, one {mappe} other {mapper}}",
"maintenance_restore_library_folder_no_files": "{folder} mangler filer!",
"maintenance_restore_library_folder_pass": "læs- og skrivbar",
"maintenance_restore_library_folder_read_fail": "ikke læsbar",
"maintenance_restore_library_folder_write_fail": "ikke skrivbar",
"maintenance_restore_library_hint_missing_files": "Du mangler måske vigtige filer",
"maintenance_restore_library_hint_regenerate_later": "Du kan genindstille disse senere, i indstillinger",
"maintenance_restore_library_hint_storage_template_missing_files": "Bruger du en lagringsskabelon? Du mangler måske nogle filer",
"maintenance_restore_library_loading": "Indlæser integritetskontroller og heuristikker …",
"maintenance_task_backup": "Laver en backup af den eksisterende database …",
"maintenance_task_migrations": "Kører migration af database…",
"maintenance_task_restore": "Genskaber den valgte backup…",
"maintenance_task_rollback": "Genoprettelse slog fejl, ruller tilbage til genoprettelsespunkt…",
"maintenance_title": "Midlertidigt Utilgængelig",
"make": "Producent",
"manage_geolocation": "Administrer placering",
@@ -1545,7 +1583,7 @@
"no_albums_with_name_yet": "Det ser ud til, at du ikke har noget album med dette navn endnu.",
"no_albums_yet": "Det ser ud til, at du ikke har nogen album endnu.",
"no_archived_assets_message": "Arkivér billeder og videoer for at gemme dem væk fra din billedoversigt",
"no_assets_message": "KLIK FOR AT UPLOADE DIT FØRSTE BILLEDE",
"no_assets_message": "Klik for at uploade dit første foto",
"no_assets_to_show": "Ingen elementer at vise",
"no_cast_devices_found": "Ingen Cast-enheder fundet",
"no_checksum_local": "Ingen checksum tilgængelig kan ikke hente lokale objekter",
@@ -1687,7 +1725,7 @@
"photos_from_previous_years": "Billeder fra tidligere år",
"photos_only": "Kun fotos",
"pick_a_location": "Vælg et sted",
"pick_custom_range": "Brugerdefineret periode",
"pick_custom_range": "Brugerdefineret interval",
"pick_date_range": "Vælg et datointerval",
"pin_code_changed_successfully": "Ændring af PIN kode lykkedes",
"pin_code_reset_successfully": "Nulstilling af PIN kode lykkedes",
@@ -1766,6 +1804,7 @@
"rating_clear": "Nulstil vurdering",
"rating_count": "{count, plural, one {# stjerne} other {# stjerner}}",
"rating_description": "Vis EXIF-klassificeringen i infopanelet",
"rating_set": "Vurdering sat til {rating, plural, one {# stjerne} other {# stjerner}}",
"reaction_options": "Reaktionsindstillinger",
"read_changelog": "Læs ændringslog",
"readonly_mode_disabled": "Skrivebeskyttet tilstand deaktiveret",
@@ -1865,11 +1904,11 @@
"saved_settings": "Gemte indstillinger",
"say_something": "Skriv noget",
"scaffold_body_error_occurred": "Der opstod en fejl",
"scan": "Scan",
"scan": "Skan",
"scan_all_libraries": "Skan alle biblioteker",
"scan_library": "Skan",
"scan_settings": "Skanningsindstillinger",
"scanning": "Scanning",
"scanning": "Skanner",
"scanning_for_album": "Skanner efter albummer...",
"search": "Søg",
"search_albums": "Søg i albummer",
@@ -2042,7 +2081,7 @@
"shared_link_edit_expire_after_option_year": "{count} år",
"shared_link_edit_password_hint": "Indtast kodeordet",
"shared_link_edit_submit_button": "Opdater link",
"shared_link_error_server_url_fetch": "Kan ikke finde server URL",
"shared_link_error_server_url_fetch": "Kan ikke hente server URL",
"shared_link_expires_day": "Udløber om {count} dag",
"shared_link_expires_days": "Udløber om {count} dage",
"shared_link_expires_hour": "Udløber om {count} time",
@@ -2129,7 +2168,7 @@
"start_date_before_end_date": "Startdato skal ligge før slutdato",
"state": "Stat",
"status": "Status",
"stop_casting": "Stop casting",
"stop_casting": "Stop med at caste",
"stop_motion_photo": "Stopmotionbillede",
"stop_photo_sharing": "Stop med at dele dine billeder?",
"stop_photo_sharing_description": "{partner} vil ikke længere kunne tilgå dine billeder.",
@@ -2182,6 +2221,7 @@
"theme_setting_theme_subtitle": "Vælg appens temaindstilling",
"theme_setting_three_stage_loading_subtitle": "Tre-trins indlæsning kan øge ydeevnen, men kan ligeledes føre til højere netværksbelastning",
"theme_setting_three_stage_loading_title": "Slå tre-trins indlæsning til",
"then": "Siden",
"they_will_be_merged_together": "De vil blive slået sammen",
"third_party_resources": "Tredjepartsressourcer",
"time": "Tid",
@@ -2266,6 +2306,7 @@
"upload_details": "Upload detaljer",
"upload_dialog_info": "Vil du sikkerhedskopiere de(t) valgte element(er) til serveren?",
"upload_dialog_title": "Upload element",
"upload_error_with_count": "Upload-fejl for {count, plural, one {# objekt} other {# objekter}}",
"upload_errors": "Upload afsluttet med {count, plural, one {# fejl} other {# fejl}}. Opdater siden for at se nye uploadaktiver.",
"upload_finished": "Upload fuldført",
"upload_progress": "Resterende {remaining, number} - Behandlet {processed, number}/{total, number}",

View File

@@ -526,8 +526,8 @@
"allowed": "Erlaubt",
"alt_text_qr_code": "QR-Code Bild",
"always_keep": "Immer behalten",
"always_keep_photos_hint": "Speicher freigeben wird alle Fotos auf dem Gerät behalten",
"always_keep_videos_hint": "Speicher freigeben wird alle Videos auf dem Gerät behalten",
"always_keep_photos_hint": "Speicherfreigabe wird alle Fotos auf dem Gerät behalten.",
"always_keep_videos_hint": "Speicherfreigabe wird alle Videos auf dem Gerät behalten.",
"anti_clockwise": "Gegen den Uhrzeigersinn",
"api_key": "API-Schlüssel",
"api_key_description": "Dieser Wert wird nur einmal angezeigt. Bitte kopiere ihn, bevor du das Fenster schließt.",
@@ -537,7 +537,7 @@
"app_bar_signout_dialog_content": "Bist du dir sicher, dass du dich abmelden möchtest?",
"app_bar_signout_dialog_ok": "Ja",
"app_bar_signout_dialog_title": "Abmelden",
"app_download_links": "App Download Links",
"app_download_links": "App Download-Links",
"app_settings": "App-Einstellungen",
"app_stores": "App Stores",
"app_update_available": "App Update verfügbar",
@@ -572,6 +572,9 @@
"asset_list_layout_sub_title": "Layout",
"asset_list_settings_subtitle": "Einstellungen für das Fotogitter-Layout",
"asset_list_settings_title": "Fotogitter",
"asset_not_found_on_device_android": "Datei auf Gerät nicht gefunden",
"asset_not_found_on_device_ios": "Datei auf Gerät nicht gefunden. Wenn Du iCloud verwendest, kann die Datei möglicherweise aufgrund schlechter Dateispeicherung von iCloud nicht auffindbar sein",
"asset_not_found_on_icloud": "Datei in iCloud nicht gefunden. Die Datei kann möglicherweise aufgrund schlechter Dateispeicherung in iCloud nicht auffindbar sein",
"asset_offline": "Datei offline",
"asset_offline_description": "Diese externe Datei ist nicht mehr auf dem Datenträger vorhanden. Bitte wende dich an deinen Immich-Administrator, um Hilfe zu erhalten.",
"asset_restored_successfully": "Datei erfolgreich wiederhergestellt",
@@ -607,14 +610,14 @@
"assets_were_part_of_album_count": "{count, plural, one {# Datei ist} other {# Dateien sind}} bereits im Album vorhanden",
"assets_were_part_of_albums_count": "{count, plural, one {Datei war} other {Dateien waren}} bereits in den Alben",
"authorized_devices": "Verwendete Geräte",
"automatic_endpoint_switching_subtitle": "Verbinden Sie sich lokal über ein bestimmtes WLAN, wenn es verfügbar ist, und verwenden Sie andere Verbindungsmöglichkeiten anderswo",
"automatic_endpoint_switching_subtitle": "Verbinden Sie sich lokal über ein bestimmtes WiFi, wenn es verfügbar ist, und verwenden Sie andere Verbindungsmöglichkeiten",
"automatic_endpoint_switching_title": "Automatische URL-Umschaltung",
"autoplay_slideshow": "Automatische Diashow",
"back": "Zurück",
"back_close_deselect": "Zurück, Schließen oder Abwählen",
"background_backup_running_error": "Sicherung läuft im Hintergrund. Manuelle Sicherung kann nicht gestartet werden",
"background_location_permission": "Hintergrund Standortfreigabe",
"background_location_permission_content": "Um im Hintergrund zwischen den Netzwerken wechseln zu können, muss Immich *immer* Zugriff auf den genauen Standort haben, damit die App den Namen des WLAN-Netzwerks ermitteln kann",
"background_location_permission_content": "Um im Hintergrund zwischen den Netzwerken wechseln zu können, muss Immich *immer* Zugriff auf den genauen Standort haben, damit die App den Namen des WiFi-Netzwerks ermitteln kann",
"background_options": "Hintergrund Optionen",
"backup": "Sicherung",
"backup_album_selection_page_albums_device": "Alben auf dem Gerät ({count})",
@@ -649,7 +652,7 @@
"backup_controller_page_background_is_on": "Automatische Sicherung im Hintergrund ist aktiviert",
"backup_controller_page_background_turn_off": "Hintergrundservice ausschalten",
"backup_controller_page_background_turn_on": "Hintergrundservice einschalten",
"backup_controller_page_background_wifi": "Nur im WLAN",
"backup_controller_page_background_wifi": "Nur im WiFi",
"backup_controller_page_backup": "Sicherung",
"backup_controller_page_backup_selected": "Ausgewählt: ",
"backup_controller_page_backup_sub": "Gesicherte Fotos und Videos",
@@ -751,7 +754,7 @@
"charging_requirement_mobile_backup": "Backup im Hintergrund erfordert Aufladen des Geräts",
"check_corrupt_asset_backup": "Auf beschädigte Asset-Backups überprüfen",
"check_corrupt_asset_backup_button": "Überprüfung durchführen",
"check_corrupt_asset_backup_description": "Führe diese Prüfung nur mit aktivierten WLAN durch, nachdem alle Dateien gesichert worden sind. Dieser Vorgang kann ein paar Minuten dauern.",
"check_corrupt_asset_backup_description": "Führe diese Prüfung nur mit aktivierten WiFi durch, nachdem alle Dateien gesichert worden sind. Dieser Vorgang kann ein paar Minuten dauern.",
"check_logs": "Logs prüfen",
"checksum": "Prüfsumme",
"choose_matching_people_to_merge": "Wähle passende Personen zum Zusammenführen",
@@ -779,6 +782,8 @@
"client_cert_import": "Importieren",
"client_cert_import_success_msg": "Client Zertifikat wurde importiert",
"client_cert_invalid_msg": "Ungültige Zertifikatsdatei oder falsches Passwort",
"client_cert_password_message": "Passwort für dieses Zertifikat angeben",
"client_cert_password_title": "Passwort des Zertifikats",
"client_cert_remove_msg": "Client Zertifikat wurde entfernt",
"client_cert_subtitle": "Unterstützt nur das PKCS12 (.p12, .pfx) Format. Zertifikatsimporte oder -entfernungen sind nur vor dem Login möglich",
"client_cert_title": "SSL-Client-Zertifikat [Experimentell]",
@@ -988,12 +993,17 @@
"edit_title": "Titel bearbeiten",
"edit_user": "Nutzer bearbeiten",
"edit_workflow": "Workflow bearbeiten",
"editor": "Bearbeiter",
"editor": "Bearbeiten",
"editor_close_without_save_prompt": "Die Änderungen werden nicht gespeichert",
"editor_close_without_save_title": "Editor schließen?",
"editor_confirm_reset_all_changes": "Alle Änderungen zurücksetzen?",
"editor_flip_horizontal": "horizontal spiegeln",
"editor_flip_vertical": "vertikal spiegeln",
"editor_discard_edits_confirm": "Änderungen verwerfen",
"editor_discard_edits_prompt": "Es liegen ungespeicherte Änderungen vorhanden. Sicher, dass diese verworfen werden sollen?",
"editor_discard_edits_title": "Änderungen verwerfen?",
"editor_edits_applied_error": "Änderungen konnten nicht angewendet werden",
"editor_edits_applied_success": "Änderungen erfolgreich angewendet",
"editor_flip_horizontal": "Horizontal spiegeln",
"editor_flip_vertical": "Vertikal spiegeln",
"editor_orientation": "Ausrichtung",
"editor_reset_all_changes": "Änderungen zurücksetzen",
"editor_rotate_left": "Um 90° gegen den Uhrzeigersinn drehen",
@@ -1009,7 +1019,7 @@
"enabled": "Aktiviert",
"end_date": "Enddatum",
"enqueued": "Eingereiht",
"enter_wifi_name": "WLAN-Name eingeben",
"enter_wifi_name": "WiFi-Name eingeben",
"enter_your_pin_code": "PIN-Code eingeben",
"enter_your_pin_code_subtitle": "Gib deinen PIN-Code ein, um auf den gesperrten Ordner zuzugreifen",
"error": "Fehler",
@@ -1192,8 +1202,9 @@
"features": "Funktionen",
"features_in_development": "Feature in Entwicklung",
"features_setting_description": "Funktionen der App verwalten",
"file_name": "Dateiname: {file_name}",
"file_name_or_extension": "Dateiname oder -erweiterung",
"file_name_text": "Dateiname",
"file_name_with_value": "Dateiname: {file_name}",
"file_size": "Dateigröße",
"filename": "Dateiname",
"filetype": "Dateityp",
@@ -1221,7 +1232,7 @@
"geolocation_instruction_location": "Klicke auf eine Datei mit GPS Koordinaten um diesen Standort zu verwenden oder wähle einen Standort direkt auf der Karte",
"get_help": "Hilfe erhalten",
"get_people_error": "Fehler beim Laden der Personen",
"get_wifiname_error": "WLAN-Name konnte nicht ermittelt werden. Vergewissere dich, dass die erforderlichen Berechtigungen erteilt wurden und du mit einem WLAN-Netzwerk verbunden bist",
"get_wifiname_error": "WiFi-Name konnte nicht ermittelt werden. Vergewissere dich, dass die erforderlichen Berechtigungen erteilt wurden und du mit einem WiFi-Netzwerk verbunden bist",
"getting_started": "Erste Schritte",
"go_back": "Zurück",
"go_to_folder": "Gehe zu Ordner",
@@ -1385,7 +1396,7 @@
"local_network_sheet_info": "Die App stellt über diese URL eine Verbindung zum Server her, wenn sie das angegebene WLAN-Netzwerk verwendet",
"location": "Standort",
"location_permission": "Standort Genehmigung",
"location_permission_content": "Um die automatische Umschaltfunktion nutzen zu können, benötigt Immich genaue Standortberechtigung, damit es den Namen des aktuellen WLAN-Netzwerks ermitteln kann",
"location_permission_content": "Um die automatische Umschaltfunktion nutzen zu können, benötigt Immich genaue Standortberechtigung, damit es den Namen des aktuellen WiFi-Netzwerks ermitteln kann",
"location_picker_choose_on_map": "Auf der Karte auswählen",
"location_picker_latitude_error": "Gültigen Breitengrad eingeben",
"location_picker_latitude_hint": "Breitengrad eingeben",
@@ -1902,7 +1913,7 @@
"search": "Suche",
"search_albums": "Album suchen",
"search_by_context": "Suche nach Kontext",
"search_by_description": "Nach Beschreibung suchen",
"search_by_description": "Suche nach Beschreibung",
"search_by_description_example": "Wandern in Sapa",
"search_by_filename": "Suche nach Dateiname oder -erweiterung",
"search_by_filename_example": "z.B. IMG_1234.JPG oder PNG",
@@ -2200,7 +2211,7 @@
"theme_setting_asset_list_storage_indicator_title": "Fortschrittsbalken der Sicherung auf dem Vorschaubild",
"theme_setting_asset_list_tiles_per_row_title": "Anzahl der Elemente pro Reihe ({count})",
"theme_setting_colorful_interface_subtitle": "Primärfarbe auf App-Hintergrund anwenden.",
"theme_setting_colorful_interface_title": "Farbige UI-Oberfläche",
"theme_setting_colorful_interface_title": "Farbige Benutzeroberfläche",
"theme_setting_image_viewer_quality_subtitle": "Einstellen der Qualität des Detailbildbetrachters",
"theme_setting_image_viewer_quality_title": "Qualität des Bildbetrachters",
"theme_setting_primary_color_subtitle": "Farbauswahl für primäre Aktionen und Akzente.",
@@ -2295,6 +2306,7 @@
"upload_details": "Upload Details",
"upload_dialog_info": "Willst du die ausgewählten Elemente auf dem Server sichern?",
"upload_dialog_title": "Element hochladen",
"upload_error_with_count": "Uploadfehler für {count, plural, one {# asset} other {# assets}}",
"upload_errors": "Hochladen mit {count, plural, one {# Fehler} other {# Fehlern}} abgeschlossen, aktualisiere die Seite, um neu hochgeladene Dateien zu sehen.",
"upload_finished": "Upload fertig",
"upload_progress": "{remaining, number} verbleibend - {processed, number}/{total, number} verarbeitet",
@@ -2372,7 +2384,7 @@
"welcome": "Willkommen",
"welcome_to_immich": "Willkommen bei Immich",
"width": "Breite",
"wifi_name": "WLAN-Name",
"wifi_name": "WiFi-Name",
"workflow_delete_prompt": "Bist du sicher, dass du diesen Workflow löschen willst?",
"workflow_deleted": "Workflow gelöscht",
"workflow_description": "Workflow-Beschreibung",
@@ -2391,7 +2403,7 @@
"years_ago": "Vor {years, plural, one {einem Jahr} other {# Jahren}}",
"yes": "Ja",
"you_dont_have_any_shared_links": "Du hast keine geteilten Links",
"your_wifi_name": "Dein WLAN-Name",
"your_wifi_name": "Dein WiFi-Name",
"zero_to_clear_rating": "drücke 0 um die Dateibewertung zurückzusetzen",
"zoom_image": "Bild vergrößern",
"zoom_to_bounds": "Auf Grenzen zoomen"

View File

@@ -5,12 +5,12 @@
"acknowledge": "Bestätige",
"action": "Aktion",
"action_common_update": "Update",
"action_description": "Eine Reihe von Aktionen, die an den gefilterten Assets ausgeführt werden sollen",
"action_description": "Es paar Aktione, wo a de gfilterete Assets usgführt wärde sölled",
"actions": "Aktione",
"active": "Aktiv",
"active_count": "Aktivi: {count}",
"activity": "Aktivität",
"activity_changed": "Aktivität ist {enabled, select, true {aktiviert} other {deaktiviert}}",
"activity_changed": "Aktivität isch {enabled, select, true {aktiviert} other {deaktiviert}}",
"add": "Hinzuefüegä",
"add_a_description": "Beschriibig hinzuefüege",
"add_a_location": "Standort hinzuefüege",
@@ -18,41 +18,42 @@
"add_a_title": "Titel hinzuefüege",
"add_action": "Aktion hinzuefüege",
"add_action_description": "Aklicke um en Aktion dure zfüehre",
"add_assets": "Assets hinzufüege",
"add_birthday": "Geburtstag hinzuefüege",
"add_endpoint": "Endpunkt hinzuefüge",
"add_exclusion_pattern": "Exklusions muster hinzuefüege",
"add_exclusion_pattern": "Uuschlussmuster hinzuefüege",
"add_filter": "Filter hinzuefüge",
"add_filter_description": "Klicken, um eine Filterbedingung hinzuzufügen",
"add_filter_description": "Klicke, um e Filterbedingig hinzuezfüege",
"add_location": "Standort hinzuefüege",
"add_more_users": "Meh Benutzer hinzuefüege",
"add_partner": "Partner hinzufügen",
"add_partner": "Partner hinzueege",
"add_path": "Pfad hinzuefüege",
"add_photos": "Föteli hinzuefüege",
"add_tag": "Tag hinzufügen",
"add_tag": "Tag hinzueege",
"add_to": "Hinzuefüege zu …",
"add_to_album": "Zum Album hinzuefüege",
"add_to_album_bottom_sheet_added": "Zu {album} hinzugefügt",
"add_to_album_bottom_sheet_already_exists": "Bereits in {album}",
"add_to_album_bottom_sheet_added": "Zu {album} hinzuegegt",
"add_to_album_bottom_sheet_already_exists": "Scho in {album}",
"add_to_album_bottom_sheet_some_local_assets": "Es hend es paar lokali Dateie nöd chöne im Album hinzuegfüegt werde",
"add_to_album_toggle": "Auswahl umschalten für {album}",
"add_to_album_toggle": "Uuswahl umschalte für {album}",
"add_to_albums": "Zu Albe hinzuefüege",
"add_to_albums_count": "Zu Alben hinzufügen ({count})",
"add_to_albums_count": "Zu Albe hinzueege ({count})",
"add_to_bottom_bar": "Hinzuefüege zu",
"add_to_shared_album": "Zum teilte Album hinzuefüege",
"add_upload_to_stack": "Upload zum Stack hinzuefüege",
"add_url": "URL hinzuefüege",
"add_workflow_step": "Workflow-Schritt hinzufügen",
"add_workflow_step": "Workflow-Schritt hinzueege",
"added_to_archive": "Is Archiv verschobe",
"added_to_favorites": "Zu dine Favoritä hinzuegfüegt",
"added_to_favorites_count": "{count, number} zu Favoriten hinzugefügt",
"added_to_favorites_count": "{count, number} zu Favorite hinzuegegt",
"admin": {
"add_exclusion_pattern_description": "Ausschlussmuster hinzufügen. Platzhalter, wie *, **, und ? werden unterstützt. Um alle Dateien in einem Verzeichnis namens „Raw\" zu ignorieren, „**/Raw/**“ verwenden. Um alle Dateien zu ignorieren, die auf „.tif“ enden, „**/*.tif“ verwenden. Um einen absoluten Pfad zu ignorieren, „/pfad/zum/ignorieren/**“ verwenden.",
"add_exclusion_pattern_description": "Uusschlussmuster hinzuefüge. Platzhalter, wie *, **, und ? wärded understützt. Zum all Dateie i eim Verzeichnis namens „Raw\" ignoriere, „**/Raw/**“ verwände. Zum all Dateien ignorieren, wo uf „.tif“ änded, „**/*.tif“ verwände. Zum en absolute Pfad ignoriere, „/pfad/zum/ignoriere/**“ verwände.",
"admin_user": "Admin Benutzer",
"asset_offline_description": "Diese Datei einer externen Bibliothek befindet sich nicht mehr auf der Festplatte und wurde in den Papierkorb verschoben. Falls die Datei innerhalb der Bibliothek verschoben wurde, überprüfe deine Zeitleiste auf die neue entsprechende Datei. Um diese Datei wiederherzustellen, stelle bitte sicher, dass Immich auf den unten stehenden Dateipfad zugreifen kann und scanne die Bibliothek.",
"asset_offline_description": "Die Datei vonere externe Bibliothek isch nümme uf de Festplatte und isch in Papierchorb verschobe worde. Falls die Datei innerhalb vo de Bibliothek verschoben worde isch, überprüf dini Ziitleiste uf die neui entsprechendi Datei. Zum die Datei wiederherstelle, stell bitte sicher, dass Immich uf de unde stehendi Dateipfad chan zuegriife und scann d'Bibliothek.",
"authentication_settings": "Authentifizierigs Iistellige",
"authentication_settings_description": "Passwort, OAuth und anderi Authentifizierigseinstellige verwalte",
"authentication_settings_disable_all": "Bisch sicher, dass du alli Login-Methodä wotsch deaktivierä? S Login isch denn komplett deaktiviert.",
"authentication_settings_reenable": "Nutze einen <link>Server-Befehl</link> zur Reaktivierung.",
"authentication_settings_reenable": "Bruuch ein <link>Server-Befehl</link> zum reaktiviere.",
"background_task_job": "Hintergrund Ufgabä",
"backup_database": "Datenbank-Dump aalege",
"backup_database_enable_description": "Datenbank-Dumps aktiviere",
@@ -72,15 +73,15 @@
"confirm_delete_library_assets": "Bisch sicher, dass du die Bibliothek wotsch lösche? Das löscht {count, plural, one {# enthaltenes Asset} other {alli # enthaltene Assets}} us Immich und chan nöd rückgängig gmacht werde. D Dateie bliibed uf em Dateträger.",
"confirm_email_below": "Zum bestätige bitte \"{email}\" une iitippe",
"confirm_reprocess_all_faces": "Bisch sicher, dass du alli Gsichter neu verarbeite wotsch? Däbii werde au benannti Persone glöscht.",
"confirm_user_password_reset": "Bist du sicher, dass du das Passwort für {user} zurücksetzen möchtest?",
"confirm_user_pin_code_reset": "Bist du sicher, dass du den PIN-Code von {user} zurücksetzen möchtest?",
"confirm_user_password_reset": "Bisch sicher, dass du s Passwort für {user} möchtisch zruggsetze?",
"confirm_user_pin_code_reset": "Bisch sicher, dass du de PIN-Code vo {user} möchtisch zruggsetze?",
"copy_config_to_clipboard_description": "Kopiere die aktuelle Systemkonfiguration als JSON-Objekt in die Zwischenablage",
"create_job": "Aufgabe erstellen",
"cron_expression": "Cron-Zeitangabe",
"cron_expression_description": "Setze das Scanintervall im Cron-Format. Hilfe mit dem Format bietet dir dabei z. B. der <link>Crontab Guru</link>",
"cron_expression_presets": "Vorlagen für Cron-Ausdruck",
"create_job": "Uufgabe erstelle",
"cron_expression": "Cron-Ziitagabe",
"cron_expression_description": "Setz s Scanintervall im Cron-Format. Hilf mit däm Format bütet z. B. der <link>Crontab Guru</link>",
"cron_expression_presets": "Vorlage für Cron-Uusdruck",
"disable_login": "Login deaktiviere",
"duplicate_detection_job_description": "Diese Aufgabe führt das maschinelle Lernen für jede Datei aus, um Duplikate zu finden. Diese Aufgabe beruht auf der intelligenten Suche",
"duplicate_detection_job_description": "Die Uufgab füehrt s maschinelle Lärne für jedi Datei us, zum Duplikat finde. Die Uufgabe berueht uf de intelligente Suechi",
"exclusion_pattern_description": "Mit Ausschlussmustern können Dateien und Ordner beim Scannen Ihrer Bibliothek ignoriert werden. Dies ist nützlich, wenn du Ordner hast, die Dateien enthalten, die du nicht importieren möchtest, wie z. B. RAW-Dateien.",
"export_config_as_json_description": "Lade die aktuelle Systemkonfiguration als JSON-Datei herunter",
"external_libraries_page_description": "Externe Bibliotheksseite für Administratoren",

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