Compare commits

..

187 Commits

Author SHA1 Message Date
Mees Frensel
3644f67f59 use single query param 2026-03-05 11:02:02 +01:00
Mees Frensel
372aad07d5 fix(web): gracefully handle map errors when WebGL is disabled 2026-02-26 17:53:38 +01:00
Mees Frensel
e454c3566b refactor: star rating (#26357)
* refactor: star rating

* transform rating 0 to null in controller dto

* migrate rating 0 to null

* deprecate rating -1

* rating type annotation

* update Rating type
2026-02-26 14:54:20 +01:00
Luis Nachtigall
4c79c3c902 feat(mobile): Prevent premature image cache eviction when higher image loading is enabled (#26208)
* feat(mobile): enhance image loading with error handling and eviction options

* pull request suggestions: remove log and remove useless local implementation
2026-02-25 17:31:37 -05:00
Alex
3bed1b6131 fix: consider DAR when extracting video dimension (#25293)
* feat: consider DAR when extracting video dimension

* move to probe

* comment

---------

Co-authored-by: mertalev <101130780+mertalev@users.noreply.github.com>
2026-02-25 21:58:53 +00:00
Brandon Wees
3c9fb651d0 feat(server): SyncAssetEditV1 (#26446)
* feat: SyncAssetEditV1

* fix: audit table import

* fix: sql tools table fetch

* fix: medium tests (wip)

* fix: circ dependency

* chore: finalize tests

* chore: codegen/lint

* fix: code review
2026-02-25 18:12:41 +00:00
Mees Frensel
55e625a2ac fix(web): error page i18n (#26517) 2026-02-25 18:35:25 +01:00
Daniel Dietzler
ca6c486a80 refactor: person stubs (#26512) 2026-02-25 08:56:00 -05:00
socksprox
d94d9600a7 fix(mobile): birthday picker shows limited months when no date exists (#26407)
* ScrollDatePicker defaults maximumDate to DateTime.now(). When no birthday exists, the picker starts at today (Feb 2026) with max also Feb 2026 — so only Jan–Feb are available for the current year.

Fix applied: Added maximumDate: DateTime(DateTime.now().year, 12, 31) at person_edit_birthday_modal.widget.dart:93, allowing all 12 months to be selected while still preventing future-year birthdays.

* fix(mobile): initialize birthday picker to past date to prevent future birthdays

When no birthday exists, initialize to 30 years ago instead of today.
This allows all 12 months to be selectable while keeping maximumDate
as DateTime.now() to prevent future birthday selection.

Fixes issue where only current months were available due to maxDate constraint.

---------

Co-authored-by: socksprox <info@shadowfly.net>
2026-02-25 07:58:02 +05:30
Mees Frensel
11e5c42bc9 fix(web): toast warning when trying to upload unsupported file type (#26492) 2026-02-24 15:58:40 -05:00
shenlong
33c6cf8325 test: backup repository (#26494)
test: backup repository tests

Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com>
2026-02-24 15:50:02 -05:00
renovate[bot]
dd97395f3a chore(deps): update dependency gunicorn to v25 (#26486)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-02-24 16:14:04 +00:00
renovate[bot]
7ae268e287 fix(deps): update dependency exiftool-vendored to v35 (#26488)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Daniel Dietzler <mail@ddietzler.dev>
2026-02-24 14:40:57 +01:00
Jason Rasmussen
f07e2b58f0 refactor: prefer buffer (#26469)
* refactor: prefer buffer

* Update server/src/schema/tables/session.table.ts

Co-authored-by: Daniel Dietzler <36593685+danieldietzler@users.noreply.github.com>

---------

Co-authored-by: Daniel Dietzler <36593685+danieldietzler@users.noreply.github.com>
2026-02-24 13:26:36 +00:00
shenlong
4b8f90aa55 refactor: remote album repository test to use context (#26481)
* refactor: remote album repository test to use context

* refactor: medium repo context (#26482)

* refactor: medium repo context

* store userId in closure

---------

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

---------

Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com>
2026-02-24 13:25:07 +00:00
Daniel Dietzler
55ee9f76da chore: eslint 10 (#26490) 2026-02-24 08:24:18 -05:00
Michel Heusschen
30f6d4439e fix(web): prevent null folder tree on concurrent load (#26489) 2026-02-24 08:23:07 -05:00
renovate[bot]
f62d98a0d1 chore(deps): update dependency eslint-plugin-unicorn to v63 (#26484)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-02-24 12:34:12 +01:00
renovate[bot]
db3d580761 chore(deps): update dependency globals to v17 (#26485)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-02-24 12:18:01 +01:00
renovate[bot]
0bc38fefe6 fix(deps): update typescript-projects (#26483)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Daniel Dietzler <mail@ddietzler.dev>
2026-02-24 11:15:26 +00:00
renovate[bot]
acc4219849 chore(deps): update actions/checkout action to v6.0.2 (#26477)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-02-24 10:09:34 +01:00
shenlong
5234e21241 fix: retain asset when either asset is a favorite (#26473)
Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com>
2026-02-23 16:52:34 -05:00
shenlong
17b327bfcd refactor: medium repository context (#26472)
refactor: repository test context

Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com>
2026-02-23 21:34:21 +00:00
Min Idzelis
d14d0a9b9b feat: add isTransparent to db (#26413) 2026-02-23 21:33:52 +00:00
Mees Frensel
bf47147fbb fix(server): accept showAt and hideAt for creating memories (#26429)
* fix(server): accept showAt and hideAt for creating memories

* fix history
2026-02-23 21:26:34 +00:00
aviv926
9ea0a69a72 feat(docs): Adding information about parameter c= (#26430)
* Adding information about parameter c=

* Apply suggestions from code review

Co-authored-by: bo0tzz <git@bo0tzz.me>

---------

Co-authored-by: Jason Rasmussen <jason@rasm.me>
Co-authored-by: bo0tzz <git@bo0tzz.me>
2026-02-23 21:21:06 +00:00
shenlong
00f43ffc25 chore: add Option type (#26467)
Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com>
2026-02-23 16:20:25 -05:00
Jonathan Jogenfors
96dc4a77a0 fix: always show library scan button (#26428)
* fix: always show library scan button

* chore: clean up

---------

Co-authored-by: Jason Rasmussen <jason@rasm.me>
2026-02-23 21:18:23 +00:00
shenlong
db7158b967 refactor: ImmichHtmlText to ImmichFormattedText (#26466)
Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com>
2026-02-23 16:05:00 -05:00
Brandon Wees
e5722c525b feat: getAssetEdits respond with edit IDs (#26445)
* feat: getAssetEdits respond with edit IDs

* chore: cleanup typings for edit API

* chore: cleanup types with jason

* fix: openapi sync

* fix: factory
2026-02-23 20:57:57 +00:00
shenlong
f616de5af8 chore(mobile): nudge users to switch to the new timeline (#26458)
* nudge users to switch to the new timeline

* remove timeline switch setting from new timeline

---------

Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com>
2026-02-23 13:42:32 -06:00
shenlong
4f39663d27 fix: simplify timeline rebuild on orientation (#26408)
* revert: current fix

# Conflicts:
#	mobile/lib/presentation/widgets/timeline/timeline.widget.dart

* fix: simpler fix

* rebase

---------

Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com>
2026-02-23 13:30:09 -05:00
Thomas
367025a3a8 chore(mobile): simplify showing details toggle (#26403)
Keeping track of the last scroll offset and guarding on scroll direction
is not necessary. The dead zone with kTouchSlop is more than sufficient,
and much simpler.

Co-authored-by: shenlong <139912620+shenlong-tanwen@users.noreply.github.com>
2026-02-23 23:49:35 +05:30
Min Idzelis
60dafecdc9 refactor: thumbnail components (#26379) 2026-02-23 11:56:20 -05:00
Yaros
16c1c3c780 fix(mobile): join local on archived timeline (#26387) 2026-02-23 20:21:32 +05:30
Brandon Wees
e633bc3f24 fix: missing deletedAt and isVisible columns on mobile (#26414)
* feat: SyncAssetV2

* feat: mobile sync handling

* feat: request correct sync object based on server version

* fix: mobile queries

* chore: sync sql

* fix: test

* chore: switch to mapper

* fix: sql sync
2026-02-23 09:50:54 -05:00
Daniel Dietzler
a07d7b0c82 chore: migrate to sql-tools library (#26400)
Co-authored-by: Jason Rasmussen <jason@rasm.me>
2026-02-23 09:50:16 -05:00
Yaros
a469d350be feat(mobile): prompt when deleting from trash (#26392)
* feat(mobile): prompt when deleting from trash

* refactor: use existing strings

* chore: use type-safe translations

* chore: remove old translation function
2026-02-23 14:45:05 +00:00
Yaros
ccab4c88bb perf(mobile): optimized album sorting (#25179)
* perf(mobile): optimized album sorting

* refactor: add index & sql query

* fix: migration

* refactor: enum, ordering & list

* test: update album service tests

* chore: fix enums

broken during merging main

* chore: remove unnecessary tests

* test: add tests for getSortedAlbumIds

* test: added back stubs in service test
2026-02-23 20:13:45 +05:30
Min Idzelis
430638e129 feat: warn when losing transparency during thumbnail generation (#26243)
* feat: preserve alpha

* refactor: use isTransparent naming and separate getImageMetadata

* warn instead of preserve
2026-02-23 08:16:28 -05:00
Thomas
caebe5166a chore(mobile): remove redundant assignment (#26404)
The view controller is already assigned during page build. Reassigning
it for every drag doesn't really make any sense.
2026-02-23 12:48:25 +00:00
Michel Heusschen
1bd28c3e78 fix(web): prevent state_unsafe_mutation error on people page (#26438) 2026-02-23 13:24:51 +01:00
Matthew Momjian
31a55aaa73 fix(web): storage template example (#26424) 2026-02-23 10:34:56 +00:00
Thomas
8b2e1509ff chore(mobile): simplify pop logic (#26410)
We have all the information we need to decide on whether we should pop
or not at the end of a drag. There's no need to track that separately,
and update the value constantly.
2026-02-23 14:49:15 +05:30
Lauritz Tieste
d0cb97f994 feat(mobile): Add slug support for shared links (#26441)
* feat(mobile): add slug support for shared links

* fix(mobile): ensure slug retains existing value when unchanged
2026-02-23 14:31:42 +05:30
Timon
f0cf3311d5 feat(mobile): Allow users to set profile picture from asset viewer (#25517)
* init

* fix

* styling

* temporary workaround for 500 error

**Root cause:**
The autogenerated Dart OpenAPI client (`UsersApi.createProfileImage()`) had two issues:
1. It set `Content-Type: multipart/form-data` without a boundary, which overrode the correct header that Dart's `MultipartRequest` would set (`multipart/form-data; boundary=...`).
2. It added the file to both `mp.fields` and `mp.files`, creating a duplicate text field.

**Result:**
Multer on the server failed to parse the multipart body, so `@UploadedFile()` was `undefined` → accessing `file.path` in `UserService.createProfileImage()` threw → **500 Internal Server Error**.

**Workaround:**
Bypass the autogenerated method in `UserApiRepository.createProfileImage()` and send the multipart request directly using the same `ApiClient` (basePath + auth), ensuring:
- No manual `Content-Type` header (let `MultipartRequest` set it with boundary)
- File only in `mp.files`, not `mp.fields`
- Proper filename fallback

* Revert "temporary workaround for 500 error"

This reverts commit 8436cd402632ca7be9272a1c72fdaf0763dcefb6.

* generate route for ProfilePictureCropPage

* add route import

* simplify

* try this

* Revert "try this"

This reverts commit fcf37d2801055c49010ddb4fd271feb900ee645a.

* try patching

* Reapply "temporary workaround for 500 error"

This reverts commit faeed810c21e4c9f0839dfff1f34aa6183469e56.

* Revert "Reapply "temporary workaround for 500 error""

This reverts commit a14a0b76d14975af98ef91748576a79cef959635.

* fix upload

* Refactor image conversion logic by introducing a new utility function. Replace inline image-to-Uint8List conversion with the new utility in EditImagePage, DriftEditImagePage, and ProfilePictureCropPage.

* use toast over snack

* format

* Revert "try patching"

This reverts commit 68a616522a1eee88c4a9755a314c0017e6450c0f.

* Enhance toast notification in ProfilePictureCropPage to include success type for better user feedback.

* Revert "simplify"

This reverts commit 8e85057a40.

* format

* add tests

* refactor to use statefulwidget

* format

---------

Co-authored-by: Alex <alex.tran1502@gmail.com>
2026-02-22 06:02:33 +00:00
Timon
3ce0654cab feat(mobile): Allow users to set album cover from mobile app (#25515)
* set album cover from asset

* add to correct kebab group

* add to album selection

* add to legacy control bottom bar

* add tests

* format

* analyze

* Revert "add to legacy control bottom bar"

This reverts commit 9d68e12a08.

* remove unnecessary event emission

* lint

* fix tests

* fix: button order and remove unncessary check

---------

Co-authored-by: Alex <alex.tran1502@gmail.com>
2026-02-22 05:53:39 +00:00
Noel S
f0e2fced57 feat(mobile): video zooming in asset viewer (#22036)
* wip

* Functional implementation, still need to bug test.

* Fixed flickering bugs

* Fixed bug with drag actions interfering with zoom panning. Fixed video being zoomable when bottom sheet is shown. Code cleanup.

* Add comments and simplify video controls

* Clearer variable name

* Fix bug where the redundant onTapDown would interfere with zooming gestures

* Fix zoom not working the second time when viewing a video.

* fix video of live photo retaining pan from photo portion

* code cleanup and simplified widget stack

---------

Co-authored-by: Alex <alex.tran1502@gmail.com>
2026-02-21 23:37:36 -06:00
Alex Balgavy
8ba20cbd44 feat: tap to see next/previous image (#20286)
* feat(mobile): tap behavior for next/previous image

This change enables switching to the next/previous photo in the photo
viewer by tapping the left/right quarter of the screen.

* Avoid animation on first/last image

* Add changes to asset_viewer.page

* Add setting for tap navigation, disable by default

Not everyone wants to have tapping for next/previous image enabled, so
this commit adds a settings toggle. Since it might be confusing behavior
for new users, it is disabled by default.

* chore: refactor

* fix: lint

---------

Co-authored-by: Alex Tran <alex.tran1502@gmail.com>
2026-02-22 05:28:17 +00:00
Mert
1d25267f22 fix(mobile): buffer width/height referenced after recycling (#26415)
recycle after getters
2026-02-21 09:41:44 -06:00
Michel Heusschen
a4d95b7aba fix(web): prevent side panel overlap during transition (#26398) 2026-02-21 09:14:53 -06:00
Min Idzelis
25d0bdc9f5 chore: replace remaining usages of npm with pnpm (#26411) 2026-02-21 08:44:33 -05:00
Michel Heusschen
905b9bd560 fix(web): album description auto height (#26420) 2026-02-21 08:43:23 -05:00
Michel Heusschen
672743f543 fix(web): escape handling on album page (#26419) 2026-02-21 08:42:31 -05:00
Michel Heusschen
27c45b5ddb fix(web): restore close action for asset viewer (#26418) 2026-02-21 10:31:30 +00:00
Peter Ombodi
82c6302549 feat(mobile): timeline - add persistentBottomBar flag (#25634)
* feat(mobile): timeline - add selectable all-assets control

* feature(mobile): introduce bottomWidgetBuilder in Timeline
remove redundant code

* fix(mobile): remove redundant code

* refactor(mobile): refactor new code in Timeline

* fix(mobile): fix format

* refactor(mobile): replace unsupported Dart syntax for analyzer compatibility

* refactor(mobile): remove Timeline.bottomSheet and migrate to bottomWidgetBuilder

* refactor(mobile): restore Timeline.bottomSheet and remove bottomWidgetBuilder
add withPersistentBottomBar param to Timeline class

* refactor(mobile): refactor var name

---------

Co-authored-by: Peter Ombodi <peter.ombodi@gmail.com>
2026-02-20 23:51:26 +05:30
Min Idzelis
aae64b5e2f test: thumbnail selector (#26383)
* test: face ordering issue/flakiness

* test: thumbnail selector
2026-02-20 15:04:17 +00:00
Benjamin Nguyen
18bf96b4b2 fix(mobile): handle userPreferencesProvider error state during sync (#26332)
fix drift_search_page render bug
2026-02-20 08:57:28 -06:00
Timon
84f2956941 fix(cli): delete sidecar files after upload if requested (#26353)
* fix(cli): delete sidecar files after upload if requested

Introduced a new function, findSidecar, to locate XMP sidecar files based on specified naming conventions. Updated the deleteFiles function to delete associated sidecar files when the main asset file is deleted. Added unit tests for findSidecar to ensure correct functionality.

* lint and format

* fix test

* chore: clean up

---------

Co-authored-by: Jason Rasmussen <jason@rasm.me>
2026-02-20 14:54:08 +00:00
Min Idzelis
6044b41648 fix: align devcontainers with standard development containers (#26321) 2026-02-20 09:37:07 -05:00
Min Idzelis
b4e16efdf4 test: face ordering issue/flakiness (#26382) 2026-02-20 09:23:40 -05:00
Min Idzelis
19da655390 fix: exiftool-vendored.exe (#26393) 2026-02-20 09:16:42 -05:00
Benjamin Nguyen
a1839b3676 fix(mobile): Reset "People" search filter chip if no selections are made (#26267)
* filter by tags

* reset people search filter chip if no selections
2026-02-20 16:37:26 +05:30
dotlambda
7461479f60 chore(ml): remove unused dependency ftfy (#25529) 2026-02-19 22:58:25 +00:00
Jason Rasmussen
01050a3d54 fix: pin code reset modal (#26370) 2026-02-19 21:50:39 +00:00
renovate[bot]
e8bedfdb7a chore(deps): update dependency @sveltejs/kit to v2.52.2 [security] (#26371)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-02-19 16:19:19 -05:00
Timon
7b4cabc2c6 chore: update task commands in web/mise.toml to use pnpm (#26345)
* chore: update task commands in mise.toml to use pnpm

* Replaced direct commands with pnpm run equivalents for consistency.
* Added new tasks for type checking and Svelte checks.
* Removed deprecated svelte-kit-sync task and adjusted dependencies accordingly.

* mroe

* chore: update mise.toml to add demo server task

* Removed the direct IMMICH_SERVER_URL setting from the environment section.
* Added a new task for starting the demo server with the IMMICH_SERVER_URL environment variable.
* Ensured consistency in task definitions.
2026-02-19 16:10:55 -05:00
David Baxter
5c7c07a09f perf: add indexes to improve People API response times (#26337)
Add SQL indexes for people search endpoints
2026-02-19 16:09:05 -05:00
Jason Rasmussen
e6ac48f4b5 refactor: app download modal (#26368) 2026-02-19 16:03:46 -05:00
Jason Rasmussen
3d4dec0cca refactor: asset actions (#26367) 2026-02-19 20:42:37 +00:00
Jason Rasmussen
1d11106dd0 refactor: add to album (#26366) 2026-02-19 15:27:30 -05:00
Timon
8eec3c810e fix(web): single select scroll behavior (#26358)
refactor(timeline): remove single select scroll behavior
2026-02-19 15:21:03 -05:00
Thomas
a43680c8b1 chore(mobile): simplify drag logic (#26291)
We were manually tracking whether gestures should be blocked, which was
a remnant of how the old code worked. This is no longer needed as we
have better heuristics for knowing whether we should skip drag updates
now.

Co-authored-by: Alex <alex.tran1502@gmail.com>
2026-02-19 14:18:44 -06:00
Jason Rasmussen
b2a510efee refactor: remove unused actions (#26363) 2026-02-19 12:52:21 -06:00
shenlong
a0077a0f51 feat(mobile): html text (#25739)
* feat: html text

* feat: mobile ui showcase (#25827)

* feat: mobile ui showcase

* remove showcase from main app

* update fonts

* update code to be loaded from asset

* fix ci

---------

Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com>
# Conflicts:
#	mobile/lib/widgets/common/immich_sliver_app_bar.dart

---------

Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com>
2026-02-19 12:27:16 -06:00
Thomas
aa02310d63 chore(mobile): cleanup asset viewer state (#26300)
initState was quite noisy, so I've moved some things around and made the
intention a bit clearer.

Co-authored-by: Alex <alex.tran1502@gmail.com>
2026-02-19 12:26:21 -06:00
renovate[bot]
7394fa1491 chore(deps): update dependency svelte to v5.51.5 [security] (#26352)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-02-19 17:11:56 +00:00
Mees Frensel
99f7eb4ce6 chore(server): remove redundant nullish checks (#26354) 2026-02-19 17:09:12 +00:00
Timon
ffd54d0431 fix(i18n): add translation key for partner's photos (#26348)
* fix(i18n): add translation key for partner's photos

* reuse existing key
2026-02-19 10:53:19 -06:00
Michel Heusschen
7005e9fc50 fix(web): update @immich/ui to v0.64.0 (#26351) 2026-02-19 16:33:06 +00:00
Michel Heusschen
4f2e6e3f15 fix(web): favoriting assets opened via GalleryViewer (#26350)
fix(web): favoriting assets through GalleryViewer
2026-02-19 10:32:25 -06:00
Michel Heusschen
8b5fc3d8bc fix(web): prevent panorama image reload during asset updates (#26349) 2026-02-19 10:31:30 -06:00
Thomas
0fa385c465 fix(mobile): infer drag intent early (#26344)
The drag intent was not set until it reached the kTouchSlop threshold.
This is not necessary as flutter already has its own heuristics for
preventing unintended drags.

The result of using kTouchSlop is that dismissing or scroll can feel a
little delayed, and will jump from 0 to kTouchSlop (18px) rather than
moving smoothly.
2026-02-19 09:56:51 -06:00
Daniel Dietzler
db4e7abf6d chore: refactor more queries (#25572)
* refactor: asset service queries

* chore: refactor more queries
2026-02-19 10:48:30 -05:00
Thomas
dadd20acfc chore(mobile): reduce the asset details snap target (#26343)
We were snapping to 75%, but 66.6% may be more natural.

Co-authored-by: Alex <alex.tran1502@gmail.com>
2026-02-19 15:48:21 +00:00
Jason Rasmussen
f04efbb714 fix: safari address bar color (#26346) 2026-02-19 09:40:13 -06:00
Timon
208c07af1f chore(web): merge "Add to album" and "Add to shared album" actions into a single action (#24669)
* refactor: simplify album selection actions by removing shared option

* Removed the shared option from AddToAlbumAction and related components.
* Updated AlbumPickerModal and other components to reflect this change.
* Cleaned up related tests and documentation for consistency.

* fix lint
2026-02-19 16:15:26 +01:00
Jason Rasmussen
72a5ccaa53 feat: editing descriminator (#26336) 2026-02-19 09:15:56 -05:00
Daniel Dietzler
fd0338f89c refactor: asset service queries (#25535) 2026-02-19 08:54:28 -05:00
Daniel Dietzler
d0ed76dc37 refactor: small face tests (#26340) 2026-02-19 08:51:18 -05:00
renovate[bot]
e0bb5f70ec fix(deps): update dependency fabric to v7 [security] (#26342)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-02-19 12:28:12 +00:00
Timon
f965daa8d2 chore: remove push trigger for check-openapi workflow (#26341) 2026-02-19 13:14:26 +01:00
Timon
316f86d25e feat: add .mxf file support (#24644)
* feat: add support for MXF format in media handling

* Updated supported formats documentation to include MXF.
* Added MXF to valid video extensions in tests.
* Registered MXF MIME type in mime-types utility.

* fix: enhance MXF handling in mime-types utility

* Updated video mime type validation to include 'application/mxf'.
* Adjusted asset type determination to recognize MXF as a video container.

* chore: clean up

---------

Co-authored-by: Jason Rasmussen <jason@rasm.me>
2026-02-19 06:39:41 +00:00
Hao Xi
e520fc3b63 fix: include DROP INDEX in transaction to prevent missing index on rollback (#25399)
* fix: ERR_PNPM_ENOENT error while `make dev` on macOS.

* fix: include `DROP INDEX` in transaction to prevent missing index on rollback.

* chore: clean up this PR.
2026-02-19 06:20:36 +00:00
Jonathan Jogenfors
b3b9834c00 feat(web): loop chromecast video (#24410) 2026-02-18 20:29:13 -05:00
Mees Frensel
84f7fb63ee feat(web): show ocr text boxes in panoramas (#25727) 2026-02-18 20:04:18 -05:00
Jorge Montejo
1f8359ead4 fix: Download the edited version when downloading multiple photos (#26259)
* fix: download the edited version when downloading multiple photos

* test: update tests

* chore: clean up

---------

Co-authored-by: Jason Rasmussen <jason@rasm.me>
2026-02-18 21:47:45 +00:00
Fabio Garavini
ea30c9d2ba fix(server): db restore failure when DB_URL is set to unix-domain socket connection (#26252)
* fix db restore fails to get postgres user

* Apply suggestion from @danieldietzler

Co-authored-by: Daniel Dietzler <36593685+danieldietzler@users.noreply.github.com>

* fix fallback to reasonable default test

---------

Co-authored-by: Daniel Dietzler <36593685+danieldietzler@users.noreply.github.com>
2026-02-18 16:37:40 -05:00
Dusan Hlavaty
d1abdea420 chore(docs): add quick-start guide for DevPod with docker (#26213) 2026-02-18 16:26:09 -05:00
Benjamin Nguyen
ae8dad68fc feat(mobile): filter by tags (#26196)
filter by tags
2026-02-18 21:16:26 +00:00
renovate[bot]
227ff70b6e chore(deps): update dependency ajv to v8.18.0 [security] (#26297)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-02-18 16:06:43 -05:00
bo0tzz
ee7ac09450 fix: bad field paste in metadata.service.spec (#26329)
Caused https://github.com/immich-app/immich/actions/runs/22153269773/job/64050176244 to flake
2026-02-18 16:04:32 -05:00
Devansh H Jani
2e59dbdc12 fix: prevent server crash when extraction of metadata fails if the assets are corrupted (#26042)
* Fix-25968 Extraction of metadata fails if the assets are corrupted

* chore: clean up

---------

Co-authored-by: Jason Rasmussen <jason@rasm.me>
2026-02-18 15:53:23 -05:00
Timon
c4c7f94317 chore: add OpenAPI check workflow (#26223) 2026-02-18 15:16:01 -05:00
Jason Rasmussen
d004d7e21b fix: metadata crash (#26327) 2026-02-18 15:09:35 -05:00
Timon
5f95aab437 chore: align mobile mise tasks (#26237)
* chore: align mobile mise tasks

* fix
2026-02-18 14:11:01 -05:00
Michel Heusschen
dd632f38de fix(web): unblock escape after opening context menu (#26325) 2026-02-18 14:10:15 -05:00
renovate[bot]
6f7fc94710 chore(deps): update github-actions (#25388)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-02-18 19:53:41 +01:00
renovate[bot]
85cb515cae chore(deps): update dependency github:cqlabs/homebrew-dcm to v1.35.1 (#26278)
* chore(deps): update dependency github:cqlabs/homebrew-dcm to v1.35.1

* fix static analysis

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com>
2026-02-18 23:47:54 +05:30
bo0tzz
65e1bb83b7 fix: use wrangler cli directly (#26326) 2026-02-18 18:06:41 +00:00
bo0tzz
d9b1b69827 fix: switch docs-deploy to use wrangler-action (#26323) 2026-02-18 18:45:43 +01:00
Min Idzelis
b2050583f5 chore: run maintenance test (e2e) in isolation too, share containers (#26246) 2026-02-18 09:39:13 -05:00
Keunes
1bdc24c730 feat(docs): Explain configuration file location for Docker Compose (#24989)
* Explain configuration file location for Docker Compose

* Update config-file.md

* Update config-file.md

* Update config-file.md

---------

Co-authored-by: Mees Frensel <33722705+meesfrensel@users.noreply.github.com>
2026-02-18 14:52:28 +01:00
renovate[bot]
5adb75c272 fix(deps): update dependency @mapbox/mapbox-gl-rtl-text to v0.3.0 (#23353)
* fix(deps): update dependency @mapbox/mapbox-gl-rtl-text to v0.3.0

* fix: maplibre rtl import

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Daniel Dietzler <mail@ddietzler.dev>
2026-02-18 12:05:41 +01:00
Daniel Dietzler
8f9ea6a171 fix: utc time zone upserts (#26258)
fix: utc timezone upserts
2026-02-17 18:59:52 +01:00
Thomas
3f41916ad7 chore(mobile): fix asset marker icon file name (#26290) 2026-02-17 11:53:44 -05:00
Thomas
5c6433b4ca feat(mobile): inline asset details (#25952)
The existing implementation for showing asset details uses a bottom
sheet, and is not in sync with the preview or scroll intent. Other apps
use inline details, which is much cleaner and feels better to use.
2026-02-17 09:24:34 -06:00
Damien Nozay
06d487782e fix(release): add docker-compose.rootless.yml to released assets (#26261)
* fix(release): add docker-compose files to released assets

Since there is a warning:
"Make sure to use the docker-compose.yml of the current release"

This should apply to other docker-compose files, so it would make sense to release them.

It also makes it slightly easier to get the asset for rootless (e.g., PR 2750).

* release docker-compose.rootless.yml
2026-02-17 12:55:34 +01:00
Min Idzelis
455afbb119 ci: fix formatting task (#26274) 2026-02-17 12:51:15 +01:00
ewinnd
0767ae0c8a fix(docs): remove truenas link from synology community guide (#26277)
* Update synology.md to remove Truenas link

Removed link to Truenas github community repo.

* remove blank line

---------

Co-authored-by: Mees Frensel <33722705+meesfrensel@users.noreply.github.com>
2026-02-17 12:50:11 +01:00
renovate[bot]
a16a00ebd4 fix(deps): update typescript-projects (#26276)
* fix(deps): update typescript-projects

* chore: downgrade kysely

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Daniel Dietzler <mail@ddietzler.dev>
2026-02-17 11:50:02 +00:00
renovate[bot]
398b750ef7 chore(deps): update dependency github:extism/js-pdk to v1.6.0 (#26279)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-02-17 12:49:14 +01:00
renovate[bot]
18bbb5b4db chore(deps): update node.js to v24.13.1 (#26275)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-02-17 11:45:57 +01:00
renovate[bot]
b3c37905f7 chore(deps): update dependency @types/node to ^24.10.13 (#26273)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-02-17 11:44:38 +01:00
renovate[bot]
90ef6c4e28 chore(deps): update docker.io/valkey/valkey:9 docker digest to 930b414 (#26272)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-02-17 11:44:21 +01:00
Michel Heusschen
ceef65154d fix(web): clear cache when asset changes (#26257)
* fix(web): clear cache when asset changes

* formatting
2026-02-17 11:43:08 +01:00
Joren Guillaume
de7b42eb23 chore(docs): Update help channel for developers (#26284)
Update help channel for developers
2026-02-17 11:39:43 +01:00
Min Idzelis
75bdd6a644 fix: development containers init race conditions (#25876) 2026-02-16 18:34:42 -05:00
Michel Heusschen
0da74569f2 fix(web): clear unsaved asset description when changing asset (#26255)
* fix(web): clear unsaved asset description when changing asset

* remove unneeded $derived
2026-02-16 18:25:13 +01:00
Michel Heusschen
cc9c261fd0 fix(web): clear face boxes when switching assets (#26249) 2026-02-16 15:52:34 +01:00
Michel Heusschen
4dccc2082b fix(web): focus tag input when modal opens (#26256) 2026-02-16 14:30:41 +00:00
shenlong
9211013996 fix: bring back timeline args auto-scoping (#26219)
Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com>
2026-02-16 08:20:28 -06:00
Alex
156e3479fa chore: styling tweak profile panel (#26248) 2026-02-16 08:20:01 -06:00
Min Idzelis
19ef196150 chore: quiet down dotenv (#26245) 2026-02-15 22:25:18 -06:00
Thomas
d2682f160e fix(mobile): inherit toolbar opacity (#25694)
Some widgets, like Icon widgets, automatically inherit opacity from the
icon theme in the context. Many other widgets however, do not. The
Immich logo, profile picture, and backup badge are examples of widgets
of this.

All unsupported toolbar widgets have been updated to support inheriting
the opacity from the icon theme.

IconButtons internally animate properties like opacity, which is kind of
nice, but means we have to do more work to replicate that behaviour for
other widgets. In most cases, we can simply use an IconButton widget and
forward the correct opacity. The Immich logo however is not a button,
and therefore we need to use a custom TweenAnimationBuilder.

All widgets are using efficient, native opacity rather than the heavy
Opacity widget.
2026-02-16 09:54:57 +05:30
Nicolas
c9dd8e0a79 feat(mobile): hide search by context/OCR if disabled on server (#25472) (#26063)
* feat(mobile): hide search by context/OCR if disabled on server (#25472)

* revert(mobile): remove changes to old search page

---------

Co-authored-by: Nicolas <nicolasroy@MacBookPro>
2026-02-16 08:11:56 +05:30
Dusan Hlavaty
f6e10afe2b chore(docs): fix discord channel in docs (#26238) 2026-02-15 21:34:02 +01:00
Thomas
5f87047490 feat(mobile): dynamic multi-line album name (#26040)
* feat(mobile): dynamic multi-line album name

Album names are currently limited to a single line, and scroll on
overflow. It would be better if album names were multi-line, and even
better if the font size was dynamic depending on how many lines there
are. The album name should then overflow with an ellipsis.

This is actually quite similar to how Google Photos handles album names.

* lint

---------

Co-authored-by: timonrieger <mail@timonrieger.de>
2026-02-15 22:23:45 +05:30
Daniel Dietzler
75e3b0467a chore: hyperlink contributing file in llm message (#26234) 2026-02-15 10:51:47 +00:00
bo0tzz
df4c25e567 fix: use pull_request_target in close-llm-pr.yml (#26232)
So that it actually has write permissions; this should be safe as it doesn't use any external input.
2026-02-15 11:47:01 +01:00
Michel Heusschen
ff7dca35f5 perf(web): speed up asset selection (#26216) 2026-02-14 15:31:04 -05:00
Alex
49ba833e4c fix(web): Revert "add checkerboard background for transparent images (#26091)" (#26220)
Revert "fix(web): add checkerboard background for transparent images (#26091)"

This reverts commit bc7a1c838c.
2026-02-14 20:25:14 +00:00
Michel Heusschen
9ab887d5d2 perf(web): speed up multi asset operations (#26217) 2026-02-14 15:24:47 -05:00
Min Idzelis
d264e78d3f chore: pnpm workspace protocol for sibling packagages (#26218) 2026-02-14 15:03:08 -05:00
Min Idzelis
2c9d69865c fix: e2e exit 135 (#26214) 2026-02-14 12:51:54 -05:00
bo0tzz
72cefcabaf chore: discourage LLM-generated PRs (#26211)
* chore: discourage LLM-generated PRs

* chore: add reading CONTRIBUTING.md to PR checklist

* chore: workflow to close LLM-generated PRs
2026-02-14 10:40:27 -06:00
Xantin
2fb9f84b56 refactor(i18n): Follow IETF standard (#26171)
* refactor(18n):  Follow IETF standard

Rename zh_SIMPLIFIED to zh_Hans

Makes it easier to merge #21337

* fix(web): zh_SIMPLIFIED -> zh_Hans
2026-02-13 18:47:41 +01:00
Weblate (bot)
434ded92f5 chore(web): update translations (#26167)
Translate-URL: https://hosted.weblate.org/projects/immich/immich/ca/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/cs/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/es/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/et/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/fr/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/ga/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/it/
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/ru/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/sk/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/sl/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/th/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/yue_Hant/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/zh_Hant/
Translation: Immich/immich

Co-authored-by: Aindriú Mac Giolla Eoin <aindriu80@gmail.com>
Co-authored-by: DevServs <bonov@mail.ru>
Co-authored-by: Happy <59247878+happy2452354@users.noreply.github.com>
Co-authored-by: Indrek Haav <indrek.haav@hotmail.com>
Co-authored-by: Jozef Gaal <preklady@mayday.sk>
Co-authored-by: Kuba <kubaant@gmail.com>
Co-authored-by: Matjaž T. <matjaz@moj-svet.si>
Co-authored-by: Michel Heusschen <59014050+michelheusschen@users.noreply.github.com>
Co-authored-by: PPNplus <ppnplus@protonmail.com>
Co-authored-by: Sylvain Pichon <service@spichon.fr>
Co-authored-by: Ulices <hasecilu@tuta.io>
Co-authored-by: Yu-Hsuan Liao <EMC521@outlook.com>
Co-authored-by: albanobattistella <albano_battistella@hotmail.com>
Co-authored-by: jcreusand <joan.creusandreu@gmail.com>
Co-authored-by: waclaw66 <waclaw66@seznam.cz>
Co-authored-by: Óscar Fernández Díaz <42654671+oscfdezdz@users.noreply.github.com>
2026-02-13 17:45:35 +00:00
agent-steven
bc7a1c838c fix(web): add checkerboard background for transparent images (#26091)
Co-authored-by: steven94kr <rlgns98kr@gmail.com>
Co-authored-by: Daniel Dietzler <36593685+danieldietzler@users.noreply.github.com>
2026-02-13 17:18:44 +00:00
Daniel Dietzler
7cb355279e chore: remove asset stubs (#26187) 2026-02-13 11:00:31 -05:00
Nykri
ecb09501a5 feat(cli): change progress bar to display file size (#23328)
* Change progress bar to display file size

* Solved lint errors
2026-02-13 10:22:00 -05:00
Michel Heusschen
34eb2e1410 fix(web): timeline multi select group state (#26180) 2026-02-13 08:34:15 -05:00
shenlong
2d6580acd8 feat(mobile): dynamic layout in new timeline (#23837)
* feat(mobile): dynamic layout in new timeline

* simplify _buildAssetRow

* auto dynamic mode on smaller column count

* auto layout on smaller tiles

---------

Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com>
2026-02-13 09:15:42 +05:30
Yaros
9aa3fe82c1 fix(mobile): inconsistent query for people (#24437)
* fix(mobile): inconsistent query for people

* refactor: implement suggestions

* refactor: refactored query impl suggestions
2026-02-13 09:13:21 +05:30
Arne Schwarck
66733eb4c0 feat: add people deeplink (#25686)
* Change path prefix from '/memories/' to '/people/'

Updated the AndroidManifest.xml to change the path prefix from '/memories/' to '/people/'.
Memories is anyway wrong and was replaced by /memory
and now the people path completes the known deeplinks.

* Add regex for people deep link handling

Add regex for people deep link handling

* Add deep link handling for 'people' route

* fix: missing person route builder method

---------

Co-authored-by: bwees <brandonwees@gmail.com>
2026-02-13 09:13:04 +05:30
Thomas
e5156df4f1 fix(mobile): hide latest version warnings (#26036)
The latest version is already hidden in the server info widget if
disabled (https://github.com/immich-app/immich/pull/25691), however I
did not realise there are more places where this warning is shown. This
hides the warning everywhere, and cleans up the code a bit.
2026-02-13 08:15:25 +05:30
Jason Rasmussen
8ef4e4d452 feat: schema-check (#25904) 2026-02-12 17:59:00 -05:00
Christos Longros
7413356a2f fix: clarify external domain translation (#26009)
* fix: clarify external domain setting is used for emails too (#24950)

* Update i18n/en.json

Co-authored-by: Jason Rasmussen <jason@rasm.me>

---------

Co-authored-by: Jason Rasmussen <jason@rasm.me>
2026-02-12 14:01:51 -05:00
Jason Rasmussen
5bf4e9595c refactor: purchase store (#25734) 2026-02-12 13:32:17 -05:00
renovate[bot]
6c0c4b3dda chore(deps): update docker.io/valkey/valkey:9 docker digest to 930b414 (#26087)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-02-12 12:36:46 -05:00
Yaros
206a208410 feat(web): change link expiration logic & presets (#26064)
* feat(web): link expiration presets

* refactor: implement suggestions

* chore: remove createdAt prop

* fix: tests

* fix: button keys
2026-02-12 18:27:49 +01:00
Jason Rasmussen
72cef8b94b feat: shared link login (#25678) 2026-02-12 12:08:38 -05:00
Jason Rasmussen
81c93101a0 feat: verify permissions (#25647) 2026-02-12 12:08:20 -05:00
Christos Longros
b06c21325e fix(mobile): prevent nav bar label text wrapping (#26011)
* fix(mobile): prevent nav bar label text wrapping (#25921)

* chore: fix format

---------

Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com>
2026-02-12 16:57:03 +00:00
Bastian Köcher
730b770e67 fix(mobile): timeline orientation & foldable phones handling (#25088)
* [mobile]: Fix timeline handling on foldable phones + ensuring that images are not cut off

This fixes the handling of unfolding the phone while having the application opened. So,
the timeline is correctly rescaled and the current position is kept.
Besides that it fixes a bug with the ordering which lead to images being "cut off" at the right side
of the screen.

* refactor + cleanup

---------

Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com>
2026-02-12 22:20:00 +05:30
Michel Heusschen
b85f6f3fce fix(web): add missing @immich/ui translations (#26143) 2026-02-12 16:42:35 +00:00
Min Idzelis
81f592ca52 feat: remove Cache API, rework preload(), cancel() and fetch() (#25289)
* feat: remove Cache API, rework preload(), cancel() and fetch()

perf - replace broadcast channel with direct postMessage

* remove sw response handling

* review comments
2026-02-12 11:25:20 -05:00
renovate[bot]
a62e8ed179 fix(deps): update typescript-projects (#25549)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Daniel Dietzler <mail@ddietzler.dev>
2026-02-12 16:24:04 +00:00
Michel Heusschen
1cf3a80840 fix(web): show correct assets in memory gallery (#26157) 2026-02-12 11:17:09 -05:00
Klenner Martins Barros
9f6dbf710c fix(web): improve api key modal responsiveness (#26151) 2026-02-12 17:13:09 +01:00
Michel Heusschen
f207f99e86 fix(web): prevent event manager from throwing error (#26156) 2026-02-12 11:09:15 -05:00
Thomas
0d35231dfd chore(mobile): cleanup server storage info (#26038)
The server storage info has a lot of whitespace due to the ListTile.
Converting it to be inline makes the styling appear more intentional.

There are also a few semantically relevant list items in the app bar
dialog which have been grouped together.
2026-02-12 21:09:55 +05:30
shenlong
675bbf3ac3 chore: remove unused key and fix casing for recent_albums (#24691)
Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com>
2026-02-12 16:06:22 +01:00
Weblate (bot)
c45450b6ac chore(web): update translations (#26118)
Translate-URL: https://hosted.weblate.org/projects/immich/immich/de/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/hi/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/lt/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/ro/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/sv/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/ta/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/th/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/tr/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/zh_Hant/
Translate-URL: https://hosted.weblate.org/projects/immich/immich/zh_SIMPLIFIED/
Translation: Immich/immich

Co-authored-by: Anton Palmqvist <apq@users.noreply.hosted.weblate.org>
Co-authored-by: PPNplus <ppnplus@protonmail.com>
Co-authored-by: Rishi <rishikesh.200@gmail.com>
Co-authored-by: TV Box <realceday.tvbox@gmail.com>
Co-authored-by: Vivek M <vivekmalhotra004@gmail.com>
Co-authored-by: WellsTsai <dan50907@gmail.com>
Co-authored-by: czlevi7 <czlevi7@gmail.com>
Co-authored-by: jässin <aouanijassin@gmail.com>
Co-authored-by: muziqaz <muziqaz@users.noreply.hosted.weblate.org>
Co-authored-by: pyccl <changcongliang@163.com>
2026-02-12 15:02:07 +00:00
renovate[bot]
fea6e8d9f3 chore(deps): update dependency python-multipart to v0.0.22 [security] (#25559) 2026-02-12 09:32:59 -05:00
renovate[bot]
27ebbab1d9 fix(deps): update dependency pillow to v12 [security] (#26142) 2026-02-12 09:32:17 -05:00
renovate[bot]
4647ecf2ea chore(deps): update machine-learning (#25067) 2026-02-12 09:31:13 -05:00
shenlong
78c8f1d5a9 chore: add indexes for foreign keys (#25925)
* chore: add indexes for foreign keys

* update idx_asset_face_person_id index

---------

Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com>
2026-02-12 19:58:31 +05:30
shenlong
ec4de54ea2 fix: null local date time in timeline queries (#26133)
* fix: null local date time in timeline queries

* refactor effectiveCreatedAt

---------

Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com>
2026-02-12 19:58:00 +05:30
Peter Ombodi
420cd5193b fix(mobile): Login routing on Splash screen (#26128)
* fix(mobile): fix Login routing on Splash screen

* fix(mobile): remove _duplicateGuard from the LoginRoute
revert changes in splash_screen

---------

Co-authored-by: Peter Ombodi <peter.ombodi@gmail.com>
2026-02-12 19:57:43 +05:30
Daniel Dietzler
7e0356e227 refactor: more small tests (#26159) 2026-02-12 08:34:32 -05:00
Michel Heusschen
913904f418 fix(web): escape shortcut handling (#26096) 2026-02-11 18:55:28 +01:00
Daniel Dietzler
e54678e0d6 refactor: small tests (#26141) 2026-02-11 11:49:00 -05:00
Daniel Dietzler
222c90b7b7 chore: remove album stubs (#26130) 2026-02-11 09:12:46 -05:00
Michel Heusschen
1c1a000c78 fix(web): use locale for date picker (#26125) 2026-02-11 11:39:30 +01:00
Jason Rasmussen
458d5f0f8f fix: ignore checksum constraint error when logging (#26113) 2026-02-10 20:43:55 +00:00
Jason Rasmussen
4c948647fc chore: asset-job medium tests (#26111) 2026-02-10 13:41:40 -05:00
834 changed files with 38962 additions and 22658 deletions

View File

@@ -2,6 +2,7 @@
"name": "Immich - Backend, Frontend and ML",
"service": "immich-server",
"runServices": [
"immich-init",
"immich-server",
"redis",
"database",
@@ -31,29 +32,8 @@
"tasks": {
"version": "2.0.0",
"tasks": [
{
"label": "Fix Permissions, Install Dependencies",
"type": "shell",
"command": "[ -f /immich-devcontainer/container-start.sh ] && /immich-devcontainer/container-start.sh || exit 0",
"isBackground": true,
"presentation": {
"echo": true,
"reveal": "always",
"focus": false,
"panel": "dedicated",
"showReuseMessage": true,
"clear": false,
"group": "Devcontainer tasks",
"close": true
},
"runOptions": {
"runOn": "default"
},
"problemMatcher": []
},
{
"label": "Immich API Server (Nest)",
"dependsOn": ["Fix Permissions, Install Dependencies"],
"type": "shell",
"command": "[ -f /immich-devcontainer/container-start-backend.sh ] && /immich-devcontainer/container-start-backend.sh || exit 0",
"isBackground": true,
@@ -74,7 +54,6 @@
},
{
"label": "Immich Web Server (Vite)",
"dependsOn": ["Fix Permissions, Install Dependencies"],
"type": "shell",
"command": "[ -f /immich-devcontainer/container-start-frontend.sh ] && /immich-devcontainer/container-start-frontend.sh || exit 0",
"isBackground": true,
@@ -130,8 +109,8 @@
}
},
"overrideCommand": true,
"workspaceFolder": "/workspaces/immich",
"remoteUser": "node",
"workspaceFolder": "/usr/src/app",
"remoteUser": "root",
"userEnvProbe": "loginInteractiveShell",
"remoteEnv": {
// The location where your uploaded files are stored

View File

@@ -1,23 +1,17 @@
services:
immich-app-base:
image: busybox
immich-server:
extends:
service: immich-app-base
profiles: !reset []
image: immich-server-dev:latest
build:
target: dev-container-mobile
environment:
- IMMICH_SERVER_URL=http://127.0.0.1:2283/
volumes: !override # bind mount host to /workspaces/immich
- ..:/workspaces/immich
volumes:
- ${UPLOAD_LOCATION:-upload-devcontainer-volume}${UPLOAD_LOCATION:+/photos}:/data
- pnpm-store:/usr/src/app/.pnpm-store
- server-node_modules:/usr/src/app/server/node_modules
- web-node_modules:/usr/src/app/web/node_modules
- github-node_modules:/usr/src/app/.github/node_modules
- cli-node_modules:/usr/src/app/cli/node_modules
- docs-node_modules:/usr/src/app/docs/node_modules
- e2e-node_modules:/usr/src/app/e2e/node_modules
- sdk-node_modules:/usr/src/app/open-api/typescript-sdk/node_modules
- app-node_modules:/usr/src/app/node_modules
- sveltekit:/usr/src/app/web/.svelte-kit
- coverage:/usr/src/app/web/coverage
- /etc/localtime:/etc/localtime:ro
immich-web:
env_file: !reset []

View File

@@ -2,6 +2,7 @@
"name": "Immich - Mobile",
"service": "immich-server",
"runServices": [
"immich-init",
"immich-server",
"redis",
"database",
@@ -35,7 +36,7 @@
},
"forwardPorts": [],
"overrideCommand": true,
"workspaceFolder": "/workspaces/immich",
"workspaceFolder": "/usr/src/app",
"remoteUser": "node",
"userEnvProbe": "loginInteractiveShell",
"remoteEnv": {

View File

@@ -2,11 +2,6 @@
export IMMICH_PORT="${DEV_SERVER_PORT:-2283}"
export DEV_PORT="${DEV_PORT:-3000}"
# search for immich directory inside workspace.
# /workspaces/immich is the bind mount, but other directories can be mounted if runing
# Devcontainer: Clone [repository|pull request] in container volumne
WORKSPACES_DIR="/workspaces"
IMMICH_DIR="$WORKSPACES_DIR/immich"
IMMICH_DEVCONTAINER_LOG="$HOME/immich-devcontainer.log"
log() {
@@ -30,52 +25,8 @@ run_cmd() {
return "${PIPESTATUS[0]}"
}
# Find directories excluding /workspaces/immich
mapfile -t other_dirs < <(find "$WORKSPACES_DIR" -mindepth 1 -maxdepth 1 -type d ! -path "$IMMICH_DIR" ! -name ".*")
if [ ${#other_dirs[@]} -gt 1 ]; then
log "Error: More than one directory found in $WORKSPACES_DIR other than $IMMICH_DIR."
exit 1
elif [ ${#other_dirs[@]} -eq 1 ]; then
export IMMICH_WORKSPACE="${other_dirs[0]}"
else
export IMMICH_WORKSPACE="$IMMICH_DIR"
fi
export IMMICH_WORKSPACE="/usr/src/app"
log "Found immich workspace in $IMMICH_WORKSPACE"
log ""
fix_permissions() {
log "Fixing permissions for ${IMMICH_WORKSPACE}"
# Change ownership for directories that exist
for dir in "${IMMICH_WORKSPACE}/.vscode" \
"${IMMICH_WORKSPACE}/server/upload" \
"${IMMICH_WORKSPACE}/.pnpm-store" \
"${IMMICH_WORKSPACE}/.github/node_modules" \
"${IMMICH_WORKSPACE}/cli/node_modules" \
"${IMMICH_WORKSPACE}/e2e/node_modules" \
"${IMMICH_WORKSPACE}/open-api/typescript-sdk/node_modules" \
"${IMMICH_WORKSPACE}/server/node_modules" \
"${IMMICH_WORKSPACE}/server/dist" \
"${IMMICH_WORKSPACE}/web/node_modules" \
"${IMMICH_WORKSPACE}/web/dist"; do
if [ -d "$dir" ]; then
run_cmd sudo chown node -R "$dir"
fi
done
log ""
}
install_dependencies() {
log "Installing dependencies"
(
cd "${IMMICH_WORKSPACE}" || exit 1
export CI=1 FROZEN=1 OFFLINE=1
run_cmd make setup-web-dev setup-server-dev
)
log ""
}

View File

@@ -1,26 +1,21 @@
services:
immich-app-base:
image: busybox
immich-server:
extends:
service: immich-app-base
profiles: !reset []
image: immich-server-dev:latest
build:
target: dev-container-server
env_file: !reset []
hostname: immich-dev
environment:
- IMMICH_SERVER_URL=http://127.0.0.1:2283/
volumes: !override
- ..:/workspaces/immich
volumes:
- ${UPLOAD_LOCATION:-upload-devcontainer-volume}${UPLOAD_LOCATION:+/photos}:/data
- /etc/localtime:/etc/localtime:ro
- 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
- pnpm_store_server:/buildcache/pnpm-store
- ../plugins:/build/corePlugin
immich-web:
env_file: !reset []

View File

@@ -1,17 +0,0 @@
#!/bin/bash
# shellcheck source=common.sh
# shellcheck disable=SC1091
source /immich-devcontainer/container-common.sh
log "Setting up Immich dev container..."
fix_permissions
log "Setup complete, please wait while backend and frontend services automatically start"
log
log "If necessary, the services may be manually started using"
log
log "$ /immich-devcontainer/container-start-backend.sh"
log "$ /immich-devcontainer/container-start-frontend.sh"
log
log "From different terminal windows, as these scripts automatically restart the server"
log "on error, and will continuously run in a loop"

2
.github/.nvmrc vendored
View File

@@ -1 +1 @@
24.13.0
24.13.1

View File

@@ -26,6 +26,7 @@ The `/api/something` endpoint is now `/api/something-else`
## Checklist:
- [ ] I have carefully read CONTRIBUTING.md
- [ ] I have performed a self-review of my own code
- [ ] I have made corresponding changes to the documentation if applicable
- [ ] I have no unrelated changes in the PR.

View File

@@ -51,14 +51,14 @@ jobs:
should_run: ${{ steps.check.outputs.should_run }}
steps:
- id: token
uses: immich-app/devtools/actions/create-workflow-token@da177fa133657503ddb7503f8ba53dccefec5da1 # create-workflow-token-action-v1.0.0
uses: immich-app/devtools/actions/create-workflow-token@05e16407c0a5492138bb38139c9d9bf067b40886 # create-workflow-token-action-v1.0.1
with:
app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
- name: Check what should run
id: check
uses: immich-app/devtools/actions/pre-job@08bac802a312fc89808e0dd589271ca0974087b5 # pre-job-action-v2.0.0
uses: immich-app/devtools/actions/pre-job@eed0f8b8165ffcb951f2ba854b2dd031935e1d73 # pre-job-action-v2.0.2
with:
github-token: ${{ steps.token.outputs.token }}
filters: |
@@ -79,12 +79,12 @@ jobs:
steps:
- id: token
uses: immich-app/devtools/actions/create-workflow-token@da177fa133657503ddb7503f8ba53dccefec5da1 # create-workflow-token-action-v1.0.0
uses: immich-app/devtools/actions/create-workflow-token@05e16407c0a5492138bb38139c9d9bf067b40886 # create-workflow-token-action-v1.0.1
with:
app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
ref: ${{ inputs.ref || github.sha }}
persist-credentials: false
@@ -96,14 +96,14 @@ jobs:
working-directory: ./mobile
run: printf "%s" $KEY_JKS | base64 -d > android/key.jks
- uses: actions/setup-java@f2beeb24e141e01a676f977032f5a29d81c9e27e # v5.1.0
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
with:
distribution: 'zulu'
java-version: '17'
- name: Restore Gradle Cache
id: cache-gradle-restore
uses: actions/cache/restore@9255dc7a253b0ccc959486e2bca901246202afeb # v5.0.1
uses: actions/cache/restore@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3
with:
path: |
~/.gradle/caches
@@ -160,7 +160,7 @@ jobs:
- name: Save Gradle Cache
id: cache-gradle-save
uses: actions/cache/save@9255dc7a253b0ccc959486e2bca901246202afeb # v5.0.1
uses: actions/cache/save@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3
if: github.ref == 'refs/heads/main'
with:
path: |
@@ -185,7 +185,7 @@ jobs:
run: sudo xcode-select -s /Applications/Xcode_26.2.app/Contents/Developer
- name: Checkout code
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
ref: ${{ inputs.ref || github.sha }}
persist-credentials: false

View File

@@ -19,13 +19,13 @@ jobs:
actions: write
steps:
- id: token
uses: immich-app/devtools/actions/create-workflow-token@da177fa133657503ddb7503f8ba53dccefec5da1 # create-workflow-token-action-v1.0.0
uses: immich-app/devtools/actions/create-workflow-token@05e16407c0a5492138bb38139c9d9bf067b40886 # create-workflow-token-action-v1.0.1
with:
app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
- name: Check out code
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
token: ${{ steps.token.outputs.token }}

32
.github/workflows/check-openapi.yml vendored Normal file
View File

@@ -0,0 +1,32 @@
name: Check OpenAPI
on:
workflow_dispatch:
pull_request:
paths:
- 'open-api/**'
- '.github/workflows/check-openapi.yml'
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions: {}
jobs:
check-openapi:
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- name: Check for breaking API changes
# sha is pinning to a commit instead of a tag since the action does not tag versions
uses: oasdiff/oasdiff-action/breaking@ccb863950ce437a50f8f1a40d2a1112117e06ce4
with:
base: https://raw.githubusercontent.com/${{ github.repository }}/main/open-api/immich-openapi-specs.json
revision: open-api/immich-openapi-specs.json
fail-on: ERR

View File

@@ -31,12 +31,12 @@ jobs:
working-directory: ./cli
steps:
- id: token
uses: immich-app/devtools/actions/create-workflow-token@da177fa133657503ddb7503f8ba53dccefec5da1 # create-workflow-token-action-v1.0.0
uses: immich-app/devtools/actions/create-workflow-token@05e16407c0a5492138bb38139c9d9bf067b40886 # create-workflow-token-action-v1.0.1
with:
app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
token: ${{ steps.token.outputs.token }}
@@ -45,7 +45,7 @@ jobs:
uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 # v4.2.0
- name: Setup Node
uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
with:
node-version-file: './cli/.nvmrc'
registry-url: 'https://registry.npmjs.org'
@@ -71,13 +71,13 @@ jobs:
steps:
- id: token
uses: immich-app/devtools/actions/create-workflow-token@da177fa133657503ddb7503f8ba53dccefec5da1 # create-workflow-token-action-v1.0.0
uses: immich-app/devtools/actions/create-workflow-token@05e16407c0a5492138bb38139c9d9bf067b40886 # create-workflow-token-action-v1.0.1
with:
app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
- name: Checkout
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
token: ${{ steps.token.outputs.token }}
@@ -89,7 +89,7 @@ jobs:
uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0
- name: Login to GitHub Container Registry
uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0
uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0
if: ${{ !github.event.pull_request.head.repo.fork }}
with:
registry: ghcr.io
@@ -115,7 +115,7 @@ jobs:
type=raw,value=latest,enable=${{ github.event_name == 'release' }}
- name: Build and push image
uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0
uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2
with:
file: cli/Dockerfile
platforms: linux/amd64,linux/arm64

View File

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

38
.github/workflows/close-llm-pr.yml vendored Normal file
View File

@@ -0,0 +1,38 @@
name: Close LLM-generated PRs
on:
pull_request_target:
types: [labeled]
permissions: {}
jobs:
comment_and_close:
runs-on: ubuntu-latest
if: ${{ github.event.label.name == 'llm-generated' }}
permissions:
pull-requests: write
steps:
- name: Comment and close
env:
GH_TOKEN: ${{ github.token }}
NODE_ID: ${{ github.event.pull_request.node_id }}
run: |
gh api graphql \
-f prId="$NODE_ID" \
-f body="Thank you for your interest in contributing to Immich! Unfortunately this PR looks like it was generated using an LLM. As noted in our [CONTRIBUTING.md](https://github.com/immich-app/immich/blob/main/CONTRIBUTING.md#use-of-generative-ai), we request that you don't use LLMs to generate PRs as those are not a good use of maintainer time." \
-f query='
mutation CommentAndClosePR($prId: ID!, $body: String!) {
addComment(input: {
subjectId: $prId,
body: $body
}) {
__typename
}
closePullRequest(input: {
pullRequestId: $prId
}) {
__typename
}
}'

View File

@@ -44,20 +44,20 @@ jobs:
steps:
- id: token
uses: immich-app/devtools/actions/create-workflow-token@da177fa133657503ddb7503f8ba53dccefec5da1 # create-workflow-token-action-v1.0.0
uses: immich-app/devtools/actions/create-workflow-token@05e16407c0a5492138bb38139c9d9bf067b40886 # create-workflow-token-action-v1.0.1
with:
app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
- name: Checkout repository
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
token: ${{ steps.token.outputs.token }}
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@5d4e8d1aca955e8d8589aabd499c5cae939e33c7 # v4.31.9
uses: github/codeql-action/init@9e907b5e64f6b83e7804b09294d44122997950d6 # v4.32.3
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
@@ -70,7 +70,7 @@ jobs:
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@5d4e8d1aca955e8d8589aabd499c5cae939e33c7 # v4.31.9
uses: github/codeql-action/autobuild@9e907b5e64f6b83e7804b09294d44122997950d6 # v4.32.3
# 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
@@ -83,6 +83,6 @@ jobs:
# ./location_of_script_within_repo/buildscript.sh
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@5d4e8d1aca955e8d8589aabd499c5cae939e33c7 # v4.31.9
uses: github/codeql-action/analyze@9e907b5e64f6b83e7804b09294d44122997950d6 # v4.32.3
with:
category: '/language:${{matrix.language}}'

View File

@@ -23,14 +23,14 @@ jobs:
should_run: ${{ steps.check.outputs.should_run }}
steps:
- id: token
uses: immich-app/devtools/actions/create-workflow-token@da177fa133657503ddb7503f8ba53dccefec5da1 # create-workflow-token-action-v1.0.0
uses: immich-app/devtools/actions/create-workflow-token@05e16407c0a5492138bb38139c9d9bf067b40886 # create-workflow-token-action-v1.0.1
with:
app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
- name: Check what should run
id: check
uses: immich-app/devtools/actions/pre-job@08bac802a312fc89808e0dd589271ca0974087b5 # pre-job-action-v2.0.0
uses: immich-app/devtools/actions/pre-job@eed0f8b8165ffcb951f2ba854b2dd031935e1d73 # pre-job-action-v2.0.2
with:
github-token: ${{ steps.token.outputs.token }}
filters: |
@@ -60,7 +60,7 @@ jobs:
suffix: ['', '-cuda', '-rocm', '-openvino', '-armnn', '-rknn']
steps:
- name: Login to GitHub Container Registry
uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0
uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
@@ -90,7 +90,7 @@ jobs:
suffix: ['']
steps:
- name: Login to GitHub Container Registry
uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0
uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
@@ -132,7 +132,7 @@ jobs:
suffixes: '-rocm'
platforms: linux/amd64
runner-mapping: '{"linux/amd64": "pokedex-giant"}'
uses: immich-app/devtools/.github/workflows/multi-runner-build.yml@0477486d82313fba68f7c82c034120a4b8981297 # multi-runner-build-workflow-v2.1.0
uses: immich-app/devtools/.github/workflows/multi-runner-build.yml@bd49ed7a5a6022149f79b6564df48177476a822b # multi-runner-build-workflow-v2.2.1
permissions:
contents: read
actions: read
@@ -155,7 +155,7 @@ jobs:
name: Build and Push Server
needs: pre-job
if: ${{ fromJSON(needs.pre-job.outputs.should_run).server == true }}
uses: immich-app/devtools/.github/workflows/multi-runner-build.yml@0477486d82313fba68f7c82c034120a4b8981297 # multi-runner-build-workflow-v2.1.0
uses: immich-app/devtools/.github/workflows/multi-runner-build.yml@bd49ed7a5a6022149f79b6564df48177476a822b # multi-runner-build-workflow-v2.2.1
permissions:
contents: read
actions: read

View File

@@ -21,14 +21,14 @@ jobs:
should_run: ${{ steps.check.outputs.should_run }}
steps:
- id: token
uses: immich-app/devtools/actions/create-workflow-token@da177fa133657503ddb7503f8ba53dccefec5da1 # create-workflow-token-action-v1.0.0
uses: immich-app/devtools/actions/create-workflow-token@05e16407c0a5492138bb38139c9d9bf067b40886 # create-workflow-token-action-v1.0.1
with:
app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
- name: Check what should run
id: check
uses: immich-app/devtools/actions/pre-job@08bac802a312fc89808e0dd589271ca0974087b5 # pre-job-action-v2.0.0
uses: immich-app/devtools/actions/pre-job@eed0f8b8165ffcb951f2ba854b2dd031935e1d73 # pre-job-action-v2.0.2
with:
github-token: ${{ steps.token.outputs.token }}
filters: |
@@ -54,13 +54,13 @@ jobs:
steps:
- id: token
uses: immich-app/devtools/actions/create-workflow-token@da177fa133657503ddb7503f8ba53dccefec5da1 # create-workflow-token-action-v1.0.0
uses: immich-app/devtools/actions/create-workflow-token@05e16407c0a5492138bb38139c9d9bf067b40886 # create-workflow-token-action-v1.0.1
with:
app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
- name: Checkout code
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
token: ${{ steps.token.outputs.token }}
@@ -70,7 +70,7 @@ jobs:
uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 # v4.2.0
- name: Setup Node
uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
with:
node-version-file: './docs/.nvmrc'
cache: 'pnpm'

View File

@@ -20,7 +20,7 @@ jobs:
artifact: ${{ steps.get-artifact.outputs.result }}
steps:
- id: token
uses: immich-app/devtools/actions/create-workflow-token@da177fa133657503ddb7503f8ba53dccefec5da1 # create-workflow-token-action-v1.0.0
uses: immich-app/devtools/actions/create-workflow-token@05e16407c0a5492138bb38139c9d9bf067b40886 # create-workflow-token-action-v1.0.1
with:
app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
@@ -119,19 +119,19 @@ jobs:
if: ${{ fromJson(needs.checks.outputs.artifact).found && fromJson(needs.checks.outputs.parameters).shouldDeploy }}
steps:
- id: token
uses: immich-app/devtools/actions/create-workflow-token@da177fa133657503ddb7503f8ba53dccefec5da1 # create-workflow-token-action-v1.0.0
uses: immich-app/devtools/actions/create-workflow-token@05e16407c0a5492138bb38139c9d9bf067b40886 # create-workflow-token-action-v1.0.1
with:
app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
- name: Checkout code
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
token: ${{ steps.token.outputs.token }}
- name: Setup Mise
uses: immich-app/devtools/actions/use-mise@cd24790a7f5f6439ac32cc94f5523cb2de8bfa8c # use-mise-action-v1.1.0
uses: immich-app/devtools/actions/use-mise@dab18118da6476e8237ac94080fd937983fecd42 # use-mise-action-v1.1.2
- name: Load parameters
id: parameters
@@ -192,16 +192,13 @@ jobs:
' >> $GITHUB_OUTPUT
- name: Publish to Cloudflare Pages
# TODO: Action is deprecated
uses: cloudflare/pages-action@f0a1cd58cd66095dee69bfa18fa5efd1dde93bca # v1.5.0
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN_PAGES_UPLOAD }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
projectName: ${{ steps.docs-output.outputs.projectName }}
workingDirectory: 'docs'
directory: 'build'
branch: ${{ steps.parameters.outputs.name }}
wranglerVersion: '3'
working-directory: docs
env:
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN_PAGES_UPLOAD }}
CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
PROJECT_NAME: ${{ steps.docs-output.outputs.projectName }}
BRANCH_NAME: ${{ steps.parameters.outputs.name }}
run: mise run //docs:deploy
- name: Deploy Docs Release Domain
if: ${{ steps.parameters.outputs.event == 'release' }}

View File

@@ -17,19 +17,19 @@ jobs:
pull-requests: write
steps:
- id: token
uses: immich-app/devtools/actions/create-workflow-token@da177fa133657503ddb7503f8ba53dccefec5da1 # create-workflow-token-action-v1.0.0
uses: immich-app/devtools/actions/create-workflow-token@05e16407c0a5492138bb38139c9d9bf067b40886 # create-workflow-token-action-v1.0.1
with:
app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
- name: Checkout code
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
token: ${{ steps.token.outputs.token }}
- name: Setup Mise
uses: immich-app/devtools/actions/use-mise@cd24790a7f5f6439ac32cc94f5523cb2de8bfa8c # use-mise-action-v1.1.0
uses: immich-app/devtools/actions/use-mise@dab18118da6476e8237ac94080fd937983fecd42 # use-mise-action-v1.1.2
- name: Destroy Docs Subdomain
env:

View File

@@ -22,7 +22,7 @@ jobs:
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
- name: 'Checkout'
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
ref: ${{ github.event.pull_request.head.ref }}
token: ${{ steps.generate-token.outputs.token }}
@@ -32,14 +32,14 @@ jobs:
uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 # v4.2.0
- name: Setup Node
uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
with:
node-version-file: './server/.nvmrc'
cache: 'pnpm'
cache-dependency-path: '**/pnpm-lock.yaml'
- name: Fix formatting
run: pnpm --recursive install && pnpm run --recursive --parallel fix:format
run: pnpm --recursive install && pnpm run --recursive --if-present --parallel format:fix
- name: Commit and push
uses: EndBug/add-and-commit@a94899bca583c204427a224a7af87c02f9b325d5 # v9.1.4

View File

@@ -14,7 +14,7 @@ jobs:
pull-requests: write
steps:
- id: token
uses: immich-app/devtools/actions/create-workflow-token@da177fa133657503ddb7503f8ba53dccefec5da1 # create-workflow-token-action-v1.0.0
uses: immich-app/devtools/actions/create-workflow-token@05e16407c0a5492138bb38139c9d9bf067b40886 # create-workflow-token-action-v1.0.1
with:
app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}

View File

@@ -12,7 +12,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- id: token
uses: immich-app/devtools/actions/create-workflow-token@da177fa133657503ddb7503f8ba53dccefec5da1 # create-workflow-token-action-v1.0.0
uses: immich-app/devtools/actions/create-workflow-token@05e16407c0a5492138bb38139c9d9bf067b40886 # create-workflow-token-action-v1.0.1
with:
app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}

View File

@@ -56,20 +56,20 @@ jobs:
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
- name: Checkout
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
token: ${{ steps.generate-token.outputs.token }}
persist-credentials: true
ref: main
- name: Install uv
uses: astral-sh/setup-uv@681c641aba71e4a1c380be3ab5e12ad51f415867 # v7.1.6
uses: astral-sh/setup-uv@eac588ad8def6316056a12d4907a9d4d84ff7a3b # v7.3.0
- name: Setup pnpm
uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 # v4.2.0
- name: Setup Node
uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
with:
node-version-file: './server/.nvmrc'
cache: 'pnpm'
@@ -130,7 +130,7 @@ jobs:
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
- name: Checkout
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
token: ${{ steps.generate-token.outputs.token }}
persist-credentials: false

View File

@@ -14,7 +14,7 @@ jobs:
pull-requests: write
steps:
- id: token
uses: immich-app/devtools/actions/create-workflow-token@da177fa133657503ddb7503f8ba53dccefec5da1 # create-workflow-token-action-v1.0.0
uses: immich-app/devtools/actions/create-workflow-token@05e16407c0a5492138bb38139c9d9bf067b40886 # create-workflow-token-action-v1.0.1
with:
app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
@@ -32,7 +32,7 @@ jobs:
pull-requests: write
steps:
- id: token
uses: immich-app/devtools/actions/create-workflow-token@da177fa133657503ddb7503f8ba53dccefec5da1 # create-workflow-token-action-v1.0.0
uses: immich-app/devtools/actions/create-workflow-token@05e16407c0a5492138bb38139c9d9bf067b40886 # create-workflow-token-action-v1.0.1
with:
app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}

View File

@@ -23,20 +23,20 @@ jobs:
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
- name: Checkout
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
token: ${{ steps.generate-token.outputs.token }}
persist-credentials: true
ref: main
- name: Install uv
uses: astral-sh/setup-uv@681c641aba71e4a1c380be3ab5e12ad51f415867 # v7.1.6
uses: astral-sh/setup-uv@eac588ad8def6316056a12d4907a9d4d84ff7a3b # v7.3.0
- name: Setup pnpm
uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 # v4.2.0
- name: Setup Node
uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
with:
node-version-file: './server/.nvmrc'
cache: 'pnpm'
@@ -159,7 +159,7 @@ jobs:
- name: Create PR
id: create-pr
uses: peter-evans/create-pull-request@98357b18bf14b5342f975ff684046ec3b2a07725 # v8.0.0
uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0 # v8.1.0
with:
token: ${{ steps.generate-token.outputs.token }}
commit-message: 'chore: release ${{ steps.bump-type.outputs.next }}'

View File

@@ -58,7 +58,7 @@ jobs:
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
- name: Checkout
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
token: ${{ steps.generate-token.outputs.token }}
persist-credentials: false
@@ -88,6 +88,7 @@ jobs:
draft: true
files: |
docker/docker-compose.yml
docker/docker-compose.rootless.yml
docker/example.env
docker/hwaccel.ml.yml
docker/hwaccel.transcoding.yml

View File

@@ -19,12 +19,12 @@ jobs:
working-directory: ./open-api/typescript-sdk
steps:
- id: token
uses: immich-app/devtools/actions/create-workflow-token@da177fa133657503ddb7503f8ba53dccefec5da1 # create-workflow-token-action-v1.0.0
uses: immich-app/devtools/actions/create-workflow-token@05e16407c0a5492138bb38139c9d9bf067b40886 # create-workflow-token-action-v1.0.1
with:
app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
token: ${{ steps.token.outputs.token }}
@@ -33,7 +33,7 @@ jobs:
uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 # v4.2.0
# Setup .npmrc file to publish to npm
- uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
- uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
with:
node-version-file: './open-api/typescript-sdk/.nvmrc'
registry-url: 'https://registry.npmjs.org'

View File

@@ -20,14 +20,14 @@ jobs:
should_run: ${{ steps.check.outputs.should_run }}
steps:
- id: token
uses: immich-app/devtools/actions/create-workflow-token@da177fa133657503ddb7503f8ba53dccefec5da1 # create-workflow-token-action-v1.0.0
uses: immich-app/devtools/actions/create-workflow-token@05e16407c0a5492138bb38139c9d9bf067b40886 # create-workflow-token-action-v1.0.1
with:
app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
- name: Check what should run
id: check
uses: immich-app/devtools/actions/pre-job@08bac802a312fc89808e0dd589271ca0974087b5 # pre-job-action-v2.0.0
uses: immich-app/devtools/actions/pre-job@eed0f8b8165ffcb951f2ba854b2dd031935e1d73 # pre-job-action-v2.0.2
with:
github-token: ${{ steps.token.outputs.token }}
filters: |
@@ -49,13 +49,13 @@ jobs:
working-directory: ./mobile
steps:
- id: token
uses: immich-app/devtools/actions/create-workflow-token@da177fa133657503ddb7503f8ba53dccefec5da1 # create-workflow-token-action-v1.0.0
uses: immich-app/devtools/actions/create-workflow-token@05e16407c0a5492138bb38139c9d9bf067b40886 # create-workflow-token-action-v1.0.1
with:
app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
- name: Checkout code
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
token: ${{ steps.token.outputs.token }}
@@ -69,6 +69,14 @@ jobs:
- name: Install dependencies
run: dart pub get
- name: Install dependencies for UI package
run: dart pub get
working-directory: ./mobile/packages/ui
- name: Install dependencies for UI Showcase
run: dart pub get
working-directory: ./mobile/packages/ui/showcase
- name: Install DCM
uses: CQLabs/setup-dcm@8697ae0790c0852e964a6ef1d768d62a6675481a # v2.0.1
with:

View File

@@ -17,14 +17,14 @@ jobs:
should_run: ${{ steps.check.outputs.should_run }}
steps:
- id: token
uses: immich-app/devtools/actions/create-workflow-token@da177fa133657503ddb7503f8ba53dccefec5da1 # create-workflow-token-action-v1.0.0
uses: immich-app/devtools/actions/create-workflow-token@05e16407c0a5492138bb38139c9d9bf067b40886 # create-workflow-token-action-v1.0.1
with:
app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
- name: Check what should run
id: check
uses: immich-app/devtools/actions/pre-job@08bac802a312fc89808e0dd589271ca0974087b5 # pre-job-action-v2.0.0
uses: immich-app/devtools/actions/pre-job@eed0f8b8165ffcb951f2ba854b2dd031935e1d73 # pre-job-action-v2.0.2
with:
github-token: ${{ steps.token.outputs.token }}
filters: |
@@ -63,13 +63,13 @@ jobs:
working-directory: ./server
steps:
- id: token
uses: immich-app/devtools/actions/create-workflow-token@da177fa133657503ddb7503f8ba53dccefec5da1 # create-workflow-token-action-v1.0.0
uses: immich-app/devtools/actions/create-workflow-token@05e16407c0a5492138bb38139c9d9bf067b40886 # create-workflow-token-action-v1.0.1
with:
app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
- name: Checkout code
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
token: ${{ steps.token.outputs.token }}
@@ -77,7 +77,7 @@ jobs:
- name: Setup pnpm
uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 # v4.2.0
- name: Setup Node
uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
with:
node-version-file: './server/.nvmrc'
cache: 'pnpm'
@@ -108,20 +108,20 @@ jobs:
working-directory: ./cli
steps:
- id: token
uses: immich-app/devtools/actions/create-workflow-token@da177fa133657503ddb7503f8ba53dccefec5da1 # create-workflow-token-action-v1.0.0
uses: immich-app/devtools/actions/create-workflow-token@05e16407c0a5492138bb38139c9d9bf067b40886 # create-workflow-token-action-v1.0.1
with:
app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
- name: Checkout code
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
token: ${{ steps.token.outputs.token }}
- name: Setup pnpm
uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 # v4.2.0
- name: Setup Node
uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
with:
node-version-file: './cli/.nvmrc'
cache: 'pnpm'
@@ -155,20 +155,20 @@ jobs:
working-directory: ./cli
steps:
- id: token
uses: immich-app/devtools/actions/create-workflow-token@da177fa133657503ddb7503f8ba53dccefec5da1 # create-workflow-token-action-v1.0.0
uses: immich-app/devtools/actions/create-workflow-token@05e16407c0a5492138bb38139c9d9bf067b40886 # create-workflow-token-action-v1.0.1
with:
app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
- name: Checkout code
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
token: ${{ steps.token.outputs.token }}
- name: Setup pnpm
uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 # v4.2.0
- name: Setup Node
uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
with:
node-version-file: './cli/.nvmrc'
cache: 'pnpm'
@@ -197,20 +197,20 @@ jobs:
working-directory: ./web
steps:
- id: token
uses: immich-app/devtools/actions/create-workflow-token@da177fa133657503ddb7503f8ba53dccefec5da1 # create-workflow-token-action-v1.0.0
uses: immich-app/devtools/actions/create-workflow-token@05e16407c0a5492138bb38139c9d9bf067b40886 # create-workflow-token-action-v1.0.1
with:
app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
- name: Checkout code
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
token: ${{ steps.token.outputs.token }}
- name: Setup pnpm
uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 # v4.2.0
- name: Setup Node
uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
with:
node-version-file: './web/.nvmrc'
cache: 'pnpm'
@@ -241,20 +241,20 @@ jobs:
working-directory: ./web
steps:
- id: token
uses: immich-app/devtools/actions/create-workflow-token@da177fa133657503ddb7503f8ba53dccefec5da1 # create-workflow-token-action-v1.0.0
uses: immich-app/devtools/actions/create-workflow-token@05e16407c0a5492138bb38139c9d9bf067b40886 # create-workflow-token-action-v1.0.1
with:
app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
- name: Checkout code
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
token: ${{ steps.token.outputs.token }}
- name: Setup pnpm
uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 # v4.2.0
- name: Setup Node
uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
with:
node-version-file: './web/.nvmrc'
cache: 'pnpm'
@@ -279,20 +279,20 @@ jobs:
contents: read
steps:
- id: token
uses: immich-app/devtools/actions/create-workflow-token@da177fa133657503ddb7503f8ba53dccefec5da1 # create-workflow-token-action-v1.0.0
uses: immich-app/devtools/actions/create-workflow-token@05e16407c0a5492138bb38139c9d9bf067b40886 # create-workflow-token-action-v1.0.1
with:
app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
- name: Checkout code
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
token: ${{ steps.token.outputs.token }}
- name: Setup pnpm
uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 # v4.2.0
- name: Setup Node
uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
with:
node-version-file: './web/.nvmrc'
cache: 'pnpm'
@@ -327,20 +327,20 @@ jobs:
working-directory: ./e2e
steps:
- id: token
uses: immich-app/devtools/actions/create-workflow-token@da177fa133657503ddb7503f8ba53dccefec5da1 # create-workflow-token-action-v1.0.0
uses: immich-app/devtools/actions/create-workflow-token@05e16407c0a5492138bb38139c9d9bf067b40886 # create-workflow-token-action-v1.0.1
with:
app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
- name: Checkout code
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
token: ${{ steps.token.outputs.token }}
- name: Setup pnpm
uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 # v4.2.0
- name: Setup Node
uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
with:
node-version-file: './e2e/.nvmrc'
cache: 'pnpm'
@@ -373,13 +373,13 @@ jobs:
working-directory: ./server
steps:
- id: token
uses: immich-app/devtools/actions/create-workflow-token@da177fa133657503ddb7503f8ba53dccefec5da1 # create-workflow-token-action-v1.0.0
uses: immich-app/devtools/actions/create-workflow-token@05e16407c0a5492138bb38139c9d9bf067b40886 # create-workflow-token-action-v1.0.1
with:
app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
- name: Checkout code
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
submodules: 'recursive'
@@ -387,7 +387,7 @@ jobs:
- name: Setup pnpm
uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 # v4.2.0
- name: Setup Node
uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
with:
node-version-file: './server/.nvmrc'
cache: 'pnpm'
@@ -412,13 +412,13 @@ jobs:
runner: [ubuntu-latest, ubuntu-24.04-arm]
steps:
- id: token
uses: immich-app/devtools/actions/create-workflow-token@da177fa133657503ddb7503f8ba53dccefec5da1 # create-workflow-token-action-v1.0.0
uses: immich-app/devtools/actions/create-workflow-token@05e16407c0a5492138bb38139c9d9bf067b40886 # create-workflow-token-action-v1.0.1
with:
app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
- name: Checkout code
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
submodules: 'recursive'
@@ -426,7 +426,7 @@ jobs:
- name: Setup pnpm
uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 # v4.2.0
- name: Setup Node
uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
with:
node-version-file: './e2e/.nvmrc'
cache: 'pnpm'
@@ -446,12 +446,29 @@ jobs:
- name: Install dependencies
run: pnpm install --frozen-lockfile
if: ${{ !cancelled() }}
- name: Docker build
run: docker compose build
- name: Start Docker Compose
run: docker compose up -d --build --renew-anon-volumes --force-recreate --remove-orphans --wait --wait-timeout 300
if: ${{ !cancelled() }}
- name: Run e2e tests (api & cli)
env:
VITEST_DISABLE_DOCKER_SETUP: true
run: pnpm test
if: ${{ !cancelled() }}
- name: Run e2e tests (maintenance)
env:
VITEST_DISABLE_DOCKER_SETUP: true
run: pnpm test:maintenance
if: ${{ !cancelled() }}
- name: Capture Docker logs
if: always()
run: docker compose logs --no-color > docker-compose-logs.txt
working-directory: ./e2e
- name: Archive Docker logs
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
if: always()
with:
name: e2e-server-docker-logs-${{ matrix.runner }}
path: e2e/docker-compose-logs.txt
e2e-tests-web:
name: End-to-End Tests (Web)
needs: pre-job
@@ -467,13 +484,13 @@ jobs:
runner: [ubuntu-latest, ubuntu-24.04-arm]
steps:
- id: token
uses: immich-app/devtools/actions/create-workflow-token@da177fa133657503ddb7503f8ba53dccefec5da1 # create-workflow-token-action-v1.0.0
uses: immich-app/devtools/actions/create-workflow-token@05e16407c0a5492138bb38139c9d9bf067b40886 # create-workflow-token-action-v1.0.1
with:
app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
- name: Checkout code
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
submodules: 'recursive'
@@ -481,7 +498,7 @@ jobs:
- name: Setup pnpm
uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 # v4.2.0
- name: Setup Node
uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
with:
node-version-file: './e2e/.nvmrc'
cache: 'pnpm'
@@ -494,16 +511,15 @@ jobs:
run: pnpm install --frozen-lockfile
if: ${{ !cancelled() }}
- name: Install Playwright Browsers
run: npx playwright install chromium --only-shell
run: pnpm exec playwright install chromium --only-shell
if: ${{ !cancelled() }}
- name: Docker build
run: docker compose up -d --build --renew-anon-volumes --force-recreate --remove-orphans --wait --wait-timeout 300
if: ${{ !cancelled() }}
- name: Run e2e tests (web)
env:
CI: true
PLAYWRIGHT_DISABLE_WEBSERVER: true
run: npx playwright test --project=web
run: pnpm test:web
if: ${{ !cancelled() }}
- name: Archive e2e test (web) results
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
@@ -513,9 +529,8 @@ jobs:
path: e2e/playwright-report/
- name: Run ui tests (web)
env:
CI: true
PLAYWRIGHT_DISABLE_WEBSERVER: true
run: npx playwright test --project=ui
run: pnpm test:web:ui
if: ${{ !cancelled() }}
- name: Archive ui test (web) results
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
@@ -525,9 +540,8 @@ jobs:
path: e2e/playwright-report/
- name: Run maintenance tests
env:
CI: true
PLAYWRIGHT_DISABLE_WEBSERVER: true
run: npx playwright test --project=maintenance
run: pnpm test:web:maintenance
if: ${{ !cancelled() }}
- name: Archive maintenance tests (web) results
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
@@ -543,7 +557,7 @@ jobs:
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
if: always()
with:
name: docker-compose-logs-${{ matrix.runner }}
name: e2e-web-docker-logs-${{ matrix.runner }}
path: e2e/docker-compose-logs.txt
success-check-e2e:
name: End-to-End Tests Success
@@ -564,12 +578,12 @@ jobs:
contents: read
steps:
- id: token
uses: immich-app/devtools/actions/create-workflow-token@da177fa133657503ddb7503f8ba53dccefec5da1 # create-workflow-token-action-v1.0.0
uses: immich-app/devtools/actions/create-workflow-token@05e16407c0a5492138bb38139c9d9bf067b40886 # create-workflow-token-action-v1.0.1
with:
app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
token: ${{ steps.token.outputs.token }}
@@ -596,17 +610,17 @@ jobs:
working-directory: ./machine-learning
steps:
- id: token
uses: immich-app/devtools/actions/create-workflow-token@da177fa133657503ddb7503f8ba53dccefec5da1 # create-workflow-token-action-v1.0.0
uses: immich-app/devtools/actions/create-workflow-token@05e16407c0a5492138bb38139c9d9bf067b40886 # create-workflow-token-action-v1.0.1
with:
app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
token: ${{ steps.token.outputs.token }}
- name: Install uv
uses: astral-sh/setup-uv@681c641aba71e4a1c380be3ab5e12ad51f415867 # v7.1.6
uses: astral-sh/setup-uv@eac588ad8def6316056a12d4907a9d4d84ff7a3b # v7.3.0
with:
python-version: 3.11
- name: Install dependencies
@@ -636,20 +650,20 @@ jobs:
working-directory: ./.github
steps:
- id: token
uses: immich-app/devtools/actions/create-workflow-token@da177fa133657503ddb7503f8ba53dccefec5da1 # create-workflow-token-action-v1.0.0
uses: immich-app/devtools/actions/create-workflow-token@05e16407c0a5492138bb38139c9d9bf067b40886 # create-workflow-token-action-v1.0.1
with:
app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
- name: Checkout code
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
token: ${{ steps.token.outputs.token }}
- name: Setup pnpm
uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 # v4.2.0
- name: Setup Node
uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
with:
node-version-file: './.github/.nvmrc'
cache: 'pnpm'
@@ -666,12 +680,12 @@ jobs:
contents: read
steps:
- id: token
uses: immich-app/devtools/actions/create-workflow-token@da177fa133657503ddb7503f8ba53dccefec5da1 # create-workflow-token-action-v1.0.0
uses: immich-app/devtools/actions/create-workflow-token@05e16407c0a5492138bb38139c9d9bf067b40886 # create-workflow-token-action-v1.0.1
with:
app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
token: ${{ steps.token.outputs.token }}
@@ -687,20 +701,20 @@ jobs:
contents: read
steps:
- id: token
uses: immich-app/devtools/actions/create-workflow-token@da177fa133657503ddb7503f8ba53dccefec5da1 # create-workflow-token-action-v1.0.0
uses: immich-app/devtools/actions/create-workflow-token@05e16407c0a5492138bb38139c9d9bf067b40886 # create-workflow-token-action-v1.0.1
with:
app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
- name: Checkout code
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
token: ${{ steps.token.outputs.token }}
- name: Setup pnpm
uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 # v4.2.0
- name: Setup Node
uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
with:
node-version-file: './server/.nvmrc'
cache: 'pnpm'
@@ -749,20 +763,20 @@ jobs:
working-directory: ./server
steps:
- id: token
uses: immich-app/devtools/actions/create-workflow-token@da177fa133657503ddb7503f8ba53dccefec5da1 # create-workflow-token-action-v1.0.0
uses: immich-app/devtools/actions/create-workflow-token@05e16407c0a5492138bb38139c9d9bf067b40886 # create-workflow-token-action-v1.0.1
with:
app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
- name: Checkout code
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
token: ${{ steps.token.outputs.token }}
- name: Setup pnpm
uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 # v4.2.0
- name: Setup Node
uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
with:
node-version-file: './server/.nvmrc'
cache: 'pnpm'

View File

@@ -24,14 +24,14 @@ jobs:
should_run: ${{ steps.check.outputs.should_run }}
steps:
- id: token
uses: immich-app/devtools/actions/create-workflow-token@da177fa133657503ddb7503f8ba53dccefec5da1 # create-workflow-token-action-v1.0.0
uses: immich-app/devtools/actions/create-workflow-token@05e16407c0a5492138bb38139c9d9bf067b40886 # create-workflow-token-action-v1.0.1
with:
app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
- name: Check what should run
id: check
uses: immich-app/devtools/actions/pre-job@08bac802a312fc89808e0dd589271ca0974087b5 # pre-job-action-v2.0.0
uses: immich-app/devtools/actions/pre-job@eed0f8b8165ffcb951f2ba854b2dd031935e1d73 # pre-job-action-v2.0.2
with:
github-token: ${{ steps.token.outputs.token }}
filters: |
@@ -47,7 +47,7 @@ jobs:
if: ${{ fromJSON(needs.pre-job.outputs.should_run).i18n == true }}
steps:
- id: token
uses: immich-app/devtools/actions/create-workflow-token@da177fa133657503ddb7503f8ba53dccefec5da1 # create-workflow-token-action-v1.0.0
uses: immich-app/devtools/actions/create-workflow-token@05e16407c0a5492138bb38139c9d9bf067b40886 # create-workflow-token-action-v1.0.1
with:
app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}

View File

@@ -4,12 +4,18 @@ module.exports = {
if (!pkg.name) {
return pkg;
}
// make exiftool-vendored.pl a regular dependency since Docker prod
// images build with --no-optional to reduce image size
if (pkg.name === "exiftool-vendored") {
if (pkg.optionalDependencies["exiftool-vendored.pl"]) {
// make exiftool-vendored.pl a regular dependency
pkg.dependencies["exiftool-vendored.pl"] =
pkg.optionalDependencies["exiftool-vendored.pl"];
delete pkg.optionalDependencies["exiftool-vendored.pl"];
const binaryPackage =
process.platform === "win32"
? "exiftool-vendored.exe"
: "exiftool-vendored.pl";
if (pkg.optionalDependencies[binaryPackage]) {
pkg.dependencies[binaryPackage] =
pkg.optionalDependencies[binaryPackage];
delete pkg.optionalDependencies[binaryPackage];
}
}
return pkg;

View File

@@ -17,7 +17,7 @@ If you are looking for something to work on, there are discussions and issues wi
## Use of generative AI
We generally discourage PRs entirely generated by an LLM. For any part generated by an LLM, please put extra effort into your self-review. By using generative AI without proper self-review, the time you save ends up being more work we need to put in for proper reviews and code cleanup. Please keep that in mind when submitting code by an LLM. Clearly state the use of LLMs/(generative) AI in your pull request as requested by the template.
We ask you not to open PRs generated with an LLM. We find that code generated like this tends to need a large amount of back-and-forth, which is a very inefficient use of our time. If we want LLM-generated code, it's much faster for us to use an LLM ourselves than to go through an intermediary via a pull request.
## Feature freezes

View File

@@ -52,7 +52,7 @@ attach-server:
docker exec -it docker_immich-server_1 sh
renovate:
LOG_LEVEL=debug npx renovate --platform=local --repository-cache=reset
LOG_LEVEL=debug pnpm exec renovate --platform=local --repository-cache=reset
# Directories that need to be created for volumes or build output
VOLUME_DIRS = \

View File

@@ -1 +1 @@
24.13.0
24.13.1

View File

@@ -13,23 +13,23 @@
"cli"
],
"devDependencies": {
"@eslint/js": "^9.8.0",
"@immich/sdk": "file:../open-api/typescript-sdk",
"@eslint/js": "^10.0.0",
"@immich/sdk": "workspace:*",
"@types/byte-size": "^8.1.0",
"@types/cli-progress": "^3.11.0",
"@types/lodash-es": "^4.17.12",
"@types/micromatch": "^4.0.9",
"@types/mock-fs": "^4.13.1",
"@types/node": "^24.10.11",
"@types/node": "^24.10.13",
"@vitest/coverage-v8": "^3.0.0",
"byte-size": "^9.0.0",
"cli-progress": "^3.12.0",
"commander": "^12.0.0",
"eslint": "^9.14.0",
"eslint": "^10.0.0",
"eslint-config-prettier": "^10.1.8",
"eslint-plugin-prettier": "^5.1.3",
"eslint-plugin-unicorn": "^62.0.0",
"globals": "^16.0.0",
"eslint-plugin-unicorn": "^63.0.0",
"globals": "^17.0.0",
"mock-fs": "^5.2.0",
"prettier": "^3.7.4",
"prettier-plugin-organize-imports": "^4.0.0",
@@ -45,8 +45,8 @@
"build": "vite build",
"build:dev": "vite build --sourcemap true",
"lint": "eslint \"src/**/*.ts\" --max-warnings 0",
"lint:fix": "npm run lint -- --fix",
"prepack": "npm run build",
"lint:fix": "pnpm run lint --fix",
"prepack": "pnpm run build",
"test": "vitest",
"test:cov": "vitest --coverage",
"format": "prettier --check .",
@@ -69,6 +69,6 @@
"micromatch": "^4.0.8"
},
"volta": {
"node": "24.13.0"
"node": "24.13.1"
}
}

View File

@@ -7,7 +7,15 @@ import { describe, expect, it, MockedFunction, vi } from 'vitest';
import { Action, checkBulkUpload, defaults, getSupportedMediaTypes, Reason } from '@immich/sdk';
import createFetchMock from 'vitest-fetch-mock';
import { checkForDuplicates, getAlbumName, startWatch, uploadFiles, UploadOptionsDto } from 'src/commands/asset';
import {
checkForDuplicates,
deleteFiles,
findSidecar,
getAlbumName,
startWatch,
uploadFiles,
UploadOptionsDto,
} from 'src/commands/asset';
vi.mock('@immich/sdk');
@@ -309,3 +317,85 @@ describe('startWatch', () => {
await fs.promises.rm(testFolder, { recursive: true, force: true });
});
});
describe('findSidecar', () => {
let testDir: string;
let testFilePath: string;
beforeEach(() => {
testDir = fs.mkdtempSync(path.join(os.tmpdir(), 'test-sidecar-'));
testFilePath = path.join(testDir, 'test.jpg');
fs.writeFileSync(testFilePath, 'test');
});
afterEach(() => {
fs.rmSync(testDir, { recursive: true, force: true });
});
it('should find sidecar file with photo.xmp naming convention', () => {
const sidecarPath = path.join(testDir, 'test.xmp');
fs.writeFileSync(sidecarPath, 'xmp data');
const result = findSidecar(testFilePath);
expect(result).toBe(sidecarPath);
});
it('should find sidecar file with photo.ext.xmp naming convention', () => {
const sidecarPath = path.join(testDir, 'test.jpg.xmp');
fs.writeFileSync(sidecarPath, 'xmp data');
const result = findSidecar(testFilePath);
expect(result).toBe(sidecarPath);
});
it('should prefer photo.ext.xmp over photo.xmp when both exist', () => {
const sidecarPath1 = path.join(testDir, 'test.xmp');
const sidecarPath2 = path.join(testDir, 'test.jpg.xmp');
fs.writeFileSync(sidecarPath1, 'xmp data 1');
fs.writeFileSync(sidecarPath2, 'xmp data 2');
const result = findSidecar(testFilePath);
// Should return the first one found (photo.xmp) based on the order in the code
expect(result).toBe(sidecarPath1);
});
it('should return undefined when no sidecar file exists', () => {
const result = findSidecar(testFilePath);
expect(result).toBeUndefined();
});
});
describe('deleteFiles', () => {
let testDir: string;
let testFilePath: string;
beforeEach(() => {
testDir = fs.mkdtempSync(path.join(os.tmpdir(), 'test-delete-'));
testFilePath = path.join(testDir, 'test.jpg');
fs.writeFileSync(testFilePath, 'test');
});
afterEach(() => {
fs.rmSync(testDir, { recursive: true, force: true });
});
it('should delete asset and sidecar file when main file is deleted', async () => {
const sidecarPath = path.join(testDir, 'test.xmp');
fs.writeFileSync(sidecarPath, 'xmp data');
await deleteFiles([{ id: 'test-id', filepath: testFilePath }], [], { delete: true, concurrency: 1 });
expect(fs.existsSync(testFilePath)).toBe(false);
expect(fs.existsSync(sidecarPath)).toBe(false);
});
it('should not delete sidecar file when delete option is false', async () => {
const sidecarPath = path.join(testDir, 'test.xmp');
fs.writeFileSync(sidecarPath, 'xmp data');
await deleteFiles([{ id: 'test-id', filepath: testFilePath }], [], { delete: false, concurrency: 1 });
expect(fs.existsSync(testFilePath)).toBe(true);
expect(fs.existsSync(sidecarPath)).toBe(true);
});
});

View File

@@ -4,6 +4,7 @@ import {
AssetBulkUploadCheckResult,
AssetMediaResponseDto,
AssetMediaStatus,
Permission,
addAssetsToAlbum,
checkBulkUpload,
createAlbum,
@@ -16,17 +17,15 @@ import { Matcher, watch as watchFs } from 'chokidar';
import { MultiBar, Presets, SingleBar } from 'cli-progress';
import { chunk } from 'lodash-es';
import micromatch from 'micromatch';
import { Stats, createReadStream } from 'node:fs';
import { Stats, createReadStream, existsSync } from 'node:fs';
import { stat, unlink } from 'node:fs/promises';
import path, { basename } from 'node:path';
import { Queue } from 'src/queue';
import { BaseOptions, Batcher, authenticate, crawl, sha1 } from 'src/utils';
import { BaseOptions, Batcher, authenticate, crawl, requirePermissions, s, sha1 } from 'src/utils';
const UPLOAD_WATCH_BATCH_SIZE = 100;
const UPLOAD_WATCH_DEBOUNCE_TIME_MS = 10_000;
const s = (count: number) => (count === 1 ? '' : 's');
// TODO figure out why `id` is missing
type AssetBulkUploadCheckResults = Array<AssetBulkUploadCheckResult & { id: string }>;
type Asset = { id: string; filepath: string };
@@ -136,6 +135,7 @@ export const startWatch = async (
export const upload = async (paths: string[], baseOptions: BaseOptions, options: UploadOptionsDto) => {
await authenticate(baseOptions);
await requirePermissions([Permission.AssetUpload]);
const scanFiles = await scan(paths, options);
@@ -180,18 +180,49 @@ export const checkForDuplicates = async (files: string[], { concurrency, skipHas
}
let multiBar: MultiBar | undefined;
let totalSize = 0;
const statsMap = new Map<string, Stats>();
// Calculate total size first
for (const filepath of files) {
const stats = await stat(filepath);
statsMap.set(filepath, stats);
totalSize += stats.size;
}
if (progress) {
multiBar = new MultiBar(
{ format: '{message} | {bar} | {percentage}% | ETA: {eta}s | {value}/{total} assets' },
{
format: '{message} | {bar} | {percentage}% | ETA: {eta_formatted} | {value}/{total}',
formatValue: (v: number, options, type) => {
// Don't format percentage
if (type === 'percentage') {
return v.toString();
}
return byteSize(v).toString();
},
etaBuffer: 100, // Increase samples for ETA calculation
},
Presets.shades_classic,
);
// Ensure we restore cursor on interrupt
process.on('SIGINT', () => {
if (multiBar) {
multiBar.stop();
}
process.exit(0);
});
} else {
console.log(`Received ${files.length} files, hashing...`);
console.log(`Received ${files.length} files (${byteSize(totalSize)}), hashing...`);
}
const hashProgressBar = multiBar?.create(files.length, 0, { message: 'Hashing files ' });
const checkProgressBar = multiBar?.create(files.length, 0, { message: 'Checking for duplicates' });
const hashProgressBar = multiBar?.create(totalSize, 0, {
message: 'Hashing files ',
});
const checkProgressBar = multiBar?.create(totalSize, 0, {
message: 'Checking for duplicates',
});
const newFiles: string[] = [];
const duplicates: Asset[] = [];
@@ -211,7 +242,13 @@ export const checkForDuplicates = async (files: string[], { concurrency, skipHas
}
}
checkProgressBar?.increment(assets.length);
// Update progress based on total size of processed files
let processedSize = 0;
for (const asset of assets) {
const stats = statsMap.get(asset.id);
processedSize += stats?.size || 0;
}
checkProgressBar?.increment(processedSize);
},
{ concurrency, retry: 3 },
);
@@ -221,6 +258,10 @@ export const checkForDuplicates = async (files: string[], { concurrency, skipHas
const queue = new Queue<string, AssetBulkUploadCheckItem[]>(
async (filepath: string): Promise<AssetBulkUploadCheckItem[]> => {
const stats = statsMap.get(filepath);
if (!stats) {
throw new Error(`Stats not found for ${filepath}`);
}
const dto = { id: filepath, checksum: await sha1(filepath) };
results.push(dto);
@@ -231,7 +272,7 @@ export const checkForDuplicates = async (files: string[], { concurrency, skipHas
void checkBulkUploadQueue.push(batch);
}
hashProgressBar?.increment();
hashProgressBar?.increment(stats.size);
return results;
},
{ concurrency, retry: 3 },
@@ -362,23 +403,6 @@ export const uploadFiles = async (
const uploadFile = async (input: string, stats: Stats): Promise<AssetMediaResponseDto> => {
const { baseUrl, headers } = defaults;
const assetPath = path.parse(input);
const noExtension = path.join(assetPath.dir, assetPath.name);
const sidecarsFiles = await Promise.all(
// XMP sidecars can come in two filename formats. For a photo named photo.ext, the filenames are photo.ext.xmp and photo.xmp
[`${noExtension}.xmp`, `${input}.xmp`].map(async (sidecarPath) => {
try {
const stats = await stat(sidecarPath);
return new UploadFile(sidecarPath, stats.size);
} catch {
return false;
}
}),
);
const sidecarData = sidecarsFiles.find((file): file is UploadFile => file !== false);
const formData = new FormData();
formData.append('deviceAssetId', `${basename(input)}-${stats.size}`.replaceAll(/\s+/g, ''));
formData.append('deviceId', 'CLI');
@@ -388,8 +412,15 @@ const uploadFile = async (input: string, stats: Stats): Promise<AssetMediaRespon
formData.append('isFavorite', 'false');
formData.append('assetData', new UploadFile(input, stats.size));
if (sidecarData) {
formData.append('sidecarData', sidecarData);
const sidecarPath = findSidecar(input);
if (sidecarPath) {
try {
const stats = await stat(sidecarPath);
const sidecarData = new UploadFile(sidecarPath, stats.size);
formData.append('sidecarData', sidecarData);
} catch {
// noop
}
}
const response = await fetch(`${baseUrl}/assets`, {
@@ -405,7 +436,19 @@ const uploadFile = async (input: string, stats: Stats): Promise<AssetMediaRespon
return response.json();
};
const deleteFiles = async (uploaded: Asset[], duplicates: Asset[], options: UploadOptionsDto): Promise<void> => {
export const findSidecar = (filepath: string): string | undefined => {
const assetPath = path.parse(filepath);
const noExtension = path.join(assetPath.dir, assetPath.name);
// XMP sidecars can come in two filename formats. For a photo named photo.ext, the filenames are photo.ext.xmp and photo.xmp
for (const sidecarPath of [`${noExtension}.xmp`, `${filepath}.xmp`]) {
if (existsSync(sidecarPath)) {
return sidecarPath;
}
}
};
export const deleteFiles = async (uploaded: Asset[], duplicates: Asset[], options: UploadOptionsDto): Promise<void> => {
let fileCount = 0;
if (options.delete) {
fileCount += uploaded.length;
@@ -433,7 +476,15 @@ const deleteFiles = async (uploaded: Asset[], duplicates: Asset[], options: Uplo
const chunkDelete = async (files: Asset[]) => {
for (const assetBatch of chunk(files, options.concurrency)) {
await Promise.all(assetBatch.map((input: Asset) => unlink(input.filepath)));
await Promise.all(
assetBatch.map(async (input: Asset) => {
await unlink(input.filepath);
const sidecarPath = findSidecar(input.filepath);
if (sidecarPath) {
await unlink(sidecarPath);
}
}),
);
deletionProgress.update(assetBatch.length);
}
};

View File

@@ -1,7 +1,15 @@
import { getMyUser } from '@immich/sdk';
import { getMyUser, Permission } from '@immich/sdk';
import { existsSync } from 'node:fs';
import { mkdir, unlink } from 'node:fs/promises';
import { BaseOptions, connect, getAuthFilePath, logError, withError, writeAuthFile } from 'src/utils';
import {
BaseOptions,
connect,
getAuthFilePath,
logError,
requirePermissions,
withError,
writeAuthFile,
} from 'src/utils';
export const login = async (url: string, key: string, options: BaseOptions) => {
console.log(`Logging in to ${url}`);
@@ -9,6 +17,7 @@ export const login = async (url: string, key: string, options: BaseOptions) => {
const { configDirectory: configDir } = options;
await connect(url, key);
await requirePermissions([Permission.UserRead]);
const [error, user] = await withError(getMyUser());
if (error) {

View File

@@ -1,8 +1,9 @@
import { getAssetStatistics, getMyUser, getServerVersion, getSupportedMediaTypes } from '@immich/sdk';
import { BaseOptions, authenticate } from 'src/utils';
import { getAssetStatistics, getMyUser, getServerVersion, getSupportedMediaTypes, Permission } from '@immich/sdk';
import { authenticate, BaseOptions, requirePermissions } from 'src/utils';
export const serverInfo = async (options: BaseOptions) => {
const { url } = await authenticate(options);
await requirePermissions([Permission.ServerAbout, Permission.AssetStatistics, Permission.UserRead]);
const [versionInfo, mediaTypes, stats, userInfo] = await Promise.all([
getServerVersion(),

View File

@@ -1,4 +1,4 @@
import { getMyUser, init, isHttpError } from '@immich/sdk';
import { ApiKeyResponseDto, getMyApiKey, getMyUser, init, isHttpError, Permission } from '@immich/sdk';
import { convertPathToPattern, glob } from 'fast-glob';
import { createHash } from 'node:crypto';
import { createReadStream } from 'node:fs';
@@ -34,6 +34,36 @@ export const authenticate = async (options: BaseOptions): Promise<AuthDto> => {
return auth;
};
export const s = (count: number) => (count === 1 ? '' : 's');
let _apiKey: ApiKeyResponseDto;
export const requirePermissions = async (permissions: Permission[]) => {
if (!_apiKey) {
_apiKey = await getMyApiKey();
}
if (_apiKey.permissions.includes(Permission.All)) {
return;
}
const missing: Permission[] = [];
for (const permission of permissions) {
if (!_apiKey.permissions.includes(permission)) {
missing.push(permission);
}
}
if (missing.length > 0) {
const combined = missing.map((permission) => `"${permission}"`).join(', ');
console.log(
`Missing required permission${s(missing.length)}: ${combined}.
Please make sure your API key has the correct permissions.`,
);
process.exit(1);
}
};
export const connect = async (url: string, key: string) => {
const wellKnownUrl = new URL('.well-known/immich', url);
try {

View File

@@ -14,33 +14,65 @@
name: immich-dev
services:
immich-app-base:
profiles: ['_base']
tmpfs:
- /tmp
volumes:
- ..:/usr/src/app
- pnpm_cache:/buildcache/pnpm_cache
- 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
immich-init:
extends:
service: immich-app-base
profiles: !reset []
container_name: immich_init
image: immich-server-dev:latest
build:
context: ../
dockerfile: server/Dockerfile.dev
target: dev
command:
- |
pnpm install
touch /tmp/init-complete
exec tail -f /dev/null
volumes:
- pnpm_store_server:/buildcache/pnpm-store
restart: 'no'
healthcheck:
test: ['CMD', 'test', '-f', '/tmp/init-complete']
interval: 2s
timeout: 3s
retries: 300
start_period: 300s
immich-server:
extends:
service: immich-app-base
profiles: !reset []
container_name: immich_server
command: ['immich-dev']
image: immich-server-dev:latest
# extends:
# file: hwaccel.transcoding.yml
# service: cpu # set to one of [nvenc, quicksync, rkmpp, vaapi, vaapi-wsl] for accelerated transcoding
build:
context: ../
dockerfile: server/Dockerfile.dev
target: dev
restart: unless-stopped
volumes:
- ..:/usr/src/app
- ${UPLOAD_LOCATION}/photos:/data
- /etc/localtime:/etc/localtime:ro
- 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
- pnpm_store_server:/buildcache/pnpm-store
- ../plugins:/build/corePlugin
env_file:
- .env
@@ -63,6 +95,8 @@ services:
- 9231:9231
- 2283:2283
depends_on:
immich-init:
condition: service_healthy
redis:
condition: service_started
database:
@@ -71,6 +105,9 @@ services:
disable: false
immich-web:
extends:
service: immich-app-base
profiles: !reset []
container_name: immich_web
image: immich-web-dev:latest
build:
@@ -84,20 +121,11 @@ services:
- 3000:3000
- 24678:24678
volumes:
- ..:/usr/src/app
- 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
- pnpm_store_web:/buildcache/pnpm-store
restart: unless-stopped
depends_on:
immich-init:
condition: service_healthy
immich-server:
condition: service_started
@@ -116,7 +144,7 @@ services:
- 3003:3003
volumes:
- ../machine-learning/immich_ml:/usr/src/immich_ml
- model-cache:/cache
- model_cache:/cache
env_file:
- .env
depends_on:
@@ -127,7 +155,7 @@ services:
redis:
container_name: immich_redis
image: docker.io/valkey/valkey:9@sha256:546304417feac0874c3dd576e0952c6bb8f06bb4093ea0c9ca303c73cf458f63
image: docker.io/valkey/valkey:9@sha256:930b41430fb727f533c5982fe509b6f04233e26d0f7354e04de4b0d5c706e44e
healthcheck:
test: redis-cli ping || exit 1
@@ -156,7 +184,7 @@ services:
# image: prom/prometheus
# volumes:
# - ./prometheus.yml:/etc/prometheus/prometheus.yml
# - prometheus-data:/prometheus
# - prometheus_data:/prometheus
# first login uses admin/admin
# add data source for http://immich-prometheus:9090 to get started
@@ -167,20 +195,22 @@ services:
# - 3000:3000
# image: grafana/grafana:10.3.3-ubuntu
# volumes:
# - grafana-data:/var/lib/grafana
# - grafana_data:/var/lib/grafana
volumes:
model-cache:
prometheus-data:
grafana-data:
pnpm-store:
server-node_modules:
web-node_modules:
github-node_modules:
cli-node_modules:
docs-node_modules:
e2e-node_modules:
sdk-node_modules:
app-node_modules:
model_cache:
prometheus_data:
grafana_data:
pnpm_cache:
pnpm_store_server:
pnpm_store_web:
server_node_modules:
web_node_modules:
github_node_modules:
cli_node_modules:
docs_node_modules:
e2e_node_modules:
sdk_node_modules:
app_node_modules:
sveltekit:
coverage:

View File

@@ -56,7 +56,7 @@ services:
redis:
container_name: immich_redis
image: docker.io/valkey/valkey:9@sha256:546304417feac0874c3dd576e0952c6bb8f06bb4093ea0c9ca303c73cf458f63
image: docker.io/valkey/valkey:9@sha256:930b41430fb727f533c5982fe509b6f04233e26d0f7354e04de4b0d5c706e44e
healthcheck:
test: redis-cli ping || exit 1
restart: always

View File

@@ -61,7 +61,7 @@ services:
redis:
container_name: immich_redis
image: docker.io/valkey/valkey:9@sha256:546304417feac0874c3dd576e0952c6bb8f06bb4093ea0c9ca303c73cf458f63
image: docker.io/valkey/valkey:9@sha256:930b41430fb727f533c5982fe509b6f04233e26d0f7354e04de4b0d5c706e44e
user: '1000:1000'
security_opt:
- no-new-privileges:true

View File

@@ -49,7 +49,7 @@ services:
redis:
container_name: immich_redis
image: docker.io/valkey/valkey:9@sha256:546304417feac0874c3dd576e0952c6bb8f06bb4093ea0c9ca303c73cf458f63
image: docker.io/valkey/valkey:9@sha256:930b41430fb727f533c5982fe509b6f04233e26d0f7354e04de4b0d5c706e44e
healthcheck:
test: redis-cli ping || exit 1
restart: always

View File

@@ -1 +1 @@
24.13.0
24.13.1

View File

@@ -44,7 +44,7 @@ While this guide focuses on VS Code, you have many options for Dev Container dev
**Self-Hostable Options:**
- [Coder](https://coder.com) - Enterprise-focused, requires Terraform knowledge, self-managed
- [DevPod](https://devpod.sh) - Client-only tool with excellent devcontainer.json support, works with any provider (local, cloud, or on-premise)
- [DevPod](https://devpod.sh) - Client-only tool with excellent devcontainer.json support, works with any provider (local, cloud, or on-premise). Check [quick-start guide](#quick-start-guide-for-devpod-with-docker)
:::
## Dev Container Services
@@ -408,7 +408,27 @@ If you encounter issues:
1. Check container logs: View → Output → Select "Dev Containers"
2. Rebuild without cache: "Dev Containers: Rebuild Container Without Cache"
3. Review [common Docker issues](https://docs.docker.com/desktop/troubleshoot/)
4. Ask in [Discord](https://discord.immich.app) `#help-desk-support` channel
4. Ask in [Discord](https://discord.immich.app) `#contributing` channel
### Quick-start guide for DevPod with docker
You will need DevPod CLI (check [DevPod CLI installation guide](https://devpod.sh/docs/getting-started/install)) and Docker Desktop.
```sh
# Step 1: Clone the Repository
git clone https://github.com/immich-app/immich.git
cd immich
# Step 2: Prepare DevPod (if you haven't already)
devpod provider add docker
devpod provider use docker
# Step 3: Build 'immich-server-dev' docker image first manually
docker build -f server/Dockerfile.dev -t immich-server-dev .
# Step 4: Now you can start devcontainer
devpod up .
```
## Mobile Development

View File

@@ -80,6 +80,10 @@ There is an automatic scan job that is scheduled to run once a day. Its schedule
This job also cleans up any libraries stuck in deletion. It is possible to trigger the cleanup by clicking "Scan all libraries" in the library management page.
### Deleting a Library
When deleting an external library, all assets inside are immediately deleted along with the library. Note that while a library can take a long time to fully delete in the background, it is immediately removed from the library list. If the deletion process is interrupted (for example, due to server restart), it will be cleaned up in the next nightly cron job. The cleanup process can also be manually initiated by clicking the "Scan All Libraries" button in the library list.
## Usage
Let's show a concrete example where we add an existing gallery to Immich. Here, we have the following folders we want to add:

View File

@@ -38,6 +38,7 @@ For the full list, refer to the [Immich source code](https://github.com/immich-a
| `MP2T` | `.mts` `.m2ts` `.m2t` | :white_check_mark: | |
| `MP4` | `.mp4` `.insv` | :white_check_mark: | |
| `MPEG` | `.mpg` `.mpe` `.mpeg` | :white_check_mark: | |
| `MXF` | `.mxf` | :white_check_mark: | |
| `QUICKTIME` | `.mov` | :white_check_mark: | |
| `WEBM` | `.webm` | :white_check_mark: | |
| `WMV` | `.wmv` | :white_check_mark: | |

View File

@@ -8,7 +8,8 @@ A config file can be provided as an alternative to the UI configuration.
### Step 1 - Create a new config file
In JSON format, create a new config file (e.g. `immich.json`) and put it in a location that can be accessed by Immich.
In JSON format, create a new config file (e.g. `immich.json`) and put it in a location mounted in the container that can be accessed by Immich.
YAML-formatted config files are also supported.
The default configuration looks like this:
<details>
@@ -251,6 +252,15 @@ So you can just grab it from there, paste it into a file and you're pretty much
In your `.env` file, set the variable `IMMICH_CONFIG_FILE` to the path of your config.
For more information, refer to the [Environment Variables](/install/environment-variables.md) section.
:::tip
YAML-formatted config files are also supported.
:::
:::info Docker Compose
In your `.env` file, the variables `UPLOAD_LOCATION` and `DB_DATA_LOCATION` concern the location on the host.
However, the variable `IMMICH_CONFIG_FILE` concerns the location inside the container, and informs the `immich-server` container that a configuration file is present.
It is recommended to reuse this variable in your `docker-compose.yml`:
```yaml
volumes:
- ./configuration.yml:${IMMICH_CONFIG_FILE}
```
::

View File

@@ -8,8 +8,6 @@ sidebar_position: 85
This is a community contribution and not officially supported by the Immich team, but included here for convenience.
Community support can be found in the dedicated channel on the [Discord Server](https://discord.immich.app/).
**Please report app issues to the corresponding [Github Repository](https://github.com/truenas/charts/tree/master/community/immich).**
:::
Immich can easily be installed on a Synology NAS using Container Manager within DSM. If you have not installed Container Manager already, you can install it in the Packages Center. Refer to the [Container Manager docs](https://kb.synology.com/en-us/DSM/help/ContainerManager/docker_desc?version=7) for more information on using Container Manager.

View File

@@ -23,3 +23,9 @@ run = "prettier --check ."
[tasks."format-fix"]
env._.path = "./node_modules/.bin"
run = "prettier --write ."
[tasks.deploy]
run = "wrangler pages deploy build --project-name=${PROJECT_NAME} --branch=${BRANCH_NAME}"
[tools]
wrangler = "4.66.0"

View File

@@ -8,7 +8,7 @@
"format:fix": "prettier --write .",
"start": "docusaurus start --port 3005",
"copy:openapi": "jq -c < ../open-api/immich-openapi-specs.json > ./static/openapi.json || exit 0",
"build": "npm run copy:openapi && docusaurus build",
"build": "pnpm run copy:openapi && docusaurus build",
"swizzle": "docusaurus swizzle",
"deploy": "docusaurus deploy",
"clear": "docusaurus clear",
@@ -58,6 +58,6 @@
"node": ">=20"
},
"volta": {
"node": "24.13.0"
"node": "24.13.1"
}
}

View File

@@ -32,3 +32,7 @@ If you would like to migrate from one media location to another, simply successf
4. Start up Immich
After version `1.136.0`, Immich can detect when a media location has moved and will automatically update the database paths to keep them in sync.
## Schema drift
Schema drift is when the database schema is out of sync with the code. This could be the result of manual database tinkering, issues during a database restore, or something else. Schema drift can lead to data corruption, application bugs, and other unpredictable behavior. Please reconcile the differences as soon as possible. Specifically, missing `CONSTRAINT`s can result in duplicate assets being uploaded, since the server relies on a checksum `CONSTRAINT` to prevent duplicates.

View File

@@ -1 +1 @@
24.13.0
24.13.1

View File

@@ -1,86 +1,77 @@
name: immich-e2e
services:
immich-app-base:
extends:
file: ../docker/docker-compose.dev.yml
service: immich-app-base
immich-init:
extends:
file: ../docker/docker-compose.dev.yml
service: immich-init
container_name: immich-e2e-init
immich-server:
extends:
file: ../docker/docker-compose.dev.yml
service: immich-server
container_name: immich-e2e-server
command: ['immich-dev']
image: immich-server-dev:latest
build:
context: ../
dockerfile: server/Dockerfile.dev
target: dev
ports: !reset []
env_file: !reset []
environment:
- DB_HOSTNAME=database
- DB_USERNAME=postgres
- DB_PASSWORD=postgres
- DB_DATABASE_NAME=immich
- IMMICH_MACHINE_LEARNING_ENABLED=false
- IMMICH_TELEMETRY_INCLUDE=all
- IMMICH_ENV=testing
- IMMICH_PORT=2285
- IMMICH_IGNORE_MOUNT_CHECK_ERRORS=true
DB_HOSTNAME: database
DB_USERNAME: postgres
DB_PASSWORD: postgres
DB_DATABASE_NAME: immich
IMMICH_MACHINE_LEARNING_ENABLED: 'false'
IMMICH_TELEMETRY_INCLUDE: all
IMMICH_ENV: testing
IMMICH_PORT: '2285'
IMMICH_IGNORE_MOUNT_CHECK_ERRORS: 'true'
volumes:
- ./test-assets:/test-assets
- ..:/usr/src/app
- ${UPLOAD_LOCATION}/photos:/data
- /etc/localtime:/etc/localtime:ro
- 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
- ../plugins:/build/corePlugin
depends_on:
immich-init:
condition: service_healthy
redis:
condition: service_started
database:
condition: service_healthy
immich-web:
extends:
file: ../docker/docker-compose.dev.yml
service: immich-web
container_name: immich-e2e-web
image: immich-web-dev:latest
build:
context: ../
dockerfile: server/Dockerfile.dev
target: dev
command: ['immich-web']
ports:
ports: !override
- 2285:3000
environment:
- IMMICH_SERVER_URL=http://immich-server:2285/
volumes:
- ..:/usr/src/app
- 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
IMMICH_SERVER_URL: http://immich-server:2285/
depends_on:
immich-init:
condition: service_healthy
restart: unless-stopped
redis:
image: redis:6.2-alpine@sha256:46884be93652d02a96a176ccf173d1040bef365c5706aa7b6a1931caec8bfeef
extends:
file: ../docker/docker-compose.dev.yml
service: redis
container_name: immich-e2e-redis
database:
image: ghcr.io/immich-app/postgres:14-vectorchord0.3.0@sha256:6f3e9d2c2177af16c2988ff71425d79d89ca630ec2f9c8db03209ab716542338
extends:
file: ../docker/docker-compose.dev.yml
service: database
container_name: immich-e2e-postgres
command: -c fsync=off -c shared_preload_libraries=vchord.so -c config_file=/var/lib/postgresql/data/postgresql.conf
env_file: !reset []
ports: !override
- 5435:5432
environment:
POSTGRES_PASSWORD: postgres
POSTGRES_USER: postgres
POSTGRES_DB: immich
ports:
- 5435:5432
healthcheck:
test: ['CMD-SHELL', 'pg_isready -U postgres -d immich']
interval: 1s
@@ -89,17 +80,19 @@ services:
start_period: 10s
volumes:
model-cache:
prometheus-data:
grafana-data:
pnpm-store:
server-node_modules:
web-node_modules:
github-node_modules:
cli-node_modules:
docs-node_modules:
e2e-node_modules:
sdk-node_modules:
app-node_modules:
model_cache:
prometheus_data:
grafana_data:
pnpm_cache:
pnpm_store_server:
pnpm_store_web:
server_node_modules:
web_node_modules:
github_node_modules:
cli_node_modules:
docs_node_modules:
e2e_node_modules:
sdk_node_modules:
app_node_modules:
sveltekit:
coverage:

View File

@@ -2,6 +2,7 @@ name: immich-e2e
services:
e2e-auth-server:
container_name: immich-e2e-auth-server
build:
context: ../e2e-auth-server
ports:
@@ -22,15 +23,15 @@ services:
- BUILD_SOURCE_REF=e2e
- BUILD_SOURCE_COMMIT=e2eeeeeeeeeeeeeeeeee
environment:
- DB_HOSTNAME=database
- DB_USERNAME=postgres
- DB_PASSWORD=postgres
- DB_DATABASE_NAME=immich
- IMMICH_MACHINE_LEARNING_ENABLED=false
- IMMICH_TELEMETRY_INCLUDE=all
- IMMICH_ENV=testing
- IMMICH_PORT=2285
- IMMICH_IGNORE_MOUNT_CHECK_ERRORS=true
DB_HOSTNAME: database
DB_USERNAME: postgres
DB_PASSWORD: postgres
DB_DATABASE_NAME: immich
IMMICH_MACHINE_LEARNING_ENABLED: 'false'
IMMICH_TELEMETRY_INCLUDE: all
IMMICH_ENV: testing
IMMICH_PORT: '2285'
IMMICH_IGNORE_MOUNT_CHECK_ERRORS: 'true'
volumes:
- ./test-assets:/test-assets
depends_on:
@@ -42,10 +43,14 @@ services:
- 2285:2285
redis:
image: redis:6.2-alpine@sha256:46884be93652d02a96a176ccf173d1040bef365c5706aa7b6a1931caec8bfeef
container_name: immich-e2e-redis
image: docker.io/valkey/valkey:9@sha256:930b41430fb727f533c5982fe509b6f04233e26d0f7354e04de4b0d5c706e44e
healthcheck:
test: redis-cli ping || exit 1
database:
image: ghcr.io/immich-app/postgres:14-vectorchord0.3.0@sha256:6f3e9d2c2177af16c2988ff71425d79d89ca630ec2f9c8db03209ab716542338
container_name: immich-e2e-postgres
image: ghcr.io/immich-app/postgres:14-vectorchord0.4.3-pgvectors0.2.0@sha256:bcf63357191b76a916ae5eb93464d65c07511da41e3bf7a8416db519b40b1c23
command: -c fsync=off -c shared_preload_libraries=vchord.so -c config_file=/var/lib/postgresql/data/postgresql.conf
environment:
POSTGRES_PASSWORD: postgres
@@ -53,6 +58,7 @@ services:
POSTGRES_DB: immich
ports:
- 5435:5432
shm_size: 128mb
healthcheck:
test: ['CMD-SHELL', 'pg_isready -U postgres -d immich']
interval: 1s

View File

@@ -7,37 +7,42 @@
"scripts": {
"test": "vitest --run",
"test:watch": "vitest",
"test:web": "npx playwright test",
"start:web": "npx playwright test --ui",
"test:maintenance": "vitest --run --config vitest.maintenance.config.ts",
"test:web": "pnpm exec playwright test --project=web",
"test:web:maintenance": "pnpm exec playwright test --project=maintenance",
"test:web:ui": "pnpm exec playwright test --project=ui",
"start:web": "pnpm exec playwright test --ui --project=web",
"start:web:maintenance": "pnpm exec playwright test --ui --project=maintenance",
"start:web:ui": "pnpm exec playwright test --ui --project=ui",
"format": "prettier --check .",
"format:fix": "prettier --write .",
"lint": "eslint \"src/**/*.ts\" --max-warnings 0",
"lint:fix": "npm run lint -- --fix",
"lint:fix": "pnpm run lint --fix",
"check": "tsc --noEmit"
},
"keywords": [],
"author": "",
"license": "GNU Affero General Public License version 3",
"devDependencies": {
"@eslint/js": "^9.8.0",
"@eslint/js": "^10.0.0",
"@faker-js/faker": "^10.1.0",
"@immich/cli": "file:../cli",
"@immich/e2e-auth-server": "file:../e2e-auth-server",
"@immich/sdk": "file:../open-api/typescript-sdk",
"@immich/cli": "workspace:*",
"@immich/e2e-auth-server": "workspace:*",
"@immich/sdk": "workspace:*",
"@playwright/test": "^1.44.1",
"@socket.io/component-emitter": "^3.1.2",
"@types/luxon": "^3.4.2",
"@types/node": "^24.10.11",
"@types/node": "^24.10.13",
"@types/pg": "^8.15.1",
"@types/pngjs": "^6.0.4",
"@types/supertest": "^6.0.2",
"dotenv": "^17.2.3",
"eslint": "^9.14.0",
"eslint": "^10.0.0",
"eslint-config-prettier": "^10.1.8",
"eslint-plugin-prettier": "^5.1.3",
"eslint-plugin-unicorn": "^62.0.0",
"exiftool-vendored": "^34.3.0",
"globals": "^16.0.0",
"eslint-plugin-unicorn": "^63.0.0",
"exiftool-vendored": "^35.0.0",
"globals": "^17.0.0",
"luxon": "^3.4.4",
"pg": "^8.11.3",
"pngjs": "^7.0.0",
@@ -52,6 +57,6 @@
"vitest": "^3.0.0"
},
"volta": {
"node": "24.13.0"
"node": "24.13.1"
}
}

View File

@@ -3,7 +3,7 @@ import dotenv from 'dotenv';
import { cpus } from 'node:os';
import { resolve } from 'node:path';
dotenv.config({ path: resolve(import.meta.dirname, '.env') });
dotenv.config({ quiet: true, path: resolve(import.meta.dirname, '.env') });
export const playwrightHost = process.env.PLAYWRIGHT_HOST ?? '127.0.0.1';
export const playwrightDbHost = process.env.PLAYWRIGHT_DB_HOST ?? '127.0.0.1';
@@ -48,7 +48,7 @@ const config: PlaywrightTestConfig = {
{
name: 'maintenance',
use: { ...devices['Desktop Chrome'] },
testDir: './src/specs/maintenance',
testDir: './src/specs/maintenance/web',
workers: 1,
},
],

View File

@@ -43,10 +43,10 @@ export const errorDto = {
message: 'Invalid share key',
correlationId: expect.any(String),
},
invalidSharePassword: {
passwordRequired: {
error: 'Unauthorized',
statusCode: 401,
message: 'Invalid password',
message: 'Password required',
correlationId: expect.any(String),
},
badRequest: (message: any = null) => ({

View File

@@ -253,7 +253,8 @@ describe('/asset', () => {
expect(status).toBe(200);
expect(body.id).toEqual(facesAsset.id);
expect(body.people).toMatchObject(expectedFaces);
const sortedPeople = body.people.toSorted((a: any, b: any) => a.name.localeCompare(b.name));
expect(sortedPeople).toMatchObject(expectedFaces);
});
});

View File

@@ -239,7 +239,7 @@ describe('/shared-links', () => {
const { status, body } = await request(app).get('/shared-links/me').query({ key: linkWithPassword.key });
expect(status).toBe(401);
expect(body).toEqual(errorDto.invalidSharePassword);
expect(body).toEqual(errorDto.passwordRequired);
});
it('should get data for correct password protected link', async () => {

View File

@@ -45,8 +45,7 @@ test.describe('Shared Links', () => {
await page.goto(`/share/${sharedLink.key}`);
await page.getByRole('heading', { name: 'Test Album' }).waitFor();
await page.locator(`[data-asset-id="${asset.id}"]`).hover();
await page.waitForSelector('[data-group] svg');
await page.getByRole('checkbox').click();
await page.waitForSelector(`[data-asset-id="${asset.id}"] [role="checkbox"]`);
await Promise.all([page.waitForEvent('download'), page.getByRole('button', { name: 'Download' }).click()]);
});

View File

@@ -438,7 +438,7 @@ test.describe('Timeline', () => {
const asset = getAsset(timelineRestData, album.assetIds[0])!;
await pageUtils.goToAsset(page, asset.fileCreatedAt);
await thumbnailUtils.expectInViewport(page, asset.id);
await thumbnailUtils.expectSelectedReadonly(page, asset.id);
await thumbnailUtils.expectSelectedDisabled(page, asset.id);
});
test('Add photos to album', async ({ page }) => {
const album = timelineRestData.album;
@@ -447,7 +447,7 @@ test.describe('Timeline', () => {
const asset = getAsset(timelineRestData, album.assetIds[0])!;
await pageUtils.goToAsset(page, asset.fileCreatedAt);
await thumbnailUtils.expectInViewport(page, asset.id);
await thumbnailUtils.expectSelectedReadonly(page, asset.id);
await thumbnailUtils.expectSelectedDisabled(page, asset.id);
await pageUtils.selectDay(page, 'Tue, Feb 27, 2024');
const put = pageRoutePromise(page, `**/api/albums/${album.id}/assets`, async (route, request) => {
const requestJson = request.postDataJSON();

View File

@@ -65,7 +65,7 @@ export const thumbnailUtils = {
return page.locator(`[data-thumbnail-focus-container][data-asset="${assetId}"] button`);
},
selectedAsset(page: Page) {
return page.locator('[data-thumbnail-focus-container]:has(button[aria-checked])');
return page.locator('[data-thumbnail-focus-container][data-selected]');
},
async clickAssetId(page: Page, assetId: string) {
await thumbnailUtils.withAssetId(page, assetId).click();
@@ -102,12 +102,9 @@ export const thumbnailUtils = {
async expectThumbnailIsNotArchive(page: Page, assetId: string) {
await expect(thumbnailUtils.withAssetId(page, assetId).locator('[data-icon-archive]')).toHaveCount(0);
},
async expectSelectedReadonly(page: Page, assetId: string) {
// todo - need a data attribute for selected
async expectSelectedDisabled(page: Page, assetId: string) {
await expect(
page.locator(
`[data-thumbnail-focus-container][data-asset="${assetId}"] > .group.cursor-not-allowed > .rounded-xl`,
),
page.locator(`[data-thumbnail-focus-container][data-asset="${assetId}"][data-selected][data-disabled]`),
).toBeVisible();
},
async expectTimelineHasOnScreenAssets(page: Page) {

View File

@@ -1,15 +1,20 @@
import { defineConfig } from 'vitest/config';
// skip `docker compose up` if `make e2e` was already run
const skipDockerSetup = process.env.VITEST_DISABLE_DOCKER_SETUP === 'true';
// skip `docker compose up` if `make e2e` was already run or if VITEST_DISABLE_DOCKER_SETUP is set
const globalSetup: string[] = [];
try {
await fetch('http://127.0.0.1:2285/api/server/ping');
} catch {
globalSetup.push('src/docker-compose.ts');
if (!skipDockerSetup) {
try {
await fetch('http://127.0.0.1:2285/api/server/ping');
} catch {
globalSetup.push('src/docker-compose.ts');
}
}
export default defineConfig({
test: {
retry: process.env.CI ? 4 : 0,
include: ['src/specs/server/**/*.e2e-spec.ts'],
globalSetup,
testTimeout: 15_000,

View File

@@ -0,0 +1,28 @@
import { defineConfig } from 'vitest/config';
const skipDockerSetup = process.env.VITEST_DISABLE_DOCKER_SETUP === 'true';
// skip `docker compose up` if `make e2e` was already run or if VITEST_DISABLE_DOCKER_SETUP is set
const globalSetup: string[] = [];
if (!skipDockerSetup) {
try {
await fetch('http://127.0.0.1:2285/api/server/ping');
} catch {
globalSetup.push('src/docker-compose.ts');
}
}
export default defineConfig({
test: {
retry: process.env.CI ? 4 : 0,
include: ['src/specs/maintenance/server/**/*.e2e-spec.ts'],
globalSetup,
testTimeout: 15_000,
pool: 'threads',
poolOptions: {
threads: {
singleThread: true,
},
},
},
});

View File

@@ -1613,7 +1613,6 @@
"not_available": "غير متاح",
"not_in_any_album": "ليست في أي ألبوم",
"not_selected": "لم يختار",
"note_apply_storage_label_to_previously_uploaded assets": "ملاحظة: لتطبيق سمة التخزين على المحتويات التي تم رفعها مسبقًا، قم بتشغيل",
"notes": "ملاحظات",
"nothing_here_yet": "لا يوجد شيء هنا بعد",
"notification_permission_dialog_content": "لتمكين الإخطارات ، انتقل إلى الإعدادات و اختار السماح.",
@@ -1815,7 +1814,7 @@
"reassigned_assets_to_new_person": "تمت إعادة تعيين {count, plural, one {# المحتوى} other {# المحتويات}} إلى شخص جديد",
"reassing_hint": "تعيين المحتويات المحددة لشخص موجود",
"recent": "حديث",
"recent-albums": "ألبومات الحديثة",
"recent_albums": "ألبومات الحديثة",
"recent_searches": "عمليات البحث الأخيرة",
"recently_added": "اضيف مؤخرا",
"recently_added_page_title": "أضيف مؤخرا",

View File

@@ -457,7 +457,7 @@
"reassign": "Перапрызначыць",
"reassing_hint": "Прыпісаць выбраныя актывы існуючай асобе",
"recent": "Нядаўні",
"recent-albums": "Нядаўнія альбомы",
"recent_albums": "Нядаўнія альбомы",
"recent_searches": "Нядаўнія пошукі",
"recently_added": "Нядаўна дададзена",
"refresh_faces": "Абнавіць твары",

View File

@@ -1613,7 +1613,6 @@
"not_available": "Неналично",
"not_in_any_album": "Не е в никой албум",
"not_selected": "Не е избрано",
"note_apply_storage_label_to_previously_uploaded assets": "Забележка: За да приложите етикета за съхранение към предварително качени активи, стартирайте",
"notes": "Бележки",
"nothing_here_yet": "Засега тук няма нищо",
"notification_permission_dialog_content": "За да включиш известията, отиди в Настройки и избери Разреши.",
@@ -1815,7 +1814,7 @@
"reassigned_assets_to_new_person": "Преназначени {count, plural, one {# елемент} other {# елемента}} на нов човек",
"reassing_hint": "Назначи избраните елементи на съществуващо лице",
"recent": "Скорошни",
"recent-albums": "Скорошни Албуми",
"recent_albums": "Скорошни Албуми",
"recent_searches": "Скорошни търсения",
"recently_added": "Наскоро добавено",
"recently_added_page_title": "Наскоро добавено",

View File

@@ -17,7 +17,7 @@
"readonly_mode_enabled": "Mod blo yu no save janjem i on",
"reassigned_assets_to_new_person": "Janjem{count, plural, one {# asset} other {# assets}} blo nu man",
"reassing_hint": "janjem ol sumtin yu bin joos i go blo wan man",
"recent-albums": "album i no old tu mas",
"recent_albums": "album i no old tu mas",
"recent_searches": "lukabout wea i no old tu mas",
"time_based_memories_duration": "hao mus second blo wan wan imij i stap lo scrin.",
"timezone": "taemzon",

View File

@@ -311,7 +311,7 @@
"search_jobs": "Cercar treballs…",
"send_welcome_email": "Enviar correu electrònic de benvinguda",
"server_external_domain_settings": "Domini extern",
"server_external_domain_settings_description": "Domini per enllaços públics compartits, incloent http(s)://",
"server_external_domain_settings_description": "Domini utilitzat per a enllaços externs",
"server_public_users": "Usuaris públics",
"server_public_users_description": "Tots els usuaris (nom i correu electrònic) apareixen a la llista a l'afegir un usuari als àlbums compartits. Si es desactiva, la llista només serà disponible pels usuaris administradors.",
"server_settings": "Configuració del servidor",
@@ -794,6 +794,11 @@
"color": "Color",
"color_theme": "Tema de color",
"command": "Ordre",
"command_palette_prompt": "Trobar ràpidament pàgines, accions o comandes",
"command_palette_to_close": "per a tancar",
"command_palette_to_navigate": "per a introduir",
"command_palette_to_select": "per a seleccionar",
"command_palette_to_show_all": "per a mostrar-ho tot",
"comment_deleted": "Comentari esborrat",
"comment_options": "Opcions de comentari",
"comments_and_likes": "Comentaris i agradaments",
@@ -1168,6 +1173,7 @@
"exif_bottom_sheet_people": "PERSONES",
"exif_bottom_sheet_person_add_person": "Afegir nom",
"exit_slideshow": "Surt de la presentació de diapositives",
"expand": "Ampliar-ho",
"expand_all": "Ampliar-ho tot",
"experimental_settings_new_asset_list_subtitle": "Treball en curs",
"experimental_settings_new_asset_list_title": "Habilita la graella de fotos experimental",
@@ -1532,7 +1538,7 @@
"mobile_app_download_onboarding_note": "Descarregar la App de mòbil fent servir les seguents opcions",
"model": "Model",
"month": "Mes",
"monthly_title_text_date_format": "MMMM y",
"monthly_title_text_date_format": "MMMM a",
"more": "Més",
"move": "Moure",
"move_down": "Moure cap avall",
@@ -1613,7 +1619,6 @@
"not_available": "N/A",
"not_in_any_album": "En cap àlbum",
"not_selected": "No seleccionat",
"note_apply_storage_label_to_previously_uploaded assets": "Nota: per aplicar l'etiqueta d'emmagatzematge als actius penjats anteriorment, executeu el",
"notes": "Notes",
"nothing_here_yet": "No hi ha res encara",
"notification_permission_dialog_content": "Per activar les notificacions, aneu a Configuració i seleccioneu permet.",
@@ -1643,6 +1648,7 @@
"online": "En línia",
"only_favorites": "Només preferits",
"open": "Obrir",
"open_calendar": "Obrir el calendari",
"open_in_map_view": "Obrir a la vista del mapa",
"open_in_openstreetmap": "Obre a OpenStreetMap",
"open_the_search_filters": "Obriu els filtres de cerca",
@@ -1815,7 +1821,7 @@
"reassigned_assets_to_new_person": "{count, plural, one {S'ha reassignat # recurs} other {S'han reassignat # recursos}} a una persona nova",
"reassing_hint": "Assignar els elements seleccionats a una persona existent",
"recent": "Recent",
"recent-albums": "Àlbums recents",
"recent_albums": "Àlbums recents",
"recent_searches": "Cerques recents",
"recently_added": "Afegit recentment",
"recently_added_page_title": "Afegit recentment",
@@ -2184,6 +2190,7 @@
"support": "Suport",
"support_and_feedback": "Suport i comentaris",
"support_third_party_description": "La vostra instal·lació immich la va empaquetar un tercer. Els problemes que experimenteu poden ser causats per aquest paquet així que, si us plau, plantegeu els poblemes amb ells en primer lloc mitjançant els enllaços següents.",
"supporter": "Contribuïdor",
"swap_merge_direction": "Canvia la direcció d'unió",
"sync": "Sincronitza",
"sync_albums": "Sincronitzar àlbums",

View File

@@ -311,7 +311,7 @@
"search_jobs": "Hledat úlohy…",
"send_welcome_email": "Odeslat uvítací e-mail",
"server_external_domain_settings": "Externí doména",
"server_external_domain_settings_description": "Doména pro veřejně sdílené odkazy, včetně http(s)://",
"server_external_domain_settings_description": "Doména používaná pro externí odkazy",
"server_public_users": "Veřejní uživatelé",
"server_public_users_description": "Všichni uživatelé (jméno a e-mail) jsou uvedeni při přidávání uživatele do sdílených alb. Pokud je tato funkce vypnuta, bude seznam uživatelů dostupný pouze uživatelům z řad správců.",
"server_settings": "Server",
@@ -794,6 +794,11 @@
"color": "Barva",
"color_theme": "Barevný motiv",
"command": "Příkaz",
"command_palette_prompt": "Rychlé vyhledávání stránek, akcí nebo příkazů",
"command_palette_to_close": "zavřít",
"command_palette_to_navigate": "vstoupit",
"command_palette_to_select": "vybrat",
"command_palette_to_show_all": "zobrazit vše",
"comment_deleted": "Komentář odstraněn",
"comment_options": "Možnosti komentáře",
"comments_and_likes": "Komentáře a lajky",
@@ -1168,6 +1173,7 @@
"exif_bottom_sheet_people": "LIDÉ",
"exif_bottom_sheet_person_add_person": "Přidat jméno",
"exit_slideshow": "Ukončit prezentaci",
"expand": "Rozbalit",
"expand_all": "Rozbalit vše",
"experimental_settings_new_asset_list_subtitle": "Zpracovávám",
"experimental_settings_new_asset_list_title": "Povolení experimentální mřížky fotografií",
@@ -1613,7 +1619,6 @@
"not_available": "Není k dispozici",
"not_in_any_album": "Bez alba",
"not_selected": "Není vybráno",
"note_apply_storage_label_to_previously_uploaded assets": "Upozornění: Chcete-li použít štítek úložiště na dříve nahrané položky, spusťte příkaz",
"notes": "Poznámky",
"nothing_here_yet": "Zatím zde nic není",
"notification_permission_dialog_content": "Chcete-li povolit oznámení, přejděte do nastavení a vyberte možnost povolit.",
@@ -1643,6 +1648,7 @@
"online": "Online",
"only_favorites": "Pouze oblíbené",
"open": "Otevřít",
"open_calendar": "Otevřít kalendář",
"open_in_map_view": "Otevřít v zobrazení mapy",
"open_in_openstreetmap": "Otevřít v OpenStreetMap",
"open_the_search_filters": "Otevřít vyhledávací filtry",
@@ -1815,7 +1821,7 @@
"reassigned_assets_to_new_person": "{count, plural, one {Přeřazena # položka} few {Přeřazeny # položky} other {Přeřazeno # položek}} na novou osobu",
"reassing_hint": "Přiřazení vybraných položek existující osobě",
"recent": "Nedávné",
"recent-albums": "Nedávná alba",
"recent_albums": "Nedávná alba",
"recent_searches": "Nedávná vyhledávání",
"recently_added": "Nedávno přidané",
"recently_added_page_title": "Nedávno přidané",
@@ -2184,6 +2190,7 @@
"support": "Podpora",
"support_and_feedback": "Podpora a zpětná vazba",
"support_third_party_description": "Vaše Immich instalace byla připravena třetí stranou. Problémy, které se u vás vyskytly, mohou být způsobeny tímto balíčkem, proto se na ně obraťte v první řadě pomocí níže uvedených odkazů.",
"supporter": "Podporovatel",
"swap_merge_direction": "Obrátit směr sloučení",
"sync": "Synchronizovat",
"sync_albums": "Synchronizovat alba",

View File

@@ -1613,7 +1613,6 @@
"not_available": "ikke tilgængelig",
"not_in_any_album": "Ikke i noget album",
"not_selected": "Ikke valgt",
"note_apply_storage_label_to_previously_uploaded assets": "Bemærk: For at anvende Lagringsmærkat på tidligere uploadede medier, kør opgaven igen",
"notes": "Noter",
"nothing_here_yet": "Intet her endnu",
"notification_permission_dialog_content": "Gå til indstillinger for at slå notifikationer til.",
@@ -1815,7 +1814,7 @@
"reassigned_assets_to_new_person": "Gentildelt {count, plural, one {# aktiv} other {# aktiver}} til en ny person",
"reassing_hint": "Tildel valgte mediefiler til en eksisterende person",
"recent": "For nylig",
"recent-albums": "Seneste albums",
"recent_albums": "Seneste albums",
"recent_searches": "Seneste søgninger",
"recently_added": "Senest tilføjet",
"recently_added_page_title": "Nyligt tilføjet",

View File

@@ -1,8 +1,8 @@
{
"about": "Über",
"about": "Über Immich",
"account": "Konto",
"account_settings": "Kontoeinstellungen",
"acknowledge": "Bestätigen",
"acknowledge": "Verstanden",
"action": "Aktion",
"action_common_update": "Aktualisieren",
"action_description": "Eine Reihe von Aktionen, die an den gefilterten Assets ausgeführt werden sollen",
@@ -1613,7 +1613,6 @@
"not_available": "N/A",
"not_in_any_album": "In keinem Album",
"not_selected": "Nicht ausgewählt",
"note_apply_storage_label_to_previously_uploaded assets": "Hinweis: Um eine Speicherpfadbezeichnung anzuwenden, starte den",
"notes": "Notizen",
"nothing_here_yet": "Noch nichts hier",
"notification_permission_dialog_content": "Um Benachrichtigungen zu aktivieren, navigiere zu Einstellungen und klicke \"Erlauben\".",
@@ -1815,7 +1814,7 @@
"reassigned_assets_to_new_person": "{count, plural, one {# Datei wurde} other {# Dateien wurden}} einer neuen Person zugewiesen",
"reassing_hint": "Markierte Dateien einer vorhandenen Person zuweisen",
"recent": "Neueste",
"recent-albums": "Neueste Alben",
"recent_albums": "Neueste Alben",
"recent_searches": "Letzte Suchen",
"recently_added": "Kürzlich hinzugefügt",
"recently_added_page_title": "Zuletzt hinzugefügt",

View File

@@ -1613,7 +1613,6 @@
"not_available": "Μ/Δ (Μη Διαθέσιμο)",
"not_in_any_album": "Σε κανένα άλμπουμ",
"not_selected": "Δεν επιλέχθηκε",
"note_apply_storage_label_to_previously_uploaded assets": "Σημείωση: Για να εφαρμόσετε την Ετικέτα Αποθήκευσης σε στοιχεία που έχουν μεταφορτωθεί προηγουμένως, εκτελέστε το",
"notes": "Σημειώσεις",
"nothing_here_yet": "Τίποτα εδώ ακόμα",
"notification_permission_dialog_content": "Για να ενεργοποιήσετε τις ειδοποιήσεις, μεταβείτε στις Ρυθμίσεις και επιλέξτε να επιτρέπεται.",
@@ -1815,7 +1814,7 @@
"reassigned_assets_to_new_person": "Η ανάθεση {count, plural, one {# αρχείου} other {# αρχείων}} σε νέο άτομο",
"reassing_hint": "Ανάθεση των επιλεγμένων στοιχείων σε υπάρχον άτομο",
"recent": "Πρόσφατα",
"recent-albums": "Πρόσφατα άλμπουμ",
"recent_albums": "Πρόσφατα άλμπουμ",
"recent_searches": "Πρόσφατες αναζητήσεις",
"recently_added": "Προστέθηκαν πρόσφατα",
"recently_added_page_title": "Προστέθηκαν Πρόσφατα",

View File

@@ -311,7 +311,7 @@
"search_jobs": "Search jobs…",
"send_welcome_email": "Send welcome email",
"server_external_domain_settings": "External domain",
"server_external_domain_settings_description": "Domain for public shared links, including http(s)://",
"server_external_domain_settings_description": "Domain used for external links",
"server_public_users": "Public Users",
"server_public_users_description": "All users (name and email) are listed when adding a user to shared albums. When disabled, the user list will only be available to admin users.",
"server_settings": "Server Settings",
@@ -794,6 +794,11 @@
"color": "Color",
"color_theme": "Color theme",
"command": "Command",
"command_palette_prompt": "Quickly find pages, actions, or commands",
"command_palette_to_close": "to close",
"command_palette_to_navigate": "to enter",
"command_palette_to_select": "to select",
"command_palette_to_show_all": "to show all",
"comment_deleted": "Comment deleted",
"comment_options": "Comment options",
"comments_and_likes": "Comments & likes",
@@ -1045,6 +1050,7 @@
"cant_get_number_of_comments": "Can't get number of comments",
"cant_search_people": "Can't search people",
"cant_search_places": "Can't search places",
"enable_webgl_for_map": "Enable WebGL to load the map.{isAdmin, select, true { To hide this warning, disable the map feature.} other {}}",
"error_adding_assets_to_album": "Error adding assets to album",
"error_adding_users_to_album": "Error adding users to album",
"error_deleting_shared_user": "Error deleting shared user",
@@ -1069,6 +1075,7 @@
"failed_to_update_notification_status": "Failed to update notification status",
"incorrect_email_or_password": "Incorrect email or password",
"library_folder_already_exists": "This import path already exists.",
"page_not_found": "Page not found :/",
"paths_validation_failed": "{paths, plural, one {# path} other {# paths}} failed validation",
"profile_picture_transparent_pixels": "Profile pictures cannot have transparent pixels. Please zoom in and/or move the image.",
"quota_higher_than_disk_size": "You set a quota higher than the disk size",
@@ -1168,6 +1175,7 @@
"exif_bottom_sheet_people": "PEOPLE",
"exif_bottom_sheet_person_add_person": "Add name",
"exit_slideshow": "Exit Slideshow",
"expand": "Expand",
"expand_all": "Expand all",
"experimental_settings_new_asset_list_subtitle": "Work in progress",
"experimental_settings_new_asset_list_title": "Enable experimental photo grid",
@@ -1212,6 +1220,7 @@
"filter_description": "Conditions to filter the target assets",
"filter_people": "Filter people",
"filter_places": "Filter places",
"filter_tags": "Filter tags",
"filters": "Filters",
"find_them_fast": "Find them fast by name with search",
"first": "First",
@@ -1237,6 +1246,7 @@
"go_back": "Go back",
"go_to_folder": "Go to folder",
"go_to_search": "Go to search",
"go_to_settings": "Go to settings",
"gps": "GPS",
"gps_missing": "No GPS",
"grant_permission": "Grant permission",
@@ -1613,7 +1623,6 @@
"not_available": "N/A",
"not_in_any_album": "Not in any album",
"not_selected": "Not selected",
"note_apply_storage_label_to_previously_uploaded assets": "Note: To apply the Storage Label to previously uploaded assets, run the",
"notes": "Notes",
"nothing_here_yet": "Nothing here yet",
"notification_permission_dialog_content": "To enable notifications, go to Settings and select allow.",
@@ -1643,6 +1652,7 @@
"online": "Online",
"only_favorites": "Only favorites",
"open": "Open",
"open_calendar": "Open calendar",
"open_in_map_view": "Open in map view",
"open_in_openstreetmap": "Open in OpenStreetMap",
"open_the_search_filters": "Open the search filters",
@@ -1802,9 +1812,8 @@
"rate_asset": "Rate Asset",
"rating": "Star rating",
"rating_clear": "Clear rating",
"rating_count": "{count, plural, one {# star} other {# stars}}",
"rating_count": "{count, plural, =0 {Unrated} one {# star} other {# stars}}",
"rating_description": "Display the EXIF rating in the info panel",
"rating_set": "Rating set to {rating, plural, one {# star} other {# stars}}",
"reaction_options": "Reaction options",
"read_changelog": "Read Changelog",
"readonly_mode_disabled": "Read-only mode disabled",
@@ -1815,7 +1824,7 @@
"reassigned_assets_to_new_person": "Re-assigned {count, plural, one {# asset} other {# assets}} to a new person",
"reassing_hint": "Assign selected assets to an existing person",
"recent": "Recent",
"recent-albums": "Recent albums",
"recent_albums": "Recent albums",
"recent_searches": "Recent searches",
"recently_added": "Recently added",
"recently_added_page_title": "Recently Added",
@@ -1939,6 +1948,7 @@
"search_filter_ocr": "Search by OCR",
"search_filter_people_title": "Select people",
"search_filter_star_rating": "Star Rating",
"search_filter_tags_title": "Select tags",
"search_for": "Search for",
"search_for_existing_person": "Search for existing person",
"search_no_more_result": "No more results",
@@ -2018,6 +2028,9 @@
"set_profile_picture": "Set profile picture",
"set_slideshow_to_fullscreen": "Set Slideshow to fullscreen",
"set_stack_primary_asset": "Set as primary asset",
"setting_image_navigation_enable_subtitle": "If enabled, you can navigate to the previous/next image by tapping the leftmost/rightmost quarter of the screen.",
"setting_image_navigation_enable_title": "Tap to Navigate",
"setting_image_navigation_title": "Image Navigation",
"setting_image_viewer_help": "The detail viewer loads the small thumbnail first, then loads the medium-size preview (if enabled), finally loads the original (if enabled).",
"setting_image_viewer_original_subtitle": "Enable to load the original full-resolution image (large!). Disable to reduce data usage (both network and on device cache).",
"setting_image_viewer_original_title": "Load original image",
@@ -2184,6 +2197,7 @@
"support": "Support",
"support_and_feedback": "Support & Feedback",
"support_third_party_description": "Your Immich installation was packaged by a third-party. Issues you experience may be caused by that package, so please raise issues with them in the first instance using the links below.",
"supporter": "Supporter",
"swap_merge_direction": "Swap merge direction",
"sync": "Sync",
"sync_albums": "Sync albums",
@@ -2295,6 +2309,7 @@
"unstack_action_prompt": "{count} unstacked",
"unstacked_assets_count": "Un-stacked {count, plural, one {# asset} other {# assets}}",
"unsupported_field_type": "Unsupported field type",
"unsupported_file_type": "File {file} can't be uploaded because its file type {type} is not supported.",
"untagged": "Untagged",
"untitled_workflow": "Untitled workflow",
"up_next": "Up next",

View File

@@ -311,7 +311,7 @@
"search_jobs": "Buscar trabajos…",
"send_welcome_email": "Enviar correo de bienvenida",
"server_external_domain_settings": "Dominio externo",
"server_external_domain_settings_description": "Dominio para enlaces públicos compartidos, incluidos http(s)://",
"server_external_domain_settings_description": "Dominio usado para enlaces externos",
"server_public_users": "Usuarios públicos",
"server_public_users_description": "Cuando se añade un usuario a los álbumes compartidos, todos los usuarios aparecen en una lista con su nombre y su correo electrónico. Si deshabilita esta opción, solo los administradores podrán ver la lista de usuarios.",
"server_settings": "Configuración del servidor",
@@ -794,6 +794,11 @@
"color": "Color",
"color_theme": "Color del tema",
"command": "Comando",
"command_palette_prompt": "Encuentra rápidamente páginas, acciones o comandos",
"command_palette_to_close": "para cerrar",
"command_palette_to_navigate": "para entrar",
"command_palette_to_select": "para seleccionar",
"command_palette_to_show_all": "para mostrar todo",
"comment_deleted": "Comentario borrado",
"comment_options": "Opciones de comentarios",
"comments_and_likes": "Comentarios y me gusta",
@@ -1168,6 +1173,7 @@
"exif_bottom_sheet_people": "PERSONAS",
"exif_bottom_sheet_person_add_person": "Añadir nombre",
"exit_slideshow": "Salir de la presentación",
"expand": "Expandir",
"expand_all": "Expandir todo",
"experimental_settings_new_asset_list_subtitle": "Trabajo en progreso",
"experimental_settings_new_asset_list_title": "Habilitar cuadrícula fotográfica experimental",
@@ -1613,7 +1619,6 @@
"not_available": "N/D",
"not_in_any_album": "Sin álbum",
"not_selected": "No seleccionado",
"note_apply_storage_label_to_previously_uploaded assets": "Nota: Para aplicar la etiqueta de almacenamiento a los recursos que ya se subieron, ejecute la",
"notes": "Notas",
"nothing_here_yet": "Sin nada aún",
"notification_permission_dialog_content": "Para activar las notificaciones, ve a Configuración y selecciona permitir.",
@@ -1643,6 +1648,7 @@
"online": "En línea",
"only_favorites": "Solo favoritos",
"open": "Abierto",
"open_calendar": "Abrir calendario",
"open_in_map_view": "Abrir en la vista del mapa",
"open_in_openstreetmap": "Abrir en OpenStreetMap",
"open_the_search_filters": "Abre los filtros de búsqueda",
@@ -1765,7 +1771,7 @@
"profile_picture_set": "Conjunto de imágenes de perfil.",
"public_album": "Álbum público",
"public_share": "Compartir públicamente",
"purchase_account_info": "Seguidor",
"purchase_account_info": "Colaborador",
"purchase_activated_subtitle": "Gracias por apoyar a Immich y al software de código abierto",
"purchase_activated_time": "Activado el {date}",
"purchase_activated_title": "Su clave ha sido activada correctamente",
@@ -1778,7 +1784,7 @@
"purchase_button_select": "Seleccionar",
"purchase_failed_activation": "¡Error al activar! ¡Por favor, revisa tu correo electrónico para obtener la clave del producto correcta!",
"purchase_individual_description_1": "Para un usuario",
"purchase_individual_description_2": "Estado de soporte",
"purchase_individual_description_2": "Estatus de colaborador",
"purchase_individual_title": "Individual",
"purchase_input_suggestion": "¿Tiene una clave de producto? Introdúzcala a continuación",
"purchase_license_subtitle": "Compre Immich para apoyar el desarrollo continuo del servicio",
@@ -1794,7 +1800,7 @@
"purchase_remove_server_product_key": "Eliminar la clave de producto del servidor",
"purchase_remove_server_product_key_prompt": "¿Está seguro de que desea eliminar la clave de producto del servidor?",
"purchase_server_description_1": "Para todo el servidor",
"purchase_server_description_2": "Estado del soporte",
"purchase_server_description_2": "Estatus de colaborador",
"purchase_server_title": "Servidor",
"purchase_settings_server_activated": "La clave del producto del servidor la administra el administrador",
"query_asset_id": "Consultar ID de recurso",
@@ -1815,7 +1821,7 @@
"reassigned_assets_to_new_person": "Reasignado {count, plural, one {# recurso} other {# recursos}} a un nuevo usuario",
"reassing_hint": "Asignar recursos seleccionados a una persona existente",
"recent": "Reciente",
"recent-albums": "Últimos álbumes",
"recent_albums": "Últimos álbumes",
"recent_searches": "Búsquedas recientes",
"recently_added": "Añadidos recientemente",
"recently_added_page_title": "Recién añadidos",
@@ -2184,6 +2190,7 @@
"support": "Soporte",
"support_and_feedback": "Soporte y comentarios",
"support_third_party_description": "Esta instalación de Immich fue empaquetada por un tercero. Los problemas actuales pueden ser ocasionados por ese paquete; por favor, discuta sus inconvenientes con el empaquetador antes de usar los enlaces de abajo.",
"supporter": "Colaborador",
"swap_merge_direction": "Alternar dirección de mezcla",
"sync": "Sincronizar",
"sync_albums": "Sincronizar álbumes",

View File

@@ -311,7 +311,7 @@
"search_jobs": "Otsi töödet…",
"send_welcome_email": "Saada tervituskiri",
"server_external_domain_settings": "Väline domeen",
"server_external_domain_settings_description": "Domeen avalikult jagatud linkide jaoks, k.a. http(s)://",
"server_external_domain_settings_description": "Domeen väliste linkide jaoks",
"server_public_users": "Avalikud kasutajad",
"server_public_users_description": "Kasutaja jagatud albumisse lisamisel kuvatakse kõiki kasutajaid (nime ja e-posti aadressiga). Kui keelatud, kuvatakse kasutajate nimekirja ainult administraatoritele.",
"server_settings": "Serveri seaded",
@@ -794,6 +794,11 @@
"color": "Värv",
"color_theme": "Värviteema",
"command": "Käsk",
"command_palette_prompt": "Leia kiirelt lehti, tegevusi või käske",
"command_palette_to_close": "sulge",
"command_palette_to_navigate": "sisene",
"command_palette_to_select": "vali",
"command_palette_to_show_all": "näita kõiki",
"comment_deleted": "Kommentaar kustutatud",
"comment_options": "Kommentaari valikud",
"comments_and_likes": "Kommentaarid ja meeldimised",
@@ -1168,6 +1173,7 @@
"exif_bottom_sheet_people": "ISIKUD",
"exif_bottom_sheet_person_add_person": "Lisa nimi",
"exit_slideshow": "Sulge slaidiesitlus",
"expand": "Laienda",
"expand_all": "Näita kõik",
"experimental_settings_new_asset_list_subtitle": "Töös",
"experimental_settings_new_asset_list_title": "Luba eksperimentaalne fotoruudistik",
@@ -1613,7 +1619,6 @@
"not_available": "Pole saadaval",
"not_in_any_album": "Pole üheski albumis",
"not_selected": "Ei ole valitud",
"note_apply_storage_label_to_previously_uploaded assets": "Märkus: Et rakendada talletussilt varem üleslaaditud üksustele, käivita",
"notes": "Märkused",
"nothing_here_yet": "Siin pole veel midagi",
"notification_permission_dialog_content": "Teavituste lubamiseks mine Seadetesse ja vali lubamine.",
@@ -1643,6 +1648,7 @@
"online": "Ühendatud",
"only_favorites": "Ainult lemmikud",
"open": "Ava",
"open_calendar": "Ava kalender",
"open_in_map_view": "Ava kaardi vaates",
"open_in_openstreetmap": "Ava OpenStreetMap",
"open_the_search_filters": "Ava otsingufiltrid",
@@ -1815,7 +1821,7 @@
"reassigned_assets_to_new_person": "{count, plural, one {# üksus} other {# üksust}} seostatud uue isikuga",
"reassing_hint": "Seosta valitud üksused olemasoleva isikuga",
"recent": "Hiljutine",
"recent-albums": "Hiljutised albumid",
"recent_albums": "Hiljutised albumid",
"recent_searches": "Hiljutised otsingud",
"recently_added": "Hiljuti lisatud",
"recently_added_page_title": "Hiljuti lisatud",
@@ -2184,6 +2190,7 @@
"support": "Tugi",
"support_and_feedback": "Tugi ja tagasiside",
"support_third_party_description": "Sinu Immich'i install on kolmanda osapoole pakendatud. Probleemid, mida täheldad, võivad olla põhjustatud selle pakendamise poolt, seega võta esmajärjekorras nendega ühendust, kasutades allolevaid linke.",
"supporter": "Toetaja",
"swap_merge_direction": "Muuda ühendamise suunda",
"sync": "Sünkrooni",
"sync_albums": "Sünkrooni albumid",

View File

@@ -1568,7 +1568,6 @@
"not_available": "N/A",
"not_in_any_album": "Ei yhdessäkään albumissa",
"not_selected": "Ei valittu",
"note_apply_storage_label_to_previously_uploaded assets": "Huom: Jotta voit soveltaa tallennustunnistetta aiemmin ladattuihin kohteisiin, suorita",
"notes": "Muistiinpanot",
"nothing_here_yet": "Ei vielä mitään",
"notification_permission_dialog_content": "Ottaaksesi ilmoitukset käyttöön, siirry asetuksiin ja valitse 'salli'.",
@@ -1767,7 +1766,7 @@
"reassigned_assets_to_new_person": "Määritetty {count, plural, one {# media} other {# mediaa}} uudelle henkilölle",
"reassing_hint": "Määritä valitut mediat käyttäjälle",
"recent": "Viimeisin",
"recent-albums": "Viimeisimmät albumit",
"recent_albums": "Viimeisimmät albumit",
"recent_searches": "Edelliset haut",
"recently_added": "Viimeksi lisätty",
"recently_added_page_title": "Viimeksi lisätyt",

View File

@@ -311,7 +311,7 @@
"search_jobs": "Recherche des tâches…",
"send_welcome_email": "Envoyer un courriel de bienvenue",
"server_external_domain_settings": "Domaine externe",
"server_external_domain_settings_description": "Nom de domaine pour les liens partagés publics, y compris http(s)://",
"server_external_domain_settings_description": "Nom de domaine utilisé pour les liens externes",
"server_public_users": "Utilisateurs publics",
"server_public_users_description": "Tous les utilisateurs (nom et courriel) sont listés lors de l'ajout d'un utilisateur à des albums partagés. Quand cela est désactivé, la liste des utilisateurs est uniquement disponible pour les comptes administrateurs.",
"server_settings": "Paramètres du serveur",
@@ -794,6 +794,11 @@
"color": "Couleur",
"color_theme": "Thème de couleur",
"command": "Commande",
"command_palette_prompt": "Trouver rapidement des pages, actions ou commandes",
"command_palette_to_close": "pour fermer",
"command_palette_to_navigate": "pour entrer",
"command_palette_to_select": "pour sélectionner",
"command_palette_to_show_all": "pour tout afficher",
"comment_deleted": "Commentaire supprimé",
"comment_options": "Options des commentaires",
"comments_and_likes": "Commentaires et \"J'aime\"",
@@ -1168,6 +1173,7 @@
"exif_bottom_sheet_people": "PERSONNES",
"exif_bottom_sheet_person_add_person": "Ajouter un nom",
"exit_slideshow": "Quitter le diaporama",
"expand": "Développer",
"expand_all": "Tout développer",
"experimental_settings_new_asset_list_subtitle": "En cours de développement",
"experimental_settings_new_asset_list_title": "Activer la grille de photos expérimentale",
@@ -1613,7 +1619,6 @@
"not_available": "N/A",
"not_in_any_album": "Dans aucun album",
"not_selected": "Non sélectionné",
"note_apply_storage_label_to_previously_uploaded assets": "Note : Pour appliquer l'étiquette de stockage aux médias précédemment envoyés, exécutez",
"notes": "Notes",
"nothing_here_yet": "Rien pour le moment",
"notification_permission_dialog_content": "Pour activer les notifications, allez dans Paramètres et sélectionnez Autoriser.",
@@ -1643,6 +1648,7 @@
"online": "En ligne",
"only_favorites": "Uniquement les favoris",
"open": "Ouvrir",
"open_calendar": "Ouvrir le calendrier",
"open_in_map_view": "Montrer sur la carte",
"open_in_openstreetmap": "Ouvrir dans OpenStreetMap",
"open_the_search_filters": "Ouvrir les filtres de recherche",
@@ -1815,7 +1821,7 @@
"reassigned_assets_to_new_person": "{count, plural, one {# média réattribué} other {# médias réattribués}} à une nouvelle personne",
"reassing_hint": "Attribuer ces médias à une personne existante",
"recent": "Récent",
"recent-albums": "Albums récents",
"recent_albums": "Albums récents",
"recent_searches": "Recherches récentes",
"recently_added": "Récemment ajouté",
"recently_added_page_title": "Récemment ajouté",
@@ -2184,6 +2190,7 @@
"support": "Soutenir",
"support_and_feedback": "Support & Retours",
"support_third_party_description": "Votre installation d'Immich est packagée via une application tierce. Si vous rencontrez des anomalies, elles peuvent venir de ce packaging tiers, merci de créer les anomalies avec ces tiers en premier lieu en utilisant les liens ci-dessous.",
"supporter": "Contributeur",
"swap_merge_direction": "Inverser la direction de fusion",
"sync": "Synchroniser",
"sync_albums": "Synchroniser dans des albums",

View File

@@ -311,7 +311,7 @@
"search_jobs": "Cuardaigh poist…",
"send_welcome_email": "Seol ríomhphost fáilte",
"server_external_domain_settings": "Fearann seachtrach",
"server_external_domain_settings_description": "Fearann le haghaidh naisc chomhroinnte poiblí, lena n-áirítear http(s)://",
"server_external_domain_settings_description": "Fearann a úsáidtear le haghaidh naisc sheachtracha",
"server_public_users": "Úsáideoirí Poiblí",
"server_public_users_description": "Liostaítear gach úsáideoir (ainm agus ríomhphost) nuair a chuirtear úsáideoir le halbaim chomhroinnte. Nuair a bhíonn sé díchumasaithe, ní bheidh an liosta úsáideoirí ar fáil ach dúsáideoirí riarthóra.",
"server_settings": "Socruithe Freastalaí",
@@ -794,6 +794,11 @@
"color": "Dath",
"color_theme": "Téama datha",
"command": "Ordú",
"command_palette_prompt": "Aimsigh leathanaigh, gníomhartha nó orduithe go tapa",
"command_palette_to_close": "a dhúnadh",
"command_palette_to_navigate": "dul isteach",
"command_palette_to_select": "a roghnú",
"command_palette_to_show_all": "chun gach rud a thaispeáint",
"comment_deleted": "Trácht scriosta",
"comment_options": "Roghanna tráchta",
"comments_and_likes": "Tráchtanna & Is maith liom",
@@ -1168,6 +1173,7 @@
"exif_bottom_sheet_people": "DAOINE",
"exif_bottom_sheet_person_add_person": "Cuir ainm leis",
"exit_slideshow": "Scoir an Taispeántais Sleamhnán",
"expand": "Leathnaigh",
"expand_all": "Leathnaigh gach rud",
"experimental_settings_new_asset_list_subtitle": "Obair ar siúl",
"experimental_settings_new_asset_list_title": "Cumasaigh eangach grianghraf turgnamhach",
@@ -1613,7 +1619,6 @@
"not_available": "N/B",
"not_in_any_album": "Ní in aon albam",
"not_selected": "Níor roghnaíodh",
"note_apply_storage_label_to_previously_uploaded assets": "Nóta: Chun an Lipéad Stórála a chur i bhfeidhm ar shócmhainní a uaslódáileadh roimhe seo, rith an",
"notes": "Nótaí",
"nothing_here_yet": "Níl aon rud anseo fós",
"notification_permission_dialog_content": "Chun fógraí a chumasú, téigh go Socruithe agus roghnaigh ceadaigh.",
@@ -1643,6 +1648,7 @@
"online": "Ar líne",
"only_favorites": "Is fearr leat amháin",
"open": "Oscail",
"open_calendar": "Oscail an féilire",
"open_in_map_view": "Oscail i radharc léarscáile",
"open_in_openstreetmap": "Oscail in OpenStreetMap",
"open_the_search_filters": "Oscail na scagairí cuardaigh",
@@ -1815,7 +1821,7 @@
"reassigned_assets_to_new_person": "Athshannadh {count, plural, one {# sócmhainn} other {# sócmhainní}} do dhuine nua",
"reassing_hint": "Sannadh sócmhainní roghnaithe do dhuine atá ann cheana féin",
"recent": "Le déanaí",
"recent-albums": "Albaim le déanaí",
"recent_albums": "Albaim le déanaí",
"recent_searches": "Cuardaigh le déanaí",
"recently_added": "Cuireadh leis le déanaí",
"recently_added_page_title": "Curtha leis le Déanaí",
@@ -2184,6 +2190,7 @@
"support": "Tacaíocht",
"support_and_feedback": "Tacaíocht & Aiseolas",
"support_third_party_description": "Rinne tríú páirtí pacáiste de do shuiteáil Immich. Dfhéadfadh sé gur an pacáiste sin ba chúis le fadhbanna a bhíonn agat, mar sin tabhair ceisteanna dóibh ar dtús trí na naisc thíos a úsáid.",
"supporter": "Tacaíochtaí",
"swap_merge_direction": "Malartaigh treo an chumaisc",
"sync": "Sioncrónaigh",
"sync_albums": "Sioncrónaigh albaim",

View File

@@ -1613,7 +1613,6 @@
"not_available": "Non dispoñible",
"not_in_any_album": "Non está en ningún álbum",
"not_selected": "Non seleccionado",
"note_apply_storage_label_to_previously_uploaded assets": "Nota: Para aplicar a Etiqueta de Almacenamento a activos cargados previamente, execute o",
"notes": "Notas",
"nothing_here_yet": "Aínda nada por aquí",
"notification_permission_dialog_content": "Para activar as notificacións, vaia a Axustes e seleccione permitir.",
@@ -1815,7 +1814,7 @@
"reassigned_assets_to_new_person": "Reasignados {count, plural, one {# activo} other {# activos}} a unha nova persoa",
"reassing_hint": "Asignar activos seleccionados a unha persoa existente",
"recent": "Recente",
"recent-albums": "Álbums recentes",
"recent_albums": "Álbums recentes",
"recent_searches": "Buscas recentes",
"recently_added": "Engadido recentemente",
"recently_added_page_title": "Engadido Recentemente",

View File

@@ -1491,7 +1491,6 @@
"not_available": "N/A",
"not_in_any_album": "I keinem Album",
"not_selected": "Nöd usgwählt",
"note_apply_storage_label_to_previously_uploaded assets": "Hiwiis: Zum e Spycherpfad-Bezeichnig aawehde, start de",
"notes": "Notize",
"nothing_here_yet": "No nüt do",
"notification_permission_dialog_content": "Zum Benachrichtige aktiviere, navigier zu Iistellige und drück \"Erlaube\".",

View File

@@ -1491,7 +1491,6 @@
"not_available": "לא רלוונטי",
"not_in_any_album": "לא בשום אלבום",
"not_selected": "לא נבחרו",
"note_apply_storage_label_to_previously_uploaded assets": "הערה: כדי להחיל את תווית האחסון על תמונות שהועלו בעבר, הפעל את",
"notes": "הערות",
"nothing_here_yet": "אין כאן כלום עדיין",
"notification_permission_dialog_content": "כדי לאפשר התראות, לך להגדרות המכשיר ובחר אפשר.",
@@ -1687,7 +1686,7 @@
"reassigned_assets_to_new_person": "{count, plural, one {תמונה # הוקצתה} other {# תמונות הוקצו}} מחדש לאדם חדש",
"reassing_hint": "הקצאת תמונות שנבחרו לאדם קיים",
"recent": "חדש",
"recent-albums": "אלבומים אחרונים",
"recent_albums": "אלבומים אחרונים",
"recent_searches": "חיפושים אחרונים",
"recently_added": "נוסף לאחרונה",
"recently_added_page_title": "נוסף לאחרונה",

View File

@@ -56,7 +56,7 @@
"authentication_settings_reenable": "पुनः सक्षम करने के लिए, <link>Server Command</link> का प्रयोग करे।",
"background_task_job": "पृष्ठभूमि कार्य",
"backup_database": "डेटाबेस डंप बनाएं",
"backup_database_enable_description": "Enable database dumps",
"backup_database_enable_description": "डेटाबेस डंप चालू करें",
"backup_keep_last_amount": "रखने के लिए पिछले डंप की मात्रा",
"backup_onboarding_1_description": "क्लाउड में या किसी अन्य भौतिक स्थान पर ऑफसाइट प्रतिलिपि।",
"backup_onboarding_2_description": "विभिन्न उपकरणों पर स्थानीय प्रतियाँ। इसमें मुख्य फ़ाइलें और उन फ़ाइलों का स्थानीय बैकअप शामिल है।",
@@ -104,6 +104,8 @@
"image_preview_description": "मेटाडेटा रहित मध्यम आकार की छवि, जिसका उपयोग एकल संपत्ति देखने और मशीन लर्निंग के लिए होता है",
"image_preview_quality_description": "पूर्वावलोकन की गुणवत्ता (1 से 100 तक)। अधिक मान बेहतर गुणवत्ता देता है, लेकिन इससे फ़ाइल का आकार बढ़ता है और ऐप की प्रतिक्रिया क्षमता कम हो सकती है। बहुत कम मान मशीन लर्निंग की गुणवत्ता को प्रभावित कर सकता है।",
"image_preview_title": "पूर्वदर्शन सेटिंग्स",
"image_progressive": "प्रगतिशील",
"image_progressive_description": "JPEG छवियों को क्रमिक रूप से लोड करने के लिए उन्हें प्रोग्रेसिवली एनकोड करें। इसका WebP छवियों पर कोई प्रभाव नहीं पड़ता है।",
"image_quality": "गुणवत्ता",
"image_resolution": "रिज़ॉल्यूशन",
"image_resolution_description": "उच्चतर रिज़ॉल्यूशन अधिक विवरण सुरक्षित रख सकता है, लेकिन एन्कोड करने में अधिक समय लेता है, फ़ाइल आकार बड़ा होता है और ऐप की प्रतिक्रियाशीलता कम हो सकती है।",
@@ -188,11 +190,23 @@
"machine_learning_smart_search_enabled": "स्मार्ट खोज सक्षम करें",
"machine_learning_smart_search_enabled_description": "यदि अक्षम किया गया है, तो स्मार्ट खोज के लिए छवियों को एन्कोड नहीं किया जाएगा।",
"machine_learning_url_description": "मशीन लर्निंग सर्वर का URL। यदि एक से अधिक URL दिए गए हैं, तो प्रत्येक सर्वर को एक-एक करके कोशिश किया जाएगा, पहले से आखिरी तक, जब तक कोई सफलतापूर्वक प्रतिक्रिया न दे। जो सर्वर प्रतिक्रिया नहीं देते, उन्हें अस्थायी रूप से नजरअंदाज किया जाएगा जब तक वे फिर से ऑनलाइन न हों।",
"maintenance_delete_backup": "बैकअप डिलीट करें",
"maintenance_delete_backup_description": "यह फ़ाइल स्थायी रूप से मिटा दी जाएगी। इसे वापस नहीं लाया जा सकेगा।",
"maintenance_delete_error": "बैकअप मिटाया नहीं जा सका।",
"maintenance_restore_backup": "बैकअप वापस लाएँ",
"maintenance_restore_backup_description": "Immich का सारा डेटा पूरी तरह मिटा दिया जाएगा और चुने गए बैकअप से डेटा वापस लाया जाएगा। आगे बढ़ने से पहले एक नया बैकअप बनाया जाएगा।",
"maintenance_restore_backup_different_version": "यह बैकअप Immich के किसी अलग version में बनाया गया था!",
"maintenance_restore_backup_unknown_version": "बैकअप का version निर्धारित नहीं किया जा सका।",
"maintenance_restore_database_backup": "डेटाबेस बैकअप वापस लाएँ",
"maintenance_restore_database_backup_description": "बैकअप फ़ाइल का उपयोग करके डेटाबेस को पहले की स्थिति में वापस लाएँ",
"maintenance_settings": "रखरखाव",
"maintenance_settings_description": "Immich को मेंटेनेंस मोड में रखें।",
"maintenance_start": "रखरखाव मोड शुरू करें",
"maintenance_start": "रखरखाव मोड पर स्विच करें",
"maintenance_start_error": "मेंटेनेंस मोड शुरू नहीं हो सका।",
"maintenance_upload_backup": "डेटाबेस की बैकअप फ़ाइल अपलोड करें",
"maintenance_upload_backup_error": "बैकअप अपलोड नहीं किया जा सका। क्या यह .sql या .sql.gz फ़ाइल है?",
"manage_concurrency": "समवर्तीता प्रबंधित करें",
"manage_concurrency_description": "एक साथ चलने वाले जॉब्स का प्रबंधन करने के लिए जॉब्स पेज पर जाएँ",
"manage_log_settings": "लॉग सेटिंग प्रबंधित करें",
"map_dark_style": "डार्क शैली",
"map_enable_description": "मानचित्र सुविधाएँ सक्षम करें",
@@ -258,7 +272,7 @@
"oauth_auto_register": "ऑटो रजिस्टर",
"oauth_auto_register_description": "OAuth के साथ साइन इन करने के बाद स्वचालित रूप से नए उपयोगकर्ताओं को पंजीकृत करें",
"oauth_button_text": "टेक्स्ट बटन",
"oauth_client_secret_description": "यदि PKCE (कोड एक्सचेंज के लिए प्रूफ़ कुंजी) OAuth प्रदाता द्वारा समर्थित नहीं है तो यह आवश्यक है",
"oauth_client_secret_description": "यह Confidential (गोपनीय) क्लाइंट के लिए आवश्यक है, या यदि Public क्लाइंट में PKCE (Proof Key for Code Exchange) समर्थित नहीं है।",
"oauth_enable_description": "OAuth से लॉगिन करें",
"oauth_mobile_redirect_uri": "मोबाइल रीडायरेक्ट यूआरआई",
"oauth_mobile_redirect_uri_override": "मोबाइल रीडायरेक्ट यूआरआई ओवरराइड",
@@ -282,10 +296,14 @@
"password_settings_description": "पासवर्ड लॉगिन सेटिंग प्रबंधित करें",
"paths_validated_successfully": "सभी पथ सफलतापूर्वक मान्य किए गए",
"person_cleanup_job": "व्यक्ति सफ़ाई",
"queue_details": "प्रक्रिया कतार का विवरण",
"queues": "कार्य कतार",
"queues_page_description": "प्रशासक कार्य कतार पेज",
"quota_size_gib": "कोटा आकार (GiB)",
"refreshing_all_libraries": "सभी पुस्तकालयों को ताज़ा किया जा रहा है",
"registration": "व्यवस्थापक पंजीकरण",
"registration": "प्रशासक पंजीकरण",
"registration_description": "चूंकि आप सिस्टम पर पहले उपयोगकर्ता हैं, इसलिए आपको व्यवस्थापक के रूप में नियुक्त किया जाएगा और आप प्रशासनिक कार्यों के लिए जिम्मेदार होंगे, और अतिरिक्त उपयोगकर्ता आपके द्वारा बनाए जाएंगे।",
"remove_failed_jobs": "असफल कार्य हटाएँ",
"require_password_change_on_login": "उपयोगकर्ता को पहले लॉगिन पर पासवर्ड बदलने की आवश्यकता है",
"reset_settings_to_default": "सेटिंग्स को डिफ़ॉल्ट पर रीसेट करें",
"reset_settings_to_recent_saved": "सेटिंग्स को हाल ही में सहेजी गई सेटिंग्स पर रीसेट करें",
@@ -298,8 +316,10 @@
"server_public_users_description": "साझा एल्बम में उपयोगकर्ता जोड़ते समय सभी उपयोगकर्ताओं (नाम और ईमेल) की सूची दिखाई जाती है। यदि यह विकल्प अक्षम किया गया है, तो उपयोगकर्ता सूची केवल व्यवस्थापक (एडमिन) उपयोगकर्ताओं के लिए उपलब्ध होगी।",
"server_settings": "सर्वर सेटिंग्स",
"server_settings_description": "सर्वर सेटिंग्स प्रबंधित करें",
"server_stats_page_description": "प्रशासक (Admin) सर्वर आँकड़े पेज",
"server_welcome_message": "स्वागत संदेश",
"server_welcome_message_description": "एक संदेश जो लॉगिन पृष्ठ पर प्रदर्शित होता है।",
"settings_page_description": "प्रशासक (Admin) सेटिंग्स पेज",
"sidecar_job": "साइडकार मेटाडेटा",
"sidecar_job_description": "फ़ाइल सिस्टम से साइडकार मेटाडेटा खोजें या सिंक्रनाइज़ करें",
"slideshow_duration_description": "प्रत्येक छवि को प्रदर्शित करने के लिए सेकंड की संख्या",
@@ -418,6 +438,8 @@
"user_restore_scheduled_removal": "उपयोगकर्ता को पुनर्स्थापित करें - {date, date, long} पर हटाया जाना निर्धारित है",
"user_settings": "उपयोगकर्ता सेटिंग",
"user_settings_description": "उपयोगकर्ता सेटिंग प्रबंधित करें",
"user_successfully_removed": "उपयोगकर्ता {email} को सफलतापूर्वक हटा दिया गया है।",
"users_page_description": "प्रशासक (Admin) उपयोगकर्ता पेज",
"version_check_enabled_description": "नई रिलीज़ की जाँच के लिए GitHub पर आवधिक अनुरोध सक्षम करें",
"version_check_implications": "संस्करण जाँच सुविधा github.com के साथ आवधिक संचार पर निर्भर करती है",
"version_check_settings": "संस्करण चेक",
@@ -429,6 +451,9 @@
"admin_password": "व्यवस्थापक पासवर्ड",
"administration": "प्रशासन",
"advanced": "विकसित",
"advanced_settings_clear_image_cache": "इमेज कैश (cache) साफ़ करें",
"advanced_settings_clear_image_cache_error": "इमेज कैश (cache) साफ़ नहीं किया जा सका",
"advanced_settings_clear_image_cache_success": "{size} सफलतापूर्वक साफ़ किया गया",
"advanced_settings_enable_alternate_media_filter_subtitle": "सिंक के दौरान वैकल्पिक मानदंडों के आधार पर मीडिया को फ़िल्टर करने के लिए इस विकल्प का उपयोग करें। इसे केवल तभी आज़माएँ जब आपको ऐप द्वारा सभी एल्बमों का पता लगाने में समस्या हो।",
"advanced_settings_enable_alternate_media_filter_title": "[प्रयोगात्मक] वैकल्पिक डिवाइस एल्बम सिंक फ़िल्टर का उपयोग करें",
"advanced_settings_log_level_title": "लॉग स्तर:{level}",
@@ -465,10 +490,12 @@
"album_remove_user": "उपयोगकर्ता हटाएं?",
"album_remove_user_confirmation": "क्या आप वाकई {user} को हटाना चाहते हैं?",
"album_search_not_found": "आपकी खोज से मेल खाता कोई एल्बम नहीं मिला",
"album_selected": "एल्बम चुना गया",
"album_share_no_users": "ऐसा लगता है कि आपने यह एल्बम सभी उपयोगकर्ताओं के साथ साझा कर दिया है या आपके पास साझा करने के लिए कोई उपयोगकर्ता नहीं है।",
"album_summary": "एल्बम सारांश",
"album_updated": "एल्बम अपडेट किया गया",
"album_updated_setting_description": "जब किसी साझा एल्बम में नई संपत्तियाँ हों तो एक ईमेल सूचना प्राप्त करें",
"album_upload_assets": "अपने कंप्यूटर से मीडिया फ़ाइलें अपलोड करें और उन्हें एल्बम में जोड़ें",
"album_user_left": "बायाँ {album}",
"album_user_removed": "{user} को हटाया गया",
"album_viewer_appbar_delete_confirm": "क्या आप वाकई इस एल्बम को अपने खाते से हटाना चाहते हैं?",
@@ -481,14 +508,16 @@
"album_viewer_page_share_add_users": "उपयोगकर्ता जोड़ें",
"album_with_link_access": "लिंक वाले किसी भी व्यक्ति को इस एल्बम में फ़ोटो और लोगों को देखने दें।",
"albums": "एलबम",
"albums_count": "{count, plural, one {{count, number} Album} other {{count, number} Albums}}",
"albums_count": "{count, plural, one {{count, number} एल्बम} other {{count, number} एल्बम}}",
"albums_default_sort_order": "डिफ़ॉल्ट एल्बम सॉर्ट क्रम",
"albums_default_sort_order_description": "नये एल्बम बनाते समय आरंभिक परिसंपत्ति सॉर्ट क्रम।",
"albums_feature_description": "परिसंपत्तियों का संग्रह जिसे अन्य उपयोगकर्ताओं के साथ साझा किया जा सकता है।",
"albums_on_device_count": "डिवाइस पर एल्बम ({count})",
"albums_selected": "{count, plural, one {# एल्बम चुना गया} other {# एल्बम चुने गए}}",
"all": "सभी",
"all_albums": "सभी एलबम",
"all_people": "सभी लोग",
"all_photos": "सभी फ़ोटो",
"all_videos": "सभी वीडियो",
"allow_dark_mode": "डार्क मोड की अनुमति दें",
"allow_edits": "संपादन की अनुमति दें",
@@ -496,6 +525,9 @@
"allow_public_user_to_upload": "सार्वजनिक उपयोगकर्ता को अपलोड करने की अनुमति दें",
"allowed": "अनुमत",
"alt_text_qr_code": "क्यूआर कोड छवि",
"always_keep": "हमेशा रखें",
"always_keep_photos_hint": "“फ्री अप स्पेस” का उपयोग करने पर इस डिवाइस की सभी फ़ोटो बनी रहेंगी।",
"always_keep_videos_hint": "“फ्री अप स्पेस” का उपयोग करने पर इस डिवाइस की सभी वीडियो बनी रहेंगी।",
"anti_clockwise": "वामावर्त",
"api_key": "एपीआई की",
"api_key_description": "यह की केवल एक बार दिखाई जाएगी। विंडो बंद करने से पहले कृपया इसे कॉपी करना सुनिश्चित करें।।",
@@ -522,10 +554,12 @@
"archived_count": "{count, plural, other {# संग्रहीत किए गए}}",
"are_these_the_same_person": "क्या ये वही व्यक्ति हैं?",
"are_you_sure_to_do_this": "क्या आप वास्तव में इसे करना चाहते हैं?",
"array_field_not_fully_supported": "Array फ़ील्ड के लिए JSON को मैन्युअल रूप से संपादित करना आवश्यक है",
"asset_action_delete_err_read_only": "केवल पढ़ने योग्य परिसंपत्ति(ओं) को हटाया नहीं जा सकता, छोड़ा जा सकता है",
"asset_action_share_err_offline": "ऑफ़लाइन परिसंपत्ति(एँ) प्राप्त नहीं की जा सकती, छोड़ी जा रही है",
"asset_added_to_album": "एल्बम में डाला गया",
"asset_adding_to_album": "एल्बम में डाला जा रहा है…",
"asset_created": "एसेट बनाया गया",
"asset_description_updated": "संपत्ति विवरण अद्यतन कर दिया गया है",
"asset_filename_is_offline": "एसेट {filename} ऑफ़लाइन है",
"asset_has_unassigned_faces": "एसेट में अनिर्धारित चेहरे हैं",
@@ -538,6 +572,9 @@
"asset_list_layout_sub_title": "लेआउट",
"asset_list_settings_subtitle": "फ़ोटो ग्रिड लेआउट सेटिंग्स",
"asset_list_settings_title": "चित्र की जाली",
"asset_not_found_on_device_android": "डिवाइस पर एसेट नहीं मिला",
"asset_not_found_on_device_ios": "डिवाइस पर एसेट नहीं मिला। यदि आप iCloud का उपयोग कर रहे हैं, तो iCloud में खराब फ़ाइल होने के कारण एसेट तक पहुँचा नहीं जा सकता",
"asset_not_found_on_icloud": "iCloud पर एसेट नहीं मिला। iCloud में खराब फ़ाइल होने के कारण एसेट तक पहुँचा नहीं जा सकता",
"asset_offline": "संपत्ति ऑफ़लाइन",
"asset_offline_description": "यह संपत्ति ऑफ़लाइन है।",
"asset_restored_successfully": "संपत्ति(याँ) सफलतापूर्वक पुनर्स्थापित की गईं",
@@ -589,7 +626,7 @@
"backup_album_selection_page_select_albums": "एल्बम चुनें",
"backup_album_selection_page_selection_info": "चयन जानकारी",
"backup_album_selection_page_total_assets": "कुल अद्वितीय संपत्तियाँ",
"backup_albums_sync": "बैकअप एल्बम का तुल्यकालन",
"backup_albums_sync": "बैकअप एल्बम का सिंक्रोनाइज़ेशन",
"backup_all": "सभी",
"backup_background_service_backup_failed_message": "संपत्तियों का बैकअप लेने में विफल. पुनः प्रयास किया जा रहा है…",
"backup_background_service_complete_notification": "एसेट का बैकअप पूरा हुआ",
@@ -650,6 +687,7 @@
"backup_options_page_title": "बैकअप विकल्प",
"backup_setting_subtitle": "पृष्ठभूमि और अग्रभूमि अपलोड सेटिंग प्रबंधित करें",
"backup_settings_subtitle": "अपलोड सेटिंग्स संभालें",
"backup_upload_details_page_more_details": "अधिक जानकारी के लिए टैप करें",
"backward": "पिछला",
"biometric_auth_enabled": "बायोमेट्रिक प्रमाणीकरण सक्षम",
"biometric_locked_out": "आप बायोमेट्रिक प्रमाणीकरण से बाहर हैं",
@@ -708,6 +746,8 @@
"change_password_form_password_mismatch": "सांकेतिक शब्द मेल नहीं खाते",
"change_password_form_reenter_new_password": "नया पासवर्ड पुनः दर्ज करें",
"change_pin_code": "पिन कोड बदलें",
"change_trigger": "ट्रिगर बदलें",
"change_trigger_prompt": "क्या आप वाकई ट्रिगर बदलना चाहते हैं? इससे सभी मौजूदा एक्शन और फ़िल्टर हटा दिए जाएँगे।",
"change_your_password": "अपना पासवर्ड बदलें",
"changed_visibility_successfully": "दृश्यता सफलतापूर्वक परिवर्तित",
"charging": "चार्जिंग",
@@ -716,8 +756,21 @@
"check_corrupt_asset_backup_button": "जाँच करें",
"check_corrupt_asset_backup_description": "यह जाँच केवल वाई-फ़ाई पर ही करें और सभी संपत्तियों का बैकअप लेने के बाद ही करें। इस प्रक्रिया में कुछ मिनट लग सकते हैं।",
"check_logs": "लॉग जांचें",
"checksum": "चेकसम (checksum)",
"choose_matching_people_to_merge": "मर्ज करने के लिए मिलते-जुलते लोगों को चुनें",
"city": "शहर",
"cleanup_confirm_description": "Immich ने {date} से पहले बनाए गए {count} एसेट सर्वर पर सुरक्षित रूप से बैकअप किए हुए पाए हैं। क्या इस डिवाइस से उनकी स्थानीय प्रतियाँ हटाई जाएँ?",
"cleanup_confirm_prompt_title": "क्या इस डिवाइस से हटाएँ?",
"cleanup_deleted_assets": "डिवाइस के ट्रैश में {count} एसेट भेज दिए गए",
"cleanup_deleting": "ट्रैश में भेजा जा रहा है…",
"cleanup_found_assets": "{count} बैकअप किए गए ऐसेट मिले",
"cleanup_found_assets_with_size": "{count} बैकअप किए गए ऐसेट मिले ({size})",
"cleanup_icloud_shared_albums_excluded": "iCloud के शेयर किए गए एल्बम स्कैन में शामिल नहीं हैं",
"cleanup_no_assets_found": "ऊपर दिए गए मानदंडों से मेल खाने वाले कोई ऐसेट नहीं मिले। ‘फ्री उप स्पेस’ केवल उन्हीं ऐसेट को हटा सकता है जिनका बैकअप सर्वर पर लिया गया है",
"cleanup_preview_title": "हटाए जाने वाले ऐसेट ({count})",
"cleanup_step3_description": "तिथि और सुरक्षित रखने की सेटिंग के अनुसार बैकअप ऐसेट स्कैन करें।",
"cleanup_step4_summary": "आपके स्थानीय डिवाइस से हटाने के लिए {date} से पहले बनाए गए {count} ऐसेट। फ़ोटो Immich ऐप में देखे जा सकेंगे।",
"cleanup_trash_hint": "स्टोरेज स्पेस पूरी तरह वापस पाने के लिए, सिस्टम गैलरी ऐप खोलें और ट्रैश खाली करें",
"clear": "स्पष्ट",
"clear_all": "सभी साफ करें",
"clear_all_recent_searches": "सभी हालिया खोजें साफ़ करें",
@@ -729,8 +782,10 @@
"client_cert_import": "आयात",
"client_cert_import_success_msg": "क्लाइंट प्रमाणपत्र आयात किया गया है",
"client_cert_invalid_msg": "अमान्य प्रमाणपत्र फ़ाइल या गलत पासवर्ड",
"client_cert_password_message": "इस प्रमाणपत्र के लिए पासवर्ड दर्ज करें",
"client_cert_password_title": "प्रमाणपत्र पासवर्ड",
"client_cert_remove_msg": "क्लाइंट प्रमाणपत्र हटा दिया गया है",
"client_cert_subtitle": "केवल PKCS12 (.p12, .pfx) प्रारूप का समर्थन करता है। प्रमाणपत्र आयात/निकालना केवल लॉगिन से पहले ही उपलब्ध है",
"client_cert_subtitle": "केवल PKCS12 (.p12, .pfx) प्रारूप का समर्थन करता है। प्रमाणपत्र आयात/निकालना केवल लॉगिन से पहले ही उपलब्ध है",
"client_cert_title": "SSL क्लाइंट प्रमाणपत्र [प्रायोगिक]",
"clockwise": "दक्षिणावर्त",
"close": "बंद करें",
@@ -738,6 +793,7 @@
"collapse_all": "सभी को संकुचित करें",
"color": "रंग",
"color_theme": "रंग थीम",
"command": "आदेश",
"comment_deleted": "टिप्पणी हटा दी गई",
"comment_options": "टिप्पणी विकल्प",
"comments_and_likes": "टिप्पणियाँ और पसंद",
@@ -782,6 +838,7 @@
"create_album": "एल्बम बनाओ",
"create_album_page_untitled": "शीर्षकहीन",
"create_api_key": "ऐ.पी.आई. चाभी बनाएं",
"create_first_workflow": "पहला वर्कफ़्लो बनाएं",
"create_library": "लाइब्रेरी बनाएं",
"create_link": "लिंक बनाएं",
"create_link_to_share": "शेयर करने के लिए लिंक बनाएं",
@@ -796,14 +853,18 @@
"create_tag": "टैग बनाएँ",
"create_tag_description": "एक नया टैग बनाएँ। नेस्टेड टैग के लिए, कृपया फ़ॉरवर्ड स्लैश सहित टैग का पूरा पथ दर्ज करें।",
"create_user": "उपयोगकर्ता बनाइये",
"create_workflow": "वर्कफ़्लो बनाएं",
"created": "बनाया",
"created_at": "बनाया था",
"creating_linked_albums": "जुड़े हुए एल्बम बनाए जा रहे हैं..।",
"crop": "छाँटें",
"crop_aspect_ratio_free": "स्वतंत्र",
"crop_aspect_ratio_original": "मूल अनुपात",
"curated_object_page_title": "चीज़ें",
"current_device": "वर्तमान उपकरण",
"current_pin_code": "वर्तमान पिन कोड",
"current_server_address": "वर्तमान सर्वर पता",
"custom_date": "मनचाही तिथि",
"custom_locale": "कस्टम लोकेल",
"custom_locale_description": "भाषा और क्षेत्र के आधार पर दिनांक और संख्याएँ प्रारूपित करें",
"custom_url": "कस्टम URL",
@@ -1178,7 +1239,7 @@
"home_page_delete_remote_err_local": "दूरस्थ चयन को हटाने, छोड़ने में स्थानीय संपत्तियाँ",
"home_page_favorite_err_local": "स्थानीय संपत्तियों को अभी तक पसंदीदा नहीं बनाया जा सका, छोड़ा जा रहा है",
"home_page_favorite_err_partner": "अब तक पार्टनर एसेट्स को फेवरेट नहीं कर सकते, स्किप कर रहे हैं",
"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_first_time_notice": "यदि आप पहली बार इस ऐप का उपयोग कर रहे हैं, तो कृपया एक बैकअप एल्बम चुनें, ताकि टाइमलाइन में फ़ोटो और वीडियो दिखाई दे सकें",
"home_page_locked_error_local": "स्थानीय संपत्तियों को लॉक किए गए फ़ोल्डर में नहीं ले जाया जा सकता, छोड़ा जा सकता है",
"home_page_locked_error_partner": "साझेदार संपत्तियों को लॉक किए गए फ़ोल्डर में नहीं ले जाया जा सकता, छोड़ें",
"home_page_share_err_local": "लोकल एसेट्स को लिंक के जरिए शेयर नहीं कर सकते, स्किप कर रहे हैं",
@@ -1447,7 +1508,7 @@
"no_albums_with_name_yet": "ऐसा लगता है कि आपके पास अभी तक इस नाम का कोई एल्बम नहीं है।",
"no_albums_yet": "ऐसा लगता है कि आपके पास अभी तक कोई एल्बम नहीं है।",
"no_archived_assets_message": "फ़ोटो और वीडियो को अपने फ़ोटो दृश्य से छिपाने के लिए उन्हें संग्रहीत करें",
"no_assets_message": "अपन पहल फोटो अपलोड करने के लिए क्लिक करें",
"no_assets_message": "अपन पहलोटो अपलोड करने के लिए क्लिक करें",
"no_assets_to_show": "दिखाने के लिए कोई संपत्ति नहीं",
"no_cast_devices_found": "कोई कास्ट डिवाइस नहीं मिला",
"no_checksum_local": "कोई चेकसम उपलब्ध नहीं है - स्थानीय संपत्तियां प्राप्त नहीं की जा सकतीं",
@@ -1474,7 +1535,6 @@
"not_available": "लागू नहीं",
"not_in_any_album": "किसी एलबम में नहीं",
"not_selected": "चयनित नहीं",
"note_apply_storage_label_to_previously_uploaded assets": "नोट: पहले अपलोड की गई संपत्तियों पर स्टोरेज लेबल लागू करने के लिए, चलाएँ",
"notes": "टिप्पणियाँ",
"nothing_here_yet": "यहाँ अभी तक कुछ नहीं",
"notification_permission_dialog_content": "सूचनाएं सक्षम करने के लिए सेटिंग्स में जाएं और अनुमति दें चुनें।",
@@ -1665,11 +1725,11 @@
"readonly_mode_enabled": "केवल-पढ़ने के लिए मोड सक्षम",
"ready_for_upload": "अपलोड के लिए तैयार",
"reassign": "पुनः असाइन",
"reassigned_assets_to_existing_person": "{count, plural, one {# asset} other {# assets}} को {name, select, null {an existing person} other {{name}}}को फिर से असाइन किया गया",
"reassigned_assets_to_existing_person": "{count, plural, one {# asset} other {# assets}} को {name, select, null {an existing person} other {{name}}}को फिर से असाइन किया गया",
"reassigned_assets_to_new_person": "{count, plural, one {# asset} other {# assets}} को एक नए व्यक्ति को फिर से असाइन किया गया",
"reassing_hint": "चयनित संपत्तियों को किसी मौजूदा व्यक्ति को सौंपें",
"recent": "हाल ही का",
"recent-albums": "हाल के एल्बम",
"recent_albums": "हाल के एल्बम",
"recent_searches": "हाल की खोजें",
"recently_added": "हाल ही में डाला गया",
"recently_added_page_title": "हाल ही में डाला गया",
@@ -1874,7 +1934,7 @@
"setting_notifications_notify_failures_grace_period": "बैकग्राउंड बैकअप फेलियर की सूचना दें: {duration}",
"setting_notifications_notify_hours": "{count} घंटे",
"setting_notifications_notify_immediately": "तुरंत",
"setting_notifications_notify_minutes": "{count} मिनट",
"setting_notifications_notify_minutes": "{count} मिनट",
"setting_notifications_notify_never": "कभी नहीं",
"setting_notifications_notify_seconds": "{count} सेकंड",
"setting_notifications_single_progress_subtitle": "हर एसेट के लिए अपलोड प्रोग्रेस की पूरी जानकारी",
@@ -1917,7 +1977,7 @@
"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_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 मिनट",
@@ -1926,8 +1986,8 @@
"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_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} घंटे में समाप्त हो जाएगा",
@@ -2052,11 +2112,11 @@
"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_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_subtitle": "प्राथमिक क्रियाओं और उच्चारणों के लिए एक रंग चुनें",
"theme_setting_primary_color_title": "प्राथमिक रंग",
"theme_setting_system_primary_color_title": "सिस्टम रंग का उपयोग करें",
"theme_setting_system_theme_switch": "ऑटोमैटिक (सिस्टम सेटिंग फ़ॉलो करें)",

View File

@@ -1459,7 +1459,6 @@
"not_available": "N/A",
"not_in_any_album": "Ni u jednom albumu",
"not_selected": "Nije odabrano",
"note_apply_storage_label_to_previously_uploaded assets": "Napomena: Da biste primijenili oznaku pohrane na prethodno prenesene stavke, pokrenite",
"notes": "Bilješke",
"nothing_here_yet": "Ovdje još nema ničega",
"notification_permission_dialog_content": "Da biste omogućili obavijesti, idite u Postavke i odaberite dopusti.",
@@ -1646,7 +1645,7 @@
"reassigned_assets_to_new_person": "{count, plural, one {# stavka ponovno dodijeljena} few {# stavke ponovno dodijeljene} other {# stavki ponovno dodijeljeno}} novoj osobi",
"reassing_hint": "Dodijelite odabrane stavke postojećoj osobi",
"recent": "Nedavno",
"recent-albums": "Nedavni albumi",
"recent_albums": "Nedavni albumi",
"recent_searches": "Nedavne pretrage",
"recently_added": "Nedavno dodano",
"recently_added_page_title": "Nedavno dodano",

View File

@@ -1604,7 +1604,6 @@
"not_available": "N/A",
"not_in_any_album": "Nincs albumban",
"not_selected": "Nincs kiválasztva",
"note_apply_storage_label_to_previously_uploaded assets": "Megjegyzés: a korábban feltöltött elemek tárhely címkézéséhez futtasd a(z)",
"notes": "Megjegyzések",
"nothing_here_yet": "Még semmi sincs itt",
"notification_permission_dialog_content": "Az értesítések bekapcsolásához a Beállítások menüben válaszd ki az Engedélyezés-t.",
@@ -1806,7 +1805,7 @@
"reassigned_assets_to_new_person": "{count, plural, other {# elem}} hozzárendelve egy új személyhez",
"reassing_hint": "Kijelölt elemek létező személyhez rendelése",
"recent": "Friss",
"recent-albums": "Legutóbbi albumok",
"recent_albums": "Legutóbbi albumok",
"recent_searches": "Legutóbbi keresések",
"recently_added": "Nemrég hozzáadott",
"recently_added_page_title": "Nemrég hozzáadott",

View File

@@ -1613,7 +1613,6 @@
"not_available": "T/T",
"not_in_any_album": "Tidak ada dalam album apa pun",
"not_selected": "Belum dipilih",
"note_apply_storage_label_to_previously_uploaded assets": "Catatan: Untuk menerapkan Label Penyimpanan pada aset yang sebelumnya telah diunggah, jalankan",
"notes": "Catatan",
"nothing_here_yet": "Masih kosong",
"notification_permission_dialog_content": "Untuk mengaktifkan notifikasi, buka Pengaturan lalu berikan izin.",
@@ -1815,7 +1814,7 @@
"reassigned_assets_to_new_person": "Menetapkan ulang {count, plural, one {# aset} other {# aset}} kepada orang baru",
"reassing_hint": "Tetapkan aset yang dipilih ke orang yang sudah ada",
"recent": "Terkini",
"recent-albums": "Album terkini",
"recent_albums": "Album terkini",
"recent_searches": "Pencarian terkini",
"recently_added": "Barusaja ditambahkan",
"recently_added_page_title": "Baru Ditambahkan",

View File

@@ -311,7 +311,7 @@
"search_jobs": "Cerca Attività…",
"send_welcome_email": "Invia email di benvenuto",
"server_external_domain_settings": "Dominio esterno",
"server_external_domain_settings_description": "Dominio per link condivisi pubblicamente, incluso http(s)://",
"server_external_domain_settings_description": "Dominio utilizzato per i link esterni",
"server_public_users": "Utenti Pubblici",
"server_public_users_description": "Tutti gli utenti (nome ed e-mail) sono elencati quando si aggiunge un utente agli album condivisi. Quando disabilitato, l'elenco degli utenti sarà disponibile solo per gli utenti amministratori.",
"server_settings": "Impostazioni Server",
@@ -794,6 +794,11 @@
"color": "Colore",
"color_theme": "Colore Tema",
"command": "Comando",
"command_palette_prompt": "Trova rapidamente pagine, azioni o comandi",
"command_palette_to_close": "per chiudere",
"command_palette_to_navigate": "per entrare",
"command_palette_to_select": "per selezionare",
"command_palette_to_show_all": "per mostrare tutto",
"comment_deleted": "Commento eliminato",
"comment_options": "Opzioni per i commenti",
"comments_and_likes": "Commenti & mi piace",
@@ -1168,6 +1173,7 @@
"exif_bottom_sheet_people": "PERSONE",
"exif_bottom_sheet_person_add_person": "Aggiungi nome",
"exit_slideshow": "Esci dalla presentazione",
"expand": "Espandi",
"expand_all": "Espandi tutto",
"experimental_settings_new_asset_list_subtitle": "Lavori in corso",
"experimental_settings_new_asset_list_title": "Attiva griglia foto sperimentale",
@@ -1613,7 +1619,6 @@
"not_available": "N/A",
"not_in_any_album": "In nessun album",
"not_selected": "Non selezionato",
"note_apply_storage_label_to_previously_uploaded assets": "Nota: Per aggiungere l'etichetta dell'archiviazione alle risorse caricate in precedenza, esegui",
"notes": "Note",
"nothing_here_yet": "Ancora nulla qui",
"notification_permission_dialog_content": "Per attivare le notifiche, vai alle Impostazioni e seleziona concedi.",
@@ -1643,6 +1648,7 @@
"online": "Online",
"only_favorites": "Solo preferiti",
"open": "Apri",
"open_calendar": "Apri il calendario",
"open_in_map_view": "Apri nella visualizzazione mappa",
"open_in_openstreetmap": "Apri su OpenStreetMap",
"open_the_search_filters": "Apri filtri di ricerca",
@@ -1815,7 +1821,7 @@
"reassigned_assets_to_new_person": "{count, plural, one {Riassegnata # risorsa} other {Riassegnate # risorse}} ad una nuova persona",
"reassing_hint": "Assegna le risorse selezionate ad una persona esistente",
"recent": "Recenti",
"recent-albums": "Album recenti",
"recent_albums": "Album recenti",
"recent_searches": "Ricerche recenti",
"recently_added": "Aggiunti recentemente",
"recently_added_page_title": "Aggiunti di recente",
@@ -2184,6 +2190,7 @@
"support": "Supporto",
"support_and_feedback": "Supporto & Feedback",
"support_third_party_description": "La tua installazione di Immich è stata costruita da terze parti. I problemi che riscontri potrebbero essere causati da altri pacchetti, quindi ti preghiamo di sollevare il problema in prima istanza utilizzando i link sottostanti.",
"supporter": "Sostenitore",
"swap_merge_direction": "Scambia direzione di unione",
"sync": "Sincronizza",
"sync_albums": "Sincronizza album",

View File

@@ -1613,7 +1613,6 @@
"not_available": "適用なし",
"not_in_any_album": "どのアルバムにも入っていない",
"not_selected": "選択なし",
"note_apply_storage_label_to_previously_uploaded assets": "注意: 以前にアップロードしたアセットにストレージラベルを適用するには以下を実行してください",
"notes": "注意",
"nothing_here_yet": "まだ何も無いようです",
"notification_permission_dialog_content": "通知を許可するには設定を開いてオンにしてください",
@@ -1815,7 +1814,7 @@
"reassigned_assets_to_new_person": "{count, plural, one {#個} other {#個}}の写真/動画を新しい人物に割り当てました",
"reassing_hint": "選択された写真/動画を既存の人物に割り当て",
"recent": "最近",
"recent-albums": "最近のアルバム",
"recent_albums": "最近のアルバム",
"recent_searches": "最近の検索",
"recently_added": "最近追加された項目",
"recently_added_page_title": "最近",

View File

@@ -1581,7 +1581,6 @@
"not_available": "없음",
"not_in_any_album": "앨범에 없음",
"not_selected": "선택되지 않음",
"note_apply_storage_label_to_previously_uploaded assets": "참고: 이전에 업로드한 항목에도 스토리지 레이블을 적용하려면 다음을 실행합니다,",
"notes": "참고",
"nothing_here_yet": "아직 아무것도 없음",
"notification_permission_dialog_content": "알림을 활성화하려면 설정에서 알림 권한을 허용하세요.",
@@ -1780,7 +1779,7 @@
"reassigned_assets_to_new_person": "{count, plural, one {항목 #개} other {항목 #개}}를 새 인물에게 재지정했습니다.",
"reassing_hint": "기존 인물에 선택한 항목 할당",
"recent": "최근",
"recent-albums": "최근 앨범",
"recent_albums": "최근 앨범",
"recent_searches": "최근 검색",
"recently_added": "최근 추가",
"recently_added_page_title": "최근 추가",

View File

@@ -1579,7 +1579,6 @@
"not_available": "Nepasiekiamas",
"not_in_any_album": "Nė viename albume",
"not_selected": "Nepasirinkta",
"note_apply_storage_label_to_previously_uploaded assets": "Pastaba: Priskirti Saugyklos Žymą prie anksčiau įkeltų ištekliu, paleiskite šį",
"notes": "Pastabos",
"nothing_here_yet": "Kol kas tuščia",
"notification_permission_dialog_content": "Pranešimų įgalinimui eikite į Nustatymus ir pasirinkite Leisti.",
@@ -1774,7 +1773,7 @@
"read_changelog": "Skaityti pakeitimų sąrašą",
"ready_for_upload": "Paruošta įkėlimui",
"recent": "Naujausi",
"recent-albums": "Naujausi albumai",
"recent_albums": "Naujausi albumai",
"recent_searches": "Naujausios paieškos",
"recently_added": "Neseniai pridėta",
"recently_added_page_title": "Neseniai pridėta",
@@ -1824,12 +1823,18 @@
"replace_with_upload": "Pakeisti naujai įkeltu failu",
"repository": "Repozitoriumas",
"require_password": "Reikalauti slaptažodžio",
"require_user_to_change_password_on_first_login": "Reikalauti, kad vartotojas pakeistų slaptažodį pirmą kartą prisijungdamas",
"rescan": "Perskenuoti",
"reset": "Atstatyti",
"reset_password": "Atstayti slaptažodį",
"reset_password": "Atstatyti slaptažodį",
"reset_people_visibility": "Atstatyti žmonių matomumą",
"reset_pin_code": "Atsatyti PIN kodą",
"reset_pin_code_description": "Jei pamiršote PIN kodą, galite susisiekti su serverio administratoriumi, kad jis jį atstatytų",
"reset_pin_code_success": "Sėkmingai atstatytas PIN kodas",
"reset_pin_code_with_password": "PIN kodą visada galite atkurti naudodami savo slaptažodį",
"reset_sqlite": "Atstatyti SQLite duomenų bazę",
"reset_sqlite_confirmation": "Ar tikrai norite atstatyti SQLite duomenų bazę? Turėsite atsijungti ir vėl prisijungti, kad iš naujo sinchronizuotumėte duomenis",
"reset_sqlite_success": "Sėkmingai atstatyta SQLite duomenų bazė",
"reset_to_default": "Atkurti numatytuosius",
"resolution": "Rezoliucija",
"resolve_duplicates": "Sutvarkyti dublikatus",
@@ -1839,7 +1844,15 @@
"restore_trash_action_prompt": "{count} atstatyta iš šiukšliadėžės",
"restore_user": "Atkurti naudotoją",
"restored_asset": "Atkurti elementą",
"resume": "Tęsti",
"resume_paused_jobs": "Tęsti {count, plural, one {# pristabdytą darbą} other {# pristabdytus darbus}}",
"retry_upload": "Bandyti išsiųsti dar kartą",
"review_duplicates": "Peržiūrėti dublikatus",
"review_large_files": "Peržiūrėti didelius failus",
"role": "Rolė",
"role_editor": "Redaktorius",
"role_viewer": "Stebėtojas",
"running": "Vykdoma",
"save": "Išsaugoti",
"save_to_gallery": "Išsaugoti galerijoje",
"saved": "Išsaugota",
@@ -1863,6 +1876,7 @@
"search_by_filename_example": "pvz. IMG_1234.JPG arba PNG",
"search_by_ocr": "Ieškoti pagal OCR",
"search_by_ocr_example": "Latte",
"search_camera_lens_model": "Ieškoti objektyvo modelio...",
"search_camera_make": "Ieškoti pagal kameros gamintoją...",
"search_camera_model": "Ieškoti kameros modelį...",
"search_city": "Ieškoti miesto...",
@@ -1883,12 +1897,15 @@
"search_filter_people_title": "Pasirinkti asmenis",
"search_filter_star_rating": "Įvertinimas",
"search_for": "Ieškoti ko",
"search_for_existing_person": "Ieškoti įvardinto asmens",
"search_no_more_result": "Nėra daugiau rezultatų",
"search_no_people": "Be asmenų",
"search_no_people_named": "Nėra žmonių vardu „{name}“",
"search_no_result": "Rezultatų nerasta, pabandykite kitą paieškos terminą ar derinį",
"search_options": "Paieškos parinktys",
"search_page_categories": "Kategorijos",
"search_page_motion_photos": "Judanti Foto",
"search_page_no_objects": "Objekto info nepasiekiama",
"search_page_no_places": "Vietovės info nepasiekiama",
"search_page_screenshots": "Ekrano nuotraukos",
"search_page_search_photos_videos": "Ieškokite nuotraukų ir vaizdo įrašų",
@@ -1902,22 +1919,35 @@
"search_rating": "Ieškoti pagal įvertinimą...",
"search_result_page_new_search_hint": "Nauja Paieška",
"search_settings": "Ieškoti nustatymų",
"search_state": "Ieškoti valstijos/apskrities...",
"search_suggestion_list_smart_search_hint_1": "Išmanioji paieška įjungta pagal numatytuosius nustatymus, metaduomenų paieškai naudokite sintaksę ",
"search_suggestion_list_smart_search_hint_2": "Paieška",
"search_tags": "Ieškoti žymų...",
"search_timezone": "Ieškoti laiko zonos...",
"search_type": "Paieškos tipas",
"search_your_photos": "Ieškoti nuotraukų",
"searching_locales": "Ieškoma vietovių...",
"second": "Sekundė",
"see_all_people": "Pamatyti visus asmenis",
"select": "Pasirinkti",
"select_album": "Rinktis albumą",
"select_album_cover": "Rinktis albumo viršelį",
"select_albums": "Rinktis albumus",
"select_all": "Pasirinkti visus",
"select_all_duplicates": "Pasirinkti visus dublikatus",
"select_all_in": "Pažymėti visus esančius {group}",
"select_avatar_color": "Pasirinkti avataro spalvą",
"select_count": "{count, plural, one {Pasirinkti #} other {Pasirinkti #}}",
"select_cutoff_date": "Pasirinkite galutinę datą",
"select_face": "Pasirinkti veidą",
"select_featured_photo": "Pasirinkti rodomą nuotrauką",
"select_from_computer": "Pasirinkti iš kompiuterio",
"select_keep_all": "Visus pažymėti \"Palikti\"",
"select_library_owner": "Pasirinkti bibliotekos savininką",
"select_new_face": "Pasirinkti naują veidą",
"select_people": "Pasirinkti asmenis",
"select_person": "Pasirinkti asmenį",
"select_person_to_tag": "Pasirinkti asmenį žymai",
"select_photos": "Pasirinkti nuotraukas",
"select_trash_all": "Visus pažymėti \"Išmesti\"",
"select_user_for_sharing_page_err_album": "Nepavyko sukurti albumo",
@@ -1926,22 +1956,29 @@
"selected_gps_coordinates": "Pasirinkti GPS Koordinates",
"send_message": "Siųsti žinutę",
"send_welcome_email": "Siųsti sveikinimo el. laišką",
"server_info_box_app_version": "Programėlės versija",
"server_endpoint": "Serverio Galinis Taškas",
"server_info_box_app_version": "Programos versija",
"server_info_box_server_url": "Serverio URL",
"server_offline": "Serveris nepasiekiamas",
"server_online": "Serveris pasiekiamas",
"server_privacy": "Serverio Privatumas",
"server_restarting_description": "Šis puslapis atsinaujins neužilgo.",
"server_restarting_title": "Serveris restartuoja",
"server_stats": "Serverio statistika",
"server_update_available": "Yra Serverio atnaujinimas",
"server_version": "Serverio versija",
"set": "Nustatyti",
"set_as_album_cover": "Naudoti kaip albumo viršelį",
"set_as_featured_photo": "Naudoti foto asmens profiliui",
"set_as_profile_picture": "Nustatyti kaip profilio nuotrauką",
"set_date_of_birth": "Nustatyti gimimo datą",
"set_profile_picture": "Nustatyti profilio nuotrauką",
"set_slideshow_to_fullscreen": "Nustatyti skaidrių peržiūrą per visą ekraną",
"set_stack_primary_asset": "Nustatyti kaip pagrindinį elementą",
"setting_image_viewer_help": "Detali peržiūra pirmiausia įkelia mažą miniatiūrą, tada įkelia vidutinio dydžio versiją (jei įjungta) ir galiausiai įkelia originalą (jei įjungta).",
"setting_image_viewer_original_subtitle": "Įjunkite, kad įkeltumėte originalų pilnos raiškos vaizdą (didelį!). Išjunkite, kad sumažintumėte duomenų naudojimą (tiek tinkle, tiek įrenginio talpykloje).",
"setting_image_viewer_original_title": "Užkrauti originalią nuotrauką",
"setting_image_viewer_preview_subtitle": "Įjunkite, jei norite įkelti vidutinės raiškos vaizdą. Išjunkite, jei norite tiesiogiai įkelti originalą ar naudoti tik miniatiūrą.",
"setting_image_viewer_preview_title": "Užkrauti peržiūros nuotrauką",
"setting_image_viewer_title": "Nuotraukos",
"setting_languages_apply": "Pritaikyti",
@@ -1976,7 +2013,11 @@
"shared_album_activities_input_disable": "Komentarai išjungti",
"shared_album_activity_remove_content": "Ar norite ištrinti šią veiklą?",
"shared_album_activity_remove_title": "Ištrinti veiklą",
"shared_album_section_people_action_error": "Klaida išeinant/šalinant iš albumo",
"shared_album_section_people_action_leave": "Pašalinti naudotoją iš albumo",
"shared_album_section_people_action_remove_user": "Pašalinti naudotoją iš albumo",
"shared_album_section_people_title": "ASMENYS",
"shared_by": "Bendrina",
"shared_by_user": "Bendrina {user}",
"shared_by_you": "Bendrinama jūsų",
"shared_from_partner": "Nuotraukos iš {partner}",
@@ -1984,6 +2025,9 @@
"shared_link_app_bar_title": "Dalinimosi Nuorodos",
"shared_link_clipboard_copied_massage": "Nukopijuota į iškarpinę",
"shared_link_clipboard_text": "Nuoroda: {link}\nSlaptažodis: {password}",
"shared_link_create_error": "Klaida kuriant bendrinimo nuorodą",
"shared_link_custom_url_description": "Pasiekite šią bendrinimo nuorodą naudodami tinkintą URL",
"shared_link_edit_description_hint": "Įveskite bendrinimo aprašymą",
"shared_link_edit_expire_after_option_day": "1 diena",
"shared_link_edit_expire_after_option_days": "{count} dienų",
"shared_link_edit_expire_after_option_hour": "1 valanda",
@@ -1992,23 +2036,32 @@
"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_edit_submit_button": "Dalinimosi Nuorodos",
"shared_link_edit_password_hint": "Įveskite bendrinimo slaptažodį",
"shared_link_edit_submit_button": "Atnaujinti nuorodą",
"shared_link_error_server_url_fetch": "Nepavyksta gauti serverio url",
"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_never": "Galiojimas baigiasi ∞",
"shared_link_expires_second": "Galiojimas baigsis už {count} sekundės",
"shared_link_expires_seconds": "Galiojimas baigsis už {count} sekundžių",
"shared_link_individual_shared": "Asmuo pasidalintas",
"shared_link_info_chip_metadata": "EXIF",
"shared_link_manage_links": "Valdyti Bendrinimo nuorodas",
"shared_link_options": "Bendrinimo nuorodos parametrai",
"shared_link_password_description": "Bendrinimo nuorodos prieigai reikalingas slaptažodis",
"shared_links": "Bendrinimo nuorodos",
"shared_links_description": "Dalintis foto ir video su nuoroda",
"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_with_me": "Bendrinama su manimi",
"shared_with_partner": "Pasidalinta su {partner}",
"sharing": "Dalijimasis",
"sharing_enter_password": "Norėdami peržiūrėti šį puslapį, įveskite slaptažodį.",
"sharing_page_album": "Bendrinami albumai",
"sharing_page_description": "Kurkite bendrinamus albumus, kad galėtumėte dalintis foto ir video su žmonėmis savo tinkle.",
"sharing_page_empty_list": "TUŠČIAS SĄRAŠAS",
"sharing_sidebar_description": "Rodyti bendrinimo rodinio nuorodą šoninėje juostoje",
"sharing_silver_appbar_create_shared_album": "Naujas bendrinamas albumas",
@@ -2027,11 +2080,17 @@
"show_metadata": "Rodyti metaduomenis",
"show_or_hide_info": "Rodyti arba slėpti informaciją",
"show_password": "Rodyti slaptažodį",
"show_person_options": "Rodyti asmens parinktis",
"show_progress_bar": "Rodyti progreso juostą",
"show_schema": "Rodyti schemą",
"show_search_options": "Rodyti paieškos parinktis",
"show_shared_links": "Rodyti bendrinamas nuorodas",
"show_slideshow_transition": "Rodyti perėjimą tarp skaidrių",
"show_supporter_badge": "Rėmėjo ženklelis",
"show_supporter_badge_description": "Rodyti rėmėjo ženklelį",
"show_text_recognition": "Rodyti teksto atpažinimą",
"show_text_search_menu": "Rodyti teksto paieškos meniu",
"shuffle": "Išmaišyti",
"sidebar": "Šoninė juosta",
"sidebar_display_description": "Rodyti rodinio nuorodą šoninėje juostoje",
"sign_out": "Atsijungti",
@@ -2041,6 +2100,8 @@
"skip_to_folders": "Praleisti iki aplankų",
"skip_to_tags": "Praleisti iki žymių",
"slideshow": "Skaidrių peržiūra",
"slideshow_repeat": "Kartoti skaidres",
"slideshow_repeat_description": "Pradėti iš pradžių, kai skaidrės baigiasi",
"slideshow_settings": "Skaidrių peržiūros nustatymai",
"sort_albums_by": "Rikiuoti albumus pagal...",
"sort_created": "Sukūrimo data",
@@ -2062,7 +2123,7 @@
"start": "Pradėti",
"start_date": "Pradžios data",
"start_date_before_end_date": "Pradžios data turi būti ankstesnė už pabaigos datą",
"state": "Valstija",
"state": "Valstija/Apskritis",
"status": "Statusas",
"stop_casting": "Nutraukti transliavimą",
"stop_motion_photo": "Sustabdyti Judančią Foto",
@@ -2104,21 +2165,34 @@
"theme": "Tema",
"theme_selection": "Temos pasirinkimas",
"theme_selection_description": "Automatiškai nustatykite šviesią arba tamsią temą pagal naršyklės sistemos nustatymus",
"theme_setting_asset_list_storage_indicator_title": "Rodyti saugyklos indikatorių elementų plytelėse",
"theme_setting_asset_list_tiles_per_row_title": "Elementų per eilutę ({count})",
"theme_setting_colorful_interface_subtitle": "Fono paviršiams užtepkite pagrindinę spalvą.",
"theme_setting_colorful_interface_title": "Spalvinga sąsaja",
"theme_setting_image_viewer_quality_subtitle": "Koreguoti detalių vaizdų peržiūros kokybę",
"theme_setting_image_viewer_quality_title": "Vaizdo peržiūros priemonės kokybė",
"theme_setting_primary_color_subtitle": "Pasirinkite spalvą pagrindiniams veiksmams ir akcentams.",
"theme_setting_primary_color_title": "Pagrindinė spalva",
"theme_setting_system_primary_color_title": "Naudoti sistemos spalvą",
"theme_setting_system_theme_switch": "Automatinė (Naudoti sistemos nustatymus)",
"theme_setting_theme_subtitle": "Pasirinkite programos temos nustatymą",
"theme_setting_three_stage_loading_subtitle": "Trijų etapų įkėlimas gali padidinti įkėlimo našumą, tačiau sukelia žymiai didesnę tinklo apkrovą",
"theme_setting_three_stage_loading_title": "Įjungti trijų etapų įkėlimą",
"then": "Tada",
"they_will_be_merged_together": "Jie bus sujungti kartu",
"third_party_resources": "Trečios Šalies Ištekliai",
"time": "Laikas",
"time_based_memories": "Atsiminimai pagal laiką",
"time_based_memories_duration": "Kiekvieno vaizdo rodymo laikas sekundėmis.",
"timeline": "Laiko skalė",
"timezone": "Laiko juosta",
"to_archive": "Archyvuoti",
"to_change_password": "Pakeisti slaptažodį",
"to_favorite": "Įtraukti prie mėgstamiausių",
"to_login": "Prisijungti",
"to_multi_select": "pasirinkti kelis elementus",
"to_parent": "Persikelti į viršų",
"to_select": "į pasirinkimą",
"to_trash": "Išmesti",
"toggle_settings": "Įjungti nustatymus",
"toggle_theme_description": "Įjungti temą",
@@ -2139,6 +2213,9 @@
"trash_page_select_assets_btn": "Pasirinkti elementus",
"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ų}}.",
"trigger_asset_uploaded": "Elementas Išsiųstas",
"trigger_person_recognized": "Asmuo Atpažintas",
"troubleshoot": "Šalinti triktis",
"type": "Tipas",
"unable_to_change_pin_code": "Negalima pakeisti PIN kodo",
"unable_to_check_version": "Nepavyko patvirtinti programos/serverio versijos",

View File

@@ -1235,7 +1235,6 @@
"not_available": "Nav pieejams",
"not_in_any_album": "Nav nevienā albumā",
"not_selected": "Nav izvēlēts",
"note_apply_storage_label_to_previously_uploaded assets": "Piezīme: Lai piemērotu glabātuves nosaukumu iepriekš augšupielādētiem failiem, izpildiet",
"notes": "Piezīmes",
"nothing_here_yet": "Šeit vēl nekā nav",
"notification_permission_dialog_content": "Lai iespējotu paziņojumus, atveriet Iestatījumi un atlasiet Atļaut.",

View File

@@ -1468,7 +1468,6 @@
"not_available": "ലഭ്യമല്ല",
"not_in_any_album": "ഒരു ആൽബത്തിലുമില്ല",
"not_selected": "തിരഞ്ഞെടുത്തിട്ടില്ല",
"note_apply_storage_label_to_previously_uploaded assets": "കുറിപ്പ്: മുമ്പ് അപ്‌ലോഡ് ചെയ്ത അസറ്റുകളിൽ സ്റ്റോറേജ് ലേബൽ പ്രയോഗിക്കാൻ, ഇത് പ്രവർത്തിപ്പിക്കുക",
"notes": "കുറിപ്പുകൾ",
"nothing_here_yet": "ഇവിടെ ഇതുവരെ ഒന്നുമില്ല",
"notification_permission_dialog_content": "അറിയിപ്പുകൾ പ്രവർത്തനക്ഷമമാക്കാൻ, ക്രമീകരണങ്ങളിലേക്ക് പോയി 'അനുവദിക്കുക' തിരഞ്ഞെടുക്കുക.",
@@ -1663,7 +1662,7 @@
"reassigned_assets_to_new_person": "{count, plural, one {# അസറ്റ്} other {# അസറ്റുകൾ}} ഒരു പുതിയ വ്യക്തിക്ക് വീണ്ടും നൽകി",
"reassing_hint": "തിരഞ്ഞെടുത്ത അസറ്റുകൾ നിലവിലുള്ള ഒരു വ്യക്തിക്ക് നൽകുക",
"recent": "സമീപകാലം",
"recent-albums": "സമീപകാല ആൽബങ്ങൾ",
"recent_albums": "സമീപകാല ആൽബങ്ങൾ",
"recent_searches": "സമീപകാല തിരയലുകൾ",
"recently_added": "അടുത്തിടെ ചേർത്തത്",
"recently_added_page_title": "അടുത്തിടെ ചേർത്തത്",

View File

@@ -1463,7 +1463,6 @@
"not_available": "उपलब्ध नाही",
"not_in_any_album": "कोणत्याही अल्बममध्ये नाही",
"not_selected": "निवडलेले नाही",
"note_apply_storage_label_to_previously_uploaded assets": "नोट: आधी अपलोड केलेल्या अॅसेट्सवर स्टोरेज लेबल लागू करण्यासाठी हा आदेश चालवा",
"notes": "नोट्स",
"nothing_here_yet": "इथे अजून काही नाही",
"notification_permission_dialog_content": "सूचना सक्षम करण्यासाठी सेटिंग्जमध्ये जा आणि अनुमती द्या.",
@@ -1658,7 +1657,7 @@
"reassigned_assets_to_new_person": "{count, plural, one {# आयटम} other {# आयटम}} नव्या व्यक्तीकडे पुन्हा नियुक्त केले",
"reassing_hint": "निवडलेले आयटम विद्यमान व्यक्तीकडे नियुक्त करा",
"recent": "अलीकडील",
"recent-albums": "अलीकडील अल्बम",
"recent_albums": "अलीकडील अल्बम",
"recent_searches": "अलीकडील शोध",
"recently_added": "नुकतेच जोडलेले",
"recently_added_page_title": "नुकतेच जोडलेले",

View File

@@ -1604,7 +1604,6 @@
"not_available": "Ikke tilgjengelig",
"not_in_any_album": "Ikke i noe album",
"not_selected": "Ikke valgt",
"note_apply_storage_label_to_previously_uploaded assets": "Merk: For å bruke lagringsetiketten på tidligere opplastede filer, kjør",
"notes": "Notater",
"nothing_here_yet": "Ingenting her enda",
"notification_permission_dialog_content": "For å aktivere notifikasjoner, gå til Innstillinger og velg tillat.",
@@ -1806,7 +1805,7 @@
"reassigned_assets_to_new_person": "Flyttet {count, plural, one {# element} other {# elementer}} til en ny person",
"reassing_hint": "Tilordne valgte eiendeler til en eksisterende person",
"recent": "Nylig",
"recent-albums": "Nylige album",
"recent_albums": "Nylige album",
"recent_searches": "Nylige søk",
"recently_added": "Nylig lagt til",
"recently_added_page_title": "Nylig oppført",

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