Compare commits

..

130 Commits

Author SHA1 Message Date
bo0tzz
fb72de0c90 tmp: build server image with lcms-enabled base 2025-09-20 13:28:33 +02:00
Jason Rasmussen
de57fecb69 fix(web): copy to clipboard on safari (#22217) 2025-09-19 17:44:18 -04:00
renovate[bot]
1e0b4fac04 fix(deps): update typescript-projects (#21510)
* fix(deps): update typescript-projects

* chore: downgrade dependencies

* chore: downgrade svelte-gestures

* fix: svelte/no-navigation-without-resolve

* fix: dumb test

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Zack Pollard <zack@futo.org>
Co-authored-by: Daniel Dietzler <mail@ddietzler.dev>
Co-authored-by: Jason Rasmussen <jason@rasm.me>
2025-09-19 12:29:01 -04:00
Jason Rasmussen
34339ea69f fix(web): show danger/warning when taken dates overlap (#22213) 2025-09-19 12:20:09 -04:00
Jason Rasmussen
6da039780e fix: automatically remove leading/trailing whitespace from search que… (#22214)
fix: automatically remove leading/trailing whitespace from search queries
2025-09-19 12:19:26 -04:00
Jason Rasmussen
3f2e0780d5 feat: availability checks (#22185) 2025-09-19 12:18:42 -04:00
Mert
52363cf0fb chore(mobile): ignore ios build folder (#22212)
ignore ios build folder
2025-09-19 09:50:24 -05:00
Jason Rasmussen
86df09a0e4 fix(mobile): smaller search page size (#22210) 2025-09-19 10:11:11 -04:00
shenlong
e1e24f3d60 fix: sqlite parameters limit (#22119)
* fix isNotIns

* fix isIns

---------

Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com>
2025-09-19 09:47:56 -04:00
Alex
33d76fb386 fix: download feedback (#22178)
* fix: download feedback

* chore: use FAB for asset viewer as well
2025-09-19 00:47:01 -05:00
Alex
642065f506 fix: get scrubber in search view working (#22175)
* feat: add option to disable snapping

* handle offset when there is no appbar
2025-09-19 00:20:09 -05:00
Jason Rasmussen
de897f6069 fix(web): do not upscale small pictures (#22191) 2025-09-18 22:28:06 -04:00
Jason Rasmussen
68f3ed89c5 chore: remove unused init service (#22188) 2025-09-19 01:11:45 +00:00
Sergey Katsubo
78516a97b3 chore(server): proper log context formatting (#22173)
* Fix log formatting for logger.error(..., error)

Rewrite it to avoid printing error msg in [context]

* Fix log formatting for logger.warn(..., error?.stack)

Rewrite it to avoid printing stack in [context]

* Fix log formatting for logger.debug(..., error.message);

Rewrite it to avoid printing error msg in [context]

* Print error msg instead of literal "Error"
2025-09-18 19:56:05 -04:00
Alex
b8a17c3c26 fix: disable scrubbing mode on drag ended (#22186) 2025-09-18 16:42:33 -05:00
Alex
e42886b767 fix: display thumbnail while scrubbing paused (#22164)
* fix: display thumbnail while scrubbing paused

* pr feedback

* pr feedback

* tune timeout
2025-09-18 20:59:58 +00:00
Alex
d36c26bf97 chore: refresh backup stats when entering backup page (#21977)
* chore: refresh backup stats when entering backup page

* check for success status

* remove logs

* remove sync remote when toggle the button

* show status immediately after navigating to screen

* pr feedback
2025-09-18 15:36:43 -05:00
Brandon Wees
dcbc266b83 chore: disable mise lockfile (#22182) 2025-09-18 15:44:33 -04:00
bo0tzz
c37d13691b feat: shared pre-job action (#20011) 2025-09-18 11:21:06 +02:00
Mert
9ae42106cc fix(mobile): stack row blocking gestures and not showing up (#21854) 2025-09-18 06:16:14 +00:00
Alex
28e9892ed3 fix: show thumbnail instantly when jumping to top of the page (#22163)
* fix: show thumbnail instantly when jumping to top of the page

* pr feedback
2025-09-18 05:26:39 +00:00
shenlong
532ec10d5f refactor: hashing service (#21997)
* download only backup selected assets

* android impl

* fix tests

* limit concurrent hashing to 16

* extension cleanup

* optimized hashing

* hash only selected albums

* remove concurrency limit

* address review comments

* log more info on failure

* add native cancellation

* small batch size on ios, large on android

* fix: get correct resources

* cleanup getResource

* ios better hash cancellation

* handle graceful cancellation android

* do not trigger multiple hashing ops

* ios: fix circular reference, improve cancellation

* kotlin: more cancellation checks

* no need to create result

* cancel previous task

* avoid race condition

* ensure cancellation gets called

* fix cancellation not happening

---------

Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com>
Co-authored-by: mertalev <101130780+mertalev@users.noreply.github.com>
Co-authored-by: Alex <alex.tran1502@gmail.com>
2025-09-17 23:42:37 -05:00
Alex
2411bf8374 fix: asset viewer background isn't shown (#22161)
* fix: asset viewer background isn't shown

* pr feedback
2025-09-17 23:26:16 -05:00
Mert
0b60cc8965 fix(mobile): thumbnail shimmering effect (#22158)
full opacity
2025-09-17 22:29:37 -05:00
Jason Rasmussen
2d816e89ad refactor(web): prefer modal manager (#22152) 2025-09-17 23:23:42 +02:00
Jason Rasmussen
eee94207ce refactor(web): album users modal (#22153) 2025-09-17 17:04:54 -04:00
Jason Rasmussen
dfa38ec3ef fix(web): download panel (#22150) 2025-09-17 15:40:11 -05:00
Jason Rasmussen
edc0698e2a refactor: album edit modal (#22151) 2025-09-17 16:34:12 -04:00
shenlong
0e987352bb fix: do not migrate existing users (#22146)
fix: do not migrate if already on 15+

Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com>
2025-09-17 13:20:43 -05:00
Jason Rasmussen
98ea3847e5 refactor: server-about-modal (#22138)
* refactor: server-about-modal

* fix: bits-ui scroll lock cleanup
2025-09-17 16:23:23 +00:00
shenlong
53c67f4d71 fix: show delete on device when asset has a local match (#22143)
* fix: show delete on device when asset has a local match

* change test description

---------

Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com>
2025-09-17 21:48:54 +05:30
Mert
20733bd7df fix(mobile): load original image (#22142)
load original image
2025-09-17 12:14:16 -04:00
Jason Rasmussen
11e72a0f35 refactor: text-primary (#22141) 2025-09-17 12:12:51 -04:00
Jason Rasmussen
53a6724039 refactor: hot module reload component (#22135) 2025-09-17 12:12:37 -04:00
Jason Rasmussen
0b20d1df9f feat(web): toggle theme shortcut (#22139) 2025-09-17 12:12:23 -04:00
Alex
6bb8903b05 chore: revert poll counts from DB rather than using callbacks from library (#22117) (#22140)
Revert "fix: poll counts from DB rather than using callbacks from library (#22117)"

This reverts commit 29fd981587.
2025-09-17 15:41:33 +00:00
Stewart Rand
26e0cb3eb4 fix: Refresh photo after updating featured photo (#21971)
fix: Refresh person photo after setting featured photo

Co-authored-by: Alex <alex.tran1502@gmail.com>
2025-09-17 10:22:26 -05:00
shenlong
a8f683ed15 chore(dep): bump flutter to 3.35.4 (#22129)
Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com>
2025-09-17 14:58:35 +00:00
Viktor Mykhailiv
4dfa011eef fix: initial size of bottom sheet (#22085) 2025-09-17 14:41:44 +00:00
Viktor Mykhailiv
0c0bec6ae2 fix: display album image in selection mode (#22087)
* fix: display album image in selection mode

* fix: align MultiSelectStatusButton to display instead of back button in album

* small styling tweak

---------

Co-authored-by: Alex <alex.tran1502@gmail.com>
2025-09-17 14:38:25 +00:00
shenlong
61c3f27fdc feat: add configurable backup on charging only and delay settings for android (#22114)
* feat: add configurable on charging only and delay

* Segmented and style the settings

---------

Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com>
Co-authored-by: Alex <alex.tran1502@gmail.com>
2025-09-17 14:13:49 +00:00
Alex
b2ca208dbb fix: ensure background worker is scheduled when the app is dismissed (#22032)
* fix: ensure background worker is scheduled when the app is dismissed

* remove logs

* fix: use native locks (#22081)

* fix: native locks

* use atomicints

* change count check

---------

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

---------

Co-authored-by: shenlong <139912620+shenlong-tanwen@users.noreply.github.com>
Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com>
2025-09-17 09:11:55 -05:00
shenlong
2e945281fc fix: beta migration check (#22092)
fix: beta migration

Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com>
2025-09-17 08:45:04 -05:00
shenlong
9ac120c772 chore: add mobile codeowner (#22130)
Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com>
2025-09-17 14:08:35 +02:00
Min Idzelis
e6e8ae7c74 chore: remove suppressed warnings (#22120)
chore: remove supressed warnings
2025-09-17 00:06:27 -04:00
shenlong
29fd981587 fix: poll counts from DB rather than using callbacks from library (#22117)
Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com>
2025-09-16 21:13:34 -05:00
Mert
585b74f233 chore(deps): bump flutter to 3.35.3 (#22054)
* bump flutter to 3.35.3

* migrate deprecated code

* linting

* disable custom_lint in ci

* disable custom_lint
2025-09-16 21:10:01 -05:00
Mert
f118bb7e08 fix(mobile): prevent concurrent refresh and processing tasks (#22111)
* task semaphore

* always call setTaskCompleted
2025-09-16 18:06:19 -04:00
renovate[bot]
1710230d61 chore(deps): update dependency @types/nodemailer to v7 (#22047)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-09-16 22:17:03 +01:00
Jason Rasmussen
2012b07645 refactor: admin settings (#22109) 2025-09-16 17:15:57 -04:00
renovate[bot]
a88a9a7d5e chore(deps): update dependency @faker-js/faker to v10 (#21514)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-09-16 21:13:09 +00:00
renovate[bot]
ae539dfdf3 chore(deps): update terraform cloudflare to v4.52.5 (#22044)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-09-16 22:01:44 +01:00
renovate[bot]
69bb8d834f chore(deps): update github-actions (#22041)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-09-16 21:59:58 +01:00
Jason Rasmussen
9693d07a8b refactor: components (#22106) 2025-09-16 16:58:47 -04:00
Jason Rasmussen
453b30069d chore: discord from simple icons (#22104) 2025-09-16 16:33:56 -04:00
Jason Rasmussen
c9daefccc4 refactor: loading spinner (#22103) 2025-09-16 16:22:13 -04:00
Jason Rasmussen
6ffd8e679e refactor: use immich/ui PasswordInput (#22099)
refactor: password-input
2025-09-16 16:09:09 -04:00
Daniel Dietzler
7fe2f19258 chore: migrate to UI lib icon (#22096) 2025-09-16 21:40:43 +02:00
Jason Rasmussen
dac545496e chore: bump immich/ui (#22100) 2025-09-16 15:39:56 -04:00
renovate[bot]
d5b112be53 chore(deps): update ghcr.io/immich-app/postgres:14-vectorchord0.3.0 docker digest to 11ced39 (#22037)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-09-16 21:38:14 +02:00
Jason Rasmussen
75322179fd refactor: more elements (#22095) 2025-09-16 15:01:23 -04:00
Jason Rasmussen
3f4b6a8e7c refactor: move more elements (#22093) 2025-09-16 14:47:38 -04:00
Jason Rasmussen
7ce1d73c20 refactor: move components/elements to elements/ (#22091) 2025-09-16 18:31:22 +00:00
Jason Rasmussen
2bf484c91c refactor: timeline components (#22089) 2025-09-16 14:01:12 -04:00
Alex
4e9bdd5e6c fix: storage indicator (#22077) 2025-09-16 12:46:48 -05:00
Jason Rasmussen
f05ef81c4f fix(web): issue with modal locking the page (#22079) 2025-09-16 12:46:09 -05:00
Jason Rasmussen
c21860fb97 refactor: rename timeline actions (#22086) 2025-09-16 13:37:01 -04:00
linux-universe
449368eee7 chore(docs): add an updated Podman/Quadlets community guide (#20744)
* chore(docs): update Podman/Quadlets instructions link to a more up to date repo

* Update community-guides.tsx: additional guide instead of replacing the other podman one

* fix community-guides.tsx: fixed podman handbook entry

* chore: linting

---------

Co-authored-by: Jason Rasmussen <jason@rasm.me>
2025-09-16 17:05:54 +00:00
Jason Rasmussen
31e098517d chore: rename asset-grid to timeline (#22084) 2025-09-16 13:05:09 -04:00
Jason Rasmussen
b9e2590752 chore: simplify (#22082) 2025-09-16 12:48:44 -04:00
Jason Rasmussen
41641ec000 chore: build sdk while server is starting (#22083) 2025-09-16 12:48:31 -04:00
Alex
8821c251c3 fix: navigate to time (#22078) 2025-09-16 11:40:31 -05:00
Jason Rasmussen
1d6b98ff86 chore: remove prepare-volumes (#22071) 2025-09-16 10:19:09 -04:00
bo0tzz
4d00261bc1 chore(mobile): translate missing strings (#22057) 2025-09-16 08:51:03 -05:00
Tom Laermans
df7ea4d8ea docs: add community immich-birthday and immich-stack projects (#21934) 2025-09-16 04:01:18 +00:00
bo0tzz
1e7cb1165f fix: add pnpm setup to fix-format worflow (#21805) 2025-09-15 23:57:58 -04:00
Alex
d9ef041b87 chore: remove beta wording and badges (#22040)
* chore: remove beta wordings and badges

* chore: remove beta wordings and badges
2025-09-15 22:55:29 -05:00
Alex
87a172ab0c fix: distance of segment label overlapsed scrubber label (#22043) 2025-09-15 22:55:07 -05:00
Jason Rasmussen
9e0553e0c4 fix(server): bulk edit rating (#21839) 2025-09-16 03:50:27 +00:00
uphillcheddar
a7addfece8 fix(oauth): omit blank pkce from url when not supported (#21976)
* fix(oauth): omit blank pkce from url when now pkce

* fix(oauth): use spread operator for pkce params

* chore: use first method

---------

Co-authored-by: Your Name <you@example.com>
Co-authored-by: Jason Rasmussen <jrasm91@gmail.com>
2025-09-16 03:48:33 +00:00
renovate[bot]
fda215f97f chore(deps): update dependency vite to v7.1.5 [security] (#21783)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-09-16 03:47:29 +00:00
Jason Rasmussen
5fad1fd899 chore: split Dockerfile (#22007) 2025-09-15 23:41:35 -04:00
Sergey Katsubo
880f2bc2c5 chore(docs): TypeORM error: force recommend v1.132.3 and avoid v1.136 (#22033)
* TypeORM error: force recommend v1.132.3 and avoid v1.136

* Add extra line break for clarity

* Fix formatting error: remove an asterisk

* chore: use admonitions

---------

Co-authored-by: Jason Rasmussen <jrasm91@gmail.com>
2025-09-16 03:29:12 +00:00
Stewart Rand
0f79e0c38e fix: Use CSS for uppercase text (#22011) 2025-09-15 23:28:42 -04:00
renovate[bot]
5fb0afb0d0 chore(deps): update ghcr.io/immich-app/postgres:14-vectorchord0.4.3-pgvectors0.2.0 docker digest to c44be5f (#22038)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-09-15 23:13:21 -04:00
renovate[bot]
4f4a50ac11 chore(deps): update dependency @types/node to ^22.18.1 (#22042)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-09-15 23:12:15 -04:00
Alex
3d883b27aa fix: sidebar link hightlight (#22035)
* fix: sidebar link hightlight

* check if current route start with href
2025-09-15 22:19:55 -04:00
Zack Pollard
01fddd58c6 chore: update ROCm image (#22034) 2025-09-15 20:42:17 -04:00
shenlong
81eb5ab40d fix: close menu anchor on navigation (#22021)
Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com>
2025-09-15 15:05:22 -05:00
Zack Pollard
8d849d226d chore: remove workflows that are now applied org-wide (#22019) 2025-09-15 19:16:11 +01:00
Alex
a9b82a8e32 chore: post release tasks (#22014) 2025-09-15 18:08:25 +00:00
immich-tofu[bot]
cc9e07401f chore: modify .github/workflows/org-zizmor.yml 2025-09-15 17:59:16 +00:00
immich-tofu[bot]
9b5f3552c0 chore: modify .github/workflows/org-zizmor.yml 2025-09-15 17:47:59 +00:00
immich-tofu[bot]
a52a3247d7 chore: modify .github/workflows/org-zizmor.yml 2025-09-15 17:28:11 +00:00
immich-tofu[bot]
c86c957860 chore: modify .github/workflows/org-pr-require-conventional-commit.yml 2025-09-15 17:27:51 +00:00
immich-tofu[bot]
eb15a2725a chore: modify .github/workflows/org-checks.yml 2025-09-15 17:26:57 +00:00
Weblate (bot)
b394046d2a chore(web): update translations (#21842)
Translate-URL: https://hosted.weblate.org/projects/immich/immich/be/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/de/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/es/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/eu/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/fr/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/gl/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/he/
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/lt/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/lv/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/mr/
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/ru/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/sl/
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/tr/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/uk/
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: Abhijeet Bonde <abhijeetbonde19@gmail.com>
Co-authored-by: Adrián Nieto Rodríguez <adrian.nieto7@gmail.com>
Co-authored-by: Alexander Lohnes <alex.lohnes@googlemail.com>
Co-authored-by: Dawider10 <dawider110@gmail.com>
Co-authored-by: DevServs <bonov@mail.ru>
Co-authored-by: Jordy H <jordy@hoebergen.net>
Co-authored-by: Marcelo Popper Costa <marcelo_popper@hotmail.com>
Co-authored-by: Matjaž T <matjaz@moj-svet.si>
Co-authored-by: Mārtiņš Bruņenieks <martinsb@gmail.com>
Co-authored-by: Nuno Rodrigues <nunogand@gmail.com>
Co-authored-by: Pavlogal <pavledosen.p@gmail.com>
Co-authored-by: Pazystamas <pazystamas@gmail.com>
Co-authored-by: Phantom0174 <darrenhsiou@gmail.com>
Co-authored-by: PontusÖsterlindh <pontus@osterlindh.com>
Co-authored-by: Sergey Katsubo <skatsubo@gmail.com>
Co-authored-by: Sylvain Pichon <service@spichon.fr>
Co-authored-by: TV Box <realceday.tvbox@gmail.com>
Co-authored-by: Taiki M <vexingly-many-mace@duck.com>
Co-authored-by: Urko Perez Azkarragaurizar <urkoperez16@gmail.com>
Co-authored-by: User 123456789 <user123456789@users.noreply.hosted.weblate.org>
Co-authored-by: Vegard Fladby <vegard@fladby.org>
Co-authored-by: Xo <xocodokie@users.noreply.hosted.weblate.org>
Co-authored-by: cube64 <204@tuta.io>
Co-authored-by: millallo <millallo@tiscali.it>
Co-authored-by: pyccl <changcongliang@163.com>
Co-authored-by: vzvl <lojewski.vitus@gmail.com>
2025-09-15 17:15:41 +00:00
github-actions
859b2451bb chore: version v1.142.1 2025-09-15 17:08:25 +00:00
Mert
b79a2eb6b9 chore(mobile): const platform checks (#21878)
* use `defaultTargetPlatform`

* extension

* formatting
2025-09-15 11:13:39 -04:00
Yaros
ee96b285f2 chore(mobile): minor changes to bottom sheet (#22008) 2025-09-15 10:09:27 -05:00
Alex
77340075f0 chore: making order of background tasks better (#21928)
* chore: making order of background tasks better

* chore: prevent action not running when returning from backup screen too soon after toggle backup
2025-09-15 10:07:41 -05:00
shenlong
5c06ec5e0b fix: move startInitialization to inside the doWork method (#21984)
fix: android background backup

Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com>
2025-09-15 10:06:30 -05:00
shenlong
dcee34095b fix: reset sqlite on beta migration (#20735)
reset sync stream on migration

Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com>
2025-09-14 16:30:25 -05:00
Alex
15f182902f fix: check if preferencesStore is defined (#21958) 2025-09-14 20:30:15 +00:00
shenlong
b26b452530 fix: do not listen for store updates in isolates (#21947)
* dispose store on isolate cleanup

* do not listen for store updates in isolates

---------

Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com>
Co-authored-by: Alex <alex.tran1502@gmail.com>
2025-09-14 14:50:17 -05:00
shenlong
2dcb32f7d0 chore: update background downloader (#21909)
Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com>
2025-09-14 14:44:48 -05:00
Brandon Wees
27d2f3efe2 feat: disable snapping when a timeline has less than 12 months (#21649)
* feat: disable snapping when a timeline has less than 12 months

* fix: disable placeholders when not snapping

also moved month constant to constants.dart

---------

Co-authored-by: Alex <alex.tran1502@gmail.com>
2025-09-14 19:24:52 +00:00
shenlong
d38468439b fix: complete does not destroy engine on close (#21943)
* fix: complete does not destroy engine on close

* reset flutterApi on cleanup

---------

Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com>
2025-09-14 14:17:12 -05:00
Alex
0166e99d90 chore: remove main timeline query watch throttle (#21942) 2025-09-14 02:09:07 -05:00
Alex
71e33e35dc chore: check before sync linked albums from websocket events (#21941) 2025-09-14 02:08:41 -05:00
Mert
a122d4b969 fix(mobile): double hero animation (#21927)
fix double hero animation
2025-09-13 16:47:07 -05:00
shenlong
dad81af6e3 fix: show view in timeline from search page (#21873)
Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com>
2025-09-12 22:44:31 -05:00
shenlong
ac6b42e1e8 fix: do not show stack action if there is only one selection (#21868)
Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com>
2025-09-12 22:43:51 -05:00
Stewart Rand
4059638151 fix: context menu jank (#21844)
* Fix issue with context menu jank by only applying overflow styling when transition is complete

* Remove comment

Co-authored-by: Alex <alex.tran1502@gmail.com>

---------

Co-authored-by: Alex <alex.tran1502@gmail.com>
2025-09-12 22:43:22 -05:00
Stewart Rand
1823a28e59 chore: improve date text slide-in transition (#21879)
* Make date text slide-in transition smooth

* fix: lint

---------

Co-authored-by: Alex Tran <alex.tran1502@gmail.com>
2025-09-13 03:42:42 +00:00
Stewart Rand
b6bf1852cd fix: keep adequate space around page title (#21881)
Keep space around page title
2025-09-12 22:42:25 -05:00
Stewart Rand
cdc26f2c7b fix: z-index of top bar on show/hide people view (#21847)
Fix z-index of top bar on show/hide people view
2025-09-12 22:32:50 -05:00
Alex
913b3789cc chore: simplify timeline switcher toggle (#21864)
chore: timeline switcher option simplify
2025-09-12 22:32:15 -05:00
Stewart Rand
994a770921 chore: improve context button accessibility (#21876)
Make context menu button filled on album list and faces page
2025-09-12 22:31:52 -05:00
Mert
17bbcdf584 chore(mobile): add debugPrint lint rule (#21872)
* add lint rule

* update usages

* stragglers

* use dcm

* formatting

* test ci

* Revert "test ci"

This reverts commit 8f864c4e4d.

* revert whitespace change
2025-09-12 18:56:00 -04:00
bo0tzz
23aa661324 fix: use mdq image with jq (#21860) 2025-09-12 21:46:39 +02:00
Min Idzelis
a10a946d1a fix: let dev docker compose service runs as root (#21579) 2025-09-12 16:20:41 +01:00
Stewart Rand
04c9531624 fix: format point count numbers on map view (#21848)
Format numbers on map view
2025-09-12 07:20:05 +00:00
Alex
d84cc450f1 chore: post release tasks (#21834) 2025-09-11 15:15:10 -05:00
github-actions
4153848c68 chore: version v1.142.0 2025-09-11 19:39:05 +00:00
Jason Rasmussen
f29230c8a6 fix(web): handle buckets before year 1000 (#21832) 2025-09-11 14:36:16 -05:00
Weblate (bot)
03af60e8eb chore(web): update translations (#21814)
Translate-URL: https://hosted.weblate.org/projects/immich/immich/ja/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/ru/
Translation: Immich/immich

Co-authored-by: DevServs <bonov@mail.ru>
Co-authored-by: Taiki M <vexingly-many-mace@duck.com>
2025-09-11 19:34:40 +00:00
bo0tzz
ae827e1406 fix: define call secrets in merge-translations (#21831) 2025-09-11 19:29:58 +00:00
shenlong
7893ac25fb fix: always use en locale for parsing timeline datetime (#21796)
Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com>
2025-09-11 14:20:39 -05:00
Alex
42a03f2556 fix: concurrency issue (#21830) 2025-09-11 19:02:03 +00:00
536 changed files with 16902 additions and 5953 deletions

View File

@@ -5,8 +5,7 @@
"immich-server", "immich-server",
"redis", "redis",
"database", "database",
"immich-machine-learning", "immich-machine-learning"
"init"
], ],
"dockerComposeFile": [ "dockerComposeFile": [
"../docker/docker-compose.dev.yml", "../docker/docker-compose.dev.yml",

View File

@@ -12,7 +12,6 @@ services:
- server_node_modules:/workspaces/immich/server/node_modules - server_node_modules:/workspaces/immich/server/node_modules
- web_node_modules:/workspaces/immich/web/node_modules - web_node_modules:/workspaces/immich/web/node_modules
- ${UPLOAD_LOCATION}/photos:/data - ${UPLOAD_LOCATION}/photos:/data
- ${UPLOAD_LOCATION}/photos/upload:/data/upload
- /etc/localtime:/etc/localtime:ro - /etc/localtime:/etc/localtime:ro
database: database:

View File

@@ -8,8 +8,7 @@ services:
- IMMICH_SERVER_URL=http://127.0.0.1:2283/ - IMMICH_SERVER_URL=http://127.0.0.1:2283/
volumes: !override volumes: !override
- ..:/workspaces/immich - ..:/workspaces/immich
- ${UPLOAD_LOCATION:-upload1-devcontainer-volume}${UPLOAD_LOCATION:+/photos}:/data - ${UPLOAD_LOCATION:-upload-devcontainer-volume}${UPLOAD_LOCATION:+/photos}:/data
- ${UPLOAD_LOCATION:-upload2-devcontainer-volume}${UPLOAD_LOCATION:+/photos/upload}:/data/upload
- /etc/localtime:/etc/localtime:ro - /etc/localtime:/etc/localtime:ro
- pnpm-store:/usr/src/app/.pnpm-store - pnpm-store:/usr/src/app/.pnpm-store
- server-node_modules:/usr/src/app/server/node_modules - server-node_modules:/usr/src/app/server/node_modules
@@ -24,9 +23,6 @@ services:
- coverage:/usr/src/app/web/coverage - coverage:/usr/src/app/web/coverage
immich-web: immich-web:
env_file: !reset [] env_file: !reset []
init:
env_file: !reset []
command: sh -c 'find /data -maxdepth 1 ! -path "/data/postgres" -type d -exec chown ${UID:-1000}:${GID:-1000} {} + 2>/dev/null || true; for path in /usr/src/app/.pnpm-store /usr/src/app/server/node_modules /usr/src/app/server/dist /usr/src/app/.github/node_modules /usr/src/app/cli/node_modules /usr/src/app/docs/node_modules /usr/src/app/e2e/node_modules /usr/src/app/open-api/typescript-sdk/node_modules /usr/src/app/web/.svelte-kit /usr/src/app/web/coverage /usr/src/app/node_modules /usr/src/app/web/node_modules; do [ -e "$$path" ] && chown -R ${UID:-1000}:${GID:-1000} "$$path" || true; done'
immich-machine-learning: immich-machine-learning:
env_file: !reset [] env_file: !reset []
database: database:
@@ -42,7 +38,5 @@ services:
redis: redis:
env_file: !reset [] env_file: !reset []
volumes: volumes:
# Node modules for each service to avoid conflicts and ensure consistent dependencies upload-devcontainer-volume:
upload1-devcontainer-volume:
upload2-devcontainer-volume:
postgres-devcontainer-volume: postgres-devcontainer-volume:

View File

@@ -32,24 +32,18 @@ jobs:
permissions: permissions:
contents: read contents: read
outputs: outputs:
should_run: ${{ steps.found_paths.outputs.mobile == 'true' || steps.should_force.outputs.should_force == 'true' }} should_run: ${{ steps.check.outputs.should_run }}
steps: steps:
- name: Checkout code - name: Check what should run
uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 id: check
with: uses: immich-app/devtools/actions/pre-job@24820aa4ef67959b0dcf69a438cccf00d7c7042b # pre-job-action-v1.0.1
persist-credentials: false
- id: found_paths
uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
with: with:
filters: | filters: |
mobile: mobile:
- 'mobile/**' - 'mobile/**'
workflow: force-filters: |
- '.github/workflows/build-mobile.yml' - '.github/workflows/build-mobile.yml'
- name: Check if we should force jobs to run force-events: 'workflow_call,workflow_dispatch'
id: should_force
run: echo "should_force=${{ steps.found_paths.outputs.workflow == 'true' || github.event_name == 'workflow_call' || github.event_name == 'workflow_dispatch' }}" >> "$GITHUB_OUTPUT"
build-sign-android: build-sign-android:
name: Build and sign Android name: Build and sign Android
@@ -57,7 +51,7 @@ jobs:
permissions: permissions:
contents: read contents: read
# Skip when PR from a fork # Skip when PR from a fork
if: ${{ !github.event.pull_request.head.repo.fork && github.actor != 'dependabot[bot]' && needs.pre-job.outputs.should_run == 'true' }} if: ${{ !github.event.pull_request.head.repo.fork && github.actor != 'dependabot[bot]' && fromJSON(needs.pre-job.outputs.should_run).mobile == true }}
runs-on: mich runs-on: mich
steps: steps:

View File

@@ -35,7 +35,7 @@ jobs:
needs: [get_body, should_run] needs: [get_body, should_run]
if: ${{ needs.should_run.outputs.should_run == 'true' }} if: ${{ needs.should_run.outputs.should_run == 'true' }}
container: container:
image: yshavit/mdq:0.9.0@sha256:4399483ca857fb1a7ed28a596f754c7373e358647de31ce14b79a27c91e1e35e image: ghcr.io/immich-app/mdq:main@sha256:d8ae47cf2e6cf4e2559bd57a60b73674fe44f897cba2c2bddff2987a05be10a4
outputs: outputs:
checked: ${{ steps.get_checkbox.outputs.checked }} checked: ${{ steps.get_checkbox.outputs.checked }}
steps: steps:

View File

@@ -50,7 +50,7 @@ jobs:
# Initializes the CodeQL tools for scanning. # Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL - name: Initialize CodeQL
uses: github/codeql-action/init@2d92b76c45b91eb80fc44c74ce3fce0ee94e8f9d # v3.30.0 uses: github/codeql-action/init@192325c86100d080feab897ff886c34abd4c83a3 # v3.30.3
with: with:
languages: ${{ matrix.language }} languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file. # If you wish to specify custom queries, you can do so here or in a config file.
@@ -63,7 +63,7 @@ jobs:
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below) # If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild - name: Autobuild
uses: github/codeql-action/autobuild@2d92b76c45b91eb80fc44c74ce3fce0ee94e8f9d # v3.30.0 uses: github/codeql-action/autobuild@192325c86100d080feab897ff886c34abd4c83a3 # v3.30.3
# Command-line programs to run using the OS shell. # Command-line programs to run using the OS shell.
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
@@ -76,6 +76,6 @@ jobs:
# ./location_of_script_within_repo/buildscript.sh # ./location_of_script_within_repo/buildscript.sh
- name: Perform CodeQL Analysis - name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@2d92b76c45b91eb80fc44c74ce3fce0ee94e8f9d # v3.30.0 uses: github/codeql-action/analyze@192325c86100d080feab897ff886c34abd4c83a3 # v3.30.3
with: with:
category: '/language:${{matrix.language}}' category: '/language:${{matrix.language}}'

View File

@@ -20,15 +20,11 @@ jobs:
permissions: permissions:
contents: read contents: read
outputs: outputs:
should_run_server: ${{ steps.found_paths.outputs.server == 'true' || steps.should_force.outputs.should_force == 'true' }} should_run: ${{ steps.check.outputs.should_run }}
should_run_ml: ${{ steps.found_paths.outputs.machine-learning == 'true' || steps.should_force.outputs.should_force == 'true' }}
steps: steps:
- name: Checkout code - name: Check what should run
uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 id: check
with: uses: immich-app/devtools/actions/pre-job@24820aa4ef67959b0dcf69a438cccf00d7c7042b # pre-job-action-v1.0.1
persist-credentials: false
- id: found_paths
uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
with: with:
filters: | filters: |
server: server:
@@ -38,14 +34,11 @@ jobs:
- 'i18n/**' - 'i18n/**'
machine-learning: machine-learning:
- 'machine-learning/**' - 'machine-learning/**'
workflow: force-filters: |
- '.github/workflows/docker.yml' - '.github/workflows/docker.yml'
- '.github/workflows/multi-runner-build.yml' - '.github/workflows/multi-runner-build.yml'
- '.github/actions/image-build' - '.github/actions/image-build'
force-events: 'workflow_dispatch,release'
- name: Check if we should force jobs to run
id: should_force
run: echo "should_force=${{ steps.found_paths.outputs.workflow == 'true' || github.event_name == 'workflow_dispatch' || github.event_name == 'release' }}" >> "$GITHUB_OUTPUT"
retag_ml: retag_ml:
name: Re-Tag ML name: Re-Tag ML
@@ -53,7 +46,7 @@ jobs:
permissions: permissions:
contents: read contents: read
packages: write packages: write
if: ${{ needs.pre-job.outputs.should_run_ml == 'false' && !github.event.pull_request.head.repo.fork }} if: ${{ fromJSON(needs.pre-job.outputs.should_run).machine-learning == false && !github.event.pull_request.head.repo.fork }}
runs-on: ubuntu-latest runs-on: ubuntu-latest
strategy: strategy:
matrix: matrix:
@@ -82,7 +75,7 @@ jobs:
permissions: permissions:
contents: read contents: read
packages: write packages: write
if: ${{ needs.pre-job.outputs.should_run_server == 'false' && !github.event.pull_request.head.repo.fork }} if: ${{ fromJSON(needs.pre-job.outputs.should_run).server == false && !github.event.pull_request.head.repo.fork }}
runs-on: ubuntu-latest runs-on: ubuntu-latest
strategy: strategy:
matrix: matrix:
@@ -108,7 +101,7 @@ jobs:
machine-learning: machine-learning:
name: Build and Push ML name: Build and Push ML
needs: pre-job needs: pre-job
if: ${{ needs.pre-job.outputs.should_run_ml == 'true' }} if: ${{ fromJSON(needs.pre-job.outputs.should_run).machine-learning == true }}
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
@@ -153,7 +146,7 @@ jobs:
server: server:
name: Build and Push Server name: Build and Push Server
needs: pre-job needs: pre-job
if: ${{ needs.pre-job.outputs.should_run_server == 'true' }} if: ${{ fromJSON(needs.pre-job.outputs.should_run).server == true }}
uses: immich-app/devtools/.github/workflows/multi-runner-build.yml@129aeda75a450666ce96e8bc8126652e717917a7 # multi-runner-build-workflow-0.1.1 uses: immich-app/devtools/.github/workflows/multi-runner-build.yml@129aeda75a450666ce96e8bc8126652e717917a7 # multi-runner-build-workflow-0.1.1
permissions: permissions:
contents: read contents: read

View File

@@ -18,32 +18,28 @@ jobs:
permissions: permissions:
contents: read contents: read
outputs: outputs:
should_run: ${{ steps.found_paths.outputs.docs == 'true' || steps.found_paths.outputs.open-api == 'true' || steps.should_force.outputs.should_force == 'true' }} should_run: ${{ steps.check.outputs.should_run }}
steps: steps:
- name: Checkout code - name: Check what should run
uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 id: check
with: uses: immich-app/devtools/actions/pre-job@24820aa4ef67959b0dcf69a438cccf00d7c7042b # pre-job-action-v1.0.1
persist-credentials: false
- id: found_paths
uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
with: with:
filters: | filters: |
docs: docs:
- 'docs/**' - 'docs/**'
workflow:
- '.github/workflows/docs-build.yml'
open-api: open-api:
- 'open-api/immich-openapi-specs.json' - 'open-api/immich-openapi-specs.json'
- name: Check if we should force jobs to run force-filters: |
id: should_force - '.github/workflows/docs-build.yml'
run: echo "should_force=${{ steps.found_paths.outputs.workflow == 'true' || github.event_name == 'release' || github.ref_name == 'main' }}" >> "$GITHUB_OUTPUT" force-events: 'release'
force-branches: 'main'
build: build:
name: Docs Build name: Docs Build
needs: pre-job needs: pre-job
permissions: permissions:
contents: read contents: read
if: ${{ needs.pre-job.outputs.should_run == 'true' }} if: ${{ fromJSON(needs.pre-job.outputs.should_run).docs == true }}
runs-on: ubuntu-latest runs-on: ubuntu-latest
defaults: defaults:
run: run:

View File

@@ -28,6 +28,9 @@ jobs:
token: ${{ steps.generate-token.outputs.token }} token: ${{ steps.generate-token.outputs.token }}
persist-credentials: true persist-credentials: true
- name: Setup pnpm
uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
- name: Setup Node - name: Setup Node
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with: with:

View File

@@ -1,8 +1,15 @@
name: Merge translations name: Merge translations
on: on:
workflow_call:
workflow_dispatch: workflow_dispatch:
workflow_call:
secrets:
PUSH_O_MATIC_APP_ID:
required: true
PUSH_O_MATIC_APP_KEY:
required: true
WEBLATE_TOKEN:
required: true
permissions: {} permissions: {}

View File

@@ -1,13 +0,0 @@
name: Org Checks
on:
pull_request_review:
pull_request:
jobs:
check-approvals:
name: Check for Team/Admin Review
uses: immich-app/devtools/.github/workflows/required-approval.yml@main
permissions:
pull-requests: read
contents: read

View File

@@ -0,0 +1,12 @@
name: PR Conventional Commit
on:
pull_request:
types: [opened, synchronize, reopened, edited]
jobs:
validate-pr-title:
name: Validate PR Title (conventional commit)
uses: immich-app/devtools/.github/workflows/shared-pr-require-conventional-commit.yml@main
permissions:
pull-requests: write

15
.github/workflows/org-zizmor.yml vendored Normal file
View File

@@ -0,0 +1,15 @@
name: Zizmor
on:
pull_request:
push:
branches: [main]
jobs:
zizmor:
name: Zizmor
uses: immich-app/devtools/.github/workflows/shared-zizmor.yml@main
permissions:
actions: read
contents: read
security-events: write

View File

@@ -1,19 +0,0 @@
name: PR Conventional Commit Validation
on:
pull_request:
types: [opened, synchronize, reopened, edited]
permissions: {}
jobs:
validate-pr-title:
runs-on: ubuntu-latest
permissions:
pull-requests: write
steps:
- name: PR Conventional Commit Validation
uses: ytanikin/PRConventionalCommits@b628c5a234cc32513014b7bfdd1e47b532124d98 # 1.3.0
with:
task_types: '["feat","fix","docs","test","ci","refactor","perf","chore","revert"]'
add_label: 'false'

View File

@@ -119,7 +119,7 @@ jobs:
name: release-apk-signed name: release-apk-signed
- name: Create draft release - name: Create draft release
uses: softprops/action-gh-release@72f2c25fcb47643c292f7107632f7a47c1df5cd8 # v2.3.2 uses: softprops/action-gh-release@6cbd405e2c4e67a21c47fa9e383d020e4e28b836 # v2.3.3
with: with:
draft: true draft: true
tag_name: ${{ env.IMMICH_VERSION }} tag_name: ${{ env.IMMICH_VERSION }}

View File

@@ -17,28 +17,23 @@ jobs:
permissions: permissions:
contents: read contents: read
outputs: outputs:
should_run: ${{ steps.found_paths.outputs.mobile == 'true' || steps.should_force.outputs.should_force == 'true' }} should_run: ${{ steps.check.outputs.should_run }}
steps: steps:
- name: Checkout code - name: Check what should run
uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 id: check
with: uses: immich-app/devtools/actions/pre-job@24820aa4ef67959b0dcf69a438cccf00d7c7042b # pre-job-action-v1.0.1
persist-credentials: false
- id: found_paths
uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
with: with:
filters: | filters: |
mobile: mobile:
- 'mobile/**' - 'mobile/**'
workflow: force-filters: |
- '.github/workflows/static_analysis.yml' - '.github/workflows/static_analysis.yml'
- name: Check if we should force jobs to run force-events: 'workflow_dispatch,release'
id: should_force
run: echo "should_force=${{ steps.found_paths.outputs.workflow == 'true' || github.event_name == 'release' }}" >> "$GITHUB_OUTPUT"
mobile-dart-analyze: mobile-dart-analyze:
name: Run Dart Code Analysis name: Run Dart Code Analysis
needs: pre-job needs: pre-job
if: ${{ needs.pre-job.outputs.should_run == 'true' }} if: ${{ fromJSON(needs.pre-job.outputs.should_run).mobile == true }}
runs-on: ubuntu-latest runs-on: ubuntu-latest
permissions: permissions:
contents: read contents: read
@@ -100,36 +95,10 @@ jobs:
- name: Run dart format - name: Run dart format
run: make format run: make format
- name: Run dart custom_lint # TODO: Re-enable after upgrading custom_lint
run: dart run custom_lint # - name: Run dart custom_lint
# run: dart run custom_lint
# TODO: Use https://github.com/CQLabs/dcm-action # TODO: Use https://github.com/CQLabs/dcm-action
- name: Run DCM - name: Run DCM
run: dcm analyze lib --fatal-style --fatal-warnings run: dcm analyze lib --fatal-style --fatal-warnings
zizmor:
name: zizmor
runs-on: ubuntu-latest
permissions:
security-events: write
contents: read
actions: read
steps:
- name: Checkout repository
uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
with:
persist-credentials: false
- name: Install the latest version of uv
uses: astral-sh/setup-uv@d4b2f3b6ecc6e67c4457f6d3e41ec42d3d0fcb86 # v5.4.2
- name: Run zizmor 🌈
run: uvx zizmor --format=sarif . > results.sarif
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Upload SARIF file
uses: github/codeql-action/upload-sarif@2d92b76c45b91eb80fc44c74ce3fce0ee94e8f9d # v3.30.0
with:
sarif_file: results.sarif
category: zizmor

View File

@@ -14,23 +14,11 @@ jobs:
permissions: permissions:
contents: read contents: read
outputs: outputs:
should_run_i18n: ${{ steps.found_paths.outputs.i18n == 'true' || steps.should_force.outputs.should_force == 'true' }} should_run: ${{ steps.check.outputs.should_run }}
should_run_web: ${{ steps.found_paths.outputs.web == 'true' || steps.should_force.outputs.should_force == 'true' }}
should_run_server: ${{ steps.found_paths.outputs.server == 'true' || steps.should_force.outputs.should_force == 'true' }}
should_run_cli: ${{ steps.found_paths.outputs.cli == 'true' || steps.should_force.outputs.should_force == 'true' }}
should_run_e2e: ${{ steps.found_paths.outputs.e2e == 'true' || steps.should_force.outputs.should_force == 'true' }}
should_run_mobile: ${{ steps.found_paths.outputs.mobile == 'true' || steps.should_force.outputs.should_force == 'true' }}
should_run_ml: ${{ steps.found_paths.outputs.machine-learning == 'true' || steps.should_force.outputs.should_force == 'true' }}
should_run_e2e_web: ${{ steps.found_paths.outputs.e2e == 'true' || steps.found_paths.outputs.web == 'true' || steps.should_force.outputs.should_force == 'true' }}
should_run_e2e_server_cli: ${{ steps.found_paths.outputs.e2e == 'true' || steps.found_paths.outputs.server == 'true' || steps.found_paths.outputs.cli == 'true' || steps.should_force.outputs.should_force == 'true' }}
should_run_.github: ${{ steps.found_paths.outputs['.github'] == 'true' || steps.should_force.outputs.should_force == 'true' }} # redundant to have should_force but if someone changes the trigger then this won't have to be changed
steps: steps:
- name: Checkout code - name: Check what should run
uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 id: check
with: uses: immich-app/devtools/actions/pre-job@24820aa4ef67959b0dcf69a438cccf00d7c7042b # pre-job-action-v1.0.1
persist-credentials: false
- id: found_paths
uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
with: with:
filters: | filters: |
i18n: i18n:
@@ -50,17 +38,16 @@ jobs:
- 'mobile/**' - 'mobile/**'
machine-learning: machine-learning:
- 'machine-learning/**' - 'machine-learning/**'
workflow:
- '.github/workflows/test.yml'
.github: .github:
- '.github/**' - '.github/**'
- name: Check if we should force jobs to run force-filters: |
id: should_force - '.github/workflows/test.yml'
run: echo "should_force=${{ steps.found_paths.outputs.workflow == 'true' || github.event_name == 'workflow_dispatch' }}" >> "$GITHUB_OUTPUT" force-events: 'workflow_dispatch'
server-unit-tests: server-unit-tests:
name: Test & Lint Server name: Test & Lint Server
needs: pre-job needs: pre-job
if: ${{ needs.pre-job.outputs.should_run_server == 'true' }} if: ${{ fromJSON(needs.pre-job.outputs.should_run).server == true }}
runs-on: ubuntu-latest runs-on: ubuntu-latest
permissions: permissions:
contents: read contents: read
@@ -97,7 +84,7 @@ jobs:
cli-unit-tests: cli-unit-tests:
name: Unit Test CLI name: Unit Test CLI
needs: pre-job needs: pre-job
if: ${{ needs.pre-job.outputs.should_run_cli == 'true' }} if: ${{ fromJSON(needs.pre-job.outputs.should_run).cli == true }}
runs-on: ubuntu-latest runs-on: ubuntu-latest
permissions: permissions:
contents: read contents: read
@@ -137,7 +124,7 @@ jobs:
cli-unit-tests-win: cli-unit-tests-win:
name: Unit Test CLI (Windows) name: Unit Test CLI (Windows)
needs: pre-job needs: pre-job
if: ${{ needs.pre-job.outputs.should_run_cli == 'true' }} if: ${{ fromJSON(needs.pre-job.outputs.should_run).cli == true }}
runs-on: windows-latest runs-on: windows-latest
permissions: permissions:
contents: read contents: read
@@ -172,7 +159,7 @@ jobs:
web-lint: web-lint:
name: Lint Web name: Lint Web
needs: pre-job needs: pre-job
if: ${{ needs.pre-job.outputs.should_run_web == 'true' }} if: ${{ fromJSON(needs.pre-job.outputs.should_run).web == true }}
runs-on: mich runs-on: mich
permissions: permissions:
contents: read contents: read
@@ -209,7 +196,7 @@ jobs:
web-unit-tests: web-unit-tests:
name: Test Web name: Test Web
needs: pre-job needs: pre-job
if: ${{ needs.pre-job.outputs.should_run_web == 'true' }} if: ${{ fromJSON(needs.pre-job.outputs.should_run).web == true }}
runs-on: ubuntu-latest runs-on: ubuntu-latest
permissions: permissions:
contents: read contents: read
@@ -243,7 +230,7 @@ jobs:
i18n-tests: i18n-tests:
name: Test i18n name: Test i18n
needs: pre-job needs: pre-job
if: ${{ needs.pre-job.outputs.should_run_i18n == 'true' }} if: ${{ fromJSON(needs.pre-job.outputs.should_run).i18n == true }}
runs-on: ubuntu-latest runs-on: ubuntu-latest
permissions: permissions:
contents: read contents: read
@@ -281,7 +268,7 @@ jobs:
e2e-tests-lint: e2e-tests-lint:
name: End-to-End Lint name: End-to-End Lint
needs: pre-job needs: pre-job
if: ${{ needs.pre-job.outputs.should_run_e2e == 'true' }} if: ${{ fromJSON(needs.pre-job.outputs.should_run).e2e == true }}
runs-on: ubuntu-latest runs-on: ubuntu-latest
permissions: permissions:
contents: read contents: read
@@ -320,7 +307,7 @@ jobs:
server-medium-tests: server-medium-tests:
name: Medium Tests (Server) name: Medium Tests (Server)
needs: pre-job needs: pre-job
if: ${{ needs.pre-job.outputs.should_run_server == 'true' }} if: ${{ fromJSON(needs.pre-job.outputs.should_run).server == true }}
runs-on: ubuntu-latest runs-on: ubuntu-latest
permissions: permissions:
contents: read contents: read
@@ -348,7 +335,7 @@ jobs:
e2e-tests-server-cli: e2e-tests-server-cli:
name: End-to-End Tests (Server & CLI) name: End-to-End Tests (Server & CLI)
needs: pre-job needs: pre-job
if: ${{ needs.pre-job.outputs.should_run_e2e_server_cli == 'true' }} if: ${{ fromJSON(needs.pre-job.outputs.should_run).e2e == true || fromJSON(needs.pre-job.outputs.should_run).server == true || fromJSON(needs.pre-job.outputs.should_run).cli == true }}
runs-on: ${{ matrix.runner }} runs-on: ${{ matrix.runner }}
permissions: permissions:
contents: read contents: read
@@ -396,7 +383,7 @@ jobs:
e2e-tests-web: e2e-tests-web:
name: End-to-End Tests (Web) name: End-to-End Tests (Web)
needs: pre-job needs: pre-job
if: ${{ needs.pre-job.outputs.should_run_e2e_web == 'true' }} if: ${{ fromJSON(needs.pre-job.outputs.should_run).e2e == true || fromJSON(needs.pre-job.outputs.should_run).web == true }}
runs-on: ${{ matrix.runner }} runs-on: ${{ matrix.runner }}
permissions: permissions:
contents: read contents: read
@@ -449,7 +436,7 @@ jobs:
mobile-unit-tests: mobile-unit-tests:
name: Unit Test Mobile name: Unit Test Mobile
needs: pre-job needs: pre-job
if: ${{ needs.pre-job.outputs.should_run_mobile == 'true' }} if: ${{ fromJSON(needs.pre-job.outputs.should_run).mobile == true }}
runs-on: ubuntu-latest runs-on: ubuntu-latest
permissions: permissions:
contents: read contents: read
@@ -471,7 +458,7 @@ jobs:
ml-unit-tests: ml-unit-tests:
name: Unit Test ML name: Unit Test ML
needs: pre-job needs: pre-job
if: ${{ needs.pre-job.outputs.should_run_ml == 'true' }} if: ${{ fromJSON(needs.pre-job.outputs.should_run).machine-learning == true }}
runs-on: ubuntu-latest runs-on: ubuntu-latest
permissions: permissions:
contents: read contents: read
@@ -507,7 +494,7 @@ jobs:
github-files-formatting: github-files-formatting:
name: .github Files Formatting name: .github Files Formatting
needs: pre-job needs: pre-job
if: ${{ needs.pre-job.outputs['should_run_.github'] == 'true' }} if: ${{ fromJSON(needs.pre-job.outputs.should_run)['.github'] == true }}
runs-on: ubuntu-latest runs-on: ubuntu-latest
permissions: permissions:
contents: read contents: read
@@ -594,7 +581,7 @@ jobs:
contents: read contents: read
services: services:
postgres: postgres:
image: ghcr.io/immich-app/postgres:14-vectorchord0.4.3@sha256:4f7ee144d4738ad02f6d9376defed7a767b748d185d47eba241578c26a63064b image: ghcr.io/immich-app/postgres:14-vectorchord0.4.3@sha256:da52bbead5d818adaa8077c8dcdaad0aaf93038c31ad8348b51f9f0ec1310a4d
env: env:
POSTGRES_PASSWORD: postgres POSTGRES_PASSWORD: postgres
POSTGRES_USER: postgres POSTGRES_USER: postgres

View File

@@ -21,25 +21,24 @@ jobs:
permissions: permissions:
contents: read contents: read
outputs: outputs:
should_run: ${{ steps.found_paths.outputs.i18n == 'true' }} should_run: ${{ steps.check.outputs.should_run }}
steps: steps:
- name: Checkout code - name: Check what should run
uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 id: check
with: uses: immich-app/devtools/actions/pre-job@24820aa4ef67959b0dcf69a438cccf00d7c7042b # pre-job-action-v1.0.1
persist-credentials: false
- id: found_paths
uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
with: with:
filters: | filters: |
i18n: i18n:
- 'i18n/!(en)**\.json' - 'i18n/!(en)**\.json'
exclude-branches: 'chore/translations'
skip-force-logic: 'true'
enforce-lock: enforce-lock:
name: Check Weblate Lock name: Check Weblate Lock
needs: [pre-job] needs: [pre-job]
runs-on: ubuntu-latest runs-on: ubuntu-latest
permissions: {} permissions: {}
if: ${{ needs.pre-job.outputs.should_run == 'true' }} if: ${{ fromJSON(needs.pre-job.outputs.should_run).i18n == true }}
steps: steps:
- name: Bot review status - name: Bot review status
env: env:

1
.gitignore vendored
View File

@@ -18,6 +18,7 @@ mobile/libisar.dylib
mobile/openapi/test mobile/openapi/test
mobile/openapi/doc mobile/openapi/doc
mobile/openapi/.openapi-generator/FILES mobile/openapi/.openapi-generator/FILES
mobile/ios/build
open-api/typescript-sdk/build open-api/typescript-sdk/build
mobile/android/fastlane/report.xml mobile/android/fastlane/report.xml

View File

@@ -4,3 +4,4 @@
/web/ @danieldietzler /web/ @danieldietzler
/machine-learning/ @mertalev /machine-learning/ @mertalev
/e2e/ @danieldietzler /e2e/ @danieldietzler
/mobile/ @shenlong-tanwen

View File

@@ -1,13 +1,13 @@
dev: prepare-volumes dev:
@trap 'make dev-down' EXIT; COMPOSE_BAKE=true docker compose -f ./docker/docker-compose.dev.yml up --remove-orphans @trap 'make dev-down' EXIT; COMPOSE_BAKE=true docker compose -f ./docker/docker-compose.dev.yml up --remove-orphans
dev-down: dev-down:
docker compose -f ./docker/docker-compose.dev.yml down --remove-orphans docker compose -f ./docker/docker-compose.dev.yml down --remove-orphans
dev-update: prepare-volumes dev-update:
@trap 'make dev-down' EXIT; COMPOSE_BAKE=true docker compose -f ./docker/docker-compose.dev.yml up --build -V --remove-orphans @trap 'make dev-down' EXIT; COMPOSE_BAKE=true docker compose -f ./docker/docker-compose.dev.yml up --build -V --remove-orphans
dev-scale: prepare-volumes dev-scale:
@trap 'make dev-down' EXIT; COMPOSE_BAKE=true docker compose -f ./docker/docker-compose.dev.yml up --build -V --scale immich-server=3 --remove-orphans @trap 'make dev-down' EXIT; COMPOSE_BAKE=true docker compose -f ./docker/docker-compose.dev.yml up --build -V --scale immich-server=3 --remove-orphans
dev-docs: dev-docs:
@@ -23,7 +23,7 @@ e2e-update:
e2e-down: e2e-down:
docker compose -f ./e2e/docker-compose.yml down --remove-orphans docker compose -f ./e2e/docker-compose.yml down --remove-orphans
prod: prod:
@trap 'make prod-down' EXIT; COMPOSE_BAKE=true docker compose -f ./docker/docker-compose.prod.yml up --build -V --remove-orphans @trap 'make prod-down' EXIT; COMPOSE_BAKE=true docker compose -f ./docker/docker-compose.prod.yml up --build -V --remove-orphans
prod-down: prod-down:
@@ -33,16 +33,16 @@ prod-scale:
@trap 'make prod-down' EXIT; COMPOSE_BAKE=true docker compose -f ./docker/docker-compose.prod.yml up --build -V --scale immich-server=3 --scale immich-microservices=3 --remove-orphans @trap 'make prod-down' EXIT; COMPOSE_BAKE=true docker compose -f ./docker/docker-compose.prod.yml up --build -V --scale immich-server=3 --scale immich-microservices=3 --remove-orphans
.PHONY: open-api .PHONY: open-api
open-api: prepare-volumes open-api:
cd ./open-api && bash ./bin/generate-open-api.sh cd ./open-api && bash ./bin/generate-open-api.sh
open-api-dart: prepare-volumes open-api-dart:
cd ./open-api && bash ./bin/generate-open-api.sh dart cd ./open-api && bash ./bin/generate-open-api.sh dart
open-api-typescript: prepare-volumes open-api-typescript:
cd ./open-api && bash ./bin/generate-open-api.sh typescript cd ./open-api && bash ./bin/generate-open-api.sh typescript
sql: prepare-volumes sql:
pnpm --filter immich run sync:sql pnpm --filter immich run sync:sql
attach-server: attach-server:
@@ -68,34 +68,6 @@ VOLUME_DIRS = \
# Include .env file if it exists # Include .env file if it exists
-include docker/.env -include docker/.env
# Helper function to chown, on error suggest remediation and exit
define safe_chown
if chown $(2) $(or $(UID),1000):$(or $(GID),1000) "$(1)" 2>/dev/null; then \
true; \
else \
STATUS=$$?; echo "Exit code: $$STATUS $(1)"; \
echo "$$STATUS $(1)"; \
echo "Permission denied when changing owner of volumes and upload location. Try running 'sudo make prepare-volumes' first."; \
exit 1; \
fi;
endef
# create empty directories and chown
prepare-volumes:
@$(foreach dir,$(VOLUME_DIRS),mkdir -p $(dir);)
@$(foreach dir,$(VOLUME_DIRS),$(call safe_chown,$(dir),-R))
ifneq ($(UPLOAD_LOCATION),)
ifeq ($(filter /%,$(UPLOAD_LOCATION)),)
@mkdir -p "docker/$(UPLOAD_LOCATION)/photos/upload"
@$(call safe_chown,docker/$(UPLOAD_LOCATION),)
@$(call safe_chown,docker/$(UPLOAD_LOCATION)/photos,-R)
else
@mkdir -p "$(UPLOAD_LOCATION)/photos/upload"
@$(call safe_chown,$(UPLOAD_LOCATION),)
@$(call safe_chown,$(UPLOAD_LOCATION)/photos,-R)
endif
endif
MODULES = e2e server web cli sdk docs .github MODULES = e2e server web cli sdk docs .github
# directory to package name mapping function # directory to package name mapping function

View File

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

View File

@@ -2,37 +2,37 @@
# Manual edits may be lost in future updates. # Manual edits may be lost in future updates.
provider "registry.opentofu.org/cloudflare/cloudflare" { provider "registry.opentofu.org/cloudflare/cloudflare" {
version = "4.52.3" version = "4.52.5"
constraints = "4.52.3" constraints = "4.52.5"
hashes = [ hashes = [
"h1:3jU62KY4Oj3xzMwkTQWon1nlIvFkgTCqI93IzUGaa0c=", "h1:+rfzF+16ZcWZWnTyW/p1HHTzYbPKX8Zt2nIFtR/+f+E=",
"h1:BWimtYXrvbzbbuoVcyobjQnXjjOb9X69JFTw+GuPxfk=", "h1:18bXaaOSq8MWKuMxo/4y7EB7/i7G90y5QsKHZRmkoDo=",
"h1:C/KvLEm8dVQ6zG2X4asLDtmw2JW/xu7E8MddtaXniO0=", "h1:4vZVOpKeEQZsF2VrARRZFeL37Ed/gD4rRMtfnvWQres=",
"h1:Doo0xcLFf+CnfDWjsA7G1NvSLURuwcgyVy8k0NF1gJA=", "h1:BZOsTF83QPKXTAaYqxPKzdl1KRjk/L2qbPpFjM0w28A=",
"h1:Gc3FGDtR8lUWsi9VImnnE5/USDXiIwYsv4Hbl+d2lwY=", "h1:CDuC+HXLvc1z6wkCRsSDcc/+QENIHEtssYshiWg3opA=",
"h1:HsDY6s1gup5fW9TeuTUy85QMIld1nDOUFlwsfxIq1ig=", "h1:DE+YFzLnqSe79pI2R4idRGx5QzLdrA7RXvngTkGfZ30=",
"h1:MnHkB56E4b/kT6WZigsZJnB5rgnCfDVbrLBNxIsEXPY=", "h1:DfaJwH3Ml4yrRbdAY4AcDVy0QTQk5T3A622TXzS/u2E=",
"h1:O/FUQEqhtknJNdsaMbIBi2pLWBds2VvN5FsTVVntzb0=", "h1:EIDXP0W3kgIv2pecrFmqtK/DnlqkyckzBzhxKaXU+4A=",
"h1:OKQBynkp0J5DIf5FOl/NR3S2rvh89pY+t5wevYxdTJs=", "h1:EV4kYyaOnwGA0bh/3hU6Ezqnt1PFDxopH7i85e48IzY=",
"h1:On+vPsYV8U/J/8wFZPXjeAgNJqFFQj42vNOKuNKURkY=", "h1:M0iXabfzamU+MPDi0G9XACpbacFKMakmM+Z9HZ8HrsM=",
"h1:SPkrMRJahxK0uum7FnUugbGN/JepHMH8M71DBtYrvG0=", "h1:YWmCbGF/KbsrUzcYVBLscwLizidbp95TDQa0N2qpmVo=",
"h1:bEh1ASPMiin3F36+hTfjMQTBnuDl2DzjzSCdova3JEM=", "h1:cxPcCB5gbrpUO1+IXkQYs1YTY50/0IlApCzGea0cwuQ=",
"h1:dtIK+x5Q1sh5SMPaHBHXhL9XDIqbRW0EBmVZ+KHQB8E=", "h1:g6DldikTV2HXUu9uoeNY5FuLufgaYWF4ufgZg7wq62s=",
"h1:kZcwWfODMWWyauZ66oaO/X+xXkqBtrbYwfUFEtspwEc=", "h1:oi/Hrx9pwoQ+Z52CBC+rrowVH387EIj0qvnxQgDeI+0=",
"zh:53946fce4a631f1d98c61550821c88edede9169dfe5cc254e09a2ab207f76b3f", "zh:1a3400cb38863b2585968d1876706bcfc67a148e1318a1d325c6c7704adc999b",
"zh:61654a21f1dd4331492d4ef77e9ebff066bc01e1281f92b925e5697c9138d681", "zh:4c5062cb9e9da1676f06ae92b8370186d98976cc4c7030d3cd76df12af54282a",
"zh:6a54e9d129b276f052a2f1b73ad0b8735fe6a7403c6a8f6aa111e525eeefaf35", "zh:52110f493b5f0587ef77a1cfd1a67001fd4c617b14c6502d732ab47352bdc2f7",
"zh:7692374e655c346a630b5a7cd776c5e0b2388900dcd7ab69a3af85d0c31c6c43", "zh:5aa536f9eaeb43823aaf2aa80e7d39b25ef2b383405ed034aa16a28b446a9238",
"zh:5cc39459a1c6be8a918f17054e4fbba573825ed5597dcada588fe99614d98a5b",
"zh:629ae6a7ba298815131da826474d199312d21cec53a4d5ded4fa56a692e6f072",
"zh:719cc7c75dc1d3eb30c22ff5102a017996d9788b948078c7e1c5b3446aeca661",
"zh:8698635a3ca04383c1e93b21d6963346bdae54d27177a48e4b1435b7f731731c",
"zh:890df766e9b839623b1f0437355032a3c006226a6c200cd911e15ee1a9014e9f", "zh:890df766e9b839623b1f0437355032a3c006226a6c200cd911e15ee1a9014e9f",
"zh:8fe5b792a4d2b1c3a0e573649642962494faa00299baa6aaf813b9a43203dc02", "zh:8a9993f1dcadf1dd6ca43b23348abe374605d29945a2fafc07fb3457644e6a54",
"zh:a0f403a4862df90f09de65c6e939d6cfd069a8dda2dd33f82948bf6f5f1124ef", "zh:b1b9a1e6bcc24d5863a664a411d2dc906373ae7a2399d2d65548ce7377057852",
"zh:a25dc3eb60777b600f8f125d321fe7c50b811c5302b58e9a727ceb749a04e35d", "zh:b270184cdeec277218e84b94cb136fead753da717f9b9dc378e51907f3f00bb0",
"zh:a2f2ac7dc703c69d2e8c67c9cb5620b5348cb4fd6b98515fbe3f478517b56602", "zh:dff2bc10071210181726ce270f954995fe42c696e61e2e8f874021fed02521e5",
"zh:d452e7bd24445ee14166470cf50f3aca566d46cab5f26f1c5c988c0f3106b697", "zh:e8e87b40b6a87dc097b0fdc20d3f725cec0d82abc9cc3755c1f89f8f6e8b0036",
"zh:e10a52b0294735659eb3f0821ad2006ec097918efe58d31d37a5e3c47efef5f6", "zh:ee964a6573d399a5dd22ce328fb38ca1207797a02248f14b2e4913ee390e7803",
"zh:e28dd0954cef9f05adf4d4b440d6f134f605344dfa56307181996675e6550af2",
"zh:f1e3b2f43a472280442f01ba71a3c06c9167432e553381132ea5c4a77e0b6dd5",
"zh:f71fd63718d38fd43829861e91fe79e16d7b4c7c3d508ae3d077368d89b8e5a0",
"zh:faf8d3da4b819c4ae8e565d2b1a684c6a948a086cb299189a5e7b30b2178409d",
] ]
} }

View File

@@ -5,7 +5,7 @@ terraform {
required_providers { required_providers {
cloudflare = { cloudflare = {
source = "cloudflare/cloudflare" source = "cloudflare/cloudflare"
version = "4.52.3" version = "4.52.5"
} }
} }
} }

View File

@@ -2,37 +2,37 @@
# Manual edits may be lost in future updates. # Manual edits may be lost in future updates.
provider "registry.opentofu.org/cloudflare/cloudflare" { provider "registry.opentofu.org/cloudflare/cloudflare" {
version = "4.52.3" version = "4.52.5"
constraints = "4.52.3" constraints = "4.52.5"
hashes = [ hashes = [
"h1:3jU62KY4Oj3xzMwkTQWon1nlIvFkgTCqI93IzUGaa0c=", "h1:+rfzF+16ZcWZWnTyW/p1HHTzYbPKX8Zt2nIFtR/+f+E=",
"h1:BWimtYXrvbzbbuoVcyobjQnXjjOb9X69JFTw+GuPxfk=", "h1:18bXaaOSq8MWKuMxo/4y7EB7/i7G90y5QsKHZRmkoDo=",
"h1:C/KvLEm8dVQ6zG2X4asLDtmw2JW/xu7E8MddtaXniO0=", "h1:4vZVOpKeEQZsF2VrARRZFeL37Ed/gD4rRMtfnvWQres=",
"h1:Doo0xcLFf+CnfDWjsA7G1NvSLURuwcgyVy8k0NF1gJA=", "h1:BZOsTF83QPKXTAaYqxPKzdl1KRjk/L2qbPpFjM0w28A=",
"h1:Gc3FGDtR8lUWsi9VImnnE5/USDXiIwYsv4Hbl+d2lwY=", "h1:CDuC+HXLvc1z6wkCRsSDcc/+QENIHEtssYshiWg3opA=",
"h1:HsDY6s1gup5fW9TeuTUy85QMIld1nDOUFlwsfxIq1ig=", "h1:DE+YFzLnqSe79pI2R4idRGx5QzLdrA7RXvngTkGfZ30=",
"h1:MnHkB56E4b/kT6WZigsZJnB5rgnCfDVbrLBNxIsEXPY=", "h1:DfaJwH3Ml4yrRbdAY4AcDVy0QTQk5T3A622TXzS/u2E=",
"h1:O/FUQEqhtknJNdsaMbIBi2pLWBds2VvN5FsTVVntzb0=", "h1:EIDXP0W3kgIv2pecrFmqtK/DnlqkyckzBzhxKaXU+4A=",
"h1:OKQBynkp0J5DIf5FOl/NR3S2rvh89pY+t5wevYxdTJs=", "h1:EV4kYyaOnwGA0bh/3hU6Ezqnt1PFDxopH7i85e48IzY=",
"h1:On+vPsYV8U/J/8wFZPXjeAgNJqFFQj42vNOKuNKURkY=", "h1:M0iXabfzamU+MPDi0G9XACpbacFKMakmM+Z9HZ8HrsM=",
"h1:SPkrMRJahxK0uum7FnUugbGN/JepHMH8M71DBtYrvG0=", "h1:YWmCbGF/KbsrUzcYVBLscwLizidbp95TDQa0N2qpmVo=",
"h1:bEh1ASPMiin3F36+hTfjMQTBnuDl2DzjzSCdova3JEM=", "h1:cxPcCB5gbrpUO1+IXkQYs1YTY50/0IlApCzGea0cwuQ=",
"h1:dtIK+x5Q1sh5SMPaHBHXhL9XDIqbRW0EBmVZ+KHQB8E=", "h1:g6DldikTV2HXUu9uoeNY5FuLufgaYWF4ufgZg7wq62s=",
"h1:kZcwWfODMWWyauZ66oaO/X+xXkqBtrbYwfUFEtspwEc=", "h1:oi/Hrx9pwoQ+Z52CBC+rrowVH387EIj0qvnxQgDeI+0=",
"zh:53946fce4a631f1d98c61550821c88edede9169dfe5cc254e09a2ab207f76b3f", "zh:1a3400cb38863b2585968d1876706bcfc67a148e1318a1d325c6c7704adc999b",
"zh:61654a21f1dd4331492d4ef77e9ebff066bc01e1281f92b925e5697c9138d681", "zh:4c5062cb9e9da1676f06ae92b8370186d98976cc4c7030d3cd76df12af54282a",
"zh:6a54e9d129b276f052a2f1b73ad0b8735fe6a7403c6a8f6aa111e525eeefaf35", "zh:52110f493b5f0587ef77a1cfd1a67001fd4c617b14c6502d732ab47352bdc2f7",
"zh:7692374e655c346a630b5a7cd776c5e0b2388900dcd7ab69a3af85d0c31c6c43", "zh:5aa536f9eaeb43823aaf2aa80e7d39b25ef2b383405ed034aa16a28b446a9238",
"zh:5cc39459a1c6be8a918f17054e4fbba573825ed5597dcada588fe99614d98a5b",
"zh:629ae6a7ba298815131da826474d199312d21cec53a4d5ded4fa56a692e6f072",
"zh:719cc7c75dc1d3eb30c22ff5102a017996d9788b948078c7e1c5b3446aeca661",
"zh:8698635a3ca04383c1e93b21d6963346bdae54d27177a48e4b1435b7f731731c",
"zh:890df766e9b839623b1f0437355032a3c006226a6c200cd911e15ee1a9014e9f", "zh:890df766e9b839623b1f0437355032a3c006226a6c200cd911e15ee1a9014e9f",
"zh:8fe5b792a4d2b1c3a0e573649642962494faa00299baa6aaf813b9a43203dc02", "zh:8a9993f1dcadf1dd6ca43b23348abe374605d29945a2fafc07fb3457644e6a54",
"zh:a0f403a4862df90f09de65c6e939d6cfd069a8dda2dd33f82948bf6f5f1124ef", "zh:b1b9a1e6bcc24d5863a664a411d2dc906373ae7a2399d2d65548ce7377057852",
"zh:a25dc3eb60777b600f8f125d321fe7c50b811c5302b58e9a727ceb749a04e35d", "zh:b270184cdeec277218e84b94cb136fead753da717f9b9dc378e51907f3f00bb0",
"zh:a2f2ac7dc703c69d2e8c67c9cb5620b5348cb4fd6b98515fbe3f478517b56602", "zh:dff2bc10071210181726ce270f954995fe42c696e61e2e8f874021fed02521e5",
"zh:d452e7bd24445ee14166470cf50f3aca566d46cab5f26f1c5c988c0f3106b697", "zh:e8e87b40b6a87dc097b0fdc20d3f725cec0d82abc9cc3755c1f89f8f6e8b0036",
"zh:e10a52b0294735659eb3f0821ad2006ec097918efe58d31d37a5e3c47efef5f6", "zh:ee964a6573d399a5dd22ce328fb38ca1207797a02248f14b2e4913ee390e7803",
"zh:e28dd0954cef9f05adf4d4b440d6f134f605344dfa56307181996675e6550af2",
"zh:f1e3b2f43a472280442f01ba71a3c06c9167432e553381132ea5c4a77e0b6dd5",
"zh:f71fd63718d38fd43829861e91fe79e16d7b4c7c3d508ae3d077368d89b8e5a0",
"zh:faf8d3da4b819c4ae8e565d2b1a684c6a948a086cb299189a5e7b30b2178409d",
] ]
} }

View File

@@ -5,7 +5,7 @@ terraform {
required_providers { required_providers {
cloudflare = { cloudflare = {
source = "cloudflare/cloudflare" source = "cloudflare/cloudflare"
version = "4.52.3" version = "4.52.5"
} }
} }
} }

View File

@@ -21,16 +21,14 @@ services:
# extends: # extends:
# file: hwaccel.transcoding.yml # file: hwaccel.transcoding.yml
# service: cpu # set to one of [nvenc, quicksync, rkmpp, vaapi, vaapi-wsl] for accelerated transcoding # service: cpu # set to one of [nvenc, quicksync, rkmpp, vaapi, vaapi-wsl] for accelerated transcoding
user: '${UID:-1000}:${GID:-1000}'
build: build:
context: ../ context: ../
dockerfile: server/Dockerfile dockerfile: server/Dockerfile.dev
target: dev target: dev
restart: unless-stopped restart: unless-stopped
volumes: volumes:
- ..:/usr/src/app - ..:/usr/src/app
- ${UPLOAD_LOCATION}/photos:/data - ${UPLOAD_LOCATION}/photos:/data
- ${UPLOAD_LOCATION}/photos/upload:/data/upload
- /etc/localtime:/etc/localtime:ro - /etc/localtime:/etc/localtime:ro
- pnpm-store:/usr/src/app/.pnpm-store - pnpm-store:/usr/src/app/.pnpm-store
- server-node_modules:/usr/src/app/server/node_modules - server-node_modules:/usr/src/app/server/node_modules
@@ -72,20 +70,15 @@ services:
condition: service_started condition: service_started
database: database:
condition: service_started condition: service_started
init:
condition: service_completed_successfully
healthcheck: healthcheck:
disable: false disable: false
immich-web: immich-web:
container_name: immich_web container_name: immich_web
image: immich-web-dev:latest image: immich-web-dev:latest
# Needed for rootless docker setup, see https://github.com/moby/moby/issues/45919
# user: 0:0
user: '${UID:-1000}:${GID:-1000}'
build: build:
context: ../ context: ../
dockerfile: server/Dockerfile dockerfile: server/Dockerfile.dev
target: dev target: dev
command: ['immich-web'] command: ['immich-web']
env_file: env_file:
@@ -114,8 +107,6 @@ services:
depends_on: depends_on:
immich-server: immich-server:
condition: service_started condition: service_started
init:
condition: service_completed_successfully
immich-machine-learning: immich-machine-learning:
container_name: immich_machine_learning container_name: immich_machine_learning
@@ -149,7 +140,7 @@ services:
database: database:
container_name: immich_postgres container_name: immich_postgres
image: ghcr.io/immich-app/postgres:14-vectorchord0.4.3-pgvectors0.2.0@sha256:8d292bdb796aa58bbbaa47fe971c8516f6f57d6a47e7172e62754feb6ed4e7b0 image: ghcr.io/immich-app/postgres:14-vectorchord0.4.3-pgvectors0.2.0@sha256:c44be5f2871c59362966d71eab4268170eb6f5653c0e6170184e72b38ffdf107
env_file: env_file:
- .env - .env
environment: environment:
@@ -183,25 +174,6 @@ services:
# volumes: # volumes:
# - grafana-data:/var/lib/grafana # - grafana-data:/var/lib/grafana
init:
container_name: init
image: busybox@sha256:ab33eacc8251e3807b85bb6dba570e4698c3998eca6f0fc2ccb60575a563ea74
env_file:
- .env
user: 0:0
command: sh -c 'find /data -maxdepth 1 -type d -exec chown ${UID:-1000}:${GID:-1000} {} + 2>/dev/null || true; for path in /usr/src/app/.pnpm-store /usr/src/app/server/node_modules /usr/src/app/server/dist /usr/src/app/.github/node_modules /usr/src/app/cli/node_modules /usr/src/app/docs/node_modules /usr/src/app/e2e/node_modules /usr/src/app/open-api/typescript-sdk/node_modules /usr/src/app/web/.svelte-kit /usr/src/app/web/coverage /usr/src/app/node_modules /usr/src/app/web/node_modules; do [ -e "$$path" ] && chown -R ${UID:-1000}:${GID:-1000} "$$path" || true; done'
volumes:
- pnpm-store:/usr/src/app/.pnpm-store
- server-node_modules:/usr/src/app/server/node_modules
- web-node_modules:/usr/src/app/web/node_modules
- github-node_modules:/usr/src/app/.github/node_modules
- cli-node_modules:/usr/src/app/cli/node_modules
- docs-node_modules:/usr/src/app/docs/node_modules
- e2e-node_modules:/usr/src/app/e2e/node_modules
- sdk-node_modules:/usr/src/app/open-api/typescript-sdk/node_modules
- app-node_modules:/usr/src/app/node_modules
- sveltekit:/usr/src/app/web/.svelte-kit
- coverage:/usr/src/app/web/coverage
volumes: volumes:
model-cache: model-cache:
prometheus-data: prometheus-data:

View File

@@ -63,7 +63,7 @@ services:
database: database:
container_name: immich_postgres container_name: immich_postgres
image: ghcr.io/immich-app/postgres:14-vectorchord0.4.3-pgvectors0.2.0@sha256:8d292bdb796aa58bbbaa47fe971c8516f6f57d6a47e7172e62754feb6ed4e7b0 image: ghcr.io/immich-app/postgres:14-vectorchord0.4.3-pgvectors0.2.0@sha256:c44be5f2871c59362966d71eab4268170eb6f5653c0e6170184e72b38ffdf107
env_file: env_file:
- .env - .env
environment: environment:

View File

@@ -56,7 +56,7 @@ services:
database: database:
container_name: immich_postgres container_name: immich_postgres
image: ghcr.io/immich-app/postgres:14-vectorchord0.4.3-pgvectors0.2.0@sha256:8d292bdb796aa58bbbaa47fe971c8516f6f57d6a47e7172e62754feb6ed4e7b0 image: ghcr.io/immich-app/postgres:14-vectorchord0.4.3-pgvectors0.2.0@sha256:c44be5f2871c59362966d71eab4268170eb6f5653c0e6170184e72b38ffdf107
environment: environment:
POSTGRES_PASSWORD: ${DB_PASSWORD} POSTGRES_PASSWORD: ${DB_PASSWORD}
POSTGRES_USER: ${DB_USERNAME} POSTGRES_USER: ${DB_USERNAME}

View File

@@ -169,8 +169,6 @@ Redis (Sentinel) URL example JSON before encoding:
| `MACHINE_LEARNING_ANN_TUNING_LEVEL` | ARM-NN GPU tuning level (1: rapid, 2: normal, 3: exhaustive) | `2` | machine learning | | `MACHINE_LEARNING_ANN_TUNING_LEVEL` | ARM-NN GPU tuning level (1: rapid, 2: normal, 3: exhaustive) | `2` | machine learning |
| `MACHINE_LEARNING_DEVICE_IDS`<sup>\*4</sup> | Device IDs to use in multi-GPU environments | `0` | machine learning | | `MACHINE_LEARNING_DEVICE_IDS`<sup>\*4</sup> | Device IDs to use in multi-GPU environments | `0` | machine learning |
| `MACHINE_LEARNING_MAX_BATCH_SIZE__FACIAL_RECOGNITION` | Set the maximum number of faces that will be processed at once by the facial recognition model | None (`1` if using OpenVINO) | machine learning | | `MACHINE_LEARNING_MAX_BATCH_SIZE__FACIAL_RECOGNITION` | Set the maximum number of faces that will be processed at once by the facial recognition model | None (`1` if using OpenVINO) | machine learning |
| `MACHINE_LEARNING_PING_TIMEOUT` | How long (ms) to wait for a PING response when checking if an ML server is available | `2000` | server |
| `MACHINE_LEARNING_AVAILABILITY_BACKOFF_TIME` | How long to ignore ML servers that are offline before trying again | `30000` | server |
| `MACHINE_LEARNING_RKNN` | Enable RKNN hardware acceleration if supported | `True` | machine learning | | `MACHINE_LEARNING_RKNN` | Enable RKNN hardware acceleration if supported | `True` | machine learning |
| `MACHINE_LEARNING_RKNN_THREADS` | How many threads of RKNN runtime should be spinned up while inferencing. | `1` | machine learning | | `MACHINE_LEARNING_RKNN_THREADS` | How many threads of RKNN runtime should be spinned up while inferencing. | `1` | machine learning |

View File

@@ -28,6 +28,12 @@ const guides: CommunityGuidesProps[] = [
description: `synchronize folders in imported library with albums having the folders name.`, description: `synchronize folders in imported library with albums having the folders name.`,
url: 'https://github.com/immich-app/immich/discussions/3382', url: 'https://github.com/immich-app/immich/discussions/3382',
}, },
{
title: 'Immich Podman Quadlets Handbook',
description:
'A rewrite of the original Immich Docker Compose file using Podman Quadlets, with a set of extra guides in the repositorys wiki.',
url: 'https://github.com/linux-universe/immich-podman-quadlets/blob/main/README.md',
},
{ {
title: 'Podman/Quadlets Install', title: 'Podman/Quadlets Install',
description: 'Documentation for simple podman setup using quadlets.', description: 'Documentation for simple podman setup using quadlets.',

View File

@@ -110,6 +110,16 @@ const projects: CommunityProjectProps[] = [
description: 'A tiny, zero-login web app for collecting photos/videos from anyone into your Immich server.', description: 'A tiny, zero-login web app for collecting photos/videos from anyone into your Immich server.',
url: 'https://github.com/Nasogaa/immich-drop', url: 'https://github.com/Nasogaa/immich-drop',
}, },
{
title: 'Immich Birthday Sync',
description: 'Bulk-upload and -download birthdays, with CardDAV sync support',
url: 'https://github.com/sid3windr/immich-birthday',
},
{
title: 'Immich Stack',
description: 'Auto-stack photos with identical filenames and differing extensions (i.e. JPG+RAW)',
url: 'https://github.com/sid3windr/immich-stack',
},
]; ];
function CommunityProject({ title, description, url }: CommunityProjectProps): JSX.Element { function CommunityProject({ title, description, url }: CommunityProjectProps): JSX.Element {

View File

@@ -2,7 +2,17 @@
## TypeORM Upgrade ## TypeORM Upgrade
In order to update to Immich to `v1.137.0` (or above), the application must be started at least once on a version in the range between `1.132.0` and `1.136.0`. Doing so will complete database schema upgrades that are required for `v1.137.0` (and above). After Immich has successfully updated to a version in this range, you can now attempt to update to v1.137.0 (or above). We recommend users upgrade to `1.132.0` since it does not have any other breaking changes. If you encountered "Migrations failed: Error: Invalid upgrade path" then perform an intermediate upgrade to `v1.132.3` first.
:::tip
We recommend users upgrade to `v1.132.3` since it does not have any breaking changes or bugs on this upgrade path.
:::
In order to update to Immich `v1.137.0` or above, the application must be started at least once on a version in the range between `1.132.0` and `1.136.0`. Doing so will complete database schema upgrades that are required for `v1.137.0` (and above). After Immich has successfully updated to a version in this range, you can now attempt to update to `v1.137.0` (or above).
:::caution
Avoid `v1.136.0` if upgrading from `v1.131.0` (or earlier) due to a bug blocking this upgrade in some installations.
:::
## Inconsistent Media Location ## Inconsistent Media Location

View File

@@ -1,4 +1,12 @@
[ [
{
"label": "v1.142.1",
"url": "https://v1.142.1.archive.immich.app"
},
{
"label": "v1.142.0",
"url": "https://v1.142.0.archive.immich.app"
},
{ {
"label": "v1.141.1", "label": "v1.141.1",
"url": "https://v1.141.1.archive.immich.app" "url": "https://v1.141.1.archive.immich.app"

View File

@@ -38,7 +38,7 @@ services:
image: redis:6.2-alpine@sha256:7fe72c486b910f6b1a9769c937dad5d63648ddee82e056f47417542dd40825bb image: redis:6.2-alpine@sha256:7fe72c486b910f6b1a9769c937dad5d63648ddee82e056f47417542dd40825bb
database: database:
image: ghcr.io/immich-app/postgres:14-vectorchord0.3.0@sha256:7a4469b9484e37bf2630a60bc2f02f086dae898143b599ecc1c93f619849ef6b image: ghcr.io/immich-app/postgres:14-vectorchord0.3.0@sha256:11ced39d65a92a54d12890ced6a26cc2003f92697d6f0d4d944b98459dba7138
command: -c fsync=off -c shared_preload_libraries=vchord.so -c config_file=/var/lib/postgresql/data/postgresql.conf command: -c fsync=off -c shared_preload_libraries=vchord.so -c config_file=/var/lib/postgresql/data/postgresql.conf
environment: environment:
POSTGRES_PASSWORD: postgres POSTGRES_PASSWORD: postgres

View File

@@ -1,6 +1,6 @@
{ {
"name": "immich-e2e", "name": "immich-e2e",
"version": "1.141.1", "version": "1.142.1",
"description": "", "description": "",
"main": "index.js", "main": "index.js",
"type": "module", "type": "module",
@@ -25,7 +25,7 @@
"@playwright/test": "^1.44.1", "@playwright/test": "^1.44.1",
"@socket.io/component-emitter": "^3.1.2", "@socket.io/component-emitter": "^3.1.2",
"@types/luxon": "^3.4.2", "@types/luxon": "^3.4.2",
"@types/node": "^22.18.0", "@types/node": "^22.18.1",
"@types/oidc-provider": "^9.0.0", "@types/oidc-provider": "^9.0.0",
"@types/pg": "^8.15.1", "@types/pg": "^8.15.1",
"@types/pngjs": "^6.0.4", "@types/pngjs": "^6.0.4",

View File

@@ -409,6 +409,7 @@
"recent-albums": "Нядаўнія альбомы", "recent-albums": "Нядаўнія альбомы",
"recent_searches": "Нядаўнія пошукі", "recent_searches": "Нядаўнія пошукі",
"recently_added": "Нядаўна дададзена", "recently_added": "Нядаўна дададзена",
"refresh_faces": "Абнавіць твары",
"remove": "Выдаліць", "remove": "Выдаліць",
"remove_from_album": "Выдаліць з альбома", "remove_from_album": "Выдаліць з альбома",
"remove_from_favorites": "Выдаліць з абраных", "remove_from_favorites": "Выдаліць з абраных",

View File

@@ -1515,7 +1515,7 @@
"profile_drawer_client_out_of_date_minor": "Mobile-App ist veraltet. Bitte aktualisiere auf die neueste Minor-Version.", "profile_drawer_client_out_of_date_minor": "Mobile-App ist veraltet. Bitte aktualisiere auf die neueste Minor-Version.",
"profile_drawer_client_server_up_to_date": "Die App- und Server-Versionen sind aktuell", "profile_drawer_client_server_up_to_date": "Die App- und Server-Versionen sind aktuell",
"profile_drawer_github": "GitHub", "profile_drawer_github": "GitHub",
"profile_drawer_readonly_mode": "Schreibgeschützter Modus aktiviert. Tippe zweimal auf das Benutzer-Avatar-Symbol, um den Modus zu verlassen.", "profile_drawer_readonly_mode": "Schreibgeschützter Modus aktiviert. Halte das Benutzer-Avatar-Symbol gedrückt, um den Modus zu verlassen.",
"profile_drawer_server_out_of_date_major": "Server-Version ist veraltet. Bitte aktualisiere auf die neueste Major-Version.", "profile_drawer_server_out_of_date_major": "Server-Version ist veraltet. Bitte aktualisiere auf die neueste Major-Version.",
"profile_drawer_server_out_of_date_minor": "Server-Version ist veraltet. Bitte aktualisiere auf die neueste Minor-Version.", "profile_drawer_server_out_of_date_minor": "Server-Version ist veraltet. Bitte aktualisiere auf die neueste Minor-Version.",
"profile_image_of_user": "Profilbild von {user}", "profile_image_of_user": "Profilbild von {user}",
@@ -1547,7 +1547,7 @@
"purchase_per_server": "Pro Server", "purchase_per_server": "Pro Server",
"purchase_per_user": "Pro Benutzer", "purchase_per_user": "Pro Benutzer",
"purchase_remove_product_key": "Produktschlüssel entfernen", "purchase_remove_product_key": "Produktschlüssel entfernen",
"purchase_remove_product_key_prompt": "Sicher, dass der Produktschlüssel entfernt werden soll?", "purchase_remove_product_key_prompt": "Bist Du sicher, dass der Produktschlüssel entfernt werden soll?",
"purchase_remove_server_product_key": "Server-Produktschlüssel entfernen", "purchase_remove_server_product_key": "Server-Produktschlüssel entfernen",
"purchase_remove_server_product_key_prompt": "Sicher, dass der Server-Produktschlüssel entfernt werden soll?", "purchase_remove_server_product_key_prompt": "Sicher, dass der Server-Produktschlüssel entfernt werden soll?",
"purchase_server_description_1": "Für den gesamten Server", "purchase_server_description_1": "Für den gesamten Server",
@@ -1917,6 +1917,8 @@
"sync_albums_manual_subtitle": "Synchronisiere alle hochgeladenen Videos und Fotos in die ausgewählten Backup-Alben", "sync_albums_manual_subtitle": "Synchronisiere alle hochgeladenen Videos und Fotos in die ausgewählten Backup-Alben",
"sync_local": "Lokal synchronisieren", "sync_local": "Lokal synchronisieren",
"sync_remote": "mit Server synchronisieren", "sync_remote": "mit Server synchronisieren",
"sync_status": "Synchronisierungstatus",
"sync_status_subtitle": "Synchronisierungssystem anzeigen und bearbeiten",
"sync_upload_album_setting_subtitle": "Erstelle deine ausgewählten Alben in Immich und lade die Fotos und Videos dort hoch", "sync_upload_album_setting_subtitle": "Erstelle deine ausgewählten Alben in Immich und lade die Fotos und Videos dort hoch",
"tag": "Tag", "tag": "Tag",
"tag_assets": "Dateien taggen", "tag_assets": "Dateien taggen",
@@ -1976,6 +1978,7 @@
"trash_page_select_assets_btn": "Elemente auswählen", "trash_page_select_assets_btn": "Elemente auswählen",
"trash_page_title": "Papierkorb ({count})", "trash_page_title": "Papierkorb ({count})",
"trashed_items_will_be_permanently_deleted_after": "Gelöschte Objekte werden nach {days, plural, one {# Tag} other {# Tagen}} endgültig gelöscht.", "trashed_items_will_be_permanently_deleted_after": "Gelöschte Objekte werden nach {days, plural, one {# Tag} other {# Tagen}} endgültig gelöscht.",
"troubleshoot": "Fehler beheben",
"type": "Typ", "type": "Typ",
"unable_to_change_pin_code": "PIN Code konnte nicht geändert werden", "unable_to_change_pin_code": "PIN Code konnte nicht geändert werden",
"unable_to_setup_pin_code": "PIN Code konnte nicht festgelegt werden", "unable_to_setup_pin_code": "PIN Code konnte nicht festgelegt werden",

View File

@@ -123,6 +123,13 @@
"logging_enable_description": "Enable logging", "logging_enable_description": "Enable logging",
"logging_level_description": "When enabled, what log level to use.", "logging_level_description": "When enabled, what log level to use.",
"logging_settings": "Logging", "logging_settings": "Logging",
"machine_learning_availability_checks": "Availability checks",
"machine_learning_availability_checks_description": "Automatically detect and prefer available machine learning servers",
"machine_learning_availability_checks_enabled": "Enable availability checks",
"machine_learning_availability_checks_interval": "Check interval",
"machine_learning_availability_checks_interval_description": "Interval in milliseconds between availability checks",
"machine_learning_availability_checks_timeout": "Request timeout",
"machine_learning_availability_checks_timeout_description": "Timeout in milliseconds for availability checks",
"machine_learning_clip_model": "CLIP model", "machine_learning_clip_model": "CLIP model",
"machine_learning_clip_model_description": "The name of a CLIP model listed <link>here</link>. Note that you must re-run the 'Smart Search' job for all images upon changing a model.", "machine_learning_clip_model_description": "The name of a CLIP model listed <link>here</link>. Note that you must re-run the 'Smart Search' job for all images upon changing a model.",
"machine_learning_duplicate_detection": "Duplicate Detection", "machine_learning_duplicate_detection": "Duplicate Detection",
@@ -387,8 +394,6 @@
"admin_password": "Admin Password", "admin_password": "Admin Password",
"administration": "Administration", "administration": "Administration",
"advanced": "Advanced", "advanced": "Advanced",
"advanced_settings_beta_timeline_subtitle": "Try the new app experience",
"advanced_settings_beta_timeline_title": "Beta Timeline",
"advanced_settings_enable_alternate_media_filter_subtitle": "Use this option to filter media during sync based on alternate criteria. Only try this if you have issues with the app detecting all albums.", "advanced_settings_enable_alternate_media_filter_subtitle": "Use this option to filter media during sync based on alternate criteria. Only try this if you have issues with the app detecting all albums.",
"advanced_settings_enable_alternate_media_filter_title": "[EXPERIMENTAL] Use alternate device album sync filter", "advanced_settings_enable_alternate_media_filter_title": "[EXPERIMENTAL] Use alternate device album sync filter",
"advanced_settings_log_level_title": "Log level: {level}", "advanced_settings_log_level_title": "Log level: {level}",
@@ -425,6 +430,7 @@
"album_remove_user_confirmation": "Are you sure you want to remove {user}?", "album_remove_user_confirmation": "Are you sure you want to remove {user}?",
"album_search_not_found": "No albums found matching your search", "album_search_not_found": "No albums found matching your search",
"album_share_no_users": "Looks like you have shared this album with all users or you don't have any user to share with.", "album_share_no_users": "Looks like you have shared this album with all users or you don't have any user to share with.",
"album_summary": "Album summary",
"album_updated": "Album updated", "album_updated": "Album updated",
"album_updated_setting_description": "Receive an email notification when a shared album has new assets", "album_updated_setting_description": "Receive an email notification when a shared album has new assets",
"album_user_left": "Left {album}", "album_user_left": "Left {album}",
@@ -496,6 +502,8 @@
"asset_restored_successfully": "Asset restored successfully", "asset_restored_successfully": "Asset restored successfully",
"asset_skipped": "Skipped", "asset_skipped": "Skipped",
"asset_skipped_in_trash": "In trash", "asset_skipped_in_trash": "In trash",
"asset_trashed": "Asset trashed",
"asset_troubleshoot": "Asset Troubleshoot",
"asset_uploaded": "Uploaded", "asset_uploaded": "Uploaded",
"asset_uploading": "Uploading…", "asset_uploading": "Uploading…",
"asset_viewer_settings_subtitle": "Manage your gallery viewer settings", "asset_viewer_settings_subtitle": "Manage your gallery viewer settings",
@@ -529,8 +537,10 @@
"autoplay_slideshow": "Autoplay slideshow", "autoplay_slideshow": "Autoplay slideshow",
"back": "Back", "back": "Back",
"back_close_deselect": "Back, close, or deselect", "back_close_deselect": "Back, close, or deselect",
"background_backup_running_error": "Background backup is currently running, cannot start manual backup",
"background_location_permission": "Background location permission", "background_location_permission": "Background location permission",
"background_location_permission_content": "In order to switch networks when running in the background, Immich must *always* have precise location access so the app can read the Wi-Fi network's name", "background_location_permission_content": "In order to switch networks when running in the background, Immich must *always* have precise location access so the app can read the Wi-Fi network's name",
"background_options": "Background Options",
"backup": "Backup", "backup": "Backup",
"backup_album_selection_page_albums_device": "Albums on device ({count})", "backup_album_selection_page_albums_device": "Albums on device ({count})",
"backup_album_selection_page_albums_tap": "Tap to include, double tap to exclude", "backup_album_selection_page_albums_tap": "Tap to include, double tap to exclude",
@@ -538,6 +548,7 @@
"backup_album_selection_page_select_albums": "Select albums", "backup_album_selection_page_select_albums": "Select albums",
"backup_album_selection_page_selection_info": "Selection Info", "backup_album_selection_page_selection_info": "Selection Info",
"backup_album_selection_page_total_assets": "Total unique assets", "backup_album_selection_page_total_assets": "Total unique assets",
"backup_albums_sync": "Backup albums synchronization",
"backup_all": "All", "backup_all": "All",
"backup_background_service_backup_failed_message": "Failed to backup assets. Retrying…", "backup_background_service_backup_failed_message": "Failed to backup assets. Retrying…",
"backup_background_service_connection_failed_message": "Failed to connect to the server. Retrying…", "backup_background_service_connection_failed_message": "Failed to connect to the server. Retrying…",
@@ -654,6 +665,8 @@
"change_pin_code": "Change PIN code", "change_pin_code": "Change PIN code",
"change_your_password": "Change your password", "change_your_password": "Change your password",
"changed_visibility_successfully": "Changed visibility successfully", "changed_visibility_successfully": "Changed visibility successfully",
"charging": "Charging",
"charging_requirement_mobile_backup": "Background backup requires the device to be charging",
"check_corrupt_asset_backup": "Check for corrupt asset backups", "check_corrupt_asset_backup": "Check for corrupt asset backups",
"check_corrupt_asset_backup_button": "Perform check", "check_corrupt_asset_backup_button": "Perform check",
"check_corrupt_asset_backup_description": "Run this check only over Wi-Fi and once all assets have been backed-up. The procedure might take a few minutes.", "check_corrupt_asset_backup_description": "Run this check only over Wi-Fi and once all assets have been backed-up. The procedure might take a few minutes.",
@@ -740,6 +753,7 @@
"create_user": "Create user", "create_user": "Create user",
"created": "Created", "created": "Created",
"created_at": "Created", "created_at": "Created",
"creating_linked_albums": "Creating linked albums...",
"crop": "Crop", "crop": "Crop",
"curated_object_page_title": "Things", "curated_object_page_title": "Things",
"current_device": "Current device", "current_device": "Current device",
@@ -889,7 +903,9 @@
"error": "Error", "error": "Error",
"error_change_sort_album": "Failed to change album sort order", "error_change_sort_album": "Failed to change album sort order",
"error_delete_face": "Error deleting face from asset", "error_delete_face": "Error deleting face from asset",
"error_getting_places": "Error getting places",
"error_loading_image": "Error loading image", "error_loading_image": "Error loading image",
"error_loading_partners": "Error loading partners: {error}",
"error_saving_image": "Error: {error}", "error_saving_image": "Error: {error}",
"error_tag_face_bounding_box": "Error tagging face - cannot get bounding box coordinates", "error_tag_face_bounding_box": "Error tagging face - cannot get bounding box coordinates",
"error_title": "Error - Something went wrong", "error_title": "Error - Something went wrong",
@@ -904,6 +920,7 @@
"cant_get_number_of_comments": "Can't get number of comments", "cant_get_number_of_comments": "Can't get number of comments",
"cant_search_people": "Can't search people", "cant_search_people": "Can't search people",
"cant_search_places": "Can't search places", "cant_search_places": "Can't search places",
"clipboard_unsupported_mime_type": "The system clipboard does not support copying this type of content: {mimeType}",
"error_adding_assets_to_album": "Error adding assets to album", "error_adding_assets_to_album": "Error adding assets to album",
"error_adding_users_to_album": "Error adding users to album", "error_adding_users_to_album": "Error adding users to album",
"error_deleting_shared_user": "Error deleting shared user", "error_deleting_shared_user": "Error deleting shared user",
@@ -1054,6 +1071,7 @@
"favorites_page_no_favorites": "No favorite assets found", "favorites_page_no_favorites": "No favorite assets found",
"feature_photo_updated": "Feature photo updated", "feature_photo_updated": "Feature photo updated",
"features": "Features", "features": "Features",
"features_in_development": "Features in Development",
"features_setting_description": "Manage the app features", "features_setting_description": "Manage the app features",
"file_name": "File name", "file_name": "File name",
"file_name_or_extension": "File name or extension", "file_name_or_extension": "File name or extension",
@@ -1218,6 +1236,7 @@
"local": "Local", "local": "Local",
"local_asset_cast_failed": "Unable to cast an asset that is not uploaded to the server", "local_asset_cast_failed": "Unable to cast an asset that is not uploaded to the server",
"local_assets": "Local Assets", "local_assets": "Local Assets",
"local_media_summary": "Local Media Summary",
"local_network": "Local network", "local_network": "Local network",
"local_network_sheet_info": "The app will connect to the server through this URL when using the specified Wi-Fi network", "local_network_sheet_info": "The app will connect to the server through this URL when using the specified Wi-Fi network",
"location_permission": "Location permission", "location_permission": "Location permission",
@@ -1229,6 +1248,7 @@
"location_picker_longitude_hint": "Enter your longitude here", "location_picker_longitude_hint": "Enter your longitude here",
"lock": "Lock", "lock": "Lock",
"locked_folder": "Locked Folder", "locked_folder": "Locked Folder",
"log_detail_title": "Log Detail",
"log_out": "Log out", "log_out": "Log out",
"log_out_all_devices": "Log Out All Devices", "log_out_all_devices": "Log Out All Devices",
"logged_in_as": "Logged in as {user}", "logged_in_as": "Logged in as {user}",
@@ -1259,6 +1279,7 @@
"login_password_changed_success": "Password updated successfully", "login_password_changed_success": "Password updated successfully",
"logout_all_device_confirmation": "Are you sure you want to log out all devices?", "logout_all_device_confirmation": "Are you sure you want to log out all devices?",
"logout_this_device_confirmation": "Are you sure you want to log out this device?", "logout_this_device_confirmation": "Are you sure you want to log out this device?",
"logs": "Logs",
"longitude": "Longitude", "longitude": "Longitude",
"look": "Look", "look": "Look",
"loop_videos": "Loop videos", "loop_videos": "Loop videos",
@@ -1301,6 +1322,7 @@
"mark_as_read": "Mark as read", "mark_as_read": "Mark as read",
"marked_all_as_read": "Marked all as read", "marked_all_as_read": "Marked all as read",
"matches": "Matches", "matches": "Matches",
"matching_assets": "Matching Assets",
"media_type": "Media type", "media_type": "Media type",
"memories": "Memories", "memories": "Memories",
"memories_all_caught_up": "All caught up", "memories_all_caught_up": "All caught up",
@@ -1341,6 +1363,7 @@
"name_or_nickname": "Name or nickname", "name_or_nickname": "Name or nickname",
"network_requirement_photos_upload": "Use cellular data to backup photos", "network_requirement_photos_upload": "Use cellular data to backup photos",
"network_requirement_videos_upload": "Use cellular data to backup videos", "network_requirement_videos_upload": "Use cellular data to backup videos",
"network_requirements": "Network Requirements",
"network_requirements_updated": "Network requirements changed, resetting backup queue", "network_requirements_updated": "Network requirements changed, resetting backup queue",
"networking_settings": "Networking", "networking_settings": "Networking",
"networking_subtitle": "Manage the server endpoint settings", "networking_subtitle": "Manage the server endpoint settings",
@@ -1351,6 +1374,7 @@
"new_person": "New person", "new_person": "New person",
"new_pin_code": "New PIN code", "new_pin_code": "New PIN code",
"new_pin_code_subtitle": "This is your first time accessing the locked folder. Create a PIN code to securely access this page", "new_pin_code_subtitle": "This is your first time accessing the locked folder. Create a PIN code to securely access this page",
"new_timeline": "New Timeline",
"new_user_created": "New user created", "new_user_created": "New user created",
"new_version_available": "NEW VERSION AVAILABLE", "new_version_available": "NEW VERSION AVAILABLE",
"newest_first": "Newest first", "newest_first": "Newest first",
@@ -1364,20 +1388,25 @@
"no_assets_message": "CLICK TO UPLOAD YOUR FIRST PHOTO", "no_assets_message": "CLICK TO UPLOAD YOUR FIRST PHOTO",
"no_assets_to_show": "No assets to show", "no_assets_to_show": "No assets to show",
"no_cast_devices_found": "No cast devices found", "no_cast_devices_found": "No cast devices found",
"no_checksum_local": "No checksum available - cannot fetch local assets",
"no_checksum_remote": "No checksum available - cannot fetch remote asset",
"no_duplicates_found": "No duplicates were found.", "no_duplicates_found": "No duplicates were found.",
"no_exif_info_available": "No exif info available", "no_exif_info_available": "No exif info available",
"no_explore_results_message": "Upload more photos to explore your collection.", "no_explore_results_message": "Upload more photos to explore your collection.",
"no_favorites_message": "Add favorites to quickly find your best pictures and videos", "no_favorites_message": "Add favorites to quickly find your best pictures and videos",
"no_libraries_message": "Create an external library to view your photos and videos", "no_libraries_message": "Create an external library to view your photos and videos",
"no_local_assets_found": "No local assets found with this checksum",
"no_locked_photos_message": "Photos and videos in the locked folder are hidden and won't show up as you browse or search your library.", "no_locked_photos_message": "Photos and videos in the locked folder are hidden and won't show up as you browse or search your library.",
"no_name": "No Name", "no_name": "No Name",
"no_notifications": "No notifications", "no_notifications": "No notifications",
"no_people_found": "No matching people found", "no_people_found": "No matching people found",
"no_places": "No places", "no_places": "No places",
"no_remote_assets_found": "No remote assets found with this checksum",
"no_results": "No results", "no_results": "No results",
"no_results_description": "Try a synonym or more general keyword", "no_results_description": "Try a synonym or more general keyword",
"no_shared_albums_message": "Create an album to share photos and videos with people in your network", "no_shared_albums_message": "Create an album to share photos and videos with people in your network",
"no_uploads_in_progress": "No uploads in progress", "no_uploads_in_progress": "No uploads in progress",
"not_available": "N/A",
"not_in_any_album": "Not in any album", "not_in_any_album": "Not in any album",
"not_selected": "Not selected", "not_selected": "Not selected",
"note_apply_storage_label_to_previously_uploaded assets": "Note: To apply the Storage Label to previously uploaded assets, run the", "note_apply_storage_label_to_previously_uploaded assets": "Note: To apply the Storage Label to previously uploaded assets, run the",
@@ -1588,6 +1617,7 @@
"regenerating_thumbnails": "Regenerating thumbnails", "regenerating_thumbnails": "Regenerating thumbnails",
"remote": "Remote", "remote": "Remote",
"remote_assets": "Remote Assets", "remote_assets": "Remote Assets",
"remote_media_summary": "Remote Media Summary",
"remove": "Remove", "remove": "Remove",
"remove_assets_album_confirmation": "Are you sure you want to remove {count, plural, one {# asset} other {# assets}} from the album?", "remove_assets_album_confirmation": "Are you sure you want to remove {count, plural, one {# asset} other {# assets}} from the album?",
"remove_assets_shared_link_confirmation": "Are you sure you want to remove {count, plural, one {# asset} other {# assets}} from this shared link?", "remove_assets_shared_link_confirmation": "Are you sure you want to remove {count, plural, one {# asset} other {# assets}} from this shared link?",
@@ -1863,6 +1893,7 @@
"show_slideshow_transition": "Show slideshow transition", "show_slideshow_transition": "Show slideshow transition",
"show_supporter_badge": "Supporter badge", "show_supporter_badge": "Supporter badge",
"show_supporter_badge_description": "Show a supporter badge", "show_supporter_badge_description": "Show a supporter badge",
"show_text_search_menu": "Show text search menu",
"shuffle": "Shuffle", "shuffle": "Shuffle",
"sidebar": "Sidebar", "sidebar": "Sidebar",
"sidebar_display_description": "Display a link to the view in the sidebar", "sidebar_display_description": "Display a link to the view in the sidebar",
@@ -1893,6 +1924,7 @@
"stacktrace": "Stacktrace", "stacktrace": "Stacktrace",
"start": "Start", "start": "Start",
"start_date": "Start date", "start_date": "Start date",
"start_date_before_end_date": "Start date must be before end date",
"state": "State", "state": "State",
"status": "Status", "status": "Status",
"stop_casting": "Stop casting", "stop_casting": "Stop casting",
@@ -2095,5 +2127,6 @@
"yes": "Yes", "yes": "Yes",
"you_dont_have_any_shared_links": "You don't have any shared links", "you_dont_have_any_shared_links": "You don't have any shared links",
"your_wifi_name": "Your Wi-Fi name", "your_wifi_name": "Your Wi-Fi name",
"zoom_image": "Zoom Image" "zoom_image": "Zoom Image",
"zoom_to_bounds": "Zoom to bounds"
} }

View File

@@ -38,7 +38,7 @@
"added_to_favorites_count": "Agregado {count, number} a favoritos", "added_to_favorites_count": "Agregado {count, number} a favoritos",
"admin": { "admin": {
"add_exclusion_pattern_description": "Agrega patrones de exclusión. Puedes utilizar los caracteres *, ** y ? (globbing). Ejemplos: para ignorar todos los archivos en cualquier directorio llamado \"Raw\", utiliza \"**/Raw/**\". Para ignorar todos los archivos que terminan en \".tif\", utiliza \"**/*.tif\". Para ignorar una ruta absoluta, utiliza \"/carpeta/a/ignorar/**\".", "add_exclusion_pattern_description": "Agrega patrones de exclusión. Puedes utilizar los caracteres *, ** y ? (globbing). Ejemplos: para ignorar todos los archivos en cualquier directorio llamado \"Raw\", utiliza \"**/Raw/**\". Para ignorar todos los archivos que terminan en \".tif\", utiliza \"**/*.tif\". Para ignorar una ruta absoluta, utiliza \"/carpeta/a/ignorar/**\".",
"admin_user": "Usuario administrativo", "admin_user": "Usuario administrador",
"asset_offline_description": "Este recurso externo de la biblioteca ya no se encuentra en el disco y se ha movido a la papelera. Si el archivo se movió dentro de la biblioteca, comprueba la línea temporal para el nuevo recurso correspondiente. Para restaurar este recurso, asegúrate de que Immich puede acceder a la siguiente ruta de archivo y escanear la biblioteca.", "asset_offline_description": "Este recurso externo de la biblioteca ya no se encuentra en el disco y se ha movido a la papelera. Si el archivo se movió dentro de la biblioteca, comprueba la línea temporal para el nuevo recurso correspondiente. Para restaurar este recurso, asegúrate de que Immich puede acceder a la siguiente ruta de archivo y escanear la biblioteca.",
"authentication_settings": "Parámetros de autenticación", "authentication_settings": "Parámetros de autenticación",
"authentication_settings_description": "Gestionar contraseñas, OAuth y otros parámetros de autenticación", "authentication_settings_description": "Gestionar contraseñas, OAuth y otros parámetros de autenticación",
@@ -1515,7 +1515,7 @@
"profile_drawer_client_out_of_date_minor": "La app está desactualizada. Por favor actualiza a la última versión menor.", "profile_drawer_client_out_of_date_minor": "La app está desactualizada. Por favor actualiza a la última versión menor.",
"profile_drawer_client_server_up_to_date": "Cliente y Servidor están actualizados", "profile_drawer_client_server_up_to_date": "Cliente y Servidor están actualizados",
"profile_drawer_github": "GitHub", "profile_drawer_github": "GitHub",
"profile_drawer_readonly_mode": "Modo Solo lectura habilitado. Toque dos veces el ícono del avatar del usuario para salir.", "profile_drawer_readonly_mode": "Modo Solo lectura habilitado. Mantén pulsado el icono del avatar del usuario para salir.",
"profile_drawer_server_out_of_date_major": "El servidor está desactualizado. Por favor actualiza a la última versión principal.", "profile_drawer_server_out_of_date_major": "El servidor está desactualizado. Por favor actualiza a la última versión principal.",
"profile_drawer_server_out_of_date_minor": "El servidor está desactualizado. Por favor actualiza a la última versión menor.", "profile_drawer_server_out_of_date_minor": "El servidor está desactualizado. Por favor actualiza a la última versión menor.",
"profile_image_of_user": "Foto de perfil de {user}", "profile_image_of_user": "Foto de perfil de {user}",
@@ -1917,6 +1917,8 @@
"sync_albums_manual_subtitle": "Sincroniza todos los videos y fotos subidos con los álbumes seleccionados a respaldar", "sync_albums_manual_subtitle": "Sincroniza todos los videos y fotos subidos con los álbumes seleccionados a respaldar",
"sync_local": "Sincronización Local", "sync_local": "Sincronización Local",
"sync_remote": "Sincronización Remota", "sync_remote": "Sincronización Remota",
"sync_status": "Estado de la sincronización",
"sync_status_subtitle": "Ver y gestionar el estado de la sincronización",
"sync_upload_album_setting_subtitle": "Crea y sube tus fotos y videos a los álbumes seleccionados en Immich", "sync_upload_album_setting_subtitle": "Crea y sube tus fotos y videos a los álbumes seleccionados en Immich",
"tag": "Etiqueta", "tag": "Etiqueta",
"tag_assets": "Etiquetar activos", "tag_assets": "Etiquetar activos",
@@ -1976,6 +1978,7 @@
"trash_page_select_assets_btn": "Seleccionar elementos", "trash_page_select_assets_btn": "Seleccionar elementos",
"trash_page_title": "Papelera ({count})", "trash_page_title": "Papelera ({count})",
"trashed_items_will_be_permanently_deleted_after": "Los elementos en la papelera serán eliminados permanentemente tras {days, plural, one {# día} other {# días}}.", "trashed_items_will_be_permanently_deleted_after": "Los elementos en la papelera serán eliminados permanentemente tras {days, plural, one {# día} other {# días}}.",
"troubleshoot": "Solucionar problemas",
"type": "Tipo", "type": "Tipo",
"unable_to_change_pin_code": "No se ha podido cambiar el PIN", "unable_to_change_pin_code": "No se ha podido cambiar el PIN",
"unable_to_setup_pin_code": "No se ha podido establecer el PIN", "unable_to_setup_pin_code": "No se ha podido establecer el PIN",

View File

@@ -42,6 +42,7 @@
"authentication_settings_description": "Kudeatu pasahitza, OAuth edo beste segurtasun konfigurazio bat", "authentication_settings_description": "Kudeatu pasahitza, OAuth edo beste segurtasun konfigurazio bat",
"authentication_settings_disable_all": "Seguru zaude saioa hasteko modu guztiak desgaitu nahi dituzula? Saioa hastea guztiz desgaitua izango da.", "authentication_settings_disable_all": "Seguru zaude saioa hasteko modu guztiak desgaitu nahi dituzula? Saioa hastea guztiz desgaitua izango da.",
"authentication_settings_reenable": "Berriro gaitzeko, erabili <link>Server Command</link>.", "authentication_settings_reenable": "Berriro gaitzeko, erabili <link>Server Command</link>.",
"background_task_job": "Atzealdeko Lanak",
"backup_onboarding_footer": "Immich-en babes kopiei buruzko informazio gehiago nahi baduzu, mesedez irakurri <link>dokumentazioa</link>.", "backup_onboarding_footer": "Immich-en babes kopiei buruzko informazio gehiago nahi baduzu, mesedez irakurri <link>dokumentazioa</link>.",
"backup_onboarding_title": "Babes Kopiak", "backup_onboarding_title": "Babes Kopiak",
"confirm_delete_library": "Seguru zaude {library} ezabatu nahi duzula?", "confirm_delete_library": "Seguru zaude {library} ezabatu nahi duzula?",
@@ -62,6 +63,15 @@
"job_created": "Zeregina sortuta", "job_created": "Zeregina sortuta",
"job_settings": "Zereginaren konfigurazioa", "job_settings": "Zereginaren konfigurazioa",
"job_status": "Zereginaren Egoera", "job_status": "Zereginaren Egoera",
"logging_enable_description": "Gaitu erregistroak",
"logging_level_description": "Erregistroak gaituta daudenean, nolako erregistro maila erabili.",
"logging_settings": "Erregistroak",
"machine_learning_duplicate_detection": "Bizkoizketa Detekzioa",
"machine_learning_duplicate_detection_enabled": "Gaitu bikoizketa detekezioa",
"machine_learning_facial_recognition": "Aurpegi-Ezagutza",
"machine_learning_facial_recognition_description": "Detektatu, ezagutu eta aurpegiak banatu argazkietan",
"machine_learning_facial_recognition_model": "Aurpegi-Ezagutza eredua",
"machine_learning_facial_recognition_setting": "Aurpegi-Ezagutza Gaitu",
"machine_learning_smart_search_enabled": "Gaitu bilaketa arina", "machine_learning_smart_search_enabled": "Gaitu bilaketa arina",
"manage_log_settings": "Kudeatu erregistroen konfigurazioa", "manage_log_settings": "Kudeatu erregistroen konfigurazioa",
"map_dark_style": "Beltz estiloa", "map_dark_style": "Beltz estiloa",

View File

@@ -389,7 +389,7 @@
"advanced": "Avancé", "advanced": "Avancé",
"advanced_settings_beta_timeline_subtitle": "Essayer la nouvelle application", "advanced_settings_beta_timeline_subtitle": "Essayer la nouvelle application",
"advanced_settings_beta_timeline_title": "Timeline de la béta", "advanced_settings_beta_timeline_title": "Timeline de la béta",
"advanced_settings_enable_alternate_media_filter_subtitle": "Utilisez cette option pour filtrer les média durant la synchronisation avec des critères alternatifs. N'utilisez cela que lorsque l'application n'arrive pas à détecter tout les albums.", "advanced_settings_enable_alternate_media_filter_subtitle": "Utilisez cette option pour filtrer les média durant la synchronisation avec des critères alternatifs. N'utilisez cela que lorsque l'application n'arrive pas à détecter tous les albums.",
"advanced_settings_enable_alternate_media_filter_title": "[EXPÉRIMENTAL] Utiliser le filtre de synchronisation d'album alternatif", "advanced_settings_enable_alternate_media_filter_title": "[EXPÉRIMENTAL] Utiliser le filtre de synchronisation d'album alternatif",
"advanced_settings_log_level_title": "Niveau de journalisation : {level}", "advanced_settings_log_level_title": "Niveau de journalisation : {level}",
"advanced_settings_prefer_remote_subtitle": "Certains appareils sont très lents à charger des miniatures à partir de ressources locales. Activez ce paramètre pour charger des images externes à la place.", "advanced_settings_prefer_remote_subtitle": "Certains appareils sont très lents à charger des miniatures à partir de ressources locales. Activez ce paramètre pour charger des images externes à la place.",
@@ -1964,7 +1964,7 @@
"total": "Total", "total": "Total",
"total_usage": "Utilisation globale", "total_usage": "Utilisation globale",
"trash": "Corbeille", "trash": "Corbeille",
"trash_action_prompt": "{count} mis à la corbeille", "trash_action_prompt": "{count} média(s) mis à la corbeille",
"trash_all": "Tout supprimer", "trash_all": "Tout supprimer",
"trash_count": "Corbeille {count, number}", "trash_count": "Corbeille {count, number}",
"trash_delete_asset": "Mettre à la corbeille/Supprimer un média", "trash_delete_asset": "Mettre à la corbeille/Supprimer un média",

View File

@@ -14,6 +14,7 @@
"add_a_location": "Engadir unha ubicación", "add_a_location": "Engadir unha ubicación",
"add_a_name": "Engadir un nome", "add_a_name": "Engadir un nome",
"add_a_title": "Engadir un título", "add_a_title": "Engadir un título",
"add_birthday": "Engadir cumpleanos",
"add_endpoint": "Engadir endpoint", "add_endpoint": "Engadir endpoint",
"add_exclusion_pattern": "Engadir patrón de exclusión", "add_exclusion_pattern": "Engadir patrón de exclusión",
"add_import_path": "Engadir ruta de importación", "add_import_path": "Engadir ruta de importación",
@@ -22,10 +23,14 @@
"add_partner": "Engadir compañeiro/a", "add_partner": "Engadir compañeiro/a",
"add_path": "Engadir ruta", "add_path": "Engadir ruta",
"add_photos": "Engadir fotos", "add_photos": "Engadir fotos",
"add_tag": "Engadir etiqueta",
"add_to": "Engadir a…", "add_to": "Engadir a…",
"add_to_album": "Engadir ao álbum", "add_to_album": "Engadir ao álbum",
"add_to_album_bottom_sheet_added": "Engadido a {album}", "add_to_album_bottom_sheet_added": "Engadido a {album}",
"add_to_album_bottom_sheet_already_exists": "Xa está en {album}", "add_to_album_bottom_sheet_already_exists": "Xa está en {album}",
"add_to_album_toggle": "Alternar selección para o {album}",
"add_to_albums": "Engadir en álbums",
"add_to_albums_count": "Engadir a {count} álbums",
"add_to_shared_album": "Engadir ao álbum compartido", "add_to_shared_album": "Engadir ao álbum compartido",
"add_url": "Engadir URL", "add_url": "Engadir URL",
"added_to_archive": "Engadido ao arquivo", "added_to_archive": "Engadido ao arquivo",
@@ -33,6 +38,7 @@
"added_to_favorites_count": "Engadido {count, number} a favoritos", "added_to_favorites_count": "Engadido {count, number} a favoritos",
"admin": { "admin": {
"add_exclusion_pattern_description": "Engadir patróns de exclusión. Admítense caracteres comodín usando *, ** e ?. Para ignorar todos os ficheiros en calquera directorio chamado \"Raw\", emprega \"**/Raw/**\". Para ignorar todos os ficheiros que rematen en \".tif\", usa \"**/*.tif\". Para ignorar unha ruta absoluta, emprega \"/ruta/a/ignorar/**\".", "add_exclusion_pattern_description": "Engadir patróns de exclusión. Admítense caracteres comodín usando *, ** e ?. Para ignorar todos os ficheiros en calquera directorio chamado \"Raw\", emprega \"**/Raw/**\". Para ignorar todos os ficheiros que rematen en \".tif\", usa \"**/*.tif\". Para ignorar unha ruta absoluta, emprega \"/ruta/a/ignorar/**\".",
"admin_user": "Usuario administrador",
"asset_offline_description": "Este activo da biblioteca externa xa non se atopa no disco e moveuse ao lixo. Se o ficheiro se moveu dentro da biblioteca, comproba a túa liña de tempo para o novo activo correspondente. Para restaurar este activo, asegúrate de que Immich poida acceder á ruta do ficheiro a continuación e escanee a biblioteca.", "asset_offline_description": "Este activo da biblioteca externa xa non se atopa no disco e moveuse ao lixo. Se o ficheiro se moveu dentro da biblioteca, comproba a túa liña de tempo para o novo activo correspondente. Para restaurar este activo, asegúrate de que Immich poida acceder á ruta do ficheiro a continuación e escanee a biblioteca.",
"authentication_settings": "Configuración de autenticación", "authentication_settings": "Configuración de autenticación",
"authentication_settings_description": "Xestionar contrasinal, OAuth e outras configuracións de autenticación", "authentication_settings_description": "Xestionar contrasinal, OAuth e outras configuracións de autenticación",

View File

@@ -1093,7 +1093,7 @@
"haptic_feedback_switch": "אפשר משוב ברטט", "haptic_feedback_switch": "אפשר משוב ברטט",
"haptic_feedback_title": "משוב ברטט", "haptic_feedback_title": "משוב ברטט",
"has_quota": "יש מכסה", "has_quota": "יש מכסה",
"hash_asset": יבוב תמונה", "hash_asset": בב פריט",
"hashed_assets": "תמונות מגובבות", "hashed_assets": "תמונות מגובבות",
"hashing": "מגבב", "hashing": "מגבב",
"header_settings_add_header_tip": "הוסף כותרת", "header_settings_add_header_tip": "הוסף כותרת",
@@ -1129,7 +1129,7 @@
"hour": "שעה", "hour": "שעה",
"hours": "שעות", "hours": "שעות",
"id": "מזהה", "id": "מזהה",
"idle": "ממתין", "idle": "במצב סרק",
"ignore_icloud_photos": "התעלם מתמונות iCloud", "ignore_icloud_photos": "התעלם מתמונות iCloud",
"ignore_icloud_photos_description": "תמונות שמאוחסנות ב-iCloud לא יועלו לשרת", "ignore_icloud_photos_description": "תמונות שמאוחסנות ב-iCloud לא יועלו לשרת",
"image": "תמונה", "image": "תמונה",
@@ -1412,6 +1412,8 @@
"open_the_search_filters": "פתח את מסנני החיפוש", "open_the_search_filters": "פתח את מסנני החיפוש",
"options": "אפשרויות", "options": "אפשרויות",
"or": "או", "or": "או",
"organize_into_albums": "ארגן בתוך אלבומים",
"organize_into_albums_description": "שים תמונות קיימות בתוך אלבומים באמצעות הגדרות הסנכרון הנוכחיות",
"organize_your_library": "ארגן את הספרייה שלך", "organize_your_library": "ארגן את הספרייה שלך",
"original": "מקורי", "original": "מקורי",
"other": "אחר", "other": "אחר",
@@ -1471,9 +1473,9 @@
"permission_onboarding_permission_limited": "הרשאה מוגבלת. כדי לתת ליישום לגבות ולנהל את כל אוסף הגלריה שלך, הענק הרשאה לתמונות וסרטונים בהגדרות.", "permission_onboarding_permission_limited": "הרשאה מוגבלת. כדי לתת ליישום לגבות ולנהל את כל אוסף הגלריה שלך, הענק הרשאה לתמונות וסרטונים בהגדרות.",
"permission_onboarding_request": "היישום דורש הרשאה כדי לראות את התמונות והסרטונים שלך.", "permission_onboarding_request": "היישום דורש הרשאה כדי לראות את התמונות והסרטונים שלך.",
"person": "אדם", "person": "אדם",
"person_age_months": ן {months, plural, one {חודש #} other {# חודשים}}", "person_age_months": גיל {months, plural, one {חודש #} other {# חודשים}}",
"person_age_year_months": ן שנה, {months, plural, one {חודש #} other {# חודשים}}", "person_age_year_months": גיל שנה ו{months, plural, one {חודש #} other {# חודשים}}",
"person_age_years": ן {years, plural, other {# שנים}}", "person_age_years": גיל {years, plural, other {# שנים}}",
"person_birthdate": "נולד בתאריך {date}", "person_birthdate": "נולד בתאריך {date}",
"person_hidden": "{name}{hidden, select, true { (מוסתר)} other {}}", "person_hidden": "{name}{hidden, select, true { (מוסתר)} other {}}",
"photo_shared_all_users": "נראה ששיתפת את התמונות שלך עם כל המשתמשים או שאין לך אף משתמש לשתף איתו.", "photo_shared_all_users": "נראה ששיתפת את התמונות שלך עם כל המשתמשים או שאין לך אף משתמש לשתף איתו.",
@@ -1513,7 +1515,7 @@
"profile_drawer_client_out_of_date_minor": "גרסת היישום לנייד מיושנת. נא לעדכן לגרסה המשנית האחרונה.", "profile_drawer_client_out_of_date_minor": "גרסת היישום לנייד מיושנת. נא לעדכן לגרסה המשנית האחרונה.",
"profile_drawer_client_server_up_to_date": "היישום והשרת מעודכנים", "profile_drawer_client_server_up_to_date": "היישום והשרת מעודכנים",
"profile_drawer_github": "GitHub", "profile_drawer_github": "GitHub",
"profile_drawer_readonly_mode": "מצב לקריאה בלבד מופעל. הקש הקשה כפולה על סמל היצגן של המשתמש כדי לצאת.", "profile_drawer_readonly_mode": "מצב לקריאה בלבד מופעל. לחץ לחיצה ארוכה על סמל היצגן של המשתמש כדי לצאת.",
"profile_drawer_server_out_of_date_major": "השרת אינו מעודכן. נא לעדכן לגרסה הראשית האחרונה.", "profile_drawer_server_out_of_date_major": "השרת אינו מעודכן. נא לעדכן לגרסה הראשית האחרונה.",
"profile_drawer_server_out_of_date_minor": "השרת אינו מעודכן. נא לעדכן לגרסה המשנית האחרונה.", "profile_drawer_server_out_of_date_minor": "השרת אינו מעודכן. נא לעדכן לגרסה המשנית האחרונה.",
"profile_image_of_user": "תמונת פרופיל של {user}", "profile_image_of_user": "תמונת פרופיל של {user}",
@@ -1552,7 +1554,8 @@
"purchase_server_description_2": "מעמד תומך", "purchase_server_description_2": "מעמד תומך",
"purchase_server_title": "שרת", "purchase_server_title": "שרת",
"purchase_settings_server_activated": "מפתח המוצר של השרת מנוהל על ידי מנהל המערכת", "purchase_settings_server_activated": "מפתח המוצר של השרת מנוהל על ידי מנהל המערכת",
"queue_status": "בתור {count}/{total}", "query_asset_id": "שאילתה על מזהה הפריט",
"queue_status": "{count} מתוך {total} עומדים בתור",
"rating": "דירוג כוכב", "rating": "דירוג כוכב",
"rating_clear": "נקה דירוג", "rating_clear": "נקה דירוג",
"rating_count": "{count, plural, one {כוכב #} other {# כוכבים}}", "rating_count": "{count, plural, one {כוכב #} other {# כוכבים}}",
@@ -1637,6 +1640,7 @@
"restore_user": "שחזר משתמש", "restore_user": "שחזר משתמש",
"restored_asset": "התמונה שוחזרה", "restored_asset": "התמונה שוחזרה",
"resume": "המשך", "resume": "המשך",
"resume_paused_jobs": "המשך {count, plural, one {עבודה # שהופסקה} other {# עבודות שהופסקו}}",
"retry_upload": "נסה שוב להעלות", "retry_upload": "נסה שוב להעלות",
"review_duplicates": "בדוק כפילויות", "review_duplicates": "בדוק כפילויות",
"review_large_files": "צפייה בקבצים גדולים", "review_large_files": "צפייה בקבצים גדולים",
@@ -1903,7 +1907,7 @@
"submit": "שלח", "submit": "שלח",
"success": "בוצע בהצלחה", "success": "בוצע בהצלחה",
"suggestions": "הצעות", "suggestions": "הצעות",
"sunrise_on_the_beach": "Sunrise on the beach (מומלץ לחפש באנגלית לתוצאות טובות יותר)", "sunrise_on_the_beach": "שקיעה בחוף",
"support": "תמיכה", "support": "תמיכה",
"support_and_feedback": "תמיכה & משוב", "support_and_feedback": "תמיכה & משוב",
"support_third_party_description": "התקנת ה-Immich שלך נארזה על ידי צד שלישי. בעיות שאתה חווה עשויות להיגרם על ידי חבילה זו, אז בבקשה תעלה בעיות איתם ראשית כל באמצעות הקישורים למטה.", "support_third_party_description": "התקנת ה-Immich שלך נארזה על ידי צד שלישי. בעיות שאתה חווה עשויות להיגרם על ידי חבילה זו, אז בבקשה תעלה בעיות איתם ראשית כל באמצעות הקישורים למטה.",
@@ -1912,7 +1916,9 @@
"sync_albums": "סנכרן אלבומים", "sync_albums": "סנכרן אלבומים",
"sync_albums_manual_subtitle": "סנכרן את כל הסרטונים והתמונות שהועלו לאלבומי הגיבוי שנבחרו", "sync_albums_manual_subtitle": "סנכרן את כל הסרטונים והתמונות שהועלו לאלבומי הגיבוי שנבחרו",
"sync_local": "סנכרן מקומי", "sync_local": "סנכרן מקומי",
"sync_remote": "סנכרן מרוחק", "sync_remote": "סנכרן נקודת קצה מרוחקת",
"sync_status": "סנכרן מצב",
"sync_status_subtitle": "הצג ונהל את מערכת הסנכרון",
"sync_upload_album_setting_subtitle": "צור והעלה תמונות וסרטונים שלך לאלבומים שנבחרו ביישום", "sync_upload_album_setting_subtitle": "צור והעלה תמונות וסרטונים שלך לאלבומים שנבחרו ביישום",
"tag": "תג", "tag": "תג",
"tag_assets": "תיוג תמונות", "tag_assets": "תיוג תמונות",
@@ -1972,6 +1978,7 @@
"trash_page_select_assets_btn": "בחר תמונות", "trash_page_select_assets_btn": "בחר תמונות",
"trash_page_title": "אשפה ({count})", "trash_page_title": "אשפה ({count})",
"trashed_items_will_be_permanently_deleted_after": "פריטים באשפה ימחקו לצמיתות לאחר {days, plural, one {יום #} other {# ימים}}.", "trashed_items_will_be_permanently_deleted_after": "פריטים באשפה ימחקו לצמיתות לאחר {days, plural, one {יום #} other {# ימים}}.",
"troubleshoot": "פתור בעיות",
"type": "סוג", "type": "סוג",
"unable_to_change_pin_code": "לא ניתן לשנות את קוד ה PIN", "unable_to_change_pin_code": "לא ניתן לשנות את קוד ה PIN",
"unable_to_setup_pin_code": "לא ניתן להגדיר קוד PIN", "unable_to_setup_pin_code": "לא ניתן להגדיר קוד PIN",
@@ -2069,6 +2076,7 @@
"view_next_asset": "הצג את התמונה הבאה", "view_next_asset": "הצג את התמונה הבאה",
"view_previous_asset": "הצג את התמונה הקודמת", "view_previous_asset": "הצג את התמונה הקודמת",
"view_qr_code": "הצג ברקוד", "view_qr_code": "הצג ברקוד",
"view_similar_photos": "הצג תמונות דומות",
"view_stack": "הצג ערימה", "view_stack": "הצג ערימה",
"view_user": "הצג משתמש", "view_user": "הצג משתמש",
"viewer_remove_from_stack": "הסר מערימה", "viewer_remove_from_stack": "הסר מערימה",

View File

@@ -1515,7 +1515,7 @@
"profile_drawer_client_out_of_date_minor": "L'applicazione non è aggiornata. Aggiorna all'ultima versione minore.", "profile_drawer_client_out_of_date_minor": "L'applicazione non è aggiornata. Aggiorna all'ultima versione minore.",
"profile_drawer_client_server_up_to_date": "Client e server sono aggiornati", "profile_drawer_client_server_up_to_date": "Client e server sono aggiornati",
"profile_drawer_github": "GitHub", "profile_drawer_github": "GitHub",
"profile_drawer_readonly_mode": "Modalità di sola lettura abilitata. Tocca due volte l'icona dell'avatar dell'utente per disabilitarla.", "profile_drawer_readonly_mode": "Modalità di sola lettura abilitata. Tieni premuto sull'avatar dell'utente per disabilitarla.",
"profile_drawer_server_out_of_date_major": "Il server non è aggiornato. Aggiorna all'ultima versione principale.", "profile_drawer_server_out_of_date_major": "Il server non è aggiornato. Aggiorna all'ultima versione principale.",
"profile_drawer_server_out_of_date_minor": "Il server non è aggiornato. Aggiorna all'ultima versione minore.", "profile_drawer_server_out_of_date_minor": "Il server non è aggiornato. Aggiorna all'ultima versione minore.",
"profile_image_of_user": "Immagine profilo di {user}", "profile_image_of_user": "Immagine profilo di {user}",

View File

@@ -1473,9 +1473,9 @@
"permission_onboarding_permission_limited": "写真へのアクセスが制限されています。Immichが写真のバックアップと管理を行うには、システム設定から写真と動画のアクセス権限を変更してください。", "permission_onboarding_permission_limited": "写真へのアクセスが制限されています。Immichが写真のバックアップと管理を行うには、システム設定から写真と動画のアクセス権限を変更してください。",
"permission_onboarding_request": "Immichは写真へのアクセス許可が必要です", "permission_onboarding_request": "Immichは写真へのアクセス許可が必要です",
"person": "人物", "person": "人物",
"person_age_months": "{months, plural, one {# ヶ月} other {# ヶ月}}", "person_age_months": "生後 {months, plural, one {# ヶ月} other {# ヶ月}}",
"person_age_year_months": "1 , {months, plural, one {# ヶ月} other {# ヶ月}}", "person_age_year_months": "1 歳と, {months, plural, one {# ヶ月} other {# ヶ月}}",
"person_age_years": "{years, plural, other {# }}", "person_age_years": "{years, plural, other {# }}",
"person_birthdate": "{date}生まれ", "person_birthdate": "{date}生まれ",
"person_hidden": "{name}{hidden, select, true { (非表示)} other {}}", "person_hidden": "{name}{hidden, select, true { (非表示)} other {}}",
"photo_shared_all_users": "写真をすべてのユーザーと共有したか、共有するユーザーがいないようです。", "photo_shared_all_users": "写真をすべてのユーザーと共有したか、共有するユーザーがいないようです。",
@@ -1515,7 +1515,7 @@
"profile_drawer_client_out_of_date_minor": "アプリが更新されてません。最新のバージョンに更新してください", "profile_drawer_client_out_of_date_minor": "アプリが更新されてません。最新のバージョンに更新してください",
"profile_drawer_client_server_up_to_date": "すべて最新版です", "profile_drawer_client_server_up_to_date": "すべて最新版です",
"profile_drawer_github": "GitHub", "profile_drawer_github": "GitHub",
"profile_drawer_readonly_mode": "読み取り専用モードが有効です。ユーザーのアイコンをダブルタップして読み取り専用モードを解除してください。", "profile_drawer_readonly_mode": "読み取り専用モードが有効です。ユーザーのアイコンを長押しして読み取り専用モードを解除してください。",
"profile_drawer_server_out_of_date_major": "サーバーが更新されてません。最新のバージョンに更新してください", "profile_drawer_server_out_of_date_major": "サーバーが更新されてません。最新のバージョンに更新してください",
"profile_drawer_server_out_of_date_minor": "サーバーが更新されてません。最新のバージョンに更新してください", "profile_drawer_server_out_of_date_minor": "サーバーが更新されてません。最新のバージョンに更新してください",
"profile_image_of_user": "{user} のプロフィール画像", "profile_image_of_user": "{user} のプロフィール画像",
@@ -1640,6 +1640,7 @@
"restore_user": "ユーザーを復元", "restore_user": "ユーザーを復元",
"restored_asset": "項目を復元しました", "restored_asset": "項目を復元しました",
"resume": "再開", "resume": "再開",
"resume_paused_jobs": "再開: {count, plural, one {# paused job} other {# paused jobs}}",
"retry_upload": "アップロードを再試行", "retry_upload": "アップロードを再試行",
"review_duplicates": "重複を調査", "review_duplicates": "重複を調査",
"review_large_files": "サイズの大きなファイルを見る", "review_large_files": "サイズの大きなファイルを見る",
@@ -1916,6 +1917,8 @@
"sync_albums_manual_subtitle": "アップロード済みの全ての写真や動画を選択されたバックアップアルバムに同期する", "sync_albums_manual_subtitle": "アップロード済みの全ての写真や動画を選択されたバックアップアルバムに同期する",
"sync_local": "ローカルを同期", "sync_local": "ローカルを同期",
"sync_remote": "リモートを同期", "sync_remote": "リモートを同期",
"sync_status": "同期の状態",
"sync_status_subtitle": "同期システムを確認・管理",
"sync_upload_album_setting_subtitle": "サーバー上のアルバムの内容を端末上のアルバムと同期します (サーバーにアルバムが無い場合自動で作成されます。また、アップロードされていない写真や動画は同期されません)", "sync_upload_album_setting_subtitle": "サーバー上のアルバムの内容を端末上のアルバムと同期します (サーバーにアルバムが無い場合自動で作成されます。また、アップロードされていない写真や動画は同期されません)",
"tag": "タグ付けする", "tag": "タグ付けする",
"tag_assets": "アセットにタグ付けする", "tag_assets": "アセットにタグ付けする",
@@ -1975,6 +1978,7 @@
"trash_page_select_assets_btn": "項目を選択", "trash_page_select_assets_btn": "項目を選択",
"trash_page_title": "ゴミ箱 ({count})", "trash_page_title": "ゴミ箱 ({count})",
"trashed_items_will_be_permanently_deleted_after": "ゴミ箱に入れられたアイテムは{days, plural, one {#日} other {#日}}後に完全に削除されます。", "trashed_items_will_be_permanently_deleted_after": "ゴミ箱に入れられたアイテムは{days, plural, one {#日} other {#日}}後に完全に削除されます。",
"troubleshoot": "トラブルシューティング",
"type": "タイプ", "type": "タイプ",
"unable_to_change_pin_code": "PINコードを変更できませんでした", "unable_to_change_pin_code": "PINコードを変更できませんでした",
"unable_to_setup_pin_code": "PINコードをセットアップできませんでした", "unable_to_setup_pin_code": "PINコードをセットアップできませんでした",
@@ -2024,7 +2028,7 @@
"upload_success": "アップロード成功、新しくアップロードされたアセットを見るにはページを更新してください。", "upload_success": "アップロード成功、新しくアップロードされたアセットを見るにはページを更新してください。",
"upload_to_immich": "Immichにアップロード ({count})", "upload_to_immich": "Immichにアップロード ({count})",
"uploading": "アップロード中", "uploading": "アップロード中",
"uploading_media": "メディアをアップロード", "uploading_media": "メディアをアップロード",
"url": "URL", "url": "URL",
"usage": "使用容量", "usage": "使用容量",
"use_biometric": "生体認証をご利用ください", "use_biometric": "生体認証をご利用ください",

View File

@@ -28,13 +28,16 @@
"add_to_album": "Pridėti į albumą", "add_to_album": "Pridėti į albumą",
"add_to_album_bottom_sheet_added": "Pridėta į {album}", "add_to_album_bottom_sheet_added": "Pridėta į {album}",
"add_to_album_bottom_sheet_already_exists": "Jau yra albume {album}", "add_to_album_bottom_sheet_already_exists": "Jau yra albume {album}",
"add_to_album_toggle": "Perjungti pažymėjimus albumui {album}",
"add_to_albums": "Pridėti į albumus",
"add_to_albums_count": "Pridėti į albumus ({count})",
"add_to_shared_album": "Pridėti į bendrinamą albumą", "add_to_shared_album": "Pridėti į bendrinamą albumą",
"add_url": "Pridėti URL", "add_url": "Pridėti URL",
"added_to_archive": "Pridėta į archyvą", "added_to_archive": "Pridėta į archyvą",
"added_to_favorites": "Pridėta prie mėgstamiausių", "added_to_favorites": "Pridėta prie mėgstamiausių",
"added_to_favorites_count": "{count, plural, one {# pridėtas} few {# pridėti} other {# pridėta}} prie mėgstamiausių", "added_to_favorites_count": "{count, plural, one {# pridėtas} few {# pridėti} other {# pridėta}} prie mėgstamiausių",
"admin": { "admin": {
"add_exclusion_pattern_description": "Pridėti išimčių taisyklęs. Plaikomi simboliai *,**, ir ?. Ignoruoti bet kokius failus bet kuriame aplanke vadintame \"Raw\", naudokite \"**/RAW/**\". Ignoravimui failų su plėtiniu \".tif\", naudokite \"**/*.tiff\". Aplanko kelio nustatymams, naudokite \"/aplanko/kelias/ignoruoti/**\"", "add_exclusion_pattern_description": "Pridėti išimčių taisykles. Palaikomi simboliai *,**, ir ?. Ignoruoti bet kokius failus bet kuriame aplanke pavadintame \"Raw\", naudokite \"**/RAW/**\". Ignoravimui failų su plėtiniu \".tif\", naudokite \"**/*.tiff\". Aplanko kelio nustatymams, naudokite \"/aplanko/kelias/ignoruoti/**\".",
"admin_user": "Administratorius", "admin_user": "Administratorius",
"asset_offline_description": "Šis išorinės bibliotekos elementas nebepasiekiamas diske ir buvo perkeltas į šiukšliadėžę. Jei failas buvo perkeltas toje pačioje bibliotekoje, laiko skalėje rasite naują atitinkamą elementą. Jei norite šį elementą atkurti, įsitikinkite, kad Immich gali pasiekti failą žemiau nurodytu adresu, ir suvykdykite bibliotekos skenavimą.", "asset_offline_description": "Šis išorinės bibliotekos elementas nebepasiekiamas diske ir buvo perkeltas į šiukšliadėžę. Jei failas buvo perkeltas toje pačioje bibliotekoje, laiko skalėje rasite naują atitinkamą elementą. Jei norite šį elementą atkurti, įsitikinkite, kad Immich gali pasiekti failą žemiau nurodytu adresu, ir suvykdykite bibliotekos skenavimą.",
"authentication_settings": "Autentifikavimo nustatymai", "authentication_settings": "Autentifikavimo nustatymai",
@@ -45,6 +48,10 @@
"backup_database": "Sukurti duomenų bazės išklotinę", "backup_database": "Sukurti duomenų bazės išklotinę",
"backup_database_enable_description": "Įgalinti duomenų bazės išklotinės", "backup_database_enable_description": "Įgalinti duomenų bazės išklotinės",
"backup_keep_last_amount": "Išsaugomų ankstesnių duomenų bazės išklotinių skaičius", "backup_keep_last_amount": "Išsaugomų ankstesnių duomenų bazės išklotinių skaičius",
"backup_onboarding_1_description": "išorinė kopija debesyje arba kitoje fizinėje lokacijoje.",
"backup_onboarding_2_description": "vietinės kopijos kituose prietaisuose. Tai apima pagrindinius failus ir jų vietines kopijas.",
"backup_onboarding_3_description": "viso jūsų duomenų kopijų, įskaitant originalius failus. Tai apima 1 išorinę ir 2 vietines kopijas.",
"backup_onboarding_description": "Jūsų duomenų apsaugojimui rekomenduojama <backblaze-link>3-2-1 atsarginės kopijos strategija</backblaze-link> . Jūs turėtumėte saugoti įkeltų nuotraukų/video bei Immich duomenų bazės kopijas išsamiam atsarginių kopijų sprendimui.",
"backup_onboarding_footer": "Daugiau informacijos apie „Immich“ atsarginių kopijų kūrimą rasite <link>dokumentacijoje</link>.", "backup_onboarding_footer": "Daugiau informacijos apie „Immich“ atsarginių kopijų kūrimą rasite <link>dokumentacijoje</link>.",
"backup_onboarding_parts_title": "3-2-1 atsarginė kopija apima:", "backup_onboarding_parts_title": "3-2-1 atsarginė kopija apima:",
"backup_onboarding_title": "Atsarginės kopijos", "backup_onboarding_title": "Atsarginės kopijos",
@@ -75,7 +82,7 @@
"image_format_description": "WebP sukuria mažesnius failus nei JPEG, tačiau lėčiau juos apdoroja.", "image_format_description": "WebP sukuria mažesnius failus nei JPEG, tačiau lėčiau juos apdoroja.",
"image_fullsize_description": "Pilno dydžio nuotrauka be meta duomenų naudojama priartinus", "image_fullsize_description": "Pilno dydžio nuotrauka be meta duomenų naudojama priartinus",
"image_fullsize_enabled": "Įgalinti pilno dydžio nuotraukų generavimą", "image_fullsize_enabled": "Įgalinti pilno dydžio nuotraukų generavimą",
"image_fullsize_enabled_description": "Generuoti viso dydžio vaizdą neinternetui pritaikytiems formatams. Kai įjungta parinktis „Pirmenybė įterptai peržiūrai“, įterptosios peržiūros naudojamos tiesiogiai be konvertavimo. Tai neturi įtakos internetui pritaikytiems formatams, pvz., JPEG", "image_fullsize_enabled_description": "Generuoti viso dydžio vaizdą naršyklėms nepritaikytiems formatams. Kai įjungta parinktis „Pirmenybė įterptai peržiūrai“, įterptosios peržiūros naudojamos tiesiogiai be konvertavimo. Tai neturi įtakos internetui pritaikytiems formatams, pvz., JPEG.",
"image_fullsize_quality_description": "Pilno dydžio nuotraukų kokybė 1-100. Didesnė yra geresnė, tačiau sukuria didesniu failus.", "image_fullsize_quality_description": "Pilno dydžio nuotraukų kokybė 1-100. Didesnė yra geresnė, tačiau sukuria didesniu failus.",
"image_fullsize_title": "Pilno dydžio nuotraukų Nustatymai", "image_fullsize_title": "Pilno dydžio nuotraukų Nustatymai",
"image_prefer_embedded_preview": "Pageidautinai rodyti įterptą peržiūrą", "image_prefer_embedded_preview": "Pageidautinai rodyti įterptą peržiūrą",
@@ -99,8 +106,8 @@
"job_settings": "Užduočių nustatymai", "job_settings": "Užduočių nustatymai",
"job_settings_description": "Keisti užduočių lygiagretumą", "job_settings_description": "Keisti užduočių lygiagretumą",
"job_status": "Užduočių būsenos", "job_status": "Užduočių būsenos",
"jobs_delayed": "{jobCount, plural, other {# delayed}}", "jobs_delayed": "{jobCount, plural, one {# atidėtas} few {# atidėti} other {# atidėtų}}",
"jobs_failed": "{jobCount, plural, other {# failed}}", "jobs_failed": "{jobCount, plural, other {# nepavyko}}",
"library_created": "Sukurta biblioteka: {library}", "library_created": "Sukurta biblioteka: {library}",
"library_deleted": "Biblioteka ištrinta", "library_deleted": "Biblioteka ištrinta",
"library_import_path_description": "Nurodykite aplanką, kurį norite importuoti. Šiame aplanke, įskaitant poaplankius, bus nuskaityti vaizdai ir vaizdo įrašai.", "library_import_path_description": "Nurodykite aplanką, kurį norite importuoti. Šiame aplanke, įskaitant poaplankius, bus nuskaityti vaizdai ir vaizdo įrašai.",
@@ -165,7 +172,7 @@
"metadata_extraction_job": "Metaduomenų nuskaitymas", "metadata_extraction_job": "Metaduomenų nuskaitymas",
"metadata_extraction_job_description": "Kiekvieno bibliotekos elemento metaduomenų nuskaitymas, tokių kaip GPS koordinatės, veidai ar rezoliucija", "metadata_extraction_job_description": "Kiekvieno bibliotekos elemento metaduomenų nuskaitymas, tokių kaip GPS koordinatės, veidai ar rezoliucija",
"metadata_faces_import_setting": "Įjungti veidų importą", "metadata_faces_import_setting": "Įjungti veidų importą",
"metadata_faces_import_setting_description": "Importuoti veidus iš vaizdo EXIF duomenų ir papildomų failų", "metadata_faces_import_setting_description": "Importuoti veidus iš vaizdo EXIF duomenų ir susietų failų",
"metadata_settings": "Metaduomenų nustatymai", "metadata_settings": "Metaduomenų nustatymai",
"metadata_settings_description": "Tvarkyti metaduomenų nustatymus", "metadata_settings_description": "Tvarkyti metaduomenų nustatymus",
"migration_job": "Tvarkymas", "migration_job": "Tvarkymas",
@@ -182,6 +189,8 @@
"nightly_tasks_settings_description": "Valdyti naktines užduotis", "nightly_tasks_settings_description": "Valdyti naktines užduotis",
"nightly_tasks_start_time_setting": "Pradžios laikas", "nightly_tasks_start_time_setting": "Pradžios laikas",
"nightly_tasks_start_time_setting_description": "Laikas kada serveris pradės vykdyti naktines užduotis", "nightly_tasks_start_time_setting_description": "Laikas kada serveris pradės vykdyti naktines užduotis",
"nightly_tasks_sync_quota_usage_setting": "Sinchronizuoti kvotos naudojimą",
"nightly_tasks_sync_quota_usage_setting_description": "Atnaujinti vartotojo vietos kvotą remiantis dabartiniu vartojimu",
"no_paths_added": "Keliai nepridėti", "no_paths_added": "Keliai nepridėti",
"no_pattern_added": "Šablonas nepridėtas", "no_pattern_added": "Šablonas nepridėtas",
"note_apply_storage_label_previous_assets": "Pastaba: norėdami pritaikyti Saugyklos Žymą seniau įkeltiems ištekliams, paleiskite", "note_apply_storage_label_previous_assets": "Pastaba: norėdami pritaikyti Saugyklos Žymą seniau įkeltiems ištekliams, paleiskite",
@@ -303,29 +312,72 @@
"transcoding_codecs_learn_more": "Sužinoti daugiau apie naudojamą terminologiją, naudokite FFmpeg dokumentaciją <h264-link>H.264 codec</h264-link>, <hevc-link>HEVC codec</hevc-link> and <vp9-link>VP9 codec</vp9-link>.", "transcoding_codecs_learn_more": "Sužinoti daugiau apie naudojamą terminologiją, naudokite FFmpeg dokumentaciją <h264-link>H.264 codec</h264-link>, <hevc-link>HEVC codec</hevc-link> and <vp9-link>VP9 codec</vp9-link>.",
"transcoding_constant_quality_mode": "Pastovios kokybės režimas", "transcoding_constant_quality_mode": "Pastovios kokybės režimas",
"transcoding_constant_quality_mode_description": "ICQ yra geriau nei CPQ, tačiau ne visi įrenginiai palaiko šį spartinimo būdą. Šis pasirinkimas būtų naudojamas kai nustatytas Kodavimas Pagal Kokybę. NVENC nepalaiko šio pasirinkimo todėl bus ignoruojamas.", "transcoding_constant_quality_mode_description": "ICQ yra geriau nei CPQ, tačiau ne visi įrenginiai palaiko šį spartinimo būdą. Šis pasirinkimas būtų naudojamas kai nustatytas Kodavimas Pagal Kokybę. NVENC nepalaiko šio pasirinkimo todėl bus ignoruojamas.",
"transcoding_constant_rate_factor": "Pastovaus greičio faktorius (-crf)",
"transcoding_constant_rate_factor_description": "Video kokybės lygis. Tipinės reikšmės yra 23 jei H.264, 28 jei HVEC, 31 jei VP9, ir 35 jei AV1. Kuo mažesnis tuo kokybiškesnis tačiau didesni failai.", "transcoding_constant_rate_factor_description": "Video kokybės lygis. Tipinės reikšmės yra 23 jei H.264, 28 jei HVEC, 31 jei VP9, ir 35 jei AV1. Kuo mažesnis tuo kokybiškesnis tačiau didesni failai.",
"transcoding_disabled_description": "Nedaryti perkodavimo, įrašų peržiūra gali neveikti ant kai kūrių sąsajų", "transcoding_disabled_description": "Nedaryti perkodavimo, įrašų peržiūra gali neveikti ant kai kūrių sąsajų",
"transcoding_encoding_options": "Užkodavimo parinktys",
"transcoding_encoding_options_description": "Nustatyti kodekus, rezoliuciją, kokybę ir kitas parinktis užkoduojamiems vaizdo įrašams",
"transcoding_hardware_acceleration": "Techninės įrangos spartinimas", "transcoding_hardware_acceleration": "Techninės įrangos spartinimas",
"transcoding_hardware_acceleration_description": "Eksperimentinis: greitesnis perkodavimas, bet galimai prastesne kokybe prie tos pačios bitų spartos",
"transcoding_hardware_decoding": "Aparatinis dekodavimas", "transcoding_hardware_decoding": "Aparatinis dekodavimas",
"transcoding_hardware_decoding_setting_description": "Įgalina visapusišką paspartinimą vietoje tik užkodavimo paspartinimo. Gali neveikti su kai kuriais vaizdo įrašais.",
"transcoding_max_b_frames": "Maksimaliai B-kadrų",
"transcoding_max_b_frames_description": "Didesnės reikšmės pagerina suspaudimo efektyvumą, bet sulėtina užkodavimą. Senesniuose prietaisuose gali būti nepalaikomas aparatinis spartinimas. 0 išjungia B-kadrus, o -1 nustato reikšmę automatiškai.",
"transcoding_max_bitrate": "Maksimalus bitų srautas", "transcoding_max_bitrate": "Maksimalus bitų srautas",
"transcoding_max_bitrate_description": "Pasirenkant max bitrate galima pasiekti labiau nuspėjamą failų dydį su minimaliais kokybės praradimais. Prie 720p, tipinės reikšmės yra 2600 kbits/s jei BP9 ar HVEC, arba 4500 kbits/s jei H.264. Neveiksnus jei pasirenkamas 0.", "transcoding_max_bitrate_description": "Pasirenkant max bitrate galima pasiekti labiau nuspėjamą failų dydį su minimaliais kokybės praradimais. Prie 720p, tipinės reikšmės yra 2600 kbits/s jei BP9 ar HVEC, arba 4500 kbits/s jei H.264. Neveiksnus jei pasirenkamas 0.",
"transcoding_max_keyframe_interval": "Maksimalus raktinio kadro intervalas",
"transcoding_max_keyframe_interval_description": "Nustato maksimalų kadro atstumą tarp raktinių kadrų. Žemesnės reikšmės pablogina suspaudimo efektyvumą, bet pagerina prasukimo laiką ir gali pagerinti greito veiksmo scenų kokybę. 0 - nustato šią reikšmę automatiškai.",
"transcoding_optimal_description": "Vaizdo įrašai aukštesne nei tikslinė rezoliucija arba nepalaikomu formatu",
"transcoding_policy": "Transkodavimo politika", "transcoding_policy": "Transkodavimo politika",
"transcoding_policy_description": "Nustatyti kada vaizdo įrašas bus perkoduotas",
"transcoding_preferred_hardware_device": "Pageidaujamas aparatinės įrangos įrenginys",
"transcoding_preferred_hardware_device_description": "Galioja tik VAAPI ir QSV. Nustato dri mazgą aparatiniam perkodavimui.",
"transcoding_preset_preset": "Iš anksto nustatytas (-preset)",
"transcoding_preset_preset_description": "Kompresijos greitis. Siekiant tam tikro bitrate lėtesnis apdorojimas lems mažesnius failų dydžius ir padidins kokybę. VP9 ignoruos greičius virš \"gretesnis\" lygio.", "transcoding_preset_preset_description": "Kompresijos greitis. Siekiant tam tikro bitrate lėtesnis apdorojimas lems mažesnius failų dydžius ir padidins kokybę. VP9 ignoruos greičius virš \"gretesnis\" lygio.",
"transcoding_reference_frames": "Nuorodiniai kadrai",
"transcoding_reference_frames_description": "Kadrų, į kuriuos reikia remtis suspaudžiant duotą kadrą, skaičius. Aukštesnė reikšmė pagerina suspaudimo efektyvumą, bet sulėtina užkodavimą. 0 - nustato reikšmę automatiškai.",
"transcoding_required_description": "Tik nepalaikomo formato vaizdo įrašai",
"transcoding_settings": "Vaizdo įrašų perkodavimo nustatymai",
"transcoding_settings_description": "Valdyti kuriuos vaizdo įrašus perkoduoti ir kaip juos apdoroti",
"transcoding_target_resolution": "Skiriamoji geba",
"transcoding_target_resolution_description": "Didesnės skiriamosios gebos gali išsaugoti daugiau detalių, tačiau jas koduoti užtrunka ilgiau, failų dydžiai yra didesni ir gali sumažėti programos jautrumas.", "transcoding_target_resolution_description": "Didesnės skiriamosios gebos gali išsaugoti daugiau detalių, tačiau jas koduoti užtrunka ilgiau, failų dydžiai yra didesni ir gali sumažėti programos jautrumas.",
"transcoding_temporal_aq": "Laikinas adaptyvus kvantavimas",
"transcoding_temporal_aq_description": "Galioja tik NVENC. Pagerina detalių, mažo judesio scenų kokybę. Gali būti nepalaikoma senesnių įrenginių.",
"transcoding_threads": "Gijos",
"transcoding_threads_description": "Didesnės reikšmės pagreitina kodavimą, bet kol aktyvus palieka mažiau serverio resursų kitoms užduotims. Ši reikšmė negali būti didesnė už procesoriaus branduolių kiekį. Jei reikšmė 0, tai išnaudoja maksimaliai.",
"transcoding_tone_mapping": "Tonų atvaizdavimas",
"transcoding_tone_mapping_description": "Bandoma išsaugoti HDR vaizdo įrašų išvaizdą konvertuojant į SDR. Kiekvienas algoritmas taiko skirtingus kompromisus dėl spalvų, detalių ir šviesumo. Hable išsaugo detales, Mobius išsaugo spalvas, o Reinhard išsaugo šviesumą.",
"transcoding_transcode_policy": "Perkodavimo strategija",
"transcoding_transcode_policy_description": "Strategija, kada vaizdo įrašas turi būti perkoduotas. HDR vaizdo įrašai visada bus perkoduoti (išskyrus jei perkodavimas išjungtas).",
"transcoding_two_pass_encoding": "Dviejų perėjimų užkodavimas",
"transcoding_two_pass_encoding_setting_description": "Perkoduoti su dviem perėjimais, kad gauti geriau užkoduotą vaizdo įrašą. Kai maksimalus bitų srautas įjungtas (veikimui reikalaujamas H.264 ir HVEC), tada naudojamas bitų intervalas remiantis maksimaliu bitų srautu ir ignoruojamas CRF. Su VP9 gali būti naudojamas CRF, jei maksimalus bitų srautas yra išjungtas.",
"transcoding_video_codec": "Video kodekas", "transcoding_video_codec": "Video kodekas",
"transcoding_video_codec_description": "VP9 turi didelį efektyvumą ir tinklo suderinamumą, bet užtrunka ilgiau perkoduojant. HVEC veikia panašiai, bet turi mažesnį tinklo suderinamumą. H.264 yra plačiai palaikomas ir greitai perkoduojamas, bet kuria didelius failus. AV1 yra efektyviausias kodekas, bet nepalaikomas senesnių prietaisų.",
"trash_enabled_description": "Įgalinti šiukšliadėžės funkcijas", "trash_enabled_description": "Įgalinti šiukšliadėžės funkcijas",
"trash_number_of_days": "Dienų skaičius", "trash_number_of_days": "Dienų skaičius",
"trash_number_of_days_description": "Kiek dienų bus laikomi elementai šiukšliadėžėje prieš galutinai juos ištrinant",
"trash_settings": "Šiukšliadėžės nustatymai", "trash_settings": "Šiukšliadėžės nustatymai",
"trash_settings_description": "Tvarkyti šiukšliadėžės nustatymus", "trash_settings_description": "Tvarkyti šiukšliadėžės nustatymus",
"unlink_all_oauth_accounts": "Atsieti visas OAuth paskyras",
"unlink_all_oauth_accounts_description": "Nepamirškite atsieti visas OAuth paskyras prieš migruojant pas naują tiekėją.",
"unlink_all_oauth_accounts_prompt": "Ar tikrai norite atsieti visas OAuth paskyras? Tai negrįžtama operacija kuri atstatys OAuth ID kiekvienam vartotojui.",
"user_cleanup_job": "Vartotojų išvalymas", "user_cleanup_job": "Vartotojų išvalymas",
"user_delete_delay": "<b>{user}</b> paskyra ir elementai bus nustatyti galutiniam ištrynimui už {delay, plural, one {# dienos} other {# dienų}}.",
"user_delete_delay_settings": "Ištrynimo delsa", "user_delete_delay_settings": "Ištrynimo delsa",
"user_delete_delay_settings_description": "Skaičius dienų po ištrynimo kuomet vartotojo paskyrą ir susiję duomenys bus negražinamai ištrinti. Vartotojo Trynimo užduotis paleidžiama vidurnaktį ir tikrina kurie vartotojai gali būti trinami. Šio nustatymo pakeitimai bus naudojami sekančio užduoties paleidimo metu.", "user_delete_delay_settings_description": "Skaičius dienų po ištrynimo kuomet naudotojo paskyra ir susiję duomenys bus negražinamai ištrinti. Naudotojo trynimo užduotis paleidžiama vidurnaktį ir tikrina kurie naudotojai gali būti trinami. Šio nustatymo pakeitimai bus naudojami sekančio užduoties paleidimo metu.",
"user_delete_immediately": "<b>{user}</b> paskyra ir elementai bus <b>nedelsiant</b> įtraukti galutiniam pašalinimui.",
"user_delete_immediately_checkbox": "Ištrinti naudotoją ir elementus nedelsiant",
"user_details": "Naudotojo duomenys",
"user_management": "Naudotojų valdymas", "user_management": "Naudotojų valdymas",
"user_password_has_been_reset": "Naudotojo slaptažodis buvo iš naujo nustatytas:", "user_password_has_been_reset": "Naudotojo slaptažodis buvo iš naujo nustatytas:",
"user_password_reset_description": "Perduokite laikiną slaptažodį naudotojui ir informuokite, kad pasikeistų slaptažodį pirmo prisijungimo metu.",
"user_restore_description": "Naudotojo <b>{user}</b> paskyra bus atkurta.", "user_restore_description": "Naudotojo <b>{user}</b> paskyra bus atkurta.",
"user_restore_scheduled_removal": "Atkurti naudotoją - suplanuotas pašalinimas {date, date, long}",
"user_settings": "Naudotojo nustatymai", "user_settings": "Naudotojo nustatymai",
"user_settings_description": "Valdyti naudotojo nustatymus", "user_settings_description": "Valdyti naudotojo nustatymus",
"user_successfully_removed": "Naudotojas {email} sėkmingai pašalintas.", "user_successfully_removed": "Naudotojas {email} sėkmingai pašalintas.",
"version_check_enabled_description": "Įgalinti versijų tikrinimą",
"version_check_implications": "Versijų tikrinimas reikalauja periodiškos komunikacijos su github.com",
"version_check_settings": "Versijos tikrinimas", "version_check_settings": "Versijos tikrinimas",
"version_check_settings_description": "Įjungti/išjungti naujos versijos pranešimus", "version_check_settings_description": "Įjungti/išjungti naujos versijos pranešimus",
"video_conversion_job": "Vaizdo įrašų konvertavimas", "video_conversion_job": "Vaizdo įrašų konvertavimas",
@@ -334,10 +386,36 @@
"admin_email": "Administratoriaus el. paštas", "admin_email": "Administratoriaus el. paštas",
"admin_password": "Administratoriaus slaptažodis", "admin_password": "Administratoriaus slaptažodis",
"administration": "Administravimas", "administration": "Administravimas",
"advanced": "Sudėtingesnis",
"advanced_settings_beta_timeline_subtitle": "Išbandykite naujos programos patirtį",
"advanced_settings_beta_timeline_title": "Beta laiko juosta",
"advanced_settings_enable_alternate_media_filter_subtitle": "Naudokite šį nustatymą medijos filtravimui sinchronizuojant remiantis alternatyviais kriterijais. Naudokite tik jei programa turi problemų su visų albumų aptikimu.",
"advanced_settings_enable_alternate_media_filter_title": "[EKSPERIMENTINIS] Naudokite alternatyvų įrenginio albumų sinchronizavimo filtrą",
"advanced_settings_log_level_title": "Žurnalo įrašų lygis: {level}",
"advanced_settings_prefer_remote_subtitle": "Kai kurie įrenginiai labai lėtai įkelia miniatiūras iš vietinių elementų. Aktyvuokite šį nustatymą, kad vietoje to užkrautumėte nuotolines nuotraukas.",
"advanced_settings_prefer_remote_title": "Teikti pirmenybę nuotolinėms nuotraukoms",
"advanced_settings_proxy_headers_subtitle": "Nustatykite tarpinio serverio antraštes kurias Immich siųs su kiekvienu užklausimu",
"advanced_settings_proxy_headers_title": "Tarpinio serverio antraštės",
"advanced_settings_readonly_mode_subtitle": "Įgalina tik skaitymo režimą kai nuotraukas galima tik žiūrėti, draudžiama pažymėti kelias, dalintis, transliuoti ar ištrinti. Įgalinkit/uždrauskit tik skaitymą per naudotojo avatar'ą iš pagrindinio lango",
"advanced_settings_readonly_mode_title": "Tik skaitymo režimas",
"advanced_settings_self_signed_ssl_subtitle": "Praleidžia SSL sertifikato tikrinimą serverio galutiniam taškui. Privaloma pačių pasirašytiems sertifikatams.",
"advanced_settings_self_signed_ssl_title": "Leisti pačių pasirašytus SSL sertifikatus",
"advanced_settings_sync_remote_deletions_subtitle": "Automatiškai ištrinti ar atkurti elementus įrenginyje, kai tie veiksmai atliekami naršyklėje",
"advanced_settings_sync_remote_deletions_title": "Sinchronizuoti nuotolinius ištrynimus [EKSPERIMENTINIS]",
"advanced_settings_tile_subtitle": "Pažangesni naudotojų nustatymai",
"advanced_settings_troubleshooting_subtitle": "Įgalinti papildomas galimybes trikčių šalinimui",
"advanced_settings_troubleshooting_title": "Trikčių šalinimas",
"age_months": "Amžius {months, plural, one {# mėnesis} few {# mėnesiai} other {# mėnesių}}",
"age_year_months": "Amžius 1 metai, {months, plural, one {# mėnesis} few {# mėnesiai} other {# mėnesių}}",
"age_years": "{years, plural, other {Amžius #}}",
"album_added": "Albumas pridėtas", "album_added": "Albumas pridėtas",
"album_added_notification_setting_description": "Gauti el. pašto pranešimą, kai būsite pridėtas prie bendrinamo albumo", "album_added_notification_setting_description": "Gauti el. pašto pranešimą, kai būsite pridėtas prie bendrinamo albumo",
"album_cover_updated": "Albumo viršelis atnaujintas", "album_cover_updated": "Albumo viršelis atnaujintas",
"album_delete_confirmation": "Ar tikrai norite ištrinti albumą {album}?", "album_delete_confirmation": "Ar tikrai norite ištrinti albumą {album}?",
"album_delete_confirmation_description": "Jei šiuo albumu dalijamasi, tai kiti naudotojai jo nebegalės pasiekti.",
"album_deleted": "Albumas ištrintas",
"album_info_card_backup_album_excluded": "neįtrauktas",
"album_info_card_backup_album_included": "įtrauktas",
"album_info_updated": "Albumo informacija atnaujinta", "album_info_updated": "Albumo informacija atnaujinta",
"album_leave": "Palikti albumą?", "album_leave": "Palikti albumą?",
"album_leave_confirmation": "Ar tikrai norite palikti albumą {album}?", "album_leave_confirmation": "Ar tikrai norite palikti albumą {album}?",
@@ -345,16 +423,27 @@
"album_options": "Albumo parinktys", "album_options": "Albumo parinktys",
"album_remove_user": "Pašalinti naudotoją?", "album_remove_user": "Pašalinti naudotoją?",
"album_remove_user_confirmation": "Ar tikrai norite pašalinti naudotoją {user}?", "album_remove_user_confirmation": "Ar tikrai norite pašalinti naudotoją {user}?",
"album_search_not_found": "Pagal jūsų paiešką albumų nerasta",
"album_share_no_users": "Atrodo, kad bendrinate šį albumą su visais naudotojais, arba neturite naudotojų, su kuriais galėtumėte bendrinti.", "album_share_no_users": "Atrodo, kad bendrinate šį albumą su visais naudotojais, arba neturite naudotojų, su kuriais galėtumėte bendrinti.",
"album_updated": "Albumas atnaujintas", "album_updated": "Albumas atnaujintas",
"album_updated_setting_description": "Gauti pranešimą el. paštu, kai bendrinamas albumas turi naujų elementų", "album_updated_setting_description": "Gauti pranešimą el. paštu, kai bendrinamas albumas turi naujų elementų",
"album_user_left": "Paliko {album}",
"album_user_removed": "Pašalintas {user}", "album_user_removed": "Pašalintas {user}",
"album_viewer_appbar_delete_confirm": "Ar tikrai norite ištrinti šį albumą iš savo paskyros?",
"album_viewer_appbar_share_err_delete": "Nepavyko ištrinti albumo", "album_viewer_appbar_share_err_delete": "Nepavyko ištrinti albumo",
"album_viewer_appbar_share_err_leave": "Nepavyko išeiti iš albumo", "album_viewer_appbar_share_err_leave": "Nepavyko išeiti iš albumo",
"album_viewer_appbar_share_err_remove": "Kilo problemų pašalinant elementus iš albumo",
"album_viewer_appbar_share_err_title": "Nepavyko pakeisti albumo pavadinimą", "album_viewer_appbar_share_err_title": "Nepavyko pakeisti albumo pavadinimą",
"album_viewer_appbar_share_leave": "Palikti albumą",
"album_viewer_appbar_share_to": "Dalintis su",
"album_viewer_page_share_add_users": "Pridėti naudotojų",
"album_with_link_access": "Tegul visi, turintys nuorodą, mato šio albumo nuotraukas ir žmones.", "album_with_link_access": "Tegul visi, turintys nuorodą, mato šio albumo nuotraukas ir žmones.",
"albums": "Albumai", "albums": "Albumai",
"albums_count": "{count, plural, one {# albumas} few {# albumai} other {# albumų}}", "albums_count": "{count, plural, one {# albumas} few {# albumai} other {# albumų}}",
"albums_default_sort_order": "Pradinė albumo rūšiavimo tvarka",
"albums_default_sort_order_description": "Pradinė elementų rūšiavimo tvarka kai kuriamas naujas albumas.",
"albums_feature_description": "Elementų rinkinys kuriuo galima dalintis su kitais naudotojais.",
"albums_on_device_count": "Albumų įrenginyje ({count})",
"all": "Visi", "all": "Visi",
"all_albums": "Visi albumai", "all_albums": "Visi albumai",
"all_people": "Visi žmonės", "all_people": "Visi žmonės",
@@ -363,51 +452,154 @@
"allow_edits": "Leisti redagavimus", "allow_edits": "Leisti redagavimus",
"allow_public_user_to_download": "Leisti viešam naudotojui atsisiųsti", "allow_public_user_to_download": "Leisti viešam naudotojui atsisiųsti",
"allow_public_user_to_upload": "Leisti viešam naudotojui įkelti", "allow_public_user_to_upload": "Leisti viešam naudotojui įkelti",
"alt_text_qr_code": "QR kodo paveiksliukas",
"anti_clockwise": "Prieš laikrodžio rodykles",
"api_key": "API raktas", "api_key": "API raktas",
"api_key_description": "Ši reikšmė bus parodyta tik vieną kartą. Prašome nusikopijuoti prieš uždarant šį langą.",
"api_key_empty": "Jūsų API rakto pavadinimas netūrėtų būti tuščias", "api_key_empty": "Jūsų API rakto pavadinimas netūrėtų būti tuščias",
"api_keys": "API raktai", "api_keys": "API raktai",
"app_bar_signout_dialog_content": "Ar tikrai norite atsijungti?",
"app_bar_signout_dialog_ok": "Taip",
"app_bar_signout_dialog_title": "Atsijungti",
"app_settings": "Programos nustatymai", "app_settings": "Programos nustatymai",
"appears_in": "Susiję",
"apply_count": "Taikyti ({count, number})",
"archive": "Archyvas", "archive": "Archyvas",
"archive_action_prompt": "{count} pridėta į archyvą",
"archive_or_unarchive_photo": "Archyvuoti arba išarchyvuoti nuotrauką", "archive_or_unarchive_photo": "Archyvuoti arba išarchyvuoti nuotrauką",
"archive_page_no_archived_assets": "Nerasta jokių archyvuotų elementų", "archive_page_no_archived_assets": "Nerasta jokių archyvuotų elementų",
"archive_page_title": "Archyve ({count})",
"archive_size": "Archyvo dydis", "archive_size": "Archyvo dydis",
"archive_size_description": "Konfigūruoti archyvo dydį atsisiuntimams (GiB)", "archive_size_description": "Konfigūruoti archyvo dydį atsisiuntimams (GiB)",
"archived": "Archyvuota", "archived": "Archyvuota",
"archived_count": "{count, plural, other {# suarchyvuota}}", "archived_count": "{count, plural, other {# suarchyvuota}}",
"are_these_the_same_person": "Ar tai tas pats asmuo?", "are_these_the_same_person": "Ar tai tas pats asmuo?",
"are_you_sure_to_do_this": "Ar tikrai norite tai daryti?", "are_you_sure_to_do_this": "Ar tikrai norite tai daryti?",
"asset_action_delete_err_read_only": "Negalima ištrinti tik skaitom(o, ų) element(o, ų), praleidžiama",
"asset_action_share_err_offline": "Negalima užkrauti neprisijungusių elementų, praleidžiama",
"asset_added_to_album": "Pridėta į albumą", "asset_added_to_album": "Pridėta į albumą",
"asset_adding_to_album": "Pridedama į albumą...", "asset_adding_to_album": "Pridedama į albumą",
"asset_description_updated": "Elemento aprašymas buvo atnaujintas", "asset_description_updated": "Elemento aprašymas buvo atnaujintas",
"asset_filename_is_offline": "Elementas {filename} nepasiekiamas", "asset_filename_is_offline": "Elementas {filename} nepasiekiamas",
"asset_has_unassigned_faces": "Elementas turi nepriskirtų veidų",
"asset_hashing": "Maišoma…",
"asset_list_group_by_sub_title": "Grupuoti pagal",
"asset_list_layout_settings_dynamic_layout_title": "Dinaminis išdėstymas",
"asset_list_layout_settings_group_automatically": "Automatiškai",
"asset_list_layout_settings_group_by": "Grupuoti elementus pagal",
"asset_list_layout_settings_group_by_month_day": "Mėnesis + diena",
"asset_list_layout_sub_title": "Išdėstymas",
"asset_list_settings_subtitle": "Nuotraukų tinklelio išdėstymo nustatymai",
"asset_list_settings_title": "Nuotraukų tinklelis",
"asset_offline": "Elementas nepasiekiamas", "asset_offline": "Elementas nepasiekiamas",
"asset_offline_description": "Šis išorinis elementas neberandamas diske. Dėl pagalbos susisiekite su savo Immich administratoriumi.", "asset_offline_description": "Šis išorinis elementas neberandamas diske. Dėl pagalbos susisiekite su savo Immich administratoriumi.",
"asset_restored_successfully": "Elementas atkurtas sėkmingai",
"asset_skipped": "Praleista",
"asset_skipped_in_trash": "Šiukšliadėžėje",
"asset_uploaded": "Įkelta", "asset_uploaded": "Įkelta",
"asset_uploading": "Įkeliama...", "asset_uploading": "Įkeliama",
"asset_viewer_settings_subtitle": "Tvarkykite savo galerijos peržiūros nustatymus",
"asset_viewer_settings_title": "Elementų peržiūra",
"assets": "Elementai", "assets": "Elementai",
"assets_added_count": "{count, plural, one {Pridėtas # elementas} few {Pridėti # elementai} other {Pridėta # elementų}}", "assets_added_count": "{count, plural, one {Pridėtas # elementas} few {Pridėti # elementai} other {Pridėta # elementų}}",
"assets_added_to_album_count": "Į albumą {count, plural, one {įtrauktas # elementas} few {įtraukti # elementai} other {įtraukta # elementų}}", "assets_added_to_album_count": "Į albumą {count, plural, one {įtrauktas # elementas} few {įtraukti # elementai} other {įtraukta # elementų}}",
"assets_added_to_albums_count": "Pridėta {assetTotal, plural, one {# elementas} few {# elementai} other {# elementų}} į {albumTotal, plural, one {# albumą} few {# albumus} other {# albumų}}",
"assets_cannot_be_added_to_album_count": "{count, plural, one {Elementas negali būti pridėtas} few {Elementai negali būti pridėti} other {Elementų negali būti pridėta}} į albumą",
"assets_cannot_be_added_to_albums": "{count, plural, one {Elementas negali būti pridėtas} few {Elementai negali būti pridėti} other {Elementų negali būti pridėta}} į nei vieną albumą",
"assets_count": "{count, plural, one {# elementas} few {# elementai} other {# elementų}}", "assets_count": "{count, plural, one {# elementas} few {# elementai} other {# elementų}}",
"assets_deleted_permanently": "{count} elementų ištrinta galutinai",
"assets_deleted_permanently_from_server": "{count} elementų ištrinta galutinai iš Immich serverio",
"assets_downloaded_failed": "{count, plural, one {Atsisiųstas # failas - {error} failas nepavyko} few {Atsisiųsti # failai - {error} failai nepavyko} other {Atsisiųsta # failų - {error} failų nepavyko}}",
"assets_downloaded_successfully": "{count, plural, one {Atsisiųstas # failas sėkmingai} few {Atsisiųsti # failai sėkmingai} other {Atsisiųsta # failų sėkmingai}}",
"assets_moved_to_trash_count": "{count, plural, one {# elementas perkeltas} few {# elementai perkelti} other {# elementų perkelta}} į šiukšliadėžę", "assets_moved_to_trash_count": "{count, plural, one {# elementas perkeltas} few {# elementai perkelti} other {# elementų perkelta}} į šiukšliadėžę",
"assets_permanently_deleted_count": "{count, plural, one {# elementas ištrintas} few {# elementai ištrinti} other {# elementų ištrinta}} visam laikui", "assets_permanently_deleted_count": "{count, plural, one {# elementas ištrintas} few {# elementai ištrinti} other {# elementų ištrinta}} visam laikui",
"assets_removed_count": "{count, plural, one {Pašalintas # elementas} few {Pašalinti # elementai} other {Pašalinta # elementų}}", "assets_removed_count": "{count, plural, one {Pašalintas # elementas} few {Pašalinti # elementai} other {Pašalinta # elementų}}",
"assets_removed_permanently_from_device": "{count} elementų pašalinta galutinai iš jūsų įrenginio",
"assets_restore_confirmation": "Ar tikrai norite atkurti visus šiukšliadėžėje esančius perkeltus elementus? Šio veiksmo atšaukti negalėsite! Pastaba: nepasiekiami elementai tokiu būdu atkurti nebus.", "assets_restore_confirmation": "Ar tikrai norite atkurti visus šiukšliadėžėje esančius perkeltus elementus? Šio veiksmo atšaukti negalėsite! Pastaba: nepasiekiami elementai tokiu būdu atkurti nebus.",
"assets_restored_count": "{count, plural, one {Atkurtas # elementas} few {Atkurti # elementai} other {Atkurta # elementų}}", "assets_restored_count": "{count, plural, one {Atkurtas # elementas} few {Atkurti # elementai} other {Atkurta # elementų}}",
"assets_restored_successfully": "{count} element(as, ai, ų) atkurta sėkmingai",
"assets_trashed": "{count} element(ai,ų,as) perkelta į šiukšliadėžę",
"assets_trashed_count": "Perkelta į šiukšliadėžę {count, plural, one {# elementas} few {# elementai} other {# elementų}}",
"assets_trashed_from_server": "{count} element(as, ai, ų) perkelta į šiukšliadėžę iš Immich serverio",
"assets_were_part_of_album_count": "{count, plural, one {# elementas} few {# elementai} other {# elementų}} jau prieš tai buvo albume", "assets_were_part_of_album_count": "{count, plural, one {# elementas} few {# elementai} other {# elementų}} jau prieš tai buvo albume",
"assets_were_part_of_albums_count": "{count, plural, one {Elementas } few {Elementai} other {Elementų}} jau buvo albumuose",
"authorized_devices": "Autorizuoti įrenginiai", "authorized_devices": "Autorizuoti įrenginiai",
"automatic_endpoint_switching_subtitle": "Prisijungti vietoje per priskirtą Wi-Fi kai įmanoma ir naudoti alternatyvų prisijungimą visur kitur",
"automatic_endpoint_switching_title": "Automatinis URL perjungimas",
"autoplay_slideshow": "Automatiškai rodyti skaidrių demonstraciją",
"back": "Atgal", "back": "Atgal",
"back_close_deselect": "Atgal, uždaryti arba atžymėti", "back_close_deselect": "Atgal, uždaryti arba atžymėti",
"background_location_permission": "Foninis vietovės leidimas",
"background_location_permission_content": "Veikiant fone tinklo perjungimui Immich privalo *visada* turėti prieigą prie tikslios vietovės, kad programa galėtų perskaityti Wi-Fi tinklo pavadinimą",
"backup": "Atsarginė kopija",
"backup_album_selection_page_albums_device": "Albumų įrenginyje ({count})",
"backup_album_selection_page_albums_tap": "Palieskite įtraukti, du kart palieskite neįtraukti",
"backup_album_selection_page_assets_scatter": "Elementai gali išsibarstyti per kelis albumus. Todėl albumai gali būti įtraukti arba neįtraukti per atsarginio kopijavimo procesą.",
"backup_album_selection_page_select_albums": "Pažymėti albumai",
"backup_album_selection_page_selection_info": "Pažymėjimo informacija",
"backup_album_selection_page_total_assets": "Viso unikalių elementų",
"backup_all": "Visi",
"backup_background_service_backup_failed_message": "Nepavyko sukurti atsarginių kopijų. Bandoma dar kartą…", "backup_background_service_backup_failed_message": "Nepavyko sukurti atsarginių kopijų. Bandoma dar kartą…",
"backup_background_service_connection_failed_message": "Nepavyko prisijungti prie serverio. Bandoma dar kartą…", "backup_background_service_connection_failed_message": "Nepavyko prisijungti prie serverio. Bandoma dar kartą…",
"backup_background_service_current_upload_notification": "Įkeliamas {filename}", "backup_background_service_current_upload_notification": "Įkeliamas {filename}",
"backup_background_service_default_notification": "Ieškoma naujų elementų…",
"backup_background_service_error_title": "Atsarginio kopijavimo klaida",
"backup_background_service_in_progress_notification": "Kuriama elementų atsarginė kopija…",
"backup_background_service_upload_failure_notification": "Nepavyko įkelti {filename}", "backup_background_service_upload_failure_notification": "Nepavyko įkelti {filename}",
"backup_controller_page_background_wifi": "Only on WiFi", "backup_controller_page_albums": "Atsarginės kopijos albumai",
"backup_controller_page_background_app_refresh_disabled_title": "Foninis programos atnaujinimas išjungtas",
"backup_controller_page_background_app_refresh_enable_button_text": "Eiti į nustatymus",
"backup_controller_page_background_battery_info_link": "Parodyk man kaip",
"backup_controller_page_background_battery_info_message": "Norint geriausių foninio atsarginio kopijavimo rezultatų, prašome išjungti akumuliatoriaus optimizavimą ribojantį foninį Immich veikimą.\n\nKadangi tai priklauso nuo įrenginio, prašome susirasti reikiamą informaciją pas įrenginio gamintoją.",
"backup_controller_page_background_battery_info_ok": "OK",
"backup_controller_page_background_battery_info_title": "Akumuliatoriaus optimizavimai",
"backup_controller_page_background_charging": "Tik kol kraunasi",
"backup_controller_page_background_configure_error": "Nepavyko sukonfigūruoti foninių paslaugų",
"backup_controller_page_background_delay": "Atidėti naujų elementų atsarginį kopijavimą: {duration}",
"backup_controller_page_background_description": "Įjunkite fonines paslaugas, kad galėtumėte automatiškai kurti atsargines kopijas neatidarant programos",
"backup_controller_page_background_is_off": "Automatinis atsarginis kopijavimas yra išjungtas",
"backup_controller_page_background_is_on": "Automatinis atsarginis kopijavimas yra įjungtas",
"backup_controller_page_background_turn_off": "Išjungti fonines paslaugas",
"backup_controller_page_background_turn_on": "Įjungti fonines paslaugas",
"backup_controller_page_background_wifi": "Tik su Wi-Fi",
"backup_controller_page_backup": "Atsarginis kopijavimas",
"backup_controller_page_backup_selected": "Pasirinkta: ",
"backup_controller_page_backup_sub": "Perkeltos nuotraukos ir vaizdo įrašai",
"backup_controller_page_created": "Sukurta: {date}", "backup_controller_page_created": "Sukurta: {date}",
"backup_controller_page_desc_backup": "Įjunkite foninį atsarginį kopijavimą, kad būtų automatiškai perkeliami nauji elementai į serverį kai atidaroma programa.",
"backup_controller_page_excluded": "Neįtraukta: ",
"backup_controller_page_failed": "Nepavyko ({count})",
"backup_controller_page_filename": "Failo pavadinimas: {filename}[{size}]", "backup_controller_page_filename": "Failo pavadinimas: {filename}[{size}]",
"backup_controller_page_id": "ID: {id}",
"backup_controller_page_info": "Atsarginio kopijavimo informacija",
"backup_controller_page_none_selected": "Niekas nepasirinkta",
"backup_controller_page_remainder": "Dar liko",
"backup_controller_page_remainder_sub": "Likusios pasirinktos atsarginio kopijavimo nuotraukos ir vaizdo įrašai",
"backup_controller_page_server_storage": "Serverio saugykla", "backup_controller_page_server_storage": "Serverio saugykla",
"backup_controller_page_start_backup": "Pradėti atsarginį kopijavimą",
"backup_controller_page_status_off": "Automatinis foninis atsarginis kopijavimas yra išjungtas",
"backup_controller_page_status_on": "Automatinis foninis atsarginis kopijavimas yra įjungtas",
"backup_controller_page_storage_format": "{used} iš {total} panaudota", "backup_controller_page_storage_format": "{used} iš {total} panaudota",
"backup_controller_page_to_backup": "Albumai kurių atsarginis kopijavimas bus atliktas",
"backup_controller_page_total_sub": "Visos unikalios nuotraukos ir video įrašai iš pažymėtų albumų",
"backup_controller_page_turn_off": "Išjungti foninį atsarginį kopijavimą",
"backup_controller_page_turn_on": "Įjungti foninį atsarginį kopijavimą",
"backup_controller_page_uploading_file_info": "Įkeliama failo info", "backup_controller_page_uploading_file_info": "Įkeliama failo info",
"backup_err_only_album": "Negalima pašalinti vienintelio albumo",
"backup_info_card_assets": "elementai",
"backup_manual_cancelled": "Atšaukta",
"backup_manual_in_progress": "Jau įkeliama, bandykite dar kartą vėliau", "backup_manual_in_progress": "Jau įkeliama, bandykite dar kartą vėliau",
"backup_manual_success": "Pavyko",
"backup_manual_title": "Įkėlimo būklė",
"backup_options": "Atsarginio kopijavimo nustatymai",
"backup_options_page_title": "Atsarginio kopijavimo nustatymai",
"backup_setting_subtitle": "Tvarkyti foninio ir priekinio plano įkėlimo nustatymus",
"backup_settings_subtitle": "Tvarkyti įkėlimo nustatymus",
"backward": "Atgalinis",
"biometric_auth_enabled": "Biometrinis autentifikavimas įgalintas",
"biometric_locked_out": "Jūs esate užblokuotas biometrinio autentifikavimo funkcijai",
"biometric_no_options": "Nėra galimų biometrinių nustatymų",
"biometric_not_available": "Biometrinis autentifikavimas šiame įrenginyje negalimas",
"birthdate_saved": "Sėkmingai išsaugota gimimo data", "birthdate_saved": "Sėkmingai išsaugota gimimo data",
"birthdate_set_description": "Gimimo data naudojama apskaičiuoti asmens amžių nuotraukos darymo metu.", "birthdate_set_description": "Gimimo data naudojama apskaičiuoti asmens amžių nuotraukos darymo metu.",
"blurred_background": "Neryškus fonas", "blurred_background": "Neryškus fonas",
@@ -416,42 +608,104 @@
"bulk_keep_duplicates_confirmation": "Ar tikrai norite palikti visus {count, plural, one {# besidubliuojantį elementą} few {# besidubliuojančius elementus} other {# besidubliuojančių elementų}}? Tokiu būdu nieko netrinant bus sutvarkytos visos dublikatų grupės.", "bulk_keep_duplicates_confirmation": "Ar tikrai norite palikti visus {count, plural, one {# besidubliuojantį elementą} few {# besidubliuojančius elementus} other {# besidubliuojančių elementų}}? Tokiu būdu nieko netrinant bus sutvarkytos visos dublikatų grupės.",
"bulk_trash_duplicates_confirmation": "Ar tikrai norite perkelti į šiukšliadėžę visus {count, plural, one {# besidubliuojantį elementą} few {# besidubliuojančius elementus} other {# besidubliuojančių elementų}}? Bus paliktas didžiausias kiekvienos grupės elementas ir į šiukšliadėžę perkelti kiti besidubliuojantys elementai.", "bulk_trash_duplicates_confirmation": "Ar tikrai norite perkelti į šiukšliadėžę visus {count, plural, one {# besidubliuojantį elementą} few {# besidubliuojančius elementus} other {# besidubliuojančių elementų}}? Bus paliktas didžiausias kiekvienos grupės elementas ir į šiukšliadėžę perkelti kiti besidubliuojantys elementai.",
"buy": "Įsigyti Immich", "buy": "Įsigyti Immich",
"cache_settings_clear_cache_button": "Išvalyti laikiną talpyklą",
"cache_settings_clear_cache_button_title": "Išvalo programos laikiną talpyklą. Tai gali smarkiai paveikti programos greitį, kol bus sukurta nauja laikinoji talpykla.",
"cache_settings_duplicated_assets_clear_button": "IŠVALYTI",
"cache_settings_duplicated_assets_subtitle": "Nuotraukos ir video įrašai kurie yra programos ignoruojamų sąraše",
"cache_settings_duplicated_assets_title": "Sudubliuoti elementai ({count})",
"cache_settings_statistics_album": "Bibliotekos miniatiūros",
"cache_settings_statistics_full": "Pilno dydžio nuotraukos",
"cache_settings_statistics_shared": "Bendrinamų albumų miniatiūros",
"cache_settings_statistics_thumbnail": "Miniatiūros",
"cache_settings_statistics_title": "Laikinos talpyklos naudojimas",
"cache_settings_subtitle": "Valdykite Immich mobiliosios programos laikinosios talpyklos elgesį",
"cache_settings_tile_subtitle": "Valdykite vietinės talpyklos elgesį",
"cache_settings_tile_title": "Vietinė talpykla",
"cache_settings_title": "Laikinosios talpyklos nustatymai",
"camera": "Fotoaparatas", "camera": "Fotoaparatas",
"camera_brand": "Fotoaparato prekės ženklas", "camera_brand": "Fotoaparato prekės ženklas",
"camera_model": "Fotoaparato modelis", "camera_model": "Fotoaparato modelis",
"cancel": "Atšaukti", "cancel": "Atšaukti",
"cancel_search": "Atšaukti paiešką", "cancel_search": "Atšaukti paiešką",
"canceled": "Atšaukta",
"canceling": "Atšaukiama",
"cannot_merge_people": "Negalima sujungti asmenų", "cannot_merge_people": "Negalima sujungti asmenų",
"cannot_undo_this_action": "Jūs negalėsite atkurti po šio veiksmo!",
"cannot_update_the_description": "Negalima atnaujinti aprašymo", "cannot_update_the_description": "Negalima atnaujinti aprašymo",
"cast": "Transliuoti",
"cast_description": "Valdyti galimas transliavimo kryptis",
"change_date": "Pakeisti datą", "change_date": "Pakeisti datą",
"change_description": "Pakeisti aprašymus",
"change_display_order": "Pakeisti atvaizdavimo tvarką",
"change_expiration_time": "Pakeisti galiojimo trukmę", "change_expiration_time": "Pakeisti galiojimo trukmę",
"change_location": "Pakeisti vietovę", "change_location": "Pakeisti vietovę",
"change_name": "Pakeisti vardą", "change_name": "Pakeisti vardą",
"change_name_successfully": "Vardas pakeistas sėkmingai",
"change_password": "Pakeisti slaptažodį", "change_password": "Pakeisti slaptažodį",
"change_password_description": "Tai arba pirmas kartas, kai jungiatės prie sistemos, arba buvo pateikta užklausa pakeisti jūsų slaptažodį. Prašome įvesti naują slaptažodį žemiau.", "change_password_description": "Tai arba pirmas kartas, kai jungiatės prie sistemos, arba buvo pateikta užklausa pakeisti jūsų slaptažodį. Prašome įvesti naują slaptažodį žemiau.",
"change_password_form_confirm_password": "Patvirtinti slaptažodį",
"change_password_form_description": "Labas {name},\n\nTai yra pirmas kartas kai tu prisijungei prie sistemos arba buvo prašymas pakeisti slaptažodį. Prašome įvesti naują slaptažodį žemiau.",
"change_password_form_new_password": "Naujas slaptažodis",
"change_password_form_password_mismatch": "Slaptažodžiai nesutampa",
"change_password_form_reenter_new_password": "Pakartotinai įveskite naują slaptažodį",
"change_pin_code": "Pakeisti PIN kodą",
"change_your_password": "Pakeisti slaptažodį", "change_your_password": "Pakeisti slaptažodį",
"changed_visibility_successfully": "Matomumas pakeistas sėkmingai", "changed_visibility_successfully": "Matomumas pakeistas sėkmingai",
"check_corrupt_asset_backup": "Patikrinti sugadintų elementų atsarginę kopiją",
"check_corrupt_asset_backup_button": "Atlikti patikrinimą",
"check_corrupt_asset_backup_description": "Paleiskite šį patikrinimą tik per Wi-Fi ir tik kai visi elementai buvo perkopijuoti. Ši procedūra užtruks kelias minutes.",
"check_logs": "Tikrinti žurnalus", "check_logs": "Tikrinti žurnalus",
"choose_matching_people_to_merge": "Pasirinkite atitinkančius žmones sujungimui",
"city": "Miestas", "city": "Miestas",
"clear": "Išvalyti", "clear": "Išvalyti",
"clear_all": "Išvalyti viską", "clear_all": "Išvalyti viską",
"clear_all_recent_searches": "Išvalyti visas naujausias paieškas",
"clear_file_cache": "Išvalyti failų laikiną talpyklą",
"clear_message": "Išvalyti pranešimą", "clear_message": "Išvalyti pranešimą",
"clear_value": "Išvalyti reikšmę", "clear_value": "Išvalyti reikšmę",
"client_cert_dialog_msg_confirm": "OK",
"client_cert_enter_password": "Įveskite slaptažodį",
"client_cert_import": "Importuoti",
"client_cert_import_success_msg": "Kliento sertifikatas yra importuotas",
"client_cert_invalid_msg": "Netinkamas sertifikato failas arba neteisingas slaptažodis", "client_cert_invalid_msg": "Netinkamas sertifikato failas arba neteisingas slaptažodis",
"client_cert_remove_msg": "Kliento sertifikatas yra pašalintas",
"client_cert_subtitle": "Palaikomi tik PKCS12 (.p12, .pfx) formatai. Sertifikato importavimas/pašalinimas galimas tik prieš prisijungimą",
"client_cert_title": "SSL kliento sertifikatas",
"clockwise": "Pagal laikrodžio rodykles",
"close": "Uždaryti", "close": "Uždaryti",
"collapse": "Suskleisti", "collapse": "Suskleisti",
"collapse_all": "Suskleisti viską", "collapse_all": "Suskleisti viską",
"color": "Spalva",
"color_theme": "Temos spalva", "color_theme": "Temos spalva",
"comment_deleted": "Komentaras ištrintas", "comment_deleted": "Komentaras ištrintas",
"comment_options": "Komentarų parinktys", "comment_options": "Komentarų parinktys",
"comments_and_likes": "Komentarai ir patiktukai", "comments_and_likes": "Komentarai ir patiktukai",
"comments_are_disabled": "Komentarai yra išjungti", "comments_are_disabled": "Komentarai yra išjungti",
"common_create_new_album": "Sukurti naują albumą",
"common_server_error": "Prašome patikrinti tinklo prisijungimą ir įsitikinti, kad serveris pasiekiamas ir programos/serverio versija sutampa.",
"completed": "Atlikta",
"confirm": "Patvirtinti", "confirm": "Patvirtinti",
"confirm_admin_password": "Patvirtinti administratoriaus slaptažodį", "confirm_admin_password": "Patvirtinti administratoriaus slaptažodį",
"confirm_delete_face": "Ar tikrai norite ištrinti {name} veidą iš elementų?",
"confirm_delete_shared_link": "Ar tikrai norite ištrinti šią bendrinimo nuorodą?", "confirm_delete_shared_link": "Ar tikrai norite ištrinti šią bendrinimo nuorodą?",
"confirm_keep_this_delete_others": "Visi kiti elementai iš krūvos bus ištrinti išskyrus šį elementą. Ar tikrai norite tęsti?",
"confirm_new_pin_code": "Patvirtinkite naują PIN kodą",
"confirm_password": "Patvirtinti slaptažodį", "confirm_password": "Patvirtinti slaptažodį",
"confirm_tag_face": "Ar norite priskirti šį veidą kaip {name}?",
"confirm_tag_face_unnamed": "Ar norite priskirti šį veidą?",
"connected_device": "Prijungtas įrenginys",
"connected_to": "Prisijungta prie",
"contain": "Tilpti",
"context": "Kontekstas", "context": "Kontekstas",
"continue": "Tęsti", "continue": "Tęsti",
"control_bottom_app_bar_create_new_album": "Sukurti naują albumą",
"control_bottom_app_bar_delete_from_immich": "Ištrinti iš Immich",
"control_bottom_app_bar_delete_from_local": "Ištrinti iš įrenginio",
"control_bottom_app_bar_edit_location": "Redaguoti vietovę",
"control_bottom_app_bar_edit_time": "Redaguoti datą ir laiką",
"control_bottom_app_bar_share_link": "Dalintis nuoroda",
"control_bottom_app_bar_share_to": "Dalintis su",
"control_bottom_app_bar_trash_from_immich": "Perkelti į šiukšliadėžę",
"copied_image_to_clipboard": "Nuotrauka nukopijuota į iškarpinę.", "copied_image_to_clipboard": "Nuotrauka nukopijuota į iškarpinę.",
"copied_to_clipboard": "Nukopijuota į iškapinę!", "copied_to_clipboard": "Nukopijuota į iškapinę!",
"copy_error": "Kopijavimo klaida", "copy_error": "Kopijavimo klaida",
@@ -462,6 +716,8 @@
"copy_password": "Kopijuoti slaptažodį", "copy_password": "Kopijuoti slaptažodį",
"copy_to_clipboard": "Kopijuoti į iškarpinę", "copy_to_clipboard": "Kopijuoti į iškarpinę",
"country": "Šalis", "country": "Šalis",
"cover": "Užpildyti",
"covers": "Viršeliai",
"create": "Sukurti", "create": "Sukurti",
"create_album": "Sukurti albumą", "create_album": "Sukurti albumą",
"create_album_page_untitled": "Be pavadinimo", "create_album_page_untitled": "Be pavadinimo",
@@ -469,57 +725,115 @@
"create_link": "Sukurti nuorodą", "create_link": "Sukurti nuorodą",
"create_link_to_share": "Sukurti bendrinimo nuorodą", "create_link_to_share": "Sukurti bendrinimo nuorodą",
"create_link_to_share_description": "Leisti bet kam su nuoroda matyti pažymėtą(-as) nuotrauką(-as)", "create_link_to_share_description": "Leisti bet kam su nuoroda matyti pažymėtą(-as) nuotrauką(-as)",
"create_new": "SUKURTI NAUJĄ",
"create_new_person": "Sukurti naują žmogų", "create_new_person": "Sukurti naują žmogų",
"create_new_person_hint": "Priskirti pasirinktus elementus naujam žmogui", "create_new_person_hint": "Priskirti pasirinktus elementus naujam žmogui",
"create_new_user": "Sukurti naują varotoją", "create_new_user": "Sukurti naują varotoją",
"create_shared_album_page_share_add_assets": "PRIDĖTI ELEMENTŲ",
"create_shared_album_page_share_select_photos": "Pažymėti nuotraukas",
"create_shared_link": "Sukurti dalijimosi nuorodą",
"create_tag": "Sukurti žymą", "create_tag": "Sukurti žymą",
"create_tag_description": "Sukurti naują žymą. Įdėtinėms žymoms įveskite pilną kelią, įskaitant pasviruosius brūkšnius.", "create_tag_description": "Sukurti naują žymą. Įdėtinėms žymoms įveskite pilną kelią, įskaitant pasviruosius brūkšnius.",
"create_user": "Sukurti naudotoją", "create_user": "Sukurti naudotoją",
"created": "Sukurta", "created": "Sukurta",
"created_at": "Sukurta",
"crop": "Apkirpti",
"curated_object_page_title": "Daiktai",
"current_device": "Dabartinis įrenginys", "current_device": "Dabartinis įrenginys",
"current_pin_code": "Dabartinis PIN kodas",
"current_server_address": "Dabartinis serverio adresas",
"custom_locale": "Pasirinktinė vietovė",
"custom_locale_description": "Formatuoti datas ir skaičius pagal kalbą ir regioną", "custom_locale_description": "Formatuoti datas ir skaičius pagal kalbą ir regioną",
"custom_url": "Pasirinktinis URL",
"daily_title_text_date": "E, MMM dd",
"daily_title_text_date_year": "E, MMM dd, yyyy",
"dark": "Tamsi",
"dark_theme": "Perjungti tamsią temą",
"date_after": "Data po", "date_after": "Data po",
"date_and_time": "Data ir laikas", "date_and_time": "Data ir laikas",
"date_before": "Data prieš", "date_before": "Data prieš",
"date_format": "E, LLL d, y • h:mm",
"date_of_birth_saved": "Gimimo data sėkmingai išsaugota", "date_of_birth_saved": "Gimimo data sėkmingai išsaugota",
"date_range": "Datų intervalas",
"day": "Diena", "day": "Diena",
"days": "Dienų",
"deduplicate_all": "Šalinti visus dublikatus", "deduplicate_all": "Šalinti visus dublikatus",
"deduplication_criteria_1": "Failo dydis baitais", "deduplication_criteria_1": "Failo dydis baitais",
"deduplication_criteria_2": "EXIF metaduomenų įrašų skaičius", "deduplication_criteria_2": "EXIF metaduomenų įrašų skaičius",
"deduplication_info": "Dublikatų šalinimo informacija", "deduplication_info": "Dublikatų šalinimo informacija",
"deduplication_info_description": "Automatinis elementų parinkimas ir masinis dublikatų šalinimas atliekamas atsižvelgiant į:", "deduplication_info_description": "Automatinis elementų parinkimas ir masinis dublikatų šalinimas atliekamas atsižvelgiant į:",
"default_locale": "Pradinė vietovė",
"default_locale_description": "Formatuoti datas ir skaičius pagal jūsų naršyklės lokalę", "default_locale_description": "Formatuoti datas ir skaičius pagal jūsų naršyklės lokalę",
"delete": "Ištrinti", "delete": "Ištrinti",
"delete_action_confirmation_message": "Ar tikrai norite ištrinti šį elementą? Šis veiksmas perkels elementą į serverio šiukšliadėžę ir paklaus ar norite ištrinti vietiniame įrenginyje",
"delete_action_prompt": "{count} ištrinta",
"delete_album": "Ištrinti albumą", "delete_album": "Ištrinti albumą",
"delete_api_key_prompt": "Ar tikrai norite ištrinti šį API raktą?", "delete_api_key_prompt": "Ar tikrai norite ištrinti šį API raktą?",
"delete_dialog_alert": "Šie elementai bus galutinai ištrinti iš Immich ir iš jūsų įrenginio",
"delete_dialog_alert_local": "Šie elementai bus galutinai pašalinti iš jūsų įrenginio, bet bus prieinami Immich serveryje",
"delete_dialog_alert_local_non_backed_up": "Kai kurie elementai be Immich atsarginės kopijos ir bus galutinai pašalinti iš jūsų įrenginio",
"delete_dialog_alert_remote": "Šie elementai bus galutinai ištrinti iš Immich serverio",
"delete_dialog_ok_force": "Vis tiek ištrinti",
"delete_dialog_title": "Ištrinti galutinai",
"delete_duplicates_confirmation": "Ar tikrai norite visam laikui ištrinti šiuos dublikatus?", "delete_duplicates_confirmation": "Ar tikrai norite visam laikui ištrinti šiuos dublikatus?",
"delete_face": "Ištrinti veidą",
"delete_key": "Ištrinti raktą", "delete_key": "Ištrinti raktą",
"delete_library": "Ištrinti biblioteką", "delete_library": "Ištrinti biblioteką",
"delete_link": "Ištrinti nuorodą", "delete_link": "Ištrinti nuorodą",
"delete_local_action_prompt": "{count} ištrinti vietiniame įrenginyje",
"delete_local_dialog_ok_backed_up_only": "Ištrinti tik turinčius atsarginę kopiją",
"delete_local_dialog_ok_force": "Vis tiek ištrinti",
"delete_others": "Ištrinti kitus",
"delete_permanently": "Ištrinti galutinai",
"delete_permanently_action_prompt": "{count} ištrinta galutinai",
"delete_shared_link": "Ištrinti bendrinimo nuorodą", "delete_shared_link": "Ištrinti bendrinimo nuorodą",
"delete_shared_link_dialog_title": "Ištrinti dalijimosi nuorodą",
"delete_tag": "Ištrinti žymą", "delete_tag": "Ištrinti žymą",
"delete_tag_confirmation_prompt": "Ar tikrai norite ištrinti žymą {tagName}?", "delete_tag_confirmation_prompt": "Ar tikrai norite ištrinti žymą {tagName}?",
"delete_user": "Ištrinti naudotoją", "delete_user": "Ištrinti naudotoją",
"deleted_shared_link": "Bendrinimo nuoroda ištrinta", "deleted_shared_link": "Bendrinimo nuoroda ištrinta",
"deletes_missing_assets": "Ištrinti diske trūkstamus elementus",
"description": "Aprašymas", "description": "Aprašymas",
"description_input_hint_text": "Pridėti aprašymą...",
"description_input_submit_error": "Klaida atnaujinant aprašymą, pasitikrinkite žurnalą norint detalesnės informacijos",
"deselect_all": "Atžymėti visus",
"details": "Detalės", "details": "Detalės",
"direction": "Kryptis", "direction": "Kryptis",
"disabled": "Išjungta", "disabled": "Išjungta",
"disallow_edits": "Neleisti redaguoti", "disallow_edits": "Neleisti redaguoti",
"discord": "Discord",
"discover": "Atrasti", "discover": "Atrasti",
"discovered_devices": "Aptikti įrenginiai",
"dismiss_all_errors": "Nepaisyti visų klaidų", "dismiss_all_errors": "Nepaisyti visų klaidų",
"dismiss_error": "Nepaisyti klaidos", "dismiss_error": "Nepaisyti klaidos",
"display_options": "Atvaizdavimo parinktys",
"display_order": "Atvaizdavimo tvarka", "display_order": "Atvaizdavimo tvarka",
"display_original_photos": "Rodyti originalias nuotraukas", "display_original_photos": "Rodyti originalias nuotraukas",
"display_original_photos_setting_description": "Pirmenybė rodyti originalią nuotrauką vietoje miniatiūros kai originalo elementas yra palaikomas naršyklės. Tai gali lemti lėtesnį nuotraukos rodymo greitį.",
"do_not_show_again": "Daugiau nerodyti šio pranešimo", "do_not_show_again": "Daugiau nerodyti šio pranešimo",
"documentation": "Dokumentacija", "documentation": "Dokumentacija",
"done": "Atlikta",
"download": "Atsisiųsti", "download": "Atsisiųsti",
"download_action_prompt": "Atsisiunčiami {count} elementai",
"download_canceled": "Atsisiuntimas atšauktas",
"download_complete": "Atsisiuntimas pabaigtas",
"download_enqueue": "Atsisiuntimai įtraukti į eilę",
"download_error": "Atsisiuntimo klaida",
"download_failed": "Nepavyko parsisiųsti", "download_failed": "Nepavyko parsisiųsti",
"download_finished": "Atsisiuntimas pabaigtas",
"download_include_embedded_motion_videos": "Įterpti vaizdo įrašai",
"download_include_embedded_motion_videos_description": "Pridėti prie judesio nuotraukų įterptus video kaip atskirą failą", "download_include_embedded_motion_videos_description": "Pridėti prie judesio nuotraukų įterptus video kaip atskirą failą",
"download_notfound": "Atsisiuntimas nerastas",
"download_paused": "Atsisiuntimas pristabdytas", "download_paused": "Atsisiuntimas pristabdytas",
"download_settings": "Atsisiųsti", "download_settings": "Atsisiųsti",
"download_settings_description": "Tvarkyti elementų atsisiuntimo nustatymus",
"download_started": "Atsisiuntimas pradėtas",
"download_sucess": "Atsisiuntimas pavyko",
"download_sucess_android": "Medija buvo atsiųsta į DCIM/Immich",
"download_waiting_to_retry": "Laukiama bandymo iš naujo",
"downloading": "Siunčiama", "downloading": "Siunčiama",
"downloading_asset_filename": "Parsisiunčiamas resursas {filename}", "downloading_asset_filename": "Parsisiunčiamas resursas {filename}",
"downloading_media": "Atsisiunčiama medija",
"drop_files_to_upload": "Užkelkite failus bet kurioje vietoje kad įkeltumėte", "drop_files_to_upload": "Užkelkite failus bet kurioje vietoje kad įkeltumėte",
"duplicates": "Dublikatai", "duplicates": "Dublikatai",
"duplicates_description": "Sutvarkykite kiekvieną elementų grupę nurodydami elementus, kurie yra dublikatai (jei tokių yra)", "duplicates_description": "Sutvarkykite kiekvieną elementų grupę nurodydami elementus, kurie yra dublikatai (jei tokių yra)",
@@ -527,8 +841,14 @@
"edit": "Redaguoti", "edit": "Redaguoti",
"edit_album": "Redaguoti albumą", "edit_album": "Redaguoti albumą",
"edit_avatar": "Redaguoti avatarą", "edit_avatar": "Redaguoti avatarą",
"edit_birthday": "Redaguoti gimtadienį",
"edit_date": "Redaguoti datą", "edit_date": "Redaguoti datą",
"edit_date_and_time": "Redaguoti datą ir laiką", "edit_date_and_time": "Redaguoti datą ir laiką",
"edit_date_and_time_action_prompt": "{count} data ir laikas redaguotas",
"edit_date_and_time_by_offset": "Keisti datą pagal poslinkį",
"edit_date_and_time_by_offset_interval": "Naujas datos intervalas: {from} - {to}",
"edit_description": "Redaguoti aprašymą",
"edit_description_prompt": "Prašome pasirinkti naują aprašymą:",
"edit_exclusion_pattern": "Redaguoti išimčių šabloną", "edit_exclusion_pattern": "Redaguoti išimčių šabloną",
"edit_faces": "Redaguoti veidus", "edit_faces": "Redaguoti veidus",
"edit_import_path": "Redaguoti importavimo kelią", "edit_import_path": "Redaguoti importavimo kelią",
@@ -536,41 +856,79 @@
"edit_key": "Redaguoti raktą", "edit_key": "Redaguoti raktą",
"edit_link": "Redaguoti nuorodą", "edit_link": "Redaguoti nuorodą",
"edit_location": "Redaguoti vietovę", "edit_location": "Redaguoti vietovę",
"edit_location_action_prompt": "{count} vietovės pakeistos",
"edit_location_dialog_title": "Vietovė",
"edit_name": "Redaguoti vardą", "edit_name": "Redaguoti vardą",
"edit_people": "Redaguoti žmones", "edit_people": "Redaguoti žmones",
"edit_tag": "Redaguoti žymą", "edit_tag": "Redaguoti žymą",
"edit_title": "Redaguoti antraštę", "edit_title": "Redaguoti antraštę",
"edit_user": "Redaguoti naudotoją", "edit_user": "Redaguoti naudotoją",
"edited": "Redaguota", "edited": "Redaguota",
"editor": "Redaktorius",
"editor_close_without_save_prompt": "Pakeitimai nebus išsaugoti",
"editor_close_without_save_title": "Uždaryti redaktorių?",
"editor_crop_tool_h2_aspect_ratios": "Vaizdo santykis",
"editor_crop_tool_h2_rotation": "Pasukimas",
"email": "El. paštas", "email": "El. paštas",
"email_notifications": "El. pašto pranešimai",
"empty_folder": "Šis katalogas yra tuščias",
"empty_trash": "Ištuštinti šiukšliadėžę", "empty_trash": "Ištuštinti šiukšliadėžę",
"empty_trash_confirmation": "Ar tikrai norite ištuštinti šiukšliadėžę? Tai galutinai pašalins elementus iš Immich.\nJūs negalėsite atkurti šio veiksmo!",
"enable": "Įgalinti", "enable": "Įgalinti",
"enable_backup": "Įgalinti atsargines kopijas",
"enable_biometric_auth_description": "Įveskite savo PIN kodą biometrinės autentifikacijos įjungimui",
"enabled": "Įgalintas", "enabled": "Įgalintas",
"end_date": "Pabaigos data", "end_date": "Pabaigos data",
"enter_wifi_name": "Enter WiFi name", "enqueued": "Įtraukta į eilę",
"enter_wifi_name": "Įveskite Wi-Fi pavadinimą",
"enter_your_pin_code": "Įveskite savo PIN kodą",
"enter_your_pin_code_subtitle": "Įveskite savo PIN kodą, kad pasiektumėte užrakintą aplanką", "enter_your_pin_code_subtitle": "Įveskite savo PIN kodą, kad pasiektumėte užrakintą aplanką",
"error": "Klaida", "error": "Klaida",
"error_change_sort_album": "Nepavyko pakeisti albumo rūšiavimo tvarkos",
"error_delete_face": "Klaida trinant veidą iš elementų",
"error_loading_image": "Klaida įkeliant vaizdą", "error_loading_image": "Klaida įkeliant vaizdą",
"error_saving_image": "Klaida: {error}",
"error_tag_face_bounding_box": "Klaida aprašant veidą - nepavyko gauti veido vietos koordinačių",
"error_title": "Klaida - Kažkas nutiko ne taip", "error_title": "Klaida - Kažkas nutiko ne taip",
"errors": { "errors": {
"cannot_navigate_next_asset": "Negalima pereiti prie sekančio elemento",
"cannot_navigate_previous_asset": "Negalima pereiti prie buvusio elemento",
"cant_apply_changes": "Negalima taikyti pakeitimų", "cant_apply_changes": "Negalima taikyti pakeitimų",
"cant_change_activity": "Negalima {enabled, select, true {išjungti} other {įjungti}} veiklos",
"cant_change_asset_favorite": "Elementui negalima pakeisti mėgstamiausio",
"cant_change_metadata_assets_count": "Negalima pakeisti {count, plural, one {# elemento} other {# elementų}} metadata",
"cant_get_faces": "Nepavyko gauti veidus",
"cant_get_number_of_comments": "Nepavyko gauti komentarų skaičiaus",
"cant_search_people": "Negalima ieškoti žmonių",
"cant_search_places": "Negalima ieškoti vietovių",
"error_adding_assets_to_album": "Klaida pridedant elementus į albumą", "error_adding_assets_to_album": "Klaida pridedant elementus į albumą",
"error_adding_users_to_album": "Klaida pridedant naudotojus prie albumo", "error_adding_users_to_album": "Klaida pridedant naudotojus prie albumo",
"error_deleting_shared_user": "Klaida trinant pasidalintą naudotoją",
"error_downloading": "Klaida atsisiunčiant {filename}", "error_downloading": "Klaida atsisiunčiant {filename}",
"error_hiding_buy_button": "Klaida slepiant pirkimo mygtuką", "error_hiding_buy_button": "Klaida slepiant pirkimo mygtuką",
"error_removing_assets_from_album": "Klaida šalinant elementus iš albumo, patikrinkite konsolę dėl išsamesnės informacijos", "error_removing_assets_from_album": "Klaida šalinant elementus iš albumo, patikrinkite konsolę dėl išsamesnės informacijos",
"error_selecting_all_assets": "Klaida pasirenkant visus elementus",
"exclusion_pattern_already_exists": "Šis išimčių šablonas jau egzistuoja.", "exclusion_pattern_already_exists": "Šis išimčių šablonas jau egzistuoja.",
"failed_to_create_album": "Nepavyko sukurti albumo", "failed_to_create_album": "Nepavyko sukurti albumo",
"failed_to_create_shared_link": "Nepavyko sukurti bendrinimo nuorodos", "failed_to_create_shared_link": "Nepavyko sukurti bendrinimo nuorodos",
"failed_to_edit_shared_link": "Nepavyko redaguoti bendrinimo nuorodos", "failed_to_edit_shared_link": "Nepavyko redaguoti bendrinimo nuorodos",
"failed_to_get_people": "Nepavyko gauti žmonių",
"failed_to_keep_this_delete_others": "Nepavyko palikti šį elementą ir ištrinti kitus elementus",
"failed_to_load_asset": "Nepavyko užkrauti elemento",
"failed_to_load_assets": "Nepavyko užrauti elementų",
"failed_to_load_notifications": "Nepavyko užkrauti pranešimų",
"failed_to_load_people": "Nepavyko užkrauti žmonių", "failed_to_load_people": "Nepavyko užkrauti žmonių",
"failed_to_remove_product_key": "Nepavyko pašalinti produkto rakto", "failed_to_remove_product_key": "Nepavyko pašalinti produkto rakto",
"failed_to_reset_pin_code": "Nepavyko atkurti PIN kodo",
"failed_to_stack_assets": "Nepavyko sugrupuoti elementų", "failed_to_stack_assets": "Nepavyko sugrupuoti elementų",
"failed_to_unstack_assets": "Nepavyko išgrupuoti elementų", "failed_to_unstack_assets": "Nepavyko išgrupuoti elementų",
"failed_to_update_notification_status": "Nepavyko atnaujinti pranešimo statuso",
"import_path_already_exists": "Šis importavimo kelias jau egzistuoja.", "import_path_already_exists": "Šis importavimo kelias jau egzistuoja.",
"incorrect_email_or_password": "Neteisingas el. pašto adresas arba slaptažodis", "incorrect_email_or_password": "Neteisingas el. pašto adresas arba slaptažodis",
"paths_validation_failed": "Nepavyko {paths, plural, one {# kelio} other {# kelių}} patvirtinimas",
"profile_picture_transparent_pixels": "Profilio nuotrauka negali turėti permatomų pikselių. Prašome priartinti ir/arba perkelkite nuotrauką.", "profile_picture_transparent_pixels": "Profilio nuotrauka negali turėti permatomų pikselių. Prašome priartinti ir/arba perkelkite nuotrauką.",
"quota_higher_than_disk_size": "Nustatyta kvota, viršija disko dydį", "quota_higher_than_disk_size": "Nustatyta kvota, viršija disko dydį",
"something_went_wrong": "Kažkas nepavyko",
"unable_to_add_album_users": "Nepavyksta pridėti naudotojų prie albumo", "unable_to_add_album_users": "Nepavyksta pridėti naudotojų prie albumo",
"unable_to_add_assets_to_shared_link": "Nepavyko į bendrinimo nuorodą pridėti elementų", "unable_to_add_assets_to_shared_link": "Nepavyko į bendrinimo nuorodą pridėti elementų",
"unable_to_add_comment": "Nepavyksta pridėti komentaro", "unable_to_add_comment": "Nepavyksta pridėti komentaro",
@@ -578,11 +936,15 @@
"unable_to_add_import_path": "Nepavyksta pridėti importavimo kelio", "unable_to_add_import_path": "Nepavyksta pridėti importavimo kelio",
"unable_to_add_partners": "Nepavyksta pridėti partnerių", "unable_to_add_partners": "Nepavyksta pridėti partnerių",
"unable_to_add_remove_archive": "Nepavyko {archived, select, true {ištraukti iš} other {pridėti prie}} arcyhvo", "unable_to_add_remove_archive": "Nepavyko {archived, select, true {ištraukti iš} other {pridėti prie}} arcyhvo",
"unable_to_add_remove_favorites": "Nepavyko {favorite, select, true {įtraukti elemento į mėgstamiausius} other {pašalinti elemento iš mėgstamiausių}}",
"unable_to_archive_unarchive": "Nepavyko {archived, select, true {archyvuoti} other {išarchyvuoti}}", "unable_to_archive_unarchive": "Nepavyko {archived, select, true {archyvuoti} other {išarchyvuoti}}",
"unable_to_change_album_user_role": "Nepavyksta pakeisti albumo naudotojo rolės", "unable_to_change_album_user_role": "Nepavyksta pakeisti albumo naudotojo rolės",
"unable_to_change_date": "Negalima pakeisti datos", "unable_to_change_date": "Negalima pakeisti datos",
"unable_to_change_description": "Nepavyko pakeisti aprašymo",
"unable_to_change_favorite": "Nepavyko pakeisti elementui mėgstamiausio",
"unable_to_change_location": "Negalima pakeisti vietos", "unable_to_change_location": "Negalima pakeisti vietos",
"unable_to_change_password": "Negalima pakeisti slaptažodžio", "unable_to_change_password": "Negalima pakeisti slaptažodžio",
"unable_to_change_visibility": "Nepavyko pakeisti matomumo {count, plural, one {# asmeniui} few {#asmenims} other {# asmenų}}",
"unable_to_complete_oauth_login": "Nepavyko prisijungti su OAuth", "unable_to_complete_oauth_login": "Nepavyko prisijungti su OAuth",
"unable_to_connect": "Nepavyko prisijungti", "unable_to_connect": "Nepavyko prisijungti",
"unable_to_copy_to_clipboard": "Negalima kopijuoti į iškarpinę, įsitikinkite, kad prie puslapio prieinate per https", "unable_to_copy_to_clipboard": "Negalima kopijuoti į iškarpinę, įsitikinkite, kad prie puslapio prieinate per https",
@@ -591,6 +953,8 @@
"unable_to_create_library": "Nepavyko sukurti bibliotekos", "unable_to_create_library": "Nepavyko sukurti bibliotekos",
"unable_to_create_user": "Nepavyko sukurti naudotojo", "unable_to_create_user": "Nepavyko sukurti naudotojo",
"unable_to_delete_album": "Nepavyksta ištrinti albumo", "unable_to_delete_album": "Nepavyksta ištrinti albumo",
"unable_to_delete_asset": "Nepavyko ištrinti elemento",
"unable_to_delete_assets": "Klaida trinant elementus",
"unable_to_delete_exclusion_pattern": "Nepavyksta ištrinti išimčių šablono", "unable_to_delete_exclusion_pattern": "Nepavyksta ištrinti išimčių šablono",
"unable_to_delete_import_path": "Nepavyksta ištrinti importavimo kelio", "unable_to_delete_import_path": "Nepavyksta ištrinti importavimo kelio",
"unable_to_delete_shared_link": "Nepavyko ištrinti bendrinimo nuorodos", "unable_to_delete_shared_link": "Nepavyko ištrinti bendrinimo nuorodos",
@@ -598,22 +962,37 @@
"unable_to_download_files": "Nepavyksta atsisiųsti failų", "unable_to_download_files": "Nepavyksta atsisiųsti failų",
"unable_to_edit_exclusion_pattern": "Nepavyksta redaguoti išimčių šablono", "unable_to_edit_exclusion_pattern": "Nepavyksta redaguoti išimčių šablono",
"unable_to_edit_import_path": "Nepavyksta redaguoti išimčių kelio", "unable_to_edit_import_path": "Nepavyksta redaguoti išimčių kelio",
"unable_to_empty_trash": "Nepavyko ištrinti šiukšliadėžės",
"unable_to_enter_fullscreen": "Nepavyksta pereiti į viso ekrano režimą", "unable_to_enter_fullscreen": "Nepavyksta pereiti į viso ekrano režimą",
"unable_to_exit_fullscreen": "Nepavyksta išeiti iš viso ekrano režimo", "unable_to_exit_fullscreen": "Nepavyksta išeiti iš viso ekrano režimo",
"unable_to_get_comments_number": "Nepavyko gauti komentarų skaičiaus",
"unable_to_get_shared_link": "Nepavyko gauti bendrinimo nuorodos", "unable_to_get_shared_link": "Nepavyko gauti bendrinimo nuorodos",
"unable_to_hide_person": "Nepavyksta paslėpti žmogaus", "unable_to_hide_person": "Nepavyksta paslėpti žmogaus",
"unable_to_link_motion_video": "Nepavyko susieti judesio video",
"unable_to_link_oauth_account": "Nepavyko susieti su OAuth paskyra", "unable_to_link_oauth_account": "Nepavyko susieti su OAuth paskyra",
"unable_to_log_out_all_devices": "Nepavyksta atjungti visų įrenginių", "unable_to_log_out_all_devices": "Nepavyksta atjungti visų įrenginių",
"unable_to_log_out_device": "Nepavyksta atjungti įrenginio", "unable_to_log_out_device": "Nepavyksta atjungti įrenginio",
"unable_to_login_with_oauth": "Nepavyko prisijungti su OAuth", "unable_to_login_with_oauth": "Nepavyko prisijungti su OAuth",
"unable_to_play_video": "Nepavyksta paleisti vaizdo įrašo", "unable_to_play_video": "Nepavyksta paleisti vaizdo įrašo",
"unable_to_reassign_assets_existing_person": "Nepavyko priskirti elementų {name, select, null {egzistuojančiam asmeniui} other {{name}}}",
"unable_to_reassign_assets_new_person": "Nepavyko priskirti elementų naujam asmeniui",
"unable_to_refresh_user": "Nepavyksta atnaujinti naudotojo", "unable_to_refresh_user": "Nepavyksta atnaujinti naudotojo",
"unable_to_remove_album_users": "Nepavyko pašalinti naudotojų iš albumo",
"unable_to_remove_api_key": "Nepavyko pašalinti API rakto", "unable_to_remove_api_key": "Nepavyko pašalinti API rakto",
"unable_to_remove_assets_from_shared_link": "Nepavyko iš bendrinimo nuorodos pašalinti elementų", "unable_to_remove_assets_from_shared_link": "Nepavyko iš bendrinimo nuorodos pašalinti elementų",
"unable_to_remove_library": "Nepavyksta pašalinti bibliotekos", "unable_to_remove_library": "Nepavyksta pašalinti bibliotekos",
"unable_to_remove_partner": "Nepavyksta pašalinti partnerio", "unable_to_remove_partner": "Nepavyksta pašalinti partnerio",
"unable_to_remove_reaction": "Nepavyksta pašalinti reakcijos", "unable_to_remove_reaction": "Nepavyksta pašalinti reakcijos",
"unable_to_reset_password": "Nepavyko atnaujinti slaptažodžio",
"unable_to_reset_pin_code": "Nepavyko atnaujinti PIN kodo",
"unable_to_resolve_duplicate": "Nepavyko sutvarkyti dublikatų", "unable_to_resolve_duplicate": "Nepavyko sutvarkyti dublikatų",
"unable_to_restore_assets": "Nepavyko atstatyti elementų",
"unable_to_restore_trash": "Nepavyko atstatyti iš šiukšliadėžės",
"unable_to_restore_user": "Nepavyko atstatyti naudotojo",
"unable_to_save_album": "Nepavyko išsaugoti albumo",
"unable_to_save_api_key": "Nepavyko išsaugoti API rakto",
"unable_to_save_date_of_birth": "Nepavyko išsaugoti gimimo datos",
"unable_to_save_name": "Nepavyko išsaugoti vardo",
"unable_to_save_profile": "Nepavyko išsaugoti profilio", "unable_to_save_profile": "Nepavyko išsaugoti profilio",
"unable_to_save_settings": "Nepavyksta išsaugoti nustatymų", "unable_to_save_settings": "Nepavyksta išsaugoti nustatymų",
"unable_to_scan_libraries": "Nepavyksta nuskaityti bibliotekų", "unable_to_scan_libraries": "Nepavyksta nuskaityti bibliotekų",
@@ -622,39 +1001,104 @@
"unable_to_set_profile_picture": "Nepavyksta nustatyti profilio nuotraukos", "unable_to_set_profile_picture": "Nepavyksta nustatyti profilio nuotraukos",
"unable_to_submit_job": "Napvyko sukurti užduoties", "unable_to_submit_job": "Napvyko sukurti užduoties",
"unable_to_trash_asset": "Nepavyko perkelti į šiukšliadėžę", "unable_to_trash_asset": "Nepavyko perkelti į šiukšliadėžę",
"unable_to_unlink_account": "Nepavyko atsieti paskyrų",
"unable_to_unlink_motion_video": "Nepavyko atsieti judesio video",
"unable_to_update_album_cover": "Nepavyko atnaujinti albumo viršelio",
"unable_to_update_album_info": "Nepavyko atnaujinti albumo informacijos",
"unable_to_update_library": "Nepavyko atnaujinti bibliotekos",
"unable_to_update_location": "Nepavyko atnaujinti vietovės",
"unable_to_update_settings": "Nepavyko atnaujinti nustatymų",
"unable_to_update_timeline_display_status": "Nepavyko atnaujinti laiko juostos rodymo statuso",
"unable_to_update_user": "Nepavyko atnaujinti naudotoją",
"unable_to_upload_file": "Nepavyksta įkelti failo" "unable_to_upload_file": "Nepavyksta įkelti failo"
}, },
"exif": "Exif",
"exif_bottom_sheet_description": "Pridėti aprašymą...",
"exif_bottom_sheet_description_error": "Klaida atnaujinant aprašymą",
"exif_bottom_sheet_details": "DETALĖS",
"exif_bottom_sheet_location": "VIETOVĖ",
"exif_bottom_sheet_people": "ŽMONĖS",
"exif_bottom_sheet_person_add_person": "Pridėti vardą",
"exit_slideshow": "Išeiti iš skaidrių peržiūros", "exit_slideshow": "Išeiti iš skaidrių peržiūros",
"expand_all": "Išskleisti viską", "expand_all": "Išskleisti viską",
"experimental_settings_new_asset_list_subtitle": "Dirbama",
"experimental_settings_new_asset_list_title": "Įgalinti eksperimentinį nuotraukų tinklelį",
"experimental_settings_subtitle": "Naudokite savo pačių rizika!",
"experimental_settings_title": "Eksperimentinis",
"expire_after": "Galiojimas baigiasi",
"expired": "Nebegalioja", "expired": "Nebegalioja",
"expires_date": "Nebegalios už {date}", "expires_date": "Nebegalios už {date}",
"explore": "Naršyti", "explore": "Naršyti",
"explorer": "Naršyklė",
"export": "Eksportuoti", "export": "Eksportuoti",
"export_as_json": "Eksportuoti kaip JSON", "export_as_json": "Eksportuoti kaip JSON",
"export_database": "Eksportuoti duomenų bazę",
"export_database_description": "Eksportuoti SQLite duomenų bazę",
"extension": "Plėtinys", "extension": "Plėtinys",
"external": "Išorinis", "external": "Išorinis",
"external_libraries": "Išorinės bibliotekos", "external_libraries": "Išorinės bibliotekos",
"external_network_sheet_info": "When not on the preferred WiFi network, the app will connect to the server through the first of the below URLs it can reach, starting from top to bottom", "external_network": "Išorinis tinklas",
"external_network_sheet_info": "Kai neprisijungta prie pageidaujamo Wi-Fi tinklo, programa jungsis prie serverio per pirmą URL nuorodą, kurią galės pasiekti, pradedant nuo viršaus į apačią",
"face_unassigned": "Nepriskirta", "face_unassigned": "Nepriskirta",
"failed": "Įvyko klaida", "failed": "Įvyko klaida",
"failed_to_authenticate": "Nepavyko autentifikuoti",
"failed_to_load_assets": "Nepavyko įkelti elementų",
"failed_to_load_folder": "Nepavyko įkelti katalogą",
"favorite": "Mėgstamiausias", "favorite": "Mėgstamiausias",
"favorite_action_prompt": "{count} pridėta prie mėgstamiausių",
"favorite_or_unfavorite_photo": "Įtraukti prie arba pašalinti iš mėgstamiausių", "favorite_or_unfavorite_photo": "Įtraukti prie arba pašalinti iš mėgstamiausių",
"favorites": "Mėgstamiausi", "favorites": "Mėgstamiausi",
"favorites_page_no_favorites": "Nerasta mėgstamiausių elementų",
"feature_photo_updated": "Pageidaujama nuotrauka atnaujinta",
"features": "Funkcijos", "features": "Funkcijos",
"features_setting_description": "Valdyti aplikacijos funkcijas", "features_setting_description": "Valdyti aplikacijos funkcijas",
"file_name": "Failo pavadinimas", "file_name": "Failo pavadinimas",
"file_name_or_extension": "Failo pavadinimas arba plėtinys", "file_name_or_extension": "Failo pavadinimas arba plėtinys",
"filename": "Failopavadinimas", "filename": "Failopavadinimas",
"filetype": "Failo tipas", "filetype": "Failo tipas",
"filter": "Filtras",
"filter_people": "Filtruoti žmones", "filter_people": "Filtruoti žmones",
"filter_places": "Filtruoti vietoves",
"find_them_fast": "Raskite greitai paieškoje pagal vardą",
"first": "Pirmas",
"fix_incorrect_match": "Pataisyti neteisingą porą",
"folder": "Katalogas",
"folder_not_found": "Katalogas nerastas",
"folders": "Aplankai", "folders": "Aplankai",
"folders_feature_description": "Peržiūrėkite failų sistemoje esančias nuotraukas ir vaizdo įrašus aplankų rodinyje", "folders_feature_description": "Peržiūrėkite failų sistemoje esančias nuotraukas ir vaizdo įrašus aplankų rodinyje",
"forgot_pin_code_question": "Pamiršote savo PIN?",
"forward": "Pirmyn",
"gcast_enabled": "Google Cast",
"gcast_enabled_description": "Kad veiktų, ši funkcija įkelia išorinius „Google“ išteklius.",
"general": "Bendri",
"geolocation_instruction_location": "Paspauskite ant elemento su GPS koordinatėmis norint naudoti tą vietovę arba pasirinkite vietovę tiesiogiai žemėlapyje",
"get_help": "Gauti pagalbos", "get_help": "Gauti pagalbos",
"get_wifiname_error": "Nepavyko gauti Wi-Fi pavadinimo. Įsitikinkite, kad suteikti būtini leidimai ir esate prisijungę prie Wi-Fi tinklo",
"getting_started": "Pradedama",
"go_back": "Eiti atgal",
"go_to_folder": "Eiti į katalogą",
"go_to_search": "Eiti į paiešką",
"gps": "GPS",
"gps_missing": "Be GPS",
"grant_permission": "Suteikti leidimą",
"group_albums_by": "Grupuoti albumus pagal...", "group_albums_by": "Grupuoti albumus pagal...",
"group_country": "Grupuoti pagal šalis",
"group_no": "Negrupuoti", "group_no": "Negrupuoti",
"group_owner": "Grupuoti pagal savininką", "group_owner": "Grupuoti pagal savininką",
"group_places_by": "Grupuoti vietoves pagal...",
"group_year": "Grupuoti pagal metus", "group_year": "Grupuoti pagal metus",
"haptic_feedback_switch": "Įjungti haptinį grįžtamąjį ryšį",
"haptic_feedback_title": "Haptinis grįžtamasis ryšys",
"has_quota": "Turi kvotą", "has_quota": "Turi kvotą",
"hash_asset": "Maišymo elementas",
"hashed_assets": "Sumaišyti elementai",
"hashing": "Maišoma",
"header_settings_add_header_tip": "Pridėti antraštę",
"header_settings_field_validator_msg": "Reikšmė negali būti tuščia",
"header_settings_header_name_input": "Antraštės pavadinimas",
"header_settings_header_value_input": "Antraštės reikšmė",
"headers_settings_tile_subtitle": "Apibrėžkite tarpinio serverio antraštes, kurias programa turėtų siųsti su kiekviena tinklo užklausa",
"headers_settings_tile_title": "Pasirinktinės tarpinio serverio antraštės",
"hi_user": "Labas {name} ({email})", "hi_user": "Labas {name} ({email})",
"hide_all_people": "Slėpti visus asmenis", "hide_all_people": "Slėpti visus asmenis",
"hide_gallery": "Slėpti galeriją", "hide_gallery": "Slėpti galeriją",
@@ -662,7 +1106,17 @@
"hide_password": "Slėpti slaptažodį", "hide_password": "Slėpti slaptažodį",
"hide_person": "Slėpti asmenį", "hide_person": "Slėpti asmenį",
"hide_unnamed_people": "Slėpti neįvardintus asmenis", "hide_unnamed_people": "Slėpti neįvardintus asmenis",
"home_page_first_time_notice": "If this is your first time using the app, please make sure to choose a backup album(s) so that the timeline can populate photos and videos in the album(s).", "home_page_add_to_album_conflicts": "Pridėta {added} elementų į albumą {album}. {failed} elementai jau yra albume.",
"home_page_add_to_album_err_local": "Kol kas negalima pridėti vietinių elementų į albumus, praleidžiama",
"home_page_add_to_album_success": "Pridėta {added} elementų į albumą {album}.",
"home_page_album_err_partner": "Kol kas negalima pridėti partnerio elementų į albumą, praleidžiama",
"home_page_archive_err_local": "Kol kas negalima archyvuoti vietinių elementų, praleidžiama",
"home_page_archive_err_partner": "Negalima archyvuoti partnerio elementų, praleidžiama",
"home_page_building_timeline": "Kuriama laiko juosta",
"home_page_delete_err_partner": "Negalima ištrinti partnerio elementų, praleidžiama",
"home_page_delete_remote_err_local": "Vietiniai elementai ištrinant nuotolinį pasirinkimą, praleidžiami",
"home_page_favorite_err_local": "Kol kad negalima priskirti mėgstamiausių vietinių elementų, praleidžiama",
"home_page_first_time_notice": "Jei jūs naudojate programą pirmą kartą, tai prašome pasirinkti atsarginės kopijos albumą, kad laiko juosta galėtų tvarkyti albumo nuotraukas ir vaizdo įrašus",
"home_page_locked_error_local": "Nepavyko perkelti lokalių failų į užrakintą aplanką, praleidžiama", "home_page_locked_error_local": "Nepavyko perkelti lokalių failų į užrakintą aplanką, praleidžiama",
"home_page_locked_error_partner": "Nepavyko perkelti partnerio failų į užrakintą aplanką, praleidžiama", "home_page_locked_error_partner": "Nepavyko perkelti partnerio failų į užrakintą aplanką, praleidžiama",
"hour": "Valanda", "hour": "Valanda",
@@ -707,7 +1161,7 @@
"list": "Sąrašas", "list": "Sąrašas",
"loading": "Kraunama", "loading": "Kraunama",
"loading_search_results_failed": "Nepavyko užkrauti paieškos rezultatų", "loading_search_results_failed": "Nepavyko užkrauti paieškos rezultatų",
"location_permission_content": "In order to use the auto-switching feature, Immich needs precise location permission so it can read the current WiFi network's name", "location_permission_content": "Norint naudoti automatinio persijungimo opciją, Immich reikia tikslios vietovės leidimo, kad galėtų nuskaityti Wi-Fi tinklo pavadinimą",
"locked_folder": "Užrakintas aplankas", "locked_folder": "Užrakintas aplankas",
"log_out": "Atsijungti", "log_out": "Atsijungti",
"log_out_all_devices": "Atsijungti iš visų įrenginių", "log_out_all_devices": "Atsijungti iš visų įrenginių",
@@ -727,7 +1181,10 @@
"manage_your_devices": "Valdyti prijungtus įrenginius", "manage_your_devices": "Valdyti prijungtus įrenginius",
"manage_your_oauth_connection": "Tvarkyti OAuth prisijungimą", "manage_your_oauth_connection": "Tvarkyti OAuth prisijungimą",
"map": "Žemėlapis", "map": "Žemėlapis",
"map_assets_in_bounds": "{count, plural, =0 {Nuotraukų nėra} one {# nuotrauka} other {# nuotraukos}}",
"map_settings": "Žemėlapio nustatymai", "map_settings": "Žemėlapio nustatymai",
"map_settings_date_range_option_days": "Pastarąsias {days} dienas",
"map_settings_date_range_option_years": "Pastaruosius {years} metus",
"map_settings_include_show_archived": "Įtraukti archyvuotus", "map_settings_include_show_archived": "Įtraukti archyvuotus",
"matches": "Atitikmenys", "matches": "Atitikmenys",
"media_type": "Laikmenos tipas", "media_type": "Laikmenos tipas",
@@ -785,6 +1242,7 @@
"notification_toggle_setting_description": "Įjungti el. pašto pranešimus", "notification_toggle_setting_description": "Įjungti el. pašto pranešimus",
"notifications": "Pranešimai", "notifications": "Pranešimai",
"notifications_setting_description": "Tvarkyti pranešimus", "notifications_setting_description": "Tvarkyti pranešimus",
"oauth": "OAuth",
"official_immich_resources": "Oficialūs Immich ištekliai", "official_immich_resources": "Oficialūs Immich ištekliai",
"offline": "Neprisijungęs", "offline": "Neprisijungęs",
"oldest_first": "Seniausias pirmas", "oldest_first": "Seniausias pirmas",
@@ -805,6 +1263,7 @@
"partner_can_access": "{partner} gali naudotis", "partner_can_access": "{partner} gali naudotis",
"partner_can_access_assets": "Visos jūsų nuotraukos ir vaizdo įrašai, išskyrus archyvuotus ir ištrintus", "partner_can_access_assets": "Visos jūsų nuotraukos ir vaizdo įrašai, išskyrus archyvuotus ir ištrintus",
"partner_can_access_location": "Vieta, kurioje darytos nuotraukos", "partner_can_access_location": "Vieta, kurioje darytos nuotraukos",
"partner_page_stop_sharing_content": "{partner} daugiau nebegalės pasiekti jūsų nuotraukų.",
"partners": "Partneriai", "partners": "Partneriai",
"password": "Slaptažodis", "password": "Slaptažodis",
"password_does_not_match": "Slaptažodis nesutampa", "password_does_not_match": "Slaptažodis nesutampa",
@@ -859,7 +1318,7 @@
"purchase_lifetime_description": "Pirkimas visam gyvenimui", "purchase_lifetime_description": "Pirkimas visam gyvenimui",
"purchase_option_title": "PIRKIMO PASIRINKIMAS", "purchase_option_title": "PIRKIMO PASIRINKIMAS",
"purchase_panel_info_1": "„Immich“ kūrimas užima daug laiko ir pastangų, o visą darbo dieną dirba inžinieriai, kad jis būtų kuo geresnis. Mūsų misija yra, kad atvirojo kodo programinė įranga ir etiška verslo praktika taptų tvariu kūrėjų pajamų šaltiniu ir sukurtų privatumą gerbiančią ekosistemą su realiomis alternatyvomis išnaudojamoms debesijos paslaugoms.", "purchase_panel_info_1": "„Immich“ kūrimas užima daug laiko ir pastangų, o visą darbo dieną dirba inžinieriai, kad jis būtų kuo geresnis. Mūsų misija yra, kad atvirojo kodo programinė įranga ir etiška verslo praktika taptų tvariu kūrėjų pajamų šaltiniu ir sukurtų privatumą gerbiančią ekosistemą su realiomis alternatyvomis išnaudojamoms debesijos paslaugoms.",
"purchase_panel_info_2": "Kadangi esame įsipareigoję nepridėti mokamų sienų, šis pirkinys nesuteiks jums jokių papildomų Immich funkcijų. Mes tikime, kad tokie naudotojai kaip jūs palaikys nuolatinį Immich vystymąsi.", "purchase_panel_info_2": "Kadangi esame įsipareigoję nepridėti mokamų sienų, šis pirkinys nesuteiks jums jokių papildomų Immich funkcijų. Mes tikime, kad tokie naudotojai kaip jūs palaikys nuolatinį Immich vystymąsi.",
"purchase_panel_title": "Palaikykite projektą", "purchase_panel_title": "Palaikykite projektą",
"purchase_per_server": "Vienam serveriui", "purchase_per_server": "Vienam serveriui",
"purchase_per_user": "Vienam naudotojui", "purchase_per_user": "Vienam naudotojui",
@@ -998,7 +1457,11 @@
"setting_image_viewer_preview_title": "Užkrauti peržiūros nuotrauką", "setting_image_viewer_preview_title": "Užkrauti peržiūros nuotrauką",
"setting_image_viewer_title": "Nuotraukos", "setting_image_viewer_title": "Nuotraukos",
"setting_languages_apply": "Pritaikyti", "setting_languages_apply": "Pritaikyti",
"setting_notifications_notify_failures_grace_period": "Informuoti apie foninio atsarginio kopijavimo nesėkmes: {duration}",
"setting_notifications_notify_hours": "{count} valandų",
"setting_notifications_notify_minutes": "{count} minučių",
"setting_notifications_notify_never": "niekada", "setting_notifications_notify_never": "niekada",
"setting_notifications_notify_seconds": "{count} sekundžių",
"setting_notifications_single_progress_subtitle": "Detali įkėlimo progreso informacija kiekvienam elementui", "setting_notifications_single_progress_subtitle": "Detali įkėlimo progreso informacija kiekvienam elementui",
"settings": "Nustatymai", "settings": "Nustatymai",
"settings_require_restart": "Prašome perkrauti Immich, siekiant pritaikyti šį nustatymą", "settings_require_restart": "Prašome perkrauti Immich, siekiant pritaikyti šį nustatymą",
@@ -1006,13 +1469,29 @@
"setup_pin_code": "Nustatyti PIN kodą", "setup_pin_code": "Nustatyti PIN kodą",
"share": "Dalintis", "share": "Dalintis",
"share_add_photos": "Įtraukti nuotraukų", "share_add_photos": "Įtraukti nuotraukų",
"share_assets_selected": "{count} pažymėta",
"share_dialog_preparing": "Ruošiama...", "share_dialog_preparing": "Ruošiama...",
"share_link": "Bendrinti nuorodą", "share_link": "Bendrinti nuorodą",
"shared": "Bendrinami", "shared": "Bendrinami",
"shared_by_user": "Bendrina {user}", "shared_by_user": "Bendrina {user}",
"shared_by_you": "Bendrinama jūsų", "shared_by_you": "Bendrinama jūsų",
"shared_from_partner": "Nuotraukos iš {partner}", "shared_from_partner": "Nuotraukos iš {partner}",
"shared_intent_upload_button_progress_text": "{current} / {total} Įkelta",
"shared_link_clipboard_copied_massage": "Nukopijuota į iškarpinę", "shared_link_clipboard_copied_massage": "Nukopijuota į iškarpinę",
"shared_link_clipboard_text": "Nuoroda: {link}\nSlaptažodis: {password}",
"shared_link_edit_expire_after_option_days": "{count} dienų",
"shared_link_edit_expire_after_option_hours": "{count} valandų",
"shared_link_edit_expire_after_option_minutes": "{count} minučių",
"shared_link_edit_expire_after_option_months": "{count} mėnesių",
"shared_link_edit_expire_after_option_year": "{count} metų",
"shared_link_expires_day": "Galiojimas baigsis už {count} dienos",
"shared_link_expires_days": "Galiojimas baigsis už {count} dienų",
"shared_link_expires_hour": "Galiojimas baigsis už {count} valandos",
"shared_link_expires_hours": "Galiojimas baigsis už {count} valandų",
"shared_link_expires_minute": "Galiojimas baigsis už {count} minutės",
"shared_link_expires_minutes": "Galiojimas baigsis už {count} minučių",
"shared_link_expires_second": "Galiojimas baigsis už {count} sekundės",
"shared_link_expires_seconds": "Galiojimas baigsis už {count} sekundžių",
"shared_link_options": "Bendrinimo nuorodos parametrai", "shared_link_options": "Bendrinimo nuorodos parametrai",
"shared_links": "Bendrinimo nuorodos", "shared_links": "Bendrinimo nuorodos",
"shared_photos_and_videos_count": "{assetCount, plural, one {# bendrinama nuotrauka ir vaizdo įrašas} few {# bendrinamos nuotraukos ir vaizdo įrašai} other {# bendrinamų nuotraukų ir vaizdo įrašų}}", "shared_photos_and_videos_count": "{assetCount, plural, one {# bendrinama nuotrauka ir vaizdo įrašas} few {# bendrinamos nuotraukos ir vaizdo įrašai} other {# bendrinamų nuotraukų ir vaizdo įrašų}}",
@@ -1092,6 +1571,7 @@
"template": "Šablonas", "template": "Šablonas",
"theme": "Tema", "theme": "Tema",
"theme_selection": "Temos pasirinkimas", "theme_selection": "Temos pasirinkimas",
"theme_setting_asset_list_tiles_per_row_title": "Elementų per eilutę ({count})",
"theme_setting_primary_color_title": "Pagrindinė spalva", "theme_setting_primary_color_title": "Pagrindinė spalva",
"theme_setting_system_primary_color_title": "Naudoti sistemos spalvą", "theme_setting_system_primary_color_title": "Naudoti sistemos spalvą",
"theme_setting_system_theme_switch": "Automatinė (Naudoti sistemos nustatymus)", "theme_setting_system_theme_switch": "Automatinė (Naudoti sistemos nustatymus)",
@@ -1110,8 +1590,10 @@
"trash_no_results_message": "Į šiukšliadėžę perkeltos nuotraukos ir vaizdo įrašai bus rodomi čia.", "trash_no_results_message": "Į šiukšliadėžę perkeltos nuotraukos ir vaizdo įrašai bus rodomi čia.",
"trash_page_delete_all": "Ištrinti Visus", "trash_page_delete_all": "Ištrinti Visus",
"trash_page_empty_trash_dialog_content": "Ar norite ištrinti išmestus elementus? Šie elementai bus visam laikui pašalinti iš Immich", "trash_page_empty_trash_dialog_content": "Ar norite ištrinti išmestus elementus? Šie elementai bus visam laikui pašalinti iš Immich",
"trash_page_info": "Šiukšliadėžės elementai bus galutinai ištrinti už {days} dienų",
"trash_page_no_assets": "Nėra išmestų elementų", "trash_page_no_assets": "Nėra išmestų elementų",
"trash_page_restore_all": "Atkurti Visus", "trash_page_restore_all": "Atkurti Visus",
"trash_page_title": "Šiukšlių ({count})",
"trashed_items_will_be_permanently_deleted_after": "Į šiukšliadėžę perkelti elementai bus visam laikui ištrinti po {days, plural, one {# dienos} other {# dienų}}.", "trashed_items_will_be_permanently_deleted_after": "Į šiukšliadėžę perkelti elementai bus visam laikui ištrinti po {days, plural, one {# dienos} other {# dienų}}.",
"type": "Tipas", "type": "Tipas",
"unarchive": "Išarchyvuoti", "unarchive": "Išarchyvuoti",
@@ -1146,7 +1628,8 @@
"upload_success": "Įkėlimas pavyko, norėdami pamatyti naujai įkeltus elementus perkraukite puslapį.", "upload_success": "Įkėlimas pavyko, norėdami pamatyti naujai įkeltus elementus perkraukite puslapį.",
"upload_to_immich": "Įkelti į Immich ({count})", "upload_to_immich": "Įkelti į Immich ({count})",
"uploading": "Įkeliama", "uploading": "Įkeliama",
"usage": "Naudojymas", "url": "URL",
"usage": "Naudojimas",
"use_biometric": "Naudoti biometriją", "use_biometric": "Naudoti biometriją",
"use_current_connection": "naudoti dabartinį ryšį", "use_current_connection": "naudoti dabartinį ryšį",
"user": "Naudotojas", "user": "Naudotojas",

View File

@@ -23,7 +23,7 @@
"add_partner": "Pievienot partneri", "add_partner": "Pievienot partneri",
"add_path": "Pievienot ceļu", "add_path": "Pievienot ceļu",
"add_photos": "Pievienot fotoattēlus", "add_photos": "Pievienot fotoattēlus",
"add_tag": "Pievienot Atzīmi", "add_tag": "Pievienot atzīmi",
"add_to": "Pievienot…", "add_to": "Pievienot…",
"add_to_album": "Pievienot albumam", "add_to_album": "Pievienot albumam",
"add_to_album_bottom_sheet_added": "Pievienots {album}", "add_to_album_bottom_sheet_added": "Pievienots {album}",
@@ -45,13 +45,14 @@
"authentication_settings_disable_all": "Vai tiešām vēlaties atspējot visas pieteikšanās metodes? Pieteikšanās tiks pilnībā atspējota.", "authentication_settings_disable_all": "Vai tiešām vēlaties atspējot visas pieteikšanās metodes? Pieteikšanās tiks pilnībā atspējota.",
"authentication_settings_reenable": "Lai atkārtoti iespējotu, izmantojiet <link>Servera Komandu</link>.", "authentication_settings_reenable": "Lai atkārtoti iespējotu, izmantojiet <link>Servera Komandu</link>.",
"background_task_job": "Fona Uzdevumi", "background_task_job": "Fona Uzdevumi",
"backup_database": "Izveidot datu bāzes izgāztuvi", "backup_database": "Izveidot datu bāzes izrakstu",
"backup_database_enable_description": "Iespējot datu bāzes izgāztuvi", "backup_database_enable_description": "Iespējot datu bāzes izrakstus",
"backup_keep_last_amount": "Iepriekšējo izgāztuvju daudzums, kas jāsaglabā", "backup_keep_last_amount": "Iepriekšējo izrakstu daudzums, kas jāsaglabā",
"backup_onboarding_1_description": "ārpussaites kopēšana mākonī vai citā fiziskā vietā.", "backup_onboarding_1_description": "ārēja kopija mākonī vai citā fiziskā atrašanās vietā.",
"backup_onboarding_2_description": "lokālas kopijas citās ierīcēs. Šis iekļauj galvenos failus kā arī dublētu kōpiju ar tiem failiem lokāli.", "backup_onboarding_2_description": "vietējās kopijas citās ierīcēs. Tas ietver galvenos failus un šo failu vietējo rezerves kopiju.",
"backup_onboarding_title": "Rezerves kopijas", "backup_onboarding_title": "Rezerves kopijas",
"backup_settings_description": "Datubāzes dublēšanas iestatījumu pārvaldība", "backup_settings": "Datubāzes izrakstu iestatījumi",
"backup_settings_description": "Datubāzes izrakstu iestatījumu pārvaldība",
"cleared_jobs": "Notīrīti uzdevumi priekš: {job}", "cleared_jobs": "Notīrīti uzdevumi priekš: {job}",
"config_set_by_file": "Konfigurāciju pašlaik iestata konfigurācijas fails", "config_set_by_file": "Konfigurāciju pašlaik iestata konfigurācijas fails",
"confirm_delete_library": "Vai tiešām vēlaties dzēst {library} bibliotēku?", "confirm_delete_library": "Vai tiešām vēlaties dzēst {library} bibliotēku?",
@@ -777,6 +778,7 @@
"let_others_respond": "Ļaut citiem atbildēt", "let_others_respond": "Ļaut citiem atbildēt",
"level": "Līmenis", "level": "Līmenis",
"library": "Bibliotēka", "library": "Bibliotēka",
"library_options": "Bibliotēkas opcijas",
"library_page_device_albums": "Albumi ierīcē", "library_page_device_albums": "Albumi ierīcē",
"library_page_new_album": "Jauns albums", "library_page_new_album": "Jauns albums",
"library_page_sort_asset_count": "Failu skaits", "library_page_sort_asset_count": "Failu skaits",
@@ -784,6 +786,8 @@
"library_page_sort_last_modified": "Pēdējās izmaiņas", "library_page_sort_last_modified": "Pēdējās izmaiņas",
"library_page_sort_title": "Albuma virsraksts", "library_page_sort_title": "Albuma virsraksts",
"licenses": "Licences", "licenses": "Licences",
"link_to_oauth": "Piesaistīt OAuth",
"linked_oauth_account": "Piesaistītais OAuth konts",
"list": "Saraksts", "list": "Saraksts",
"loading": "Ielādē", "loading": "Ielādē",
"local_network": "Lokālais tīkls", "local_network": "Lokālais tīkls",
@@ -943,6 +947,8 @@
"open_the_search_filters": "Atvērt meklēšanas filtrus", "open_the_search_filters": "Atvērt meklēšanas filtrus",
"options": "Iestatījumi", "options": "Iestatījumi",
"or": "vai", "or": "vai",
"organize_into_albums": "Sakārtot albumos",
"organize_into_albums_description": "Ievietot esošās fotogrāfijas albumos, izmantojot pašreizējos sinhronizācijas iestatījumus",
"organize_your_library": "Bibliotēkas organizēšana", "organize_your_library": "Bibliotēkas organizēšana",
"original": "oriģināls", "original": "oriģināls",
"other": "Citi", "other": "Citi",
@@ -1297,6 +1303,8 @@
"support": "Atbalsts", "support": "Atbalsts",
"support_and_feedback": "Atbalsts un atsauksmes", "support_and_feedback": "Atbalsts un atsauksmes",
"sync": "Sinhronizēt", "sync": "Sinhronizēt",
"sync_status": "Sinhronizācijas statuss",
"sync_status_subtitle": "Skatīt un pārvaldīt sinhronizācijas sistēmu",
"theme": "Dizains", "theme": "Dizains",
"theme_setting_asset_list_storage_indicator_title": "Rādīt krātuves indikatoru uz aktīvu elementiem", "theme_setting_asset_list_storage_indicator_title": "Rādīt krātuves indikatoru uz aktīvu elementiem",
"theme_setting_asset_list_tiles_per_row_title": "Failu skaits rindā ({count})", "theme_setting_asset_list_tiles_per_row_title": "Failu skaits rindā ({count})",
@@ -1337,6 +1345,7 @@
"trash_page_select_assets_btn": "Atlasīt aktīvus", "trash_page_select_assets_btn": "Atlasīt aktīvus",
"trash_page_title": "Atkritne ({count})", "trash_page_title": "Atkritne ({count})",
"trashed_items_will_be_permanently_deleted_after": "Faili no atkritnes tiks neatgriezeniski dzēsti pēc {days, plural, one {# dienas} other {# dienām}}.", "trashed_items_will_be_permanently_deleted_after": "Faili no atkritnes tiks neatgriezeniski dzēsti pēc {days, plural, one {# dienas} other {# dienām}}.",
"troubleshoot": "Problēmu novēršana",
"type": "Veids", "type": "Veids",
"unable_to_change_pin_code": "Neizdevās nomainīt PIN kodu", "unable_to_change_pin_code": "Neizdevās nomainīt PIN kodu",
"unable_to_setup_pin_code": "Neizdevās uzstādīt PIN kodu", "unable_to_setup_pin_code": "Neizdevās uzstādīt PIN kodu",

View File

@@ -1056,6 +1056,706 @@
"group_no": "गटबद्ध नाही", "group_no": "गटबद्ध नाही",
"group_owner": "मालकानुसार गट करा", "group_owner": "मालकानुसार गट करा",
"group_places_by": "स्थळे गटबद्ध करा: …", "group_places_by": "स्थळे गटबद्ध करा: …",
"notification_permission_dialog_content": "सूचना सक्षम करण्यासाठी सेटिंग्जमध्ये जा आणि अनुमती द्या.",
"notification_permission_list_tile_content": "सूचना सक्षम करण्यासाठी परवानगी द्या.",
"notification_permission_list_tile_enable_button": "सूचना सक्षम करा",
"notification_permission_list_tile_title": "सूचना परवानगी",
"notification_toggle_setting_description": "ईमेल सूचना सक्षम करा",
"notifications": "सूचना",
"notifications_setting_description": "सूचना व्यवस्थापित करा",
"oauth": "OAuth",
"official_immich_resources": "अधिकृत Immich संसाधने",
"offline": "ऑफलाइन",
"offset": "ऑफसेट",
"ok": "ठीक",
"oldest_first": "सर्वात जुने आधी",
"on_this_device": "या डिव्हाइसवर",
"onboarding": "ऑनबोर्डिंग",
"onboarding_locale_description": "तुमची पसंतीची भाषा निवडा. हे नंतर सेटिंग्जमध्ये बदलू शकता.",
"onboarding_privacy_description": "खालील (पर्यायी) वैशिष्ट्ये बाह्य सेवांवर अवलंबून आहेत आणि सेटिंग्जमध्ये कधीही अक्षम करता येतात.",
"onboarding_server_welcome_description": "काही सामान्य सेटिंग्जसह तुमची इन्स्टन्स सेटअप करूया.",
"onboarding_theme_description": "तुमच्या इन्स्टन्ससाठी रंग थीम निवडा. हे नंतर सेटिंग्जमध्ये बदलू शकता.",
"onboarding_user_welcome_description": "चला, सुरुवात करूया!",
"onboarding_welcome_user": "स्वागत आहे, {user}",
"online": "ऑनलाइन",
"only_favorites": "फक्त आवडते",
"open": "उघडा",
"open_in_map_view": "नकाशा दृश्यात उघडा",
"open_in_openstreetmap": "OpenStreetMap मध्ये उघडा",
"open_the_search_filters": "शोध फिल्टर उघडा",
"options": "पर्याय",
"or": "किंवा",
"organize_into_albums": "अल्बममध्ये आयोजित करा",
"organize_into_albums_description": "सध्याच्या समक्रमण सेटिंग्ज वापरून विद्यमान फोटो अल्बममध्ये ठेवा",
"organize_your_library": "तुमची लायब्ररी व्यवस्थित करा",
"original": "मूळ",
"other": "इतर",
"other_devices": "इतर उपकरणे",
"other_entities": "इतर घटक",
"other_variables": "इतर चल",
"owned": "मालकीचे",
"owner": "मालक",
"partner": "भागीदार",
"partner_can_access": "{partner} ला प्रवेश आहे",
"partner_can_access_assets": "संग्रहित व हटविलेले वगळता तुमचे सर्व फोटो आणि व्हिडिओ",
"partner_can_access_location": "ज्या ठिकाणी तुमचे फोटो काढले गेले ते स्थान",
"partner_list_user_photos": "{user} चे फोटो",
"partner_list_view_all": "सर्व पहा",
"partner_page_empty_message": "तुमचे फोटो अजून कोणत्याही भागीदारासोबत शेअर केलेले नाहीत.",
"partner_page_no_more_users": "जोडण्यासाठी आणखी वापरकर्ते नाहीत",
"partner_page_partner_add_failed": "भागीदार जोडण्यात अयशस्वी",
"partner_page_select_partner": "भागीदार निवडा",
"partner_page_shared_to_title": "यांना शेअर केले",
"partner_page_stop_sharing_content": "{partner} आता तुमचे फोटो पाहू शकणार नाही.",
"partner_sharing": "भागीदार शेअरिंग",
"partners": "भागीदार",
"password": "पासवर्ड",
"password_does_not_match": "पासवर्ड जुळत नाही",
"password_required": "पासवर्ड आवश्यक",
"password_reset_success": "पासवर्ड रीसेट यशस्वी",
"past_durations": {
"days": "मागील {days, plural, one {# दिवस} other {# दिवस}}",
"hours": "मागील {hours, plural, one {# तास} other {# तास}}",
"years": "मागील {years, plural, one {# वर्ष} other {# वर्षे}}"
},
"path": "मार्ग",
"pattern": "नमुना",
"pause": "थांबवा",
"pause_memories": "आठवणी थांबवा",
"paused": "थांबवले",
"pending": "प्रलंबित",
"people": "लोक",
"people_edits_count": "संपादित {count, plural, one {# व्यक्ती} other {# लोक}}",
"people_feature_description": "लोकांनुसार गटबद्ध फोटो आणि व्हिडिओ ब्राउझ करा",
"people_sidebar_description": "साइडबारमध्ये “लोक” साठी दुवा दाखवा",
"permanent_deletion_warning": "कायमस्वरूपी विलोपन सूचना",
"permanent_deletion_warning_setting_description": "अ‍ॅसेट्स कायमचे हटवताना सूचना दाखवा",
"permanently_delete": "कायमचे हटवा",
"permanently_delete_assets_count": "{count, plural, one {अ‍ॅसेट} other {अ‍ॅसेट्स}} कायमचे हटवा",
"permanently_delete_assets_prompt": "आपण {count, plural, one {हा अ‍ॅसेट कायमचा हटवू इच्छिता?} other {हे <b></b> अ‍ॅसेट्स कायमचे हटवू इच्छिता?}} यामुळे {count, plural, one {तो त्याच्या} other {ते त्यांच्या}} अल्बम(मधून) देखील काढले जातील.",
"permanently_deleted_asset": "कायमचा हटवलेला अ‍ॅसेट",
"permanently_deleted_assets_count": "कायमचे हटवले {count, plural, one {# अ‍ॅसेट} other {# अ‍ॅसेट्स}}",
"permission": "परवानगी",
"permission_empty": "तुमची परवानगी रिक्त असू नये",
"permission_onboarding_back": "मागे",
"permission_onboarding_continue_anyway": "तरीही पुढे जा",
"permission_onboarding_get_started": "सुरू करा",
"permission_onboarding_go_to_settings": "सेटिंग्जमध्ये जा",
"permission_onboarding_permission_denied": "परवानगी नाकारली. Immich वापरण्यासाठी, सेटिंग्जमध्ये फोटो आणि व्हिडिओ परवानग्या द्या.",
"permission_onboarding_permission_granted": "परवानगी मंजूर! सर्व तयार.",
"permission_onboarding_permission_limited": "परवानगी मर्यादित. Immich ला संपूर्ण गॅलरी संग्रहाचा बॅकअप व व्यवस्थापन करण्यासाठी, सेटिंग्जमध्ये फोटो आणि व्हिडिओ परवानग्या द्या.",
"permission_onboarding_request": "तुमचे फोटो आणि व्हिडिओ पाहण्यासाठी Immich ला परवानगी आवश्यक आहे.",
"person": "व्यक्ती",
"person_age_months": "{months, plural, one {# महिना} other {# महिने}} वय",
"person_age_year_months": "1 वर्ष, {months, plural, one {# महिना} other {# महिने}} वय",
"person_age_years": "{years, plural, other {# वर्षांचे}}",
"person_birthdate": "जन्म {date} रोजी",
"person_hidden": "{name}{hidden, select, true { {hidden}} other {}}",
"photo_shared_all_users": "तुम्ही सर्व वापरकर्त्यांसोबत फोटो शेअर केले आहेत असे दिसते किंवा शेअर करण्यासाठी कोणताही वापरकर्ता नाही.",
"photos": "फोटो",
"photos_and_videos": "फोटो आणि व्हिडिओ",
"photos_count": "{count, plural, one {{count, number} फोटो} other {{count, number} फोटो}}",
"photos_from_previous_years": "मागील वर्षांतील फोटो",
"pick_a_location": "स्थान निवडा",
"pin_code_changed_successfully": "PIN कोड यशस्वीरित्या बदलला",
"pin_code_reset_successfully": "PIN कोड यशस्वीरित्या रीसेट केला",
"pin_code_setup_successfully": "PIN कोड यशस्वीरित्या सेट केला",
"pin_verification": "PIN कोड पडताळणी",
"place": "स्थान",
"places": "स्थाने",
"places_count": "{count, plural, one {{count, number} स्थान} other {{count, number} स्थाने}}",
"play": "प्ले करा",
"play_memories": "आठवणी प्ले करा",
"play_motion_photo": "मोशन फोटो प्ले करा",
"play_or_pause_video": "व्हिडिओ प्ले किंवा पॉज करा",
"please_auth_to_access": "प्रवेशासाठी कृपया प्रमाणीकरण करा",
"port": "पोर्ट",
"preferences_settings_subtitle": "अ‍ॅपची प्राधान्ये व्यवस्थापित करा",
"preferences_settings_title": "प्राधान्ये",
"preset": "प्रिसेट",
"preview": "पूर्वावलोकन",
"previous": "मागील",
"previous_memory": "मागील आठवण",
"previous_or_next_day": "दिवस पुढे/मागे",
"previous_or_next_month": "महिना पुढे/मागे",
"previous_or_next_photo": "फोटो पुढे/मागे",
"previous_or_next_year": "वर्ष पुढे/मागे",
"primary": "प्राथमिक",
"privacy": "गोपनीयता",
"profile": "प्रोफाइल",
"profile_drawer_app_logs": "लॉग्स",
"profile_drawer_client_out_of_date_major": "मोबाइल अ‍ॅप कालबाह्य आहे. कृपया नवीनतम मेजर आवृत्तीवर अद्यतन करा.",
"profile_drawer_client_out_of_date_minor": "मोबाइल अ‍ॅप कालबाह्य आहे. कृपया नवीनतम माइनर आवृत्तीवर अद्यतन करा.",
"profile_drawer_client_server_up_to_date": "क्लायंट आणि सर्व्हर अद्ययावत आहेत",
"profile_drawer_github": "गिटहब",
"profile_drawer_readonly_mode": "फक्त-वाचन मोड सक्षम. बाहेर पडण्यासाठी वापरकर्त्याच्या अवतार आयकॉनवर लांब-प्रेस करा.",
"profile_drawer_server_out_of_date_major": "सर्व्हर कालबाह्य आहे. कृपया नवीनतम मेजर आवृत्तीवर अद्यतन करा.",
"profile_drawer_server_out_of_date_minor": "सर्व्हर कालबाह्य आहे. कृपया नवीनतम माइनर आवृत्तीवर अद्यतन करा.",
"profile_image_of_user": "{user} ची प्रोफाइल प्रतिमा",
"profile_picture_set": "प्रोफाइल चित्र सेट केले.",
"public_album": "सार्वजनिक अल्बम",
"public_share": "सार्वजनिक शेअर",
"purchase_account_info": "समर्थक",
"purchase_activated_subtitle": "Immich आणि मुक्त-स्रोत सॉफ्टवेअरला पाठिंबा दिल्याबद्दल धन्यवाद",
"purchase_activated_time": "{date} रोजी सक्रिय केले",
"purchase_activated_title": "तुमची की यशस्वीपणे सक्रिय करण्यात आली आहे",
"purchase_button_activate": "सक्रिय करा",
"purchase_button_buy": "खरेदी करा",
"purchase_button_buy_immich": "Immich खरेदी करा",
"purchase_button_never_show_again": "पुन्हा दाखवू नका",
"purchase_button_reminder": "३० दिवसांनी मला आठवण करून द्या",
"purchase_button_remove_key": "की हटवा",
"purchase_button_select": "निवडा",
"purchase_failed_activation": "सक्रिय करण्यात अयशस्वी! योग्य प्रोडक्ट कीसाठी कृपया तुमचे ईमेल तपासा!",
"purchase_individual_description_1": "वैयक्तिक वापरासाठी",
"purchase_individual_description_2": "समर्थक स्थिती",
"purchase_individual_title": "वैयक्तिक",
"purchase_input_suggestion": "प्रॉडक्ट की आहे? खाली की टाका",
"purchase_license_subtitle": "सेवेच्या पुढील विकासासाठी Immich खरेदी करून साथ द्या",
"purchase_lifetime_description": "आयुष्यभराची खरेदी",
"purchase_option_title": "खरेदी पर्याय",
"purchase_panel_info_1": "Immich तयार करणे वेळखाऊ आणि कष्टाचे आहे. आमचे ध्येय मुक्त-स्रोत सॉफ्टवेअर व नैतिक व्यावसायिक पद्धतींमधून टिकाऊ उत्पन्न मिळवणे, विकसकांना आधार देणे आणि शोषणकारी क्लाउड सेवांना पर्याय देणारे गोपनीयतेचा मान राखणारे इकोसिस्टम तयार करणे हे आहे.",
"purchase_panel_info_2": "आम्ही पेवॉल न वाढवण्यास कटिबद्ध आहोत; त्यामुळे या खरेदीमुळे Immich मध्ये कोणतीही अतिरिक्त वैशिष्ट्ये उघडणार नाहीत. चालू विकासासाठी आम्ही तुमच्यासारख्या वापरकर्त्यांच्या पाठबळावर अवलंबून आहोत.",
"purchase_panel_title": "प्रकल्पाला साथ द्या",
"purchase_per_server": "प्रति सर्व्हर",
"purchase_per_user": "प्रति वापरकर्ता",
"purchase_remove_product_key": "प्रॉडक्ट की काढा",
"purchase_remove_product_key_prompt": "तुम्हाला नक्की प्रॉडक्ट की काढायची आहे का?",
"purchase_remove_server_product_key": "सर्व्हरची प्रॉडक्ट की काढा",
"purchase_remove_server_product_key_prompt": "तुम्हाला नक्की सर्व्हरची प्रॉडक्ट की काढायची आहे का?",
"purchase_server_description_1": "संपूर्ण सर्व्हरसाठी",
"purchase_server_description_2": "समर्थक स्थिती",
"purchase_server_title": "सर्व्हर",
"purchase_settings_server_activated": "सर्व्हरची प्रॉडक्ट की प्रशासकाद्वारे व्यवस्थापित केली जाते",
"query_asset_id": "अॅसेट ID चौकशी",
"queue_status": "रांगेत {count}/{total}",
"rating": "स्टार रेटिंग",
"rating_clear": "रेटिंग साफ करा",
"rating_count": "{count, plural, one {# तारा} other {# तारे}}",
"rating_description": "माहिती पॅनेलमध्ये EXIF रेटिंग दर्शवा",
"reaction_options": "रिऍक्शन पर्याय",
"read_changelog": "चेंजलॉग वाचा",
"readonly_mode_disabled": "फक्त-वाचन मोड निष्क्रिय केला",
"readonly_mode_enabled": "फक्त-वाचन मोड सक्षम केला",
"reassign": "पुन्हा नियुक्त करा",
"reassigned_assets_to_existing_person": "{count, plural, one {# आयटम} other {# आयटम}} {name, select, null {विद्यमान व्यक्तीकडे} other {{name} कडे}} पुन्हा नियुक्त केले",
"reassigned_assets_to_new_person": "{count, plural, one {# आयटम} other {# आयटम}} नव्या व्यक्तीकडे पुन्हा नियुक्त केले",
"reassing_hint": "निवडलेले आयटम विद्यमान व्यक्तीकडे नियुक्त करा",
"recent": "अलीकडील",
"recent-albums": "अलीकडील अल्बम",
"recent_searches": "अलीकडील शोध",
"recently_added": "नुकतेच जोडलेले",
"recently_added_page_title": "नुकतेच जोडलेले",
"recently_taken": "अलीकडे घेतलेले",
"recently_taken_page_title": "अलीकडे घेतलेले",
"refresh": "रीफ्रेश करा",
"refresh_encoded_videos": "एन्कोड केलेले व्हिडिओ रीफ्रेश करा",
"refresh_faces": "चेहरे रीफ्रेश करा",
"refresh_metadata": "मेटाडेटा रीफ्रेश करा",
"refresh_thumbnails": "थंबनेल रीफ्रेश करा",
"refreshed": "रीफ्रेश झाले",
"refreshes_every_file": "विद्यमान व नवीन सर्व फाइल्स पुन्हा वाचा",
"refreshing_encoded_video": "एन्कोड केलेला व्हिडिओ रीफ्रेश करत आहे",
"refreshing_faces": "चेहरे रीफ्रेश करत आहे",
"refreshing_metadata": "मेटाडेटा रीफ्रेश करत आहे",
"regenerating_thumbnails": "थंबनेल्स पुन्हा तयार करत आहे",
"remote": "दूरस्थ",
"remote_assets": "दूरस्थ आयटम",
"remove": "काढा",
"remove_assets_album_confirmation": "अल्बममधून {count, plural, one {# आयटम} other {# आयटम}} काढायचे आहेत का?",
"remove_assets_shared_link_confirmation": "या शेअर्ड दुव्यातून {count, plural, one {# आयटम} other {# आयटम}} काढायचे आहेत का?",
"remove_assets_title": "आयटम काढायचे?",
"remove_custom_date_range": "सानुकूल दिनांक श्रेणी काढा",
"remove_deleted_assets": "हटवलेले आयटम काढा",
"remove_from_album": "अल्बममधून काढा",
"remove_from_album_action_prompt": "अल्बममधून {count} काढले",
"remove_from_favorites": "आवडीतून काढा",
"remove_from_lock_folder_action_prompt": "लॉक केलेल्या फोल्डरमधून {count} काढले",
"remove_from_locked_folder": "लॉक फोल्डरमधून काढा",
"remove_from_locked_folder_confirmation": "हे फोटो आणि व्हिडिओ लॉक फोल्डरमधून बाहेर हलवायचे आहेत का? ते तुमच्या लायब्ररीमध्ये दिसतील.",
"remove_from_shared_link": "शेअर्ड दुव्यातून काढा",
"remove_memory": "मेमरी काढा",
"remove_photo_from_memory": "या मेमरीतून फोटो काढा",
"remove_tag": "टॅग काढा",
"remove_url": "URL काढा",
"remove_user": "वापरकर्ता काढा",
"removed_api_key": "काढलेली API की: {name}",
"removed_from_archive": "आर्काइव्हमधून काढले",
"removed_from_favorites": "आवडीतून काढले",
"removed_from_favorites_count": "{count, plural, other {आवडीतून # काढले}}",
"removed_memory": "मेमरी काढली",
"removed_photo_from_memory": "मेमरीतून फोटो काढला",
"removed_tagged_assets": "{count, plural, one {# आयटमवरून टॅग काढला} other {# आयटमवरून टॅग काढले}}",
"rename": "नाव बदला",
"repair": "दुरुस्ती",
"repair_no_results_message": "अनट्रॅक्ड व हरवलेल्या फाइल्स येथे दिसतील",
"replace_with_upload": "अपलोडने बदला",
"repository": "रिपॉझिटरी",
"require_password": "पासवर्ड आवश्यक",
"require_user_to_change_password_on_first_login": "पहिल्या लॉगिनवेळी वापरकर्त्याने पासवर्ड बदलणे आवश्यक",
"rescan": "पुन्हा स्कॅन करा",
"reset": "रीसेट करा",
"reset_password": "पासवर्ड रीसेट करा",
"reset_people_visibility": "लोकांची दृश्यता रीसेट करा",
"reset_pin_code": "PIN कोड रीसेट करा",
"reset_pin_code_description": "तुमचा PIN विसरला असल्यास, तो रीसेट करण्यासाठी सर्व्हर प्रशासकाशी संपर्क साधा",
"reset_pin_code_success": "PIN कोड यशस्वीरीत्या रीसेट केला",
"reset_pin_code_with_password": "पासवर्डने तुम्ही नेहमी PIN कोड रीसेट करू शकता",
"reset_sqlite": "SQLite डेटाबेस रीसेट करा",
"reset_sqlite_confirmation": "तुम्हाला नक्की SQLite डेटाबेस रीसेट करायचा आहे का? डेटा पुन्हा समक्रमित करण्यासाठी तुम्हाला लॉगआउट करून पुन्हा लॉगइन करावे लागेल",
"reset_sqlite_success": "SQLite डेटाबेस यशस्वीरीत्या रीसेट केला",
"reset_to_default": "डीफॉल्टवर रीसेट करा",
"resolve_duplicates": "डुप्लिकेट्स सोडवा",
"resolved_all_duplicates": "सर्व डुप्लिकेट्स सोडवले",
"restore": "पुनर्संचयित करा",
"restore_all": "सर्व पुनर्संचयित करा",
"restore_trash_action_prompt": "कचरापेटीतून {count} पुनर्संचयित केले",
"restore_user": "वापरकर्ता पुनर्संचयित करा",
"restored_asset": "पुनर्संचयित आयटम",
"resume": "पुन्हा सुरू करा",
"resume_paused_jobs": "{count, plural, one {# थांबवलेले काम} other {# थांबवलेली कामे}} पुन्हा सुरू करा",
"retry_upload": "अपलोड पुन्हा करा",
"review_duplicates": "डुप्लिकेट्सचे पुनरावलोकन करा",
"review_large_files": "मोठ्या फाइल्सचे पुनरावलोकन करा",
"role": "भूमिका",
"role_editor": "संपादक",
"role_viewer": "दर्शक",
"running": "चालू",
"save": "जतन करा",
"save_to_gallery": "गॅलरीमध्ये जतन करा",
"saved_api_key": "जतन केलेली API की",
"saved_profile": "जतन केलेले प्रोफाइल",
"saved_settings": "जतन केलेल्या सेटिंग्ज",
"say_something": "काहीतरी बोला",
"scaffold_body_error_occurred": "त्रुटी आली",
"scan_all_libraries": "सर्व लायब्ररी स्कॅन करा",
"scan_library": "स्कॅन करा",
"scan_settings": "स्कॅन सेटिंग्ज",
"scanning_for_album": "अल्बमसाठी स्कॅन करत आहे...",
"search": "शोधा",
"search_albums": "अल्बम शोधा",
"search_by_context": "परिस्थितीनुसार शोधा",
"search_by_description": "वर्णनानुसार शोधा",
"search_by_description_example": "सापा मधील हायकिंगचा दिवस",
"search_by_filename": "फाइल नाव/एक्स्टेंशननुसार शोधा",
"search_by_filename_example": "उदा. IMG_1234.JPG किंवा PNG",
"search_camera_make": "कॅमेरा निर्माता शोधा...",
"search_camera_model": "कॅमेरा मॉडेल शोधा...",
"search_city": "शहर शोधा...",
"search_country": "देश शोधा...",
"search_filter_apply": "फिल्टर लागू करा",
"search_filter_camera_title": "कॅमेरा प्रकार निवडा",
"search_filter_date": "तारीख",
"search_filter_date_interval": "{start} ते {end}",
"search_filter_date_title": "दिनांक श्रेणी निवडा",
"search_filter_display_option_not_in_album": "अल्बममध्ये नाही",
"search_filter_display_options": "प्रदर्शन पर्याय",
"search_filter_filename": "फाइल नावाने शोधा",
"search_filter_location": "स्थान",
"search_filter_location_title": "स्थान निवडा",
"search_filter_media_type": "माध्यम प्रकार",
"search_filter_media_type_title": "माध्यम प्रकार निवडा",
"search_filter_people_title": "लोक निवडा",
"search_for": "यासाठी शोधा",
"search_for_existing_person": "विद्यमान व्यक्ती शोधा",
"search_no_more_result": "आणखी परिणाम नाहीत",
"search_no_people": "कोणतीही व्यक्ती नाही",
"search_no_people_named": "“{name}” नावाची व्यक्ती सापडली नाही",
"search_no_result": "काहीही सापडले नाही; वेगळा शोध शब्द किंवा संयोजन वापरा",
"search_options": "शोध पर्याय",
"search_page_categories": "श्रेण्या",
"search_page_motion_photos": "मोशन फोटो",
"search_page_no_objects": "वस्तूंची माहिती उपलब्ध नाही",
"search_page_no_places": "ठिकाणांची माहिती उपलब्ध नाही",
"search_page_screenshots": "स्क्रीनशॉट्स",
"search_page_search_photos_videos": "तुमचे फोटो व व्हिडिओ शोधा",
"search_page_selfies": "सेल्फीज",
"search_page_things": "वस्तू",
"search_page_view_all_button": "सर्व पहा",
"search_page_your_activity": "तुमचे क्रियाकलाप",
"search_page_your_map": "तुमचा नकाशा",
"search_people": "लोक शोधा",
"search_places": "ठिकाणे शोधा",
"search_rating": "रेटिंगनुसार शोधा...",
"search_result_page_new_search_hint": "नवीन शोध",
"search_settings": "शोध सेटिंग्ज",
"search_state": "राज्य/स्टेट शोधा...",
"search_suggestion_list_smart_search_hint_1": "डीफॉल्टने स्मार्ट सर्च सुरू आहे; मेटाडेटा शोधण्यासाठी ही रचना वापरा. ",
"search_suggestion_list_smart_search_hint_2": "m:तुमचा-शोध-शब्द",
"search_tags": "टॅग्स शोधा...",
"search_timezone": "वेळक्षेत्र शोधा...",
"search_type": "शोध प्रकार",
"search_your_photos": "तुमचे फोटो शोधा",
"searching_locales": "लोकल्स शोधत आहे...",
"second": "सेकंद",
"see_all_people": "सर्व लोक पाहा",
"select": "निवडा",
"select_album_cover": "अल्बम कव्हर निवडा",
"select_all": "सर्व निवडा",
"select_all_duplicates": "सर्व डुप्लिकेट्स निवडा",
"select_all_in": "{group} मधील सर्व निवडा",
"select_avatar_color": "अवतारचा रंग निवडा",
"select_face": "चेहरा निवडा",
"select_featured_photo": "फिचर्ड फोटो निवडा",
"select_from_computer": "कॉम्प्युटरमधून निवडा",
"select_keep_all": "सर्व ठेवणे निवडा",
"select_library_owner": "लायब्ररी मालक निवडा",
"select_new_face": "नवा चेहरा निवडा",
"select_person_to_tag": "टॅग करण्यासाठी व्यक्ती निवडा",
"select_photos": "फोटो निवडा",
"select_trash_all": "कचरापेटीतील सर्व निवडा",
"select_user_for_sharing_page_err_album": "अल्बम तयार करण्यात अयशस्वी",
"selected": "निवडलेले",
"selected_count": "{count, plural, other {# निवडले}}",
"selected_gps_coordinates": "निवडलेल्या GPS स्थाननिर्देशांक",
"send_message": "संदेश पाठवा",
"send_welcome_email": "स्वागत ईमेल पाठवा",
"server_endpoint": "सर्व्हर एंडपॉइंट",
"server_info_box_app_version": "अॅप आवृत्ती",
"server_info_box_server_url": "सर्व्हर URL",
"server_offline": "सर्व्हर ऑफलाइन",
"server_online": "सर्व्हर ऑनलाइन",
"server_privacy": "सर्व्हर गोपनीयता",
"server_stats": "सर्व्हर आकडेवारी",
"server_version": "सर्व्हर आवृत्ती",
"set": "सेट करा",
"set_as_album_cover": "अल्बम कव्हर म्हणून सेट करा",
"set_as_featured_photo": "फिचर्ड फोटो म्हणून सेट करा",
"set_as_profile_picture": "प्रोफाइल फोटो म्हणून सेट करा",
"set_date_of_birth": "जन्मतारीख सेट करा",
"set_profile_picture": "प्रोफाइल फोटो सेट करा",
"set_slideshow_to_fullscreen": "स्लाइडशो फुलस्क्रीन करा",
"set_stack_primary_asset": "मुख्य आयटम म्हणून सेट करा",
"setting_image_viewer_help": "डीटेल व्ह्यूअर आधी लहान थंबनेल लोड करतो, नंतर (सक्षम असल्यास) मध्यम आकाराचे प्रिव्ह्यू लोड करतो, आणि शेवटी (सक्षम असल्यास) मूळ प्रतिमा लोड करतो.",
"setting_image_viewer_original_subtitle": "पूर्ण-रिझोल्यूशनची मूळ प्रतिमा लोड करण्यासाठी सक्षम करा (मोठी). डेटा वापर कमी करण्यासाठी (नेटवर्क व डिव्हाइस कॅश दोन्ही) अक्षम करा.",
"setting_image_viewer_original_title": "मूळ प्रतिमा लोड करा",
"setting_image_viewer_preview_subtitle": "मध्यम-रिझोल्यूशन प्रतिमा लोड करण्यासाठी सक्षम करा. अक्षम केल्यास थेट मूळ प्रतिमा लोड होईल किंवा फक्त थंबनेल वापरला जाईल.",
"setting_image_viewer_preview_title": "प्रिव्ह्यू प्रतिमा लोड करा",
"setting_image_viewer_title": "प्रतिमा",
"setting_languages_apply": "लागू करा",
"setting_languages_subtitle": "अॅपची भाषा बदला",
"setting_notifications_notify_failures_grace_period": "पार्श्वभूमी बॅकअप अपयशांची सूचना: {duration}",
"setting_notifications_notify_hours": "{count} तास",
"setting_notifications_notify_immediately": "तत्काळ",
"setting_notifications_notify_minutes": "{count} मिनिटे",
"setting_notifications_notify_never": "कधीच नाही",
"setting_notifications_notify_seconds": "{count} सेकंद",
"setting_notifications_single_progress_subtitle": "प्रत्येक आयटमसाठी तपशीलवार अपलोड प्रगती माहिती",
"setting_notifications_single_progress_title": "पार्श्वभूमी बॅकअपची तपशीलवार प्रगती दाखवा",
"setting_notifications_subtitle": "तुमची सूचना प्राधान्ये समायोजित करा",
"setting_notifications_total_progress_subtitle": "एकूण अपलोड प्रगती (पूर्ण/एकूण आयटम)",
"setting_notifications_total_progress_title": "पार्श्वभूमी बॅकअपची एकूण प्रगती दाखवा",
"setting_video_viewer_looping_title": "लूपिंग",
"setting_video_viewer_original_video_subtitle": "सर्व्हरवरून व्हिडिओ स्ट्रिम करताना ट्रान्सकोड उपलब्ध असला तरी मूळ व्हिडिओ प्ले करा. बफरिंग होऊ शकते. स्थानिकरीत्या उपलब्ध व्हिडिओ या सेटिंगपासून स्वतंत्रपणे मूळ गुणवत्तेत प्ले होतात.",
"setting_video_viewer_original_video_title": "मूळ व्हिडिओ सक्तीने प्ले करा",
"settings": "सेटिंग्ज",
"settings_require_restart": "ही सेटिंग लागू करण्यासाठी कृपया Immich रीस्टार्ट करा",
"settings_saved": "सेटिंग्ज जतन केल्या",
"setup_pin_code": "PIN कोड सेट करा",
"share": "शेअर करा",
"share_action_prompt": "{count} आयटम शेअर केले",
"share_add_photos": "फोटो जोडा",
"share_assets_selected": "{count} निवडले",
"share_dialog_preparing": "तयार करत आहे...",
"share_link": "शेअर दुवा",
"shared": "शेअर केले",
"shared_album_activities_input_disable": "टिप्पणी निष्क्रिय आहे",
"shared_album_activity_remove_content": "ही कृती हटवायची आहे का?",
"shared_album_activity_remove_title": "कृती हटवा",
"shared_album_section_people_action_error": "अल्बममधून बाहेर पडताना/काढताना त्रुटी",
"shared_album_section_people_action_leave": "अल्बममधून वापरकर्ता काढा",
"shared_album_section_people_action_remove_user": "अल्बममधून वापरकर्ता काढा",
"shared_album_section_people_title": "लोक",
"shared_by": "यांनी शेअर केले",
"shared_by_user": "{user} यांनी शेअर केले",
"shared_by_you": "तुमच्याकडून शेअर केले",
"shared_from_partner": "{partner} कडील फोटो",
"shared_intent_upload_button_progress_text": "{current}/{total} अपलोड झाले",
"shared_link_app_bar_title": "शेअर्ड दुवे",
"shared_link_clipboard_copied_massage": "क्लिपबोर्डवर कॉपी केले",
"shared_link_clipboard_text": "दुवा: {link}\nपासवर्ड: {password}",
"shared_link_create_error": "शेअर्ड दुवा तयार करताना त्रुटी",
"shared_link_custom_url_description": "सानुकूल URL द्वारे हा शेअर्ड दुवा उघडा",
"shared_link_edit_description_hint": "शेअरचे वर्णन प्रविष्ट करा",
"shared_link_edit_expire_after_option_day": "1 दिवस",
"shared_link_edit_expire_after_option_days": "{count} दिवस",
"shared_link_edit_expire_after_option_hour": "1 तास",
"shared_link_edit_expire_after_option_hours": "{count} तास",
"shared_link_edit_expire_after_option_minute": "1 मिनिट",
"shared_link_edit_expire_after_option_minutes": "{count} मिनिटे",
"shared_link_edit_expire_after_option_months": "{count} महिने",
"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_expires_day": "{count} दिवसात संपेल",
"shared_link_expires_days": "{count} दिवसात संपेल",
"shared_link_expires_hour": "{count} तासात संपेल",
"shared_link_expires_hours": "{count} तासांत संपेल",
"shared_link_expires_minute": "{count} मिनिटात संपेल",
"shared_link_expires_minutes": "{count} मिनिटांत संपेल",
"shared_link_expires_never": "कधीच संपत नाही ∞",
"shared_link_expires_second": "{count} सेकंदात संपेल",
"shared_link_expires_seconds": "{count} सेकंदात संपेल",
"shared_link_individual_shared": "वैयक्तिक शेअर",
"shared_link_info_chip_metadata": "EXIF (एक्सिफ)",
"shared_link_manage_links": "शेअर्ड दुवे व्यवस्थापित करा",
"shared_link_options": "शेअर्ड दुवा पर्याय",
"shared_link_password_description": "हा शेअर्ड दुवा पाहण्यासाठी पासवर्ड आवश्यक आहे",
"shared_links": "शेअर्ड दुवे",
"shared_links_description": "दुव्याद्वारे फोटो आणि व्हिडिओ शेअर करा",
"shared_photos_and_videos_count": "{assetCount, plural, other {# शेअर्ड फोटो आणि व्हिडिओ}}",
"shared_with_me": "माझ्यासोबत शेअर केलेले",
"shared_with_partner": "{partner} सोबत शेअर केले",
"sharing": "शेअरिंग",
"sharing_enter_password": "हे पृष्ठ पाहण्यासाठी कृपया पासवर्ड प्रविष्ट करा.",
"sharing_page_album": "शेअर्ड अल्बम",
"sharing_page_description": "तुमच्या नेटवर्कमधील लोकांसोबत फोटो-व्हिडिओ शेअर करण्यासाठी शेअर्ड अल्बम तयार करा.",
"sharing_page_empty_list": "रिकामी यादी",
"sharing_sidebar_description": "साइडबारमध्ये शेअरिंगचा दुवा दाखवा",
"sharing_silver_appbar_create_shared_album": "नवीन शेअर्ड अल्बम",
"sharing_silver_appbar_share_partner": "भागीदारासोबत शेअर करा",
"shift_to_permanent_delete": "अॅसेट कायमचे हटवण्यासाठी ⇧ दाबा",
"show_album_options": "अल्बम पर्याय दाखवा",
"show_albums": "अल्बम दाखवा",
"show_all_people": "सर्व लोक दाखवा",
"show_and_hide_people": "लोक दाखवा आणि लपवा",
"show_file_location": "फाइलचे स्थान दाखवा",
"show_gallery": "गॅलरी दाखवा",
"show_hidden_people": "लपवलेले लोक दाखवा",
"show_in_timeline": "टाइमलाइनमध्ये दाखवा",
"show_in_timeline_setting_description": "या वापरकर्त्याचे फोटो-व्हिडिओ तुमच्या टाइमलाइनमध्ये दाखवा",
"show_keyboard_shortcuts": "कीबोर्ड शॉर्टकट दाखवा",
"show_metadata": "मेटाडेटा दाखवा",
"show_or_hide_info": "माहिती दाखवा किंवा लपवा",
"show_password": "पासवर्ड दाखवा",
"show_person_options": "व्यक्तीचे पर्याय दाखवा",
"show_progress_bar": "प्रगती पट्टी दाखवा",
"show_search_options": "शोध पर्याय दाखवा",
"show_shared_links": "शेअर केलेले दुवे दाखवा",
"show_slideshow_transition": "स्लाइडशो ट्रांझिशन दाखवा",
"show_supporter_badge": "समर्थक बॅज",
"show_supporter_badge_description": "समर्थक बॅज दाखवा",
"shuffle": "शफल",
"sidebar": "साइडबार",
"sidebar_display_description": "साइडबारमध्ये दृश्याचा दुवा दाखवा",
"sign_out": "साइन आउट",
"sign_up": "साइन अप",
"size": "आकार",
"skip_to_content": "सामग्रीकडे जा",
"skip_to_folders": "फोल्डर्सकडे जा",
"skip_to_tags": "टॅग्सकडे जा",
"slideshow": "स्लाइडशो",
"slideshow_settings": "स्लाइडशो सेटिंग्ज",
"sort_albums_by": "अल्बम यानुसार क्रम लावा…",
"sort_created": "तयार केलेली तारीख",
"sort_items": "आयटमांची संख्या",
"sort_modified": "बदल केलेली तारीख",
"sort_newest": "अलीकडचा फोटो",
"sort_oldest": "सर्वात जुना फोटो",
"sort_people_by_similarity": "साम्यतेनुसार व्यक्तींचा क्रम लावा",
"sort_recent": "नुकताच घेतलेला फोटो",
"sort_title": "शीर्षक",
"source": "स्त्रोत",
"stack": "स्टॅक",
"stack_action_prompt": "{count} स्टॅक केले",
"stack_duplicates": "डुप्लिकेट्स स्टॅक करा",
"stack_select_one_photo": "स्टॅकसाठी एक मुख्य फोटो निवडा",
"stack_selected_photos": "निवडलेले फोटो स्टॅक करा",
"stacked_assets_count": "स्टॅक केलेले {count, plural, one {# आयटम} other {# आयटम}}",
"stacktrace": "स्टॅकट्रेस",
"start": "सुरू करा",
"start_date": "सुरुवातीची तारीख",
"state": "स्थिती",
"status": "स्टेटस",
"stop_casting": "कास्टिंग थांबवा",
"stop_motion_photo": "मोशन फोटो थांबवा",
"stop_photo_sharing": "तुमचे फोटो शेअर करणे थांबवायचे?",
"stop_photo_sharing_description": "{partner} यांना आता तुमचे फोटो पाहता येणार नाहीत.",
"stop_sharing_photos_with_user": "या वापरकर्त्यासोबत तुमचे फोटो शेअर करणे थांबवा",
"storage": "संचयन जागा",
"storage_label": "संचयन लेबल",
"storage_quota": "संचयन कोटा",
"storage_usage": "{available} पैकी {used} वापरले",
"submit": "सादर करा",
"success": "यशस्वी",
"suggestions": "सूचना",
"sunrise_on_the_beach": "समुद्रकिनाऱ्यावर सूर्योदय",
"support": "सहाय्य",
"support_and_feedback": "सहाय्य आणि अभिप्राय",
"support_third_party_description": "तुमची Immich स्थापना तृतीय-पक्ष पॅकेजद्वारे दिली आहे. तुम्हाला येणाऱ्या समस्या त्या पॅकेजमुळे असू शकतात; त्यामुळे खालील दुव्यांचा वापर करून सर्वप्रथम त्यांच्याकडे समस्या नोंदवा.",
"swap_merge_direction": "मर्ज दिशेची अदलाबदल करा",
"sync": "समक्रमण",
"sync_albums": "अल्बम समक्रमित करा",
"sync_albums_manual_subtitle": "अपलोड केलेले सर्व फोटो-व्हिडिओ निवडलेल्या बॅकअप अल्बममध्ये समक्रमित करा",
"sync_local": "स्थानिक समक्रमण",
"sync_remote": "दूरस्थ समक्रमण",
"sync_status": "समक्रमण स्थिती",
"sync_status_subtitle": "समक्रमण प्रणाली पाहा आणि व्यवस्थापित करा",
"sync_upload_album_setting_subtitle": "Immich वरील निवडलेल्या अल्बममध्ये तुमचे फोटो व व्हिडिओ तयार करा आणि अपलोड करा",
"tag": "टॅग",
"tag_assets": "आयटमना टॅग लावा",
"tag_created": "तयार केलेला टॅग: {tag}",
"tag_feature_description": "तार्किक टॅग विषयांनुसार गटबद्ध फोटो व व्हिडिओ ब्राउझ करा",
"tag_not_found_question": "टॅग सापडत नाही? <link>नवा टॅग तयार करा</link>",
"tag_people": "व्यक्तींना टॅग करा",
"tag_updated": "अद्ययावत टॅग: {tag}",
"tagged_assets": "टॅग केलेले {count, plural, one {# आयटम} other {# आयटम}}",
"tags": "टॅग्स",
"tap_to_run_job": "जॉब चालवण्यासाठी टॅप करा",
"template": "टेम्पलेट",
"theme": "थीम",
"theme_selection": "थीम निवड",
"theme_selection_description": "ब्राउझरच्या सिस्टम पसंतीनुसार थीम आपोआप लाइट/डार्क करा",
"theme_setting_asset_list_storage_indicator_title": "अॅसेट टाइल्सवर स्टोरेज निर्देशक दाखवा",
"theme_setting_asset_list_tiles_per_row_title": "प्रत्येक रांगेतील अॅसेट्सची संख्या ({count})",
"theme_setting_colorful_interface_subtitle": "बॅकग्राऊंड पृष्ठभागांवर प्राथमिक रंग लागू करा.",
"theme_setting_colorful_interface_title": "रंगीबेरंगी इंटरफेस",
"theme_setting_image_viewer_quality_subtitle": "डीटेल इमेज व्ह्यूअरची गुणवत्ता समायोजित करा",
"theme_setting_image_viewer_quality_title": "इमेज व्ह्यूअर गुणवत्ता",
"theme_setting_primary_color_subtitle": "प्राथमिक कृती व अॅक्सेंटसाठी रंग निवडा.",
"theme_setting_primary_color_title": "प्राथमिक रंग",
"theme_setting_system_primary_color_title": "सिस्टम रंग वापरा",
"theme_setting_system_theme_switch": "स्वयंचलित (सिस्टम सेटिंग्जनुसार)",
"theme_setting_theme_subtitle": "अॅपची थीम सेटिंग निवडा",
"theme_setting_three_stage_loading_subtitle": "थ्री-स्टेज लोडिंगमुळे गती वाढू शकते; परंतु नेटवर्क लोड लक्षणीय वाढतो",
"theme_setting_three_stage_loading_title": "थ्री-स्टेज लोडिंग सुरू करा",
"they_will_be_merged_together": "ते एकत्र विलीन केले जातील",
"third_party_resources": "तृतीय-पक्ष संसाधने",
"time_based_memories": "वेळ-आधारित मेमरीज",
"timeline": "टाइमलाइन",
"timezone": "वेळक्षेत्र",
"to_archive": "आर्काइव्ह करा",
"to_change_password": "परवलीचा शब्द बदला",
"to_favorite": "आवडीमध्ये जोडा",
"to_login": "लॉग इन करा",
"to_multi_select": "बहु-निवड करा",
"to_parent": "पालकाकडे जा",
"to_select": "निवडा",
"to_trash": "कचरापेटीत टाका",
"toggle_settings": "सेटिंग्ज टॉगल करा",
"total": "एकूण",
"total_usage": "एकूण वापर",
"trash": "कचरापेटी",
"trash_action_prompt": "{count} कचरापेटीत हलवले",
"trash_all": "सर्व कचरापेटीत टाका",
"trash_count": "कचरापेटी {count, number}",
"trash_delete_asset": "कचरापेटीत टाका/अॅसेट हटवा",
"trash_emptied": "कचरापेटी रिकामी केली",
"trash_no_results_message": "कचरापेटीत टाकलेले फोटो व व्हिडिओ येथे दिसतील.",
"trash_page_delete_all": "सर्व हटवा",
"trash_page_empty_trash_dialog_content": "कचरापेटी रिकामी करायची का? हे आयटम Immich मधून कायमचे हटवले जातील",
"trash_page_info": "कचरापेटीतील आयटम {days} दिवसांनंतर कायमचे हटवले जातील",
"trash_page_no_assets": "कचरापेटीत कोणतेही आयटम नाहीत",
"trash_page_restore_all": "सर्व परत आणा",
"trash_page_select_assets_btn": "आयटम निवडा",
"trash_page_title": "कचरापेटी ({count})",
"trashed_items_will_be_permanently_deleted_after": "कचरापेटीतील आयटम {days, plural, one {# दिवसांनंतर} other {# दिवसांनंतर}} कायमचे हटवले जातील.",
"troubleshoot": "समस्या निवारण",
"type": "प्रकार",
"unable_to_change_pin_code": "PIN कोड बदलता येत नाही",
"unable_to_setup_pin_code": "PIN कोड सेट करू शकत नाही",
"unarchive": "अनआर्काइव्ह करा",
"unarchive_action_prompt": "{count} आर्काइव्हमधून काढले",
"unarchived_count": "{count, plural, other {अनआर्काइव्ह #}}",
"undo": "पूर्ववत करा",
"unfavorite": "आवडीतून काढा",
"unfavorite_action_prompt": "{count} आवडीतून काढले",
"unhide_person": "व्यक्ती दर्शवा",
"unknown": "अज्ञात",
"unknown_country": "अज्ञात देश",
"unknown_year": "अज्ञात वर्ष",
"unlimited": "अमर्यादित",
"unlink_motion_video": "मोशन व्हिडिओ अनलिंक करा",
"unlink_oauth": "OAuth अनलिंक करा",
"unlinked_oauth_account": "OAuth खाते अनलिंक केले",
"unmute_memories": "मेमरीज अनम्यूट करा",
"unnamed_album": "नाव नसलेला अल्बम",
"unnamed_album_delete_confirmation": "तुम्हाला हा अल्बम खरंच हटवायचा आहे का?",
"unnamed_share": "नाव नसलेले शेअर",
"unsaved_change": "न साठवलेला बदल",
"unselect_all": "सर्व निवडी रद्द करा",
"unselect_all_duplicates": "सर्व डुप्लिकेट्सची निवड रद्द करा",
"unselect_all_in": "{group} मधील सर्व निवडी रद्द करा",
"unstack": "स्टॅक वेगळा करा",
"unstack_action_prompt": "{count} अनस्टॅक केले",
"unstacked_assets_count": "अनस्टॅक केलेले {count, plural, one {# आयटम} other {# आयटम}}",
"untagged": "टॅग नसलेले",
"up_next": "पुढे",
"update_location_action_prompt": "निवडलेल्या {count} आयटमचे स्थान याने अद्ययावत करा:",
"updated_at": "अद्ययावत केले",
"updated_password": "परवलीचा शब्द अद्ययावत केला",
"upload": "अपलोड",
"upload_action_prompt": "अपलोडसाठी {count} रांगेत",
"upload_concurrency": "अपलोड समांतरता",
"upload_details": "अपलोड तपशील",
"upload_dialog_info": "निवडलेले आयटम सर्व्हरवर बॅकअप करायचे का?",
"upload_dialog_title": "अॅसेट अपलोड करा",
"upload_errors": "अपलोड पूर्ण झाले; {count, plural, one {# त्रुटी} other {# त्रुटी}} आढळल्या. नवीन अपलोड आयटम पाहण्यासाठी पृष्ठ रीफ्रेश करा.",
"upload_finished": "अपलोड पूर्ण",
"upload_progress": "उर्वरित {remaining, number} — प्रक्रिया झालेले {processed, number}/{total, number}",
"upload_skipped_duplicates": "वगळले {count, plural, one {# डुप्लिकेट आयटम} other {# डुप्लिकेट आयटम}}",
"upload_status_duplicates": "डुप्लिकेट",
"upload_status_errors": "त्रुटी",
"upload_status_uploaded": "अपलोड झाले",
"upload_success": "अपलोड यशस्वी. नवीन अपलोड आयटम दिसण्यासाठी पृष्ठ रीफ्रेश करा.",
"upload_to_immich": "Immich वर अपलोड करा ({count})",
"uploading": "अपलोड होत आहे",
"uploading_media": "माध्यमे अपलोड होत आहेत",
"url": "URL",
"usage": "वापर",
"use_biometric": "बायोमेट्रिक वापरा",
"use_current_connection": "सध्याचे कनेक्शन वापरा",
"use_custom_date_range": "याऐवजी सानुकूल दिनांक श्रेणी वापरा",
"user": "वापरकर्ता",
"user_has_been_deleted": "हा वापरकर्ता हटविला गेला आहे.",
"user_id": "वापरकर्ता आयडी",
"user_liked": "{user} यांना {type, select, photo {हा फोटो} video {हा व्हिडिओ} asset {हा आयटम} other {हे}} आवडले",
"user_pin_code_settings": "PIN कोड",
"user_pin_code_settings_description": "तुमचा PIN कोड व्यवस्थापित करा",
"user_privacy": "वापरकर्ता गोपनीयता",
"user_purchase_settings": "खरेदी",
"user_purchase_settings_description": "तुमची खरेदी व्यवस्थापित करा",
"user_role_set": "{user} यांना {role} म्हणून सेट करा",
"user_usage_detail": "वापरकर्त्याच्या वापराचा तपशील",
"user_usage_stats": "खात्याच्या वापराच्या सांख्यिकी",
"user_usage_stats_description": "खात्याच्या वापराच्या सांख्यिकी पहा",
"username": "वापरकर्तानाव",
"users": "वापरकर्ते",
"users_added_to_album_count": "अल्बममध्ये {count, plural, one {# वापरकर्ता जोडला} other {# वापरकर्ते जोडले}}",
"utilities": "उपयुक्तता",
"validate": "तपासा",
"validate_endpoint_error": "कृपया वैध URL प्रविष्ट करा",
"variables": "चल",
"version": "आवृत्ती",
"version_announcement_closing": "तुमचा मित्र, अ‍ॅलेक्स",
"version_announcement_message": "नमस्कार! Immich ची नवी आवृत्ती उपलब्ध आहे. तुमची संरचना अद्ययावत आणि बिनचूक राहावी यासाठी कृपया काही वेळ काढून <link>रिलीज नोट्स</link> वाचा, विशेषतः तुम्ही WatchTower किंवा अद्ययावत प्रक्रिया स्वयंचलितपणे हाताळणारी कोणतीही व्यवस्था वापरत असाल तर.",
"version_history": "आवृत्ती इतिहास",
"version_history_item": "{date} रोजी {version} स्थापित केली",
"video": "व्हिडिओ",
"video_hover_setting": "हावर केल्यावर व्हिडिओ थंबनेल प्ले करा",
"video_hover_setting_description": "आयटमवर माऊस नेल्यावर व्हिडिओ थंबनेल प्ले होईल. पर्याय बंद असला तरी प्ले चिन्हावर हावर केल्यास प्लेबॅक सुरू करता येईल.",
"videos": "व्हिडिओ",
"videos_count": "{count, plural, one {# व्हिडिओ} other {# व्हिडिओ}}",
"view": "पहा",
"view_album": "अल्बम पहा",
"view_all": "सर्व पहा",
"view_all_users": "सर्व वापरकर्ते पहा",
"view_details": "तपशील पहा",
"view_in_timeline": "टाइमलाइनमध्ये पहा",
"view_link": "दुवा पहा",
"view_links": "दुवे पहा",
"view_name": "पहा",
"view_next_asset": "पुढील आयटम पहा",
"view_previous_asset": "मागील आयटम पहा",
"view_qr_code": "QR कोड पहा",
"view_similar_photos": "समान फोटो पहा",
"view_stack": "स्टॅक पहा",
"view_user": "वापरकर्ता पहा",
"viewer_remove_from_stack": "स्टॅकमधून काढा",
"viewer_stack_use_as_main_asset": "मुख्य आयटम म्हणून वापरा",
"viewer_unstack": "स्टॅक वेगळा करा",
"visibility_changed": "दृश्यता {count, plural, one {# व्यक्तीसाठी बदलली} other {# व्यक्तींसाठी बदलली}}",
"waiting": "प्रतीक्षेत", "waiting": "प्रतीक्षेत",
"warning": "चेतावणी", "warning": "चेतावणी",
"week": "आठवडा", "week": "आठवडा",

View File

@@ -1515,7 +1515,7 @@
"profile_drawer_client_out_of_date_minor": "Mobilapp er utdatert. Vennligst oppdater til nyeste versjon.", "profile_drawer_client_out_of_date_minor": "Mobilapp er utdatert. Vennligst oppdater til nyeste versjon.",
"profile_drawer_client_server_up_to_date": "Klient og server er oppdatert", "profile_drawer_client_server_up_to_date": "Klient og server er oppdatert",
"profile_drawer_github": "GitHub", "profile_drawer_github": "GitHub",
"profile_drawer_readonly_mode": "Skrivebeskyttet modus er aktivert. Dobbelttrykk på brukerens avatarikon for å avslutte.", "profile_drawer_readonly_mode": "Skrivebeskyttet modus er aktivert. Langttrykk på brukerens avatarikon for å avslutte.",
"profile_drawer_server_out_of_date_major": "Server er utdatert. Vennligst oppdater til nyeste versjon.", "profile_drawer_server_out_of_date_major": "Server er utdatert. Vennligst oppdater til nyeste versjon.",
"profile_drawer_server_out_of_date_minor": "Server er utdatert. Vennligst oppdater til nyeste versjon.", "profile_drawer_server_out_of_date_minor": "Server er utdatert. Vennligst oppdater til nyeste versjon.",
"profile_image_of_user": "Profil bilde av {user}", "profile_image_of_user": "Profil bilde av {user}",
@@ -1917,6 +1917,8 @@
"sync_albums_manual_subtitle": "Synkroniser alle opplastede videoer og bilder til det valgte backupalbumet", "sync_albums_manual_subtitle": "Synkroniser alle opplastede videoer og bilder til det valgte backupalbumet",
"sync_local": "Synkroniser lokalt", "sync_local": "Synkroniser lokalt",
"sync_remote": "Synkroniser eksternt", "sync_remote": "Synkroniser eksternt",
"sync_status": "Synkroniseringsstatus",
"sync_status_subtitle": "Vis og håndter synkronisering",
"sync_upload_album_setting_subtitle": "Opprett og last opp dine bilder og videoer til det valgte albumet på Immich", "sync_upload_album_setting_subtitle": "Opprett og last opp dine bilder og videoer til det valgte albumet på Immich",
"tag": "Tagg", "tag": "Tagg",
"tag_assets": "Merk ressurser", "tag_assets": "Merk ressurser",
@@ -1976,6 +1978,7 @@
"trash_page_select_assets_btn": "Velg objekter", "trash_page_select_assets_btn": "Velg objekter",
"trash_page_title": "Søppelbøtte ({count})", "trash_page_title": "Søppelbøtte ({count})",
"trashed_items_will_be_permanently_deleted_after": "Elementer i papirkurven vil bli permanent slettet etter {days, plural, one {# dag} other {# dager}}.", "trashed_items_will_be_permanently_deleted_after": "Elementer i papirkurven vil bli permanent slettet etter {days, plural, one {# dag} other {# dager}}.",
"troubleshoot": "Feilsøk",
"type": "Type", "type": "Type",
"unable_to_change_pin_code": "Klarte ikke å endre PIN-kode", "unable_to_change_pin_code": "Klarte ikke å endre PIN-kode",
"unable_to_setup_pin_code": "Klarte ikke å sette opp PINkode", "unable_to_setup_pin_code": "Klarte ikke å sette opp PINkode",

View File

@@ -708,7 +708,7 @@
"control_bottom_app_bar_edit_time": "Datum & tijd bewerken", "control_bottom_app_bar_edit_time": "Datum & tijd bewerken",
"control_bottom_app_bar_share_link": "Link delen", "control_bottom_app_bar_share_link": "Link delen",
"control_bottom_app_bar_share_to": "Delen met", "control_bottom_app_bar_share_to": "Delen met",
"control_bottom_app_bar_trash_from_immich": "Verwijderen uit Immich", "control_bottom_app_bar_trash_from_immich": "Verwijderen van Immich",
"copied_image_to_clipboard": "Afbeelding gekopieerd naar klembord.", "copied_image_to_clipboard": "Afbeelding gekopieerd naar klembord.",
"copied_to_clipboard": "Gekopieerd naar klembord!", "copied_to_clipboard": "Gekopieerd naar klembord!",
"copy_error": "Fout bij kopiëren", "copy_error": "Fout bij kopiëren",
@@ -1515,7 +1515,7 @@
"profile_drawer_client_out_of_date_minor": "Mobiele app is verouderd. Werk bij naar de nieuwste subversie.", "profile_drawer_client_out_of_date_minor": "Mobiele app is verouderd. Werk bij naar de nieuwste subversie.",
"profile_drawer_client_server_up_to_date": "App en server zijn up-to-date", "profile_drawer_client_server_up_to_date": "App en server zijn up-to-date",
"profile_drawer_github": "GitHub", "profile_drawer_github": "GitHub",
"profile_drawer_readonly_mode": "Alleen-lezen-modus ingeschakeld. Dubbeltik op het avatarpictogram van de gebruiker om te verlaten.", "profile_drawer_readonly_mode": "Alleen-lezen-modus ingeschakeld. Druk lang op je profielfoto om te verlaten.",
"profile_drawer_server_out_of_date_major": "Server is verouderd. Werk bij naar de nieuwste hoofdversie.", "profile_drawer_server_out_of_date_major": "Server is verouderd. Werk bij naar de nieuwste hoofdversie.",
"profile_drawer_server_out_of_date_minor": "Server is verouderd. Werk bij naar de nieuwste subversie.", "profile_drawer_server_out_of_date_minor": "Server is verouderd. Werk bij naar de nieuwste subversie.",
"profile_image_of_user": "Profielfoto van {user}", "profile_image_of_user": "Profielfoto van {user}",
@@ -1640,6 +1640,7 @@
"restore_user": "Gebruiker herstellen", "restore_user": "Gebruiker herstellen",
"restored_asset": "Item hersteld", "restored_asset": "Item hersteld",
"resume": "Hervatten", "resume": "Hervatten",
"resume_paused_jobs": "Hervat {count, plural, one {# gepauseerde taak} other {# gepauseerde taken}}",
"retry_upload": "Opnieuw uploaden", "retry_upload": "Opnieuw uploaden",
"review_duplicates": "Controleer duplicaten", "review_duplicates": "Controleer duplicaten",
"review_large_files": "Grote bestanden beoordelen", "review_large_files": "Grote bestanden beoordelen",
@@ -1916,6 +1917,8 @@
"sync_albums_manual_subtitle": "Synchroniseer alle geüploade videos en fotos naar de geselecteerde back-up albums", "sync_albums_manual_subtitle": "Synchroniseer alle geüploade videos en fotos naar de geselecteerde back-up albums",
"sync_local": "Lokaal synchroniseren", "sync_local": "Lokaal synchroniseren",
"sync_remote": "Op afstand synchroniseren", "sync_remote": "Op afstand synchroniseren",
"sync_status": "Sync Status",
"sync_status_subtitle": "Bekijk en beheer het synchronisatie systeem",
"sync_upload_album_setting_subtitle": "Maak en upload je foto's en video's naar de geselecteerde albums op Immich", "sync_upload_album_setting_subtitle": "Maak en upload je foto's en video's naar de geselecteerde albums op Immich",
"tag": "Tag", "tag": "Tag",
"tag_assets": "Items taggen", "tag_assets": "Items taggen",
@@ -1975,6 +1978,7 @@
"trash_page_select_assets_btn": "Selecteer items", "trash_page_select_assets_btn": "Selecteer items",
"trash_page_title": "Prullenbak ({count})", "trash_page_title": "Prullenbak ({count})",
"trashed_items_will_be_permanently_deleted_after": "Items in de prullenbak worden na {days, plural, one {# dag} other {# dagen}} permanent verwijderd.", "trashed_items_will_be_permanently_deleted_after": "Items in de prullenbak worden na {days, plural, one {# dag} other {# dagen}} permanent verwijderd.",
"troubleshoot": "Problemen oplossen",
"type": "Type", "type": "Type",
"unable_to_change_pin_code": "PIN code kan niet gewijzigd worden", "unable_to_change_pin_code": "PIN code kan niet gewijzigd worden",
"unable_to_setup_pin_code": "PIN code kan niet ingesteld worden", "unable_to_setup_pin_code": "PIN code kan niet ingesteld worden",

View File

@@ -443,7 +443,7 @@
"albums_default_sort_order": "Domyślna kolejność sortowania w albumach", "albums_default_sort_order": "Domyślna kolejność sortowania w albumach",
"albums_default_sort_order_description": "Początkowa kolejność sortowania zasobów przy tworzeniu nowych albumów.", "albums_default_sort_order_description": "Początkowa kolejność sortowania zasobów przy tworzeniu nowych albumów.",
"albums_feature_description": "Kolekcje zasobów, które można udostępniać innym użytkownikom.", "albums_feature_description": "Kolekcje zasobów, które można udostępniać innym użytkownikom.",
"albums_on_device_count": "Albumów na urzadzeniu ({count})", "albums_on_device_count": "Albumy na urządzeniu ({count})",
"all": "Wszystkie", "all": "Wszystkie",
"all_albums": "Wszystkie albumy", "all_albums": "Wszystkie albumy",
"all_people": "Wszystkie osoby", "all_people": "Wszystkie osoby",
@@ -504,7 +504,7 @@
"assets_added_count": "Dodano {count, plural, one {# zasób} few {# zasoby} other {# zasobów}}", "assets_added_count": "Dodano {count, plural, one {# zasób} few {# zasoby} other {# zasobów}}",
"assets_added_to_album_count": "Dodano {count, plural, one {# zasób} few {# zasoby} other {# zasobów}} do albumu", "assets_added_to_album_count": "Dodano {count, plural, one {# zasób} few {# zasoby} other {# zasobów}} do albumu",
"assets_added_to_albums_count": "Dodano {assetTotal, plural, one {# zasób} few {# zasoby} other {# zasobów}} do {albumTotal, plural, one {# albumu} other {# albumów}}", "assets_added_to_albums_count": "Dodano {assetTotal, plural, one {# zasób} few {# zasoby} other {# zasobów}} do {albumTotal, plural, one {# albumu} other {# albumów}}",
"assets_cannot_be_added_to_album_count": "{count, plural, one {sztuka Elementu} other {szt. Elementów}} nie może być dodana do albumu", "assets_cannot_be_added_to_album_count": "{count, plural, one {Zasób nie może zostać dodany} other {Zasoby nie mogą zostać dodane}} do albumu",
"assets_cannot_be_added_to_albums": "{count, plural, one {Zasób nie może być dodany} other {Zasoby nie mogą być dodane}} do żadnego z albumów", "assets_cannot_be_added_to_albums": "{count, plural, one {Zasób nie może być dodany} other {Zasoby nie mogą być dodane}} do żadnego z albumów",
"assets_count": "{count, plural, one {# zasób} few {# zasoby} other {# zasobów}}", "assets_count": "{count, plural, one {# zasób} few {# zasoby} other {# zasobów}}",
"assets_deleted_permanently": "{count} zostało trwale usuniętych", "assets_deleted_permanently": "{count} zostało trwale usuniętych",
@@ -521,7 +521,7 @@
"assets_trashed": "{count} szt. zostało wrzucone do kosza", "assets_trashed": "{count} szt. zostało wrzucone do kosza",
"assets_trashed_count": "Wrzucono do kosza {count, plural, one {# zasób} few {# zasoby} other {# zasobów}}", "assets_trashed_count": "Wrzucono do kosza {count, plural, one {# zasób} few {# zasoby} other {# zasobów}}",
"assets_trashed_from_server": "{count} szt. usuniętych z serwera Immich", "assets_trashed_from_server": "{count} szt. usuniętych z serwera Immich",
"assets_were_part_of_album_count": "{count, plural, one {Zasób był} few {Zasoby były} many {Zasobów było} other {Zasobów było}} już częścią albumu", "assets_were_part_of_album_count": "{count, plural, one {Zasób był} other {Zasoby były}} już częścią albumu",
"assets_were_part_of_albums_count": "{count, plural, one {Zasób był} other {Zasoby były}} już częścią albumów", "assets_were_part_of_albums_count": "{count, plural, one {Zasób był} other {Zasoby były}} już częścią albumów",
"authorized_devices": "Autoryzowane urządzenia", "authorized_devices": "Autoryzowane urządzenia",
"automatic_endpoint_switching_subtitle": "Połącz się lokalnie przez wyznaczoną sieć Wi-Fi, jeśli jest dostępna, i korzystaj z alternatywnych połączeń gdzie indziej", "automatic_endpoint_switching_subtitle": "Połącz się lokalnie przez wyznaczoną sieć Wi-Fi, jeśli jest dostępna, i korzystaj z alternatywnych połączeń gdzie indziej",
@@ -535,7 +535,7 @@
"backup_album_selection_page_albums_device": "Albumy na urządzeniu ({count})", "backup_album_selection_page_albums_device": "Albumy na urządzeniu ({count})",
"backup_album_selection_page_albums_tap": "Stuknij, aby włączyć, stuknij dwukrotnie, aby wykluczyć", "backup_album_selection_page_albums_tap": "Stuknij, aby włączyć, stuknij dwukrotnie, aby wykluczyć",
"backup_album_selection_page_assets_scatter": "Pliki mogą być rozproszone w wielu albumach. Dzięki temu albumy mogą być włączane lub wyłączane podczas procesu tworzenia kopii zapasowej.", "backup_album_selection_page_assets_scatter": "Pliki mogą być rozproszone w wielu albumach. Dzięki temu albumy mogą być włączane lub wyłączane podczas procesu tworzenia kopii zapasowej.",
"backup_album_selection_page_select_albums": "Zaznacz albumy", "backup_album_selection_page_select_albums": "Wybierz albumy",
"backup_album_selection_page_selection_info": "Info o wyborze", "backup_album_selection_page_selection_info": "Info o wyborze",
"backup_album_selection_page_total_assets": "Łącznie unikalnych plików", "backup_album_selection_page_total_assets": "Łącznie unikalnych plików",
"backup_all": "Wszystkie", "backup_all": "Wszystkie",
@@ -564,7 +564,7 @@
"backup_controller_page_background_turn_on": "Włącz usługę w tle", "backup_controller_page_background_turn_on": "Włącz usługę w tle",
"backup_controller_page_background_wifi": "Tylko Wi-Fi", "backup_controller_page_background_wifi": "Tylko Wi-Fi",
"backup_controller_page_backup": "Kopia zapasowa", "backup_controller_page_backup": "Kopia zapasowa",
"backup_controller_page_backup_selected": "Zaznaczone: ", "backup_controller_page_backup_selected": "Wybrane: ",
"backup_controller_page_backup_sub": "Zdjęcia i filmy z utworzoną kopią zapasową", "backup_controller_page_backup_sub": "Zdjęcia i filmy z utworzoną kopią zapasową",
"backup_controller_page_created": "Utworzono dnia: {date}", "backup_controller_page_created": "Utworzono dnia: {date}",
"backup_controller_page_desc_backup": "Włącz kopię zapasową na pierwszym planie, aby automatycznie przesyłać nowe zasoby na serwer po otworzeniu aplikacji.", "backup_controller_page_desc_backup": "Włącz kopię zapasową na pierwszym planie, aby automatycznie przesyłać nowe zasoby na serwer po otworzeniu aplikacji.",
@@ -573,7 +573,7 @@
"backup_controller_page_filename": "Nazwa pliku: {filename} [{size}]", "backup_controller_page_filename": "Nazwa pliku: {filename} [{size}]",
"backup_controller_page_id": "ID: {id}", "backup_controller_page_id": "ID: {id}",
"backup_controller_page_info": "Informacje o kopii zapasowej", "backup_controller_page_info": "Informacje o kopii zapasowej",
"backup_controller_page_none_selected": "Brak wybranych", "backup_controller_page_none_selected": "Nic nie wybrano",
"backup_controller_page_remainder": "Pozostałe", "backup_controller_page_remainder": "Pozostałe",
"backup_controller_page_remainder_sub": "Pozostałe zdjęcia i filmy wybrane do wykonania kopii zapasowej", "backup_controller_page_remainder_sub": "Pozostałe zdjęcia i filmy wybrane do wykonania kopii zapasowej",
"backup_controller_page_server_storage": "Pamięć Serwera", "backup_controller_page_server_storage": "Pamięć Serwera",
@@ -638,7 +638,7 @@
"cast": "Odtwórz na telewizorze", "cast": "Odtwórz na telewizorze",
"cast_description": "Skonfiguruj dostępne cele do przesyłania", "cast_description": "Skonfiguruj dostępne cele do przesyłania",
"change_date": "Zmień datę", "change_date": "Zmień datę",
"change_description": "Zmiana opisu", "change_description": "Zmi opis",
"change_display_order": "Zmień kolejność wyświetlania", "change_display_order": "Zmień kolejność wyświetlania",
"change_expiration_time": "Zmień czas ważności", "change_expiration_time": "Zmień czas ważności",
"change_location": "Zmień lokalizację", "change_location": "Zmień lokalizację",
@@ -691,7 +691,7 @@
"confirm_admin_password": "Potwierdź Hasło Administratora", "confirm_admin_password": "Potwierdź Hasło Administratora",
"confirm_delete_face": "Czy na pewno chcesz usunąć twarz {name} z zasobów?", "confirm_delete_face": "Czy na pewno chcesz usunąć twarz {name} z zasobów?",
"confirm_delete_shared_link": "Czy na pewno chcesz usunąć ten udostępniony link?", "confirm_delete_shared_link": "Czy na pewno chcesz usunąć ten udostępniony link?",
"confirm_keep_this_delete_others": "Wszystkie inne zasoby zostaną usunięte poza tym zasobem. Czy jesteś pewien, że chcesz kontynuować?", "confirm_keep_this_delete_others": "Wszystkie inne zasoby w tym stosie, z wyjątkiem tego zasobu, zostaną usunięte. Czy jesteś pewien, że chcesz kontynuować?",
"confirm_new_pin_code": "Potwierdź nowy kod PIN", "confirm_new_pin_code": "Potwierdź nowy kod PIN",
"confirm_password": "Potwierdź hasło", "confirm_password": "Potwierdź hasło",
"confirm_tag_face": "Chcesz dodać do tej twarzy etykietę {name}?", "confirm_tag_face": "Chcesz dodać do tej twarzy etykietę {name}?",
@@ -708,7 +708,7 @@
"control_bottom_app_bar_edit_time": "Edytuj datę i godzinę", "control_bottom_app_bar_edit_time": "Edytuj datę i godzinę",
"control_bottom_app_bar_share_link": "Udostępnij link", "control_bottom_app_bar_share_link": "Udostępnij link",
"control_bottom_app_bar_share_to": "Wyślij", "control_bottom_app_bar_share_to": "Wyślij",
"control_bottom_app_bar_trash_from_immich": "Przenieść do kosza", "control_bottom_app_bar_trash_from_immich": "Przenieś do kosza",
"copied_image_to_clipboard": "Skopiowano obraz do schowka.", "copied_image_to_clipboard": "Skopiowano obraz do schowka.",
"copied_to_clipboard": "Skopiowano do schowka!", "copied_to_clipboard": "Skopiowano do schowka!",
"copy_error": "Błąd kopiowania", "copy_error": "Błąd kopiowania",
@@ -786,7 +786,7 @@
"delete_local_action_prompt": "{count} lokalnie usunięto", "delete_local_action_prompt": "{count} lokalnie usunięto",
"delete_local_dialog_ok_backed_up_only": "Usuń tylko kopię zapasową", "delete_local_dialog_ok_backed_up_only": "Usuń tylko kopię zapasową",
"delete_local_dialog_ok_force": "Usuń mimo to", "delete_local_dialog_ok_force": "Usuń mimo to",
"delete_others": "Usuń inne", "delete_others": "Usuń pozostałe",
"delete_permanently": "Usuń trwale", "delete_permanently": "Usuń trwale",
"delete_permanently_action_prompt": "{count} trwale usuniętych", "delete_permanently_action_prompt": "{count} trwale usuniętych",
"delete_shared_link": "Usuń udostępniony link", "delete_shared_link": "Usuń udostępniony link",
@@ -898,7 +898,7 @@
"cannot_navigate_previous_asset": "Nie można przejść do poprzedniego zasobu", "cannot_navigate_previous_asset": "Nie można przejść do poprzedniego zasobu",
"cant_apply_changes": "Nie można zastosować zmian", "cant_apply_changes": "Nie można zastosować zmian",
"cant_change_activity": "Nie można {enabled, select, true {wyłączyć} other {włączyć}} aktywności", "cant_change_activity": "Nie można {enabled, select, true {wyłączyć} other {włączyć}} aktywności",
"cant_change_asset_favorite": "Nie można zmienić ulubionego dla zasobu", "cant_change_asset_favorite": "Nie można zmienić statusu ulubionego dla zasobu",
"cant_change_metadata_assets_count": "Nie można zmienić metadanych {count, plural, one {# zasobu} other {# zasobów}}", "cant_change_metadata_assets_count": "Nie można zmienić metadanych {count, plural, one {# zasobu} other {# zasobów}}",
"cant_get_faces": "Nie można pozyskać twarzy", "cant_get_faces": "Nie można pozyskać twarzy",
"cant_get_number_of_comments": "Nie można uzyskać liczby komentarzy", "cant_get_number_of_comments": "Nie można uzyskać liczby komentarzy",
@@ -923,7 +923,7 @@
"failed_to_load_people": "Nie udało się pobrać ludzi", "failed_to_load_people": "Nie udało się pobrać ludzi",
"failed_to_remove_product_key": "Nie udało się usunąć klucza produktu", "failed_to_remove_product_key": "Nie udało się usunąć klucza produktu",
"failed_to_reset_pin_code": "Nie udało się zresetować kodu PIN", "failed_to_reset_pin_code": "Nie udało się zresetować kodu PIN",
"failed_to_stack_assets": "Nie udało się zestawić zasobów", "failed_to_stack_assets": "Nie udało się utworzyć stosu z zasobów",
"failed_to_unstack_assets": "Nie udało się rozdzielić zasobów", "failed_to_unstack_assets": "Nie udało się rozdzielić zasobów",
"failed_to_update_notification_status": "Nie udało się zaktualizować stanu powiadomienia", "failed_to_update_notification_status": "Nie udało się zaktualizować stanu powiadomienia",
"import_path_already_exists": "Ta ścieżka importu już istnieje.", "import_path_already_exists": "Ta ścieżka importu już istnieje.",
@@ -1151,7 +1151,7 @@
"immich_web_interface": "Interfejs internetowy Immich", "immich_web_interface": "Interfejs internetowy Immich",
"import_from_json": "Wczytaj z JSON", "import_from_json": "Wczytaj z JSON",
"import_path": "Ścieżka importu", "import_path": "Ścieżka importu",
"in_albums": "W {count, plural, one {# album} other {# albumy}}", "in_albums": "W {count, plural, one {# albumie} other {# albumach}}",
"in_archive": "W archiwum", "in_archive": "W archiwum",
"include_archived": "Uwzględnij zarchiwizowane", "include_archived": "Uwzględnij zarchiwizowane",
"include_shared_albums": "Uwzględnij udostępnione albumy", "include_shared_albums": "Uwzględnij udostępnione albumy",
@@ -1175,11 +1175,11 @@
"ios_debug_info_no_sync_yet": "Nie uruchomiono jeszcze żadnego zadania synchronizacji w tle", "ios_debug_info_no_sync_yet": "Nie uruchomiono jeszcze żadnego zadania synchronizacji w tle",
"ios_debug_info_processes_queued": "{count, plural, one {{count} proces w tle w kolejce} few {{count} procesy w tle w kolejce} other {{count} procesów w tle w kolejce}}", "ios_debug_info_processes_queued": "{count, plural, one {{count} proces w tle w kolejce} few {{count} procesy w tle w kolejce} other {{count} procesów w tle w kolejce}}",
"ios_debug_info_processing_ran_at": "Przetwarzanie przebiegło {dateTime}", "ios_debug_info_processing_ran_at": "Przetwarzanie przebiegło {dateTime}",
"items_count": "{count, plural, one {# element} other {# elementy}}", "items_count": "{count, plural, one {# element} few {# elementy} other {# elementów}}",
"jobs": "Zadania", "jobs": "Zadania",
"keep": "Zachowaj", "keep": "Zachowaj",
"keep_all": "Zachowaj wszystko", "keep_all": "Zachowaj wszystko",
"keep_this_delete_others": "Zachowaj to, usuń inne", "keep_this_delete_others": "Zachowaj to, usuń pozostałe",
"kept_this_deleted_others": "Zachowano ten zasób i usunięto {count, plural, one {#zasób} other {#zasoby}}", "kept_this_deleted_others": "Zachowano ten zasób i usunięto {count, plural, one {#zasób} other {#zasoby}}",
"keyboard_shortcuts": "Skróty klawiaturowe", "keyboard_shortcuts": "Skróty klawiaturowe",
"language": "Język", "language": "Język",
@@ -1459,7 +1459,7 @@
"permanent_deletion_warning_setting_description": "Pokaż ostrzeżenie przy trwałym usuwaniu zasobów", "permanent_deletion_warning_setting_description": "Pokaż ostrzeżenie przy trwałym usuwaniu zasobów",
"permanently_delete": "Usuń trwale", "permanently_delete": "Usuń trwale",
"permanently_delete_assets_count": "Trwale usuń {count, plural, one {zasób} few {zasoby} many {zasobów} other {zasobów}}", "permanently_delete_assets_count": "Trwale usuń {count, plural, one {zasób} few {zasoby} many {zasobów} other {zasobów}}",
"permanently_delete_assets_prompt": "Czy na pewno chcesz trwale usunąć {count, plural, one {ten zasób?} other {te <b>#</b> zasoby?}} Spowoduje to również usunięcie {count, plural, one {go z jego} other {ich z ich}} album(ów).", "permanently_delete_assets_prompt": "Czy na pewno chcesz trwale usunąć {count, plural, one {ten zasób?} few {te <b>#</b> zasoby?} other {te <b>#</b> zasobów?}} Spowoduje to również usunięcie {count, plural, one {go z jego} other {ich z ich}} album(ów).",
"permanently_deleted_asset": "Pomyślnie trwale usunięto zasób", "permanently_deleted_asset": "Pomyślnie trwale usunięto zasób",
"permanently_deleted_assets_count": "Trwale usunięto {count, plural, one {# zasób} other {# zasobów}}", "permanently_deleted_assets_count": "Trwale usunięto {count, plural, one {# zasób} other {# zasobów}}",
"permission": "Pozwolenie", "permission": "Pozwolenie",
@@ -1589,7 +1589,7 @@
"remote": "Zdalny", "remote": "Zdalny",
"remote_assets": "Zasoby zdalne", "remote_assets": "Zasoby zdalne",
"remove": "Usuń", "remove": "Usuń",
"remove_assets_album_confirmation": "Czy na pewno chcesz usunąć {count, plural, one {# zasób} other {# zasoby}} z albumu?", "remove_assets_album_confirmation": "Czy na pewno chcesz usunąć {count, plural, one {# zasób} few {# zasoby} other {# zasobów}} z albumu?",
"remove_assets_shared_link_confirmation": "Czy na pewno chcesz usunąć {count, plural, one {# zasób} other {# zasoby}} z tego udostępnionego linku?", "remove_assets_shared_link_confirmation": "Czy na pewno chcesz usunąć {count, plural, one {# zasób} other {# zasoby}} z tego udostępnionego linku?",
"remove_assets_title": "Usunąć zasoby?", "remove_assets_title": "Usunąć zasoby?",
"remove_custom_date_range": "Usuń niestandardowy zakres dat", "remove_custom_date_range": "Usuń niestandardowy zakres dat",
@@ -1712,7 +1712,7 @@
"search_tags": "Wyszukaj etykiety...", "search_tags": "Wyszukaj etykiety...",
"search_timezone": "Wyszukaj strefę czasową...", "search_timezone": "Wyszukaj strefę czasową...",
"search_type": "Wyszukaj w", "search_type": "Wyszukaj w",
"search_your_photos": "Szukaj swoich zdjęć", "search_your_photos": "Przeszukaj swoje zdjęcia",
"searching_locales": "Wyszukaj region...", "searching_locales": "Wyszukaj region...",
"second": "Sekunda", "second": "Sekunda",
"see_all_people": "Zobacz wszystkie osoby", "see_all_people": "Zobacz wszystkie osoby",
@@ -1732,7 +1732,7 @@
"select_photos": "Wybierz zdjęcia", "select_photos": "Wybierz zdjęcia",
"select_trash_all": "Zaznacz wszystko do kosza", "select_trash_all": "Zaznacz wszystko do kosza",
"select_user_for_sharing_page_err_album": "Nie udało się utworzyć albumu", "select_user_for_sharing_page_err_album": "Nie udało się utworzyć albumu",
"selected": "Zaznaczone", "selected": "Wybrane",
"selected_count": "{count, plural, other {# wybrane}}", "selected_count": "{count, plural, other {# wybrane}}",
"selected_gps_coordinates": "Wybrane Współrzędne GPS", "selected_gps_coordinates": "Wybrane Współrzędne GPS",
"send_message": "Wyślij wiadomość", "send_message": "Wyślij wiadomość",
@@ -1887,9 +1887,9 @@
"stack": "Stos", "stack": "Stos",
"stack_action_prompt": "{count} zgrupowano", "stack_action_prompt": "{count} zgrupowano",
"stack_duplicates": "Stos duplikatów", "stack_duplicates": "Stos duplikatów",
"stack_select_one_photo": "Wybierz jedno główne zdjęcie do stosu", "stack_select_one_photo": "Wybierz jedno główne zdjęcie dla stosu",
"stack_selected_photos": "Układaj wybrane zdjęcia", "stack_selected_photos": "Utwórz stos z wybranych zdjęć",
"stacked_assets_count": "Ułożone {count, plural, one {# zasób} other{# zasoby}}", "stacked_assets_count": "Utworzono stos z {count, plural, one {# zasobu} other {# zasobów}}",
"stacktrace": "Ślad stosu", "stacktrace": "Ślad stosu",
"start": "Start", "start": "Start",
"start_date": "Od dnia", "start_date": "Od dnia",
@@ -1952,7 +1952,7 @@
"time_based_memories": "Wspomnienia oparte na czasie", "time_based_memories": "Wspomnienia oparte na czasie",
"timeline": "Oś czasu", "timeline": "Oś czasu",
"timezone": "Strefa czasowa", "timezone": "Strefa czasowa",
"to_archive": "Archiwum", "to_archive": "Zarchiwizuj",
"to_change_password": "Zmień hasło", "to_change_password": "Zmień hasło",
"to_favorite": "Dodaj do ulubionych", "to_favorite": "Dodaj do ulubionych",
"to_login": "Zaloguj się", "to_login": "Zaloguj się",
@@ -1966,7 +1966,7 @@
"trash": "Kosz", "trash": "Kosz",
"trash_action_prompt": "{count} przeniesione do kosza", "trash_action_prompt": "{count} przeniesione do kosza",
"trash_all": "Usuń wszystkie", "trash_all": "Usuń wszystkie",
"trash_count": "Kosz {count, number}", "trash_count": "Usuń {count, number}",
"trash_delete_asset": "Kosz/Usuń zasób", "trash_delete_asset": "Kosz/Usuń zasób",
"trash_emptied": "Opróżnione śmieci", "trash_emptied": "Opróżnione śmieci",
"trash_no_results_message": "Tu znajdziesz wyrzucone zdjęcia i filmy.", "trash_no_results_message": "Tu znajdziesz wyrzucone zdjęcia i filmy.",
@@ -1982,7 +1982,7 @@
"type": "Typ", "type": "Typ",
"unable_to_change_pin_code": "Nie można zmienić kodu PIN", "unable_to_change_pin_code": "Nie można zmienić kodu PIN",
"unable_to_setup_pin_code": "Nie można ustawić kodu PIN", "unable_to_setup_pin_code": "Nie można ustawić kodu PIN",
"unarchive": "Cofnij archiwizację", "unarchive": "Przywróć z archiwum",
"unarchive_action_prompt": "{count} usunięto z archiwum", "unarchive_action_prompt": "{count} usunięto z archiwum",
"unarchived_count": "{count, plural, one {# cofnięta archiwizacja} few {# cofnięte archiwizacje} other {# cofniętych archiwizacji}}", "unarchived_count": "{count, plural, one {# cofnięta archiwizacja} few {# cofnięte archiwizacje} other {# cofniętych archiwizacji}}",
"undo": "Cofnij", "undo": "Cofnij",
@@ -2004,9 +2004,9 @@
"unselect_all": "Odznacz wszystko", "unselect_all": "Odznacz wszystko",
"unselect_all_duplicates": "Odznacz wszystkie duplikaty", "unselect_all_duplicates": "Odznacz wszystkie duplikaty",
"unselect_all_in": "Odznacz wszystkie w {group}", "unselect_all_in": "Odznacz wszystkie w {group}",
"unstack": "Rozłóż stos", "unstack": "Rozdziel stos",
"unstack_action_prompt": "{count} odgrupowano", "unstack_action_prompt": "{count} rozdzielono",
"unstacked_assets_count": "{count, plural, one {Rozłożony # zasób} few {Rozłożone # zasoby} other {Rozłożonych # zasobów}}", "unstacked_assets_count": "Rozdzielono {count, plural, one {# zasób} few {# zasoby} other {# zasobów}}",
"untagged": "Nieoznaczone", "untagged": "Nieoznaczone",
"up_next": "Do następnego", "up_next": "Do następnego",
"update_location_action_prompt": "Zaktualizuj lokalizację {count} wybranych zasobów na:", "update_location_action_prompt": "Zaktualizuj lokalizację {count} wybranych zasobów na:",
@@ -2077,11 +2077,11 @@
"view_previous_asset": "Wyświetl poprzedni zasób", "view_previous_asset": "Wyświetl poprzedni zasób",
"view_qr_code": "Pokaż kod QR", "view_qr_code": "Pokaż kod QR",
"view_similar_photos": "Zobacz podobne zdjęcia", "view_similar_photos": "Zobacz podobne zdjęcia",
"view_stack": "Zobacz Ułożenie", "view_stack": "Zobacz stos",
"view_user": "Wyświetl użytkownika", "view_user": "Wyświetl użytkownika",
"viewer_remove_from_stack": "Usuń ze stosu", "viewer_remove_from_stack": "Usuń ze stosu",
"viewer_stack_use_as_main_asset": "Użyj jako głównego zasobu", "viewer_stack_use_as_main_asset": "Użyj jako głównego zasobu",
"viewer_unstack": "Rozłóż Stos", "viewer_unstack": "Rozdziel stos",
"visibility_changed": "Zmieniono widoczność dla {count, plural, one {# osoby} other {# osób}}", "visibility_changed": "Zmieniono widoczność dla {count, plural, one {# osoby} other {# osób}}",
"waiting": "Oczekujące", "waiting": "Oczekujące",
"warning": "Ostrzeżenie", "warning": "Ostrzeżenie",

View File

@@ -1412,6 +1412,8 @@
"open_the_search_filters": "Abrir os filtros de pesquisa", "open_the_search_filters": "Abrir os filtros de pesquisa",
"options": "Opções", "options": "Opções",
"or": "ou", "or": "ou",
"organize_into_albums": "Organizar em álbuns",
"organize_into_albums_description": "Colocar fotos existentes em álbuns utilizando as definições atuais de sincronização",
"organize_your_library": "Organizar a sua biblioteca", "organize_your_library": "Organizar a sua biblioteca",
"original": "original", "original": "original",
"other": "Outro", "other": "Outro",
@@ -1513,7 +1515,7 @@
"profile_drawer_client_out_of_date_minor": "O aplicativo está desatualizado. Por favor, atualize para a versão mais recente.", "profile_drawer_client_out_of_date_minor": "O aplicativo está desatualizado. Por favor, atualize para a versão mais recente.",
"profile_drawer_client_server_up_to_date": "Cliente e Servidor atualizados", "profile_drawer_client_server_up_to_date": "Cliente e Servidor atualizados",
"profile_drawer_github": "GitHub", "profile_drawer_github": "GitHub",
"profile_drawer_readonly_mode": "Modo somente leitura activado. Toque duas vezes no ícone do avatar do utilizador para sair.", "profile_drawer_readonly_mode": "Modo somente leitura ativado. Toque duas vezes no ícone do avatar do utilizador para sair.",
"profile_drawer_server_out_of_date_major": "O servidor está desatualizado. Atualize para a versão principal mais recente.", "profile_drawer_server_out_of_date_major": "O servidor está desatualizado. Atualize para a versão principal mais recente.",
"profile_drawer_server_out_of_date_minor": "O servidor está desatualizado. Atualize para a versão mais recente.", "profile_drawer_server_out_of_date_minor": "O servidor está desatualizado. Atualize para a versão mais recente.",
"profile_image_of_user": "Imagem de perfil de {user}", "profile_image_of_user": "Imagem de perfil de {user}",
@@ -1552,6 +1554,7 @@
"purchase_server_description_2": "Status de apoiante", "purchase_server_description_2": "Status de apoiante",
"purchase_server_title": "Servidor", "purchase_server_title": "Servidor",
"purchase_settings_server_activated": "A chave de produto do servidor é gerida pelo administrador", "purchase_settings_server_activated": "A chave de produto do servidor é gerida pelo administrador",
"query_asset_id": "Consultar ID do recurso",
"queue_status": "Em fila {count}/{total}", "queue_status": "Em fila {count}/{total}",
"rating": "Classificação por estrelas", "rating": "Classificação por estrelas",
"rating_clear": "Limpar classificação", "rating_clear": "Limpar classificação",
@@ -1637,6 +1640,7 @@
"restore_user": "Restaurar utilizador", "restore_user": "Restaurar utilizador",
"restored_asset": "Ficheiro restaurado", "restored_asset": "Ficheiro restaurado",
"resume": "Continuar", "resume": "Continuar",
"resume_paused_jobs": "Continuar {count, plural, one {# trabalho em pausa} other {# trabalhos pausados}}",
"retry_upload": "Tentar carregar novamente", "retry_upload": "Tentar carregar novamente",
"review_duplicates": "Rever itens duplicados", "review_duplicates": "Rever itens duplicados",
"review_large_files": "Rever arquivos grandes", "review_large_files": "Rever arquivos grandes",
@@ -1730,7 +1734,7 @@
"select_user_for_sharing_page_err_album": "Ocorreu um erro ao criar o álbum", "select_user_for_sharing_page_err_album": "Ocorreu um erro ao criar o álbum",
"selected": "Selecionados", "selected": "Selecionados",
"selected_count": "{count, plural, other {# selecionados}}", "selected_count": "{count, plural, other {# selecionados}}",
"selected_gps_coordinates": "coordenadas gps seleccionadas", "selected_gps_coordinates": "Coordenadas GPS selecionadas",
"send_message": "Enviar mensagem", "send_message": "Enviar mensagem",
"send_welcome_email": "Enviar E-mail de boas vindas", "send_welcome_email": "Enviar E-mail de boas vindas",
"server_endpoint": "URL do servidor", "server_endpoint": "URL do servidor",
@@ -1913,6 +1917,8 @@
"sync_albums_manual_subtitle": "Sincronizar todas as fotos e vídeos enviados para o álbum de backup selecionado", "sync_albums_manual_subtitle": "Sincronizar todas as fotos e vídeos enviados para o álbum de backup selecionado",
"sync_local": "Sincronização Local", "sync_local": "Sincronização Local",
"sync_remote": "Sincronização Remota", "sync_remote": "Sincronização Remota",
"sync_status": "Status da sincronização",
"sync_status_subtitle": "Ver e gerir o sistema de sincronização",
"sync_upload_album_setting_subtitle": "Crie e envie suas fotos e vídeos para o álbum selecionado no Immich", "sync_upload_album_setting_subtitle": "Crie e envie suas fotos e vídeos para o álbum selecionado no Immich",
"tag": "Etiqueta", "tag": "Etiqueta",
"tag_assets": "Etiquetar ficheiros", "tag_assets": "Etiquetar ficheiros",
@@ -1972,6 +1978,7 @@
"trash_page_select_assets_btn": "Selecionar arquivos", "trash_page_select_assets_btn": "Selecionar arquivos",
"trash_page_title": "Reciclagem ({count})", "trash_page_title": "Reciclagem ({count})",
"trashed_items_will_be_permanently_deleted_after": "Os itens da reciclagem são eliminados permanentemente após {days, plural, one {# dia} other {# dias}}.", "trashed_items_will_be_permanently_deleted_after": "Os itens da reciclagem são eliminados permanentemente após {days, plural, one {# dia} other {# dias}}.",
"troubleshoot": "Diagnosticar problemas",
"type": "Tipo", "type": "Tipo",
"unable_to_change_pin_code": "Não foi possível alterar o código PIN", "unable_to_change_pin_code": "Não foi possível alterar o código PIN",
"unable_to_setup_pin_code": "Não foi possível configurar o código PIN", "unable_to_setup_pin_code": "Não foi possível configurar o código PIN",
@@ -2069,6 +2076,7 @@
"view_next_asset": "Ver próximo ficheiro", "view_next_asset": "Ver próximo ficheiro",
"view_previous_asset": "Ver ficheiro anterior", "view_previous_asset": "Ver ficheiro anterior",
"view_qr_code": "Ver código QR", "view_qr_code": "Ver código QR",
"view_similar_photos": "Ver fotos similares",
"view_stack": "Ver pilha", "view_stack": "Ver pilha",
"view_user": "Ver utilizador", "view_user": "Ver utilizador",
"viewer_remove_from_stack": "Remover da pilha", "viewer_remove_from_stack": "Remover da pilha",

View File

@@ -1515,7 +1515,7 @@
"profile_drawer_client_out_of_date_minor": "O aplicativo está desatualizado. Por favor, atualize para a versão mais recente.", "profile_drawer_client_out_of_date_minor": "O aplicativo está desatualizado. Por favor, atualize para a versão mais recente.",
"profile_drawer_client_server_up_to_date": "Cliente e Servidor estão atualizados", "profile_drawer_client_server_up_to_date": "Cliente e Servidor estão atualizados",
"profile_drawer_github": "GitHub", "profile_drawer_github": "GitHub",
"profile_drawer_readonly_mode": "Modo apenas visualização ativado. Toque duas vezes na foto do usuário para sair deste modo.", "profile_drawer_readonly_mode": "Modo apenas leitura habilidato. Dê um toque prolongado na foto do usuário para sair deste modo.",
"profile_drawer_server_out_of_date_major": "O servidor está desatualizado. Atualize para a versão principal mais recente.", "profile_drawer_server_out_of_date_major": "O servidor está desatualizado. Atualize para a versão principal mais recente.",
"profile_drawer_server_out_of_date_minor": "O servidor está desatualizado. Atualize para a versão mais recente.", "profile_drawer_server_out_of_date_minor": "O servidor está desatualizado. Atualize para a versão mais recente.",
"profile_image_of_user": "Imagem do perfil de {user}", "profile_image_of_user": "Imagem do perfil de {user}",
@@ -1640,6 +1640,7 @@
"restore_user": "Restaurar usuário", "restore_user": "Restaurar usuário",
"restored_asset": "Arquivo restaurado", "restored_asset": "Arquivo restaurado",
"resume": "Continuar", "resume": "Continuar",
"resume_paused_jobs": "Retomar {count, plural, one {# paused job} other {# paused jobs}}",
"retry_upload": "Tentar enviar novamente", "retry_upload": "Tentar enviar novamente",
"review_duplicates": "Revisar duplicidade", "review_duplicates": "Revisar duplicidade",
"review_large_files": "Ver arquivos grandes", "review_large_files": "Ver arquivos grandes",
@@ -1916,6 +1917,8 @@
"sync_albums_manual_subtitle": "Sincronize todos as fotos e vídeos enviados para os álbuns de backup selecionados", "sync_albums_manual_subtitle": "Sincronize todos as fotos e vídeos enviados para os álbuns de backup selecionados",
"sync_local": "Sincronização Local", "sync_local": "Sincronização Local",
"sync_remote": "Sincronização Remota", "sync_remote": "Sincronização Remota",
"sync_status": "Status da Sincronização",
"sync_status_subtitle": "Ver e gerenciar o sistema de sincronização",
"sync_upload_album_setting_subtitle": "Crie e envie suas fotos e vídeos para o álbum selecionado no Immich", "sync_upload_album_setting_subtitle": "Crie e envie suas fotos e vídeos para o álbum selecionado no Immich",
"tag": "Marcador", "tag": "Marcador",
"tag_assets": "Marcar arquivos", "tag_assets": "Marcar arquivos",
@@ -1975,6 +1978,7 @@
"trash_page_select_assets_btn": "Selecionar arquivos", "trash_page_select_assets_btn": "Selecionar arquivos",
"trash_page_title": "Lixeira ({count})", "trash_page_title": "Lixeira ({count})",
"trashed_items_will_be_permanently_deleted_after": "Os itens da lixeira serão deletados permanentemente após {days, plural, one {# dia} other {# dias}}.", "trashed_items_will_be_permanently_deleted_after": "Os itens da lixeira serão deletados permanentemente após {days, plural, one {# dia} other {# dias}}.",
"troubleshoot": "Diagnosticar",
"type": "Tipo", "type": "Tipo",
"unable_to_change_pin_code": "Não foi possível alterar o código PIN", "unable_to_change_pin_code": "Não foi possível alterar o código PIN",
"unable_to_setup_pin_code": "Não foi possível criar o código PIN", "unable_to_setup_pin_code": "Não foi possível criar o código PIN",

View File

@@ -35,7 +35,7 @@
"add_url": "Добавить URL", "add_url": "Добавить URL",
"added_to_archive": "Добавлено в архив", "added_to_archive": "Добавлено в архив",
"added_to_favorites": "Добавлено в избранное", "added_to_favorites": "Добавлено в избранное",
"added_to_favorites_count": "Добавлено{count, number} в избранное", "added_to_favorites_count": "{count, plural, one {# объект добавлен} many {# объектов добавлено} other {# объекта добавлено}} в избранное",
"admin": { "admin": {
"add_exclusion_pattern_description": "Добавьте шаблоны исключений. Поддерживаются символы подстановки *, ** и ?. Чтобы игнорировать все файлы в любом каталоге с именем \"Raw\", укажите \"**/Raw/**\". Чтобы игнорировать все файлы, заканчивающиеся на \".tif\", используйте \"**/*.tif\". Чтобы игнорировать путь целиком, укажите \"/path/to/ignore/**\".", "add_exclusion_pattern_description": "Добавьте шаблоны исключений. Поддерживаются символы подстановки *, ** и ?. Чтобы игнорировать все файлы в любом каталоге с именем \"Raw\", укажите \"**/Raw/**\". Чтобы игнорировать все файлы, заканчивающиеся на \".tif\", используйте \"**/*.tif\". Чтобы игнорировать путь целиком, укажите \"/path/to/ignore/**\".",
"admin_user": "Администратор", "admin_user": "Администратор",
@@ -396,7 +396,7 @@
"advanced_settings_prefer_remote_title": "Предпочитать фото на сервере", "advanced_settings_prefer_remote_title": "Предпочитать фото на сервере",
"advanced_settings_proxy_headers_subtitle": "Определите заголовки прокси-сервера, которые Immich должен отправлять с каждым сетевым запросом", "advanced_settings_proxy_headers_subtitle": "Определите заголовки прокси-сервера, которые Immich должен отправлять с каждым сетевым запросом",
"advanced_settings_proxy_headers_title": "Заголовки прокси", "advanced_settings_proxy_headers_title": "Заголовки прокси",
"advanced_settings_readonly_mode_subtitle": "Включает режим «только просмотр», в котором можно только просматривать объекты. Функции выбора нескольких объектов, публикации, трансляции и удаления будут недоступны. Включить/отключить режим «только просмотр» можно с помощью значка аватара пользователя на главном экране.", "advanced_settings_readonly_mode_subtitle": "Включает режим, в котором можно только просматривать объекты. Функции выбора нескольких объектов, публикации, трансляции и удаления будут недоступны. Включить/отключить этот режим можно удерживая значок аватара пользователя на главном экране.",
"advanced_settings_readonly_mode_title": "Режим «только просмотр»", "advanced_settings_readonly_mode_title": "Режим «только просмотр»",
"advanced_settings_self_signed_ssl_subtitle": "Пропускать проверку SSL-сертификата сервера. Требуется для самоподписанных сертификатов.", "advanced_settings_self_signed_ssl_subtitle": "Пропускать проверку SSL-сертификата сервера. Требуется для самоподписанных сертификатов.",
"advanced_settings_self_signed_ssl_title": "Разрешить самоподписанные SSL-сертификаты", "advanced_settings_self_signed_ssl_title": "Разрешить самоподписанные SSL-сертификаты",
@@ -448,7 +448,7 @@
"all_albums": "Все альбомы", "all_albums": "Все альбомы",
"all_people": "Все люди", "all_people": "Все люди",
"all_videos": "Все видео", "all_videos": "Все видео",
"allow_dark_mode": "Разрешить темный режим", "allow_dark_mode": "Разрешить тёмный режим",
"allow_edits": "Разрешить редактирование", "allow_edits": "Разрешить редактирование",
"allow_public_user_to_download": "Разрешить скачивание", "allow_public_user_to_download": "Разрешить скачивание",
"allow_public_user_to_upload": "Разрешить добавление файлов", "allow_public_user_to_upload": "Разрешить добавление файлов",
@@ -534,9 +534,9 @@
"backup": "Резервное копирование", "backup": "Резервное копирование",
"backup_album_selection_page_albums_device": "Альбомы на устройстве ({count})", "backup_album_selection_page_albums_device": "Альбомы на устройстве ({count})",
"backup_album_selection_page_albums_tap": "Нажмите, чтобы включить, дважды, чтобы исключить", "backup_album_selection_page_albums_tap": "Нажмите, чтобы включить, дважды, чтобы исключить",
"backup_album_selection_page_assets_scatter": "Ваши изображения и видео могут находиться в разных альбомах. Вы можете выбрать, какие альбомы включить, а какие исключить из резервного копирования.", "backup_album_selection_page_assets_scatter": "Ваши фото и видео могут находиться в разных альбомах/папках на устройстве. Вы можете выбрать, какие альбомы включить, а какие исключить из резервного копирования.",
"backup_album_selection_page_select_albums": "Выбор альбомов", "backup_album_selection_page_select_albums": "Выбор альбомов",
"backup_album_selection_page_selection_info": "Информация о выборе", "backup_album_selection_page_selection_info": "Выбранные альбомы",
"backup_album_selection_page_total_assets": "Всего уникальных объектов", "backup_album_selection_page_total_assets": "Всего уникальных объектов",
"backup_all": "Все", "backup_all": "Все",
"backup_background_service_backup_failed_message": "Не удалось выполнить резервное копирование. Повторная попытка…", "backup_background_service_backup_failed_message": "Не удалось выполнить резервное копирование. Повторная попытка…",
@@ -546,7 +546,7 @@
"backup_background_service_error_title": "Ошибка резервного копирования", "backup_background_service_error_title": "Ошибка резервного копирования",
"backup_background_service_in_progress_notification": "Резервное копирование объектов…", "backup_background_service_in_progress_notification": "Резервное копирование объектов…",
"backup_background_service_upload_failure_notification": "Ошибка загрузки {filename}", "backup_background_service_upload_failure_notification": "Ошибка загрузки {filename}",
"backup_controller_page_albums": "Резервное копирование альбомов", "backup_controller_page_albums": "Альбомы",
"backup_controller_page_background_app_refresh_disabled_content": "Включите фоновое обновление приложения в Настройки > Общие > Фоновое обновление приложений, чтобы использовать фоновое резервное копирование.", "backup_controller_page_background_app_refresh_disabled_content": "Включите фоновое обновление приложения в Настройки > Общие > Фоновое обновление приложений, чтобы использовать фоновое резервное копирование.",
"backup_controller_page_background_app_refresh_disabled_title": "Фоновое обновление отключено", "backup_controller_page_background_app_refresh_disabled_title": "Фоновое обновление отключено",
"backup_controller_page_background_app_refresh_enable_button_text": "Перейти в настройки", "backup_controller_page_background_app_refresh_enable_button_text": "Перейти в настройки",
@@ -563,8 +563,8 @@
"backup_controller_page_background_turn_off": "Выключить фоновую службу", "backup_controller_page_background_turn_off": "Выключить фоновую службу",
"backup_controller_page_background_turn_on": "Включить фоновую службу", "backup_controller_page_background_turn_on": "Включить фоновую службу",
"backup_controller_page_background_wifi": "Только через Wi-Fi", "backup_controller_page_background_wifi": "Только через Wi-Fi",
"backup_controller_page_backup": "Резервное копирование", "backup_controller_page_backup": "Загружено",
"backup_controller_page_backup_selected": "Выбрано: ", "backup_controller_page_backup_selected": "Выбраны: ",
"backup_controller_page_backup_sub": "Загруженные фото и видео", "backup_controller_page_backup_sub": "Загруженные фото и видео",
"backup_controller_page_created": "Создано: {date}", "backup_controller_page_created": "Создано: {date}",
"backup_controller_page_desc_backup": "Включите резервное копирование в активном режиме, чтобы автоматически загружать новые объекты при открытии приложения.", "backup_controller_page_desc_backup": "Включите резервное копирование в активном режиме, чтобы автоматически загружать новые объекты при открытии приложения.",
@@ -768,7 +768,7 @@
"default_locale": "Дата и время по умолчанию", "default_locale": "Дата и время по умолчанию",
"default_locale_description": "Использовать формат даты и времени в соответствии с языковым стандартом вашего браузера", "default_locale_description": "Использовать формат даты и времени в соответствии с языковым стандартом вашего браузера",
"delete": "Удалить", "delete": "Удалить",
"delete_action_confirmation_message": "Вы действительно хотите удалить этот объект? Это действие переместит объект в корзину сервера и предложит удалить его локально.", "delete_action_confirmation_message": "Вы действительно хотите удалить этот объект? Это действие переместит объект в корзину сервера и попробует удалить его локально.",
"delete_action_prompt": "Объекты удалены ({count} шт.)", "delete_action_prompt": "Объекты удалены ({count} шт.)",
"delete_album": "Удалить альбом", "delete_album": "Удалить альбом",
"delete_api_key_prompt": "Вы действительно хотите удалить этот API ключ?", "delete_api_key_prompt": "Вы действительно хотите удалить этот API ключ?",
@@ -1041,7 +1041,7 @@
"external": "Внешний", "external": "Внешний",
"external_libraries": "Внешние библиотеки", "external_libraries": "Внешние библиотеки",
"external_network": "Внешняя сеть", "external_network": "Внешняя сеть",
"external_network_sheet_info": "Когда устройство не подключено к выбранной Wi-Fi сети, приложение будет пытаться подключиться к серверу по адресам ниже, сверху вниз, до успешного подключения", "external_network_sheet_info": "Когда устройство не подключено к указанной Wi-Fi сети, приложение будет пытаться подключиться к серверу по адресам ниже, сверху вниз до успешного подключения",
"face_unassigned": "Не назначено", "face_unassigned": "Не назначено",
"failed": "Ошибка", "failed": "Ошибка",
"failed_to_authenticate": "Ошибка аутентификации", "failed_to_authenticate": "Ошибка аутентификации",
@@ -1093,8 +1093,8 @@
"haptic_feedback_switch": "Включить тактильную отдачу", "haptic_feedback_switch": "Включить тактильную отдачу",
"haptic_feedback_title": "Тактильная отдача", "haptic_feedback_title": "Тактильная отдача",
"has_quota": "Квота", "has_quota": "Квота",
"hash_asset": "Хешированный объект", "hash_asset": "Хеширование объектов",
"hashed_assets": "Хешированные объекты", "hashed_assets": "Хеши",
"hashing": "Хеширование", "hashing": "Хеширование",
"header_settings_add_header_tip": "Добавить заголовок", "header_settings_add_header_tip": "Добавить заголовок",
"header_settings_field_validator_msg": "Значение не может быть пустым", "header_settings_field_validator_msg": "Значение не может быть пустым",
@@ -1112,14 +1112,14 @@
"home_page_add_to_album_conflicts": "Добавлено {added} медиа в альбом {album}. {failed} медиа уже в альбоме.", "home_page_add_to_album_conflicts": "Добавлено {added} медиа в альбом {album}. {failed} медиа уже в альбоме.",
"home_page_add_to_album_err_local": "Пока нельзя добавлять локальные объекты в альбомы, пропуск", "home_page_add_to_album_err_local": "Пока нельзя добавлять локальные объекты в альбомы, пропуск",
"home_page_add_to_album_success": "Добавлено {added} медиа в альбом {album}.", "home_page_add_to_album_success": "Добавлено {added} медиа в альбом {album}.",
"home_page_album_err_partner": "Пока нельзя добавить медиа партнера в альбом, пропуск", "home_page_album_err_partner": "Невозможно добавить объекты партнёра в альбом, пропуск",
"home_page_archive_err_local": "Пока нельзя добавить локальные файлы в архив, пропуск", "home_page_archive_err_local": "Пока нельзя добавить локальные файлы в архив, пропуск",
"home_page_archive_err_partner": "Невозможно архивировать медиа партнера, пропуск", "home_page_archive_err_partner": "Невозможно добавить объекты партнёра в архив, пропуск",
"home_page_building_timeline": "Построение хронологии", "home_page_building_timeline": "Построение хронологии",
"home_page_delete_err_partner": "Невозможно удалить медиа партнера, пропуск", "home_page_delete_err_partner": "Невозможно удалить объекты партнёра, пропуск",
"home_page_delete_remote_err_local": "Невозможно удалить локальные файлы с сервера, пропуск", "home_page_delete_remote_err_local": "Невозможно удалить локальные файлы с сервера, пропуск",
"home_page_favorite_err_local": "Пока нельзя добавить в избранное локальные файлы, пропуск", "home_page_favorite_err_local": "Пока нельзя добавить в избранное локальные файлы, пропуск",
"home_page_favorite_err_partner": "Пока нельзя добавить в избранное медиа партнера, пропуск", "home_page_favorite_err_partner": "Невозможно добавить объекты партнёра в избранное, пропуск",
"home_page_first_time_notice": "Перед началом использования приложения выберите альбом с объектами для резервного копирования, чтобы они отобразились на временной шкале", "home_page_first_time_notice": "Перед началом использования приложения выберите альбом с объектами для резервного копирования, чтобы они отобразились на временной шкале",
"home_page_locked_error_local": "Невозможно переместить локальные объекты в личную папку, пропуск", "home_page_locked_error_local": "Невозможно переместить локальные объекты в личную папку, пропуск",
"home_page_locked_error_partner": "Невозможно переместить объекты партнёра в личную папку, пропуск", "home_page_locked_error_partner": "Невозможно переместить объекты партнёра в личную папку, пропуск",
@@ -1154,8 +1154,8 @@
"in_albums": "В {count, plural, one {# альбоме} other {# альбомах}}", "in_albums": "В {count, plural, one {# альбоме} other {# альбомах}}",
"in_archive": "В архиве", "in_archive": "В архиве",
"include_archived": "Отображать архив", "include_archived": "Отображать архив",
"include_shared_albums": "Включать общие альбомы", "include_shared_albums": "Включать объекты общих альбомов",
"include_shared_partner_assets": "Включать общие ресурсы партнера", "include_shared_partner_assets": "Включать объекты партнёров",
"individual_share": "Индивидуальная подборка", "individual_share": "Индивидуальная подборка",
"individual_shares": "Подборки", "individual_shares": "Подборки",
"info": "Информация", "info": "Информация",
@@ -1219,7 +1219,7 @@
"local_asset_cast_failed": "Невозможна трансляция объектов, которые ещё не загружены на сервер", "local_asset_cast_failed": "Невозможна трансляция объектов, которые ещё не загружены на сервер",
"local_assets": "Объекты на устройстве", "local_assets": "Объекты на устройстве",
"local_network": "Локальная сеть", "local_network": "Локальная сеть",
"local_network_sheet_info": "Приложение будет подключаться к серверу по этому адресу, когда устройство подключено к выбранной Wi-Fi сети", "local_network_sheet_info": "Приложение будет подключаться к серверу по этому адресу, когда устройство подключено к указанной Wi-Fi сети",
"location_permission": "Доступ к местоположению", "location_permission": "Доступ к местоположению",
"location_permission_content": "Чтобы использовать функцию автоматического переключения, Immich необходимо разрешение на точное определение местоположения, чтобы оно могло считывать название текущей Wi-Fi сети", "location_permission_content": "Чтобы использовать функцию автоматического переключения, Immich необходимо разрешение на точное определение местоположения, чтобы оно могло считывать название текущей Wi-Fi сети",
"location_picker_choose_on_map": "Выбрать на карте", "location_picker_choose_on_map": "Выбрать на карте",
@@ -1367,7 +1367,7 @@
"no_duplicates_found": "Дубликатов не обнаружено.", "no_duplicates_found": "Дубликатов не обнаружено.",
"no_exif_info_available": "Нет доступной информации exif", "no_exif_info_available": "Нет доступной информации exif",
"no_explore_results_message": "Загружайте больше фотографий, чтобы наслаждаться вашей коллекцией.", "no_explore_results_message": "Загружайте больше фотографий, чтобы наслаждаться вашей коллекцией.",
"no_favorites_message": "Добавляйте в избранное, чтобы быстро найти свои лучшие фотографии и видео", "no_favorites_message": "Добавляйте объекты в избранное, чтобы быстрее находить свои лучшие фото и видео",
"no_libraries_message": "Создайте внешнюю библиотеку для просмотра в Immich сторонних фотографий и видео", "no_libraries_message": "Создайте внешнюю библиотеку для просмотра в Immich сторонних фотографий и видео",
"no_locked_photos_message": "Фото и видео, перемещенные в личную папку, скрыты и не отображаются при просмотре библиотеки.", "no_locked_photos_message": "Фото и видео, перемещенные в личную папку, скрыты и не отображаются при просмотре библиотеки.",
"no_name": "Нет имени", "no_name": "Нет имени",
@@ -1413,7 +1413,7 @@
"options": "Опции", "options": "Опции",
"or": "или", "or": "или",
"organize_into_albums": "Распределить по альбомам", "organize_into_albums": "Распределить по альбомам",
"organize_into_albums_description": "Добавить уже существующие фотографии в альбомы, используя текущие настройки синхронизации", "organize_into_albums_description": "Добавить уже существующие объекты в альбомы, используя текущие настройки синхронизации",
"organize_your_library": "Приведите в порядок свою библиотеку", "organize_your_library": "Приведите в порядок свою библиотеку",
"original": "оригинал", "original": "оригинал",
"other": "Другое", "other": "Другое",
@@ -1422,18 +1422,18 @@
"other_variables": "Другие переменные", "other_variables": "Другие переменные",
"owned": "Мои", "owned": "Мои",
"owner": "Владелец", "owner": "Владелец",
"partner": "Партнер", "partner": "Партнёр",
"partner_can_access": "{partner} имеет доступ", "partner_can_access": "Пользователю {partner} доступны",
"partner_can_access_assets": "Все ваши фотографии и видеозаписи, кроме тех, которые находятся в Архиве и Корзине", "partner_can_access_assets": "Все ваши фото и видео, кроме тех, что находятся в архиве и корзине",
"partner_can_access_location": "Местоположение, где были сделаны ваши фотографии", "partner_can_access_location": "Места, где были сделаны ваши фото и видео",
"partner_list_user_photos": "Фотографии пользователя {user}", "partner_list_user_photos": "Фото и видео пользователя {user}",
"partner_list_view_all": "Посмотреть все", "partner_list_view_all": "Посмотреть все",
"partner_page_empty_message": "У вашего партнёра еще нет доступа к вашим фото.", "partner_page_empty_message": "Вы пока никому из партнёров не предоставили доступ к своим фото и видео.",
"partner_page_no_more_users": "Выбраны все доступные пользователи", "partner_page_no_more_users": "Выбраны все доступные пользователи",
"partner_page_partner_add_failed": "Не удалось добавить партнёра", "partner_page_partner_add_failed": "Не удалось добавить партнёра",
"partner_page_select_partner": "Выбрать партнёра", "partner_page_select_partner": "Выбрать партнёра",
"partner_page_shared_to_title": "Поделиться с...", "partner_page_shared_to_title": "Поделиться с...",
"partner_page_stop_sharing_content": "Пользователь {partner} больше не сможет получить доступ к вашим фото.", "partner_page_stop_sharing_content": "Пользователь {partner} больше не будет иметь доступ к вашим фото и видео.",
"partner_sharing": "Совместное использование", "partner_sharing": "Совместное использование",
"partners": "Партнёры", "partners": "Партнёры",
"password": "Пароль", "password": "Пароль",
@@ -1796,7 +1796,7 @@
"shared_by": "Поделился", "shared_by": "Поделился",
"shared_by_user": "Владелец: {user}", "shared_by_user": "Владелец: {user}",
"shared_by_you": "Вы поделились", "shared_by_you": "Вы поделились",
"shared_from_partner": "Фото и видео пользователя {partner}", "shared_from_partner": "Пользователь {partner} предоставил вам доступ",
"shared_intent_upload_button_progress_text": "{current} / {total} Загружено", "shared_intent_upload_button_progress_text": "{current} / {total} Загружено",
"shared_link_app_bar_title": "Публичные ссылки", "shared_link_app_bar_title": "Публичные ссылки",
"shared_link_clipboard_copied_massage": "Скопировано в буфер обмена", "shared_link_clipboard_copied_massage": "Скопировано в буфер обмена",
@@ -1833,7 +1833,7 @@
"shared_links_description": "Делитесь фотографиями и видео по ссылке", "shared_links_description": "Делитесь фотографиями и видео по ссылке",
"shared_photos_and_videos_count": "{assetCount, plural, other {# фото и видео.}}", "shared_photos_and_videos_count": "{assetCount, plural, other {# фото и видео.}}",
"shared_with_me": "Доступные мне", "shared_with_me": "Доступные мне",
"shared_with_partner": "Совместно с {partner}", "shared_with_partner": "Вы предоставили доступ пользователю {partner}",
"sharing": "Общие", "sharing": "Общие",
"sharing_enter_password": "Пожалуйста, введите пароль для просмотра этой страницы.", "sharing_enter_password": "Пожалуйста, введите пароль для просмотра этой страницы.",
"sharing_page_album": "Общие альбомы", "sharing_page_album": "Общие альбомы",
@@ -1851,7 +1851,7 @@
"show_gallery": "Показать галерею", "show_gallery": "Показать галерею",
"show_hidden_people": "Показать скрытых людей", "show_hidden_people": "Показать скрытых людей",
"show_in_timeline": "Показать на временной шкале", "show_in_timeline": "Показать на временной шкале",
"show_in_timeline_setting_description": "Отображать фото и видео этого пользователя в своей ленте", "show_in_timeline_setting_description": "Отображать фото и видео этого пользователя на своей временной шкале",
"show_keyboard_shortcuts": "Показать сочетания клавиш", "show_keyboard_shortcuts": "Показать сочетания клавиш",
"show_metadata": "Показывать метаданные", "show_metadata": "Показывать метаданные",
"show_or_hide_info": "Показать или скрыть информацию", "show_or_hide_info": "Показать или скрыть информацию",
@@ -1897,9 +1897,9 @@
"status": "Состояние", "status": "Состояние",
"stop_casting": "Остановить трансляцию", "stop_casting": "Остановить трансляцию",
"stop_motion_photo": "Покадровая анимация", "stop_motion_photo": "Покадровая анимация",
"stop_photo_sharing": "Закрыть доступ партнёра к вашим фото?", "stop_photo_sharing": "Закрыть доступ партнёру?",
"stop_photo_sharing_description": "Пользователь {partner} больше не имеет доступа к вашим фотографиям.", "stop_photo_sharing_description": "Пользователь {partner} больше не имеет доступа к вашим фотографиям.",
"stop_sharing_photos_with_user": "Прекратить делиться своими фотографиями с этим пользователем", "stop_sharing_photos_with_user": "Прекратить делиться своими фото и видео с этим пользователем",
"storage": "Хранилище", "storage": "Хранилище",
"storage_label": "Метка хранилища", "storage_label": "Метка хранилища",
"storage_quota": "Квота хранилища", "storage_quota": "Квота хранилища",
@@ -1915,11 +1915,11 @@
"sync": "Синхр.", "sync": "Синхр.",
"sync_albums": "Синхронизировать альбомы", "sync_albums": "Синхронизировать альбомы",
"sync_albums_manual_subtitle": "Синхронизировать все загруженные фото и видео в выбранные альбомы для резервного копирования", "sync_albums_manual_subtitle": "Синхронизировать все загруженные фото и видео в выбранные альбомы для резервного копирования",
"sync_local": "Синхронизировать локально", "sync_local": "Локальная синхронизация",
"sync_remote": "Синхронизация с сервером", "sync_remote": "Синхронизация с сервером",
"sync_status": "Статус синхронизации", "sync_status": "Статус синхронизации",
"sync_status_subtitle": "Просмотр и управление системой синхронизации", "sync_status_subtitle": "Просмотр и управление системой синхронизации",
"sync_upload_album_setting_subtitle": "Создавайте и загружайте свои фотографии и видео в выбранные альбомы на сервер Immich", "sync_upload_album_setting_subtitle": "Создавать на сервере такие же альбомы, как выбранные на устройстве, и загружать в них фото и видео",
"tag": "Тег", "tag": "Тег",
"tag_assets": "Добавить теги", "tag_assets": "Добавить теги",
"tag_created": "Тег {tag} создан", "tag_created": "Тег {tag} создан",

View File

@@ -1515,7 +1515,7 @@
"profile_drawer_client_out_of_date_minor": "Mobilna aplikacija je zastarela. Posodobite na najnovejšo manjšo različico.", "profile_drawer_client_out_of_date_minor": "Mobilna aplikacija je zastarela. Posodobite na najnovejšo manjšo različico.",
"profile_drawer_client_server_up_to_date": "Odjemalec in strežnik sta posodobljena", "profile_drawer_client_server_up_to_date": "Odjemalec in strežnik sta posodobljena",
"profile_drawer_github": "GitHub", "profile_drawer_github": "GitHub",
"profile_drawer_readonly_mode": "Način samo za branje je omogočen. Za izhod dvakrat tapnite ikono uporabniškega avatarja.", "profile_drawer_readonly_mode": "Način samo za branje je omogočen. Za izhod dolgo pritisnite ikono uporabniškega avatarja.",
"profile_drawer_server_out_of_date_major": "Strežnik je zastarel. Posodobite na najnovejšo glavno različico.", "profile_drawer_server_out_of_date_major": "Strežnik je zastarel. Posodobite na najnovejšo glavno različico.",
"profile_drawer_server_out_of_date_minor": "Strežnik je zastarel. Posodobite na najnovejšo manjšo različico.", "profile_drawer_server_out_of_date_minor": "Strežnik je zastarel. Posodobite na najnovejšo manjšo različico.",
"profile_image_of_user": "Profilna slika uporabnika {user}", "profile_image_of_user": "Profilna slika uporabnika {user}",
@@ -1917,6 +1917,8 @@
"sync_albums_manual_subtitle": "Sinhronizirajte vse naložene videoposnetke in fotografije v izbrane varnostne albume", "sync_albums_manual_subtitle": "Sinhronizirajte vse naložene videoposnetke in fotografije v izbrane varnostne albume",
"sync_local": "Sinhroniziraj lokalno", "sync_local": "Sinhroniziraj lokalno",
"sync_remote": "Sinhroniziraj oddaljeno", "sync_remote": "Sinhroniziraj oddaljeno",
"sync_status": "Stanje sinhronizacije",
"sync_status_subtitle": "Ogled in upravljanje sistema sinhronizacije",
"sync_upload_album_setting_subtitle": "Ustvarite in naložite svoje fotografije in videoposnetke v izbrane albume na Immich", "sync_upload_album_setting_subtitle": "Ustvarite in naložite svoje fotografije in videoposnetke v izbrane albume na Immich",
"tag": "Oznaka", "tag": "Oznaka",
"tag_assets": "Označi sredstva", "tag_assets": "Označi sredstva",
@@ -1976,6 +1978,7 @@
"trash_page_select_assets_btn": "Izberite sredstva", "trash_page_select_assets_btn": "Izberite sredstva",
"trash_page_title": "Smetnjak ({count})", "trash_page_title": "Smetnjak ({count})",
"trashed_items_will_be_permanently_deleted_after": "Elementi v smetnjaku bodo trajno izbrisani po {days, plural, one {# dnevu} two {# dnevih} few {# dnevih} other {# dneh}}.", "trashed_items_will_be_permanently_deleted_after": "Elementi v smetnjaku bodo trajno izbrisani po {days, plural, one {# dnevu} two {# dnevih} few {# dnevih} other {# dneh}}.",
"troubleshoot": "Odpravljanje težav",
"type": "Vrsta", "type": "Vrsta",
"unable_to_change_pin_code": "PIN kode ni mogoče spremeniti", "unable_to_change_pin_code": "PIN kode ni mogoče spremeniti",
"unable_to_setup_pin_code": "PIN kode ni mogoče nastaviti", "unable_to_setup_pin_code": "PIN kode ni mogoče nastaviti",

View File

@@ -4,6 +4,7 @@
"account_settings": "Podešavanja za Profil", "account_settings": "Podešavanja za Profil",
"acknowledge": "Potvrdi", "acknowledge": "Potvrdi",
"action": "Postupak", "action": "Postupak",
"action_common_update": "Ažuriraj",
"actions": "Postupci", "actions": "Postupci",
"active": "Aktivni", "active": "Aktivni",
"activity": "Aktivnost", "activity": "Aktivnost",
@@ -13,6 +14,7 @@
"add_a_location": "Dodaj Lokaciju", "add_a_location": "Dodaj Lokaciju",
"add_a_name": "Dodaj ime", "add_a_name": "Dodaj ime",
"add_a_title": "Dodaj naslov", "add_a_title": "Dodaj naslov",
"add_birthday": "Dodaj rođendan",
"add_endpoint": "Dodajte krajnju tačku", "add_endpoint": "Dodajte krajnju tačku",
"add_exclusion_pattern": "Dodajte obrazac izuzimanja", "add_exclusion_pattern": "Dodajte obrazac izuzimanja",
"add_import_path": "Dodaj putanju za preuzimanje", "add_import_path": "Dodaj putanju za preuzimanje",
@@ -21,10 +23,14 @@
"add_partner": "Dodaj partner", "add_partner": "Dodaj partner",
"add_path": "Dodaj putanju", "add_path": "Dodaj putanju",
"add_photos": "Dodaj fotografije", "add_photos": "Dodaj fotografije",
"add_tag": "Dodaj oznaku",
"add_to": "Dodaj u…", "add_to": "Dodaj u…",
"add_to_album": "Dodaj u album", "add_to_album": "Dodaj u album",
"add_to_album_bottom_sheet_added": "Dodato u {album}", "add_to_album_bottom_sheet_added": "Dodato u {album}",
"add_to_album_bottom_sheet_already_exists": "Već u {album}", "add_to_album_bottom_sheet_already_exists": "Već u {album}",
"add_to_album_toggle": "Uključi/isključi izbor za {album}",
"add_to_albums": "Dodaj u albume",
"add_to_albums_count": "Dodaj u albume ({count})",
"add_to_shared_album": "Dodaj u deljen album", "add_to_shared_album": "Dodaj u deljen album",
"add_url": "Dodaj URL", "add_url": "Dodaj URL",
"added_to_archive": "Dodato u arhivu", "added_to_archive": "Dodato u arhivu",
@@ -32,6 +38,7 @@
"added_to_favorites_count": "Dodato {count, number} u favorite", "added_to_favorites_count": "Dodato {count, number} u favorite",
"admin": { "admin": {
"add_exclusion_pattern_description": "Dodajte obrasce isključenja. Korištenje *, ** i ? je podržano. Da biste ignorisali sve datoteke u bilo kom direktorijumu pod nazivom „Rav“, koristite „**/Rav/**“. Da biste ignorisali sve datoteke koje se završavaju na „.tif“, koristite „**/*.tif“. Da biste ignorisali apsolutnu putanju, koristite „/path/to/ignore/**“.", "add_exclusion_pattern_description": "Dodajte obrasce isključenja. Korištenje *, ** i ? je podržano. Da biste ignorisali sve datoteke u bilo kom direktorijumu pod nazivom „Rav“, koristite „**/Rav/**“. Da biste ignorisali sve datoteke koje se završavaju na „.tif“, koristite „**/*.tif“. Da biste ignorisali apsolutnu putanju, koristite „/path/to/ignore/**“.",
"admin_user": "Administrator",
"asset_offline_description": "Ovo eksterno bibliotečko sredstvo se više ne nalazi na disku i premešteno je u smeće. Ako je datoteka premeštena unutar biblioteke, proverite svoju vremensku liniju za novo odgovarajuće sredstvo. Da biste vratili ovo sredstvo, uverite se da Immich može da pristupi dole navedenoj putanji datoteke i skenirajte biblioteku.", "asset_offline_description": "Ovo eksterno bibliotečko sredstvo se više ne nalazi na disku i premešteno je u smeće. Ako je datoteka premeštena unutar biblioteke, proverite svoju vremensku liniju za novo odgovarajuće sredstvo. Da biste vratili ovo sredstvo, uverite se da Immich može da pristupi dole navedenoj putanji datoteke i skenirajte biblioteku.",
"authentication_settings": "Podešavanja za autentifikaciju", "authentication_settings": "Podešavanja za autentifikaciju",
"authentication_settings_description": "Upravljajte lozinkom, OAuth-om i drugim podešavanjima autentifikacije", "authentication_settings_description": "Upravljajte lozinkom, OAuth-om i drugim podešavanjima autentifikacije",
@@ -41,8 +48,15 @@
"backup_database": "Kreirajte rezervnu kopiju baze podataka", "backup_database": "Kreirajte rezervnu kopiju baze podataka",
"backup_database_enable_description": "Omogući dampove baze podataka", "backup_database_enable_description": "Omogući dampove baze podataka",
"backup_keep_last_amount": "Količina prethodnih dampova koje treba zadržati", "backup_keep_last_amount": "Količina prethodnih dampova koje treba zadržati",
"backup_onboarding_1_description": "kopija na oblaku ili na drugoj fizičkoj lokaciji.",
"backup_onboarding_2_description": "lokalne kopije na različitim uređajima. Ovo uključuje glavne datoteke i rezervnu kopiju tih datoteka lokalno.",
"backup_onboarding_3_description": "ukupno kopija vaših podataka, uklučujući originalne datoteke. Ovo uključuje 1 udaljenu kopiju i 2 lokalne kopije.",
"backup_onboarding_description": "<backblaze-link>3-2-1 strategija rezervnih kopija</backblaze-link> je preporučena da zaštiti vaše podatke. Trebali biste čuvati kopije vaših otpremljenih slika/videa kao i Immich bazu podataka za sveobuhvatno rešenje za rezervne kopije.",
"backup_onboarding_footer": "Za više informacija o pravljenju rezervne kopije Immich-a, molimo vas pogledajte <link>dokumentaciju</link>.",
"backup_onboarding_parts_title": "3-2-1 rezervna kopija uključuje:",
"backup_onboarding_title": "Rezervne kopije",
"backup_settings": "Podešavanja dampa baze podataka", "backup_settings": "Podešavanja dampa baze podataka",
"backup_settings_description": "Upravljajte podešavanjima dampa baze podataka. Napomena: Ovi poslovi se ne prate i nećete biti obavešteni o neuspehu.", "backup_settings_description": "Upravljajte podešavanjima dampa baze podataka.",
"cleared_jobs": "Očišćeni poslovi za: {job}", "cleared_jobs": "Očišćeni poslovi za: {job}",
"config_set_by_file": "Konfiguraciju trenutno postavlja konfiguracioni fajl", "config_set_by_file": "Konfiguraciju trenutno postavlja konfiguracioni fajl",
"confirm_delete_library": "Da li stvarno želite da izbrišete biblioteku {library} ?", "confirm_delete_library": "Da li stvarno želite da izbrišete biblioteku {library} ?",
@@ -163,12 +177,23 @@
"metadata_settings_description": "Upravljajte podešavanjima metapodataka", "metadata_settings_description": "Upravljajte podešavanjima metapodataka",
"migration_job": "Migracije", "migration_job": "Migracije",
"migration_job_description": "Prenesite sličice datoteka i lica u najnoviju strukturu direktorijuma", "migration_job_description": "Prenesite sličice datoteka i lica u najnoviju strukturu direktorijuma",
"nightly_tasks_cluster_faces_setting_description": "Pokreni prepoznavanje lica na novodetektovanim licima",
"nightly_tasks_cluster_new_faces_setting": "Združi nova lica",
"nightly_tasks_database_cleanup_setting": "Zadaci čiščenja baze podataka",
"nightly_tasks_database_cleanup_setting_description": "Očisti stare, istekle podatke iz baze podataka",
"nightly_tasks_generate_memories_setting": "Generiši sjećanja",
"nightly_tasks_generate_memories_setting_description": "Kreiraj nova sjećanja",
"nightly_tasks_missing_thumbnails_setting": "Generiši nedostajuće sličice",
"nightly_tasks_missing_thumbnails_setting_description": "Dodajte elemente bez sličica u red za generisanje sličica",
"nightly_tasks_settings": "Podešavanja noćnih zadataka",
"nightly_tasks_settings_description": "Upravljaj noćnim zadacima",
"nightly_tasks_sync_quota_usage_setting_description": "Ažurirajte kvotu memorijskog prostora korisnika na osnovu trenutne upotrebe",
"no_paths_added": "Nema dodatih putanja", "no_paths_added": "Nema dodatih putanja",
"no_pattern_added": "Nije dodat obrazac", "no_pattern_added": "Nije dodat obrazac",
"note_apply_storage_label_previous_assets": "Napomena: Da biste primenili oznaku za skladištenje na prethodno otpremljena sredstva, pokrenite", "note_apply_storage_label_previous_assets": "Napomena: Da biste primenili oznaku za skladištenje na prethodno otpremljena sredstva, pokrenite",
"note_cannot_be_changed_later": "NAPOMENA: Ovo se kasnije ne može promeniti!", "note_cannot_be_changed_later": "NAPOMENA: Ovo se kasnije ne može promeniti!",
"notification_email_from_address": "Sa adrese", "notification_email_from_address": "Sa adrese",
"notification_email_from_address_description": "Adresa e-pošte pošiljaoca, na primer: \"Immich foto server <noreply@example.com>\"", "notification_email_from_address_description": "Adresa e-pošte pošiljaoca, na primer: \"Immich foto server <noreply@example.com>\". Pobrinite se da koristite adresu sa koje vam je dozovljeno slati e-poštu.",
"notification_email_host_description": "Host servera e-pošte (npr. smtp.immich.app)", "notification_email_host_description": "Host servera e-pošte (npr. smtp.immich.app)",
"notification_email_ignore_certificate_errors": "Zanemarite greške sertifikata", "notification_email_ignore_certificate_errors": "Zanemarite greške sertifikata",
"notification_email_ignore_certificate_errors_description": "Ignorišite greške u validaciji TLS sertifikata (ne preporučuje se)", "notification_email_ignore_certificate_errors_description": "Ignorišite greške u validaciji TLS sertifikata (ne preporučuje se)",
@@ -201,7 +226,7 @@
"oauth_storage_quota_claim": "Zahtev za kvotu skladištenja", "oauth_storage_quota_claim": "Zahtev za kvotu skladištenja",
"oauth_storage_quota_claim_description": "Automatski podesite kvotu memorijskog prostora korisnika na vrednost ovog zahteva.", "oauth_storage_quota_claim_description": "Automatski podesite kvotu memorijskog prostora korisnika na vrednost ovog zahteva.",
"oauth_storage_quota_default": "Podrazumevana kvota za skladištenje (GiB)", "oauth_storage_quota_default": "Podrazumevana kvota za skladištenje (GiB)",
"oauth_storage_quota_default_description": "Kvota u GiB koja se koristi kada nema potraživanja (unesite 0 za neograničenu kvotu).", "oauth_storage_quota_default_description": "Kvota u GiB koja se koristi kada nema potraživanja.",
"oauth_timeout": "Vremensko ograničenje zahteva", "oauth_timeout": "Vremensko ograničenje zahteva",
"oauth_timeout_description": "Vremensko ograničenje za zahteve u milisekundama", "oauth_timeout_description": "Vremensko ograničenje za zahteve u milisekundama",
"password_enable_description": "Prijavite se pomoću e-pošte i lozinke", "password_enable_description": "Prijavite se pomoću e-pošte i lozinke",
@@ -508,7 +533,7 @@
"backup_controller_page_background_turn_off": "Isključi pozadinski servis", "backup_controller_page_background_turn_off": "Isključi pozadinski servis",
"backup_controller_page_background_turn_on": "Uključi pozadinski servis", "backup_controller_page_background_turn_on": "Uključi pozadinski servis",
"backup_controller_page_background_wifi": "Samo na Wi-Fi", "backup_controller_page_background_wifi": "Samo na Wi-Fi",
"backup_controller_page_backup": "Napravi rezervnu kopiju", "backup_controller_page_backup": "Rezervne kopije",
"backup_controller_page_backup_selected": "Odabrano: ", "backup_controller_page_backup_selected": "Odabrano: ",
"backup_controller_page_backup_sub": "Završeno pravljenje rezervne kopije fotografija i videa", "backup_controller_page_backup_sub": "Završeno pravljenje rezervne kopije fotografija i videa",
"backup_controller_page_created": "Napravljeno:{date}", "backup_controller_page_created": "Napravljeno:{date}",
@@ -519,8 +544,8 @@
"backup_controller_page_id": "ID:{id}", "backup_controller_page_id": "ID:{id}",
"backup_controller_page_info": "Informacije", "backup_controller_page_info": "Informacije",
"backup_controller_page_none_selected": "Ništa odabrano", "backup_controller_page_none_selected": "Ništa odabrano",
"backup_controller_page_remainder": "Podsetnik", "backup_controller_page_remainder": "Ostatak",
"backup_controller_page_remainder_sub": "Ostalo fotografija i videa da se otpremi od selekcije", "backup_controller_page_remainder_sub": "Ostale fotografije i video snimci za otpremanje od selekcije",
"backup_controller_page_server_storage": "Prostor na serveru", "backup_controller_page_server_storage": "Prostor na serveru",
"backup_controller_page_start_backup": "Pokreni pravljenje rezervne kopije", "backup_controller_page_start_backup": "Pokreni pravljenje rezervne kopije",
"backup_controller_page_status_off": "Automatsko pravljenje rezervnih kopija u prvom planu je isključeno", "backup_controller_page_status_off": "Automatsko pravljenje rezervnih kopija u prvom planu je isključeno",

View File

@@ -1515,7 +1515,7 @@
"profile_drawer_client_out_of_date_minor": "Mobilappen är föråldrad. Uppdatera till senaste versionen.", "profile_drawer_client_out_of_date_minor": "Mobilappen är föråldrad. Uppdatera till senaste versionen.",
"profile_drawer_client_server_up_to_date": "Klient och server är uppdaterade", "profile_drawer_client_server_up_to_date": "Klient och server är uppdaterade",
"profile_drawer_github": "GitHub", "profile_drawer_github": "GitHub",
"profile_drawer_readonly_mode": "Skrivskyddat läge aktiverat. Dubbeltryck på användaravatarikonen för att avsluta", "profile_drawer_readonly_mode": "Skrivskyddat läge aktiverat. Håll in användaravatarikonen för att avsluta",
"profile_drawer_server_out_of_date_major": "Servern har en föråldrad mjukvara. Uppdatera till senaste versionen.", "profile_drawer_server_out_of_date_major": "Servern har en föråldrad mjukvara. Uppdatera till senaste versionen.",
"profile_drawer_server_out_of_date_minor": "Servern har en föråldrad mjukvara. Uppdatera till senaste versionen.", "profile_drawer_server_out_of_date_minor": "Servern har en föråldrad mjukvara. Uppdatera till senaste versionen.",
"profile_image_of_user": "{user} profilbild", "profile_image_of_user": "{user} profilbild",
@@ -1917,6 +1917,8 @@
"sync_albums_manual_subtitle": "Synka alla uppladdade videor och foton till valda backup-album", "sync_albums_manual_subtitle": "Synka alla uppladdade videor och foton till valda backup-album",
"sync_local": "Synkronisera lokalt", "sync_local": "Synkronisera lokalt",
"sync_remote": "Synkronisera fjärrserver", "sync_remote": "Synkronisera fjärrserver",
"sync_status": "Synk Status",
"sync_status_subtitle": "Visa och hantera synkroniseringssystemet",
"sync_upload_album_setting_subtitle": "Skapa och ladda upp dina foton och videor till de valda albumen på Immich", "sync_upload_album_setting_subtitle": "Skapa och ladda upp dina foton och videor till de valda albumen på Immich",
"tag": "Tagg", "tag": "Tagg",
"tag_assets": "Tagga tillgångar", "tag_assets": "Tagga tillgångar",
@@ -1976,6 +1978,7 @@
"trash_page_select_assets_btn": "Välj objekt", "trash_page_select_assets_btn": "Välj objekt",
"trash_page_title": "Papperskorg ({count})", "trash_page_title": "Papperskorg ({count})",
"trashed_items_will_be_permanently_deleted_after": "Objekt i papperskorgen raderas permanent efter {days, plural, one {# dag} other {# dagar}}.", "trashed_items_will_be_permanently_deleted_after": "Objekt i papperskorgen raderas permanent efter {days, plural, one {# dag} other {# dagar}}.",
"troubleshoot": "Felsök",
"type": "Typ", "type": "Typ",
"unable_to_change_pin_code": "Kunde inte ändra pinkod", "unable_to_change_pin_code": "Kunde inte ändra pinkod",
"unable_to_setup_pin_code": "Kunde inte konfigurera pinkod", "unable_to_setup_pin_code": "Kunde inte konfigurera pinkod",

File diff suppressed because it is too large Load Diff

View File

@@ -1640,7 +1640,7 @@
"restore_user": "Відновити користувача", "restore_user": "Відновити користувача",
"restored_asset": "Відновлений ресурс", "restored_asset": "Відновлений ресурс",
"resume": "Продовжити", "resume": "Продовжити",
"resume_paused_jobs": "Резюме {count, plural, one {# призупинене завдання} other {# призупинені завдання}}", "resume_paused_jobs": "Відновити {count, plural, one {# призупинене завдання} other {# призупинені завдання}}",
"retry_upload": "Повторити завантаження", "retry_upload": "Повторити завантаження",
"review_duplicates": "Переглянути дублікати", "review_duplicates": "Переглянути дублікати",
"review_large_files": "Перегляд великих файлів", "review_large_files": "Перегляд великих файлів",

View File

@@ -1510,7 +1510,7 @@
"profile_drawer_client_out_of_date_minor": "客戶端有小版本升級,請盡快升級至最新版。", "profile_drawer_client_out_of_date_minor": "客戶端有小版本升級,請盡快升級至最新版。",
"profile_drawer_client_server_up_to_date": "客戶端和服務端都是最新的", "profile_drawer_client_server_up_to_date": "客戶端和服務端都是最新的",
"profile_drawer_github": "GitHub", "profile_drawer_github": "GitHub",
"profile_drawer_readonly_mode": "唯讀模式已開啟。請連點兩下使用者頭像圖示以退出。", "profile_drawer_readonly_mode": "唯讀模式已開啟。請長按使用者頭像圖示以退出。",
"profile_drawer_server_out_of_date_major": "服務端有大版本升級,請盡快升級至最新版。", "profile_drawer_server_out_of_date_major": "服務端有大版本升級,請盡快升級至最新版。",
"profile_drawer_server_out_of_date_minor": "服務端有小版本升級,請盡快升級至最新版。", "profile_drawer_server_out_of_date_minor": "服務端有小版本升級,請盡快升級至最新版。",
"profile_image_of_user": "{user} 的個人資料圖片", "profile_image_of_user": "{user} 的個人資料圖片",
@@ -1549,6 +1549,7 @@
"purchase_server_description_2": "擁護者狀態", "purchase_server_description_2": "擁護者狀態",
"purchase_server_title": "伺服器", "purchase_server_title": "伺服器",
"purchase_settings_server_activated": "伺服器產品金鑰是由管理者管理的", "purchase_settings_server_activated": "伺服器產品金鑰是由管理者管理的",
"query_asset_id": "査詢資產ID",
"queue_status": "處理中 {count}/{total}", "queue_status": "處理中 {count}/{total}",
"rating": "評星", "rating": "評星",
"rating_clear": "清除評等", "rating_clear": "清除評等",
@@ -1634,6 +1635,7 @@
"restore_user": "還原使用者", "restore_user": "還原使用者",
"restored_asset": "已還原檔案", "restored_asset": "已還原檔案",
"resume": "繼續", "resume": "繼續",
"resume_paused_jobs": "恢復 {count, plural, one {# 暫停的任務} other {# 暫停的任務}}",
"retry_upload": "重新上傳", "retry_upload": "重新上傳",
"review_duplicates": "檢視重複項目", "review_duplicates": "檢視重複項目",
"review_large_files": "檢視大型文件", "review_large_files": "檢視大型文件",
@@ -1910,6 +1912,8 @@
"sync_albums_manual_subtitle": "將所有上傳的短片和照片同步到選定的備份相簿", "sync_albums_manual_subtitle": "將所有上傳的短片和照片同步到選定的備份相簿",
"sync_local": "同步本機", "sync_local": "同步本機",
"sync_remote": "同步遠端", "sync_remote": "同步遠端",
"sync_status": "同步状态",
"sync_status_subtitle": "查看和管理同步系統",
"sync_upload_album_setting_subtitle": "新增照片和短片並上傳到 Immich 上的選定相簿中", "sync_upload_album_setting_subtitle": "新增照片和短片並上傳到 Immich 上的選定相簿中",
"tag": "標籤", "tag": "標籤",
"tag_assets": "標記檔案", "tag_assets": "標記檔案",
@@ -1947,7 +1951,9 @@
"to_change_password": "變更密碼", "to_change_password": "變更密碼",
"to_favorite": "收藏", "to_favorite": "收藏",
"to_login": "登入", "to_login": "登入",
"to_multi_select": "進行多選",
"to_parent": "到上一級", "to_parent": "到上一級",
"to_select": "选择",
"to_trash": "垃圾桶", "to_trash": "垃圾桶",
"toggle_settings": "切換設定", "toggle_settings": "切換設定",
"total": "統計", "total": "統計",
@@ -1967,6 +1973,7 @@
"trash_page_select_assets_btn": "選擇項目", "trash_page_select_assets_btn": "選擇項目",
"trash_page_title": "垃圾桶 ({count})", "trash_page_title": "垃圾桶 ({count})",
"trashed_items_will_be_permanently_deleted_after": "垃圾桶中的項目會在 {days, plural, other {# 天}}後永久刪除。", "trashed_items_will_be_permanently_deleted_after": "垃圾桶中的項目會在 {days, plural, other {# 天}}後永久刪除。",
"troubleshoot": "疑难解答",
"type": "類型", "type": "類型",
"unable_to_change_pin_code": "無法變更 PIN 碼", "unable_to_change_pin_code": "無法變更 PIN 碼",
"unable_to_setup_pin_code": "無法設定 PIN 碼", "unable_to_setup_pin_code": "無法設定 PIN 碼",
@@ -1997,6 +2004,7 @@
"unstacked_assets_count": "已解除堆疊 {count, plural, other {# 個檔案}}", "unstacked_assets_count": "已解除堆疊 {count, plural, other {# 個檔案}}",
"untagged": "無標籤", "untagged": "無標籤",
"up_next": "下一個", "up_next": "下一個",
"update_location_action_prompt": "使用以下命令更新{count}個所選資產的位置:",
"updated_at": "更新於", "updated_at": "更新於",
"updated_password": "已更新密碼", "updated_password": "已更新密碼",
"upload": "上傳", "upload": "上傳",
@@ -2063,6 +2071,7 @@
"view_next_asset": "查看下一項", "view_next_asset": "查看下一項",
"view_previous_asset": "查看上一項", "view_previous_asset": "查看上一項",
"view_qr_code": "查看 QR code", "view_qr_code": "查看 QR code",
"view_similar_photos": "查看相似照片",
"view_stack": "查看堆疊", "view_stack": "查看堆疊",
"view_user": "顯示使用者", "view_user": "顯示使用者",
"viewer_remove_from_stack": "從堆疊中移除", "viewer_remove_from_stack": "從堆疊中移除",

View File

@@ -26,8 +26,8 @@
"add_tag": "添加标签", "add_tag": "添加标签",
"add_to": "添加到…", "add_to": "添加到…",
"add_to_album": "添加到相册", "add_to_album": "添加到相册",
"add_to_album_bottom_sheet_added": "添加到 {album}", "add_to_album_bottom_sheet_added": "添加到相册 “{album}",
"add_to_album_bottom_sheet_already_exists": "已在 {album} 中", "add_to_album_bottom_sheet_already_exists": "已在相册“ {album} 中",
"add_to_album_toggle": "选择相册 {album}", "add_to_album_toggle": "选择相册 {album}",
"add_to_albums": "添加到相册", "add_to_albums": "添加到相册",
"add_to_albums_count": "添加到相册({count}个)", "add_to_albums_count": "添加到相册({count}个)",
@@ -100,7 +100,7 @@
"image_thumbnail_description": "剥离元数据的小缩略图,用于浏览主时间线等照片组", "image_thumbnail_description": "剥离元数据的小缩略图,用于浏览主时间线等照片组",
"image_thumbnail_quality_description": "缩略图质量从 1 到 100。越高越好但会产生更大的文件并且会降低系统的响应能力。", "image_thumbnail_quality_description": "缩略图质量从 1 到 100。越高越好但会产生更大的文件并且会降低系统的响应能力。",
"image_thumbnail_title": "缩略图设置", "image_thumbnail_title": "缩略图设置",
"job_concurrency": "{job}并发", "job_concurrency": "{job}任务并发",
"job_created": "任务已创建", "job_created": "任务已创建",
"job_not_concurrency_safe": "此任务并发并不安全。", "job_not_concurrency_safe": "此任务并发并不安全。",
"job_settings": "任务设置", "job_settings": "任务设置",
@@ -121,13 +121,13 @@
"library_watching_settings": "监控图库(实验性)", "library_watching_settings": "监控图库(实验性)",
"library_watching_settings_description": "自动监控文件变化", "library_watching_settings_description": "自动监控文件变化",
"logging_enable_description": "启用日志记录", "logging_enable_description": "启用日志记录",
"logging_level_description": "启用的日志级别。", "logging_level_description": "启用时,要使用的日志级别。",
"logging_settings": "日志", "logging_settings": "日志",
"machine_learning_clip_model": "CLIP 模型", "machine_learning_clip_model": "CLIP 模型",
"machine_learning_clip_model_description": "请于 <link>此处</link>查看支持的 CLIP 模型名称。注意,更换模型后需要对所有图片重新运行“智能搜索”任务。", "machine_learning_clip_model_description": "请于 <link>此处</link>查看支持的 CLIP 模型名称。注意,更换模型后需要对所有图片重新运行“智能搜索”任务。",
"machine_learning_duplicate_detection": "重复项检测", "machine_learning_duplicate_detection": "重复项检测",
"machine_learning_duplicate_detection_enabled": "启用重复检测", "machine_learning_duplicate_detection_enabled": "启用重复检测",
"machine_learning_duplicate_detection_enabled_description": "如果禁用此功能,完全相同的项目仍将被去重。", "machine_learning_duplicate_detection_enabled_description": "如果禁用,完全相同的项目仍将被去重。",
"machine_learning_duplicate_detection_setting_description": "使用 CLIP 向量匹配(关键词相似度)来查找可能的重复项", "machine_learning_duplicate_detection_setting_description": "使用 CLIP 向量匹配(关键词相似度)来查找可能的重复项",
"machine_learning_enabled": "启用机器学习", "machine_learning_enabled": "启用机器学习",
"machine_learning_enabled_description": "如果禁用,无论以下如何设置,所有机器学习功能将被禁用。", "machine_learning_enabled_description": "如果禁用,无论以下如何设置,所有机器学习功能将被禁用。",
@@ -158,7 +158,7 @@
"map_enable_description": "启用地图功能", "map_enable_description": "启用地图功能",
"map_gps_settings": "地图与 GPS 设置", "map_gps_settings": "地图与 GPS 设置",
"map_gps_settings_description": "管理地图与 GPS反向地理编码设置", "map_gps_settings_description": "管理地图与 GPS反向地理编码设置",
"map_implications": "地图功能依赖于外部地形贴图服务tiles.immich.cloud", "map_implications": "地图功能依赖于外部地图瓦片服务tiles.immich.cloud",
"map_light_style": "浅色模式", "map_light_style": "浅色模式",
"map_manage_reverse_geocoding_settings": "管理<link>反向地理编码</link>设置", "map_manage_reverse_geocoding_settings": "管理<link>反向地理编码</link>设置",
"map_reverse_geocoding": "反向地理编码", "map_reverse_geocoding": "反向地理编码",
@@ -220,7 +220,7 @@
"oauth_enable_description": "使用 OAuth 登录", "oauth_enable_description": "使用 OAuth 登录",
"oauth_mobile_redirect_uri": "移动端重定向 URI", "oauth_mobile_redirect_uri": "移动端重定向 URI",
"oauth_mobile_redirect_uri_override": "移动端重定向 URI 覆盖", "oauth_mobile_redirect_uri_override": "移动端重定向 URI 覆盖",
"oauth_mobile_redirect_uri_override_description": "当 OAuth 提供商不允许使用移动 URI 时启用,如“''{callback}''”", "oauth_mobile_redirect_uri_override_description": "当 OAuth 提供商不允许使用移动 URI 时启用,如“{callback}”",
"oauth_role_claim": "角色声明", "oauth_role_claim": "角色声明",
"oauth_role_claim_description": "根据此声明的存在自动授予管理员访问权限。声明可以是“user”用户或“admin”管理员。", "oauth_role_claim_description": "根据此声明的存在自动授予管理员访问权限。声明可以是“user”用户或“admin”管理员。",
"oauth_settings": "OAuth", "oauth_settings": "OAuth",
@@ -364,7 +364,7 @@
"user_cleanup_job": "清理用户", "user_cleanup_job": "清理用户",
"user_delete_delay": "<b>{user}</b>的账户及项目将在{delay, plural, one {#天} other {#天}}后自动永久删除。", "user_delete_delay": "<b>{user}</b>的账户及项目将在{delay, plural, one {#天} other {#天}}后自动永久删除。",
"user_delete_delay_settings": "延期删除", "user_delete_delay_settings": "延期删除",
"user_delete_delay_settings_description": "永久删除账户及其所有项目之前所保留的天数。用户删除作业会在午夜检查是否有用户可以删除。对该设置的更改将在下次执行时生效。", "user_delete_delay_settings_description": "删除后永久删除用户帐户和资产的天数。用户删除作业会在午夜检查是否有用户可以删除。对该设置的更改将在下次执行时生效。",
"user_delete_immediately": "<b>{user}</b>的账户及项目将<b>立即</b>永久删除。", "user_delete_immediately": "<b>{user}</b>的账户及项目将<b>立即</b>永久删除。",
"user_delete_immediately_checkbox": "立即删除检索到的用户及项目", "user_delete_immediately_checkbox": "立即删除检索到的用户及项目",
"user_details": "用户详情", "user_details": "用户详情",
@@ -1640,7 +1640,7 @@
"restore_user": "恢复用户", "restore_user": "恢复用户",
"restored_asset": "已恢复项目", "restored_asset": "已恢复项目",
"resume": "继续", "resume": "继续",
"resume_paused_jobs": "继续 {count, plural, one {# 已暂停的作业} other {# 已暂停的作业}}", "resume_paused_jobs": "继续 {count, plural, one {# 已暂停的任务} other {# 已暂停的任务}}",
"retry_upload": "重新上传", "retry_upload": "重新上传",
"review_duplicates": "检查重复项", "review_duplicates": "检查重复项",
"review_large_files": "查看大文件", "review_large_files": "查看大文件",
@@ -1929,7 +1929,7 @@
"tag_updated": "已更新标签:{tag}", "tag_updated": "已更新标签:{tag}",
"tagged_assets": "{count, plural, one {# 个项目} other {# 个项目}}被加上标签", "tagged_assets": "{count, plural, one {# 个项目} other {# 个项目}}被加上标签",
"tags": "标签", "tags": "标签",
"tap_to_run_job": "点击运行作业", "tap_to_run_job": "点击运行任务",
"template": "模版", "template": "模版",
"theme": "主题", "theme": "主题",
"theme_selection": "主题选项", "theme_selection": "主题选项",

View File

@@ -22,7 +22,7 @@ FROM builder-cpu AS builder-rknn
# Warning: 25GiB+ disk space required to pull this image # Warning: 25GiB+ disk space required to pull this image
# TODO: find a way to reduce the image size # TODO: find a way to reduce the image size
FROM rocm/dev-ubuntu-22.04:6.3.4-complete@sha256:1f7e92ca7e3a3785680473329ed1091fc99db3e90fcb3a1688f2933e870ed76b AS builder-rocm FROM rocm/dev-ubuntu-22.04:6.4.3-complete@sha256:1f7e92ca7e3a3785680473329ed1091fc99db3e90fcb3a1688f2933e870ed76b AS builder-rocm
# renovate: datasource=github-releases depName=Microsoft/onnxruntime # renovate: datasource=github-releases depName=Microsoft/onnxruntime
ARG ONNXRUNTIME_VERSION="v1.20.1" ARG ONNXRUNTIME_VERSION="v1.20.1"
@@ -99,7 +99,7 @@ COPY --from=builder-cuda /usr/local/bin/python3 /usr/local/bin/python3
COPY --from=builder-cuda /usr/local/lib/python3.11 /usr/local/lib/python3.11 COPY --from=builder-cuda /usr/local/lib/python3.11 /usr/local/lib/python3.11
COPY --from=builder-cuda /usr/local/lib/libpython3.11.so /usr/local/lib/libpython3.11.so COPY --from=builder-cuda /usr/local/lib/libpython3.11.so /usr/local/lib/libpython3.11.so
FROM rocm/dev-ubuntu-22.04:6.3.4-complete@sha256:1f7e92ca7e3a3785680473329ed1091fc99db3e90fcb3a1688f2933e870ed76b AS prod-rocm FROM rocm/dev-ubuntu-22.04:6.4.3-complete@sha256:1f7e92ca7e3a3785680473329ed1091fc99db3e90fcb3a1688f2933e870ed76b AS prod-rocm
FROM prod-cpu AS prod-armnn FROM prod-cpu AS prod-armnn

View File

@@ -1,34 +0,0 @@
[tools.dart]
version = "3.8.2"
backend = "asdf:dart"
[tools.flutter]
version = "3.32.8-stable"
backend = "asdf:flutter"
[tools."github:CQLabs/homebrew-dcm"]
version = "1.31.4"
backend = "github:CQLabs/homebrew-dcm"
[tools."github:CQLabs/homebrew-dcm".platforms.linux-x64]
checksum = "blake3:e9df5b765df327e1248fccf2c6165a89d632a065667f99c01765bf3047b94955"
size = 8821083
url = "https://github.com/CQLabs/homebrew-dcm/releases/download/1.31.4/dcm-linux-x64-release.zip"
[tools.node]
version = "22.18.0"
backend = "core:node"
[tools.node.platforms.linux-x64]
checksum = "sha256:a2e703725d8683be86bb5da967bf8272f4518bdaf10f21389e2b2c9eaeae8c8a"
size = 54824343
url = "https://nodejs.org/dist/v22.18.0/node-v22.18.0-linux-x64.tar.gz"
[tools.pnpm]
version = "10.14.0"
backend = "aqua:pnpm/pnpm"
[tools.pnpm.platforms.linux-x64]
checksum = "blake3:13dfa46b7173d3cad3bad60a756a492ecf0bce48b23eb9f793e7ccec5a09b46d"
size = 66231525
url = "https://github.com/pnpm/pnpm/releases/download/v10.14.0/pnpm-linux-x64"

View File

@@ -1,7 +1,7 @@
[tools] [tools]
node = "22.19.0" node = "22.19.0"
flutter = "3.32.8" flutter = "3.35.4"
pnpm = "10.14.0" pnpm = "10.15.1"
dart = "3.8.2" dart = "3.8.2"
[tools."github:CQLabs/homebrew-dcm"] [tools."github:CQLabs/homebrew-dcm"]
@@ -11,7 +11,6 @@ postinstall = "chmod +x $MISE_TOOL_INSTALL_PATH/dcm"
[settings] [settings]
experimental = true experimental = true
lockfile = true
pin = true pin = true
# .github # .github
@@ -300,7 +299,7 @@ run = "tsc --noEmit"
depends = "web:svelte-kit-sync" depends = "web:svelte-kit-sync"
env._.path = "web/node_modules/.bin" env._.path = "web/node_modules/.bin"
dir = "web" dir = "web"
run = "svelte-check --no-tsconfig --fail-on-warnings --compiler-warnings 'reactive_declaration_non_reactive_property:ignore' --ignore src/lib/components/photos-page/asset-grid.svelte" run = "svelte-check --no-tsconfig --fail-on-warnings"
[tasks."web:checklist"] [tasks."web:checklist"]
run = [ run = [

View File

@@ -1,3 +1,3 @@
{ {
"flutter": "3.32.8" "flutter": "3.35.4"
} }

View File

@@ -1,8 +1,8 @@
{ {
"dart.flutterSdkPath": ".fvm/versions/3.32.8", "dart.flutterSdkPath": ".fvm/versions/3.35.4",
"dart.lineLength": 120, "dart.lineLength": 120,
"[dart]": { "[dart]": {
"editor.rulers": [120], "editor.rulers": [120]
}, },
"search.exclude": { "search.exclude": {
"**/.fvm": true "**/.fvm": true

View File

@@ -43,8 +43,9 @@ analyzer:
- lib/**/*.g.dart - lib/**/*.g.dart
- lib/**/*.drift.dart - lib/**/*.drift.dart
plugins: # TODO: Re-enable after upgrading custom_lint
- custom_lint # plugins:
# - custom_lint
custom_lint: custom_lint:
debug: true debug: true
@@ -134,6 +135,13 @@ custom_lint:
dart_code_metrics: dart_code_metrics:
rules: rules:
- banned-usage:
entries:
- name: debugPrint
description: Use dPrint instead of debugPrint for proper tree-shaking in release builds.
exclude-paths:
- 'lib/utils/debug_print.dart'
severity: perf
# All rules from "recommended" preset # All rules from "recommended" preset
# Show potential errors # Show potential errors
# - avoid-cascade-after-if-null # - avoid-cascade-after-if-null

View File

@@ -3,6 +3,7 @@ package app.alextran.immich
import android.app.Application import android.app.Application
import androidx.work.Configuration import androidx.work.Configuration
import androidx.work.WorkManager import androidx.work.WorkManager
import app.alextran.immich.background.BackgroundWorkerApiImpl
class ImmichApp : Application() { class ImmichApp : Application() {
override fun onCreate() { override fun onCreate() {
@@ -14,6 +15,8 @@ class ImmichApp : Application() {
// Thus, the BackupWorker is not started. If the system kills the process after each initialization // Thus, the BackupWorker is not started. If the system kills the process after each initialization
// (because of low memory etc.), the backup is never performed. // (because of low memory etc.), the backup is never performed.
// As a workaround, we also run a backup check when initializing the application // As a workaround, we also run a backup check when initializing the application
ContentObserverWorker.startBackupWorker(context = this, delayMilliseconds = 0) ContentObserverWorker.startBackupWorker(context = this, delayMilliseconds = 0)
BackgroundWorkerApiImpl.enqueueBackgroundWorker(this)
} }
} }

View File

@@ -3,6 +3,7 @@ package app.alextran.immich
import android.content.Context import android.content.Context
import android.os.Build import android.os.Build
import android.os.ext.SdkExtensions import android.os.ext.SdkExtensions
import app.alextran.immich.background.BackgroundEngineLock
import app.alextran.immich.background.BackgroundWorkerApiImpl import app.alextran.immich.background.BackgroundWorkerApiImpl
import app.alextran.immich.background.BackgroundWorkerFgHostApi import app.alextran.immich.background.BackgroundWorkerFgHostApi
import app.alextran.immich.connectivity.ConnectivityApi import app.alextran.immich.connectivity.ConnectivityApi
@@ -25,6 +26,7 @@ class MainActivity : FlutterFragmentActivity() {
fun registerPlugins(ctx: Context, flutterEngine: FlutterEngine) { fun registerPlugins(ctx: Context, flutterEngine: FlutterEngine) {
flutterEngine.plugins.add(BackgroundServicePlugin()) flutterEngine.plugins.add(BackgroundServicePlugin())
flutterEngine.plugins.add(HttpSSLOptionsPlugin()) flutterEngine.plugins.add(HttpSSLOptionsPlugin())
flutterEngine.plugins.add(BackgroundEngineLock())
val messenger = flutterEngine.dartExecutor.binaryMessenger val messenger = flutterEngine.dartExecutor.binaryMessenger
val nativeSyncApiImpl = val nativeSyncApiImpl =

View File

@@ -0,0 +1,33 @@
package app.alextran.immich.background
import android.util.Log
import androidx.work.WorkManager
import io.flutter.embedding.engine.FlutterEngineCache
import io.flutter.embedding.engine.plugins.FlutterPlugin
import java.util.concurrent.atomic.AtomicInteger
private const val TAG = "BackgroundEngineLock"
class BackgroundEngineLock : FlutterPlugin {
companion object {
const val ENGINE_CACHE_KEY = "immich::background_worker::engine"
var engineCount = AtomicInteger(0)
}
override fun onAttachedToEngine(binding: FlutterPlugin.FlutterPluginBinding) {
// work manager task is running while the main app is opened, cancel the worker
if (engineCount.incrementAndGet() > 1 && FlutterEngineCache.getInstance()
.get(ENGINE_CACHE_KEY) != null
) {
WorkManager.getInstance(binding.applicationContext)
.cancelUniqueWork(BackgroundWorkerApiImpl.BACKGROUND_WORKER_NAME)
FlutterEngineCache.getInstance().remove(ENGINE_CACHE_KEY)
}
Log.i(TAG, "Flutter engine attached. Attached Engines count: $engineCount")
}
override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) {
engineCount.decrementAndGet()
Log.i(TAG, "Flutter engine detached. Attached Engines count: $engineCount")
}
}

View File

@@ -37,6 +37,36 @@ private object BackgroundWorkerPigeonUtils {
) )
} }
} }
fun deepEquals(a: Any?, b: Any?): Boolean {
if (a is ByteArray && b is ByteArray) {
return a.contentEquals(b)
}
if (a is IntArray && b is IntArray) {
return a.contentEquals(b)
}
if (a is LongArray && b is LongArray) {
return a.contentEquals(b)
}
if (a is DoubleArray && b is DoubleArray) {
return a.contentEquals(b)
}
if (a is Array<*> && b is Array<*>) {
return a.size == b.size &&
a.indices.all{ deepEquals(a[it], b[it]) }
}
if (a is List<*> && b is List<*>) {
return a.size == b.size &&
a.indices.all{ deepEquals(a[it], b[it]) }
}
if (a is Map<*, *> && b is Map<*, *>) {
return a.size == b.size && a.all {
(b as Map<Any?, Any?>).containsKey(it.key) &&
deepEquals(it.value, b[it.key])
}
}
return a == b
}
} }
/** /**
@@ -50,18 +80,63 @@ class FlutterError (
override val message: String? = null, override val message: String? = null,
val details: Any? = null val details: Any? = null
) : Throwable() ) : Throwable()
/** Generated class from Pigeon that represents data sent in messages. */
data class BackgroundWorkerSettings (
val requiresCharging: Boolean,
val minimumDelaySeconds: Long
)
{
companion object {
fun fromList(pigeonVar_list: List<Any?>): BackgroundWorkerSettings {
val requiresCharging = pigeonVar_list[0] as Boolean
val minimumDelaySeconds = pigeonVar_list[1] as Long
return BackgroundWorkerSettings(requiresCharging, minimumDelaySeconds)
}
}
fun toList(): List<Any?> {
return listOf(
requiresCharging,
minimumDelaySeconds,
)
}
override fun equals(other: Any?): Boolean {
if (other !is BackgroundWorkerSettings) {
return false
}
if (this === other) {
return true
}
return BackgroundWorkerPigeonUtils.deepEquals(toList(), other.toList()) }
override fun hashCode(): Int = toList().hashCode()
}
private open class BackgroundWorkerPigeonCodec : StandardMessageCodec() { private open class BackgroundWorkerPigeonCodec : StandardMessageCodec() {
override fun readValueOfType(type: Byte, buffer: ByteBuffer): Any? { override fun readValueOfType(type: Byte, buffer: ByteBuffer): Any? {
return super.readValueOfType(type, buffer) return when (type) {
129.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
BackgroundWorkerSettings.fromList(it)
}
}
else -> super.readValueOfType(type, buffer)
}
} }
override fun writeValue(stream: ByteArrayOutputStream, value: Any?) { override fun writeValue(stream: ByteArrayOutputStream, value: Any?) {
super.writeValue(stream, value) when (value) {
is BackgroundWorkerSettings -> {
stream.write(129)
writeValue(stream, value.toList())
}
else -> super.writeValue(stream, value)
}
} }
} }
/** Generated interface from Pigeon that represents a handler of messages from Flutter. */ /** Generated interface from Pigeon that represents a handler of messages from Flutter. */
interface BackgroundWorkerFgHostApi { interface BackgroundWorkerFgHostApi {
fun enable() fun enable()
fun configure(settings: BackgroundWorkerSettings)
fun disable() fun disable()
companion object { companion object {
@@ -89,6 +164,24 @@ interface BackgroundWorkerFgHostApi {
channel.setMessageHandler(null) channel.setMessageHandler(null)
} }
} }
run {
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.immich_mobile.BackgroundWorkerFgHostApi.configure$separatedMessageChannelSuffix", codec)
if (api != null) {
channel.setMessageHandler { message, reply ->
val args = message as List<Any?>
val settingsArg = args[0] as BackgroundWorkerSettings
val wrapped: List<Any?> = try {
api.configure(settingsArg)
listOf(null)
} catch (exception: Throwable) {
BackgroundWorkerPigeonUtils.wrapError(exception)
}
reply.reply(wrapped)
}
} else {
channel.setMessageHandler(null)
}
}
run { run {
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.immich_mobile.BackgroundWorkerFgHostApi.disable$separatedMessageChannelSuffix", codec) val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.immich_mobile.BackgroundWorkerFgHostApi.disable$separatedMessageChannelSuffix", codec)
if (api != null) { if (api != null) {

View File

@@ -19,6 +19,7 @@ import com.google.common.util.concurrent.ListenableFuture
import com.google.common.util.concurrent.SettableFuture import com.google.common.util.concurrent.SettableFuture
import io.flutter.FlutterInjector import io.flutter.FlutterInjector
import io.flutter.embedding.engine.FlutterEngine import io.flutter.embedding.engine.FlutterEngine
import io.flutter.embedding.engine.FlutterEngineCache
import io.flutter.embedding.engine.dart.DartExecutor import io.flutter.embedding.engine.dart.DartExecutor
import io.flutter.embedding.engine.loader.FlutterLoader import io.flutter.embedding.engine.loader.FlutterLoader
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
@@ -54,12 +55,6 @@ class BackgroundWorker(context: Context, params: WorkerParameters) :
private var foregroundFuture: ListenableFuture<Void>? = null private var foregroundFuture: ListenableFuture<Void>? = null
init {
if (!loader.initialized()) {
loader.startInitialization(ctx)
}
}
companion object { companion object {
private const val NOTIFICATION_CHANNEL_ID = "immich::background_worker::notif" private const val NOTIFICATION_CHANNEL_ID = "immich::background_worker::notif"
private const val NOTIFICATION_ID = 100 private const val NOTIFICATION_ID = 100
@@ -68,6 +63,10 @@ class BackgroundWorker(context: Context, params: WorkerParameters) :
override fun startWork(): ListenableFuture<Result> { override fun startWork(): ListenableFuture<Result> {
Log.i(TAG, "Starting background upload worker") Log.i(TAG, "Starting background upload worker")
if (!loader.initialized()) {
loader.startInitialization(ctx)
}
val notificationChannel = NotificationChannel( val notificationChannel = NotificationChannel(
NOTIFICATION_CHANNEL_ID, NOTIFICATION_CHANNEL_ID,
NOTIFICATION_CHANNEL_ID, NOTIFICATION_CHANNEL_ID,
@@ -77,6 +76,9 @@ class BackgroundWorker(context: Context, params: WorkerParameters) :
loader.ensureInitializationCompleteAsync(ctx, null, Handler(Looper.getMainLooper())) { loader.ensureInitializationCompleteAsync(ctx, null, Handler(Looper.getMainLooper())) {
engine = FlutterEngine(ctx) engine = FlutterEngine(ctx)
FlutterEngineCache.getInstance().remove(BackgroundEngineLock.ENGINE_CACHE_KEY);
FlutterEngineCache.getInstance()
.put(BackgroundEngineLock.ENGINE_CACHE_KEY, engine!!)
// Register custom plugins // Register custom plugins
MainActivity.registerPlugins(ctx, engine!!) MainActivity.registerPlugins(ctx, engine!!)
@@ -190,6 +192,7 @@ class BackgroundWorker(context: Context, params: WorkerParameters) :
isComplete = true isComplete = true
engine?.destroy() engine?.destroy()
engine = null engine = null
FlutterEngineCache.getInstance().remove(BackgroundEngineLock.ENGINE_CACHE_KEY);
flutterApi = null flutterApi = null
notificationManager.cancel(NOTIFICATION_ID) notificationManager.cancel(NOTIFICATION_ID)
waitForForegroundPromotion() waitForForegroundPromotion()

View File

@@ -1,6 +1,7 @@
package app.alextran.immich.background package app.alextran.immich.background
import android.content.Context import android.content.Context
import android.content.SharedPreferences
import android.provider.MediaStore import android.provider.MediaStore
import android.util.Log import android.util.Log
import androidx.work.BackoffPolicy import androidx.work.BackoffPolicy
@@ -10,7 +11,7 @@ import androidx.work.OneTimeWorkRequest
import androidx.work.WorkManager import androidx.work.WorkManager
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
private const val TAG = "BackgroundUploadImpl" private const val TAG = "BackgroundWorkerApiImpl"
class BackgroundWorkerApiImpl(context: Context) : BackgroundWorkerFgHostApi { class BackgroundWorkerApiImpl(context: Context) : BackgroundWorkerFgHostApi {
private val ctx: Context = context.applicationContext private val ctx: Context = context.applicationContext
@@ -19,25 +20,34 @@ class BackgroundWorkerApiImpl(context: Context) : BackgroundWorkerFgHostApi {
enqueueMediaObserver(ctx) enqueueMediaObserver(ctx)
} }
override fun configure(settings: BackgroundWorkerSettings) {
BackgroundWorkerPreferences(ctx).updateSettings(settings)
enqueueMediaObserver(ctx)
}
override fun disable() { override fun disable() {
WorkManager.getInstance(ctx).cancelUniqueWork(OBSERVER_WORKER_NAME) WorkManager.getInstance(ctx).apply {
WorkManager.getInstance(ctx).cancelUniqueWork(BACKGROUND_WORKER_NAME) cancelUniqueWork(OBSERVER_WORKER_NAME)
cancelUniqueWork(BACKGROUND_WORKER_NAME)
}
Log.i(TAG, "Cancelled background upload tasks") Log.i(TAG, "Cancelled background upload tasks")
} }
companion object { companion object {
private const val BACKGROUND_WORKER_NAME = "immich/BackgroundWorkerV1" const val BACKGROUND_WORKER_NAME = "immich/BackgroundWorkerV1"
private const val OBSERVER_WORKER_NAME = "immich/MediaObserverV1" private const val OBSERVER_WORKER_NAME = "immich/MediaObserverV1"
fun enqueueMediaObserver(ctx: Context) { fun enqueueMediaObserver(ctx: Context) {
val constraints = Constraints.Builder() val settings = BackgroundWorkerPreferences(ctx).getSettings()
.addContentUriTrigger(MediaStore.Images.Media.INTERNAL_CONTENT_URI, true) val constraints = Constraints.Builder().apply {
.addContentUriTrigger(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, true) addContentUriTrigger(MediaStore.Images.Media.INTERNAL_CONTENT_URI, true)
.addContentUriTrigger(MediaStore.Video.Media.INTERNAL_CONTENT_URI, true) addContentUriTrigger(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, true)
.addContentUriTrigger(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, true) addContentUriTrigger(MediaStore.Video.Media.INTERNAL_CONTENT_URI, true)
.setTriggerContentUpdateDelay(30, TimeUnit.SECONDS) addContentUriTrigger(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, true)
.setTriggerContentMaxDelay(3, TimeUnit.MINUTES) setTriggerContentUpdateDelay(settings.minimumDelaySeconds, TimeUnit.SECONDS)
.build() setTriggerContentMaxDelay(settings.minimumDelaySeconds * 10, TimeUnit.MINUTES)
setRequiresCharging(settings.requiresCharging)
}.build()
val work = OneTimeWorkRequest.Builder(MediaObserver::class.java) val work = OneTimeWorkRequest.Builder(MediaObserver::class.java)
.setConstraints(constraints) .setConstraints(constraints)
@@ -45,7 +55,10 @@ class BackgroundWorkerApiImpl(context: Context) : BackgroundWorkerFgHostApi {
WorkManager.getInstance(ctx) WorkManager.getInstance(ctx)
.enqueueUniqueWork(OBSERVER_WORKER_NAME, ExistingWorkPolicy.REPLACE, work) .enqueueUniqueWork(OBSERVER_WORKER_NAME, ExistingWorkPolicy.REPLACE, work)
Log.i(TAG, "Enqueued media observer worker with name: $OBSERVER_WORKER_NAME") Log.i(
TAG,
"Enqueued media observer worker with name: $OBSERVER_WORKER_NAME and settings: $settings"
)
} }
fun enqueueBackgroundWorker(ctx: Context) { fun enqueueBackgroundWorker(ctx: Context) {
@@ -56,9 +69,39 @@ class BackgroundWorkerApiImpl(context: Context) : BackgroundWorkerFgHostApi {
.setBackoffCriteria(BackoffPolicy.EXPONENTIAL, 1, TimeUnit.MINUTES) .setBackoffCriteria(BackoffPolicy.EXPONENTIAL, 1, TimeUnit.MINUTES)
.build() .build()
WorkManager.getInstance(ctx) WorkManager.getInstance(ctx)
.enqueueUniqueWork(BACKGROUND_WORKER_NAME, ExistingWorkPolicy.REPLACE, work) .enqueueUniqueWork(BACKGROUND_WORKER_NAME, ExistingWorkPolicy.KEEP, work)
Log.i(TAG, "Enqueued background worker with name: $BACKGROUND_WORKER_NAME") Log.i(TAG, "Enqueued background worker with name: $BACKGROUND_WORKER_NAME")
} }
} }
} }
private class BackgroundWorkerPreferences(private val ctx: Context) {
companion object {
private const val SHARED_PREF_NAME = "Immich::BackgroundWorker"
private const val SHARED_PREF_MIN_DELAY_KEY = "BackgroundWorker::minDelaySeconds"
private const val SHARED_PREF_REQUIRE_CHARGING_KEY = "BackgroundWorker::requireCharging"
private const val DEFAULT_MIN_DELAY_SECONDS = 30L
private const val DEFAULT_REQUIRE_CHARGING = false
}
private val sp: SharedPreferences by lazy {
ctx.getSharedPreferences(SHARED_PREF_NAME, Context.MODE_PRIVATE)
}
fun updateSettings(settings: BackgroundWorkerSettings) {
sp.edit().apply {
putLong(SHARED_PREF_MIN_DELAY_KEY, settings.minimumDelaySeconds)
putBoolean(SHARED_PREF_REQUIRE_CHARGING_KEY, settings.requiresCharging)
apply()
}
}
fun getSettings(): BackgroundWorkerSettings {
return BackgroundWorkerSettings(
minimumDelaySeconds = sp.getLong(SHARED_PREF_MIN_DELAY_KEY, DEFAULT_MIN_DELAY_SECONDS),
requiresCharging = sp.getBoolean(SHARED_PREF_REQUIRE_CHARGING_KEY, DEFAULT_REQUIRE_CHARGING),
)
}
}

View File

@@ -8,7 +8,6 @@ import android.net.Uri
import android.os.Build import android.os.Build
import android.os.CancellationSignal import android.os.CancellationSignal
import android.os.OperationCanceledException import android.os.OperationCanceledException
import android.provider.MediaStore
import android.provider.MediaStore.Images import android.provider.MediaStore.Images
import android.provider.MediaStore.Video import android.provider.MediaStore.Video
import android.util.Size import android.util.Size
@@ -19,7 +18,6 @@ import com.bumptech.glide.Glide
import com.bumptech.glide.Priority import com.bumptech.glide.Priority
import com.bumptech.glide.load.DecodeFormat import com.bumptech.glide.load.DecodeFormat
import java.util.Base64 import java.util.Base64
import java.util.HashMap
import java.util.concurrent.CancellationException import java.util.concurrent.CancellationException
import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.ConcurrentHashMap
import java.util.concurrent.Future import java.util.concurrent.Future
@@ -202,8 +200,10 @@ class ThumbnailsImpl(context: Context) : ThumbnailApi {
val source = ImageDecoder.createSource(resolver, uri) val source = ImageDecoder.createSource(resolver, uri)
signal.throwIfCanceled() signal.throwIfCanceled()
ImageDecoder.decodeBitmap(source) { decoder, info, _ -> ImageDecoder.decodeBitmap(source) { decoder, info, _ ->
val sampleSize = max(1, min(info.size.width / targetWidth, info.size.height / targetHeight)) if (targetWidth > 0 && targetHeight > 0) {
decoder.setTargetSampleSize(sampleSize) val sample = max(1, min(info.size.width / targetWidth, info.size.height / targetHeight))
decoder.setTargetSampleSize(sample)
}
decoder.allocator = ImageDecoder.ALLOCATOR_SOFTWARE decoder.allocator = ImageDecoder.ALLOCATOR_SOFTWARE
decoder.setTargetColorSpace(ColorSpace.get(ColorSpace.Named.SRGB)) decoder.setTargetColorSpace(ColorSpace.get(ColorSpace.Named.SRGB))
} }

View File

@@ -209,6 +209,40 @@ data class SyncDelta (
override fun hashCode(): Int = toList().hashCode() override fun hashCode(): Int = toList().hashCode()
} }
/** Generated class from Pigeon that represents data sent in messages. */
data class HashResult (
val assetId: String,
val error: String? = null,
val hash: String? = null
)
{
companion object {
fun fromList(pigeonVar_list: List<Any?>): HashResult {
val assetId = pigeonVar_list[0] as String
val error = pigeonVar_list[1] as String?
val hash = pigeonVar_list[2] as String?
return HashResult(assetId, error, hash)
}
}
fun toList(): List<Any?> {
return listOf(
assetId,
error,
hash,
)
}
override fun equals(other: Any?): Boolean {
if (other !is HashResult) {
return false
}
if (this === other) {
return true
}
return MessagesPigeonUtils.deepEquals(toList(), other.toList()) }
override fun hashCode(): Int = toList().hashCode()
}
private open class MessagesPigeonCodec : StandardMessageCodec() { private open class MessagesPigeonCodec : StandardMessageCodec() {
override fun readValueOfType(type: Byte, buffer: ByteBuffer): Any? { override fun readValueOfType(type: Byte, buffer: ByteBuffer): Any? {
return when (type) { return when (type) {
@@ -227,6 +261,11 @@ private open class MessagesPigeonCodec : StandardMessageCodec() {
SyncDelta.fromList(it) SyncDelta.fromList(it)
} }
} }
132.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
HashResult.fromList(it)
}
}
else -> super.readValueOfType(type, buffer) else -> super.readValueOfType(type, buffer)
} }
} }
@@ -244,11 +283,16 @@ private open class MessagesPigeonCodec : StandardMessageCodec() {
stream.write(131) stream.write(131)
writeValue(stream, value.toList()) writeValue(stream, value.toList())
} }
is HashResult -> {
stream.write(132)
writeValue(stream, value.toList())
}
else -> super.writeValue(stream, value) else -> super.writeValue(stream, value)
} }
} }
} }
/** Generated interface from Pigeon that represents a handler of messages from Flutter. */ /** Generated interface from Pigeon that represents a handler of messages from Flutter. */
interface NativeSyncApi { interface NativeSyncApi {
fun shouldFullSync(): Boolean fun shouldFullSync(): Boolean
@@ -259,7 +303,8 @@ interface NativeSyncApi {
fun getAlbums(): List<PlatformAlbum> fun getAlbums(): List<PlatformAlbum>
fun getAssetsCountSince(albumId: String, timestamp: Long): Long fun getAssetsCountSince(albumId: String, timestamp: Long): Long
fun getAssetsForAlbum(albumId: String, updatedTimeCond: Long?): List<PlatformAsset> fun getAssetsForAlbum(albumId: String, updatedTimeCond: Long?): List<PlatformAsset>
fun hashPaths(paths: List<String>): List<ByteArray?> fun hashAssets(assetIds: List<String>, allowNetworkAccess: Boolean, callback: (Result<List<HashResult>>) -> Unit)
fun cancelHashing()
companion object { companion object {
/** The codec used by NativeSyncApi. */ /** The codec used by NativeSyncApi. */
@@ -402,13 +447,33 @@ interface NativeSyncApi {
} }
} }
run { run {
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.immich_mobile.NativeSyncApi.hashPaths$separatedMessageChannelSuffix", codec, taskQueue) val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.immich_mobile.NativeSyncApi.hashAssets$separatedMessageChannelSuffix", codec, taskQueue)
if (api != null) { if (api != null) {
channel.setMessageHandler { message, reply -> channel.setMessageHandler { message, reply ->
val args = message as List<Any?> val args = message as List<Any?>
val pathsArg = args[0] as List<String> val assetIdsArg = args[0] as List<String>
val allowNetworkAccessArg = args[1] as Boolean
api.hashAssets(assetIdsArg, allowNetworkAccessArg) { result: Result<List<HashResult>> ->
val error = result.exceptionOrNull()
if (error != null) {
reply.reply(MessagesPigeonUtils.wrapError(error))
} else {
val data = result.getOrNull()
reply.reply(MessagesPigeonUtils.wrapResult(data))
}
}
}
} else {
channel.setMessageHandler(null)
}
}
run {
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.immich_mobile.NativeSyncApi.cancelHashing$separatedMessageChannelSuffix", codec)
if (api != null) {
channel.setMessageHandler { _, reply ->
val wrapped: List<Any?> = try { val wrapped: List<Any?> = try {
listOf(api.hashPaths(pathsArg)) api.cancelHashing()
listOf(null)
} catch (exception: Throwable) { } catch (exception: Throwable) {
MessagesPigeonUtils.wrapError(exception) MessagesPigeonUtils.wrapError(exception)
} }

View File

@@ -1,14 +1,25 @@
package app.alextran.immich.sync package app.alextran.immich.sync
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.content.ContentUris
import android.content.Context import android.content.Context
import android.database.Cursor import android.database.Cursor
import android.provider.MediaStore import android.provider.MediaStore
import android.util.Log import android.util.Base64
import androidx.core.database.getStringOrNull import androidx.core.database.getStringOrNull
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.ensureActive
import kotlinx.coroutines.launch
import kotlinx.coroutines.sync.Semaphore
import kotlinx.coroutines.sync.withPermit
import java.io.File import java.io.File
import java.io.FileInputStream
import java.security.MessageDigest import java.security.MessageDigest
import kotlin.coroutines.cancellation.CancellationException
import kotlin.coroutines.coroutineContext
sealed class AssetResult { sealed class AssetResult {
data class ValidAsset(val asset: PlatformAsset, val albumId: String) : AssetResult() data class ValidAsset(val asset: PlatformAsset, val albumId: String) : AssetResult()
@@ -19,8 +30,12 @@ sealed class AssetResult {
open class NativeSyncApiImplBase(context: Context) { open class NativeSyncApiImplBase(context: Context) {
private val ctx: Context = context.applicationContext private val ctx: Context = context.applicationContext
private var hashTask: Job? = null
companion object { companion object {
private const val TAG = "NativeSyncApiImplBase" private const val MAX_CONCURRENT_HASH_OPERATIONS = 16
private val hashSemaphore = Semaphore(MAX_CONCURRENT_HASH_OPERATIONS)
private const val HASHING_CANCELLED_CODE = "HASH_CANCELLED"
const val MEDIA_SELECTION = const val MEDIA_SELECTION =
"(${MediaStore.Files.FileColumns.MEDIA_TYPE} = ? OR ${MediaStore.Files.FileColumns.MEDIA_TYPE} = ?)" "(${MediaStore.Files.FileColumns.MEDIA_TYPE} = ? OR ${MediaStore.Files.FileColumns.MEDIA_TYPE} = ?)"
@@ -215,23 +230,74 @@ open class NativeSyncApiImplBase(context: Context) {
.toList() .toList()
} }
fun hashPaths(paths: List<String>): List<ByteArray?> { fun hashAssets(
val buffer = ByteArray(HASH_BUFFER_SIZE) assetIds: List<String>,
val digest = MessageDigest.getInstance("SHA-1") // allowNetworkAccess is only used on the iOS implementation
@Suppress("UNUSED_PARAMETER") allowNetworkAccess: Boolean,
callback: (Result<List<HashResult>>) -> Unit
) {
if (assetIds.isEmpty()) {
callback(Result.success(emptyList()))
return
}
return paths.map { path -> hashTask?.cancel()
hashTask = CoroutineScope(Dispatchers.IO).launch {
try { try {
FileInputStream(path).use { file -> val results = assetIds.map { assetId ->
var bytesRead: Int async {
while (file.read(buffer).also { bytesRead = it } > 0) { hashSemaphore.withPermit {
digest.update(buffer, 0, bytesRead) ensureActive()
hashAsset(assetId)
}
} }
} }.awaitAll()
digest.digest()
callback(Result.success(results))
} catch (e: CancellationException) {
callback(
Result.failure(
FlutterError(
HASHING_CANCELLED_CODE,
"Hashing operation was cancelled",
null
)
)
)
} catch (e: Exception) { } catch (e: Exception) {
Log.w(TAG, "Failed to hash file $path: $e") callback(Result.failure(e))
null
} }
} }
} }
private suspend fun hashAsset(assetId: String): HashResult {
return try {
val assetUri = ContentUris.withAppendedId(
MediaStore.Files.getContentUri(MediaStore.VOLUME_EXTERNAL),
assetId.toLong()
)
val digest = MessageDigest.getInstance("SHA-1")
ctx.contentResolver.openInputStream(assetUri)?.use { inputStream ->
var bytesRead: Int
val buffer = ByteArray(HASH_BUFFER_SIZE)
while (inputStream.read(buffer).also { bytesRead = it } > 0) {
coroutineContext.ensureActive()
digest.update(buffer, 0, bytesRead)
}
} ?: return HashResult(assetId, "Cannot open input stream for asset", null)
val hashString = Base64.encodeToString(digest.digest(), Base64.NO_WRAP)
HashResult(assetId, null, hashString)
} catch (e: SecurityException) {
HashResult(assetId, "Permission denied accessing asset: ${e.message}", null)
} catch (e: Exception) {
HashResult(assetId, "Failed to hash asset: ${e.message}", null)
}
}
fun cancelHashing() {
hashTask?.cancel()
hashTask = null
}
} }

View File

@@ -35,8 +35,8 @@ platform :android do
task: 'bundle', task: 'bundle',
build_type: 'Release', build_type: 'Release',
properties: { properties: {
"android.injected.version.code" => 3013, "android.injected.version.code" => 3015,
"android.injected.version.name" => "1.141.1", "android.injected.version.name" => "1.142.1",
} }
) )
upload_to_play_store(skip_upload_apk: true, skip_upload_images: true, skip_upload_screenshots: true, aab: '../build/app/outputs/bundle/release/app-release.aab') upload_to_play_store(skip_upload_apk: true, skip_upload_images: true, skip_upload_screenshots: true, aab: '../build/app/outputs/bundle/release/app-release.aab')

File diff suppressed because one or more lines are too long

View File

@@ -4,7 +4,6 @@
*.moved-aside *.moved-aside
*.pbxuser *.pbxuser
*.perspectivev3 *.perspectivev3
**/*sync/
.sconsign.dblite .sconsign.dblite
.tags* .tags*
**/.vagrant/ **/.vagrant/

View File

@@ -21,6 +21,6 @@
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>1.0</string> <string>1.0</string>
<key>MinimumOSVersion</key> <key>MinimumOSVersion</key>
<string>12.0</string> <string>13.0</string>
</dict> </dict>
</plist> </plist>

View File

@@ -253,7 +253,7 @@ SPEC CHECKSUMS:
DKImagePickerController: 946cec48c7873164274ecc4624d19e3da4c1ef3c DKImagePickerController: 946cec48c7873164274ecc4624d19e3da4c1ef3c
DKPhotoGallery: b3834fecb755ee09a593d7c9e389d8b5d6deed60 DKPhotoGallery: b3834fecb755ee09a593d7c9e389d8b5d6deed60
file_picker: a0560bc09d61de87f12d246fc47d2119e6ef37be file_picker: a0560bc09d61de87f12d246fc47d2119e6ef37be
Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7 Flutter: cabc95a1d2626b1b06e7179b784ebcf0c0cde467
flutter_local_notifications: ad39620c743ea4c15127860f4b5641649a988100 flutter_local_notifications: ad39620c743ea4c15127860f4b5641649a988100
flutter_native_splash: c32d145d68aeda5502d5f543ee38c192065986cf flutter_native_splash: c32d145d68aeda5502d5f543ee38c192065986cf
flutter_secure_storage: 1ed9476fba7e7a782b22888f956cce43e2c62f13 flutter_secure_storage: 1ed9476fba7e7a782b22888f956cce43e2c62f13

View File

@@ -3,7 +3,7 @@
archiveVersion = 1; archiveVersion = 1;
classes = { classes = {
}; };
objectVersion = 77; objectVersion = 54;
objects = { objects = {
/* Begin PBXBuildFile section */ /* Begin PBXBuildFile section */
@@ -133,6 +133,8 @@
/* Begin PBXFileSystemSynchronizedRootGroup section */ /* Begin PBXFileSystemSynchronizedRootGroup section */
B2CF7F8C2DDE4EBB00744BF6 /* Sync */ = { B2CF7F8C2DDE4EBB00744BF6 /* Sync */ = {
isa = PBXFileSystemSynchronizedRootGroup; isa = PBXFileSystemSynchronizedRootGroup;
exceptions = (
);
path = Sync; path = Sync;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
@@ -519,14 +521,10 @@
inputFileListPaths = ( inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-input-files.xcfilelist", "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-input-files.xcfilelist",
); );
inputPaths = (
);
name = "[CP] Copy Pods Resources"; name = "[CP] Copy Pods Resources";
outputFileListPaths = ( outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-output-files.xcfilelist", "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-output-files.xcfilelist",
); );
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh; shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n"; shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n";
@@ -555,14 +553,10 @@
inputFileListPaths = ( inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
); );
inputPaths = (
);
name = "[CP] Embed Pods Frameworks"; name = "[CP] Embed Pods Frameworks";
outputFileListPaths = ( outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
); );
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh; shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
@@ -711,7 +705,7 @@
CODE_SIGN_ENTITLEMENTS = Runner/RunnerProfile.entitlements; CODE_SIGN_ENTITLEMENTS = Runner/RunnerProfile.entitlements;
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 219; CURRENT_PROJECT_VERSION = 224;
CUSTOM_GROUP_ID = group.app.immich.share; CUSTOM_GROUP_ID = group.app.immich.share;
DEVELOPMENT_TEAM = 2F67MQ8R79; DEVELOPMENT_TEAM = 2F67MQ8R79;
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
@@ -855,7 +849,7 @@
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 219; CURRENT_PROJECT_VERSION = 224;
CUSTOM_GROUP_ID = group.app.immich.share; CUSTOM_GROUP_ID = group.app.immich.share;
DEVELOPMENT_TEAM = 2F67MQ8R79; DEVELOPMENT_TEAM = 2F67MQ8R79;
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
@@ -885,7 +879,7 @@
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 219; CURRENT_PROJECT_VERSION = 224;
CUSTOM_GROUP_ID = group.app.immich.share; CUSTOM_GROUP_ID = group.app.immich.share;
DEVELOPMENT_TEAM = 2F67MQ8R79; DEVELOPMENT_TEAM = 2F67MQ8R79;
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
@@ -919,7 +913,7 @@
CODE_SIGN_ENTITLEMENTS = WidgetExtension/WidgetExtension.entitlements; CODE_SIGN_ENTITLEMENTS = WidgetExtension/WidgetExtension.entitlements;
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 219; CURRENT_PROJECT_VERSION = 224;
DEVELOPMENT_TEAM = 2F67MQ8R79; DEVELOPMENT_TEAM = 2F67MQ8R79;
ENABLE_USER_SCRIPT_SANDBOXING = YES; ENABLE_USER_SCRIPT_SANDBOXING = YES;
GCC_C_LANGUAGE_STANDARD = gnu17; GCC_C_LANGUAGE_STANDARD = gnu17;
@@ -962,7 +956,7 @@
CODE_SIGN_ENTITLEMENTS = WidgetExtension/WidgetExtension.entitlements; CODE_SIGN_ENTITLEMENTS = WidgetExtension/WidgetExtension.entitlements;
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 219; CURRENT_PROJECT_VERSION = 224;
DEVELOPMENT_TEAM = 2F67MQ8R79; DEVELOPMENT_TEAM = 2F67MQ8R79;
ENABLE_USER_SCRIPT_SANDBOXING = YES; ENABLE_USER_SCRIPT_SANDBOXING = YES;
GCC_C_LANGUAGE_STANDARD = gnu17; GCC_C_LANGUAGE_STANDARD = gnu17;
@@ -1002,7 +996,7 @@
CODE_SIGN_ENTITLEMENTS = WidgetExtension/WidgetExtension.entitlements; CODE_SIGN_ENTITLEMENTS = WidgetExtension/WidgetExtension.entitlements;
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 219; CURRENT_PROJECT_VERSION = 224;
DEVELOPMENT_TEAM = 2F67MQ8R79; DEVELOPMENT_TEAM = 2F67MQ8R79;
ENABLE_USER_SCRIPT_SANDBOXING = YES; ENABLE_USER_SCRIPT_SANDBOXING = YES;
GCC_C_LANGUAGE_STANDARD = gnu17; GCC_C_LANGUAGE_STANDARD = gnu17;
@@ -1041,7 +1035,7 @@
CODE_SIGN_ENTITLEMENTS = ShareExtension/ShareExtension.entitlements; CODE_SIGN_ENTITLEMENTS = ShareExtension/ShareExtension.entitlements;
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 219; CURRENT_PROJECT_VERSION = 224;
CUSTOM_GROUP_ID = group.app.immich.share; CUSTOM_GROUP_ID = group.app.immich.share;
DEVELOPMENT_TEAM = 2F67MQ8R79; DEVELOPMENT_TEAM = 2F67MQ8R79;
ENABLE_USER_SCRIPT_SANDBOXING = YES; ENABLE_USER_SCRIPT_SANDBOXING = YES;
@@ -1085,7 +1079,7 @@
CODE_SIGN_ENTITLEMENTS = ShareExtension/ShareExtension.entitlements; CODE_SIGN_ENTITLEMENTS = ShareExtension/ShareExtension.entitlements;
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 219; CURRENT_PROJECT_VERSION = 224;
CUSTOM_GROUP_ID = group.app.immich.share; CUSTOM_GROUP_ID = group.app.immich.share;
DEVELOPMENT_TEAM = 2F67MQ8R79; DEVELOPMENT_TEAM = 2F67MQ8R79;
ENABLE_USER_SCRIPT_SANDBOXING = YES; ENABLE_USER_SCRIPT_SANDBOXING = YES;
@@ -1126,7 +1120,7 @@
CODE_SIGN_ENTITLEMENTS = ShareExtension/ShareExtension.entitlements; CODE_SIGN_ENTITLEMENTS = ShareExtension/ShareExtension.entitlements;
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 219; CURRENT_PROJECT_VERSION = 224;
CUSTOM_GROUP_ID = group.app.immich.share; CUSTOM_GROUP_ID = group.app.immich.share;
DEVELOPMENT_TEAM = 2F67MQ8R79; DEVELOPMENT_TEAM = 2F67MQ8R79;
ENABLE_USER_SCRIPT_SANDBOXING = YES; ENABLE_USER_SCRIPT_SANDBOXING = YES;

View File

@@ -50,11 +50,119 @@ private func nilOrValue<T>(_ value: Any?) -> T? {
return value as! T? return value as! T?
} }
func deepEqualsBackgroundWorker(_ lhs: Any?, _ rhs: Any?) -> Bool {
let cleanLhs = nilOrValue(lhs) as Any?
let cleanRhs = nilOrValue(rhs) as Any?
switch (cleanLhs, cleanRhs) {
case (nil, nil):
return true
case (nil, _), (_, nil):
return false
case is (Void, Void):
return true
case let (cleanLhsHashable, cleanRhsHashable) as (AnyHashable, AnyHashable):
return cleanLhsHashable == cleanRhsHashable
case let (cleanLhsArray, cleanRhsArray) as ([Any?], [Any?]):
guard cleanLhsArray.count == cleanRhsArray.count else { return false }
for (index, element) in cleanLhsArray.enumerated() {
if !deepEqualsBackgroundWorker(element, cleanRhsArray[index]) {
return false
}
}
return true
case let (cleanLhsDictionary, cleanRhsDictionary) as ([AnyHashable: Any?], [AnyHashable: Any?]):
guard cleanLhsDictionary.count == cleanRhsDictionary.count else { return false }
for (key, cleanLhsValue) in cleanLhsDictionary {
guard cleanRhsDictionary.index(forKey: key) != nil else { return false }
if !deepEqualsBackgroundWorker(cleanLhsValue, cleanRhsDictionary[key]!) {
return false
}
}
return true
default:
// Any other type shouldn't be able to be used with pigeon. File an issue if you find this to be untrue.
return false
}
}
func deepHashBackgroundWorker(value: Any?, hasher: inout Hasher) {
if let valueList = value as? [AnyHashable] {
for item in valueList { deepHashBackgroundWorker(value: item, hasher: &hasher) }
return
}
if let valueDict = value as? [AnyHashable: AnyHashable] {
for key in valueDict.keys {
hasher.combine(key)
deepHashBackgroundWorker(value: valueDict[key]!, hasher: &hasher)
}
return
}
if let hashableValue = value as? AnyHashable {
hasher.combine(hashableValue.hashValue)
}
return hasher.combine(String(describing: value))
}
/// Generated class from Pigeon that represents data sent in messages.
struct BackgroundWorkerSettings: Hashable {
var requiresCharging: Bool
var minimumDelaySeconds: Int64
// swift-format-ignore: AlwaysUseLowerCamelCase
static func fromList(_ pigeonVar_list: [Any?]) -> BackgroundWorkerSettings? {
let requiresCharging = pigeonVar_list[0] as! Bool
let minimumDelaySeconds = pigeonVar_list[1] as! Int64
return BackgroundWorkerSettings(
requiresCharging: requiresCharging,
minimumDelaySeconds: minimumDelaySeconds
)
}
func toList() -> [Any?] {
return [
requiresCharging,
minimumDelaySeconds,
]
}
static func == (lhs: BackgroundWorkerSettings, rhs: BackgroundWorkerSettings) -> Bool {
return deepEqualsBackgroundWorker(lhs.toList(), rhs.toList()) }
func hash(into hasher: inout Hasher) {
deepHashBackgroundWorker(value: toList(), hasher: &hasher)
}
}
private class BackgroundWorkerPigeonCodecReader: FlutterStandardReader { private class BackgroundWorkerPigeonCodecReader: FlutterStandardReader {
override func readValue(ofType type: UInt8) -> Any? {
switch type {
case 129:
return BackgroundWorkerSettings.fromList(self.readValue() as! [Any?])
default:
return super.readValue(ofType: type)
}
}
} }
private class BackgroundWorkerPigeonCodecWriter: FlutterStandardWriter { private class BackgroundWorkerPigeonCodecWriter: FlutterStandardWriter {
override func writeValue(_ value: Any) {
if let value = value as? BackgroundWorkerSettings {
super.writeByte(129)
super.writeValue(value.toList())
} else {
super.writeValue(value)
}
}
} }
private class BackgroundWorkerPigeonCodecReaderWriter: FlutterStandardReaderWriter { private class BackgroundWorkerPigeonCodecReaderWriter: FlutterStandardReaderWriter {
@@ -74,6 +182,7 @@ class BackgroundWorkerPigeonCodec: FlutterStandardMessageCodec, @unchecked Senda
/// Generated protocol from Pigeon that represents a handler of messages from Flutter. /// Generated protocol from Pigeon that represents a handler of messages from Flutter.
protocol BackgroundWorkerFgHostApi { protocol BackgroundWorkerFgHostApi {
func enable() throws func enable() throws
func configure(settings: BackgroundWorkerSettings) throws
func disable() throws func disable() throws
} }
@@ -96,6 +205,21 @@ class BackgroundWorkerFgHostApiSetup {
} else { } else {
enableChannel.setMessageHandler(nil) enableChannel.setMessageHandler(nil)
} }
let configureChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.immich_mobile.BackgroundWorkerFgHostApi.configure\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec)
if let api = api {
configureChannel.setMessageHandler { message, reply in
let args = message as! [Any?]
let settingsArg = args[0] as! BackgroundWorkerSettings
do {
try api.configure(settings: settingsArg)
reply(wrapResult(nil))
} catch {
reply(wrapError(error))
}
}
} else {
configureChannel.setMessageHandler(nil)
}
let disableChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.immich_mobile.BackgroundWorkerFgHostApi.disable\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) let disableChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.immich_mobile.BackgroundWorkerFgHostApi.disable\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec)
if let api = api { if let api = api {
disableChannel.setMessageHandler { _, reply in disableChannel.setMessageHandler { _, reply in

View File

@@ -133,7 +133,6 @@ class BackgroundWorker: BackgroundWorkerBgHostApi {
return return
} }
isComplete = true
flutterApi?.cancel { result in flutterApi?.cancel { result in
self.complete(success: false) self.complete(success: false)
} }
@@ -174,6 +173,7 @@ class BackgroundWorker: BackgroundWorkerBgHostApi {
isComplete = true isComplete = true
engine.destroyContext() engine.destroyContext()
flutterApi = nil
completionHandler(success) completionHandler(success)
} }
} }

View File

@@ -5,17 +5,22 @@ class BackgroundWorkerApiImpl: BackgroundWorkerFgHostApi {
func enable() throws { func enable() throws {
BackgroundWorkerApiImpl.scheduleRefreshWorker() BackgroundWorkerApiImpl.scheduleRefreshWorker()
BackgroundWorkerApiImpl.scheduleProcessingWorker() BackgroundWorkerApiImpl.scheduleProcessingWorker()
print("BackgroundUploadImpl:enbale Background worker scheduled") print("BackgroundWorkerApiImpl:enable Background worker scheduled")
}
func configure(settings: BackgroundWorkerSettings) throws {
// Android only
} }
func disable() throws { func disable() throws {
BGTaskScheduler.shared.cancel(taskRequestWithIdentifier: BackgroundWorkerApiImpl.refreshTaskID); BGTaskScheduler.shared.cancel(taskRequestWithIdentifier: BackgroundWorkerApiImpl.refreshTaskID);
BGTaskScheduler.shared.cancel(taskRequestWithIdentifier: BackgroundWorkerApiImpl.processingTaskID); BGTaskScheduler.shared.cancel(taskRequestWithIdentifier: BackgroundWorkerApiImpl.processingTaskID);
print("BackgroundUploadImpl:disableUploadWorker Disabled background workers") print("BackgroundWorkerApiImpl:disableUploadWorker Disabled background workers")
} }
private static let refreshTaskID = "app.alextran.immich.background.refreshUpload" private static let refreshTaskID = "app.alextran.immich.background.refreshUpload"
private static let processingTaskID = "app.alextran.immich.background.processingUpload" private static let processingTaskID = "app.alextran.immich.background.processingUpload"
private static let taskSemaphore = DispatchSemaphore(value: 1)
public static func registerBackgroundWorkers() { public static func registerBackgroundWorkers() {
BGTaskScheduler.shared.register( BGTaskScheduler.shared.register(
@@ -59,12 +64,18 @@ class BackgroundWorkerApiImpl: BackgroundWorkerFgHostApi {
private static func handleBackgroundRefresh(task: BGAppRefreshTask) { private static func handleBackgroundRefresh(task: BGAppRefreshTask) {
scheduleRefreshWorker() scheduleRefreshWorker()
// Restrict the refresh task to run only for a maximum of (maxSeconds) seconds // If another task is running, cede the background time back to the OS
runBackgroundWorker(task: task, taskType: .refresh, maxSeconds: 20) if taskSemaphore.wait(timeout: .now()) == .success {
// Restrict the refresh task to run only for a maximum of (maxSeconds) seconds
runBackgroundWorker(task: task, taskType: .refresh, maxSeconds: 20)
} else {
task.setTaskCompleted(success: false)
}
} }
private static func handleBackgroundProcessing(task: BGProcessingTask) { private static func handleBackgroundProcessing(task: BGProcessingTask) {
scheduleProcessingWorker() scheduleProcessingWorker()
taskSemaphore.wait()
// There are no restrictions for processing tasks. Although, the OS could signal expiration at any time // There are no restrictions for processing tasks. Although, the OS could signal expiration at any time
runBackgroundWorker(task: task, taskType: .processing, maxSeconds: nil) runBackgroundWorker(task: task, taskType: .processing, maxSeconds: nil)
} }
@@ -80,6 +91,7 @@ class BackgroundWorkerApiImpl: BackgroundWorkerFgHostApi {
* - maxSeconds: Optional timeout for the operation in seconds * - maxSeconds: Optional timeout for the operation in seconds
*/ */
private static func runBackgroundWorker(task: BGTask, taskType: BackgroundTaskType, maxSeconds: Int?) { private static func runBackgroundWorker(task: BGTask, taskType: BackgroundTaskType, maxSeconds: Int?) {
defer { taskSemaphore.signal() }
let semaphore = DispatchSemaphore(value: 0) let semaphore = DispatchSemaphore(value: 0)
var isSuccess = true var isSuccess = true

View File

@@ -105,7 +105,7 @@ class ThumbnailApiImpl: ThumbnailApi {
var image: UIImage? var image: UIImage?
Self.imageManager.requestImage( Self.imageManager.requestImage(
for: asset, for: asset,
targetSize: CGSize(width: Double(width), height: Double(height)), targetSize: width > 0 && height > 0 ? CGSize(width: Double(width), height: Double(height)) : PHImageManagerMaximumSize,
contentMode: .aspectFill, contentMode: .aspectFill,
options: Self.requestOptions, options: Self.requestOptions,
resultHandler: { (_image, info) -> Void in resultHandler: { (_image, info) -> Void in

View File

@@ -80,7 +80,7 @@
<key>CFBundlePackageType</key> <key>CFBundlePackageType</key>
<string>APPL</string> <string>APPL</string>
<key>CFBundleShortVersionString</key> <key>CFBundleShortVersionString</key>
<string>1.140.0</string> <string>1.142.1</string>
<key>CFBundleSignature</key> <key>CFBundleSignature</key>
<string>????</string> <string>????</string>
<key>CFBundleURLTypes</key> <key>CFBundleURLTypes</key>
@@ -107,7 +107,7 @@
</dict> </dict>
</array> </array>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>219</string> <string>224</string>
<key>FLTEnableImpeller</key> <key>FLTEnableImpeller</key>
<true/> <true/>
<key>ITSAppUsesNonExemptEncryption</key> <key>ITSAppUsesNonExemptEncryption</key>

View File

@@ -267,6 +267,39 @@ struct SyncDelta: Hashable {
} }
} }
/// Generated class from Pigeon that represents data sent in messages.
struct HashResult: Hashable {
var assetId: String
var error: String? = nil
var hash: String? = nil
// swift-format-ignore: AlwaysUseLowerCamelCase
static func fromList(_ pigeonVar_list: [Any?]) -> HashResult? {
let assetId = pigeonVar_list[0] as! String
let error: String? = nilOrValue(pigeonVar_list[1])
let hash: String? = nilOrValue(pigeonVar_list[2])
return HashResult(
assetId: assetId,
error: error,
hash: hash
)
}
func toList() -> [Any?] {
return [
assetId,
error,
hash,
]
}
static func == (lhs: HashResult, rhs: HashResult) -> Bool {
return deepEqualsMessages(lhs.toList(), rhs.toList()) }
func hash(into hasher: inout Hasher) {
deepHashMessages(value: toList(), hasher: &hasher)
}
}
private class MessagesPigeonCodecReader: FlutterStandardReader { private class MessagesPigeonCodecReader: FlutterStandardReader {
override func readValue(ofType type: UInt8) -> Any? { override func readValue(ofType type: UInt8) -> Any? {
switch type { switch type {
@@ -276,6 +309,8 @@ private class MessagesPigeonCodecReader: FlutterStandardReader {
return PlatformAlbum.fromList(self.readValue() as! [Any?]) return PlatformAlbum.fromList(self.readValue() as! [Any?])
case 131: case 131:
return SyncDelta.fromList(self.readValue() as! [Any?]) return SyncDelta.fromList(self.readValue() as! [Any?])
case 132:
return HashResult.fromList(self.readValue() as! [Any?])
default: default:
return super.readValue(ofType: type) return super.readValue(ofType: type)
} }
@@ -293,6 +328,9 @@ private class MessagesPigeonCodecWriter: FlutterStandardWriter {
} else if let value = value as? SyncDelta { } else if let value = value as? SyncDelta {
super.writeByte(131) super.writeByte(131)
super.writeValue(value.toList()) super.writeValue(value.toList())
} else if let value = value as? HashResult {
super.writeByte(132)
super.writeValue(value.toList())
} else { } else {
super.writeValue(value) super.writeValue(value)
} }
@@ -313,6 +351,7 @@ class MessagesPigeonCodec: FlutterStandardMessageCodec, @unchecked Sendable {
static let shared = MessagesPigeonCodec(readerWriter: MessagesPigeonCodecReaderWriter()) static let shared = MessagesPigeonCodec(readerWriter: MessagesPigeonCodecReaderWriter())
} }
/// Generated protocol from Pigeon that represents a handler of messages from Flutter. /// Generated protocol from Pigeon that represents a handler of messages from Flutter.
protocol NativeSyncApi { protocol NativeSyncApi {
func shouldFullSync() throws -> Bool func shouldFullSync() throws -> Bool
@@ -323,7 +362,8 @@ protocol NativeSyncApi {
func getAlbums() throws -> [PlatformAlbum] func getAlbums() throws -> [PlatformAlbum]
func getAssetsCountSince(albumId: String, timestamp: Int64) throws -> Int64 func getAssetsCountSince(albumId: String, timestamp: Int64) throws -> Int64
func getAssetsForAlbum(albumId: String, updatedTimeCond: Int64?) throws -> [PlatformAsset] func getAssetsForAlbum(albumId: String, updatedTimeCond: Int64?) throws -> [PlatformAsset]
func hashPaths(paths: [String]) throws -> [FlutterStandardTypedData?] func hashAssets(assetIds: [String], allowNetworkAccess: Bool, completion: @escaping (Result<[HashResult], Error>) -> Void)
func cancelHashing() throws
} }
/// Generated setup class from Pigeon to handle messages through the `binaryMessenger`. /// Generated setup class from Pigeon to handle messages through the `binaryMessenger`.
@@ -459,22 +499,38 @@ class NativeSyncApiSetup {
} else { } else {
getAssetsForAlbumChannel.setMessageHandler(nil) getAssetsForAlbumChannel.setMessageHandler(nil)
} }
let hashPathsChannel = taskQueue == nil let hashAssetsChannel = taskQueue == nil
? FlutterBasicMessageChannel(name: "dev.flutter.pigeon.immich_mobile.NativeSyncApi.hashPaths\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) ? FlutterBasicMessageChannel(name: "dev.flutter.pigeon.immich_mobile.NativeSyncApi.hashAssets\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec)
: FlutterBasicMessageChannel(name: "dev.flutter.pigeon.immich_mobile.NativeSyncApi.hashPaths\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec, taskQueue: taskQueue) : FlutterBasicMessageChannel(name: "dev.flutter.pigeon.immich_mobile.NativeSyncApi.hashAssets\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec, taskQueue: taskQueue)
if let api = api { if let api = api {
hashPathsChannel.setMessageHandler { message, reply in hashAssetsChannel.setMessageHandler { message, reply in
let args = message as! [Any?] let args = message as! [Any?]
let pathsArg = args[0] as! [String] let assetIdsArg = args[0] as! [String]
let allowNetworkAccessArg = args[1] as! Bool
api.hashAssets(assetIds: assetIdsArg, allowNetworkAccess: allowNetworkAccessArg) { result in
switch result {
case .success(let res):
reply(wrapResult(res))
case .failure(let error):
reply(wrapError(error))
}
}
}
} else {
hashAssetsChannel.setMessageHandler(nil)
}
let cancelHashingChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.immich_mobile.NativeSyncApi.cancelHashing\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec)
if let api = api {
cancelHashingChannel.setMessageHandler { _, reply in
do { do {
let result = try api.hashPaths(paths: pathsArg) try api.cancelHashing()
reply(wrapResult(result)) reply(wrapResult(nil))
} catch { } catch {
reply(wrapError(error)) reply(wrapError(error))
} }
} }
} else { } else {
hashPathsChannel.setMessageHandler(nil) cancelHashingChannel.setMessageHandler(nil)
} }
} }
} }

View File

@@ -17,30 +17,16 @@ struct AssetWrapper: Hashable, Equatable {
} }
} }
extension PHAsset {
func toPlatformAsset() -> PlatformAsset {
return PlatformAsset(
id: localIdentifier,
name: title(),
type: Int64(mediaType.rawValue),
createdAt: creationDate.map { Int64($0.timeIntervalSince1970) },
updatedAt: modificationDate.map { Int64($0.timeIntervalSince1970) },
width: Int64(pixelWidth),
height: Int64(pixelHeight),
durationInSeconds: Int64(duration),
orientation: 0,
isFavorite: isFavorite
)
}
}
class NativeSyncApiImpl: NativeSyncApi { class NativeSyncApiImpl: NativeSyncApi {
private let defaults: UserDefaults private let defaults: UserDefaults
private let changeTokenKey = "immich:changeToken" private let changeTokenKey = "immich:changeToken"
private let albumTypes: [PHAssetCollectionType] = [.album, .smartAlbum] private let albumTypes: [PHAssetCollectionType] = [.album, .smartAlbum]
private let recoveredAlbumSubType = 1000000219 private let recoveredAlbumSubType = 1000000219
private let hashBufferSize = 2 * 1024 * 1024 private var hashTask: Task<Void, Error>?
private static let hashCancelledCode = "HASH_CANCELLED"
private static let hashCancelled = Result<[HashResult], Error>.failure(PigeonError(code: hashCancelledCode, message: "Hashing cancelled", details: nil))
init(with defaults: UserDefaults = .standard) { init(with defaults: UserDefaults = .standard) {
self.defaults = defaults self.defaults = defaults
@@ -96,7 +82,7 @@ class NativeSyncApiImpl: NativeSyncApi {
let collections = PHAssetCollection.fetchAssetCollections(with: type, subtype: .any, options: nil) let collections = PHAssetCollection.fetchAssetCollections(with: type, subtype: .any, options: nil)
for i in 0..<collections.count { for i in 0..<collections.count {
let album = collections.object(at: i) let album = collections.object(at: i)
// Ignore recovered album // Ignore recovered album
if(album.assetCollectionSubtype.rawValue == self.recoveredAlbumSubType) { if(album.assetCollectionSubtype.rawValue == self.recoveredAlbumSubType) {
continue; continue;
@@ -254,7 +240,7 @@ class NativeSyncApiImpl: NativeSyncApi {
let date = NSDate(timeIntervalSince1970: TimeInterval(updatedTimeCond!)) let date = NSDate(timeIntervalSince1970: TimeInterval(updatedTimeCond!))
options.predicate = NSPredicate(format: "creationDate > %@ OR modificationDate > %@", date, date) options.predicate = NSPredicate(format: "creationDate > %@ OR modificationDate > %@", date, date)
} }
let result = PHAsset.fetchAssets(in: album, options: options) let result = PHAsset.fetchAssets(in: album, options: options)
if(result.count == 0) { if(result.count == 0) {
return [] return []
@@ -267,23 +253,114 @@ class NativeSyncApiImpl: NativeSyncApi {
return assets return assets
} }
func hashPaths(paths: [String]) throws -> [FlutterStandardTypedData?] { func hashAssets(assetIds: [String], allowNetworkAccess: Bool, completion: @escaping (Result<[HashResult], Error>) -> Void) {
return paths.map { path in if let prevTask = hashTask {
guard let file = FileHandle(forReadingAtPath: path) else { prevTask.cancel()
print("Cannot open file: \(path)") hashTask = nil
return nil }
} hashTask = Task { [weak self] in
var missingAssetIds = Set(assetIds)
var hasher = Insecure.SHA1() var assets = [PHAsset]()
while autoreleasepool(invoking: { assets.reserveCapacity(assetIds.count)
let chunk = file.readData(ofLength: hashBufferSize) PHAsset.fetchAssets(withLocalIdentifiers: assetIds, options: nil).enumerateObjects { (asset, _, stop) in
guard !chunk.isEmpty else { return false } if Task.isCancelled {
hasher.update(data: chunk) stop.pointee = true
return true return
}) { } }
missingAssetIds.remove(asset.localIdentifier)
let digest = hasher.finalize() assets.append(asset)
return FlutterStandardTypedData(bytes: Data(digest))
} }
if Task.isCancelled {
return completion(Self.hashCancelled)
}
await withTaskGroup(of: HashResult?.self) { taskGroup in
var results = [HashResult]()
results.reserveCapacity(assets.count)
for asset in assets {
if Task.isCancelled {
return completion(Self.hashCancelled)
}
taskGroup.addTask {
guard let self = self else { return nil }
return await self.hashAsset(asset, allowNetworkAccess: allowNetworkAccess)
}
}
for await result in taskGroup {
guard let result = result else {
return completion(Self.hashCancelled)
}
results.append(result)
}
for missing in missingAssetIds {
results.append(HashResult(assetId: missing, error: "Asset not found in library", hash: nil))
}
completion(.success(results))
}
}
}
func cancelHashing() {
hashTask?.cancel()
hashTask = nil
}
private func hashAsset(_ asset: PHAsset, allowNetworkAccess: Bool) async -> HashResult? {
class RequestRef {
var id: PHAssetResourceDataRequestID?
}
let requestRef = RequestRef()
return await withTaskCancellationHandler(operation: {
if Task.isCancelled {
return nil
}
guard let resource = asset.getResource() else {
return HashResult(assetId: asset.localIdentifier, error: "Cannot get asset resource", hash: nil)
}
if Task.isCancelled {
return nil
}
let options = PHAssetResourceRequestOptions()
options.isNetworkAccessAllowed = allowNetworkAccess
return await withCheckedContinuation { continuation in
var hasher = Insecure.SHA1()
requestRef.id = PHAssetResourceManager.default().requestData(
for: resource,
options: options,
dataReceivedHandler: { data in
hasher.update(data: data)
},
completionHandler: { error in
let result: HashResult? = switch (error) {
case let e as PHPhotosError where e.code == .userCancelled: nil
case let .some(e): HashResult(
assetId: asset.localIdentifier,
error: "Failed to hash asset: \(e.localizedDescription)",
hash: nil
)
case .none:
HashResult(
assetId: asset.localIdentifier,
error: nil,
hash: Data(hasher.finalize()).base64EncodedString()
)
}
continuation.resume(returning: result)
}
)
}
}, onCancel: {
guard let requestId = requestRef.id else { return }
PHAssetResourceManager.default().cancelDataRequest(requestId)
})
} }
} }

View File

@@ -0,0 +1,77 @@
import Photos
extension PHAsset {
func toPlatformAsset() -> PlatformAsset {
return PlatformAsset(
id: localIdentifier,
name: title,
type: Int64(mediaType.rawValue),
createdAt: creationDate.map { Int64($0.timeIntervalSince1970) },
updatedAt: modificationDate.map { Int64($0.timeIntervalSince1970) },
width: Int64(pixelWidth),
height: Int64(pixelHeight),
durationInSeconds: Int64(duration),
orientation: 0,
isFavorite: isFavorite
)
}
var title: String {
return filename ?? originalFilename ?? "<unknown>"
}
var filename: String? {
return value(forKey: "filename") as? String
}
// This method is expected to be slow as it goes through the asset resources to fetch the originalFilename
var originalFilename: String? {
return getResource()?.originalFilename
}
func getResource() -> PHAssetResource? {
let resources = PHAssetResource.assetResources(for: self)
let filteredResources = resources.filter { $0.isMediaResource && isValidResourceType($0.type) }
guard !filteredResources.isEmpty else {
return nil
}
if filteredResources.count == 1 {
return filteredResources.first
}
if let currentResource = filteredResources.first(where: { $0.isCurrent }) {
return currentResource
}
if let fullSizeResource = filteredResources.first(where: { isFullSizeResourceType($0.type) }) {
return fullSizeResource
}
return nil
}
private func isValidResourceType(_ type: PHAssetResourceType) -> Bool {
switch mediaType {
case .image:
return [.photo, .alternatePhoto, .fullSizePhoto].contains(type)
case .video:
return [.video, .fullSizeVideo, .fullSizePairedVideo].contains(type)
default:
return false
}
}
private func isFullSizeResourceType(_ type: PHAssetResourceType) -> Bool {
switch mediaType {
case .image:
return type == .fullSizePhoto
case .video:
return type == .fullSizeVideo
default:
return false
}
}
}

View File

@@ -0,0 +1,16 @@
import Photos
extension PHAssetResource {
var isCurrent: Bool {
return value(forKey: "isCurrent") as? Bool ?? false
}
var isMediaResource: Bool {
var isMedia = type != .adjustmentData
if #available(iOS 17, *) {
isMedia = isMedia && type != .photoProxy
}
return isMedia
}
}

View File

@@ -22,7 +22,7 @@ platform :ios do
path: "./Runner.xcodeproj", path: "./Runner.xcodeproj",
) )
increment_version_number( increment_version_number(
version_number: "1.141.1" version_number: "1.142.1"
) )
increment_build_number( increment_build_number(
build_number: latest_testflight_build_number + 1, build_number: latest_testflight_build_number + 1,

View File

@@ -1,3 +1,5 @@
import 'dart:io';
const int noDbId = -9223372036854775808; // from Isar const int noDbId = -9223372036854775808; // from Isar
const double downloadCompleted = -1; const double downloadCompleted = -1;
const double downloadFailed = -2; const double downloadFailed = -2;
@@ -10,7 +12,7 @@ const int kSyncEventBatchSize = 5000;
const int kFetchLocalAssetsBatchSize = 40000; const int kFetchLocalAssetsBatchSize = 40000;
// Hash batch limits // Hash batch limits
const int kBatchHashFileLimit = 256; final int kBatchHashFileLimit = Platform.isIOS ? 32 : 512;
const int kBatchHashSizeLimit = 1024 * 1024 * 1024; // 1GB const int kBatchHashSizeLimit = 1024 * 1024 * 1024; // 1GB
// Secure storage keys // Secure storage keys
@@ -45,3 +47,5 @@ const List<(String, String)> kWidgetNames = [
const double kUploadStatusFailed = -1.0; const double kUploadStatusFailed = -1.0;
const double kUploadStatusCanceled = -2.0; const double kUploadStatusCanceled = -2.0;
const int kMinMonthsToEnableScrubberSnap = 12;

View File

@@ -77,7 +77,9 @@ enum StoreKey<T> {
enableBackup<bool>._(1003), enableBackup<bool>._(1003),
useWifiForUploadVideos<bool>._(1004), useWifiForUploadVideos<bool>._(1004),
useWifiForUploadPhotos<bool>._(1005), useWifiForUploadPhotos<bool>._(1005),
needBetaMigration<bool>._(1006); needBetaMigration<bool>._(1006),
// TODO: Remove this after patching open-api
shouldResetSync<bool>._(1007);
const StoreKey._(this.id); const StoreKey._(this.id);
final int id; final int id;

View File

@@ -1,22 +1,20 @@
import 'package:immich_mobile/domain/models/album/local_album.model.dart'; import 'package:immich_mobile/domain/models/album/local_album.model.dart';
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart'; import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
import 'package:immich_mobile/domain/models/exif.model.dart'; import 'package:immich_mobile/domain/models/exif.model.dart';
import 'package:immich_mobile/extensions/platform_extensions.dart';
import 'package:immich_mobile/infrastructure/repositories/local_asset.repository.dart'; import 'package:immich_mobile/infrastructure/repositories/local_asset.repository.dart';
import 'package:immich_mobile/infrastructure/repositories/remote_asset.repository.dart'; import 'package:immich_mobile/infrastructure/repositories/remote_asset.repository.dart';
import 'package:immich_mobile/infrastructure/utils/exif.converter.dart'; import 'package:immich_mobile/infrastructure/utils/exif.converter.dart';
import 'package:platform/platform.dart';
class AssetService { class AssetService {
final RemoteAssetRepository _remoteAssetRepository; final RemoteAssetRepository _remoteAssetRepository;
final DriftLocalAssetRepository _localAssetRepository; final DriftLocalAssetRepository _localAssetRepository;
final Platform _platform;
const AssetService({ const AssetService({
required RemoteAssetRepository remoteAssetRepository, required RemoteAssetRepository remoteAssetRepository,
required DriftLocalAssetRepository localAssetRepository, required DriftLocalAssetRepository localAssetRepository,
}) : _remoteAssetRepository = remoteAssetRepository, }) : _remoteAssetRepository = remoteAssetRepository,
_localAssetRepository = localAssetRepository, _localAssetRepository = localAssetRepository;
_platform = const LocalPlatform();
Future<BaseAsset?> getAsset(BaseAsset asset) { Future<BaseAsset?> getAsset(BaseAsset asset) {
final id = asset is LocalAsset ? asset.id : (asset as RemoteAsset).id; final id = asset is LocalAsset ? asset.id : (asset as RemoteAsset).id;
@@ -42,13 +40,12 @@ class AssetService {
Future<List<RemoteAsset>> getStack(RemoteAsset asset) async { Future<List<RemoteAsset>> getStack(RemoteAsset asset) async {
if (asset.stackId == null) { if (asset.stackId == null) {
return []; return const [];
} }
return _remoteAssetRepository.getStackChildren(asset).then((assets) { final stack = await _remoteAssetRepository.getStackChildren(asset);
// Include the primary asset in the stack as the first item // Include the primary asset in the stack as the first item
return [asset, ...assets]; return [asset, ...stack];
});
} }
Future<ExifInfo?> getExif(BaseAsset asset) async { Future<ExifInfo?> getExif(BaseAsset asset) async {
@@ -71,7 +68,7 @@ class AssetService {
width = exif?.width ?? asset.width?.toDouble(); width = exif?.width ?? asset.width?.toDouble();
height = exif?.height ?? asset.height?.toDouble(); height = exif?.height ?? asset.height?.toDouble();
} else if (asset is LocalAsset) { } else if (asset is LocalAsset) {
isFlipped = _platform.isAndroid && (asset.orientation == 90 || asset.orientation == 270); isFlipped = CurrentPlatform.isAndroid && (asset.orientation == 90 || asset.orientation == 270);
width = asset.width?.toDouble(); width = asset.width?.toDouble();
height = asset.height?.toDouble(); height = asset.height?.toDouble();
} else { } else {

View File

@@ -7,6 +7,8 @@ import 'package:cancellation_token_http/http.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/constants/constants.dart'; import 'package:immich_mobile/constants/constants.dart';
import 'package:immich_mobile/domain/services/log.service.dart';
import 'package:immich_mobile/entities/store.entity.dart';
import 'package:immich_mobile/extensions/network_capability_extensions.dart'; import 'package:immich_mobile/extensions/network_capability_extensions.dart';
import 'package:immich_mobile/extensions/translate_extensions.dart'; import 'package:immich_mobile/extensions/translate_extensions.dart';
import 'package:immich_mobile/generated/intl_keys.g.dart'; import 'package:immich_mobile/generated/intl_keys.g.dart';
@@ -27,6 +29,7 @@ import 'package:immich_mobile/services/localization.service.dart';
import 'package:immich_mobile/services/server_info.service.dart'; import 'package:immich_mobile/services/server_info.service.dart';
import 'package:immich_mobile/services/upload.service.dart'; import 'package:immich_mobile/services/upload.service.dart';
import 'package:immich_mobile/utils/bootstrap.dart'; import 'package:immich_mobile/utils/bootstrap.dart';
import 'package:immich_mobile/utils/debug_print.dart';
import 'package:immich_mobile/utils/http_ssl_options.dart'; import 'package:immich_mobile/utils/http_ssl_options.dart';
import 'package:isar/isar.dart'; import 'package:isar/isar.dart';
import 'package:logging/logging.dart'; import 'package:logging/logging.dart';
@@ -40,6 +43,17 @@ class BackgroundWorkerFgService {
// TODO: Move this call to native side once old timeline is removed // TODO: Move this call to native side once old timeline is removed
Future<void> enable() => _foregroundHostApi.enable(); Future<void> enable() => _foregroundHostApi.enable();
Future<void> configure({int? minimumDelaySeconds, bool? requireCharging}) => _foregroundHostApi.configure(
BackgroundWorkerSettings(
minimumDelaySeconds:
minimumDelaySeconds ??
Store.get(AppSettingsEnum.backupTriggerDelay.storeKey, AppSettingsEnum.backupTriggerDelay.defaultValue),
requiresCharging:
requireCharging ??
Store.get(AppSettingsEnum.backupRequireCharging.storeKey, AppSettingsEnum.backupRequireCharging.defaultValue),
),
);
Future<void> disable() => _foregroundHostApi.disable(); Future<void> disable() => _foregroundHostApi.disable();
} }
@@ -159,7 +173,7 @@ class BackgroundWorkerBgService extends BackgroundWorkerFlutterApi {
try { try {
await _cleanup(); await _cleanup();
} catch (error, stack) { } catch (error, stack) {
debugPrint('Failed to cleanup background worker: $error with stack: $stack'); dPrint(() => 'Failed to cleanup background worker: $error with stack: $stack');
} }
} }
@@ -169,7 +183,11 @@ class BackgroundWorkerBgService extends BackgroundWorkerFlutterApi {
} }
try { try {
final backgroundSyncManager = _ref.read(backgroundSyncProvider);
final nativeSyncApi = _ref.read(nativeSyncApiProvider);
_isCleanedUp = true; _isCleanedUp = true;
_ref.dispose();
_cancellationToken.cancel(); _cancellationToken.cancel();
_logger.info("Cleaning up background worker"); _logger.info("Cleaning up background worker");
final cleanupFutures = [ final cleanupFutures = [
@@ -177,53 +195,61 @@ class BackgroundWorkerBgService extends BackgroundWorkerFlutterApi {
// Discard any errors on the dispose call // Discard any errors on the dispose call
return; return;
}), }),
LogService.I.dispose(),
Store.dispose(),
_drift.close(), _drift.close(),
_driftLogger.close(), _driftLogger.close(),
_ref.read(backgroundSyncProvider).cancel(), backgroundSyncManager.cancel(),
_ref.read(backgroundSyncProvider).cancelLocal(), nativeSyncApi.cancelHashing(),
]; ];
if (_isar.isOpen) { if (_isar.isOpen) {
cleanupFutures.add(_isar.close()); cleanupFutures.add(_isar.close());
} }
_ref.dispose();
await Future.wait(cleanupFutures); await Future.wait(cleanupFutures);
_logger.info("Background worker resources cleaned up"); _logger.info("Background worker resources cleaned up");
} catch (error, stack) { } catch (error, stack) {
debugPrint('Failed to cleanup background worker: $error with stack: $stack'); dPrint(() => 'Failed to cleanup background worker: $error with stack: $stack');
} }
} }
Future<void> _handleBackup() async { Future<void> _handleBackup() async {
if (!_isBackupEnabled || _isCleanedUp) { await runZonedGuarded(
_logger.info("[_handleBackup 1] Backup is disabled. Skipping backup routine"); () async {
return; if (!_isBackupEnabled || _isCleanedUp) {
} _logger.info("[_handleBackup 1] Backup is disabled. Skipping backup routine");
return;
}
_logger.info("[_handleBackup 2] Enqueuing assets for backup from the background service"); _logger.info("[_handleBackup 2] Enqueuing assets for backup from the background service");
final currentUser = _ref.read(currentUserProvider); final currentUser = _ref.read(currentUserProvider);
if (currentUser == null) { if (currentUser == null) {
_logger.warning("[_handleBackup 3] No current user found. Skipping backup from background"); _logger.warning("[_handleBackup 3] No current user found. Skipping backup from background");
return; return;
} }
_logger.info("[_handleBackup 4] Resume backup from background"); _logger.info("[_handleBackup 4] Resume backup from background");
if (Platform.isIOS) { if (Platform.isIOS) {
return _ref.read(driftBackupProvider.notifier).handleBackupResume(currentUser.id); return _ref.read(driftBackupProvider.notifier).handleBackupResume(currentUser.id);
} }
final canPing = await _ref.read(serverInfoServiceProvider).ping(); final canPing = await _ref.read(serverInfoServiceProvider).ping();
if (!canPing) { if (!canPing) {
_logger.warning("[_handleBackup 5] Server is not reachable. Skipping backup from background"); _logger.warning("[_handleBackup 5] Server is not reachable. Skipping backup from background");
return; return;
} }
final networkCapabilities = await _ref.read(connectivityApiProvider).getCapabilities(); final networkCapabilities = await _ref.read(connectivityApiProvider).getCapabilities();
return _ref return _ref
.read(uploadServiceProvider) .read(uploadServiceProvider)
.startBackupWithHttpClient(currentUser.id, networkCapabilities.hasWifi, _cancellationToken); .startBackupWithHttpClient(currentUser.id, networkCapabilities.hasWifi, _cancellationToken);
},
(error, stack) {
dPrint(() => "Error in backup zone $error, $stack");
},
);
} }
Future<void> _syncAssets({Duration? hashTimeout}) async { Future<void> _syncAssets({Duration? hashTimeout}) async {
@@ -259,6 +285,6 @@ Future<void> backgroundSyncNativeEntrypoint() async {
DartPluginRegistrant.ensureInitialized(); DartPluginRegistrant.ensureInitialized();
final (isar, drift, logDB) = await Bootstrap.initDB(); final (isar, drift, logDB) = await Bootstrap.initDB();
await Bootstrap.initDomain(isar, drift, logDB, shouldBufferLogs: false); await Bootstrap.initDomain(isar, drift, logDB, shouldBufferLogs: false, listenStoreUpdates: false);
await BackgroundWorkerBgService(isar: isar, drift: drift, driftLogger: logDB).init(); await BackgroundWorkerBgService(isar: isar, drift: drift, driftLogger: logDB).init();
} }

View File

@@ -1,20 +1,18 @@
import 'dart:convert'; import 'package:flutter/services.dart';
import 'package:immich_mobile/constants/constants.dart'; import 'package:immich_mobile/constants/constants.dart';
import 'package:immich_mobile/domain/models/album/local_album.model.dart'; import 'package:immich_mobile/domain/models/album/local_album.model.dart';
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart'; import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
import 'package:immich_mobile/infrastructure/repositories/local_album.repository.dart'; import 'package:immich_mobile/infrastructure/repositories/local_album.repository.dart';
import 'package:immich_mobile/infrastructure/repositories/local_asset.repository.dart'; import 'package:immich_mobile/infrastructure/repositories/local_asset.repository.dart';
import 'package:immich_mobile/infrastructure/repositories/storage.repository.dart';
import 'package:immich_mobile/platform/native_sync_api.g.dart'; import 'package:immich_mobile/platform/native_sync_api.g.dart';
import 'package:logging/logging.dart'; import 'package:logging/logging.dart';
const String _kHashCancelledCode = "HASH_CANCELLED";
class HashService { class HashService {
final int batchSizeLimit; final int _batchSize;
final int batchFileLimit;
final DriftLocalAlbumRepository _localAlbumRepository; final DriftLocalAlbumRepository _localAlbumRepository;
final DriftLocalAssetRepository _localAssetRepository; final DriftLocalAssetRepository _localAssetRepository;
final StorageRepository _storageRepository;
final NativeSyncApi _nativeSyncApi; final NativeSyncApi _nativeSyncApi;
final bool Function()? _cancelChecker; final bool Function()? _cancelChecker;
final _log = Logger('HashService'); final _log = Logger('HashService');
@@ -22,37 +20,42 @@ class HashService {
HashService({ HashService({
required DriftLocalAlbumRepository localAlbumRepository, required DriftLocalAlbumRepository localAlbumRepository,
required DriftLocalAssetRepository localAssetRepository, required DriftLocalAssetRepository localAssetRepository,
required StorageRepository storageRepository,
required NativeSyncApi nativeSyncApi, required NativeSyncApi nativeSyncApi,
bool Function()? cancelChecker, bool Function()? cancelChecker,
this.batchSizeLimit = kBatchHashSizeLimit, int? batchSize,
this.batchFileLimit = kBatchHashFileLimit,
}) : _localAlbumRepository = localAlbumRepository, }) : _localAlbumRepository = localAlbumRepository,
_localAssetRepository = localAssetRepository, _localAssetRepository = localAssetRepository,
_storageRepository = storageRepository,
_cancelChecker = cancelChecker, _cancelChecker = cancelChecker,
_nativeSyncApi = nativeSyncApi; _nativeSyncApi = nativeSyncApi,
_batchSize = batchSize ?? kBatchHashFileLimit;
bool get isCancelled => _cancelChecker?.call() ?? false; bool get isCancelled => _cancelChecker?.call() ?? false;
Future<void> hashAssets() async { Future<void> hashAssets() async {
_log.info("Starting hashing of assets"); _log.info("Starting hashing of assets");
final Stopwatch stopwatch = Stopwatch()..start(); final Stopwatch stopwatch = Stopwatch()..start();
// Sorted by backupSelection followed by isCloud try {
final localAlbums = await _localAlbumRepository.getAll( // Sorted by backupSelection followed by isCloud
sortBy: {SortLocalAlbumsBy.backupSelection, SortLocalAlbumsBy.isIosSharedAlbum}, final localAlbums = await _localAlbumRepository.getBackupAlbums();
);
for (final album in localAlbums) { for (final album in localAlbums) {
if (isCancelled) { if (isCancelled) {
_log.warning("Hashing cancelled. Stopped processing albums."); _log.warning("Hashing cancelled. Stopped processing albums.");
break; break;
} }
final assetsToHash = await _localAlbumRepository.getAssetsToHash(album.id); final assetsToHash = await _localAlbumRepository.getAssetsToHash(album.id);
if (assetsToHash.isNotEmpty) { if (assetsToHash.isNotEmpty) {
await _hashAssets(album, assetsToHash); await _hashAssets(album, assetsToHash);
}
} }
} on PlatformException catch (e) {
if (e.code == _kHashCancelledCode) {
_log.warning("Hashing cancelled by platform");
return;
}
} catch (e, s) {
_log.severe("Error during hashing", e, s);
} }
stopwatch.stop(); stopwatch.stop();
@@ -63,8 +66,7 @@ class HashService {
/// with hash for those that were successfully hashed. Hashes are looked up in a table /// with hash for those that were successfully hashed. Hashes are looked up in a table
/// [LocalAssetHashEntity] by local id. Only missing entries are newly hashed and added to the DB. /// [LocalAssetHashEntity] by local id. Only missing entries are newly hashed and added to the DB.
Future<void> _hashAssets(LocalAlbum album, List<LocalAsset> assetsToHash) async { Future<void> _hashAssets(LocalAlbum album, List<LocalAsset> assetsToHash) async {
int bytesProcessed = 0; final toHash = <String, LocalAsset>{};
final toHash = <_AssetToPath>[];
for (final asset in assetsToHash) { for (final asset in assetsToHash) {
if (isCancelled) { if (isCancelled) {
@@ -72,21 +74,10 @@ class HashService {
return; return;
} }
final file = await _storageRepository.getFileForAsset(asset.id); toHash[asset.id] = asset;
if (file == null) { if (toHash.length == _batchSize) {
_log.warning(
"Cannot get file for asset ${asset.id}, name: ${asset.name}, created on: ${asset.createdAt} from album: ${album.name}",
);
continue;
}
bytesProcessed += await file.length();
toHash.add(_AssetToPath(asset: asset, path: file.path));
if (toHash.length >= batchFileLimit || bytesProcessed >= batchSizeLimit) {
await _processBatch(album, toHash); await _processBatch(album, toHash);
toHash.clear(); toHash.clear();
bytesProcessed = 0;
} }
} }
@@ -94,33 +85,36 @@ class HashService {
} }
/// Processes a batch of assets. /// Processes a batch of assets.
Future<void> _processBatch(LocalAlbum album, List<_AssetToPath> toHash) async { Future<void> _processBatch(LocalAlbum album, Map<String, LocalAsset> toHash) async {
if (toHash.isEmpty) { if (toHash.isEmpty) {
return; return;
} }
_log.fine("Hashing ${toHash.length} files"); _log.fine("Hashing ${toHash.length} files");
final hashed = <LocalAsset>[]; final hashed = <String, String>{};
final hashes = await _nativeSyncApi.hashPaths(toHash.map((e) => e.path).toList()); final hashResults = await _nativeSyncApi.hashAssets(
toHash.keys.toList(),
allowNetworkAccess: album.backupSelection == BackupSelection.selected,
);
assert( assert(
hashes.length == toHash.length, hashResults.length == toHash.length,
"Hashes length does not match toHash length: ${hashes.length} != ${toHash.length}", "Hashes length does not match toHash length: ${hashResults.length} != ${toHash.length}",
); );
for (int i = 0; i < hashes.length; i++) { for (int i = 0; i < hashResults.length; i++) {
if (isCancelled) { if (isCancelled) {
_log.warning("Hashing cancelled. Stopped processing batch."); _log.warning("Hashing cancelled. Stopped processing batch.");
return; return;
} }
final hash = hashes[i]; final hashResult = hashResults[i];
final asset = toHash[i].asset; if (hashResult.hash != null) {
if (hash?.length == 20) { hashed[hashResult.assetId] = hashResult.hash!;
hashed.add(asset.copyWith(checksum: base64.encode(hash!)));
} else { } else {
final asset = toHash[hashResult.assetId];
_log.warning( _log.warning(
"Failed to hash file for ${asset.id}: ${asset.name} created at ${asset.createdAt} from album: ${album.name}", "Failed to hash asset with id: ${hashResult.assetId}, name: ${asset?.name}, createdAt: ${asset?.createdAt}, from album: ${album.name}. Error: ${hashResult.error ?? "unknown"}",
); );
} }
} }
@@ -128,13 +122,5 @@ class HashService {
_log.fine("Hashed ${hashed.length}/${toHash.length} assets"); _log.fine("Hashed ${hashed.length}/${toHash.length} assets");
await _localAssetRepository.updateHashes(hashed); await _localAssetRepository.updateHashes(hashed);
await _storageRepository.clearCache();
} }
} }
class _AssetToPath {
final LocalAsset asset;
final String path;
const _AssetToPath({required this.asset, required this.path});
}

View File

@@ -1,29 +1,24 @@
import 'dart:async'; import 'dart:async';
import 'package:collection/collection.dart'; import 'package:collection/collection.dart';
import 'package:flutter/widgets.dart'; import 'package:flutter/foundation.dart';
import 'package:immich_mobile/domain/models/album/local_album.model.dart'; import 'package:immich_mobile/domain/models/album/local_album.model.dart';
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart'; import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
import 'package:immich_mobile/extensions/platform_extensions.dart';
import 'package:immich_mobile/infrastructure/repositories/local_album.repository.dart'; import 'package:immich_mobile/infrastructure/repositories/local_album.repository.dart';
import 'package:immich_mobile/platform/native_sync_api.g.dart'; import 'package:immich_mobile/platform/native_sync_api.g.dart';
import 'package:immich_mobile/utils/datetime_helpers.dart'; import 'package:immich_mobile/utils/datetime_helpers.dart';
import 'package:immich_mobile/utils/diff.dart'; import 'package:immich_mobile/utils/diff.dart';
import 'package:logging/logging.dart'; import 'package:logging/logging.dart';
import 'package:platform/platform.dart';
class LocalSyncService { class LocalSyncService {
final DriftLocalAlbumRepository _localAlbumRepository; final DriftLocalAlbumRepository _localAlbumRepository;
final NativeSyncApi _nativeSyncApi; final NativeSyncApi _nativeSyncApi;
final Platform _platform;
final Logger _log = Logger("DeviceSyncService"); final Logger _log = Logger("DeviceSyncService");
LocalSyncService({ LocalSyncService({required DriftLocalAlbumRepository localAlbumRepository, required NativeSyncApi nativeSyncApi})
required DriftLocalAlbumRepository localAlbumRepository, : _localAlbumRepository = localAlbumRepository,
required NativeSyncApi nativeSyncApi, _nativeSyncApi = nativeSyncApi;
Platform? platform,
}) : _localAlbumRepository = localAlbumRepository,
_nativeSyncApi = nativeSyncApi,
_platform = platform ?? const LocalPlatform();
Future<void> sync({bool full = false}) async { Future<void> sync({bool full = false}) async {
final Stopwatch stopwatch = Stopwatch()..start(); final Stopwatch stopwatch = Stopwatch()..start();
@@ -53,14 +48,14 @@ class LocalSyncService {
final dbAlbums = await _localAlbumRepository.getAll(); final dbAlbums = await _localAlbumRepository.getAll();
// On Android, we need to sync all albums since it is not possible to // On Android, we need to sync all albums since it is not possible to
// detect album deletions from the native side // detect album deletions from the native side
if (_platform.isAndroid) { if (CurrentPlatform.isAndroid) {
for (final album in dbAlbums) { for (final album in dbAlbums) {
final deviceIds = await _nativeSyncApi.getAssetIdsForAlbum(album.id); final deviceIds = await _nativeSyncApi.getAssetIdsForAlbum(album.id);
await _localAlbumRepository.syncDeletes(album.id, deviceIds); await _localAlbumRepository.syncDeletes(album.id, deviceIds);
} }
} }
if (_platform.isIOS) { if (CurrentPlatform.isIOS) {
// On iOS, we need to full sync albums that are marked as cloud as the delta sync // On iOS, we need to full sync albums that are marked as cloud as the delta sync
// does not include changes for cloud albums. If ignoreIcloudAssets is enabled, // does not include changes for cloud albums. If ignoreIcloudAssets is enabled,
// remove the albums from the local database from the previous sync // remove the albums from the local database from the previous sync

View File

@@ -1,11 +1,11 @@
import 'dart:async'; import 'dart:async';
import 'package:flutter/foundation.dart';
import 'package:immich_mobile/constants/constants.dart'; import 'package:immich_mobile/constants/constants.dart';
import 'package:immich_mobile/domain/models/log.model.dart'; import 'package:immich_mobile/domain/models/log.model.dart';
import 'package:immich_mobile/domain/models/store.model.dart'; import 'package:immich_mobile/domain/models/store.model.dart';
import 'package:immich_mobile/infrastructure/repositories/log.repository.dart'; import 'package:immich_mobile/infrastructure/repositories/log.repository.dart';
import 'package:immich_mobile/infrastructure/repositories/store.repository.dart'; import 'package:immich_mobile/infrastructure/repositories/store.repository.dart';
import 'package:immich_mobile/utils/debug_print.dart';
import 'package:logging/logging.dart'; import 'package:logging/logging.dart';
/// Service responsible for handling application logging. /// Service responsible for handling application logging.
@@ -66,13 +66,12 @@ class LogService {
} }
void _handleLogRecord(LogRecord r) { void _handleLogRecord(LogRecord r) {
if (kDebugMode) { dPrint(
debugPrint( () =>
'[${r.level.name}] [${r.time}] [${r.loggerName}] ${r.message}' '[${r.level.name}] [${r.time}] [${r.loggerName}] ${r.message}'
'${r.error == null ? '' : '\nError: ${r.error}'}' '${r.error == null ? '' : '\nError: ${r.error}'}'
'${r.stackTrace == null ? '' : '\nStack: ${r.stackTrace}'}', '${r.stackTrace == null ? '' : '\nStack: ${r.stackTrace}'}',
); );
}
final record = LogMessage( final record = LogMessage(
message: r.message, message: r.message,

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