From 54895fb10ec4c70835bc67f9979ee37f2978d74d Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 16 Jun 2026 13:43:22 +0000 Subject: [PATCH 01/64] chore(deps): update node to ^24.13.2 (#29129) --- e2e/package.json | 2 +- package.json | 2 +- packages/cli/package.json | 2 +- packages/plugin-sdk/package.json | 2 +- packages/sdk/package.json | 2 +- pnpm-lock.yaml | 18 +++++++++--------- server/package.json | 2 +- 7 files changed, 15 insertions(+), 15 deletions(-) diff --git a/e2e/package.json b/e2e/package.json index 6bcd4904c1..f5b57598c2 100644 --- a/e2e/package.json +++ b/e2e/package.json @@ -32,7 +32,7 @@ "@playwright/test": "^1.44.1", "@socket.io/component-emitter": "^3.1.2", "@types/luxon": "^3.4.2", - "@types/node": "^24.12.4", + "@types/node": "^24.13.2", "@types/pg": "^8.15.1", "@types/pngjs": "^6.0.4", "@types/supertest": "^7.0.0", diff --git a/package.json b/package.json index 5de1ec055c..c33b8e292c 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,7 @@ "pnpm": ">=10.0.0" }, "devDependencies": { - "@types/node": "^24.12.4", + "@types/node": "^24.13.2", "prettier": "^3.8.3", "prettier-plugin-sort-json": "^4.2.0", "semver": "^7.8.1", diff --git a/packages/cli/package.json b/packages/cli/package.json index 9991599968..925bdf7e24 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -25,7 +25,7 @@ "@types/lodash-es": "^4.17.12", "@types/micromatch": "^4.0.9", "@types/mock-fs": "^4.13.1", - "@types/node": "^24.12.4", + "@types/node": "^24.13.2", "@vitest/coverage-v8": "^4.0.0", "byte-size": "^9.0.0", "cli-progress": "^3.12.0", diff --git a/packages/plugin-sdk/package.json b/packages/plugin-sdk/package.json index 5a23409b8b..8b8d64fcd9 100644 --- a/packages/plugin-sdk/package.json +++ b/packages/plugin-sdk/package.json @@ -28,7 +28,7 @@ "devDependencies": { "@extism/js-pdk": "^1.1.1", "@immich/sdk": "workspace:*", - "@types/node": "^24.12.4", + "@types/node": "^24.13.2", "esbuild": "^0.28.0", "tsc-alias": "^1.8.16", "typescript": "^5.9.3" diff --git a/packages/sdk/package.json b/packages/sdk/package.json index 33bfbb21ea..ca08805f73 100644 --- a/packages/sdk/package.json +++ b/packages/sdk/package.json @@ -24,7 +24,7 @@ "@oazapfts/runtime": "^1.0.2" }, "devDependencies": { - "@types/node": "^24.12.4", + "@types/node": "^24.13.2", "typescript": "^6.0.0" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f2491f9e47..601853b767 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -18,7 +18,7 @@ importers: .: devDependencies: '@types/node': - specifier: ^24.12.4 + specifier: ^24.13.2 version: 24.13.2 prettier: specifier: ^3.8.3 @@ -136,7 +136,7 @@ importers: specifier: ^3.4.2 version: 3.7.1 '@types/node': - specifier: ^24.12.4 + specifier: ^24.13.2 version: 24.13.2 '@types/pg': specifier: ^8.15.1 @@ -248,7 +248,7 @@ importers: specifier: ^4.13.1 version: 4.13.4 '@types/node': - specifier: ^24.12.4 + specifier: ^24.13.2 version: 24.13.2 '@vitest/coverage-v8': specifier: ^4.0.0 @@ -347,7 +347,7 @@ importers: specifier: workspace:* version: link:../sdk '@types/node': - specifier: ^24.12.4 + specifier: ^24.13.2 version: 24.13.2 esbuild: specifier: ^0.28.0 @@ -366,7 +366,7 @@ importers: version: 1.2.0 devDependencies: '@types/node': - specifier: ^24.12.4 + specifier: ^24.13.2 version: 24.13.2 typescript: specifier: ^6.0.0 @@ -676,7 +676,7 @@ importers: specifier: ^2.0.0 version: 2.1.0 '@types/node': - specifier: ^24.12.4 + specifier: ^24.13.2 version: 24.13.2 '@types/nodemailer': specifier: ^8.0.0 @@ -13922,7 +13922,7 @@ snapshots: dependencies: '@babel/code-frame': 7.29.7 '@babel/generator': 7.29.7 - '@babel/parser': 7.27.0 + '@babel/parser': 7.29.7 '@babel/template': 7.29.7 '@babel/types': 7.29.7 debug: 4.4.3 @@ -18032,7 +18032,7 @@ snapshots: '@types/connect-history-api-fallback@1.5.4': dependencies: - '@types/express-serve-static-core': 4.19.8 + '@types/express-serve-static-core': 5.1.1 '@types/node': 24.13.2 '@types/connect@3.4.38': @@ -18382,7 +18382,7 @@ snapshots: '@types/pg-pool@2.0.7': dependencies: - '@types/pg': 8.15.6 + '@types/pg': 8.20.0 '@types/pg@8.15.6': dependencies: diff --git a/server/package.json b/server/package.json index 9b432f5f2e..09e1bc1b8b 100644 --- a/server/package.json +++ b/server/package.json @@ -138,7 +138,7 @@ "@types/luxon": "^3.6.2", "@types/mock-fs": "^4.13.1", "@types/multer": "^2.0.0", - "@types/node": "^24.12.4", + "@types/node": "^24.13.2", "@types/nodemailer": "^8.0.0", "@types/picomatch": "^4.0.0", "@types/pngjs": "^6.0.5", From 8036dc4b8ce57dea4f7c4b2feacd9fb3715af0bf Mon Sep 17 00:00:00 2001 From: okxint <130782884+okxint@users.noreply.github.com> Date: Tue, 16 Jun 2026 19:15:49 +0530 Subject: [PATCH 02/64] fix(web): respect local timezone when building date range for search (#29128) --- web/src/lib/modals/SearchFilterModal.svelte | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/web/src/lib/modals/SearchFilterModal.svelte b/web/src/lib/modals/SearchFilterModal.svelte index 0145caacaf..6766009af8 100644 --- a/web/src/lib/modals/SearchFilterModal.svelte +++ b/web/src/lib/modals/SearchFilterModal.svelte @@ -11,7 +11,7 @@ import { MediaType, QueryType, validQueryTypes } from '$lib/constants'; import { authManager } from '$lib/managers/auth-manager.svelte'; import type { SearchFilter } from '$lib/types'; - import { parseUtcDate } from '$lib/utils/date-time'; + import { asLocalTimeISO, parseUtcDate } from '$lib/utils/date-time'; import { generateId } from '$lib/utils/generate-id'; import { AssetTypeEnum, AssetVisibility, type MetadataSearchDto, type SmartSearchDto } from '@immich/sdk'; import { Button, HStack, Modal, ModalBody, ModalFooter } from '@immich/ui'; @@ -27,7 +27,6 @@ let { searchQuery, onClose }: Props = $props(); - const parseOptionalDate = (dateString?: DateTime) => (dateString ? parseUtcDate(dateString.toString()) : undefined); const toStartOfDayDate = (dateString: string) => parseUtcDate(dateString)?.startOf('day') || undefined; const formId = generateId(); @@ -144,8 +143,12 @@ make: filter.camera.make, model: filter.camera.model, lensModel: filter.camera.lensModel, - takenAfter: parseOptionalDate(filter.date.takenAfter)?.startOf('day').toISO() || undefined, - takenBefore: parseOptionalDate(filter.date.takenBefore)?.endOf('day').toISO() || undefined, + takenAfter: filter.date.takenAfter + ? asLocalTimeISO(filter.date.takenAfter.startOf('day') as DateTime) + : undefined, + takenBefore: filter.date.takenBefore + ? asLocalTimeISO(filter.date.takenBefore.endOf('day') as DateTime) + : undefined, visibility: filter.display.isArchive ? AssetVisibility.Archive : undefined, isFavorite: filter.display.isFavorite || undefined, isNotInAlbum: filter.display.isNotInAlbum || undefined, From 1fa034125cca150ae63ddf6a54713cfe51d3d4d7 Mon Sep 17 00:00:00 2001 From: Mees Frensel <33722705+meesfrensel@users.noreply.github.com> Date: Tue, 16 Jun 2026 15:49:47 +0200 Subject: [PATCH 03/64] fix(web): language selector (#29065) --- mobile/lib/constants/locales.dart | 3 ++- web/src/lib/utils/i18n.ts | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/mobile/lib/constants/locales.dart b/mobile/lib/constants/locales.dart index fd88cbb654..1909afb19d 100644 --- a/mobile/lib/constants/locales.dart +++ b/mobile/lib/constants/locales.dart @@ -17,7 +17,8 @@ const Map locales = { 'Dutch (nl)': Locale('nl'), 'English (United Kingdom) (en_GB)': Locale('en', 'GB'), 'Estonian (et)': Locale('et'), - 'Filipino (tl)': Locale('tl'), + 'Filipino (fil)': Locale('fil'), + 'Filipino (Tagalog) (tl)': Locale('tl'), 'Finnish (fi)': Locale('fi'), 'French (fr)': Locale('fr'), 'Galician (gl)': Locale('gl'), diff --git a/web/src/lib/utils/i18n.ts b/web/src/lib/utils/i18n.ts index 9207c5f557..d179efb5bd 100644 --- a/web/src/lib/utils/i18n.ts +++ b/web/src/lib/utils/i18n.ts @@ -116,6 +116,7 @@ const nonIntlNames: Record = { kxm: 'Khmer Surin', mfa: 'Malay (Pattani)', swg: 'Schwäbisch', + tl: 'Tagalog', }; const getLanguageName = (code: string) => From ce59cc924127c4a254dd9603eba98e3d15cd4024 Mon Sep 17 00:00:00 2001 From: Timon Date: Tue, 16 Jun 2026 16:07:36 +0200 Subject: [PATCH 04/64] docs(server): clarify AssetBulkUploadCheckItem.id is a correlation token (#29141) --- mobile/openapi/lib/model/asset_bulk_upload_check_item.dart | 2 +- open-api/immich-openapi-specs.json | 2 +- packages/sdk/src/fetch-client.ts | 2 +- server/src/dtos/asset-media.dto.ts | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/mobile/openapi/lib/model/asset_bulk_upload_check_item.dart b/mobile/openapi/lib/model/asset_bulk_upload_check_item.dart index 65f81926e3..a3d928b0d8 100644 --- a/mobile/openapi/lib/model/asset_bulk_upload_check_item.dart +++ b/mobile/openapi/lib/model/asset_bulk_upload_check_item.dart @@ -20,7 +20,7 @@ class AssetBulkUploadCheckItem { /// Base64 or hex encoded SHA1 hash String checksum; - /// Asset ID + /// Client-side identifier echoed in the response to match results to inputs (e.g. filename) String id; @override diff --git a/open-api/immich-openapi-specs.json b/open-api/immich-openapi-specs.json index 88c0412b67..529237b836 100644 --- a/open-api/immich-openapi-specs.json +++ b/open-api/immich-openapi-specs.json @@ -16965,7 +16965,7 @@ "type": "string" }, "id": { - "description": "Asset ID", + "description": "Client-side identifier echoed in the response to match results to inputs (e.g. filename)", "type": "string" } }, diff --git a/packages/sdk/src/fetch-client.ts b/packages/sdk/src/fetch-client.ts index ecec1dad23..1c7270fd13 100644 --- a/packages/sdk/src/fetch-client.ts +++ b/packages/sdk/src/fetch-client.ts @@ -696,7 +696,7 @@ export type AssetBulkUpdateDto = { export type AssetBulkUploadCheckItem = { /** Base64 or hex encoded SHA1 hash */ checksum: string; - /** Asset ID */ + /** Client-side identifier echoed in the response to match results to inputs (e.g. filename) */ id: string; }; export type AssetBulkUploadCheckDto = { diff --git a/server/src/dtos/asset-media.dto.ts b/server/src/dtos/asset-media.dto.ts index 596273eddb..c378a7c74d 100644 --- a/server/src/dtos/asset-media.dto.ts +++ b/server/src/dtos/asset-media.dto.ts @@ -58,7 +58,7 @@ const AssetMediaCreateSchema = AssetMediaBaseSchema.extend({ const AssetBulkUploadCheckItemSchema = z .object({ - id: z.string().describe('Asset ID'), + id: z.string().describe('Client-side identifier echoed in the response to match results to inputs (e.g. filename)'), checksum: z.string().describe('Base64 or hex encoded SHA1 hash'), }) .meta({ id: 'AssetBulkUploadCheckItem' }); From d307ab60ca361eb1dfb8c5754dc9bcafc6c2dd75 Mon Sep 17 00:00:00 2001 From: Mees Frensel <33722705+meesfrensel@users.noreply.github.com> Date: Tue, 16 Jun 2026 16:09:45 +0200 Subject: [PATCH 05/64] fix: update datetimeRelative description to minutes instead of seconds (#29137) --- mobile/openapi/lib/model/asset_bulk_update_dto.dart | 2 +- open-api/immich-openapi-specs.json | 2 +- packages/sdk/src/fetch-client.ts | 2 +- server/src/dtos/asset.dto.ts | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/mobile/openapi/lib/model/asset_bulk_update_dto.dart b/mobile/openapi/lib/model/asset_bulk_update_dto.dart index 71f21b812f..fe34c3a14c 100644 --- a/mobile/openapi/lib/model/asset_bulk_update_dto.dart +++ b/mobile/openapi/lib/model/asset_bulk_update_dto.dart @@ -35,7 +35,7 @@ class AssetBulkUpdateDto { /// Optional dateTimeOriginal; - /// Relative time offset in seconds + /// Relative time offset in minutes /// /// Minimum value: -9007199254740991 /// Maximum value: 9007199254740991 diff --git a/open-api/immich-openapi-specs.json b/open-api/immich-openapi-specs.json index 529237b836..5e36725451 100644 --- a/open-api/immich-openapi-specs.json +++ b/open-api/immich-openapi-specs.json @@ -16868,7 +16868,7 @@ "type": "string" }, "dateTimeRelative": { - "description": "Relative time offset in seconds", + "description": "Relative time offset in minutes", "maximum": 9007199254740991, "minimum": -9007199254740991, "type": "integer" diff --git a/packages/sdk/src/fetch-client.ts b/packages/sdk/src/fetch-client.ts index 1c7270fd13..1e3fe6add7 100644 --- a/packages/sdk/src/fetch-client.ts +++ b/packages/sdk/src/fetch-client.ts @@ -673,7 +673,7 @@ export type AssetMediaResponseDto = { export type AssetBulkUpdateDto = { /** Original date and time */ dateTimeOriginal?: string; - /** Relative time offset in seconds */ + /** Relative time offset in minutes */ dateTimeRelative?: number; /** Asset description */ description?: string; diff --git a/server/src/dtos/asset.dto.ts b/server/src/dtos/asset.dto.ts index d7d680fb43..3dddcfaa3e 100644 --- a/server/src/dtos/asset.dto.ts +++ b/server/src/dtos/asset.dto.ts @@ -41,7 +41,7 @@ const UpdateAssetBaseSchema = z const AssetBulkUpdateBaseSchema = UpdateAssetBaseSchema.extend({ ids: z.array(z.uuidv4()).describe('Asset IDs to update'), duplicateId: z.string().nullish().describe('Duplicate ID'), - dateTimeRelative: z.int().optional().describe('Relative time offset in seconds'), + dateTimeRelative: z.int().optional().describe('Relative time offset in minutes'), timeZone: z.string().optional().describe('Time zone (IANA timezone)'), }); From 10fddf2d51611d7d3a6652847f7272ae0326f1e3 Mon Sep 17 00:00:00 2001 From: shenlong <139912620+shenlong-tanwen@users.noreply.github.com> Date: Tue, 16 Jun 2026 19:43:28 +0530 Subject: [PATCH 06/64] fix: resize map after scroll (#29112) Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com> --- .../widgets/bottom_sheet/map_bottom_sheet.widget.dart | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/mobile/lib/presentation/widgets/bottom_sheet/map_bottom_sheet.widget.dart b/mobile/lib/presentation/widgets/bottom_sheet/map_bottom_sheet.widget.dart index f905940c5e..945bdc9584 100644 --- a/mobile/lib/presentation/widgets/bottom_sheet/map_bottom_sheet.widget.dart +++ b/mobile/lib/presentation/widgets/bottom_sheet/map_bottom_sheet.widget.dart @@ -23,7 +23,9 @@ class MapBottomSheet extends StatelessWidget { resizeOnScroll: false, actions: [], backgroundColor: context.themeData.colorScheme.surface, - slivers: [const SliverFillRemaining(hasScrollBody: true, child: _ScopedMapTimeline())], + slivers: [ + const SliverFillRemaining(hasScrollBody: false, child: SizedBox(height: 0, child: _ScopedMapTimeline())), + ], ); } } From 010220d588f4009b247a618d5f7afbd7cb325b22 Mon Sep 17 00:00:00 2001 From: Brandon Wees Date: Tue, 16 Jun 2026 09:13:31 -0500 Subject: [PATCH 07/64] fix: video thumbnail quality sharing (#29104) --- .../share_action_button.widget.dart | 34 +++++++++++++++---- .../repositories/asset_media.repository.dart | 4 ++- 2 files changed, 30 insertions(+), 8 deletions(-) diff --git a/mobile/lib/presentation/widgets/action_buttons/share_action_button.widget.dart b/mobile/lib/presentation/widgets/action_buttons/share_action_button.widget.dart index 1217638452..53bd15b457 100644 --- a/mobile/lib/presentation/widgets/action_buttons/share_action_button.widget.dart +++ b/mobile/lib/presentation/widgets/action_buttons/share_action_button.widget.dart @@ -6,10 +6,12 @@ import 'package:flutter/material.dart'; import 'package:fluttertoast/fluttertoast.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/constants/enums.dart'; +import 'package:immich_mobile/domain/models/asset/base_asset.model.dart'; import 'package:immich_mobile/domain/models/settings_key.dart'; import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/generated/translations.g.dart'; import 'package:immich_mobile/presentation/widgets/action_buttons/base_action_button.widget.dart'; +import 'package:immich_mobile/providers/asset_viewer/asset_viewer.provider.dart'; import 'package:immich_mobile/providers/infrastructure/action.provider.dart'; import 'package:immich_mobile/providers/infrastructure/settings.provider.dart'; import 'package:immich_mobile/providers/timeline/multiselect.provider.dart'; @@ -51,7 +53,9 @@ class _SharePreparingDialog extends StatelessWidget { } class _ShareFileTypeDialog extends StatelessWidget { - const _ShareFileTypeDialog(); + final bool showPreview; + + const _ShareFileTypeDialog({this.showPreview = true}); @override Widget build(BuildContext context) { @@ -66,11 +70,12 @@ class _ShareFileTypeDialog extends StatelessWidget { title: Text(context.t.share_original), onTap: () => context.pop(ShareAssetType.original), ), - ListTile( - leading: const Icon(Icons.photo_size_select_large_rounded), - title: Text(context.t.share_preview), - onTap: () => context.pop(ShareAssetType.preview), - ), + if (showPreview) + ListTile( + leading: const Icon(Icons.photo_size_select_large_rounded), + title: Text(context.t.share_preview), + onTap: () => context.pop(ShareAssetType.preview), + ), ], ), actions: [TextButton(onPressed: () => context.pop(), child: Text(context.t.cancel))], @@ -85,6 +90,16 @@ class ShareActionButton extends ConsumerWidget { const ShareActionButton({super.key, required this.source, this.iconOnly = false, this.menuItem = false}); + Set _getSelectedAssets(WidgetRef ref) { + return switch (source) { + ActionSource.timeline => ref.read(multiSelectProvider).selectedAssets, + ActionSource.viewer => switch (ref.read(assetViewerProvider).currentAsset) { + BaseAsset asset => {asset}, + null => const {}, + }, + }; + } + void _onTap(BuildContext context, WidgetRef ref) async { if (!context.mounted) { return; @@ -99,9 +114,14 @@ class ShareActionButton extends ConsumerWidget { return; } + // only show preview option when at least one of the assets is not a video + // we cant share previews of videos + final assets = _getSelectedAssets(ref); + final showPreview = assets.isEmpty || assets.any((asset) => !asset.isVideo); + final fileType = await showDialog( context: context, - builder: (_) => const _ShareFileTypeDialog(), + builder: (_) => _ShareFileTypeDialog(showPreview: showPreview), useRootNavigator: false, ); diff --git a/mobile/lib/repositories/asset_media.repository.dart b/mobile/lib/repositories/asset_media.repository.dart index de544e42bb..4c9b6f6009 100644 --- a/mobile/lib/repositories/asset_media.repository.dart +++ b/mobile/lib/repositories/asset_media.repository.dart @@ -285,7 +285,9 @@ class AssetMediaRepository { return 0; } - final shareFile = switch (fileType) { + final effectiveFileType = asset.isVideo ? ShareAssetType.original : fileType; + + final shareFile = switch (effectiveFileType) { ShareAssetType.original => await _getOriginalShareFile( asset, cancelCompleter: cancelCompleter, From 9ee412110f027ce4e98acf4f56b6376ba8d4cb60 Mon Sep 17 00:00:00 2001 From: Santo Shakil Date: Tue, 16 Jun 2026 20:14:33 +0600 Subject: [PATCH 08/64] fix(mobile): stop sync albums crashing on the main isolate (#29133) the album sync provider read cancellationProvider, which only exists in the background isolate and throws on the main one. moved the cancel signal onto the isolate call path. fixes #29125 fixes #29119 --- .../services/sync_linked_album.service.dart | 12 ++--- .../lib/domain/utils/sync_linked_album.dart | 5 ++- .../sync_linked_album_service_test.dart | 44 +++++++++++++++++++ 3 files changed, 52 insertions(+), 9 deletions(-) create mode 100644 mobile/test/domain/services/sync_linked_album_service_test.dart diff --git a/mobile/lib/domain/services/sync_linked_album.service.dart b/mobile/lib/domain/services/sync_linked_album.service.dart index ddcd6721d7..091ca222f0 100644 --- a/mobile/lib/domain/services/sync_linked_album.service.dart +++ b/mobile/lib/domain/services/sync_linked_album.service.dart @@ -7,7 +7,6 @@ import 'package:immich_mobile/domain/services/store.service.dart'; import 'package:immich_mobile/infrastructure/repositories/local_album.repository.dart'; import 'package:immich_mobile/infrastructure/repositories/remote_album.repository.dart'; import 'package:immich_mobile/providers/infrastructure/album.provider.dart'; -import 'package:immich_mobile/providers/infrastructure/cancel.provider.dart'; import 'package:immich_mobile/providers/infrastructure/store.provider.dart'; import 'package:immich_mobile/repositories/drift_album_api_repository.dart'; import 'package:immich_mobile/utils/debug_print.dart'; @@ -19,7 +18,6 @@ final syncLinkedAlbumServiceProvider = Provider( ref.watch(remoteAlbumRepository), ref.watch(driftAlbumApiRepositoryProvider), ref.watch(storeServiceProvider), - cancellation: ref.watch(cancellationProvider), ), ); @@ -28,19 +26,17 @@ class SyncLinkedAlbumService { final DriftRemoteAlbumRepository _remoteAlbumRepository; final DriftAlbumApiRepository _albumApiRepository; final StoreService _storeService; - final Completer? _cancellation; SyncLinkedAlbumService( this._localAlbumRepository, this._remoteAlbumRepository, this._albumApiRepository, - this._storeService, { - this._cancellation, - }); + this._storeService, + ); final _log = Logger("SyncLinkedAlbumService"); - Future syncLinkedAlbums(String userId) async { + Future syncLinkedAlbums(String userId, {Completer? cancellation}) async { final selectedAlbums = await _localAlbumRepository.getBackupAlbums(); await Future.wait( @@ -64,7 +60,7 @@ class SyncLinkedAlbumService { final album = await _albumApiRepository.addAssets( remoteAlbum.id, assetIds, - abortTrigger: _cancellation?.future, + abortTrigger: cancellation?.future, ); await _remoteAlbumRepository.addAssets(remoteAlbum.id, album.added); } diff --git a/mobile/lib/domain/utils/sync_linked_album.dart b/mobile/lib/domain/utils/sync_linked_album.dart index 7bfadc96e7..bdf35d3e2a 100644 --- a/mobile/lib/domain/utils/sync_linked_album.dart +++ b/mobile/lib/domain/utils/sync_linked_album.dart @@ -2,6 +2,7 @@ import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/domain/models/store.model.dart'; import 'package:immich_mobile/domain/services/sync_linked_album.service.dart'; import 'package:immich_mobile/entities/store.entity.dart'; +import 'package:immich_mobile/providers/infrastructure/cancel.provider.dart'; import 'package:logging/logging.dart'; Future syncLinkedAlbumsIsolated(ProviderContainer ref) { @@ -10,5 +11,7 @@ Future syncLinkedAlbumsIsolated(ProviderContainer ref) { Logger("SyncLinkedAlbum").warning("No user logged in, skipping linked album sync"); return Future.value(); } - return ref.read(syncLinkedAlbumServiceProvider).syncLinkedAlbums(user.id); + return ref + .read(syncLinkedAlbumServiceProvider) + .syncLinkedAlbums(user.id, cancellation: ref.read(cancellationProvider)); } diff --git a/mobile/test/domain/services/sync_linked_album_service_test.dart b/mobile/test/domain/services/sync_linked_album_service_test.dart new file mode 100644 index 0000000000..d4fc1396c5 --- /dev/null +++ b/mobile/test/domain/services/sync_linked_album_service_test.dart @@ -0,0 +1,44 @@ +import 'package:flutter_test/flutter_test.dart'; +import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:immich_mobile/domain/services/sync_linked_album.service.dart'; +import 'package:immich_mobile/providers/infrastructure/album.provider.dart'; +import 'package:immich_mobile/providers/infrastructure/store.provider.dart'; +import 'package:immich_mobile/repositories/drift_album_api_repository.dart'; + +import '../../infrastructure/repository.mock.dart'; +import '../service.mock.dart'; + +void main() { + // A container with the service's deps overridden but cancellationProvider left + // alone, i.e. the root (main) isolate, where cancellationProvider has no + // override and throws if read. The UI reads this provider here. + ProviderContainer rootContainer() { + final container = ProviderContainer( + overrides: [ + localAlbumRepository.overrideWithValue(MockLocalAlbumRepository()), + remoteAlbumRepository.overrideWithValue(MockRemoteAlbumRepository()), + driftAlbumApiRepositoryProvider.overrideWithValue(MockDriftAlbumApiRepository()), + storeServiceProvider.overrideWithValue(MockStoreService()), + ], + ); + addTearDown(container.dispose); + return container; + } + + // Regression for #29125 (Sync Albums toggle) and #29119 (can't leave the album + // selection screen): #28694 made the provider watch cancellationProvider, so + // reading it off the isolate threw. The cancellation now lives on the isolate + // call path, not the provider, so the UI can build it. + test('builds on the root isolate without a cancellationProvider override', () { + final container = rootContainer(); + + expect(() => container.read(syncLinkedAlbumServiceProvider), returnsNormally); + expect(container.read(syncLinkedAlbumServiceProvider), isA()); + }); + + test('manageLinkedAlbums runs from the UI without a cancellation signal', () { + final service = rootContainer().read(syncLinkedAlbumServiceProvider); + + expect(service.manageLinkedAlbums(const [], 'user-1'), completes); + }); +} From 805ca1a2bf6090e1336df8b2bdae43f8954c7a5d Mon Sep 17 00:00:00 2001 From: Daniel Dietzler <36593685+danieldietzler@users.noreply.github.com> Date: Tue, 16 Jun 2026 16:15:54 +0200 Subject: [PATCH 09/64] chore: maintenance page design tweaks (#29087) --- i18n/en.json | 5 ++ .../ServerStatisticsCard.svelte | 5 +- web/src/routes/admin/maintenance/+page.svelte | 77 +++++++++++-------- 3 files changed, 54 insertions(+), 33 deletions(-) diff --git a/i18n/en.json b/i18n/en.json index cdffc66a51..648138a878 100644 --- a/i18n/en.json +++ b/i18n/en.json @@ -189,18 +189,23 @@ "machine_learning_smart_search_enabled": "Enable smart search", "machine_learning_smart_search_enabled_description": "If disabled, images will not be encoded for smart search.", "machine_learning_url_description": "The URL of the machine learning server. If more than one URL is provided, each server will be attempted one-at-a-time until one responds successfully, in order from first to last. Servers that don't respond will be temporarily ignored until they come back online.", + "maintenance_backup_management": "Backup management", "maintenance_delete_backup": "Delete Backup", "maintenance_delete_backup_description": "This file will be irrevocably deleted.", "maintenance_delete_error": "Failed to delete backup.", + "maintenance_integrity_check": "Check", "maintenance_integrity_check_all": "Check All", "maintenance_integrity_checksum_mismatch": "Checksum Mismatch", + "maintenance_integrity_checksum_mismatch_description": "Files whose on-disk checksum mismatches the checksum Immich has stored in its database.", "maintenance_integrity_checksum_mismatch_job": "Check for checksum mismatches", "maintenance_integrity_checksum_mismatch_refresh_job": "Refresh checksum mismatch reports", "maintenance_integrity_missing_file": "Missing Files", + "maintenance_integrity_missing_file_description": "Files that Immich has tracked in its database but do not exist on the file system.", "maintenance_integrity_missing_file_job": "Check for missing files", "maintenance_integrity_missing_file_refresh_job": "Refresh missing file reports", "maintenance_integrity_report": "Integrity Report", "maintenance_integrity_untracked_file": "Untracked Files", + "maintenance_integrity_untracked_file_description": "Files in Immich's directories that Immich does not have any record of.", "maintenance_integrity_untracked_file_job": "Check for untracked files", "maintenance_integrity_untracked_file_refresh_job": "Refresh untracked file reports", "maintenance_restore_backup": "Restore Backup", diff --git a/web/src/lib/components/server-statistics/ServerStatisticsCard.svelte b/web/src/lib/components/server-statistics/ServerStatisticsCard.svelte index b8ece40b49..73b4f62dc0 100644 --- a/web/src/lib/components/server-statistics/ServerStatisticsCard.svelte +++ b/web/src/lib/components/server-statistics/ServerStatisticsCard.svelte @@ -12,10 +12,11 @@ icon?: string; title: string; valuePromise: MaybePromise; + tooltip?: string; footer?: Snippet; } - let { icon, title, valuePromise, footer }: Props = $props(); + let { icon, title, valuePromise, tooltip, footer }: Props = $props(); const zeros = (data?: ValueData) => { let length = 13; if (data) { @@ -32,7 +33,7 @@ {#if icon} {/if} - {title} + {title} {#await valuePromise} diff --git a/web/src/routes/admin/maintenance/+page.svelte b/web/src/routes/admin/maintenance/+page.svelte index 940142f259..f915aecd72 100644 --- a/web/src/routes/admin/maintenance/+page.svelte +++ b/web/src/routes/admin/maintenance/+page.svelte @@ -21,6 +21,7 @@ import { onMount } from 'svelte'; import { t, type Translations } from 'svelte-i18n'; import type { PageData } from './$types'; + import { SvelteSet } from 'svelte/reactivity'; type Props = { data: PageData; @@ -50,7 +51,7 @@ }; let jobs: QueuesResponseLegacyDto | undefined = $state(); - let expectingUpdate: boolean = $state(false); + const activeJobs = new SvelteSet(); const getReportTypeTranslation = (report: IntegrityReport): Translations => { switch (report) { @@ -66,13 +67,27 @@ } }; + const getReportTypeDescriptionKey = (report: IntegrityReport): Translations => { + switch (report) { + case IntegrityReport.UntrackedFile: { + return 'admin.maintenance_integrity_untracked_file_description'; + } + case IntegrityReport.MissingFile: { + return 'admin.maintenance_integrity_missing_file_description'; + } + case IntegrityReport.ChecksumMismatch: { + return 'admin.maintenance_integrity_checksum_mismatch_description'; + } + } + }; + const updateReports = async () => { jobs = await getQueuesLegacy(); if (jobs.integrityCheck.queueStatus.isActive) { - expectingUpdate = true; - } else if (expectingUpdate) { + activeJobs.add(ManualJobName.IntegrityUntrackedFilesRefresh); + } else if (activeJobs.size > 0) { + activeJobs.clear(); integrityReport = await getIntegrityReportSummary(); - expectingUpdate = false; } }; @@ -84,7 +99,7 @@ const onJobCreate = ({ dto }: { dto: JobCreateDto }) => { if ((Object.values(jobNames).includes(dto.name) || Object.values(refreshJobNames).includes(dto.name)) && jobs) { - expectingUpdate = true; + activeJobs.add(dto.name); jobs.integrityCheck.queueStatus.isActive = true; } }; @@ -106,7 +121,7 @@ } }} class="mt-1 self-end" - disabled={expectingUpdate}>{$t('admin.maintenance_integrity_check_all')} 0}>{$t('admin.maintenance_integrity_check_all')} 0}>{$t('refresh')} @@ -125,36 +140,36 @@ {#each reportTypes as reportType (reportType)} {#snippet footer()} - - - + + + + + {$t('view')} {/snippet} @@ -166,7 +181,7 @@
- {$t('admin.maintenance_settings')} + {$t('admin.maintenance_backup_management')} Date: Tue, 16 Jun 2026 17:12:25 +0200 Subject: [PATCH 10/64] chore(web): use ui's Badge (#29143) --- web/src/lib/elements/Badge.svelte | 18 -------------- web/src/routes/admin/queues/QueueCard.svelte | 26 ++++++-------------- 2 files changed, 7 insertions(+), 37 deletions(-) delete mode 100644 web/src/lib/elements/Badge.svelte diff --git a/web/src/lib/elements/Badge.svelte b/web/src/lib/elements/Badge.svelte deleted file mode 100644 index 3313d59778..0000000000 --- a/web/src/lib/elements/Badge.svelte +++ /dev/null @@ -1,18 +0,0 @@ - - - - {@render children?.()} - diff --git a/web/src/routes/admin/queues/QueueCard.svelte b/web/src/routes/admin/queues/QueueCard.svelte index 6e7fbb940d..9954cbd122 100644 --- a/web/src/routes/admin/queues/QueueCard.svelte +++ b/web/src/routes/admin/queues/QueueCard.svelte @@ -2,13 +2,12 @@ import { cleanClass } from '$lib'; import QueueCardBadge from './QueueCardBadge.svelte'; import QueueCardButton from './QueueCardButton.svelte'; - import Badge from '$lib/elements/Badge.svelte'; import { Route } from '$lib/route'; import { asQueueItem } from '$lib/services/queue.service'; import { locale } from '$lib/stores/preferences.store'; import { transformToTitleCase } from '$lib/utils'; import { QueueCommand, type QueueCommandDto, type QueueResponseDto } from '@immich/sdk'; - import { Icon, IconButton, Link } from '@immich/ui'; + import { Badge, Icon, IconButton, Link } from '@immich/ui'; import { mdiAlertCircle, mdiAllInclusive, @@ -67,27 +66,16 @@ />
{#if statistics.failed > 0} - -
- - {$t('admin.jobs_failed', { values: { jobCount: statistics.failed.toLocaleString($locale) } })} - - onCommand({ command: QueueCommand.ClearFailed, force: false })} - /> -
+ onCommand({ command: QueueCommand.ClearFailed, force: false })} + translations={{ close: $t('clear_message') }} + > + {$t('admin.jobs_failed', { values: { jobCount: statistics.failed.toLocaleString($locale) } })} {/if} {#if statistics.delayed > 0} - - {$t('admin.jobs_delayed', { values: { jobCount: statistics.delayed.toLocaleString($locale) } })} - + {$t('admin.jobs_delayed', { values: { jobCount: statistics.delayed.toLocaleString($locale) } })} {/if}
From 34f78e3fd49e8482a8d4d2b59e87f74fc38b08c0 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 16 Jun 2026 17:53:55 +0200 Subject: [PATCH 11/64] chore(deps): update github-actions (#29124) --- .github/workflows/build-mobile.yml | 2 +- .github/workflows/check-openapi.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-mobile.yml b/.github/workflows/build-mobile.yml index ff77a1cd2d..cb281b2bcb 100644 --- a/.github/workflows/build-mobile.yml +++ b/.github/workflows/build-mobile.yml @@ -237,7 +237,7 @@ jobs: run: flutter build ios --config-only --no-codesign - name: Setup Ruby - uses: ruby/setup-ruby@afeafc3d1ab54a631816aba4c914a0081c12ff2f # v1.310.0 + uses: ruby/setup-ruby@12fd324f1d0b43274fdc8130f6980590a667c455 # v1.312.0 with: ruby-version: '3.3' bundler-cache: true diff --git a/.github/workflows/check-openapi.yml b/.github/workflows/check-openapi.yml index 1fb78e80b2..6280f2ef14 100644 --- a/.github/workflows/check-openapi.yml +++ b/.github/workflows/check-openapi.yml @@ -25,7 +25,7 @@ jobs: persist-credentials: false - name: Check for breaking API changes - uses: oasdiff/oasdiff-action/breaking@a8c7f0e5649d20d623edb5b38446d3ab3d82d43c # v0.0.53 + uses: oasdiff/oasdiff-action/breaking@3530478ec30f84adedbfeb28f0d9527a290f50a9 # v0.0.57 with: base: https://raw.githubusercontent.com/${{ github.repository }}/main/open-api/immich-openapi-specs.json revision: open-api/immich-openapi-specs.json From df4a708aed6762f636c5ce38c4acf3ce9d4c21d9 Mon Sep 17 00:00:00 2001 From: Mees Frensel <33722705+meesfrensel@users.noreply.github.com> Date: Tue, 16 Jun 2026 18:21:24 +0200 Subject: [PATCH 12/64] chore(e2e): remove vite-tsconfig-paths (#29145) --- e2e/package.json | 1 - e2e/vitest.config.ts | 5 +++-- e2e/vitest.maintenance.config.ts | 5 +++-- pnpm-lock.yaml | 3 --- 4 files changed, 6 insertions(+), 8 deletions(-) diff --git a/e2e/package.json b/e2e/package.json index f5b57598c2..1a6017e2d9 100644 --- a/e2e/package.json +++ b/e2e/package.json @@ -54,7 +54,6 @@ "typescript": "^6.0.0", "typescript-eslint": "^8.28.0", "utimes": "^5.2.1", - "vite-tsconfig-paths": "^6.1.1", "vitest": "^4.0.0" } } diff --git a/e2e/vitest.config.ts b/e2e/vitest.config.ts index 17ece152d7..1f617481e4 100644 --- a/e2e/vitest.config.ts +++ b/e2e/vitest.config.ts @@ -1,4 +1,3 @@ -import tsconfigPaths from 'vite-tsconfig-paths'; import { defineConfig } from 'vitest/config'; const skipDockerSetup = process.env.VITEST_DISABLE_DOCKER_SETUP === 'true'; @@ -24,5 +23,7 @@ export default defineConfig({ maxWorkers: 1, isolate: false, }, - plugins: [tsconfigPaths()], + resolve: { + tsconfigPaths: true, + }, }); diff --git a/e2e/vitest.maintenance.config.ts b/e2e/vitest.maintenance.config.ts index a6e96ccc0a..908133f955 100644 --- a/e2e/vitest.maintenance.config.ts +++ b/e2e/vitest.maintenance.config.ts @@ -1,4 +1,3 @@ -import tsconfigPaths from 'vite-tsconfig-paths'; import { defineConfig } from 'vitest/config'; const skipDockerSetup = process.env.VITEST_DISABLE_DOCKER_SETUP === 'true'; @@ -24,5 +23,7 @@ export default defineConfig({ maxWorkers: 1, isolate: false, }, - plugins: [tsconfigPaths()], + resolve: { + tsconfigPaths: true, + }, }); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 601853b767..7bb2289996 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -201,9 +201,6 @@ importers: utimes: specifier: ^5.2.1 version: 5.2.1 - vite-tsconfig-paths: - specifier: ^6.1.1 - version: 6.1.1(typescript@6.0.3)(vite@8.0.16(@types/node@24.13.2)(esbuild@0.28.1)(jiti@2.7.0)(sass@1.101.0)(terser@5.48.0)(tsx@4.22.4)(yaml@2.9.0)) vitest: specifier: ^4.0.0 version: 4.1.9(@opentelemetry/api@1.9.1)(@types/node@24.13.2)(@vitest/coverage-v8@4.1.9)(happy-dom@20.10.3)(jsdom@26.1.0(canvas@3.2.3))(vite@8.0.16(@types/node@24.13.2)(esbuild@0.28.1)(jiti@2.7.0)(sass@1.101.0)(terser@5.48.0)(tsx@4.22.4)(yaml@2.9.0)) From 0f49bcbd27189cf1a5c95facd33a8f0fd2c533ed Mon Sep 17 00:00:00 2001 From: shenlong <139912620+shenlong-tanwen@users.noreply.github.com> Date: Tue, 16 Jun 2026 22:12:12 +0530 Subject: [PATCH 13/64] chore: do not optimize on cleanup (#29118) --- .../services/background_worker.service.dart | 16 +++++++++++++++- .../repositories/logger_db.repository.dart | 9 +++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/mobile/lib/domain/services/background_worker.service.dart b/mobile/lib/domain/services/background_worker.service.dart index 529ec770c4..d490b226c7 100644 --- a/mobile/lib/domain/services/background_worker.service.dart +++ b/mobile/lib/domain/services/background_worker.service.dart @@ -104,6 +104,7 @@ class BackgroundWorkerBgService extends BackgroundWorkerFlutterApi { Future onAndroidUpload(int? maxMinutes) async { final hashTimeout = Duration(minutes: _isBackupEnabled ? 3 : 6); final backupTimeout = maxMinutes != null ? Duration(minutes: maxMinutes - 1) : null; + await _optimizeDB(); return _backgroundLoop( hashTimeout: hashTimeout, backupTimeout: backupTimeout, @@ -123,6 +124,11 @@ class BackgroundWorkerBgService extends BackgroundWorkerFlutterApi { return; } + // Only for Background Processing tasks + if (maxSeconds == null) { + await _optimizeDB(); + } + // Run sync local, sync remote, hash and backup concurrently so the bg // refresh task (20s budget) can make progress on all four instead of // racing them sequentially. Phases are independent at the data layer: @@ -193,6 +199,14 @@ class BackgroundWorkerBgService extends BackgroundWorkerFlutterApi { } } + Future _optimizeDB() async { + try { + await (_drift.optimize(allTables: true), _driftLogger.optimize()).wait; + } catch (error, stack) { + dPrint(() => "Error during background worker optimize: $error, $stack"); + } + } + Future _cleanup() async { await runZonedGuarded(_handleCleanup, (error, stack) { dPrint(() => "Error during background worker cleanup: $error, $stack"); @@ -221,7 +235,7 @@ class BackgroundWorkerBgService extends BackgroundWorkerFlutterApi { if (nativeSyncApi != null) nativeSyncApi.cancelHashing(), ]); await workerManagerPatch.dispose().catchError((_) async {}); - await Future.wait([LogService.I.dispose(), Store.dispose(), _drift.optimize(allTables: true)]); + await Future.wait([LogService.I.dispose(), Store.dispose()]); await _drift.close(); await _driftLogger.close(); diff --git a/mobile/lib/infrastructure/repositories/logger_db.repository.dart b/mobile/lib/infrastructure/repositories/logger_db.repository.dart index 32af4af748..8d9794ac8b 100644 --- a/mobile/lib/infrastructure/repositories/logger_db.repository.dart +++ b/mobile/lib/infrastructure/repositories/logger_db.repository.dart @@ -2,6 +2,7 @@ import 'package:drift/drift.dart'; import 'package:drift_sqlite_async/drift_sqlite_async.dart'; import 'package:immich_mobile/infrastructure/entities/log.entity.dart'; import 'package:immich_mobile/infrastructure/repositories/logger_db.repository.drift.dart'; +import 'package:immich_mobile/utils/debug_print.dart'; import 'package:sqlite_async/sqlite_async.dart'; @DriftDatabase(tables: [LogMessageEntity]) @@ -13,6 +14,14 @@ class DriftLogger extends $DriftLogger { @override int get schemaVersion => 1; + Future optimize() async { + try { + await customStatement('PRAGMA optimize=0x10002'); + } catch (error) { + dPrint(() => 'Failed to optimize logger database: $error'); + } + } + @override MigrationStrategy get migration => MigrationStrategy( beforeOpen: (details) async { From 76c042abc7798437e9c01dfa376a655a8c694436 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 16 Jun 2026 19:08:09 +0200 Subject: [PATCH 14/64] chore(deps): lock file maintenance (mise) (#29091) --- docs/mise.lock | 5 ++- mise.lock | 77 ++++++++++++++++++++++++++++++++++++++ mobile/mise.lock | 97 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 178 insertions(+), 1 deletion(-) diff --git a/docs/mise.lock b/docs/mise.lock index dee476c431..65cf1124a2 100644 --- a/docs/mise.lock +++ b/docs/mise.lock @@ -1,5 +1,8 @@ # @generated - this file is auto-generated by `mise lock` https://mise.en.dev/dev-tools/mise-lock.html [[tools.wrangler]] -version = "4.66.0" +version = "4.98.0" backend = "npm:wrangler" + +[tools.wrangler.options] +allow_builds = '["esbuild", "sharp", "workerd"]' diff --git a/mise.lock b/mise.lock index 0962628be1..37df6f1048 100644 --- a/mise.lock +++ b/mise.lock @@ -95,6 +95,56 @@ checksum = "sha256:bea03c670e8cc5bfe9edc0c5d624d4735421610cef5e808db93e7d8596952 url = "https://github.com/jellyfin/jellyfin-ffmpeg/releases/download/v7.1.3-6/jellyfin-ffmpeg_7.1.3-6_portable_linuxarm64-gpl.tar.xz" url_api = "https://api.github.com/repos/jellyfin/jellyfin-ffmpeg/releases/assets/409048876" +[[tools."github:jellyfin/jellyfin-ffmpeg"]] +version = "7.1.3-6" +backend = "github:jellyfin/jellyfin-ffmpeg" + +[tools."github:jellyfin/jellyfin-ffmpeg".options] +asset_pattern = "jellyfin-ffmpeg_*_portable_linux64-gpl.tar.xz" + +[tools."github:jellyfin/jellyfin-ffmpeg"."platforms.linux-x64"] +checksum = "sha256:39e99a7927468a6abec5f65d00f55010e8ff2ae3c2605294f179c94f6ae21af2" +url = "https://github.com/jellyfin/jellyfin-ffmpeg/releases/download/v7.1.3-6/jellyfin-ffmpeg_7.1.3-6_portable_linux64-gpl.tar.xz" +url_api = "https://api.github.com/repos/jellyfin/jellyfin-ffmpeg/releases/assets/409048879" + +[tools."github:jellyfin/jellyfin-ffmpeg"."platforms.linux-x64-musl"] +checksum = "sha256:39e99a7927468a6abec5f65d00f55010e8ff2ae3c2605294f179c94f6ae21af2" +url = "https://github.com/jellyfin/jellyfin-ffmpeg/releases/download/v7.1.3-6/jellyfin-ffmpeg_7.1.3-6_portable_linux64-gpl.tar.xz" +url_api = "https://api.github.com/repos/jellyfin/jellyfin-ffmpeg/releases/assets/409048879" + +[[tools."github:jellyfin/jellyfin-ffmpeg"]] +version = "7.1.3-6" +backend = "github:jellyfin/jellyfin-ffmpeg" + +[tools."github:jellyfin/jellyfin-ffmpeg".options] +asset_pattern = "jellyfin-ffmpeg_*_portable_macarm64-gpl.tar.xz" + +[tools."github:jellyfin/jellyfin-ffmpeg"."platforms.macos-arm64"] +checksum = "sha256:e024d5e78d5414e75f0181036cd21373fafb9270c72894dfd7dbda2572439820" +url = "https://github.com/jellyfin/jellyfin-ffmpeg/releases/download/v7.1.3-6/jellyfin-ffmpeg_7.1.3-6_portable_macarm64-gpl.tar.xz" +url_api = "https://api.github.com/repos/jellyfin/jellyfin-ffmpeg/releases/assets/408995838" + +[[tools."github:jellyfin/jellyfin-ffmpeg"]] +version = "7.1.3-6" +backend = "github:jellyfin/jellyfin-ffmpeg" + +[tools."github:jellyfin/jellyfin-ffmpeg"."platforms.windows-x64"] +checksum = "sha256:7b7168149689610296f3a187c717056ce0786cc125a31caf28056737e9ba1cc1" +url = "https://github.com/jellyfin/jellyfin-ffmpeg/releases/download/v7.1.3-6/jellyfin-ffmpeg_7.1.3-6_portable_win64-clang-gpl.zip" +url_api = "https://api.github.com/repos/jellyfin/jellyfin-ffmpeg/releases/assets/409036094" + +[[tools."github:jellyfin/jellyfin-ffmpeg"]] +version = "7.1.3-6" +backend = "github:jellyfin/jellyfin-ffmpeg" + +[tools."github:jellyfin/jellyfin-ffmpeg".options] +asset_pattern = "jellyfin-ffmpeg_*_portable_mac64-gpl.tar.xz" + +[tools."github:jellyfin/jellyfin-ffmpeg"."platforms.macos-x64"] +checksum = "sha256:066ede9774aaae97a18098aaeea8b7e0d286653eb8618f640476e99c59a536c2" +url = "https://github.com/jellyfin/jellyfin-ffmpeg/releases/download/v7.1.3-6/jellyfin-ffmpeg_7.1.3-6_portable_mac64-gpl.tar.xz" +url_api = "https://api.github.com/repos/jellyfin/jellyfin-ffmpeg/releases/assets/408995889" + [[tools."github:webassembly/binaryen"]] version = "version_124" backend = "github:webassembly/binaryen" @@ -158,6 +208,33 @@ url = "https://download.java.net/java/GA/jdk21.0.2/f2283984656d49d69e91c55847602 checksum = "sha256:b6c17e747ae78cdd6de4d7532b3164b277daee97c007d3eaa2b39cca99882664" url = "https://download.java.net/java/GA/jdk21.0.2/f2283984656d49d69e91c558476027ac/13/GPL/openjdk-21.0.2_windows-x64_bin.zip" +[[tools.java]] +version = "21.0.2" +backend = "core:java" + +[tools.java.options] +shorthand_vendor = "openjdk" + +[tools.java."platforms.linux-arm64"] +checksum = "sha256:08db1392a48d4eb5ea5315cf8f18b89dbaf36cda663ba882cf03c704c9257ec2" +url = "https://download.java.net/java/GA/jdk21.0.2/f2283984656d49d69e91c558476027ac/13/GPL/openjdk-21.0.2_linux-aarch64_bin.tar.gz" + +[tools.java."platforms.linux-x64"] +checksum = "sha256:a2def047a73941e01a73739f92755f86b895811afb1f91243db214cff5bdac3f" +url = "https://download.java.net/java/GA/jdk21.0.2/f2283984656d49d69e91c558476027ac/13/GPL/openjdk-21.0.2_linux-x64_bin.tar.gz" + +[tools.java."platforms.macos-arm64"] +checksum = "sha256:b3d588e16ec1e0ef9805d8a696591bd518a5cea62567da8f53b5ce32d11d22e4" +url = "https://download.java.net/java/GA/jdk21.0.2/f2283984656d49d69e91c558476027ac/13/GPL/openjdk-21.0.2_macos-aarch64_bin.tar.gz" + +[tools.java."platforms.macos-x64"] +checksum = "sha256:8fd09e15dc406387a0aba70bf5d99692874e999bf9cd9208b452b5d76ac922d3" +url = "https://download.java.net/java/GA/jdk21.0.2/f2283984656d49d69e91c558476027ac/13/GPL/openjdk-21.0.2_macos-x64_bin.tar.gz" + +[tools.java."platforms.windows-x64"] +checksum = "sha256:b6c17e747ae78cdd6de4d7532b3164b277daee97c007d3eaa2b39cca99882664" +url = "https://download.java.net/java/GA/jdk21.0.2/f2283984656d49d69e91c558476027ac/13/GPL/openjdk-21.0.2_windows-x64_bin.zip" + [[tools.node]] version = "24.15.0" backend = "core:node" diff --git a/mobile/mise.lock b/mobile/mise.lock index e95323e4d7..763c026559 100644 --- a/mobile/mise.lock +++ b/mobile/mise.lock @@ -64,6 +64,76 @@ checksum = "sha256:f133470daa3fb0427f039b424392af7e917d7e7db6b556aa2a968ab0e3158 url = "https://github.com/CQLabs/homebrew-dcm/releases/download/1.37.0/dcm-windows-release.zip" url_api = "https://api.github.com/repos/CQLabs/homebrew-dcm/releases/assets/404543660" +[[tools."github:CQLabs/homebrew-dcm"]] +version = "1.37.0" +backend = "github:CQLabs/homebrew-dcm" + +[tools."github:CQLabs/homebrew-dcm".options] +asset_pattern = "dcm-linux-arm-release.zip" + +[tools."github:CQLabs/homebrew-dcm"."platforms.linux-arm64"] +checksum = "sha256:253da2512b149913dfe345bf9a62a79acb2d730f66e71162ba4a92dfc4224b82" +url = "https://github.com/CQLabs/homebrew-dcm/releases/download/1.37.0/dcm-linux-arm-release.zip" +url_api = "https://api.github.com/repos/CQLabs/homebrew-dcm/releases/assets/404543838" + +[tools."github:CQLabs/homebrew-dcm"."platforms.linux-arm64-musl"] +checksum = "sha256:253da2512b149913dfe345bf9a62a79acb2d730f66e71162ba4a92dfc4224b82" +url = "https://github.com/CQLabs/homebrew-dcm/releases/download/1.37.0/dcm-linux-arm-release.zip" +url_api = "https://api.github.com/repos/CQLabs/homebrew-dcm/releases/assets/404543838" + +[[tools."github:CQLabs/homebrew-dcm"]] +version = "1.37.0" +backend = "github:CQLabs/homebrew-dcm" + +[tools."github:CQLabs/homebrew-dcm".options] +asset_pattern = "dcm-linux-x64-release.zip" + +[tools."github:CQLabs/homebrew-dcm"."platforms.linux-x64"] +checksum = "sha256:477e086d4099c12f21e5ccd83b005d5fb945dd4cac4fd127fd9a08d7649af1cf" +url = "https://github.com/CQLabs/homebrew-dcm/releases/download/1.37.0/dcm-linux-x64-release.zip" +url_api = "https://api.github.com/repos/CQLabs/homebrew-dcm/releases/assets/404543797" + +[tools."github:CQLabs/homebrew-dcm"."platforms.linux-x64-musl"] +checksum = "sha256:477e086d4099c12f21e5ccd83b005d5fb945dd4cac4fd127fd9a08d7649af1cf" +url = "https://github.com/CQLabs/homebrew-dcm/releases/download/1.37.0/dcm-linux-x64-release.zip" +url_api = "https://api.github.com/repos/CQLabs/homebrew-dcm/releases/assets/404543797" + +[[tools."github:CQLabs/homebrew-dcm"]] +version = "1.37.0" +backend = "github:CQLabs/homebrew-dcm" + +[tools."github:CQLabs/homebrew-dcm".options] +asset_pattern = "dcm-macos-x64-release.zip" + +[tools."github:CQLabs/homebrew-dcm"."platforms.macos-x64"] +checksum = "sha256:e56cb99872be7445a4de1d37e5438ca70e3bcd83be7a2b9b385e3538881f8068" +url = "https://github.com/CQLabs/homebrew-dcm/releases/download/1.37.0/dcm-macos-x64-release.zip" +url_api = "https://api.github.com/repos/CQLabs/homebrew-dcm/releases/assets/404543727" + +[[tools."github:CQLabs/homebrew-dcm"]] +version = "1.37.0" +backend = "github:CQLabs/homebrew-dcm" + +[tools."github:CQLabs/homebrew-dcm".options] +asset_pattern = "dcm-windows-release.zip" + +[tools."github:CQLabs/homebrew-dcm"."platforms.windows-x64"] +checksum = "sha256:f133470daa3fb0427f039b424392af7e917d7e7db6b556aa2a968ab0e31587da" +url = "https://github.com/CQLabs/homebrew-dcm/releases/download/1.37.0/dcm-windows-release.zip" +url_api = "https://api.github.com/repos/CQLabs/homebrew-dcm/releases/assets/404543660" + +[[tools."github:CQLabs/homebrew-dcm"]] +version = "1.37.0" +backend = "github:CQLabs/homebrew-dcm" + +[tools."github:CQLabs/homebrew-dcm".options] +asset_pattern = "dcm-macos-arm-release.zip" + +[tools."github:CQLabs/homebrew-dcm"."platforms.macos-arm64"] +checksum = "sha256:30bede64367d09067093cc57af6ec9496d7717898138ded5cb98a16ac8dd9d93" +url = "https://github.com/CQLabs/homebrew-dcm/releases/download/1.37.0/dcm-macos-arm-release.zip" +url_api = "https://api.github.com/repos/CQLabs/homebrew-dcm/releases/assets/404543757" + [[tools.java]] version = "21.0.2" backend = "core:java" @@ -87,3 +157,30 @@ url = "https://download.java.net/java/GA/jdk21.0.2/f2283984656d49d69e91c55847602 [tools.java."platforms.windows-x64"] checksum = "sha256:b6c17e747ae78cdd6de4d7532b3164b277daee97c007d3eaa2b39cca99882664" url = "https://download.java.net/java/GA/jdk21.0.2/f2283984656d49d69e91c558476027ac/13/GPL/openjdk-21.0.2_windows-x64_bin.zip" + +[[tools.java]] +version = "21.0.2" +backend = "core:java" + +[tools.java.options] +shorthand_vendor = "openjdk" + +[tools.java."platforms.linux-arm64"] +checksum = "sha256:08db1392a48d4eb5ea5315cf8f18b89dbaf36cda663ba882cf03c704c9257ec2" +url = "https://download.java.net/java/GA/jdk21.0.2/f2283984656d49d69e91c558476027ac/13/GPL/openjdk-21.0.2_linux-aarch64_bin.tar.gz" + +[tools.java."platforms.linux-x64"] +checksum = "sha256:a2def047a73941e01a73739f92755f86b895811afb1f91243db214cff5bdac3f" +url = "https://download.java.net/java/GA/jdk21.0.2/f2283984656d49d69e91c558476027ac/13/GPL/openjdk-21.0.2_linux-x64_bin.tar.gz" + +[tools.java."platforms.macos-arm64"] +checksum = "sha256:b3d588e16ec1e0ef9805d8a696591bd518a5cea62567da8f53b5ce32d11d22e4" +url = "https://download.java.net/java/GA/jdk21.0.2/f2283984656d49d69e91c558476027ac/13/GPL/openjdk-21.0.2_macos-aarch64_bin.tar.gz" + +[tools.java."platforms.macos-x64"] +checksum = "sha256:8fd09e15dc406387a0aba70bf5d99692874e999bf9cd9208b452b5d76ac922d3" +url = "https://download.java.net/java/GA/jdk21.0.2/f2283984656d49d69e91c558476027ac/13/GPL/openjdk-21.0.2_macos-x64_bin.tar.gz" + +[tools.java."platforms.windows-x64"] +checksum = "sha256:b6c17e747ae78cdd6de4d7532b3164b277daee97c007d3eaa2b39cca99882664" +url = "https://download.java.net/java/GA/jdk21.0.2/f2283984656d49d69e91c558476027ac/13/GPL/openjdk-21.0.2_windows-x64_bin.zip" From 27cfa0e788e046d323f4ee4b8ee677a7b92dc631 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 16 Jun 2026 19:22:40 +0200 Subject: [PATCH 15/64] chore(deps): update github-actions (#29146) --- .github/workflows/close-duplicates.yml | 2 +- .github/workflows/docker.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/close-duplicates.yml b/.github/workflows/close-duplicates.yml index fe804f8443..6694781e72 100644 --- a/.github/workflows/close-duplicates.yml +++ b/.github/workflows/close-duplicates.yml @@ -39,7 +39,7 @@ jobs: needs: [get_body, should_run] if: ${{ needs.should_run.outputs.should_run == 'true' }} container: - image: ghcr.io/immich-app/mdq:main@sha256:e73f60195b39748c4876f23e3e6cd22a68a9754acec8aef1fd6979fd52cd2c9f + image: ghcr.io/immich-app/mdq:main@sha256:2a64c7f045cb7b580fbdf3614d7d1805f5775fec453e3d1023764180efa8c70b outputs: checked: ${{ steps.get_checkbox.outputs.checked }} steps: diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 133950fb0a..9ff2a705e6 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -132,7 +132,7 @@ jobs: suffixes: '-rocm' platforms: linux/amd64 runner-mapping: '{"linux/amd64": "pokedex-large"}' - uses: immich-app/devtools/.github/workflows/multi-runner-build.yml@db54dcf16fbb12c43479a23749ceea0ad1b4a704 # multi-runner-build-workflow-v3.0.0 + uses: immich-app/devtools/.github/workflows/multi-runner-build.yml@50dc3a14f0606ecd8fc28d78d3a3c655115ab695 # multi-runner-build-workflow-v3.1.0 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@db54dcf16fbb12c43479a23749ceea0ad1b4a704 # multi-runner-build-workflow-v3.0.0 + uses: immich-app/devtools/.github/workflows/multi-runner-build.yml@50dc3a14f0606ecd8fc28d78d3a3c655115ab695 # multi-runner-build-workflow-v3.1.0 permissions: contents: read actions: read From 3927eb6755987fe3783f82738982bf6ba2fa2384 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 16 Jun 2026 17:29:17 +0000 Subject: [PATCH 16/64] chore(deps): update base-image to v202606161235 (#29151) --- server/Dockerfile | 4 ++-- server/Dockerfile.dev | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/server/Dockerfile b/server/Dockerfile index 8d33206d07..058938a42a 100644 --- a/server/Dockerfile +++ b/server/Dockerfile @@ -1,4 +1,4 @@ -FROM ghcr.io/immich-app/base-server-dev:202606021219@sha256:63fa91aa011f6f2921dd32fe6d1be8d637e9bd7f3e3dd0c8e446afb31b282af4 AS builder +FROM ghcr.io/immich-app/base-server-dev:202606161235@sha256:9f88b07acc8b7bf37a1dd3d5a19193f664443eaaab4e08e9f9341414c5e4b23f AS builder ENV COREPACK_ENABLE_DOWNLOAD_PROMPT=0 \ CI=1 \ COREPACK_HOME=/tmp \ @@ -80,7 +80,7 @@ RUN --mount=type=cache,id=pnpm-packages,target=/buildcache/pnpm-store \ --mount=type=cache,id=mise-tools-${TARGETPLATFORM},target=/buildcache/mise \ mise //:plugins -FROM ghcr.io/immich-app/base-server-prod:202606021219@sha256:6ef9ef5859492149af770a6c884b5e2ddbaeef99f8885ea5f2d9f73625a3d9ec +FROM ghcr.io/immich-app/base-server-prod:202606161235@sha256:c6d59e3923f548d29a212b4dc51b6281a722cfa1da7972a009c0f3830f5762d6 WORKDIR /usr/src/app ENV NODE_ENV=production \ diff --git a/server/Dockerfile.dev b/server/Dockerfile.dev index 06196ae143..83fdc3eb02 100644 --- a/server/Dockerfile.dev +++ b/server/Dockerfile.dev @@ -1,5 +1,5 @@ # dev build -FROM ghcr.io/immich-app/base-server-dev:202606021219@sha256:63fa91aa011f6f2921dd32fe6d1be8d637e9bd7f3e3dd0c8e446afb31b282af4 AS dev +FROM ghcr.io/immich-app/base-server-dev:202606161235@sha256:9f88b07acc8b7bf37a1dd3d5a19193f664443eaaab4e08e9f9341414c5e4b23f AS dev COPY --from=ghcr.io/jdx/mise:2026.5.18@sha256:5bb3311994fa78cef307ca3077cdb18f9551da0886371fc26ea91ab56220ffc5 /usr/local/bin/mise /usr/local/bin/mise From 83b4dc1733b2bf297aad642905a40737935d5f6f Mon Sep 17 00:00:00 2001 From: shenlong <139912620+shenlong-tanwen@users.noreply.github.com> Date: Tue, 16 Jun 2026 23:44:09 +0530 Subject: [PATCH 18/64] fix: scrolling state update after unmounted (#29149) Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com> --- .../widgets/timeline/fixed/segment.model.dart | 7 ++-- .../widgets/timeline/timeline.widget.dart | 34 +++++++++++-------- 2 files changed, 23 insertions(+), 18 deletions(-) diff --git a/mobile/lib/presentation/widgets/timeline/fixed/segment.model.dart b/mobile/lib/presentation/widgets/timeline/fixed/segment.model.dart index ea6f3e739e..7712983fde 100644 --- a/mobile/lib/presentation/widgets/timeline/fixed/segment.model.dart +++ b/mobile/lib/presentation/widgets/timeline/fixed/segment.model.dart @@ -110,9 +110,6 @@ class _FixedSegmentRow extends ConsumerWidget { final timelineService = ref.read(timelineServiceProvider); final isDynamicLayout = columnCount <= (context.isMobile ? 2 : 3); - if (isScrubbing) { - return _buildPlaceholder(context); - } if (timelineService.hasRange(assetIndex, assetCount)) { return _buildAssetRow( context, @@ -122,6 +119,10 @@ class _FixedSegmentRow extends ConsumerWidget { ); } + if (isScrubbing) { + return _buildPlaceholder(context); + } + return FutureBuilder>( future: timelineService.loadAssets(assetIndex, assetCount), builder: (context, snapshot) { diff --git a/mobile/lib/presentation/widgets/timeline/timeline.widget.dart b/mobile/lib/presentation/widgets/timeline/timeline.widget.dart index eb7a31ac8b..8acaebf40e 100644 --- a/mobile/lib/presentation/widgets/timeline/timeline.widget.dart +++ b/mobile/lib/presentation/widgets/timeline/timeline.widget.dart @@ -21,8 +21,8 @@ import 'package:immich_mobile/presentation/widgets/timeline/scrubber.widget.dart import 'package:immich_mobile/presentation/widgets/timeline/segment.model.dart'; import 'package:immich_mobile/presentation/widgets/timeline/timeline.state.dart'; import 'package:immich_mobile/presentation/widgets/timeline/timeline_drag_region.dart'; -import 'package:immich_mobile/providers/infrastructure/settings.provider.dart'; import 'package:immich_mobile/providers/infrastructure/readonly_mode.provider.dart'; +import 'package:immich_mobile/providers/infrastructure/settings.provider.dart'; import 'package:immich_mobile/providers/infrastructure/timeline.provider.dart'; import 'package:immich_mobile/providers/timeline/multiselect.provider.dart'; import 'package:immich_mobile/widgets/common/immich_sliver_app_bar.dart'; @@ -181,10 +181,13 @@ class _SliverTimelineState extends ConsumerState<_SliverTimeline> { void _onEvent(Event event) { switch (event) { case ScrollToTopEvent(): - ref.read(timelineStateProvider.notifier).setScrubbing(true); - _scrollController - .animateTo(0, duration: const Duration(milliseconds: 250), curve: Curves.easeInOut) - .whenComplete(() => ref.read(timelineStateProvider.notifier).setScrubbing(false)); + { + final timelineState = ref.read(timelineStateProvider.notifier); + timelineState.setScrubbing(true); + _scrollController + .animateTo(0, duration: const Duration(milliseconds: 250), curve: Curves.easeInOut) + .whenComplete(() => timelineState.setScrubbing(false)); + } case ScrollToDateEvent scrollToDateEvent: _scrollToDate(scrollToDateEvent.date); @@ -249,6 +252,7 @@ class _SliverTimelineState extends ConsumerState<_SliverTimeline> { } void _scrollToDate(DateTime date) { + final timelineState = ref.read(timelineStateProvider.notifier); final asyncSegments = ref.read(timelineSegmentProvider); asyncSegments.whenData((segments) { // Find the segment that contains assets from the target date @@ -275,16 +279,16 @@ class _SliverTimelineState extends ConsumerState<_SliverTimeline> { if (fallbackSegment != null) { // Scroll to the segment with a small offset to show the header final targetOffset = fallbackSegment.startOffset - 50; - ref.read(timelineStateProvider.notifier).setScrubbing(true); + timelineState.setScrubbing(true); _scrollController .animateTo( targetOffset.clamp(0.0, _scrollController.position.maxScrollExtent), duration: const Duration(milliseconds: 500), curve: Curves.easeInOut, ) - .whenComplete(() => ref.read(timelineStateProvider.notifier).setScrubbing(false)); + .whenComplete(() => timelineState.setScrubbing(false)); } else { - ref.read(timelineStateProvider.notifier).setScrubbing(false); + timelineState.setScrubbing(false); } }); } @@ -301,19 +305,19 @@ class _SliverTimelineState extends ConsumerState<_SliverTimeline> { void _stopDrag() { WidgetsBinding.instance.addPostFrameCallback((_) { // Update the physics post frame to prevent sudden change in physics on iOS. - setState(() { - _scrollPhysics = null; - }); + if (mounted) { + setState(() { + _scrollPhysics = null; + }); + } }); setState(() { _dragging = false; _draggedAssets.clear(); }); - // Reset the scrolling state after a small delay to allow bottom sheet to expand again + final timelineState = ref.read(timelineStateProvider.notifier); Future.delayed(const Duration(milliseconds: 300), () { - if (mounted) { - ref.read(timelineStateProvider.notifier).setScrolling(false); - } + timelineState.setScrolling(false); }); } From 12b7cd066b8824ecf7b17d2e835c0f8ec2ce5fb9 Mon Sep 17 00:00:00 2001 From: Santo Shakil Date: Wed, 17 Jun 2026 00:46:52 +0600 Subject: [PATCH 19/64] fix(mobile): show memories with no showAt/hideAt in the timeline lane (#29158) --- .../repositories/memory.repository.dart | 4 +- .../repositories/memory_repository_test.dart | 108 ++++++++++++++++++ mobile/test/medium/repository_context.dart | 36 ++++++ 3 files changed, 146 insertions(+), 2 deletions(-) create mode 100644 mobile/test/medium/repositories/memory_repository_test.dart diff --git a/mobile/lib/infrastructure/repositories/memory.repository.dart b/mobile/lib/infrastructure/repositories/memory.repository.dart index 0dcf7200cc..37cccbf2d4 100644 --- a/mobile/lib/infrastructure/repositories/memory.repository.dart +++ b/mobile/lib/infrastructure/repositories/memory.repository.dart @@ -25,8 +25,8 @@ class DriftMemoryRepository extends DriftDatabaseRepository { ]) ..where(_db.memoryEntity.ownerId.equals(ownerId)) ..where(_db.memoryEntity.deletedAt.isNull()) - ..where(_db.memoryEntity.showAt.isSmallerOrEqualValue(localUtc)) - ..where(_db.memoryEntity.hideAt.isBiggerOrEqualValue(localUtc)) + ..where(_db.memoryEntity.showAt.isNull() | _db.memoryEntity.showAt.isSmallerOrEqualValue(localUtc)) + ..where(_db.memoryEntity.hideAt.isNull() | _db.memoryEntity.hideAt.isBiggerOrEqualValue(localUtc)) ..orderBy([OrderingTerm.desc(_db.memoryEntity.memoryAt), OrderingTerm.asc(_db.remoteAssetEntity.createdAt)]); final rows = await query.get(); diff --git a/mobile/test/medium/repositories/memory_repository_test.dart b/mobile/test/medium/repositories/memory_repository_test.dart new file mode 100644 index 0000000000..e57098f3bd --- /dev/null +++ b/mobile/test/medium/repositories/memory_repository_test.dart @@ -0,0 +1,108 @@ +import 'package:flutter_test/flutter_test.dart'; +import 'package:immich_mobile/infrastructure/repositories/memory.repository.dart'; + +import '../repository_context.dart'; + +void main() { + late MediumRepositoryContext ctx; + late DriftMemoryRepository sut; + + setUp(() { + ctx = MediumRepositoryContext(); + sut = DriftMemoryRepository(ctx.db); + }); + + tearDown(() async { + await ctx.dispose(); + }); + + group('getAll', () { + // #24745: memories created via the API have no showAt/hideAt. before the fix + // the window filter (show_at <= now AND hide_at >= now) drops them because a + // NULL comparison is never true. + test('includes a memory with null showAt/hideAt', () async { + final user = await ctx.newUser(); + final asset = await ctx.newRemoteAsset(ownerId: user.id); + final memory = await ctx.newMemory(ownerId: user.id); + await ctx.newMemoryAsset(memoryId: memory.id, assetId: asset.id); + + final result = await sut.getAll(user.id); + + expect(result, hasLength(1)); + expect(result.first.id, memory.id); + expect(result.first.assets.single.id, asset.id); + }); + + test('includes a memory whose window covers today', () async { + final user = await ctx.newUser(); + final asset = await ctx.newRemoteAsset(ownerId: user.id); + final now = DateTime.now().toUtc(); + final memory = await ctx.newMemory( + ownerId: user.id, + showAt: now.subtract(const Duration(days: 10)), + hideAt: now.add(const Duration(days: 10)), + ); + await ctx.newMemoryAsset(memoryId: memory.id, assetId: asset.id); + + final result = await sut.getAll(user.id); + + expect(result.map((m) => m.id), [memory.id]); + }); + + test('excludes a memory whose hideAt is in the past', () async { + final user = await ctx.newUser(); + final asset = await ctx.newRemoteAsset(ownerId: user.id); + final now = DateTime.now().toUtc(); + final memory = await ctx.newMemory( + ownerId: user.id, + showAt: now.subtract(const Duration(days: 20)), + hideAt: now.subtract(const Duration(days: 10)), + ); + await ctx.newMemoryAsset(memoryId: memory.id, assetId: asset.id); + + final result = await sut.getAll(user.id); + + expect(result, isEmpty); + }); + + test('excludes a memory whose showAt is in the future', () async { + final user = await ctx.newUser(); + final asset = await ctx.newRemoteAsset(ownerId: user.id); + final now = DateTime.now().toUtc(); + final memory = await ctx.newMemory( + ownerId: user.id, + showAt: now.add(const Duration(days: 10)), + hideAt: now.add(const Duration(days: 20)), + ); + await ctx.newMemoryAsset(memoryId: memory.id, assetId: asset.id); + + final result = await sut.getAll(user.id); + + expect(result, isEmpty); + }); + + test('includes a memory with showAt in the past and null hideAt', () async { + final user = await ctx.newUser(); + final asset = await ctx.newRemoteAsset(ownerId: user.id); + final now = DateTime.now().toUtc(); + final memory = await ctx.newMemory(ownerId: user.id, showAt: now.subtract(const Duration(days: 10))); + await ctx.newMemoryAsset(memoryId: memory.id, assetId: asset.id); + + final result = await sut.getAll(user.id); + + expect(result.map((m) => m.id), [memory.id]); + }); + + test('excludes a memory with null showAt and hideAt in the past', () async { + final user = await ctx.newUser(); + final asset = await ctx.newRemoteAsset(ownerId: user.id); + final now = DateTime.now().toUtc(); + final memory = await ctx.newMemory(ownerId: user.id, hideAt: now.subtract(const Duration(days: 10))); + await ctx.newMemoryAsset(memoryId: memory.id, assetId: asset.id); + + final result = await sut.getAll(user.id); + + expect(result, isEmpty); + }); + }); +} diff --git a/mobile/test/medium/repository_context.dart b/mobile/test/medium/repository_context.dart index 436a58aaf8..00390d455f 100644 --- a/mobile/test/medium/repository_context.dart +++ b/mobile/test/medium/repository_context.dart @@ -3,11 +3,14 @@ import 'package:drift/native.dart'; import 'package:immich_mobile/domain/models/album/album.model.dart'; import 'package:immich_mobile/domain/models/album/local_album.model.dart'; import 'package:immich_mobile/domain/models/asset/base_asset.model.dart'; +import 'package:immich_mobile/domain/models/memory.model.dart'; import 'package:immich_mobile/domain/models/user.model.dart'; import 'package:immich_mobile/infrastructure/entities/asset_face.entity.drift.dart'; import 'package:immich_mobile/infrastructure/entities/local_album.entity.drift.dart'; import 'package:immich_mobile/infrastructure/entities/local_album_asset.entity.drift.dart'; import 'package:immich_mobile/infrastructure/entities/local_asset.entity.drift.dart'; +import 'package:immich_mobile/infrastructure/entities/memory.entity.drift.dart'; +import 'package:immich_mobile/infrastructure/entities/memory_asset.entity.drift.dart'; import 'package:immich_mobile/infrastructure/entities/partner.entity.drift.dart'; import 'package:immich_mobile/infrastructure/entities/person.entity.drift.dart'; import 'package:immich_mobile/infrastructure/entities/remote_album.entity.drift.dart'; @@ -309,4 +312,37 @@ class MediumRepositoryContext { Future newLocalAlbumAsset({required String albumId, required String assetId}) => db .into(db.localAlbumAssetEntity) .insert(LocalAlbumAssetEntityCompanion(albumId: .new(albumId), assetId: .new(assetId))); + + Future newMemory({ + String? id, + String? ownerId, + MemoryTypeEnum? type, + int? year, + DateTime? memoryAt, + DateTime? showAt, + DateTime? hideAt, + DateTime? deletedAt, + bool? isSaved, + }) async { + id ??= TestUtils.uuid(); + return db + .into(db.memoryEntity) + .insertReturning( + MemoryEntityCompanion( + id: .new(id), + ownerId: .new(TestUtils.uuid(ownerId)), + type: .new(type ?? MemoryTypeEnum.onThisDay), + data: .new(MemoryData(year: year ?? 2020).toJson()), + isSaved: .new(isSaved ?? false), + memoryAt: .new(TestUtils.date(memoryAt)), + showAt: .new(showAt), + hideAt: .new(hideAt), + deletedAt: .new(deletedAt), + ), + ); + } + + Future newMemoryAsset({required String memoryId, required String assetId}) => db + .into(db.memoryAssetEntity) + .insert(MemoryAssetEntityCompanion(memoryId: .new(memoryId), assetId: .new(assetId))); } From cda499f2b548c7023bb97e60e0eebf494c4141d3 Mon Sep 17 00:00:00 2001 From: Santo Shakil Date: Wed, 17 Jun 2026 00:51:29 +0600 Subject: [PATCH 20/64] fix(mobile): keep toasts off the dynamic island when keyboard is open (#29159) --- mobile/lib/widgets/common/immich_toast.dart | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/mobile/lib/widgets/common/immich_toast.dart b/mobile/lib/widgets/common/immich_toast.dart index 3e7ab273d8..1da07f419d 100644 --- a/mobile/lib/widgets/common/immich_toast.dart +++ b/mobile/lib/widgets/common/immich_toast.dart @@ -50,9 +50,10 @@ class ImmichToast { ), ), positionedToastBuilder: (context, child, gravity) { + final isTop = gravity == ToastGravity.TOP; return Positioned( - top: gravity == ToastGravity.TOP ? 150 : null, - bottom: gravity == ToastGravity.BOTTOM ? 150 : null, + top: isTop ? 150 : null, + bottom: isTop ? null : 150 + MediaQuery.of(context).viewInsets.bottom, left: MediaQuery.of(context).size.width / 2 - 150, right: MediaQuery.of(context).size.width / 2 - 150, child: IgnorePointer(child: child), From 983a005709cb55d0fb2ba3499a05b25c2291e152 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 16 Jun 2026 19:18:01 +0000 Subject: [PATCH 21/64] chore(deps): update github-actions to v3 (#29147) --- .github/workflows/build-mobile.yml | 4 ++-- .github/workflows/check-openapi.yml | 2 +- .github/workflows/cli.yml | 2 +- .github/workflows/docs-build.yml | 2 +- .github/workflows/docs-deploy.yml | 2 +- .github/workflows/docs-destroy.yml | 2 +- .github/workflows/fix-format.yml | 2 +- .github/workflows/prepare-release.yml | 2 +- .github/workflows/sdk.yml | 2 +- .github/workflows/static_analysis.yml | 2 +- .github/workflows/test.yml | 28 +++++++++++++-------------- 11 files changed, 25 insertions(+), 25 deletions(-) diff --git a/.github/workflows/build-mobile.yml b/.github/workflows/build-mobile.yml index cb281b2bcb..224f673ff9 100644 --- a/.github/workflows/build-mobile.yml +++ b/.github/workflows/build-mobile.yml @@ -91,7 +91,7 @@ jobs: token: ${{ steps.token.outputs.token }} - name: Setup Mise - uses: immich-app/devtools/actions/use-mise@7b8610a904d57da241e4ddba17fa62b62b15aed4 # use-mise-action-v2.0.2 + uses: immich-app/devtools/actions/use-mise@3bca63ca3c15020293b36b51737a3ee2c773340b # use-mise-action-v3.1.0 with: github_token: ${{ steps.token.outputs.token }} working_directory: ./mobile @@ -217,7 +217,7 @@ jobs: persist-credentials: false - name: Setup Mise - uses: immich-app/devtools/actions/use-mise@7b8610a904d57da241e4ddba17fa62b62b15aed4 # use-mise-action-v2.0.2 + uses: immich-app/devtools/actions/use-mise@3bca63ca3c15020293b36b51737a3ee2c773340b # use-mise-action-v3.1.0 with: github_token: ${{ steps.token.outputs.token }} working_directory: ./mobile diff --git a/.github/workflows/check-openapi.yml b/.github/workflows/check-openapi.yml index 6280f2ef14..8a64d15541 100644 --- a/.github/workflows/check-openapi.yml +++ b/.github/workflows/check-openapi.yml @@ -42,7 +42,7 @@ jobs: persist-credentials: false - name: Setup Mise - uses: immich-app/devtools/actions/use-mise@7b8610a904d57da241e4ddba17fa62b62b15aed4 # use-mise-action-v2.0.2 + uses: immich-app/devtools/actions/use-mise@3bca63ca3c15020293b36b51737a3ee2c773340b # use-mise-action-v3.1.0 with: github_token: ${{ github.token }} working_directory: ./mobile diff --git a/.github/workflows/cli.yml b/.github/workflows/cli.yml index 59c09a3fb2..821427aef5 100644 --- a/.github/workflows/cli.yml +++ b/.github/workflows/cli.yml @@ -43,7 +43,7 @@ jobs: token: ${{ steps.token.outputs.token }} - name: Setup Mise - uses: immich-app/devtools/actions/use-mise@7b8610a904d57da241e4ddba17fa62b62b15aed4 # use-mise-action-v2.0.2 + uses: immich-app/devtools/actions/use-mise@3bca63ca3c15020293b36b51737a3ee2c773340b # use-mise-action-v3.1.0 with: github_token: ${{ steps.token.outputs.token }} diff --git a/.github/workflows/docs-build.yml b/.github/workflows/docs-build.yml index df042eac54..af5293adce 100644 --- a/.github/workflows/docs-build.yml +++ b/.github/workflows/docs-build.yml @@ -66,7 +66,7 @@ jobs: token: ${{ steps.token.outputs.token }} - name: Setup Mise - uses: immich-app/devtools/actions/use-mise@7b8610a904d57da241e4ddba17fa62b62b15aed4 # use-mise-action-v2.0.2 + uses: immich-app/devtools/actions/use-mise@3bca63ca3c15020293b36b51737a3ee2c773340b # use-mise-action-v3.1.0 with: github_token: ${{ steps.token.outputs.token }} diff --git a/.github/workflows/docs-deploy.yml b/.github/workflows/docs-deploy.yml index 07025fd23a..089450c9af 100644 --- a/.github/workflows/docs-deploy.yml +++ b/.github/workflows/docs-deploy.yml @@ -138,7 +138,7 @@ jobs: token: ${{ steps.token.outputs.token }} - name: Setup Mise - uses: immich-app/devtools/actions/use-mise@7b8610a904d57da241e4ddba17fa62b62b15aed4 # use-mise-action-v2.0.2 + uses: immich-app/devtools/actions/use-mise@3bca63ca3c15020293b36b51737a3ee2c773340b # use-mise-action-v3.1.0 with: github_token: ${{ steps.token.outputs.token }} diff --git a/.github/workflows/docs-destroy.yml b/.github/workflows/docs-destroy.yml index cb640e0ae7..45d8b1c73f 100644 --- a/.github/workflows/docs-destroy.yml +++ b/.github/workflows/docs-destroy.yml @@ -29,7 +29,7 @@ jobs: token: ${{ steps.token.outputs.token }} - name: Setup Mise - uses: immich-app/devtools/actions/use-mise@7b8610a904d57da241e4ddba17fa62b62b15aed4 # use-mise-action-v2.0.2 + uses: immich-app/devtools/actions/use-mise@3bca63ca3c15020293b36b51737a3ee2c773340b # use-mise-action-v3.1.0 with: github_token: ${{ steps.token.outputs.token }} diff --git a/.github/workflows/fix-format.yml b/.github/workflows/fix-format.yml index 27d7e414f4..4cba413aec 100644 --- a/.github/workflows/fix-format.yml +++ b/.github/workflows/fix-format.yml @@ -28,7 +28,7 @@ jobs: token: ${{ steps.token.outputs.token }} - name: Setup Mise - uses: immich-app/devtools/actions/use-mise@7b8610a904d57da241e4ddba17fa62b62b15aed4 # use-mise-action-v2.0.2 + uses: immich-app/devtools/actions/use-mise@3bca63ca3c15020293b36b51737a3ee2c773340b # use-mise-action-v3.1.0 with: github_token: ${{ steps.token.outputs.token }} diff --git a/.github/workflows/prepare-release.yml b/.github/workflows/prepare-release.yml index d29af8763b..6a26f23472 100644 --- a/.github/workflows/prepare-release.yml +++ b/.github/workflows/prepare-release.yml @@ -67,7 +67,7 @@ jobs: ref: main - name: Setup Mise - uses: immich-app/devtools/actions/use-mise@7b8610a904d57da241e4ddba17fa62b62b15aed4 # use-mise-action-v2.0.2 + uses: immich-app/devtools/actions/use-mise@3bca63ca3c15020293b36b51737a3ee2c773340b # use-mise-action-v3.1.0 with: github_token: ${{ steps.token.outputs.token }} diff --git a/.github/workflows/sdk.yml b/.github/workflows/sdk.yml index 14029b6a70..416eaf7fa7 100644 --- a/.github/workflows/sdk.yml +++ b/.github/workflows/sdk.yml @@ -28,7 +28,7 @@ jobs: token: ${{ steps.token.outputs.token }} - name: Setup Mise - uses: immich-app/devtools/actions/use-mise@7b8610a904d57da241e4ddba17fa62b62b15aed4 # use-mise-action-v2.0.2 + uses: immich-app/devtools/actions/use-mise@3bca63ca3c15020293b36b51737a3ee2c773340b # use-mise-action-v3.1.0 with: github_token: ${{ steps.token.outputs.token }} diff --git a/.github/workflows/static_analysis.yml b/.github/workflows/static_analysis.yml index a92c9cafee..008730b514 100644 --- a/.github/workflows/static_analysis.yml +++ b/.github/workflows/static_analysis.yml @@ -61,7 +61,7 @@ jobs: token: ${{ steps.token.outputs.token }} - name: Setup Mise - uses: immich-app/devtools/actions/use-mise@7b8610a904d57da241e4ddba17fa62b62b15aed4 # use-mise-action-v2.0.2 + uses: immich-app/devtools/actions/use-mise@3bca63ca3c15020293b36b51737a3ee2c773340b # use-mise-action-v3.1.0 with: github_token: ${{ steps.token.outputs.token }} working_directory: ./mobile diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 1344754471..2bfa53618d 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -87,7 +87,7 @@ jobs: token: ${{ steps.token.outputs.token }} - name: Setup Mise - uses: immich-app/devtools/actions/use-mise@7b8610a904d57da241e4ddba17fa62b62b15aed4 # use-mise-action-v2.0.2 + uses: immich-app/devtools/actions/use-mise@3bca63ca3c15020293b36b51737a3ee2c773340b # use-mise-action-v3.1.0 with: github_token: ${{ steps.token.outputs.token }} @@ -115,7 +115,7 @@ jobs: token: ${{ steps.token.outputs.token }} - name: Setup Mise - uses: immich-app/devtools/actions/use-mise@7b8610a904d57da241e4ddba17fa62b62b15aed4 # use-mise-action-v2.0.2 + uses: immich-app/devtools/actions/use-mise@3bca63ca3c15020293b36b51737a3ee2c773340b # use-mise-action-v3.1.0 with: github_token: ${{ steps.token.outputs.token }} @@ -146,7 +146,7 @@ jobs: token: ${{ steps.token.outputs.token }} - name: Setup Mise - uses: immich-app/devtools/actions/use-mise@7b8610a904d57da241e4ddba17fa62b62b15aed4 # use-mise-action-v2.0.2 + uses: immich-app/devtools/actions/use-mise@3bca63ca3c15020293b36b51737a3ee2c773340b # use-mise-action-v3.1.0 with: github_token: ${{ steps.token.outputs.token }} @@ -177,7 +177,7 @@ jobs: token: ${{ steps.token.outputs.token }} - name: Setup Mise - uses: immich-app/devtools/actions/use-mise@7b8610a904d57da241e4ddba17fa62b62b15aed4 # use-mise-action-v2.0.2 + uses: immich-app/devtools/actions/use-mise@3bca63ca3c15020293b36b51737a3ee2c773340b # use-mise-action-v3.1.0 with: github_token: ${{ steps.token.outputs.token }} @@ -221,7 +221,7 @@ jobs: token: ${{ steps.token.outputs.token }} - name: Setup Mise - uses: immich-app/devtools/actions/use-mise@7b8610a904d57da241e4ddba17fa62b62b15aed4 # use-mise-action-v2.0.2 + uses: immich-app/devtools/actions/use-mise@3bca63ca3c15020293b36b51737a3ee2c773340b # use-mise-action-v3.1.0 with: github_token: ${{ steps.token.outputs.token }} @@ -259,7 +259,7 @@ jobs: token: ${{ steps.token.outputs.token }} - name: Setup Mise - uses: immich-app/devtools/actions/use-mise@7b8610a904d57da241e4ddba17fa62b62b15aed4 # use-mise-action-v2.0.2 + uses: immich-app/devtools/actions/use-mise@3bca63ca3c15020293b36b51737a3ee2c773340b # use-mise-action-v3.1.0 with: github_token: ${{ steps.token.outputs.token }} @@ -287,7 +287,7 @@ jobs: token: ${{ steps.token.outputs.token }} - name: Setup Mise - uses: immich-app/devtools/actions/use-mise@7b8610a904d57da241e4ddba17fa62b62b15aed4 # use-mise-action-v2.0.2 + uses: immich-app/devtools/actions/use-mise@3bca63ca3c15020293b36b51737a3ee2c773340b # use-mise-action-v3.1.0 with: github_token: ${{ steps.token.outputs.token }} @@ -337,7 +337,7 @@ jobs: token: ${{ steps.token.outputs.token }} - name: Setup Mise - uses: immich-app/devtools/actions/use-mise@7b8610a904d57da241e4ddba17fa62b62b15aed4 # use-mise-action-v2.0.2 + uses: immich-app/devtools/actions/use-mise@3bca63ca3c15020293b36b51737a3ee2c773340b # use-mise-action-v3.1.0 with: github_token: ${{ steps.token.outputs.token }} @@ -370,7 +370,7 @@ jobs: token: ${{ steps.token.outputs.token }} - name: Setup Mise - uses: immich-app/devtools/actions/use-mise@7b8610a904d57da241e4ddba17fa62b62b15aed4 # use-mise-action-v2.0.2 + uses: immich-app/devtools/actions/use-mise@3bca63ca3c15020293b36b51737a3ee2c773340b # use-mise-action-v3.1.0 with: github_token: ${{ steps.token.outputs.token }} @@ -589,7 +589,7 @@ jobs: token: ${{ steps.token.outputs.token }} - name: Setup Mise - uses: immich-app/devtools/actions/use-mise@7b8610a904d57da241e4ddba17fa62b62b15aed4 # use-mise-action-v2.0.2 + uses: immich-app/devtools/actions/use-mise@3bca63ca3c15020293b36b51737a3ee2c773340b # use-mise-action-v3.1.0 with: github_token: ${{ steps.token.outputs.token }} working_directory: ./mobile @@ -627,7 +627,7 @@ jobs: token: ${{ steps.token.outputs.token }} - name: Setup Mise - uses: immich-app/devtools/actions/use-mise@7b8610a904d57da241e4ddba17fa62b62b15aed4 # use-mise-action-v2.0.2 + uses: immich-app/devtools/actions/use-mise@3bca63ca3c15020293b36b51737a3ee2c773340b # use-mise-action-v3.1.0 with: github_token: ${{ steps.token.outputs.token }} @@ -658,7 +658,7 @@ jobs: token: ${{ steps.token.outputs.token }} - name: Setup Mise - uses: immich-app/devtools/actions/use-mise@7b8610a904d57da241e4ddba17fa62b62b15aed4 # use-mise-action-v2.0.2 + uses: immich-app/devtools/actions/use-mise@3bca63ca3c15020293b36b51737a3ee2c773340b # use-mise-action-v3.1.0 with: github_token: ${{ steps.token.outputs.token }} @@ -709,7 +709,7 @@ jobs: token: ${{ steps.token.outputs.token }} - name: Setup Mise - uses: immich-app/devtools/actions/use-mise@7b8610a904d57da241e4ddba17fa62b62b15aed4 # use-mise-action-v2.0.2 + uses: immich-app/devtools/actions/use-mise@3bca63ca3c15020293b36b51737a3ee2c773340b # use-mise-action-v3.1.0 with: github_token: ${{ steps.token.outputs.token }} @@ -767,7 +767,7 @@ jobs: token: ${{ steps.token.outputs.token }} - name: Setup Mise - uses: immich-app/devtools/actions/use-mise@7b8610a904d57da241e4ddba17fa62b62b15aed4 # use-mise-action-v2.0.2 + uses: immich-app/devtools/actions/use-mise@3bca63ca3c15020293b36b51737a3ee2c773340b # use-mise-action-v3.1.0 with: github_token: ${{ steps.token.outputs.token }} From 7cf904acbee12e6fb101a0e0c635236c5370c0ab Mon Sep 17 00:00:00 2001 From: "Weblate (bot)" Date: Tue, 16 Jun 2026 21:48:06 +0200 Subject: [PATCH 22/64] chore(web): update translations (#29036) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Translate-URL: https://hosted.weblate.org/projects/immich/immich/ Translate-URL: https://hosted.weblate.org/projects/immich/immich/ar/ Translate-URL: https://hosted.weblate.org/projects/immich/immich/be/ Translate-URL: https://hosted.weblate.org/projects/immich/immich/bg/ Translate-URL: https://hosted.weblate.org/projects/immich/immich/ca/ Translate-URL: https://hosted.weblate.org/projects/immich/immich/cs/ Translate-URL: https://hosted.weblate.org/projects/immich/immich/de/ Translate-URL: https://hosted.weblate.org/projects/immich/immich/en_GB/ Translate-URL: https://hosted.weblate.org/projects/immich/immich/es/ Translate-URL: https://hosted.weblate.org/projects/immich/immich/fr/ Translate-URL: https://hosted.weblate.org/projects/immich/immich/ga/ Translate-URL: https://hosted.weblate.org/projects/immich/immich/hu/ Translate-URL: https://hosted.weblate.org/projects/immich/immich/id/ Translate-URL: https://hosted.weblate.org/projects/immich/immich/it/ Translate-URL: https://hosted.weblate.org/projects/immich/immich/ja/ Translate-URL: https://hosted.weblate.org/projects/immich/immich/ko/ Translate-URL: https://hosted.weblate.org/projects/immich/immich/lt/ Translate-URL: https://hosted.weblate.org/projects/immich/immich/lv/ Translate-URL: https://hosted.weblate.org/projects/immich/immich/ms/ Translate-URL: https://hosted.weblate.org/projects/immich/immich/nb_NO/ Translate-URL: https://hosted.weblate.org/projects/immich/immich/nl/ Translate-URL: https://hosted.weblate.org/projects/immich/immich/pl/ Translate-URL: https://hosted.weblate.org/projects/immich/immich/pt/ Translate-URL: https://hosted.weblate.org/projects/immich/immich/pt_BR/ Translate-URL: https://hosted.weblate.org/projects/immich/immich/ru/ Translate-URL: https://hosted.weblate.org/projects/immich/immich/sk/ Translate-URL: https://hosted.weblate.org/projects/immich/immich/sq/ Translate-URL: https://hosted.weblate.org/projects/immich/immich/uk/ Translate-URL: https://hosted.weblate.org/projects/immich/immich/yue_Hant/ Translate-URL: https://hosted.weblate.org/projects/immich/immich/zh_Hans/ Translate-URL: https://hosted.weblate.org/projects/immich/immich/zh_Hant/ Translation: Immich/immich Co-authored-by: Aindriú Mac Giolla Eoin Co-authored-by: Arif Budiman Co-authored-by: Bananenbrot Co-authored-by: Charles Chase Co-authored-by: Dan Bishop Co-authored-by: Dennis Co-authored-by: DevServs Co-authored-by: Dániel Gál Co-authored-by: Enrico Jaupi <78313537@itiscastelli.onmicrosoft.com> Co-authored-by: Erison Silva Co-authored-by: Fatah Rokbi Co-authored-by: Felipe Cabrera Co-authored-by: Hurricane_32 Co-authored-by: Jayden Lo Co-authored-by: Jozef Gaal Co-authored-by: Mees Frensel Co-authored-by: MrKoby07 Co-authored-by: Mārtiņš Bruņenieks Co-authored-by: Nagy Krisztián Co-authored-by: Nicola Bortoletto Co-authored-by: Nicolas Ceballos Co-authored-by: Paul Comte Co-authored-by: Pavel Miniutka Co-authored-by: Popa Co-authored-by: SAHOON KIM Co-authored-by: Sylvain Pichon Co-authored-by: Unimpeded Lemur Co-authored-by: User 123456789 Co-authored-by: Vegard Fladby Co-authored-by: anton garcias Co-authored-by: azuziii Co-authored-by: dimetrius Co-authored-by: muziqaz Co-authored-by: rubes Co-authored-by: waclaw66 --- i18n/ar.json | 5 + i18n/be.json | 8 + i18n/bg.json | 26 +- i18n/ca.json | 25 +- i18n/cs.json | 4 +- i18n/de.json | 16 +- i18n/en_GB.json | 2562 +++++++++++++++++++++++++++++++++++++++++++- i18n/es.json | 9 +- i18n/fr.json | 13 +- i18n/ga.json | 25 +- i18n/hu.json | 10 +- i18n/id.json | 30 +- i18n/it.json | 80 +- i18n/ja.json | 8 + i18n/ko.json | 108 +- i18n/lt.json | 42 +- i18n/lv.json | 3 + i18n/ms.json | 11 + i18n/nb_NO.json | 26 +- i18n/nl.json | 23 +- i18n/pl.json | 13 +- i18n/pt.json | 25 +- i18n/pt_BR.json | 4 +- i18n/ru.json | 7 +- i18n/sk.json | 8 +- i18n/sq.json | 180 +++- i18n/uk.json | 6 + i18n/yue_Hant.json | 144 ++- i18n/zh_Hans.json | 30 +- i18n/zh_Hant.json | 93 +- 30 files changed, 3408 insertions(+), 136 deletions(-) diff --git a/i18n/ar.json b/i18n/ar.json index 89845e3bcb..0f9e98efc7 100644 --- a/i18n/ar.json +++ b/i18n/ar.json @@ -79,6 +79,7 @@ "cron_expression_description": "اضبط الفاصل الزمني للفحص باستخدام تنسيق cron. لمزيد من المعلومات يُرجى الرجوع إلى Crontab Guru على سبيل المثال", "cron_expression_presets": "الإعدادات المسبقة لتعبير Cron", "disable_login": "تعطيل تسجيل الدخول", + "download_csv": "حمل CSV", "duplicate_detection_job_description": "بدء التعلم الآلي على المحتوى للعثور على الصور المتشابهة. يعتمد على البحث الذكي", "exclusion_pattern_description": "تتيح لك أنماط الاستبعاد تجاهل الملفات والمجلدات عند فحص مكتبتك. يعد هذا مفيدًا إذا كان لديك مجلدات تحتوي على ملفات لا تريد استيرادها، مثل ملفات RAW.", "export_config_as_json_description": "تحميل اعدادات النظام الحالية كملف بصيغة JSON", @@ -191,6 +192,10 @@ "maintenance_delete_backup": "حذف النسخ الاحتياطي", "maintenance_delete_backup_description": "هذا الملف سيتم حذفه بشكل لا رجعه فيه.", "maintenance_delete_error": "فشل حذف النسخ الاحتياطي.", + "maintenance_integrity_check_all": "تحديد الكل", + "maintenance_integrity_checksum_mismatch": "عدم تطابق رمز التحقق", + "maintenance_integrity_missing_file": "الملفات المفقودة", + "maintenance_integrity_missing_file_job": "التحقق من الملفات المفقودة", "maintenance_restore_backup": "استعادة النسخ الاحتياطي", "maintenance_restore_backup_description": "سيتم مسح بيانات Immich واستعادتها من النسخة الاحتياطي المختار. سيتم إنشاء نسخة احتياطية قبل المتابعة.", "maintenance_restore_backup_different_version": "هذا النسخ الاحتياطي تم انشائه باستخدام اصدار مختلف من Immich!", diff --git a/i18n/be.json b/i18n/be.json index 0491582a33..c3901e8c1b 100644 --- a/i18n/be.json +++ b/i18n/be.json @@ -79,6 +79,7 @@ "cron_expression_description": "Задайце інтэрвал сканавання, выкарыстоўваючы фармат cron. Для атрымання дадатковай інфармацыі, звярніцеся, напрыклад, да Crontab Guru", "cron_expression_presets": "Прадустаноўкі выразаў Cron", "disable_login": "Адключыць уваход", + "download_csv": "Спампаваць CSV", "duplicate_detection_job_description": "Запусціць машыннае навучанне на аб’ектах для выяўлення падобных відарысаў. Залежыць ад Smart Search", "exclusion_pattern_description": "Шаблоны выключэння дазваляюць ігнараваць файлы і папкі пры сканаванні вашай бібліятэкі. Гэта карысна, калі ў вас ёсць папкі, якія змяшчаюць файлы, якія вы не хочаце імпартаваць, напрыклад, файлы RAW.", "export_config_as_json_description": "Захаваць бягучую канфігурацыю сістэмы ў файл JSON", @@ -191,6 +192,13 @@ "maintenance_delete_backup": "Выдаліць рэзервовую копію", "maintenance_delete_backup_description": "Гэты файл будзе беззваротна выдалены.", "maintenance_delete_error": "Не атрымалася выдаліць рэзервовую копію.", + "maintenance_integrity_check_all": "Праверыць усе", + "maintenance_integrity_checksum_mismatch": "Несупадзенне кантрольнай сумы", + "maintenance_integrity_checksum_mismatch_job": "Праверка на несупадзенне кантрольных сум", + "maintenance_integrity_checksum_mismatch_refresh_job": "Абнавіць справаздачы аб несупадзенні кантрольных сум", + "maintenance_integrity_missing_file": "Адсутныя файлы", + "maintenance_integrity_missing_file_job": "Праверка наяўнасці адсутных файлаў", + "maintenance_integrity_missing_file_refresh_job": "Абнавіць справаздачы аб адсутных файлах", "maintenance_restore_backup": "Аднавіць рэзервовую копію", "maintenance_restore_backup_description": "Immich будзе сцёрты і адноўлены з абранай рэзервовай копіі. Перад працягам будзе створана рэзервовая копія.", "maintenance_restore_backup_different_version": "Гэтая рэзервовая копія была створана з для іншай версіі Immich!", diff --git a/i18n/bg.json b/i18n/bg.json index 88f61f626b..b4aa9a0aba 100644 --- a/i18n/bg.json +++ b/i18n/bg.json @@ -2273,23 +2273,23 @@ "sort_created": "Дата на създаване", "sort_items": "Брой елементи", "sort_modified": "Дата на промяна", - "sort_newest": "Най-нови снимки", - "sort_oldest": "Най-старата снимка", + "sort_newest": "Най-нова снимка", + "sort_oldest": "Най-стара снимка", "sort_people_by_similarity": "Сортиране на хора по прилика", - "sort_recent": "Най-новата снимка", + "sort_recent": "Най-скорошна снимка", "sort_title": "Заглавие", "source": "Код", - "stack": "Събери", + "stack": "Групирай", "stack_action_prompt": "{count} са групирани", - "stack_duplicates": "Подреждане на дубликати", - "stack_select_one_photo": "Избери една главна снимка за събраните снимки", - "stack_selected_photos": "Подреждане на избрани снимки", - "stacked_assets_count": "Събрани {count, plural, one {# елемент} other {# елементи}}", - "stacktrace": "Следа на събраните", - "start": "Старт", + "stack_duplicates": "Групирай дубликати", + "stack_select_one_photo": "Избери главна снимка за групировката", + "stack_selected_photos": "Групиране на избрани снимки", + "stacked_assets_count": "Групиран(и) {count, plural, one {# елемент} other {# елементи}}", + "stacktrace": "Проследяване на стека (stacktrace)", + "start": "Начало", "start_date": "Начална дата", "start_date_before_end_date": "Началната дата трябва да бъде преди крайната дата", - "state": "Щат", + "state": "Област (щат)", "status": "Статус", "step_delete": "Премахни стъпката", "step_delete_confirm": "Сигурни ли сте, че искате да премахнете тази стъпка?", @@ -2389,11 +2389,13 @@ "trash_page_title": "В коша ({count})", "trashed_items_will_be_permanently_deleted_after": "Изхвърлените в кошчето елементи ще бъдат изтрити за постоянно след {days, plural, one {# ден} other {# дни}}.", "trigger": "Тригер", + "trigger_asset_metadata_extraction": "Извличане на метаданни от елементи", + "trigger_asset_metadata_extraction_description": "Задействан, когато EXIF метаданните от даден елемент са извлечени", "trigger_asset_uploaded": "Качване на файлове", "trigger_asset_uploaded_description": "Сработва при зареждане на нов обект", "trigger_description": "Събитие, което стартира работния процес", "trigger_person_recognized": "Разпознато е лице", - "trigger_person_recognized_description": "Сработва при разпознаване на лице", + "trigger_person_recognized_description": "Задействан при разпознаване на лице", "trigger_type": "Тип на тригера", "troubleshoot": "Отстраняване на проблеми", "type": "Тип", diff --git a/i18n/ca.json b/i18n/ca.json index 9a4dddbaf5..3c3a312fbf 100644 --- a/i18n/ca.json +++ b/i18n/ca.json @@ -79,6 +79,7 @@ "cron_expression_description": "Estableix l'interval d'escaneig amb el format cron. Per obtenir més informació, consulteu, p.e Crontab Guru", "cron_expression_presets": "Ajustos predefinits d'expressions Cron", "disable_login": "Deshabiliteu l'inici de sessió", + "download_csv": "Descarregar CSV", "duplicate_detection_job_description": "Executa l'aprenentatge automàtic en els elements per a detectar imatges semblants. Fa servir la cerca intel·ligent", "exclusion_pattern_description": "Els patrons d'exclusió permeten ignorar fitxers i carpetes quan escanegeu una llibreria. Això és útil si teniu carpetes que contenen fitxer que no voleu importar, com els fitxers RAW.", "export_config_as_json_description": "Baixa la configuració actual del sistema com a fitxer JSON", @@ -191,6 +192,17 @@ "maintenance_delete_backup": "Elimina la còpia de seguretat", "maintenance_delete_backup_description": "Aquest fitxer s'eliminarà de forma permanent.", "maintenance_delete_error": "No s'ha pogut suprimir la còpia de seguretat.", + "maintenance_integrity_check_all": "Verificar tot", + "maintenance_integrity_checksum_mismatch": "Checksum incorrecte", + "maintenance_integrity_checksum_mismatch_job": "Comprovar checksums", + "maintenance_integrity_checksum_mismatch_refresh_job": "Actualitzar errors de checksums", + "maintenance_integrity_missing_file": "Manquen fitxers", + "maintenance_integrity_missing_file_job": "Verificar fitxers que falten", + "maintenance_integrity_missing_file_refresh_job": "Refrescar informe de fitxers desapareguts", + "maintenance_integrity_report": "Informe Integritat", + "maintenance_integrity_untracked_file": "Arxius no rastrejats", + "maintenance_integrity_untracked_file_job": "Consulta de fitxers no rastrejats", + "maintenance_integrity_untracked_file_refresh_job": "Actualitza els informes de fitxers no rastrejats", "maintenance_restore_backup": "Restaura la còpia de seguretat", "maintenance_restore_backup_description": "Immich s'esborrarà i es restaurarà des de la còpia de seguretat escollida. Es crearà una còpia de seguretat abans de continuar.", "maintenance_restore_backup_different_version": "Aquesta còpia de seguretat s'ha creat amb una versió diferent d'Immich!", @@ -915,6 +927,8 @@ "deduplicate_all": "Desduplica-ho tot", "default_locale": "Configuració regional predeterminada", "default_locale_description": "Format de dades i números en funció de la configuració local", + "default_quality_subtitle": "Qualitat utilitzada a l’hora de tocar la compartició. Premeu el botó de compartir per triar cada vegada.", + "default_share_quality": "Qualitat de comparticio per defecte", "delete": "Esborrar", "delete_action_confirmation_message": "Segur que vols eliminar aquest recurs? Aquesta acció el mourà a la paperera del servidor, i et preguntarà si el vols eliminar localment", "delete_action_prompt": "{count} eliminats", @@ -1224,6 +1238,7 @@ "failed": "Fallat", "failed_count": "Fallits: {count}", "failed_to_authenticate": "No s'ha pogut autenticar", + "failed_to_delete_file": "No s'ha pogut esborrar el fitxer", "failed_to_load_assets": "Error carregant recursos", "failed_to_load_folder": "No s'ha pogut carregar la carpeta", "favorite": "Preferit", @@ -1354,6 +1369,7 @@ "individual_share": "Compartit individualment", "individual_shares": "Espais individuals", "info": "Informació", + "integrity_checks": "Verificacions d'integritat", "interval": { "day_at_onepm": "Cada dia a les 13h", "hours": "Cada {hours, plural, one {hour} other {{hours, number} hours}}", @@ -1426,6 +1442,7 @@ "linked_oauth_account": "Compte OAuth enllaçat", "list": "Llista", "live": "En viu", + "load_more": "Carregar més", "loading": "Carregant", "loading_search_results_failed": "No s'han pogut carregar els resultats de la cerca", "local": "Local", @@ -2084,6 +2101,7 @@ "select_person": "Seleccionar persona", "select_person_to_tag": "Selecciona una persona per etiquetar", "select_photos": "Tria fotografies", + "select_quality": "Selecciona qualitat", "select_trash_all": "Envia la selecció a la paperera", "select_user_for_sharing_page_err_album": "Error al crear l'àlbum", "selected": "Seleccionat", @@ -2147,6 +2165,8 @@ "share_assets_selected": "{count} seleccionats", "share_dialog_preparing": "S'està preparant...", "share_link": "Compartir Enllaç", + "share_original": "Ús original (gran)", + "share_preview": "Ús de la miniatura (petit)", "shared": "Compartit", "shared_album_activities_input_disable": "Els comentaris estan desactivats", "shared_album_activity_remove_content": "Voleu eliminar aquesta activitat?", @@ -2248,6 +2268,7 @@ "slideshow_repeat_description": "Torna al principi quan acaba la presentació de diapositives", "slideshow_settings": "Configuració de diapositives", "smart_album": "Àlbum inteŀligent", + "some_assets_already_have_a_location_warning": "Alguns dels actius seleccionats ja tenen una ubicació", "sort_albums_by": "Ordena àlbums per...", "sort_created": "Data de creació", "sort_items": "Quantitat d'elements", @@ -2368,11 +2389,13 @@ "trash_page_title": "Paperera ({count})", "trashed_items_will_be_permanently_deleted_after": "Els elements que s'enviïn a la paperera s'eliminaran permanentment després de {days, plural, one {# dia} other {# dies}}.", "trigger": "Disparador", + "trigger_asset_metadata_extraction": "Extracció de metadades d'actius", + "trigger_asset_metadata_extraction_description": "Disparat quan s'extreuen les metadades EXIF d'un actiu", "trigger_asset_uploaded": "Càrrega de Mitjans", "trigger_asset_uploaded_description": "Es dispara quan un nou mitjà es puge al servidor", "trigger_description": "L'esdeveniment que inicia l'automatització", "trigger_person_recognized": "Persona identificada", - "trigger_person_recognized_description": "Es dispara quan es detecta una persona", + "trigger_person_recognized_description": "Disparat quan es reconeix una persona", "trigger_type": "Tipus de disparador", "troubleshoot": "Solució de problemes", "type": "Tipus", diff --git a/i18n/cs.json b/i18n/cs.json index af45e5ede1..44b9cf8f36 100644 --- a/i18n/cs.json +++ b/i18n/cs.json @@ -2390,12 +2390,12 @@ "trashed_items_will_be_permanently_deleted_after": "Smazané položky budou trvale odstraněny po {days, plural, one {# dni} other {# dnech}}.", "trigger": "Spouštěč", "trigger_asset_metadata_extraction": "Extrakce metadat položek", - "trigger_asset_metadata_extraction_description": "Spustí se při extrakci EXIF údajů z mediálního souboru", + "trigger_asset_metadata_extraction_description": "Spustí se při extrakci EXIF metadat z mediálního souboru", "trigger_asset_uploaded": "Nahrání položky", "trigger_asset_uploaded_description": "Spustí se při nahrání nového souboru", "trigger_description": "Událost, která spustí pracovní postup", "trigger_person_recognized": "Osoba rozpoznána", - "trigger_person_recognized_description": "Spustí se, když je objevena osoba", + "trigger_person_recognized_description": "Spustí se, když je rozpoznána osoba", "trigger_type": "Typ spouštěče", "troubleshoot": "Diagnostika", "type": "Typ", diff --git a/i18n/de.json b/i18n/de.json index c218d9b0db..dddb42e3f6 100644 --- a/i18n/de.json +++ b/i18n/de.json @@ -9,7 +9,7 @@ "actions": "Aktionen", "active": "Aktiv", "active_count": "Aktive: {count}", - "activity": "Ansicht", + "activity": "Aktivität", "activity_changed": "Aktivität ist {enabled, select, true {aktiviert} other {deaktiviert}}", "add": "Hinzufügen", "add_a_description": "Beschreibung hinzufügen", @@ -55,7 +55,7 @@ "background_task_job": "Hintergrundaufgaben", "backup_database": "Datenbanksicherung erstellen", "backup_database_enable_description": "Datenbank regelmäßig sichern", - "backup_keep_last_amount": "Anzahl der aufzubewahrenden früheren Sicherungen", + "backup_keep_last_amount": "Anzahl der zu speichernden vorherigen Sicherungen", "backup_onboarding_1_description": "Offsite-Kopie in der Cloud oder an einem anderen physischen Ort.", "backup_onboarding_2_description": "Lokale Kopien auf verschiedenen Geräten. Dazu gehören die Hauptdateien und eine lokale Sicherung dieser Dateien.", "backup_onboarding_3_description": "Kopien deiner Daten inklusive Originaldateien. Dies umfasst 1 Kopie an einem anderen Ort und 2 lokale Kopien.", @@ -311,8 +311,8 @@ "paths_validated_successfully": "Alle Pfade erfolgreich überprüft", "person_cleanup_job": "Personen aufräumen", "queue_details": "Warteschlangendetails", - "queues": "Auftrags-Warteschlangen", - "queues_page_description": "Auftragswarteschlangen-Adminseite", + "queues": "Auftrags-Schlangen", + "queues_page_description": "Auftragsschlangen-Adminseite", "quota_size_gib": "Kontingent (GiB)", "refreshing_all_libraries": "Alle Bibliotheken aktualisieren", "registration": "Admin-Registrierung", @@ -562,7 +562,7 @@ "app_download_links": "App Download-Links", "app_settings": "App-Einstellungen", "app_stores": "App Stores", - "app_update_available": "App Update verfügbar", + "app_update_available": "App-Update verfügbar", "appears_in": "Enthalten in", "apply_count": "Anwenden ({count, number})", "archive": "Archiv", @@ -2166,7 +2166,7 @@ "share_dialog_preparing": "Vorbereiten...", "share_link": "Link teilen", "share_original": "Original verwenden (groß)", - "share_preview": "Verwenden Sie Thumbnail (klein)", + "share_preview": "Thumbnail verwenden (klein)", "shared": "Geteilt", "shared_album_activities_input_disable": "Kommentare sind deaktiviert", "shared_album_activity_remove_content": "Möchtest du diese Aktivität entfernen?", @@ -2395,7 +2395,7 @@ "trigger_asset_uploaded_description": "Löst aus, wenn eine neue Datei hochgeladen wurde", "trigger_description": "Ein Ereignis, das den Workflow startet", "trigger_person_recognized": "Person erkannt", - "trigger_person_recognized_description": "Löst aus, wenn eine Person erkannt wird", + "trigger_person_recognized_description": "Löst aus, wenn eine Person erkannt wurde", "trigger_type": "Auslöser-Typ", "troubleshoot": "Fehler beheben", "type": "Typ", @@ -2437,6 +2437,7 @@ "updated_password": "Passwort aktualisiert", "upload": "Hochladen", "upload_concurrency": "Parallelität beim Hochladen", + "upload_day_count": "{date}: {count, plural, one {# Upload} other {# Uploads}}", "upload_details": "Upload Details", "upload_dialog_info": "Willst du die ausgewählten Elemente auf dem Server sichern?", "upload_dialog_title": "Element hochladen", @@ -2453,6 +2454,7 @@ "uploading": "Wird hochgeladen", "uploading_media": "Medien werden hochgeladen", "uploads": "Uploads", + "uploads_count": "{count, plural, one {# Upload} other {# Uploads}}", "url": "URL", "usage": "Verwendung", "use_biometric": "Biometrie verwenden", diff --git a/i18n/en_GB.json b/i18n/en_GB.json index 0967ef424b..5129a334ef 100644 --- a/i18n/en_GB.json +++ b/i18n/en_GB.json @@ -1 +1,2561 @@ -{} +{ + "about": "About", + "account": "Account", + "account_settings": "Account Settings", + "acknowledge": "Acknowledge", + "action": "Action", + "action_common_update": "Update", + "action_description": "A set of action to perform on the filtered assets", + "actions": "Actions", + "active": "Active", + "active_count": "Active: {count}", + "activity": "Activity", + "activity_changed": "Activity is {enabled, select, true {enabled} other {disabled}}", + "add": "Add", + "add_a_description": "Add a description", + "add_a_location": "Add a location", + "add_a_name": "Add a name", + "add_a_title": "Add a title", + "add_action": "Add action", + "add_action_description": "Click to add an action to perform", + "add_assets": "Add assets", + "add_birthday": "Add a birthday", + "add_endpoint": "Add endpoint", + "add_exclusion_pattern": "Add exclusion pattern", + "add_location": "Add location", + "add_more_users": "Add more users", + "add_partner": "Add partner", + "add_path": "Add path", + "add_photos": "Add photos", + "add_step": "Add step", + "add_tag": "Add tag", + "add_to": "Add to…", + "add_to_album": "Add to album", + "add_to_album_bottom_sheet_added": "Added to {album}", + "add_to_album_bottom_sheet_already_exists": "Already in {album}", + "add_to_album_bottom_sheet_some_local_assets": "Some local assets could not be added to album", + "add_to_album_toggle": "Toggle selection for {album}", + "add_to_albums": "Add to albums", + "add_to_albums_count": "Add to albums ({count})", + "add_to_bottom_bar": "Add to", + "add_to_shared_album": "Add to shared album", + "add_upload_to_stack": "Add upload to stack", + "add_url": "Add URL", + "added_to_archive": "Added to archive", + "added_to_favorites": "Added to favourites", + "added_to_favorites_count": "Added {count, number} to favourites", + "admin": { + "add_exclusion_pattern_description": "Add exclusion patterns. Globbing using *, **, and ? is supported. To ignore all files in any directory named \"Raw\", use \"**/Raw/**\". To ignore all files ending in \".tif\", use \"**/*.tif\". To ignore an absolute path, use \"/path/to/ignore/**\".", + "admin_user": "Admin User", + "asset_offline_description": "This external library asset is no longer found on disk and has been moved to the bin. If the file was moved within the library, check your timeline for the new corresponding asset. To restore this asset, please ensure that the file path below can be accessed by Immich and scan the library.", + "authentication_settings": "Authentication Settings", + "authentication_settings_description": "Manage password, OAuth, and other authentication settings", + "authentication_settings_disable_all": "Are you sure you want to disable all login methods? Login will be completely disabled.", + "authentication_settings_reenable": "To re-enable, use a Server Command.", + "background_task_job": "Background Tasks", + "backup_database": "Create Database Dump", + "backup_database_enable_description": "Enable database dumps", + "backup_keep_last_amount": "Amount of previous dumps to keep", + "backup_onboarding_1_description": "offsite copy in the cloud or at another physical location.", + "backup_onboarding_2_description": "local copies on different devices. This includes the main files and a backup of those files locally.", + "backup_onboarding_3_description": "total copies of your data, including the original files. This includes 1 offsite copy and 2 local copies.", + "backup_onboarding_description": "A 3-2-1 backup strategy is recommended to protect your data. You should keep copies of your uploaded photos/videos as well as the Immich database for a comprehensive backup solution.", + "backup_onboarding_footer": "For more information about backing up Immich, please refer to the documentation.", + "backup_onboarding_parts_title": "A 3-2-1 backup includes:", + "backup_onboarding_title": "Backups", + "backup_settings": "Database Dump Settings", + "backup_settings_description": "Manage database dump settings.", + "cleared_jobs": "Cleared jobs for: {job}", + "config_set_by_file": "Config is currently set by a config file", + "confirm_delete_library": "Are you sure you want to delete {library} library?", + "confirm_delete_library_assets": "Are you sure you want to delete this library? This will delete {count, plural, one {# contained asset} other {all # contained assets}} from Immich and cannot be undone. Files will remain on disk.", + "confirm_email_below": "To confirm, type \"{email}\" below", + "confirm_reprocess_all_faces": "Are you sure you want to reprocess all faces? This will also clear named people.", + "confirm_user_password_reset": "Are you sure you want to reset {user}'s password?", + "confirm_user_pin_code_reset": "Are you sure you want to reset {user}'s PIN code?", + "copy_config_to_clipboard_description": "Copy the current system config as a JSON object to the clipboard", + "create_job": "Create job", + "cron_expression": "Cron expression", + "cron_expression_description": "Set the scanning interval using the cron format. For more information please refer to e.g. Crontab Guru", + "cron_expression_presets": "Cron expression presets", + "disable_login": "Disable login", + "download_csv": "Download CSV", + "duplicate_detection_job_description": "Run machine learning on assets to detect similar images. Relies on Smart Search", + "exclusion_pattern_description": "Exclusion patterns lets you ignore files and folders when scanning your library. This is useful if you have folders that contain files you don't want to import, such as RAW files.", + "export_config_as_json_description": "Download the current system config as a JSON file", + "external_libraries_page_description": "Admin external library page", + "face_detection": "Face detection", + "face_detection_description": "Detect the faces in assets using machine learning. For videos, only the thumbnail is considered. \"Refresh\" (re-)processes all assets. \"Reset\" additionally clears all current face data. \"Missing\" queues assets that haven't been processed yet. Detected faces will be queued for Facial Recognition after Face Detection is complete, grouping them into existing or new people.", + "facial_recognition_job_description": "Group detected faces into people. This step runs after Face Detection is complete. \"Reset\" (re-)clusters all faces. \"Missing\" queues faces that don't have a person assigned.", + "failed_job_command": "Command {command} failed for job: {job}", + "force_delete_user_warning": "WARNING: This will immediately remove the user and all assets. This cannot be undone and the files cannot be recovered.", + "image_format": "Format", + "image_format_description": "WebP produces smaller files than JPEG, but is slower to encode.", + "image_fullsize_description": "Full-size image with stripped metadata, used when zoomed in", + "image_fullsize_enabled": "Enable full-size image generation", + "image_fullsize_enabled_description": "Generate full-size image for non-web-friendly formats. When \"Prefer embedded preview\" is enabled, embedded previews are used directly without conversion. Does not affect web-friendly formats like JPEG.", + "image_fullsize_quality_description": "Full-size image quality from 1-100. Higher is better, but produces larger files.", + "image_fullsize_title": "Full-size Image Settings", + "image_prefer_embedded_preview": "Prefer embedded preview", + "image_prefer_embedded_preview_setting_description": "Use embedded previews in RAW photos as the input to image processing and when available. This can produce more accurate colours for some images, but the quality of the preview is camera-dependent and the image may have more compression artifacts.", + "image_prefer_wide_gamut": "Prefer wide gamut", + "image_prefer_wide_gamut_setting_description": "Use Display P3 for thumbnails. This better preserves the vibrance of images with wide colourspaces, but images may appear differently on old devices with an old browser version. sRGB images are kept as sRGB to avoid colour shifts.", + "image_preview_description": "Medium-size image with stripped metadata, used when viewing a single asset and for machine learning", + "image_preview_quality_description": "Preview quality from 1-100. Higher is better, but produces larger files and can reduce app responsiveness. Setting a low value may affect machine learning quality.", + "image_preview_title": "Preview Settings", + "image_progressive": "Progressive", + "image_progressive_description": "Encode JPEG images progressively for gradual loading display. This has no effect on WebP images.", + "image_quality": "Quality", + "image_resolution": "Resolution", + "image_resolution_description": "Higher resolutions can preserve more detail but take longer to encode, have larger file sizes and can reduce app responsiveness.", + "image_settings": "Image Settings", + "image_settings_description": "Manage the quality and resolution of generated images", + "image_thumbnail_description": "Small thumbnail with stripped metadata, used when viewing groups of photos like the main timeline", + "image_thumbnail_quality_description": "Thumbnail quality from 1-100. Higher is better, but produces larger files and can reduce app responsiveness.", + "image_thumbnail_title": "Thumbnail Settings", + "import_config_from_json_description": "Import system config by uploading a JSON config file", + "job_concurrency": "{job} concurrency", + "job_created": "Job created", + "job_not_concurrency_safe": "This job is not concurrency-safe.", + "job_settings": "Job Settings", + "job_settings_description": "Manage job concurrency", + "jobs_delayed": "{jobCount, plural, other {# delayed}}", + "jobs_failed": "{jobCount, plural, other {# failed}}", + "jobs_over_time": "Jobs over time", + "library_created": "Created library: {library}", + "library_deleted": "Library deleted", + "library_details": "Library details", + "library_folder_description": "Specify a folder to import. This folder, including subfolders, will be scanned for images and videos.", + "library_remove_exclusion_pattern_prompt": "Are you sure you want to remove this exclusion pattern?", + "library_remove_folder_prompt": "Are you sure you want to remove this import folder?", + "library_scanning": "Periodic Scanning", + "library_scanning_description": "Configure periodic library scanning", + "library_scanning_enable_description": "Enable periodic library scanning", + "library_settings": "External Library", + "library_settings_description": "Manage external library settings", + "library_tasks_description": "Scan external libraries for new and/or changed assets", + "library_updated": "Updated library", + "library_watching_enable_description": "Watch external libraries for file changes", + "library_watching_settings": "Library watching [EXPERIMENTAL]", + "library_watching_settings_description": "Automatically watch for changed files", + "logging_enable_description": "Enable logging", + "logging_level_description": "When enabled, what log level to use.", + "logging_settings": "Logging", + "machine_learning_availability_checks": "Availability checks", + "machine_learning_availability_checks_description": "Automatically detect and prefer available machine learning servers", + "machine_learning_availability_checks_enabled": "Enable availability checks", + "machine_learning_availability_checks_interval": "Check interval", + "machine_learning_availability_checks_interval_description": "Interval in milliseconds between availability checks", + "machine_learning_availability_checks_timeout": "Request timeout", + "machine_learning_availability_checks_timeout_description": "Timeout in milliseconds for availability checks", + "machine_learning_clip_model": "CLIP model", + "machine_learning_clip_model_description": "The name of a CLIP model listed here. Note that you must re-run the 'Smart Search' job for all images upon changing a model.", + "machine_learning_duplicate_detection": "Duplicate Detection", + "machine_learning_duplicate_detection_enabled": "Enable duplicate detection", + "machine_learning_duplicate_detection_enabled_description": "If disabled, exactly identical assets will still be de-duplicated.", + "machine_learning_duplicate_detection_setting_description": "Use CLIP embeddings to find likely duplicates", + "machine_learning_enabled": "Enable machine learning", + "machine_learning_enabled_description": "If disabled, all ML features will be disabled regardless of the below settings.", + "machine_learning_facial_recognition": "Facial Recognition", + "machine_learning_facial_recognition_description": "Detect, recognise and group faces in images", + "machine_learning_facial_recognition_model": "Facial recognition model", + "machine_learning_facial_recognition_model_description": "Models are listed in descending order of size. Larger models are slower and use more memory, but produce better results. Note that you must re-run the Face Detection job for all images upon changing a model.", + "machine_learning_facial_recognition_setting": "Enable facial recognition", + "machine_learning_facial_recognition_setting_description": "If disabled, images will not be encoded for facial recognition and will not populate the People section in the Explore page.", + "machine_learning_max_detection_distance": "Maximum detection distance", + "machine_learning_max_detection_distance_description": "Maximum distance between two images to consider them duplicates, ranging from 0.001-0.1. Higher values will detect more duplicates, but may result in false positives.", + "machine_learning_max_recognition_distance": "Maximum recognition distance", + "machine_learning_max_recognition_distance_description": "Maximum distance between two faces to be considered the same person, ranging from 0-2. Lowering this can prevent labializing two people as the same person, while raising it can prevent labelling the same person as two different people. Note that it is easier to merge two people than to split one person in two, so err on the side of a lower threshold when possible.", + "machine_learning_min_detection_score": "Minimum detection score", + "machine_learning_min_detection_score_description": "Minimum confidence score for a face to be detected from 0-1. Lower values will detect more faces but may result in false positives.", + "machine_learning_min_recognized_faces": "Minimum recognised faces", + "machine_learning_min_recognized_faces_description": "The minimum number of recognised faces for a person to be created. Increasing this makes Facial Recognition more precise at the cost of increasing the chance that a face is not assigned to a person.", + "machine_learning_ocr": "OCR", + "machine_learning_ocr_description": "Use machine learning to recognise text in images", + "machine_learning_ocr_enabled": "Enable OCR", + "machine_learning_ocr_enabled_description": "If disabled, images will not undergo text recognition.", + "machine_learning_ocr_max_resolution": "Maximum resolution", + "machine_learning_ocr_max_resolution_description": "Previews above this resolution will be resized while preserving aspect ratio. Higher values are more accurate, but take longer to process and use more memory.", + "machine_learning_ocr_min_detection_score": "Minimum detection score", + "machine_learning_ocr_min_detection_score_description": "Minimum confidence score for text to be detected from 0-1. Lower values will detect more text but may result in false positives.", + "machine_learning_ocr_min_recognition_score": "Minimum recognition score", + "machine_learning_ocr_min_score_recognition_description": "Minimum confidence score for detected text to be recognised from 0-1. Lower values will recognise more text but may result in false positives.", + "machine_learning_ocr_model": "OCR model", + "machine_learning_ocr_model_description": "Server models are more accurate than mobile models, but take longer to process and use more memory.", + "machine_learning_settings": "Machine Learning Settings", + "machine_learning_settings_description": "Manage machine learning features and settings", + "machine_learning_smart_search": "Smart Search", + "machine_learning_smart_search_description": "Search for images semantically using CLIP embeddings", + "machine_learning_smart_search_enabled": "Enable smart search", + "machine_learning_smart_search_enabled_description": "If disabled, images will not be encoded for smart search.", + "machine_learning_url_description": "The URL of the machine learning server. If more than one URL is provided, each server will be attempted one-at-a-time until one responds successfully, in order from first to last. Servers that don't respond will be temporarily ignored until they come back online.", + "maintenance_backup_management": "Backup management", + "maintenance_delete_backup": "Delete Backup", + "maintenance_delete_backup_description": "This file will be irrevocably deleted.", + "maintenance_delete_error": "Failed to delete backup.", + "maintenance_integrity_check": "Check", + "maintenance_integrity_check_all": "Check All", + "maintenance_integrity_checksum_mismatch": "Checksum Mismatch", + "maintenance_integrity_checksum_mismatch_description": "Files whose on-disk checksum mismatches the checksum which Immich had stored in its database.", + "maintenance_integrity_checksum_mismatch_job": "Check for checksum mismatches", + "maintenance_integrity_checksum_mismatch_refresh_job": "Refresh checksum mismatch reports", + "maintenance_integrity_missing_file": "Missing Files", + "maintenance_integrity_missing_file_description": "Files that Immich has tracked in its database but do not exist on the file system.", + "maintenance_integrity_missing_file_job": "Check for missing files", + "maintenance_integrity_missing_file_refresh_job": "Refresh missing file reports", + "maintenance_integrity_report": "Integrity Report", + "maintenance_integrity_untracked_file": "Untracked Files", + "maintenance_integrity_untracked_file_description": "Files in Immich's directories that Immich does not have any record of.", + "maintenance_integrity_untracked_file_job": "Check for untracked files", + "maintenance_integrity_untracked_file_refresh_job": "Refresh untracked file reports", + "maintenance_restore_backup": "Restore Backup", + "maintenance_restore_backup_description": "Immich will be wiped and restored from the chosen backup. A backup will be created before continuing.", + "maintenance_restore_backup_different_version": "This backup was created with a different version of Immich!", + "maintenance_restore_backup_unknown_version": "Couldn't determine backup version.", + "maintenance_restore_database_backup": "Restore database backup", + "maintenance_restore_database_backup_description": "Rollback to an earlier database state using a backup file", + "maintenance_settings": "Maintenance", + "maintenance_settings_description": "Put Immich into maintenance mode.", + "maintenance_start": "Switch to maintenance mode", + "maintenance_start_error": "Failed to start maintenance mode.", + "maintenance_upload_backup": "Upload database backup file", + "maintenance_upload_backup_error": "Could not upload backup, is it an .sql/.sql.gz file?", + "manage_concurrency": "Manage Concurrency", + "manage_concurrency_description": "Navigate to the jobs page to manage job concurrency", + "manage_log_settings": "Manage log settings", + "map_dark_style": "Dark style", + "map_enable_description": "Enable map features", + "map_gps_settings": "Map & GPS Settings", + "map_gps_settings_description": "Manage Map & GPS (Reverse Geocoding) Settings", + "map_implications": "The map feature relies on an external tile service (tiles.immich.cloud)", + "map_light_style": "Light style", + "map_manage_reverse_geocoding_settings": "Manage Reverse Geocoding settings", + "map_reverse_geocoding": "Reverse Geocoding", + "map_reverse_geocoding_enable_description": "Enable reverse geocoding", + "map_reverse_geocoding_settings": "Reverse Geocoding Settings", + "map_settings": "Map", + "map_settings_description": "Manage map settings", + "map_style_description": "URL to a style.json map theme", + "memory_cleanup_job": "Memory cleanup", + "memory_generate_job": "Memory generation", + "metadata_extraction_job": "Extract metadata", + "metadata_extraction_job_description": "Extract metadata information from each asset, such as GPS, faces and resolution", + "metadata_faces_import_setting": "Enable face import", + "metadata_faces_import_setting_description": "Import faces from image EXIF data and sidecar files", + "metadata_settings": "Metadata Settings", + "metadata_settings_description": "Manage metadata settings", + "migration_job": "Migration", + "migration_job_description": "Migrate thumbnails for assets and faces to the latest folder structure", + "nightly_tasks_cluster_faces_setting_description": "Run facial recognition on newly detected faces", + "nightly_tasks_cluster_new_faces_setting": "Cluster new faces", + "nightly_tasks_database_cleanup_setting": "Database cleanup tasks", + "nightly_tasks_database_cleanup_setting_description": "Clean up old, expired data from the database", + "nightly_tasks_generate_memories_setting": "Generate memories", + "nightly_tasks_generate_memories_setting_description": "Create new memories from assets", + "nightly_tasks_missing_thumbnails_setting": "Generate missing thumbnails", + "nightly_tasks_missing_thumbnails_setting_description": "Queue assets without thumbnails for thumbnail generation", + "nightly_tasks_settings": "Nightly Tasks Settings", + "nightly_tasks_settings_description": "Manage nightly tasks", + "nightly_tasks_start_time_setting": "Start time", + "nightly_tasks_start_time_setting_description": "The time at which the server starts running the nightly tasks", + "nightly_tasks_sync_quota_usage_setting": "Sync quota usage", + "nightly_tasks_sync_quota_usage_setting_description": "Update user storage quota, based on current usage", + "no_paths_added": "No paths added", + "no_pattern_added": "No pattern added", + "note_apply_storage_label_previous_assets": "Note: To apply the Storage Label to previously uploaded assets, run the", + "note_cannot_be_changed_later": "NOTE: This cannot be changed later!", + "notification_email_from_address": "From address", + "notification_email_from_address_description": "Sender email address, for example: \"Immich Photo Server \". Make sure to use an address you're allowed to send emails from.", + "notification_email_host_description": "Address of the email server (e.g. smtp.immich.app)", + "notification_email_ignore_certificate_errors": "Ignore certificate errors", + "notification_email_ignore_certificate_errors_description": "Ignore TLS certificate validation errors (not recommended)", + "notification_email_password_description": "Password to use when authenticating with the email server", + "notification_email_port_description": "Port of the email server (e.g 25, 465, or 587)", + "notification_email_secure": "SMTPS", + "notification_email_secure_description": "Use SMTPS (SMTP over TLS)", + "notification_email_sent_test_email_button": "Send test email and save", + "notification_email_setting_description": "Settings for sending email notifications", + "notification_email_test_email": "Send test email", + "notification_email_test_email_failed": "Failed to send test email, check your values", + "notification_email_test_email_sent": "A test email has been sent to {email}. Please check your inbox.", + "notification_email_username_description": "Username to use when authenticating with the email server", + "notification_enable_email_notifications": "Enable email notifications", + "notification_settings": "Notification Settings", + "notification_settings_description": "Manage notification settings, including email", + "oauth_allow_insecure_requests": "Allow insecure requests", + "oauth_allow_insecure_requests_description": "WARNING: This disables TLS certificate validation for OAuth requests and may expose you to MITM attacks.", + "oauth_auto_launch": "Auto launch", + "oauth_auto_launch_description": "Start the OAuth login flow automatically upon navigating to the login page", + "oauth_auto_register": "Auto register", + "oauth_auto_register_description": "Automatically register new users after signing in with OAuth", + "oauth_button_text": "Button text", + "oauth_client_secret_description": "Required for confidential client, or if PKCE (Proof Key for Code Exchange) is not supported for public client.", + "oauth_enable_description": "Login with OAuth", + "oauth_end_session_url_description": "Redirect the user to this URI when they log out.", + "oauth_mobile_redirect_uri": "Mobile redirect URI", + "oauth_mobile_redirect_uri_override": "Mobile redirect URI override", + "oauth_mobile_redirect_uri_override_description": "Enable when OAuth provider does not allow a mobile URI, like ''{callback}''", + "oauth_prompt_description": "Prompt parameter (e.g. select_account, login, consent)", + "oauth_role_claim": "Role Claim", + "oauth_role_claim_description": "Automatically grant admin access based on the presence of this claim. The claim may have either 'user' or 'admin'.", + "oauth_settings": "OAuth", + "oauth_settings_description": "Manage OAuth login settings", + "oauth_settings_more_details": "For more details about this feature, refer to the docs.", + "oauth_storage_label_claim": "Storage label claim", + "oauth_storage_label_claim_description": "Automatically set the user's storage label to the value of this claim.", + "oauth_storage_quota_claim": "Storage quota claim", + "oauth_storage_quota_claim_description": "Automatically set the user's storage quota to the value of this claim.", + "oauth_storage_quota_default": "Default storage quota (GiB)", + "oauth_storage_quota_default_description": "Quota in GiB to be used when no claim is provided.", + "oauth_timeout": "Request Timeout", + "oauth_timeout_description": "Timeout for requests in milliseconds", + "ocr_job_description": "Use machine learning to recognise text in images", + "password_enable_description": "Login with email and password", + "password_settings": "Password Login", + "password_settings_description": "Manage password login settings", + "paths_validated_successfully": "All paths validated successfully", + "person_cleanup_job": "Person cleanup", + "queue_details": "Queue Details", + "queues": "Job Queues", + "queues_page_description": "Admin job queues page", + "quota_size_gib": "Quota Size (GiB)", + "refreshing_all_libraries": "Refreshing all libraries", + "registration": "Admin Registration", + "registration_description": "Since you are the first user on the system, you will be assigned as the Admin and are responsible for administrative tasks, and additional users will be created by you.", + "release_channel_release_candidate": "Release candidate", + "release_channel_stable": "Stable", + "remove_failed_jobs": "Remove failed jobs", + "require_password_change_on_login": "Require user to change password on first login", + "reset_settings_to_default": "Reset settings to default", + "reset_settings_to_recent_saved": "Reset settings to the recent saved settings", + "scanning_library": "Scanning library", + "search_jobs": "Search jobs…", + "send_welcome_email": "Send welcome email", + "server_external_domain_settings": "External domain", + "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", + "server_settings_description": "Manage server settings", + "server_stats_page_description": "Admin server statistics page", + "server_welcome_message": "Welcome message", + "server_welcome_message_description": "A message that is displayed on the login page.", + "settings_page_description": "Admin settings page", + "sidecar_job": "Sidecar metadata", + "sidecar_job_description": "Discover or synchronise sidecar metadata from the filesystem", + "slideshow_duration_description": "Number of seconds to display each image", + "smart_search_job_description": "Run machine learning on assets to support smart search", + "storage_template_date_time_description": "Asset's creation timestamp is used for the datetime information", + "storage_template_date_time_sample": "Sample time {date}", + "storage_template_enable_description": "Enable storage template engine", + "storage_template_hash_verification_enabled": "Hash verification enabled", + "storage_template_hash_verification_enabled_description": "Enables hash verification, don't disable this unless you're certain of the implications", + "storage_template_migration": "Storage template migration", + "storage_template_migration_description": "Apply the current {template} to previously uploaded assets", + "storage_template_migration_info": "The storage template will convert all extensions to lowercase. Template changes will only apply to new assets. To retroactively apply the template to previously uploaded assets, run the {job}.", + "storage_template_migration_job": "Storage Template Migration Job", + "storage_template_more_details": "For more details about this feature, refer to the Storage Template and its implications", + "storage_template_onboarding_description_v2": "When enabled, this feature will auto-organise files based on a user-defined template. For more information, please see the documentation.", + "storage_template_path_length": "Approximate path length limit: {length, number}/{limit, number}", + "storage_template_settings": "Storage Template", + "storage_template_settings_description": "Manage the folder structure and file name of the upload asset", + "storage_template_user_label": "{label} is the user's Storage Label", + "system_settings": "System Settings", + "tag_cleanup_job": "Tag cleanup", + "template_email_available_tags": "You can use the following variables in your template: {tags}", + "template_email_if_empty": "If the template is empty, the default email will be used.", + "template_email_invite_album": "Invite Album Template", + "template_email_preview": "Preview", + "template_email_settings": "Email Templates", + "template_email_update_album": "Update Album Template", + "template_email_welcome": "Welcome email template", + "template_settings": "Notification Templates", + "template_settings_description": "Manage custom templates for notifications", + "theme_custom_css_settings": "Custom CSS", + "theme_custom_css_settings_description": "Cascading Style Sheets allow the design of Immich to be customised.", + "theme_settings": "Theme Settings", + "theme_settings_description": "Manage customisation of the Immich web interface", + "thumbnail_generation_job": "Generate Thumbnails", + "thumbnail_generation_job_description": "Generate large, small and blurred thumbnails for each asset, as well as thumbnails for each person", + "transcoding_acceleration_api": "Acceleration API", + "transcoding_acceleration_api_description": "The API that will interact with your device to accelerate transcoding. This setting is 'best effort': it will fallback to software transcoding on failure. VP9 may or may not work depending on your hardware.", + "transcoding_acceleration_nvenc": "NVENC (requires NVIDIA GPU)", + "transcoding_acceleration_qsv": "Quick Sync (requires 7th gen Intel CPU or later)", + "transcoding_acceleration_rkmpp": "RKMPP (only on Rockchip SOCs)", + "transcoding_acceleration_vaapi": "VAAPI", + "transcoding_accepted_audio_codecs": "Accepted audio codecs", + "transcoding_accepted_audio_codecs_description": "Select which audio codecs do not need to be transcoded. Only used for certain transcode policies.", + "transcoding_accepted_containers": "Accepted containers", + "transcoding_accepted_containers_description": "Select which container formats do not need to be remuxed to MP4. Only used for certain transcode policies.", + "transcoding_accepted_video_codecs": "Accepted video codecs", + "transcoding_accepted_video_codecs_description": "Select which video codecs do not need to be transcoded. Only used for certain transcode policies.", + "transcoding_advanced_options_description": "Options most users should not need to change", + "transcoding_audio_codec": "Audio codec", + "transcoding_audio_codec_description": "Opus is the highest quality option, but has lower compatibility with old devices or software.", + "transcoding_bitrate_description": "Videos higher than max bitrate or not in an accepted format", + "transcoding_codecs_learn_more": "To learn more about the terminology used here, refer to FFmpeg documentation for H.264 codec, HEVC codec and VP9 codec.", + "transcoding_constant_quality_mode": "Constant quality mode", + "transcoding_constant_quality_mode_description": "ICQ is better than CQP, but some hardware acceleration devices do not support this mode. Setting this option will prefer the specified mode when using quality-based encoding. Ignored by NVENC as it does not support ICQ.", + "transcoding_constant_rate_factor": "Constant rate factor (-crf)", + "transcoding_constant_rate_factor_description": "Video quality level. Typical values are 23 for H.264, 28 for HEVC, 31 for VP9, and 35 for AV1. Lower is better, but produces larger files.", + "transcoding_disabled_description": "Don't transcode any videos, may break playback on some clients", + "transcoding_encoding_options": "Encoding Options", + "transcoding_encoding_options_description": "Set codecs, resolution, quality and other options for the encoded videos", + "transcoding_hardware_acceleration": "Hardware Acceleration", + "transcoding_hardware_acceleration_description": "Experimental: faster transcoding but may reduce quality at same bitrate", + "transcoding_hardware_decoding": "Hardware decoding", + "transcoding_hardware_decoding_setting_description": "Enables end-to-end acceleration instead of only accelerating encoding. May not work on all videos.", + "transcoding_max_b_frames": "Maximum B-frames", + "transcoding_max_b_frames_description": "Higher values improve compression efficiency, but slow down encoding. May not be compatible with hardware acceleration on older devices. 0 disables B-frames, while -1 sets this value automatically.", + "transcoding_max_bitrate": "Maximum bitrate", + "transcoding_max_bitrate_description": "Setting a max bitrate can make file sizes more predictable at a minor cost to quality. At 720p, typical values are 2600 kbit/s for VP9 or HEVC, or 4500 kbit/s for H.264. Disabled if set to 0. When no unit is specified, k (for kbit/s) is assumed; therefore 5000, 5000k, and 5M (for Mbit/s) are equivalent.", + "transcoding_max_keyframe_interval": "Maximum keyframe interval", + "transcoding_max_keyframe_interval_description": "Sets the maximum frame distance between keyframes. Lower values worsen compression efficiency, but improve seek times and may improve quality in scenes with fast movement. 0 sets this value automatically.", + "transcoding_optimal_description": "Videos higher than target resolution or not in an accepted format", + "transcoding_policy": "Transcode Policy", + "transcoding_policy_description": "Set when a video will be transcoded", + "transcoding_preferred_hardware_device": "Preferred hardware device", + "transcoding_preferred_hardware_device_description": "Applies only to VAAPI and QSV. Sets the dri node used for hardware transcoding.", + "transcoding_preset_preset": "Preset (-preset)", + "transcoding_preset_preset_description": "Compression speed. Slower presets produce smaller files, and increase quality when targeting a certain bitrate. VP9 ignores speeds above 'faster'.", + "transcoding_realtime": "Real-time Transcoding [EXPERIMENTAL]", + "transcoding_realtime_description": "Allows transcoding to be performed in real-time as the video is being streamed. Enables quality switching, but may cause higher playback latency and stuttering depending on server capabilities.", + "transcoding_realtime_enabled": "Enable real-time transcoding", + "transcoding_realtime_enabled_description": "If disabled, the server will refuse to start new real-time transcoding sessions.", + "transcoding_reference_frames": "Reference frames", + "transcoding_reference_frames_description": "The number of frames to reference when compressing a given frame. Higher values improve compression efficiency, but slow down encoding. 0 sets this value automatically.", + "transcoding_required_description": "Only videos not in an accepted format", + "transcoding_settings": "Video Transcoding Settings", + "transcoding_settings_description": "Manage which videos to transcode and how to process them", + "transcoding_target_resolution": "Target resolution", + "transcoding_target_resolution_description": "Higher resolutions can preserve more detail but take longer to encode, have larger file sizes, and can reduce app responsiveness.", + "transcoding_temporal_aq": "Temporal AQ", + "transcoding_temporal_aq_description": "Applies only to NVENC. Temporal Adaptive Quantisation increases quality of high-detail, low-motion scenes. May not be compatible with older devices.", + "transcoding_threads": "Threads", + "transcoding_threads_description": "Higher values lead to faster encoding, but leave less room for the server to process other tasks while active. This value should not be more than the number of CPU cores. Maximises utilisation if set to 0.", + "transcoding_tone_mapping": "Tone-mapping", + "transcoding_tone_mapping_description": "Attempts to preserve the appearance of HDR videos when converted to SDR. Each algorithm makes different trade-offs for colour, detail and brightness. Hable preserves detail, Mobius preserves colour, and Reinhard preserves brightness.", + "transcoding_transcode_policy": "Transcode policy", + "transcoding_transcode_policy_description": "Policy for when a video should be transcoded. HDR videos and videos with a pixel format other than YUV 4:2:0 will always be transcoded (except if transcoding is disabled).", + "transcoding_two_pass_encoding": "Two-pass encodingy", + "transcoding_two_pass_encoding_setting_description": "Transcode in two passes to produce better encoded videos. When max bitrate is enabled (required for it to work with H.264 and HEVC), this mode uses a bitrate range based on the max bitrate and ignores CRF. For VP9, CRF can be used if max bitrate is disabled.", + "transcoding_video_codec": "Video codec", + "transcoding_video_codec_description": "VP9 has high efficiency and web compatibility, but takes longer to transcode. HEVC performs similarly, but has lower web compatibility. H.264 is widely compatible and quick to transcode, but produces much larger files. AV1 is the most efficient codec but lacks support on older devices.", + "trash_enabled_description": "Enable Trash features", + "trash_number_of_days": "Number of days", + "trash_number_of_days_description": "Number of days to keep the assets in the bin before permanently removing them", + "trash_settings": "Bin Settings", + "trash_settings_description": "Manage bin settings", + "unlink_all_oauth_accounts": "Unlink all OAuth accounts", + "unlink_all_oauth_accounts_description": "Remember to unlink all OAuth accounts before migrating to a new provider.", + "unlink_all_oauth_accounts_prompt": "Are you sure you want to unlink all OAuth accounts? This will reset the OAuth ID for each user and cannot be undone.", + "user_cleanup_job": "User cleanup", + "user_delete_delay": "{user}'s account and assets will be scheduled for permanent deletion in {delay, plural, one {# day} other {# days}}.", + "user_delete_delay_settings": "Delete delay", + "user_delete_delay_settings_description": "Number of days after removal to permanently delete a user's account and assets. The user deletion job runs at midnight to check for users that are ready for deletion. Changes to this setting will be evaluated at the next execution.", + "user_delete_immediately": "{user}'s account and assets will be queued for permanent deletion immediately.", + "user_delete_immediately_checkbox": "Queue user and assets for immediate deletion", + "user_details": "User Details", + "user_management": "User Management", + "user_password_has_been_reset": "The user's password has been reset:", + "user_password_reset_description": "Please provide the temporary password to the user and inform them they will need to change the password at their next login.", + "user_restore_description": "{user}'s account will be restored.", + "user_restore_scheduled_removal": "Restore user - scheduled removal on {date, date, long}", + "user_settings": "User Settings", + "user_settings_description": "Manage user settings", + "user_successfully_removed": "User {email} has been successfully removed.", + "users_page_description": "Admin users page", + "version_check_channel": "Release channel", + "version_check_channel_description": "Pick the release channel you want to get version announcements for", + "version_check_enabled_description": "Enable version check", + "version_check_implications": "The version check feature relies on periodic communication with {server}", + "version_check_settings": "Version Check", + "version_check_settings_description": "Enable/disable the new version notification", + "video_conversion_job": "Transcode videos", + "video_conversion_job_description": "Transcode videos for wider compatibility with browsers and devices" + }, + "admin_email": "Admin Email", + "admin_password": "Admin Password", + "administration": "Administration", + "advanced": "Advanced", + "advanced_settings_clear_image_cache": "Clear Image Cache", + "advanced_settings_clear_image_cache_error": "Failed to clear image cache", + "advanced_settings_clear_image_cache_success": "Successfully cleared {size}", + "advanced_settings_enable_alternate_media_filter_subtitle": "Use this option to filter media during sync based on alternate criteria. Only try this if you have issues with the app detecting all albums.", + "advanced_settings_enable_alternate_media_filter_title": "[EXPERIMENTAL] Use alternate device album sync filter", + "advanced_settings_log_level_title": "Log level: {level}", + "advanced_settings_prefer_remote_subtitle": "Some devices are painfully slow to load thumbnails from local assets. Activate this setting to load remote images instead.", + "advanced_settings_prefer_remote_title": "Prefer remote images", + "advanced_settings_proxy_headers_subtitle": "Define proxy headers Immich should send with each network request", + "advanced_settings_proxy_headers_title": "Custom proxy headers [EXPERIMENTAL]", + "advanced_settings_readonly_mode_subtitle": "Enables the read-only mode where the photos can be only viewed, things like selecting multiple images, sharing, casting, delete are all disabled. Enable/Disable read-only via user avatar from the main screen", + "advanced_settings_readonly_mode_title": "Read-only mode", + "advanced_settings_self_signed_ssl_subtitle": "Skips SSL certificate verification for the server endpoint. Required for self-signed certificates.", + "advanced_settings_self_signed_ssl_title": "Allow self-signed SSL certificates [EXPERIMENTAL]", + "advanced_settings_sync_remote_deletions_subtitle": "Automatically delete or restore an asset on this device when that action is taken on the web", + "advanced_settings_sync_remote_deletions_title": "Sync remote deletions [EXPERIMENTAL]", + "advanced_settings_tile_subtitle": "Advanced user's settings", + "advanced_settings_troubleshooting_subtitle": "Enable additional features for troubleshooting", + "advanced_settings_troubleshooting_title": "Troubleshooting", + "age_months": "Age {months, plural, one {# month} other {# months}}", + "age_year_months": "Age 1 year, {months, plural, one {# month} other {# months}}", + "age_years": "{years, plural, other {Age #}}", + "album": "Album", + "album_added": "Album added", + "album_added_notification_setting_description": "Receive an email notification when you are added to a shared album", + "album_cover_updated": "Album cover updated", + "album_delete_confirmation": "Are you sure you want to delete the album {album}?", + "album_delete_confirmation_description": "If this album is shared, other users will not be able to access it any more.", + "album_deleted": "Album deleted", + "album_info_card_backup_album_excluded": "EXCLUDED", + "album_info_card_backup_album_included": "INCLUDED", + "album_info_updated": "Album info updated", + "album_leave": "Leave album?", + "album_leave_confirmation": "Are you sure you want to leave {album}?", + "album_name": "Album Name", + "album_options": "Album options", + "album_remove_user": "Remove user?", + "album_remove_user_confirmation": "Are you sure you want to remove {user}?", + "album_search_not_found": "No albums found matching your search", + "album_selected": "Album selected", + "album_share_no_users": "Looks like you have shared this album with all users or you don't have any users to share with.", + "album_summary": "Album summary", + "album_updated": "Album updated", + "album_updated_setting_description": "Receive an email notification when a shared album has new assets", + "album_upload_assets": "Upload assets from your computer and add to album", + "album_user_left": "Left {album}", + "album_user_removed": "Removed {user}", + "album_viewer_appbar_delete_confirm": "Are you sure you want to delete this album from your account?", + "album_viewer_appbar_share_err_delete": "Failed to delete album", + "album_viewer_appbar_share_err_leave": "Failed to leave album", + "album_viewer_appbar_share_err_remove": "There are problems in removing assets from album", + "album_viewer_appbar_share_err_title": "Failed to change album title", + "album_viewer_appbar_share_leave": "Leave album", + "album_viewer_appbar_share_to": "Share To", + "album_viewer_page_share_add_users": "Add users", + "album_with_link_access": "Let anyone with the link see photos and people in this album.", + "albums": "Albums", + "albums_count": "{count, plural, one {{count, number} Album} other {{count, number} Albums}}", + "albums_default_sort_order": "Default album sort order", + "albums_default_sort_order_description": "Initial asset sort order when creating new albums.", + "albums_feature_description": "Collections of assets that can be shared with other users.", + "albums_on_device_count": "Albums on device ({count})", + "albums_selected": "{count, plural, one {# album selected} other {# albums selected}}", + "all": "All", + "all_albums": "All albums", + "all_people": "All people", + "all_photos": "All photos", + "all_videos": "All videos", + "allow_dark_mode": "Allow dark mode", + "allow_edits": "Allow edits", + "allow_public_user_to_download": "Allow public user to download", + "allow_public_user_to_upload": "Allow public user to upload", + "allowed": "Allowed", + "alt_text_qr_code": "QR code image", + "always_keep": "Always keep", + "always_keep_photos_hint": "Free Up Space will keep all photos on this device.", + "always_keep_videos_hint": "Free Up Space will keep all videos on this device.", + "anti_clockwise": "Anti-clockwise", + "api_key": "API Key", + "api_key_description": "This value will only be shown once. Please be sure to copy it before closing the window.", + "api_key_empty": "Your API Key name shouldn't be empty", + "api_keys": "API Keys", + "app_architecture_variant": "Variant (Architecture)", + "app_bar_signout_dialog_content": "Are you sure you want to sign out?", + "app_bar_signout_dialog_ok": "Yes", + "app_bar_signout_dialog_title": "Sign out", + "app_download_links": "App Download Links", + "app_settings": "App Settings", + "app_stores": "App Stores", + "app_update_available": "App update is available", + "appears_in": "Appears in", + "apply_count": "Apply ({count, number})", + "archive": "Archive", + "archive_action_prompt": "{count} added to Archive", + "archive_or_unarchive_photo": "Archive or unarchive photo", + "archive_page_no_archived_assets": "No archived assets found", + "archive_page_title": "Archive ({count})", + "archive_size": "Archive size", + "archive_size_description": "Configure the archive size for downloads (in GiB)", + "archived": "Archived", + "archived_count": "{count, plural, other {Archived #}}", + "are_these_the_same_person": "Are these the same person?", + "are_you_sure_to_do_this": "Are you sure you want to do this?", + "array_field_not_fully_supported": "Array fields require manual JSON editing", + "asset_action_delete_err_read_only": "Cannot delete read only asset(s), skipping", + "asset_action_share_err_offline": "Cannot fetch offline asset(s), skipping", + "asset_added_to_album": "Added to album", + "asset_adding_to_album": "Adding to album…", + "asset_created": "Asset created", + "asset_day_count": "{date}: {count, plural, one {# asset} other {# assets}}", + "asset_description_updated": "Asset description has been updated", + "asset_filename_is_offline": "Asset {filename} is offline", + "asset_has_unassigned_faces": "Asset has unassigned faces", + "asset_hashing": "Hashing…", + "asset_list_group_by_sub_title": "Group by", + "asset_list_layout_settings_dynamic_layout_title": "Dynamic layout", + "asset_list_layout_settings_group_automatically": "Automatic", + "asset_list_layout_settings_group_by": "Group assets by", + "asset_list_layout_settings_group_by_month_day": "Month + day", + "asset_list_layout_sub_title": "Layout", + "asset_list_settings_subtitle": "Photo grid layout settings", + "asset_list_settings_title": "Photo Grid", + "asset_not_found_on_device_android": "Asset not found on device", + "asset_not_found_on_device_ios": "Asset not found on device. If you are using iCloud, the asset may be inaccessible due to bad file stored on iCloud", + "asset_not_found_on_icloud": "Asset not found on iCloud. the asset may be inaccessible due to bad file stored on iCloud", + "asset_offline": "Asset Offline", + "asset_offline_description": "This external asset is no longer found on disk. Please contact your Immich administrator for help.", + "asset_restored_successfully": "Asset restored successfully", + "asset_skipped": "Skipped", + "asset_skipped_in_trash": "In trash", + "asset_trashed": "Asset trashed", + "asset_troubleshoot": "Asset Troubleshoot", + "asset_uploaded": "Uploaded", + "asset_uploading": "Uploading…", + "asset_viewer_settings_subtitle": "Manage your gallery viewer settings", + "asset_viewer_settings_title": "Asset Viewer", + "assets": "Assets", + "assets_added_count": "Added {count, plural, one {# asset} other {# assets}}", + "assets_added_to_album_count": "Added {count, plural, one {# asset} other {# assets}} to the album", + "assets_added_to_albums_count": "Added {assetTotal, plural, one {# asset} other {# assets}} to {albumTotal, plural, one {# album} other {# albums}}", + "assets_cannot_be_added_to_album_count": "{count, plural, one {Asset} other {Assets}} cannot be added to the album", + "assets_cannot_be_added_to_albums": "{count, plural, one {Asset} other {Assets}} cannot be added to any of the albums", + "assets_count": "{count, plural, one {# asset} other {# assets}}", + "assets_deleted_permanently": "{count} asset(s) deleted permanently", + "assets_deleted_permanently_from_server": "{count} asset(s) deleted permanently from the Immich server", + "assets_downloaded_failed": "{count, plural, one {Downloaded # file - {error} file failed} other {Downloaded # files - {error} files failed}}", + "assets_downloaded_successfully": "{count, plural, one {Downloaded # file successfully} other {Downloaded # files successfully}}", + "assets_moved_to_trash_count": "Moved {count, plural, one {# asset} other {# assets}} to trash", + "assets_permanently_deleted_count": "Permanently deleted {count, plural, one {# asset} other {# assets}}", + "assets_removed_count": "Removed {count, plural, one {# asset} other {# assets}}", + "assets_removed_permanently_from_device": "{count} asset(s) removed permanently from your device", + "assets_restore_confirmation": "Are you sure you want to restore all your binned assets? You cannot undo this action! Note that any offline assets cannot be restored this way.", + "assets_restored_count": "Restored {count, plural, one {# asset} other {# assets}}", + "assets_restored_successfully": "{count} asset(s) restored successfully", + "assets_trashed": "{count} asset(s) binned", + "assets_trashed_count": "Binned {count, plural, one {# asset} other {# assets}}", + "assets_trashed_from_server": "{count} asset(s) binned from the Immich server", + "assets_were_part_of_album_count": "{count, plural, one {Asset was} other {Assets were}} already part of the album", + "assets_were_part_of_albums_count": "{count, plural, one {Asset was} other {Assets were}} already part of the albums", + "authorized_devices": "Authorised Devices", + "automatic_endpoint_switching_subtitle": "Connect locally over designated Wi-Fi when available and use alternative connections elsewhere", + "automatic_endpoint_switching_title": "Automatic URL switching", + "autoplay_slideshow": "Autoplay slideshow", + "back": "Back", + "back_close_deselect": "Back, close, or deselect", + "background_backup_running_error": "Background backup is currently running, cannot start manual backup", + "background_location_permission": "Background location permission", + "background_location_permission_content": "In order to switch networks when running in the background, Immich must *always* have precise location access so the app can read the Wi-Fi network's name", + "background_options": "Background Options", + "backup": "Backup", + "backup_album_selection_page_albums_device": "Albums on device ({count})", + "backup_album_selection_page_albums_tap": "Tap to include, double tap to exclude", + "backup_album_selection_page_assets_scatter": "Assets can scatter across multiple albums. Thus, albums can be included or excluded during the backup process.", + "backup_album_selection_page_select_albums": "Select albums", + "backup_album_selection_page_selection_info": "Selection Info", + "backup_album_selection_page_total_assets": "Total unique assets", + "backup_albums_sync": "Backup Albums Synchronisation", + "backup_all": "All", + "backup_background_service_backup_failed_message": "Failed to backup assets. Retrying…", + "backup_background_service_complete_notification": "Asset backup complete", + "backup_background_service_connection_failed_message": "Failed to connect to the server. Retrying…", + "backup_background_service_current_upload_notification": "Uploading {filename}", + "backup_background_service_default_notification": "Checking for new assets…", + "backup_background_service_error_title": "Backup error", + "backup_background_service_in_progress_notification": "Backing up your assets…", + "backup_background_service_upload_failure_notification": "Failed to upload {filename}", + "backup_controller_page_albums": "Backup Albums", + "backup_controller_page_background_app_refresh_disabled_content": "Enable background app refresh in Settings > General > Background App Refresh in order to use background backup.", + "backup_controller_page_background_app_refresh_disabled_title": "Background app refresh disabled", + "backup_controller_page_background_app_refresh_enable_button_text": "Go to settings", + "backup_controller_page_background_battery_info_link": "Show me how", + "backup_controller_page_background_battery_info_message": "For the best background backup experience, please disable any battery optimisations restricting background activity for Immich.\n\nSince this is device-specific, please lookup the required information for your device manufacturer.", + "backup_controller_page_background_battery_info_ok": "OK", + "backup_controller_page_background_battery_info_title": "Battery optimisations", + "backup_controller_page_background_charging": "Only while charging", + "backup_controller_page_background_configure_error": "Failed to configure the background service", + "backup_controller_page_background_delay": "Delay new assets backup: {duration}", + "backup_controller_page_background_description": "Turn on the background service to automatically backup any new assets without needing to open the app", + "backup_controller_page_background_is_off": "Automatic background backup is off", + "backup_controller_page_background_is_on": "Automatic background backup is on", + "backup_controller_page_background_turn_off": "Turn off background service", + "backup_controller_page_background_turn_on": "Turn on background service", + "backup_controller_page_background_wifi": "Only on Wi-Fi", + "backup_controller_page_backup": "Backup", + "backup_controller_page_backup_selected": "Selected: ", + "backup_controller_page_backup_sub": "Backed up photos and videos", + "backup_controller_page_created": "Created on: {date}", + "backup_controller_page_desc_backup": "Turn on foreground backup to automatically upload new assets to the server when opening the app.", + "backup_controller_page_excluded": "Excluded: ", + "backup_controller_page_failed": "Failed ({count})", + "backup_controller_page_filename": "File name: {filename} [{size}]", + "backup_controller_page_id": "ID: {id}", + "backup_controller_page_info": "Backup Information", + "backup_controller_page_none_selected": "None selected", + "backup_controller_page_remainder": "Remainder", + "backup_controller_page_remainder_sub": "Remaining photos and videos to back up from selection", + "backup_controller_page_server_storage": "Server Storage", + "backup_controller_page_start_backup": "Start Backup", + "backup_controller_page_status_off": "Automatic foreground backup is off", + "backup_controller_page_status_on": "Automatic foreground backup is on", + "backup_controller_page_storage_format": "{used} of {total} used", + "backup_controller_page_to_backup": "Albums to be backed up", + "backup_controller_page_total_sub": "All unique photos and videos from selected albums", + "backup_controller_page_turn_off": "Turn off foreground backup", + "backup_controller_page_turn_on": "Turn on foreground backup", + "backup_controller_page_uploading_file_info": "Uploading file info", + "backup_err_only_album": "Cannot remove the only album", + "backup_error_sync_failed": "Sync failed. Cannot process backup.", + "backup_info_card_assets": "assets", + "backup_manual_cancelled": "Cancelled", + "backup_manual_in_progress": "Upload already in progress. Try after sometime", + "backup_manual_success": "Success", + "backup_manual_title": "Upload status", + "backup_options": "Backup Options", + "backup_options_page_title": "Backup options", + "backup_setting_subtitle": "Manage background and foreground upload settings", + "backup_settings_subtitle": "Manage upload settings", + "backup_upload_details_page_more_details": "Tap for more details", + "backward": "Backward", + "battery_optimization_backup_reliability": "Disabling battery optimisations can improve the reliability of background backup", + "biometric_auth_enabled": "Biometric authentication enabled", + "biometric_locked_out": "You are locked out of biometric authentication", + "biometric_no_options": "No biometric options available", + "biometric_not_available": "Biometric authentication is not available on this device", + "birthdate_saved": "Date of birth saved successfully", + "birthdate_set_description": "Date of birth is used to calculate the age of this person at the time of a photo.", + "blurred_background": "Blurred background", + "browse_templates": "Browse templates", + "bugs_and_feature_requests": "Bugs & Feature Requests", + "build": "Build", + "build_image": "Build Image", + "bulk_delete_duplicates_confirmation": "Are you sure you want to bulk delete {count, plural, one {# duplicate asset} other {# duplicate assets}}? This will keep the largest asset of each group and permanently delete all other duplicates. You cannot undo this action!", + "bulk_keep_duplicates_confirmation": "Are you sure you want to keep {count, plural, one {# duplicate asset} other {# duplicate assets}}? This will resolve all duplicate groups without deleting anything.", + "bulk_trash_duplicates_confirmation": "Are you sure you want to bulk trash {count, plural, one {# duplicate asset} other {# duplicate assets}}? This will keep the largest asset of each group and trash all other duplicates.", + "buy": "Purchase Immich", + "cache_settings_clear_cache_button": "Clear cache", + "cache_settings_clear_cache_button_title": "Clears the app's cache. This will significantly impact the app's performance until the cache has rebuilt.", + "cache_settings_duplicated_assets_clear_button": "CLEAR", + "cache_settings_duplicated_assets_subtitle": "Photos and videos that are ignore listed by the app", + "cache_settings_duplicated_assets_title": "Duplicated Assets ({count})", + "cache_settings_statistics_album": "Library thumbnails", + "cache_settings_statistics_full": "Full images", + "cache_settings_statistics_shared": "Shared album thumbnails", + "cache_settings_statistics_thumbnail": "Thumbnails", + "cache_settings_statistics_title": "Cache usage", + "cache_settings_subtitle": "Control the caching behaviour of the Immich mobile application", + "cache_settings_tile_subtitle": "Control the local storage behaviour", + "cache_settings_tile_title": "Local Storage", + "cache_settings_title": "Caching Settings", + "camera": "Camera", + "camera_brand": "Camera brand", + "camera_model": "Camera model", + "cancel": "Cancel", + "cancel_search": "Cancel search", + "canceled": "Cancelled", + "canceling": "Cancelling", + "cannot_merge_people": "Cannot merge people", + "cannot_undo_this_action": "You cannot undo this action!", + "cannot_update_the_description": "Cannot update the description", + "cast": "Cast", + "cast_description": "Configure available cast destinations", + "change": "Change", + "change_date": "Change date", + "change_description": "Change description", + "change_display_order": "Change display order", + "change_expiration_time": "Change expiration time", + "change_location": "Change location", + "change_name": "Change name", + "change_name_successfully": "Changed name successfully", + "change_password": "Change Password", + "change_password_description": "This is either the first time you are signing into the system or a request has been made to change your password. Please enter the new password below.", + "change_password_form_confirm_password": "Confirm Password", + "change_password_form_description": "Hi {name},\n\nThis is either the first time you are signing into the system or a request has been made to change your password. Please enter the new password below.", + "change_password_form_log_out": "Log out all other devices", + "change_password_form_log_out_description": "It is recommended to log out of all other devices", + "change_password_form_new_password": "New Password", + "change_password_form_password_mismatch": "Passwords do not match", + "change_password_form_reenter_new_password": "Re-enter New Password", + "change_pin_code": "Change PIN code", + "change_trigger": "Change trigger", + "change_trigger_prompt": "Are you sure you want to change the trigger? This will remove all existing actions and filters.", + "change_your_password": "Change your password", + "changed_visibility_successfully": "Changed visibility successfully", + "charging": "Charging", + "charging_requirement_mobile_backup": "Background backup requires the device to be charging", + "check_corrupt_asset_backup": "Check for corrupt asset backups", + "check_corrupt_asset_backup_button": "Perform check", + "check_corrupt_asset_backup_description": "Run this check only over Wi-Fi and once all assets have been backed-up. The procedure might take a few minutes.", + "check_logs": "Check Logs", + "checksum": "Checksum", + "choose": "Choose", + "choose_matching_people_to_merge": "Choose matching people to merge", + "city": "City", + "cleanup_confirm_description": "Immich found {count} assets (created before {date}) safely backed up to the server. Remove the local copies from this device?", + "cleanup_confirm_prompt_title": "Remove from this device?", + "cleanup_deleted_assets": "Moved {count} assets to device trash", + "cleanup_deleting": "Moving to bin...", + "cleanup_found_assets": "Found {count} backed up assets", + "cleanup_found_assets_with_size": "Found {count} backed up assets ({size})", + "cleanup_icloud_shared_albums_excluded": "iCloud Shared Albums are excluded from the scan", + "cleanup_no_assets_found": "No assets found matching the criteria above. Free Up Space can only remove assets that have been backed up to the server", + "cleanup_preview_title": "Assets to remove ({count})", + "cleanup_step3_description": "Scan for backed up assets matching your date and keep settings.", + "cleanup_step4_summary": "{count} assets (created before {date}) to remove from your local device. Photos will remain accessible from the Immich app.", + "cleanup_trash_hint": "To fully reclaim storage space, open the system gallery app and empty the bin", + "clear": "Clear", + "clear_all": "Clear all", + "clear_all_recent_searches": "Clear all recent searches", + "clear_failed_count": "Clear failed ({count})", + "clear_file_cache": "Clear File Cache", + "clear_message": "Clear message", + "clear_value": "Clear value", + "client_cert_dialog_msg_confirm": "OK", + "client_cert_enter_password": "Enter Password", + "client_cert_import": "Import", + "client_cert_import_success_msg": "Client certificate is imported", + "client_cert_invalid_msg": "Invalid certificate file or wrong password", + "client_cert_password_message": "Enter the password for this certificate", + "client_cert_password_title": "Certificate Password", + "client_cert_remove_msg": "Client certificate is removed", + "client_cert_subtitle": "Supports PKCS12 (.p12, .pfx) format only. Certificate import/removal is available only before login", + "client_cert_title": "SSL client certificate [EXPERIMENTAL]", + "clockwise": "Сlockwise", + "close": "Close", + "collapse": "Collapse", + "collapse_all": "Collapse all", + "color": "Colour", + "color_theme": "Colour 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", + "comments_are_disabled": "Comments are disabled", + "common_create_new_album": "Create new album", + "completed": "Completed", + "configuration": "Configuration", + "confirm": "Confirm", + "confirm_admin_password": "Confirm Admin Password", + "confirm_delete_face": "Are you sure you want to delete {name} face from the asset?", + "confirm_delete_shared_link": "Are you sure you want to delete this shared link?", + "confirm_keep_this_delete_others": "All other assets in the stack will be deleted except for this asset. Are you sure you want to continue?", + "confirm_new_pin_code": "Confirm new PIN code", + "confirm_password": "Confirm password", + "confirm_tag_face": "Do you want to tag this face as {name}?", + "confirm_tag_face_unnamed": "Do you want to tag this face?", + "connected_device": "Connected device", + "connected_to": "Connected to", + "contain": "Contain", + "context": "Context", + "continue": "Continue", + "control_bottom_app_bar_add_tags": "Add Tags", + "control_bottom_app_bar_create_new_album": "Create new album", + "control_bottom_app_bar_delete_from_immich": "Delete from Immich", + "control_bottom_app_bar_delete_from_local": "Delete from device", + "control_bottom_app_bar_edit_location": "Edit Location", + "control_bottom_app_bar_edit_time": "Edit Date & Time", + "control_bottom_app_bar_share_link": "Share Link", + "control_bottom_app_bar_share_to": "Share To", + "control_bottom_app_bar_trash_from_immich": "Move to Bin", + "copied_image_to_clipboard": "Copied image to clipboard.", + "copied_to_clipboard": "Copied to clipboard!", + "copy_error": "Copy error", + "copy_file_path": "Copy file path", + "copy_image": "Copy Image", + "copy_json": "Copy JSON", + "copy_link": "Copy link", + "copy_link_to_clipboard": "Copy link to clipboard", + "copy_password": "Copy password", + "copy_to_clipboard": "Copy to Clipboard", + "country": "Country", + "cover": "Cover", + "covers": "Covers", + "create": "Create", + "create_album": "Create album", + "create_album_page_untitled": "Untitled", + "create_api_key": "Create API key", + "create_first_workflow": "Create first workflow", + "create_library": "Create Library", + "create_link": "Create link", + "create_link_to_share": "Create link to share", + "create_link_to_share_description": "Let anyone with the link see the selected photo(s)", + "create_new": "CREATE NEW", + "create_new_face": "Create new face", + "create_new_person": "Create new person", + "create_new_person_hint": "Assign selected assets to a new person", + "create_new_user": "Create new user", + "create_person": "Create person", + "create_person_subtitle": "Add a name to the selected face to create and tag the new person", + "create_shared_album_page_share_add_assets": "ADD ASSETS", + "create_shared_album_page_share_select_photos": "Select Photos", + "create_shared_link": "Create shared link", + "create_tag": "Create tag", + "create_tag_description": "Create a new tag. For nested tags, please enter the full path of the tag including forward slashes.", + "create_user": "Create user", + "create_workflow": "Create workflow", + "created": "Created", + "created_at": "Created", + "creating_linked_albums": "Creating linked albums...", + "crop": "Crop", + "crop_aspect_ratio_fixed": "Fixed", + "crop_aspect_ratio_free": "Free", + "crop_aspect_ratio_original": "Original", + "crop_aspect_ratio_square": "Square", + "curated_object_page_title": "Things", + "current_device": "Current device", + "current_pin_code": "Current PIN code", + "current_server_address": "Current server address", + "custom_date": "Custom date", + "custom_locale": "Custom locale", + "custom_locale_description": "Format dates, times, and numbers based on the selected language and region", + "custom_url": "Custom URL", + "cutoff_date_description": "Keep photos from the last…", + "cutoff_day": "{count, plural, one {day} other {days}}", + "cutoff_year": "{count, plural, one {year} other {years}}", + "dark": "Dark", + "dark_theme": "Switch to dark theme", + "date": "Date", + "date_after": "Date after", + "date_and_time": "Date and Time", + "date_before": "Date before", + "date_of_birth": "Date of birth", + "date_of_birth_saved": "Date of birth saved successfully", + "date_range": "Date range", + "date_time_original": "Date/Time Original", + "day": "Day", + "days": "Days", + "deduplicate_all": "Deduplicate All", + "default_locale": "Default Locale", + "default_locale_description": "Format dates and numbers based on your browser locale", + "default_quality_subtitle": "Quality used when tapping share. Long press the share button to choose each time.", + "default_share_quality": "Default share quality", + "delete": "Delete", + "delete_action_confirmation_message": "Are you sure you want to delete this asset? This action will move the asset to the server's bin and will prompt if you want to delete it locally", + "delete_action_prompt": "{count} deleted", + "delete_album": "Delete album", + "delete_api_key_prompt": "Are you sure you want to delete this API key?", + "delete_dialog_alert": "These items will be permanently deleted from Immich and from your device", + "delete_dialog_alert_local": "These items will be permanently removed from your device but still be available on the Immich server", + "delete_dialog_alert_local_non_backed_up": "Some of the items aren't backed up to Immich and will be permanently removed from your device", + "delete_dialog_alert_remote": "These items will be permanently deleted from the Immich server", + "delete_dialog_ok_force": "Delete Anyway", + "delete_dialog_title": "Delete Permanently", + "delete_duplicates_confirmation": "Are you sure you want to permanently delete these duplicates?", + "delete_face": "Delete face", + "delete_key": "Delete key", + "delete_library": "Delete Library", + "delete_link": "Delete link", + "delete_local_action_prompt": "{count} deleted locally", + "delete_local_dialog_ok_backed_up_only": "Delete Backed Up Only", + "delete_local_dialog_ok_force": "Delete Anyway", + "delete_others": "Delete others", + "delete_permanently": "Delete permanently", + "delete_permanently_action_prompt": "{count} deleted permanently", + "delete_shared_link": "Delete shared link", + "delete_shared_link_dialog_title": "Delete Shared Link", + "delete_tag": "Delete tag", + "delete_tag_confirmation_prompt": "Are you sure you want to delete {tagName} tag?", + "delete_user": "Delete user", + "deleted_shared_link": "Deleted shared link", + "deletes_missing_assets": "Deletes assets missing from disk", + "description": "Description", + "description_input_hint_text": "Add description...", + "description_input_submit_error": "Error updating description, check the log for more details", + "deselect_all": "Deselect All", + "details": "Details", + "direction": "Direction", + "disable": "Disable", + "disabled": "Disabled", + "disallow_edits": "Disallow edits", + "discord": "Discord", + "discover": "Discover", + "discovered_devices": "Discovered devices", + "dismiss_all_errors": "Dismiss all errors", + "dismiss_error": "Dismiss error", + "display_options": "Display options", + "display_order": "Display order", + "display_original_photos": "Display original photos", + "display_original_photos_setting_description": "Prefer to display the original photo when viewing an asset rather than thumbnails when the original asset is web-compatible. This may result in slower photo display speeds.", + "do_not_show_again": "Do not show this message again", + "documentation": "Documentation", + "done": "Done", + "download": "Download", + "download_action_prompt": "Downloading {count} assets", + "download_canceled": "Download cancelled", + "download_complete": "Download complete", + "download_enqueue": "Download enqueued", + "download_error": "Download Error", + "download_failed": "Download failed", + "download_finished": "Download finished", + "download_include_embedded_motion_videos": "Embedded videos", + "download_include_embedded_motion_videos_description": "Include videos embedded in motion photos as a separate file", + "download_notfound": "Download not found", + "download_original": "Download original", + "download_paused": "Download paused", + "download_settings": "Download", + "download_settings_description": "Manage settings related to asset download", + "download_started": "Download started", + "download_sucess": "Download success", + "download_sucess_android": "The media has been downloaded to DCIM/Immich", + "download_waiting_to_retry": "Waiting to retry", + "downloading": "Downloading", + "downloading_asset_filename": "Downloading asset {filename}", + "downloading_from_icloud": "Downloading from iCloud", + "downloading_media": "Downloading media", + "drag_to_reorder": "Drag to reorder", + "drop_files_to_upload": "Drop files anywhere to upload", + "duplicate": "Duplicate", + "duplicate_workflow": "Duplicate workflow", + "duplicates": "Duplicates", + "duplicates_description": "Resolve each group by indicating which, if any, are duplicates.", + "duration": "Duration", + "edit": "Edit", + "edit_album": "Edit album", + "edit_avatar": "Edit avatar", + "edit_birthday": "Edit birthday", + "edit_date": "Edit date", + "edit_date_and_time": "Edit date and time", + "edit_date_and_time_action_prompt": "{count} date and time edited", + "edit_date_and_time_by_offset": "Change date by offset", + "edit_date_and_time_by_offset_interval": "New date range: {from} - {to}", + "edit_description": "Edit description", + "edit_description_prompt": "Please select a new description:", + "edit_exclusion_pattern": "Edit exclusion pattern", + "edit_faces": "Edit faces", + "edit_key": "Edit key", + "edit_link": "Edit link", + "edit_location": "Edit location", + "edit_location_action_prompt": "{count} location edited", + "edit_location_dialog_title": "Location", + "edit_name": "Edit name", + "edit_people": "Edit people", + "edit_tag": "Edit tag", + "edit_title": "Edit Title", + "edit_user": "Edit user", + "edit_workflow": "Edit workflow", + "editor": "Editor", + "editor_close_without_save_prompt": "The changes will not be saved", + "editor_close_without_save_title": "Close editor?", + "editor_confirm_reset_all_changes": "Are you sure you want to reset all changes?", + "editor_discard_edits_confirm": "Discard edits", + "editor_discard_edits_prompt": "You have unsaved edits. Are you sure you want to discard them?", + "editor_discard_edits_title": "Discard edits?", + "editor_edits_applied_error": "Failed to apply edits", + "editor_edits_applied_success": "Edits applied successfully", + "editor_flip_horizontal": "Flip horizontally", + "editor_flip_vertical": "Flip vertically", + "editor_handle_corner": "{corner, select, top_left {Top-left} top_right {Top-right} bottom_left {Bottom-left} bottom_right {Bottom-right} other {A}} corner handle", + "editor_handle_edge": "{edge, select, top {Top} bottom {Bottom} left {Left} right {Right} other {An}} edge handle", + "editor_orientation": "Orientation", + "editor_reset_all_changes": "Reset changes", + "editor_rotate_left": "Rotate 90° anticlockwise", + "editor_rotate_right": "Rotate 90° clockwise", + "email": "Email", + "email_notifications": "Email notifications", + "empty_folder": "This folder is empty", + "empty_trash": "Empty bin", + "empty_trash_confirmation": "Are you sure you want to empty the bin? This will remove all the assets in the bin permanently from Immich.\nYou cannot undo this action!", + "enable": "Enable", + "enable_backup": "Enable Backup", + "enable_biometric_auth_description": "Enter your PIN code to enable biometric authentication", + "enabled": "Enabled", + "end_date": "End date", + "enqueued": "Enqueued", + "enter_wifi_name": "Enter Wi-Fi name", + "enter_your_pin_code": "Enter your PIN code", + "enter_your_pin_code_subtitle": "Enter your PIN code to access the locked folder", + "error": "Error", + "error_change_sort_album": "Failed to change album sort order", + "error_delete_face": "Error deleting face from asset", + "error_getting_places": "Error getting places", + "error_loading_albums": "Error loading albums", + "error_loading_image": "Error loading image", + "error_loading_partners": "Error loading partners: {error}", + "error_retrieving_asset_information": "Error retrieving asset information", + "error_saving_image": "Error: {error}", + "error_tag_face_bounding_box": "Error tagging face - cannot get bounding box coordinates", + "error_title": "Error - Something went wrong", + "error_while_navigating": "Error while navigating to asset", + "errors": { + "cannot_navigate_next_asset": "Cannot navigate to the next asset", + "cannot_navigate_previous_asset": "Cannot navigate to previous asset", + "cant_apply_changes": "Can't apply changes", + "cant_change_activity": "Can't {enabled, select, true {disable} other {enable}} activity", + "cant_change_asset_favorite": "Can't change favourite for asset", + "cant_change_metadata_assets_count": "Can't change metadata of {count, plural, one {# asset} other {# assets}}", + "cant_get_faces": "Can't get faces", + "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", + "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", + "error_downloading": "Error downloading {filename}", + "error_hiding_buy_button": "Error hiding buy button", + "error_removing_assets_from_album": "Error removing assets from album, check console for more details", + "error_selecting_all_assets": "Error selecting all assets", + "exclusion_pattern_already_exists": "This exclusion pattern already exists.", + "failed_to_create_album": "Failed to create album", + "failed_to_create_shared_link": "Failed to create shared link", + "failed_to_edit_shared_link": "Failed to edit shared link", + "failed_to_get_people": "Failed to get people", + "failed_to_keep_this_delete_others": "Failed to keep this asset and delete the other assets", + "failed_to_load_asset": "Failed to load asset", + "failed_to_load_assets": "Failed to load assets", + "failed_to_load_notifications": "Failed to load notifications", + "failed_to_load_people": "Failed to load people", + "failed_to_remove_product_key": "Failed to remove product key", + "failed_to_reset_pin_code": "Failed to reset PIN code", + "failed_to_stack_assets": "Failed to stack assets", + "failed_to_tag_assets": "Failed to tag assets", + "failed_to_unstack_assets": "Failed to un-stack assets", + "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", + "something_went_wrong": "Something went wrong", + "unable_to_add_album_users": "Unable to add users to album", + "unable_to_add_assets_to_shared_link": "Unable to add assets to shared link", + "unable_to_add_comment": "Unable to add comment", + "unable_to_add_exclusion_pattern": "Unable to add exclusion pattern", + "unable_to_add_partners": "Unable to add partners", + "unable_to_add_remove_archive": "Unable to {archived, select, true {remove asset from} other {add asset to}} archive", + "unable_to_add_remove_favorites": "Unable to {favorite, select, true {add asset to} other {remove asset from}} favourites", + "unable_to_archive_unarchive": "Unable to {archived, select, true {archive} other {unarchive}}", + "unable_to_change_album_user_role": "Unable to change the album user's role", + "unable_to_change_date": "Unable to change date", + "unable_to_change_description": "Unable to change description", + "unable_to_change_favorite": "Unable to change favourite for asset", + "unable_to_change_location": "Unable to change location", + "unable_to_change_password": "Unable to change password", + "unable_to_change_visibility": "Unable to change the visibility for {count, plural, one {# person} other {# people}}", + "unable_to_complete_oauth_login": "Unable to complete OAuth login", + "unable_to_connect": "Unable to connect", + "unable_to_copy_to_clipboard": "Cannot copy to clipboard, make sure you are accessing the page through https", + "unable_to_create": "Unable to create workflow", + "unable_to_create_admin_account": "Unable to create admin account", + "unable_to_create_api_key": "Unable to create a new API Key", + "unable_to_create_library": "Unable to create library", + "unable_to_create_user": "Unable to create user", + "unable_to_delete_album": "Unable to delete album", + "unable_to_delete_asset": "Unable to delete asset", + "unable_to_delete_assets": "Error deleting assets", + "unable_to_delete_exclusion_pattern": "Unable to delete exclusion pattern", + "unable_to_delete_shared_link": "Unable to delete shared link", + "unable_to_delete_user": "Unable to delete user", + "unable_to_delete_workflow": "Unable to delete workflow", + "unable_to_download_files": "Unable to download files", + "unable_to_edit_exclusion_pattern": "Unable to edit exclusion pattern", + "unable_to_empty_trash": "Unable to empty bin", + "unable_to_enter_fullscreen": "Unable to enter fullscreen", + "unable_to_exit_fullscreen": "Unable to exit fullscreen", + "unable_to_get_comments_number": "Unable to get number of comments", + "unable_to_get_shared_link": "Failed to get shared link", + "unable_to_hide_person": "Unable to hide person", + "unable_to_link_motion_video": "Unable to link motion video", + "unable_to_link_oauth_account": "Unable to link OAuth account", + "unable_to_log_out_all_devices": "Unable to log out all devices", + "unable_to_log_out_device": "Unable to log out device", + "unable_to_login_with_oauth": "Unable to login with OAuth", + "unable_to_play_video": "Unable to play video", + "unable_to_reassign_assets_existing_person": "Unable to reassign assets to {name, select, null {an existing person} other {{name}}}", + "unable_to_reassign_assets_new_person": "Unable to reassign assets to a new person", + "unable_to_refresh_user": "Unable to refresh user", + "unable_to_remove_album_users": "Unable to remove users from album", + "unable_to_remove_api_key": "Unable to remove API Key", + "unable_to_remove_assets_from_shared_link": "Unable to remove assets from shared link", + "unable_to_remove_library": "Unable to remove library", + "unable_to_remove_partner": "Unable to remove partner", + "unable_to_remove_reaction": "Unable to remove reaction", + "unable_to_reset_password": "Unable to reset password", + "unable_to_reset_pin_code": "Unable to reset PIN code", + "unable_to_resolve_duplicate": "Unable to resolve duplicate", + "unable_to_restore_assets": "Unable to restore assets", + "unable_to_restore_trash": "Unable to restore bin", + "unable_to_restore_user": "Unable to restore user", + "unable_to_save_album": "Unable to save album", + "unable_to_save_api_key": "Unable to save API Key", + "unable_to_save_date_of_birth": "Unable to save date of birth", + "unable_to_save_name": "Unable to save name", + "unable_to_save_profile": "Unable to save profile", + "unable_to_save_settings": "Unable to save settings", + "unable_to_scan_libraries": "Unable to scan libraries", + "unable_to_scan_library": "Unable to scan library", + "unable_to_set_feature_photo": "Unable to set feature photo", + "unable_to_set_profile_picture": "Unable to set profile picture", + "unable_to_set_rating": "Unable to set rating", + "unable_to_submit_job": "Unable to submit job", + "unable_to_trash_asset": "Unable to bin asset", + "unable_to_unlink_account": "Unable to unlink account", + "unable_to_unlink_motion_video": "Unable to unlink motion video", + "unable_to_update_album_cover": "Unable to update album cover", + "unable_to_update_album_info": "Unable to update album info", + "unable_to_update_library": "Unable to update library", + "unable_to_update_location": "Unable to update location", + "unable_to_update_settings": "Unable to update settings", + "unable_to_update_timeline_display_status": "Unable to update timeline display status", + "unable_to_update_user": "Unable to update user", + "unable_to_update_workflow": "Unable to update workflow", + "unable_to_upload_file": "Unable to upload file" + }, + "errors_text": "Errors", + "exclusion_pattern": "Exclusion pattern", + "exif": "Exif", + "exif_bottom_sheet_description": "Add Description...", + "exif_bottom_sheet_description_error": "Error updating description", + "exif_bottom_sheet_details": "DETAILS", + "exif_bottom_sheet_location": "LOCATION", + "exif_bottom_sheet_no_description": "No description", + "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", + "experimental_settings_subtitle": "Use at your own risk!", + "experimental_settings_title": "Experimental", + "expire_after": "Expire after", + "expired": "Expired", + "expires_date": "Expires {date}", + "explore": "Explore", + "explorer": "Explorer", + "export": "Export", + "export_as_json": "Export as JSON", + "export_database": "Export Database", + "export_database_description": "Export the SQLite database", + "exposure_time": "Exposure Time", + "extension": "Extension", + "external": "External", + "external_libraries": "External Libraries", + "external_network": "External network", + "external_network_sheet_info": "When not on the preferred Wi-Fi network, the app will connect to the server through the first of the below URLs it can reach, starting from top to bottom", + "f_number": "F-Number", + "face_unassigned": "Unassigned", + "failed": "Failed", + "failed_count": "Failed: {count}", + "failed_to_authenticate": "Failed to authenticate", + "failed_to_delete_file": "Failed to delete file", + "failed_to_load_assets": "Failed to load assets", + "failed_to_load_folder": "Failed to load folder", + "favorite": "Favourite", + "favorite_action_prompt": "{count} added to Favourites", + "favorite_or_unfavorite_photo": "Favourite or unfavourite photo", + "favorites": "Favourites", + "favorites_page_no_favorites": "No favourite assets found", + "feature_photo_updated": "Feature photo updated", + "features": "Features", + "features_in_development": "Features in Development", + "features_setting_description": "Manage the app features", + "file_name_or_extension": "File name or extension", + "file_name_text": "File name", + "file_size": "File size", + "filename": "Filename", + "filetype": "Filetype", + "filter": "Filter", + "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", + "fix_incorrect_match": "Fix incorrect match", + "focal_length": "Focal Length", + "folder": "Folder", + "folder_not_found": "Folder not found", + "folders": "Folders", + "folders_feature_description": "Browsing the folder view for the photos and videos on the file system", + "forgot_pin_code_question": "Forgotten your PIN?", + "forward": "Forward", + "free_up_space": "Free Up Space", + "free_up_space_description": "Move backed-up photos and videos to your device's bin to free up space. Your copies on the server remain safe.", + "free_up_space_settings_subtitle": "Free up device storage", + "full_path": "Full path: {path}", + "full_path_or_folder": "Full path or folder", + "gcast_enabled": "Google Cast", + "gcast_enabled_description": "This feature loads external resources from Google in order to work.", + "general": "General", + "geolocation_instruction_location": "Click on an asset with GPS coordinates to use its location, or select a location directly from the map", + "get_help": "Get Help", + "get_people_error": "Error getting people", + "get_wifiname_error": "Could not get Wi-Fi name. Make sure you have granted the necessary permissions and are connected to a Wi-Fi network", + "getting_started": "Getting Started", + "go_back": "Go back", + "go_to_folder": "Go to folder", + "go_to_search": "Go to search", + "gps": "GPS", + "gps_missing": "No GPS", + "grant_permission": "Grant permission", + "group_albums_by": "Group albums by...", + "group_country": "Group by country", + "group_no": "No grouping", + "group_owner": "Group by owner", + "group_places_by": "Group places by...", + "group_year": "Group by year", + "haptic_feedback_switch": "Enable haptic feedback", + "haptic_feedback_title": "Haptic Feedback", + "has_quota": "Has quota", + "hash_asset": "Hash asset", + "hashed_assets": "Hashed assets", + "hashing": "Hashing", + "header_settings_add_header_tip": "Add header", + "header_settings_field_validator_msg": "Value cannot be empty", + "header_settings_header_name_input": "Header name", + "header_settings_header_value_input": "Header value", + "headers_settings_tile_title": "Custom proxy headers", + "height": "Height", + "hi_user": "Hi {name} ({email})", + "hide_all_people": "Hide all people", + "hide_gallery": "Hide gallery", + "hide_named_person": "Hide person {name}", + "hide_password": "Hide password", + "hide_person": "Hide person", + "hide_schema": "Hide schema", + "hide_text_recognition": "Hide text recognition", + "hide_unnamed_people": "Hide unnamed people", + "home_page_add_to_album_conflicts": "Added {added} assets to album {album}. {failed} assets are already in the album.", + "home_page_add_to_album_err_local": "Can not add local assets to albums yet, skipping", + "home_page_add_to_album_success": "Added {added} assets to album {album}.", + "home_page_album_err_partner": "Can not add partner assets to an album yet, skipping", + "home_page_archive_err_local": "Can not archive local assets yet, skipping", + "home_page_archive_err_partner": "Can not archive partner assets, skipping", + "home_page_building_timeline": "Building the timeline", + "home_page_delete_err_partner": "Can not delete partner assets, skipping", + "home_page_delete_remote_err_local": "Local assets in delete remote selection, skipping", + "home_page_favorite_err_local": "Can not favourite local assets yet, skipping", + "home_page_favorite_err_partner": "Can not favourite partner assets yet, skipping", + "home_page_first_time_notice": "If this is your first time using the app, please make sure to choose a backup album so that the timeline can populate photos and videos in it", + "home_page_locked_error_local": "Can not move local assets to locked folder, skipping", + "home_page_locked_error_partner": "Can not move partner assets to locked folder, skipping", + "home_page_share_err_local": "Can not share local assets via link, skipping", + "home_page_upload_err_limit": "Can only upload a maximum of 30 assets at a time, skipping", + "host": "Host", + "hour": "Hour", + "hours": "Hours", + "id": "ID", + "idle": "Idle", + "ignore_icloud_photos": "Ignore iCloud photos", + "ignore_icloud_photos_description": "Photos that are stored on iCloud will not be uploaded to the Immich server", + "image": "Image", + "image_alt_text_date": "{isVideo, select, true {Video} other {Image}} taken on {date}", + "image_alt_text_date_1_person": "{isVideo, select, true {Video} other {Image}} taken with {person1} on {date}", + "image_alt_text_date_2_people": "{isVideo, select, true {Video} other {Image}} taken with {person1} and {person2} on {date}", + "image_alt_text_date_3_people": "{isVideo, select, true {Video} other {Image}} taken with {person1}, {person2}, and {person3} on {date}", + "image_alt_text_date_4_or_more_people": "{isVideo, select, true {Video} other {Image}} taken with {person1}, {person2}, and {additionalCount, number} others on {date}", + "image_alt_text_date_place": "{isVideo, select, true {Video} other {Image}} taken in {city}, {country} on {date}", + "image_alt_text_date_place_1_person": "{isVideo, select, true {Video} other {Image}} taken in {city}, {country} with {person1} on {date}", + "image_alt_text_date_place_2_people": "{isVideo, select, true {Video} other {Image}} taken in {city}, {country} with {person1} and {person2} on {date}", + "image_alt_text_date_place_3_people": "{isVideo, select, true {Video} other {Image}} taken in {city}, {country} with {person1}, {person2}, and {person3} on {date}", + "image_alt_text_date_place_4_or_more_people": "{isVideo, select, true {Video} other {Image}} taken in {city}, {country} with {person1}, {person2}, and {additionalCount, number} others on {date}", + "image_saved_successfully": "Image saved", + "image_viewer_page_state_provider_download_started": "Download Started", + "image_viewer_page_state_provider_download_success": "Download Success", + "image_viewer_page_state_provider_share_error": "Share Error", + "immich_logo": "Immich Logo", + "immich_web_interface": "Immich Web Interface", + "import_from_json": "Import from JSON", + "import_path": "Import path", + "in_albums": "In {count, plural, one {# album} other {# albums}}", + "in_archive": "In archive", + "in_year": "In {year}", + "in_year_selector": "In", + "include_archived": "Include archived", + "include_shared_albums": "Include shared albums", + "include_shared_partner_assets": "Include shared partner assets", + "individual_share": "Individual share", + "individual_shares": "Individual shares", + "info": "Info", + "integrity_checks": "Integrity Checks", + "interval": { + "day_at_onepm": "Every day at 1pm", + "hours": "Every {hours, plural, one {hour} other {{hours, number} hours}}", + "night_at_midnight": "Every night at midnight", + "night_at_twoam": "Every night at 2am" + }, + "invalid_date": "Invalid date", + "invalid_date_format": "Invalid date format", + "invite_people": "Invite People", + "invite_to_album": "Invite to album", + "ios_debug_info_fetch_ran_at": "Fetch ran {dateTime}", + "ios_debug_info_last_sync_at": "Last sync {dateTime}", + "ios_debug_info_no_processes_queued": "No background processes queued", + "ios_debug_info_no_sync_yet": "No background sync job has run yet", + "ios_debug_info_processes_queued": "{count, plural, one {{count} background process queued} other {{count} background processes queued}}", + "ios_debug_info_processing_ran_at": "Processing ran {dateTime}", + "iso": "ISO", + "items_count": "{count, plural, one {# item} other {# items}}", + "jobs": "Jobs", + "json_editor": "JSON editor", + "json_error": "JSON error", + "keep": "Keep", + "keep_albums": "Keep albums", + "keep_albums_count": "Keeping {count} {count, plural, one {album} other {albums}}", + "keep_all": "Keep All", + "keep_description": "Choose what stays on your device when freeing up space.", + "keep_favorites": "Keep favourites", + "keep_on_device": "Keep on device", + "keep_on_device_hint": "Select items to keep on this device", + "keep_this_delete_others": "Keep this, delete others", + "keeping": "Keeping: {items}", + "kept_this_deleted_others": "Kept this asset and deleted {count, plural, one {# asset} other {# assets}}", + "keyboard_shortcuts": "Keyboard shortcuts", + "language": "Language", + "language_no_results_subtitle": "Try adjusting your search term", + "language_no_results_title": "No languages found", + "language_search_hint": "Search languages...", + "language_setting_description": "Select your preferred language", + "large_files": "Large Files", + "last": "Last", + "last_months": "{count, plural, one {Last month} other {Last # months}}", + "last_seen": "Last seen", + "latest_version": "Latest Version", + "latitude": "Latitude", + "leave": "Leave", + "leave_album": "Leave album", + "lens_model": "Lens model", + "less": "Less", + "let_others_respond": "Let others respond", + "level": "Level", + "library": "Library", + "library_add_folder": "Add folder", + "library_edit_folder": "Edit folder", + "library_options": "Library options", + "library_page_device_albums": "Albums on Device", + "library_page_new_album": "New album", + "library_page_sort_asset_count": "Number of assets", + "library_page_sort_created": "Created date", + "library_page_sort_last_modified": "Last modified", + "library_page_sort_title": "Album title", + "licenses": "Licences", + "light": "Light", + "light_theme": "Switch to light theme", + "like": "Like", + "like_deleted": "Like deleted", + "link": "Link", + "link_motion_video": "Link motion video", + "link_to_docs": "For more information, refer to the documentation.", + "link_to_oauth": "Link to OAuth", + "linked_oauth_account": "Linked OAuth account", + "list": "List", + "live": "Live", + "load_more": "Load More", + "loading": "Loading", + "loading_search_results_failed": "Loading search results failed", + "local": "Local", + "local_asset_cast_failed": "Unable to cast an asset that is not uploaded to the server", + "local_assets": "Local Assets", + "local_id": "Local ID", + "local_media_summary": "Local Media Summary", + "local_network": "Local network", + "local_network_sheet_info": "The app will connect to the server through this URL when using the specified Wi-Fi network", + "location": "Location", + "location_permission": "Location permission", + "location_permission_content": "In order to use the auto-switching feature, Immich needs precise location permission so it can read the current Wi-Fi network's name", + "location_picker_choose_on_map": "Choose on map", + "location_picker_latitude_error": "Enter a valid latitude", + "location_picker_latitude_hint": "Enter your latitude here", + "location_picker_longitude_error": "Enter a valid longitude", + "location_picker_longitude_hint": "Enter your longitude here", + "lock": "Lock", + "locked_folder": "Locked Folder", + "log_detail_title": "Log Detail", + "log_out": "Log out", + "log_out_all_devices": "Log Out All Devices", + "logged_in_as": "Logged in as {user}", + "logged_out_all_devices": "Logged out all devices", + "logged_out_device": "Logged out device", + "login": "Login", + "login_disabled": "Login has been disabled", + "login_form_api_exception": "API exception. Please check the server URL and try again.", + "login_form_back_button_text": "Back", + "login_form_email_hint": "youremail@email.uk", + "login_form_endpoint_hint": "http://your-server-ip:port", + "login_form_endpoint_url": "Server Endpoint URL", + "login_form_err_http": "Please specify http:// or https://", + "login_form_err_invalid_email": "Invalid Email", + "login_form_err_invalid_url": "Invalid URL", + "login_form_err_leading_whitespace": "Leading whitespace", + "login_form_err_trailing_whitespace": "Trailing whitespace", + "login_form_failed_get_oauth_server_config": "Error logging using OAuth, check server URL", + "login_form_failed_get_oauth_server_disable": "OAuth feature is not available on this server", + "login_form_failed_login": "Error logging you in, check server URL, email and password", + "login_form_handshake_exception": "There was an Handshake Exception with the server. Enable self-signed certificate support in the settings if you are using a self-signed certificate.", + "login_form_password_hint": "password", + "login_form_save_login": "Stay logged in", + "login_form_server_empty": "Enter a server URL.", + "login_form_server_error": "Could not connect to server.", + "login_has_been_disabled": "Login has been disabled.", + "login_password_changed_error": "There was an error updating your password", + "login_password_changed_success": "Password updated successfully", + "logout_all_device_confirmation": "Are you sure you want to log out all devices?", + "logout_this_device_confirmation": "Are you sure you want to log out this device?", + "logs": "Logs", + "longitude": "Longitude", + "look": "Look", + "loop_videos": "Loop videos", + "loop_videos_description": "Enable to automatically loop a video in the detail viewer.", + "main_branch_warning": "You're using a development version; we strongly recommend using a release version!", + "main_menu": "Main menu", + "maintenance_action_restore": "Restoring Database", + "maintenance_description": "Immich has been put into maintenance mode.", + "maintenance_end": "End maintenance mode", + "maintenance_end_error": "Failed to end maintenance mode.", + "maintenance_logged_in_as": "Currently logged in as {user}", + "maintenance_restore_from_backup": "Restore From Backup", + "maintenance_restore_library": "Restore Your Library", + "maintenance_restore_library_confirm": "If this looks correct, continue to restoring a backup!", + "maintenance_restore_library_description": "Restoring Database", + "maintenance_restore_library_folder_has_files": "{folder} has {count} folder(s)", + "maintenance_restore_library_folder_no_files": "{folder} is missing files!", + "maintenance_restore_library_folder_pass": "readable and writable", + "maintenance_restore_library_folder_read_fail": "not readable", + "maintenance_restore_library_folder_write_fail": "not writable", + "maintenance_restore_library_hint_missing_files": "You may be missing important files", + "maintenance_restore_library_hint_regenerate_later": "You can regenerate these later in settings", + "maintenance_restore_library_hint_storage_template_missing_files": "Using storage template? You may be missing files", + "maintenance_restore_library_loading": "Loading integrity checks and heuristics…", + "maintenance_task_backup": "Creating a backup of the existing database…", + "maintenance_task_migrations": "Running database migrations…", + "maintenance_task_restore": "Restoring the chosen backup…", + "maintenance_task_rollback": "Restore failed, rolling back to restore point…", + "maintenance_title": "Temporarily Unavailable", + "make": "Make", + "manage_geolocation": "Manage location", + "manage_media_access_rationale": "This permission is required for proper handling of moving assets to the trash and restoring them from it.", + "manage_media_access_settings": "Open settings", + "manage_media_access_subtitle": "Allow the Immich app to manage and move media files.", + "manage_media_access_title": "Media Management Access", + "manage_shared_links": "Manage shared links", + "manage_sharing_with_partners": "Manage sharing with partners", + "manage_the_app_settings": "Manage the app settings", + "manage_your_account": "Manage your account", + "manage_your_api_keys": "Manage your API keys", + "manage_your_devices": "Manage your logged-in devices", + "manage_your_oauth_connection": "Manage your OAuth connection", + "map": "Map", + "map_assets_in_bounds": "{count, plural, =0 {No photos in this area} one {# photo} other {# photos}}", + "map_cannot_get_user_location": "Cannot get user's location", + "map_location_dialog_yes": "Yes", + "map_location_picker_page_use_location": "Use this location", + "map_location_service_disabled_content": "Location service needs to be enabled to display assets from your current location. Do you want to enable it now?", + "map_location_service_disabled_title": "Location Service disabled", + "map_marker_for_images": "Map marker for images taken in {city}, {country}", + "map_marker_with_image": "Map marker with image", + "map_no_location_permission_content": "Location permission is needed to display assets from your current location. Do you want to allow it now?", + "map_no_location_permission_title": "Location Permission denied", + "map_settings": "Map settings", + "map_settings_dark_mode": "Dark mode", + "map_settings_date_range_option_day": "Past 24 hours", + "map_settings_date_range_option_days": "Past {days} days", + "map_settings_date_range_option_year": "Past year", + "map_settings_date_range_option_years": "Past {years} years", + "map_settings_dialog_title": "Map Settings", + "map_settings_include_show_archived": "Include Archived", + "map_settings_include_show_partners": "Include Partners", + "map_settings_only_show_favorites": "Show Favourite Only", + "map_settings_theme_settings": "Map Theme", + "map_zoom_to_see_photos": "Zoom out to see photos", + "mark_all_as_read": "Mark all as read", + "mark_as_read": "Mark as read", + "marked_all_as_read": "Marked all as read", + "matches": "Matches", + "matching_assets": "Matching Assets", + "media_chrome": { + "auto": "Auto", + "captions": "Captions", + "captions_off": "Off", + "closed_captions": "closed captions", + "decode_error": "Decode error", + "disable_captions": "Disable captions", + "enable_captions": "Enable captions", + "enter_fullscreen_mode": "Enter fullscreen mode", + "exit_fullscreen_mode": "Exit fullscreen mode", + "loop": "Loop", + "media_error_description": "A media error caused playback to be aborted. The media could be corrupt or your browser does not support this format.", + "media_loading": "media loading", + "mute": "Mute", + "network_error": "Network error", + "network_error_description": "A network error caused the media download to fail.", + "not_supported_error": "Source Not Supported", + "playback_rate": "Playback rate", + "playback_rate_current": "current playback rate", + "playback_rate_value": "Playback rate {playbackRate}", + "playback_time": "playback time", + "quality": "Quality", + "second": "second", + "seconds": "seconds", + "time_value_of_total_time": "{currentTime} of {totalTime}", + "time_value_remaining": "{time} remaining", + "unmute": "Unmute", + "unsupported_error_description": "An unsupported error occurred. The server or network failed, or your browser does not support this format.", + "video_not_loaded_unknown_time": "video not loaded, unknown time.", + "video_player": "video player", + "volume": "volume" + }, + "media_type": "Media type", + "memories": "Memories", + "memories_all_caught_up": "All caught up", + "memories_check_back_tomorrow": "Check back tomorrow for more memories", + "memories_setting_description": "Manage what you see in your memories", + "memories_start_over": "Start Over", + "memories_swipe_to_close": "Swipe up to close", + "memory": "Memory", + "memory_lane_title": "Memory Lane {title}", + "menu": "Menu", + "merge": "Merge", + "merge_people": "Merge people", + "merge_people_limit": "You can only merge up to 5 faces at a time", + "merge_people_prompt": "Do you want to merge these people? This action is irreversible.", + "merge_people_successfully": "Merge people successfully", + "merged_people_count": "Merged {count, plural, one {# person} other {# people}}", + "minFaces": "Minimum faces", + "minFaces_description": "The minimum number of recognised faces for a person to be displayed", + "minimize": "Minimise", + "minute": "Minute", + "minutes": "Minutes", + "mirror_horizontal": "Horizontal", + "mirror_vertical": "Vertical", + "missing": "Missing", + "mobile_app": "Mobile App", + "mobile_app_download_onboarding_note": "Download the companion mobile app using the following options", + "model": "Model", + "modify_date": "Modify Date", + "month": "Month", + "more": "More", + "motion": "Motion", + "move": "Move", + "move_down": "Move down", + "move_off_locked_folder": "Move out of locked folder", + "move_to": "Move to", + "move_to_device_trash": "Move to device bin", + "move_to_lock_folder_action_prompt": "{count} added to the locked folder", + "move_to_locked_folder": "Move to locked folder", + "move_to_locked_folder_confirmation": "These photos and video will be removed from all albums, and only viewable from the locked folder", + "move_up": "Move up", + "moved_to_archive": "Moved {count, plural, one {# asset} other {# assets}} to archive", + "moved_to_library": "Moved {count, plural, one {# asset} other {# assets}} to library", + "moved_to_trash": "Moved to bin", + "multiselect_grid_edit_date_time_err_read_only": "Cannot edit date of read only asset(s), skipping", + "multiselect_grid_edit_gps_err_read_only": "Cannot edit location of read only asset(s), skipping", + "mute_memories": "Mute Memories", + "my_albums": "My albums", + "my_immich_description": "Copy current page as a My Immich link", + "my_immich_title": "My Immich link", + "name": "Name", + "name_or_nickname": "Name or nickname", + "name_required": "Name is required", + "navigate": "Navigate", + "navigate_to_time": "Navigate to Time", + "network_requirement_photos_upload": "Use mobile data to backup photos", + "network_requirement_videos_upload": "Use mobile data to backup videos", + "network_requirements": "Network Requirements", + "network_requirements_updated": "Network requirements changed, resetting backup queue", + "networking_settings": "Networking", + "networking_subtitle": "Manage the server endpoint settings", + "never": "Never", + "new_album": "New Album", + "new_api_key": "New API Key", + "new_date_range": "New date range", + "new_password": "New password", + "new_person": "New person", + "new_pin_code": "New PIN code", + "new_pin_code_subtitle": "This is your first time accessing the locked folder. Create a PIN code to securely access this page", + "new_timeline": "New Timeline", + "new_update": "New update", + "new_user_created": "New user created", + "new_version_available": "NEW VERSION AVAILABLE", + "newest_first": "Newest first", + "next": "Next", + "next_memory": "Next memory", + "no": "No", + "no_albums_found": "No albums found", + "no_albums_message": "Create an album to organise your photos and videos", + "no_albums_with_name_yet": "It looks like you do not have any albums with this name yet.", + "no_albums_yet": "It looks like you do not have any albums yet.", + "no_archived_assets_message": "Archive photos and videos to hide them from your Photos view", + "no_assets_message": "Click to upload your first photo", + "no_assets_to_show": "No assets to show", + "no_cast_devices_found": "No cast devices found", + "no_checksum_local": "No checksum available - cannot fetch local assets", + "no_checksum_remote": "No checksum available - cannot fetch remote asset", + "no_configuration_needed": "No configuration needed", + "no_devices": "No authorised devices", + "no_duplicates_found": "No duplicates were found.", + "no_exif_info_available": "No exif info available", + "no_explore_results_message": "Upload more photos to explore your collection.", + "no_favorites_message": "Add favourites to quickly find your best pictures and videos", + "no_libraries_message": "Create an external library to view your photos and videos", + "no_local_assets_found": "No local assets found with this checksum", + "no_location_set": "No location set", + "no_locked_photos_message": "Photos and videos in the locked folder are hidden and won't show up as you browse or search your library.", + "no_name": "No Name", + "no_notifications": "No notifications", + "no_people_found": "No matching people found", + "no_places": "No places", + "no_remote_assets_found": "No remote assets found with this checksum", + "no_results": "No results", + "no_results_description": "Try a synonym or more general keyword", + "no_shared_albums_message": "Create an album to share photos and videos with people in your network", + "no_steps": "No steps added yet", + "no_uploads_in_progress": "No uploads in progress", + "none": "None", + "not_allowed": "Not allowed", + "not_available": "N/A", + "not_in_any_album": "Not in any album", + "not_selected": "Not selected", + "notes": "Notes", + "nothing_here_yet": "Nothing here yet", + "notification_backup_reliability": "Enable notifications to improve background backup reliability", + "notification_permission_dialog_content": "To enable notifications, go to Settings and select allow.", + "notification_permission_list_tile_content": "Grant permission to enable notifications.", + "notification_permission_list_tile_enable_button": "Enable Notifications", + "notification_permission_list_tile_title": "Notification Permission", + "notification_toggle_setting_description": "Enable email notifications", + "notifications": "Notifications", + "notifications_setting_description": "Manage notifications", + "oauth": "OAuth", + "obtainium_configurator": "Obtainium Configurator", + "obtainium_configurator_instructions": "Use Obtainium to install and update the Android app directly from Immich GitHub's release. Create an API key and select a variant to create your Obtainium configuration link", + "ocr": "OCR", + "official_immich_resources": "Official Immich Resources", + "offline": "Offline", + "offset": "Offset", + "ok": "Ok", + "oldest_first": "Oldest first", + "on_this_device": "On this device", + "onboarding": "Onboarding", + "onboarding_locale_description": "Select your preferred language. You can change this later in your settings.", + "onboarding_privacy_description": "The following (optional) features rely on external services, and can be disabled at any time in settings.", + "onboarding_server_welcome_description": "Let's get your instance set up with some common settings.", + "onboarding_theme_description": "Choose a colour theme for your instance. You can change this later in your settings.", + "onboarding_user_welcome_description": "Let's get you started!", + "onboarding_welcome_user": "Welcome, {user}", + "online": "Online", + "only_favorites": "Only favourites", + "open": "Open", + "open_calendar": "Open calendar", + "open_in_browser": "Open in browser", + "open_in_map_view": "Open in map view", + "open_in_openstreetmap": "Open in OpenStreetMap", + "open_the_search_filters": "Open the search filters", + "options": "Options", + "or": "or", + "organize_into_albums": "Organise into albums", + "organize_into_albums_description": "Put existing photos into albums using current sync settings", + "organize_your_library": "Organise your library", + "orientation": "Orientation", + "original": "original", + "other": "Other", + "other_devices": "Other devices", + "other_entities": "Other entities", + "other_variables": "Other variables", + "owned": "Owned", + "owner": "Owner", + "page": "Page", + "partner": "Partner", + "partner_can_access": "{partner} can access", + "partner_can_access_assets": "All your photos and videos except those in Archived and Deleted", + "partner_can_access_location": "The location where your photos were taken", + "partner_list_user_photos": "{user}'s photos", + "partner_list_view_all": "View all", + "partner_page_empty_message": "Your photos are not yet shared with any partner.", + "partner_page_no_more_users": "No more users to add", + "partner_page_partner_add_failed": "Failed to add partner", + "partner_page_select_partner": "Select partner", + "partner_page_shared_to_title": "Shared to", + "partner_page_stop_sharing_content": "{partner} will no longer be able to access your photos.", + "partner_sharing": "Partner Sharing", + "partners": "Partners", + "password": "Password", + "password_does_not_match": "Password does not match", + "password_required": "Password Required", + "password_reset_success": "Password reset success", + "past_durations": { + "days": "Past {days, plural, one {day} other {# days}}", + "hours": "Past {hours, plural, one {hour} other {# hours}}", + "years": "Past {years, plural, one {year} other {# years}}" + }, + "path": "Path", + "pattern": "Pattern", + "pause": "Pause", + "pause_memories": "Pause memories", + "paused": "Paused", + "pending": "Pending", + "people": "People", + "people_edits_count": "Edited {count, plural, one {# person} other {# people}}", + "people_feature_description": "Browsing photos and videos grouped by people", + "people_selected": "{count, plural, one {# person selected} other {# people selected}}", + "people_sidebar_description": "Display a link to People in the sidebar", + "permanent_deletion_warning": "Permanent deletion warning", + "permanent_deletion_warning_setting_description": "Show a warning when permanently deleting assets", + "permanently_delete": "Permanently delete", + "permanently_delete_assets_count": "Permanently delete {count, plural, one {asset} other {assets}}", + "permanently_delete_assets_prompt": "Are you sure you want to permanently delete {count, plural, one {this asset?} other {these # assets?}} This will also remove {count, plural, one {it from its} other {them from their}} album(s).", + "permanently_deleted_asset": "Permanently deleted asset", + "permanently_deleted_assets_count": "Permanently deleted {count, plural, one {# asset} other {# assets}}", + "permission": "Permission", + "permission_empty": "Your permission shouldn't be empty", + "permission_onboarding_back": "Back", + "permission_onboarding_continue_anyway": "Continue anyway", + "permission_onboarding_get_started": "Get started", + "permission_onboarding_go_to_settings": "Go to settings", + "permission_onboarding_permission_denied": "Permission denied. To use Immich, grant photo and video permissions in Settings.", + "permission_onboarding_permission_granted": "Permission granted! You are all set.", + "permission_onboarding_permission_limited": "Permission limited. To let Immich backup and manage your entire gallery collection, grant photo and video permissions in Settings.", + "permission_onboarding_request": "Immich requires permission to view your photos and videos.", + "person": "Person", + "person_age_months": "{months, plural, one {# month} other {# months}} old", + "person_age_year_months": "1 year, {months, plural, one {# month} other {# months}} old", + "person_age_years": "{years, plural, other {# years}} old", + "person_birthdate": "Born on {date}", + "person_hidden": "{name}{hidden, select, true { (hidden)} other {}}", + "person_recognized": "Person recognised", + "person_selected": "Person selected", + "photo_shared_all_users": "Looks like you shared your photos with all users or you don't have any users to share with.", + "photos": "Photos", + "photos_and_videos": "Photos & Videos", + "photos_count": "{count, plural, one {{count, number} Photo} other {{count, number} Photos}}", + "photos_from_previous_years": "Photos from previous years", + "photos_only": "Photos only", + "pick_a_location": "Pick a location", + "pick_custom_range": "Custom range", + "pick_date_range": "Select a date range", + "pin_code_changed_successfully": "Successfully changed PIN code", + "pin_code_reset_successfully": "Successfully reset PIN code", + "pin_code_setup_successfully": "Successfully setup a PIN code", + "pin_verification": "PIN code verification", + "place": "Place", + "places": "Places", + "places_count": "{count, plural, one {{count, number} Place} other {{count, number} Places}}", + "play": "Play", + "play_memories": "Play memories", + "play_motion_photo": "Play Motion Photo", + "play_or_pause_video": "Play or pause video", + "play_original_video": "Play original video", + "play_original_video_setting_description": "Prefer playback of original videos rather than transcoded videos. If original asset is not compatible it may not playback correctly.", + "play_transcoded_video": "Play transcoded video", + "please_auth_to_access": "Please authenticate to access", + "plugin_method_filter_type": "Filter", + "plugin_method_filter_type_description": "This method can filter events and conditionally prevent subsequent steps from running", + "port": "Port", + "preferences_settings_subtitle": "Manage the app's preferences", + "preferences_settings_title": "Preferences", + "preparing": "Preparing", + "preset": "Preset", + "preview": "Preview", + "previous": "Previous", + "previous_memory": "Previous memory", + "previous_or_next_day": "Day forward/back", + "previous_or_next_month": "Month forward/back", + "previous_or_next_photo": "Photo forward/back", + "previous_or_next_year": "Year forward/back", + "primary": "Primary", + "privacy": "Privacy", + "profile": "Profile", + "profile_drawer_app_logs": "Logs", + "profile_drawer_client_server_up_to_date": "Client and Server are up-to-date", + "profile_drawer_github": "GitHub", + "profile_drawer_readonly_mode": "Read-only mode enabled. Long-press the user avatar icon to exit.", + "profile_image_of_user": "Profile image of {user}", + "profile_picture_set": "Profile picture set.", + "projection_type": "Projection Type", + "public_album": "Public album", + "public_share": "Public Share", + "purchase_account_info": "Supporter", + "purchase_activated_subtitle": "Thank you for supporting Immich and open-source software", + "purchase_activated_time": "Activated on {date}", + "purchase_activated_title": "Your key has been successfully activated", + "purchase_button_activate": "Activate", + "purchase_button_buy": "Buy", + "purchase_button_buy_immich": "Buy Immich", + "purchase_button_never_show_again": "Never show again", + "purchase_button_reminder": "Remind me in 30 days", + "purchase_button_remove_key": "Remove key", + "purchase_button_select": "Select", + "purchase_failed_activation": "Failed to activate! Please check your email for the correct product key!", + "purchase_individual_description_1": "For an individual", + "purchase_individual_description_2": "Supporter status", + "purchase_individual_title": "Individual", + "purchase_input_suggestion": "Have a product key? Enter the key below", + "purchase_license_subtitle": "Buy Immich to support the continued development of the service", + "purchase_lifetime_description": "Lifetime purchase", + "purchase_option_title": "PURCHASE OPTIONS", + "purchase_panel_info_1": "Building Immich takes a lot of time and effort, and we have full-time engineers working on it to make it as good as we possibly can. Our mission is for open-source software and ethical business practices to become a sustainable income source for developers and to create a privacy-respecting ecosystem with real alternatives to exploitative cloud services.", + "purchase_panel_info_2": "As we're committed not to add paywalls, this purchase will not grant you any additional features in Immich. We rely on users like you to support Immich's ongoing development.", + "purchase_panel_title": "Support the project", + "purchase_per_server": "Per server", + "purchase_per_user": "Per user", + "purchase_remove_product_key": "Remove Product Key", + "purchase_remove_product_key_prompt": "Are you sure you want to remove the product key?", + "purchase_remove_server_product_key": "Remove Server product key", + "purchase_remove_server_product_key_prompt": "Are you sure you want to remove the Server product key?", + "purchase_server_description_1": "For the whole server", + "purchase_server_description_2": "Supporter status", + "purchase_server_title": "Server", + "purchase_settings_server_activated": "The server product key is managed by the admin", + "query_asset_id": "Query Asset ID", + "queue_status": "Queuing {count}/{total}", + "rate_asset": "Rate Asset", + "rating": "Star rating", + "rating_clear": "Clear rating", + "rating_count": "{count, plural, =0 {Unrated} one {# star} other {# stars}}", + "rating_description": "Display the EXIF rating in the info panel", + "reaction_options": "Reaction options", + "read_changelog": "Read Changelog", + "readonly_mode_disabled": "Read-only mode disabled", + "readonly_mode_enabled": "Read-only mode enabled", + "ready_for_upload": "Ready for upload", + "reassign": "Reassign", + "reassigned_assets_to_existing_person": "Re-assigned {count, plural, one {# asset} other {# assets}} to {name, select, null {an existing person} other {{name}}}", + "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_searches": "Recent searches", + "recently_added": "Recently added", + "recently_added_page_title": "Recently Added", + "recently_taken": "Recently taken", + "recently_taken_page_title": "Recently Taken", + "refresh": "Refresh", + "refresh_encoded_videos": "Refresh encoded videos", + "refresh_faces": "Refresh faces", + "refresh_metadata": "Refresh metadata", + "refresh_thumbnails": "Refresh thumbnails", + "refreshed": "Refreshed", + "refreshes_every_file": "Re-reads all existing and new files", + "refreshing_encoded_video": "Refreshing encoded video", + "refreshing_faces": "Refreshing faces", + "refreshing_metadata": "Refreshing metadata", + "regenerating_thumbnails": "Regenerating thumbnails", + "remote": "Remote", + "remote_assets": "Remote Assets", + "remote_media_summary": "Remote Media Summary", + "remove": "Remove", + "remove_assets_album_confirmation": "Are you sure you want to remove {count, plural, one {# asset} other {# assets}} from the album?", + "remove_assets_shared_link_confirmation": "Are you sure you want to remove {count, plural, one {# asset} other {# assets}} from this shared link?", + "remove_assets_title": "Remove assets?", + "remove_custom_date_range": "Remove custom date range", + "remove_deleted_assets": "Remove Deleted Assets", + "remove_filter": "Remove filter", + "remove_from_album": "Remove from album", + "remove_from_album_action_prompt": "{count} removed from the album", + "remove_from_favorites": "Remove from favourites", + "remove_from_lock_folder_action_prompt": "{count} removed from the locked folder", + "remove_from_locked_folder": "Remove from locked folder", + "remove_from_locked_folder_confirmation": "Are you sure you want to move these photos and videos out of the locked folder? They will be visible in your library.", + "remove_from_shared_link": "Remove from shared link", + "remove_memory": "Remove memory", + "remove_photo_from_memory": "Remove photo from this memory", + "remove_tag": "Remove tag", + "remove_url": "Remove URL", + "remove_user": "Remove user", + "removed_api_key": "Removed API Key: {name}", + "removed_from_archive": "Removed from archive", + "removed_from_favorites": "Removed from favourites", + "removed_from_favorites_count": "{count, plural, other {Removed #}} from favourites", + "removed_memory": "Removed memory", + "removed_photo_from_memory": "Removed photo from memory", + "removed_tagged_assets": "Removed tag from {count, plural, one {# asset} other {# assets}}", + "rename": "Rename", + "repair": "Repair", + "repair_no_results_message": "Untracked and missing files will show up here", + "replace_with_upload": "Replace with upload", + "repository": "Repository", + "require_password": "Require password", + "require_user_to_change_password_on_first_login": "Require user to change password on first login", + "rescan": "Rescan", + "reset": "Reset", + "reset_password": "Reset password", + "reset_people_visibility": "Reset people visibility", + "reset_pin_code": "Reset PIN code", + "reset_pin_code_description": "If you forgot your PIN code, you can contact the server administrator to reset it", + "reset_pin_code_success": "Successfully reset PIN code", + "reset_pin_code_with_password": "You can always reset your PIN code with your password", + "reset_sqlite": "Reset SQLite Database", + "reset_sqlite_clear_app_data": "Clear Data", + "reset_sqlite_confirmation": "Are you sure you want to clear the app data? This will remove all settings and sign you out.", + "reset_sqlite_confirmation_note": "Note: You will need to restart the app after clearing.", + "reset_sqlite_done": "App data has been cleared. Please restart Immich and log in again.", + "reset_sqlite_success": "Successfully reset the SQLite database", + "reset_to_default": "Reset to default", + "resolution": "Resolution", + "resolve_duplicates": "Resolve duplicates", + "resolved_all_duplicates": "Resolved all duplicates", + "restore": "Restore", + "restore_all": "Restore all", + "restore_trash_action_prompt": "{count} restored from bin", + "restore_user": "Restore user", + "restored_asset": "Restored asset", + "resume": "Resume", + "resume_paused_jobs": "Resume {count, plural, one {# paused job} other {# paused jobs}}", + "retry_upload": "Retry upload", + "review_duplicates": "Review duplicates", + "review_large_files": "Review large files", + "role": "Role", + "role_editor": "Editor", + "role_viewer": "Viewer", + "running": "Running", + "save": "Save", + "save_to_gallery": "Save to gallery", + "saved": "Saved", + "saved_api_key": "Saved API Key", + "saved_profile": "Saved profile", + "saved_settings": "Saved settings", + "say_something": "Say something", + "scaffold_body_error_occurred": "Error occurred", + "scaffold_body_error_unrecoverable": "An unrecoverable error has occurred. Please share the error and stack trace on Discord or GitHub so we can help. If advised, you can clear the app data below.", + "scan": "Scan", + "scan_all_libraries": "Scan All Libraries", + "scan_library": "Scan", + "scan_settings": "Scan Settings", + "scanning": "Scanning", + "scanning_for_album": "Scanning for album...", + "screencast_mode_description": "Show keyboard and mouse event indicators on the screen", + "screencast_mode_title": "Toggle screencast mode", + "search": "Search", + "search_albums": "Search albums", + "search_by_context": "Search by context", + "search_by_description": "Search by description", + "search_by_description_example": "Hiking day in Sapa", + "search_by_filename": "Search by file name or extension", + "search_by_filename_example": "i.e. IMG_1234.JPG or PNG", + "search_by_full_path": "Search by full path or folder", + "search_by_full_path_example": "/John/Projects/3D_Printing/2026-07-01 - you can search for Projects, 3D, Printing, 2026 etc.", + "search_by_ocr": "Search by OCR", + "search_by_ocr_example": "Latte", + "search_camera_lens_model": "Search lens model...", + "search_camera_make": "Search camera make...", + "search_camera_model": "Search camera model...", + "search_city": "Search city...", + "search_country": "Search country...", + "search_filter_apply": "Apply filter", + "search_filter_camera_title": "Select camera type", + "search_filter_date": "Date", + "search_filter_date_interval": "{start} to {end}", + "search_filter_date_title": "Select a date range", + "search_filter_display_option_not_in_album": "Not in album", + "search_filter_display_options": "Display Options", + "search_filter_filename": "Search by file name", + "search_filter_location": "Location", + "search_filter_location_title": "Select location", + "search_filter_media_type": "Media Type", + "search_filter_media_type_title": "Select media type", + "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", + "search_no_people": "No people", + "search_no_people_named": "No people named \"{name}\"", + "search_no_result": "No results found, try a different search term or combination", + "search_options": "Search options", + "search_page_categories": "Categories", + "search_page_motion_photos": "Motion Photos", + "search_page_no_objects": "No Objects Info Available", + "search_page_no_places": "No Places Info Available", + "search_page_screenshots": "Screenshots", + "search_page_search_photos_videos": "Search for your photos and videos", + "search_page_selfies": "Selfies", + "search_page_things": "Things", + "search_page_view_all_button": "View all", + "search_page_your_activity": "Your activity", + "search_page_your_map": "Your Map", + "search_people": "Search people", + "search_places": "Search places", + "search_rating": "Search by rating...", + "search_result_page_new_search_hint": "New Search", + "search_settings": "Search settings", + "search_state": "Search state...", + "search_suggestion_list_smart_search_hint_1": "Smart search is enabled by default, to search for metadata use the syntax ", + "search_suggestion_list_smart_search_hint_2": "m:your-search-term", + "search_tags": "Search tags...", + "search_timezone": "Search timezone...", + "search_type": "Search type", + "search_your_photos": "Search your photos", + "searching_locales": "Searching locales...", + "second": "Second", + "see_all_people": "See all people", + "select": "Select", + "select_album": "Select album", + "select_album_cover": "Select album cover", + "select_albums": "Select albums", + "select_all": "Select all", + "select_all_duplicates": "Select all duplicates", + "select_all_in": "Select all in {group}", + "select_avatar_color": "Select avatar colour", + "select_count": "{count, plural, one {Select #} other {Select #}}", + "select_cutoff_date": "Select cutoff date", + "select_face": "Select face", + "select_featured_photo": "Select featured photo", + "select_from_computer": "Select from computer", + "select_keep_all": "Select keep all", + "select_library_owner": "Select library owner", + "select_new_face": "Select new face", + "select_people": "Select people", + "select_person": "Select person", + "select_person_to_tag": "Select a person to tag", + "select_photos": "Select photos", + "select_quality": "Select quality", + "select_trash_all": "Select trash all", + "select_user_for_sharing_page_err_album": "Failed to create album", + "selected": "Selected", + "selected_count": "{count, plural, other {# selected}}", + "selected_gps_coordinates": "Selected GPS Coordinates", + "send_message": "Send message", + "send_welcome_email": "Send welcome email", + "server_endpoint": "Server Endpoint", + "server_info_box_app_version": "App Version", + "server_info_box_server_url": "Server URL", + "server_offline": "Server Offline", + "server_online": "Server Online", + "server_privacy": "Server Privacy", + "server_restarting_description": "This page will refresh momentarily.", + "server_restarting_title": "Server is restarting", + "server_stats": "Server Stats", + "server_update_available": "Server update is available", + "server_version": "Server Version", + "set": "Set", + "set_as_album_cover": "Set as album cover", + "set_as_featured_photo": "Set as featured photo", + "set_as_profile_picture": "Set as profile picture", + "set_date_of_birth": "Set date of birth", + "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", + "setting_image_viewer_preview_subtitle": "Enable to load a medium-resolution image. Disable to either directly load the original or only use the thumbnail.", + "setting_image_viewer_preview_title": "Load preview image", + "setting_image_viewer_title": "Images", + "setting_languages_apply": "Apply", + "setting_languages_subtitle": "Change the app's language", + "setting_notifications_notify_failures_grace_period": "Notify background backup failures: {duration}", + "setting_notifications_notify_hours": "{count} hours", + "setting_notifications_notify_immediately": "immediately", + "setting_notifications_notify_minutes": "{count} minutes", + "setting_notifications_notify_never": "never", + "setting_notifications_notify_seconds": "{count} seconds", + "setting_notifications_single_progress_subtitle": "Detailed upload progress information per asset", + "setting_notifications_single_progress_title": "Show background backup detail progress", + "setting_notifications_subtitle": "Adjust your notification preferences", + "setting_notifications_total_progress_subtitle": "Overall upload progress (done/total assets)", + "setting_notifications_total_progress_title": "Show background backup total progress", + "setting_video_viewer_auto_play_subtitle": "Automatically start playing videos when they are opened", + "setting_video_viewer_auto_play_title": "Auto play videos", + "setting_video_viewer_looping_title": "Looping", + "setting_video_viewer_original_video_subtitle": "When streaming a video from the server, play the original even when a transcode is available. May lead to buffering. Videos available locally are played in original quality regardless of this setting.", + "setting_video_viewer_original_video_title": "Force original video", + "settings": "Settings", + "settings_require_restart": "Please restart Immich to apply this setting", + "settings_saved": "Settings saved", + "setup_pin_code": "Setup a PIN code", + "share": "Share", + "share_action_prompt": "Shared {count} assets", + "share_add_photos": "Add photos", + "share_assets_selected": "{count} selected", + "share_dialog_preparing": "Preparing...", + "share_link": "Share Link", + "share_original": "Use original (large)", + "share_preview": "Use thumbnail (small)", + "shared": "Shared", + "shared_album_activities_input_disable": "Comment is disabled", + "shared_album_activity_remove_content": "Do you want to delete this activity?", + "shared_album_activity_remove_title": "Delete Activity", + "shared_album_section_people_action_error": "Error leaving/removing from album", + "shared_album_section_people_action_leave": "Remove user from album", + "shared_album_section_people_action_remove_user": "Remove user from album", + "shared_album_section_people_title": "PEOPLE", + "shared_by": "Shared by", + "shared_by_user": "Shared by {user}", + "shared_by_you": "Shared by you", + "shared_from_partner": "Photos from {partner}", + "shared_intent_upload_button_progress_text": "{current} / {total} Uploaded", + "shared_link_app_bar_title": "Shared Links", + "shared_link_clipboard_copied_massage": "Copied to clipboard", + "shared_link_clipboard_text": "Link: {link}\nPassword: {password}", + "shared_link_create_error": "Error while creating shared link", + "shared_link_custom_url_description": "Access this shared link with a custom URL", + "shared_link_edit_description_hint": "Enter the share description", + "shared_link_edit_expire_after_option_day": "1 day", + "shared_link_edit_expire_after_option_days": "{count} days", + "shared_link_edit_expire_after_option_hour": "1 hour", + "shared_link_edit_expire_after_option_hours": "{count} hours", + "shared_link_edit_expire_after_option_minute": "1 minute", + "shared_link_edit_expire_after_option_minutes": "{count} minutes", + "shared_link_edit_expire_after_option_months": "{count} months", + "shared_link_edit_expire_after_option_year": "{count} year", + "shared_link_edit_password_hint": "Enter the share password", + "shared_link_edit_submit_button": "Update link", + "shared_link_error_server_url_fetch": "Cannot fetch the server url", + "shared_link_expires_day": "Expires in {count} day", + "shared_link_expires_days": "Expires in {count} days", + "shared_link_expires_hour": "Expires in {count} hour", + "shared_link_expires_hours": "Expires in {count} hours", + "shared_link_expires_minute": "Expires in {count} minute", + "shared_link_expires_minutes": "Expires in {count} minutes", + "shared_link_expires_never": "Expires ∞", + "shared_link_expires_second": "Expires in {count} second", + "shared_link_expires_seconds": "Expires in {count} seconds", + "shared_link_individual_shared": "Individual shared", + "shared_link_info_chip_metadata": "EXIF", + "shared_link_manage_links": "Manage Shared links", + "shared_link_options": "Shared link options", + "shared_link_password_description": "Require a password to access this shared link", + "shared_links": "Shared links", + "shared_links_description": "Share photos and videos with a link", + "shared_photos_and_videos_count": "{assetCount, plural, other {# shared photos & videos.}}", + "shared_with_me": "Shared with me", + "shared_with_partner": "Shared with {partner}", + "sharing": "Sharing", + "sharing_enter_password": "Please enter the password to view this page.", + "sharing_page_album": "Shared albums", + "sharing_page_description": "Create shared albums to share photos and videos with people in your network.", + "sharing_page_empty_list": "EMPTY LIST", + "sharing_sidebar_description": "Display a link to Sharing in the sidebar", + "sharing_silver_appbar_create_shared_album": "New shared album", + "sharing_silver_appbar_share_partner": "Share with partner", + "shift_to_permanent_delete": "press ⇧ to permanently delete asset", + "show_album_options": "Show album options", + "show_albums": "Show albums", + "show_all_people": "Show all people", + "show_and_hide_people": "Show & hide people", + "show_file_location": "Show file location", + "show_gallery": "Show gallery", + "show_hidden_people": "Show hidden people", + "show_in_timeline": "Show in timeline", + "show_in_timeline_setting_description": "Show photos and videos from this user in your timeline", + "show_keyboard_shortcuts": "Show keyboard shortcuts", + "show_less": "Show less", + "show_metadata": "Show metadata", + "show_more_fields": "{count, plural, one {Show # more field} other {Show # more fields}}", + "show_or_hide_info": "Show or hide info", + "show_password": "Show password", + "show_person_options": "Show person options", + "show_progress_bar": "Show Progress Bar", + "show_schema": "Show schema", + "show_search_options": "Show search options", + "show_shared_links": "Show shared links", + "show_slideshow_metadata_overlay": "Show image info overlay", + "show_slideshow_transition": "Show slideshow transition", + "show_supporter_badge": "Supporter badge", + "show_supporter_badge_description": "Show a supporter badge", + "show_text_recognition": "Show text recognition", + "show_text_search_menu": "Show text search menu", + "shuffle": "Shuffle", + "sidebar": "Sidebar", + "sidebar_display_description": "Display a link to the view in the sidebar", + "sign_out": "Sign Out", + "sign_up": "Sign up", + "size": "Size", + "skip_to_content": "Skip to content", + "skip_to_folders": "Skip to folders", + "skip_to_tags": "Skip to tags", + "slideshow": "Slideshow", + "slideshow_metadata_overlay_mode": "Overlay content", + "slideshow_metadata_overlay_mode_description_only": "Description only", + "slideshow_metadata_overlay_mode_full": "Full", + "slideshow_repeat": "Repeat slideshow", + "slideshow_repeat_description": "Loop back to beginning when slideshow ends", + "slideshow_settings": "Slideshow settings", + "smart_album": "Smart album", + "some_assets_already_have_a_location_warning": "Some of the selected assets already have a location", + "sort_albums_by": "Sort albums by...", + "sort_created": "Date created", + "sort_items": "Number of items", + "sort_modified": "Date modified", + "sort_newest": "Newest photo", + "sort_oldest": "Oldest photo", + "sort_people_by_similarity": "Sort people by similarity", + "sort_recent": "Most recent photo", + "sort_title": "Title", + "source": "Source", + "stack": "Stack", + "stack_action_prompt": "{count} stacked", + "stack_duplicates": "Stack duplicates", + "stack_select_one_photo": "Select one main photo for the stack", + "stack_selected_photos": "Stack selected photos", + "stacked_assets_count": "Stacked {count, plural, one {# asset} other {# assets}}", + "stacktrace": "Stacktrace", + "start": "Start", + "start_date": "Start date", + "start_date_before_end_date": "Start date must be before end date", + "state": "State", + "status": "Status", + "step_delete": "Delete step", + "step_delete_confirm": "Are you sure you want to delete this step?", + "step_details": "Step details", + "steps": "Steps", + "steps_count": "{count, plural, one {# step} other {# steps}}", + "stop_casting": "Stop casting", + "stop_motion_photo": "Stop Motion Photo", + "stop_photo_sharing": "Stop sharing your photos?", + "stop_photo_sharing_description": "{partner} will no longer be able to access your photos.", + "stop_sharing_photos_with_user": "Stop sharing your photos with this user", + "storage": "Storage space", + "storage_label": "Storage label", + "storage_quota": "Storage Quota", + "storage_usage": "{used} of {available} used", + "submit": "Submit", + "success": "Success", + "suggestions": "Suggestions", + "sunrise_on_the_beach": "Sunrise on the beach", + "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", + "sync_albums_manual_subtitle": "Sync all uploaded videos and photos to the selected backup albums", + "sync_local": "Sync Local", + "sync_remote": "Sync Remote", + "sync_status": "Sync Status", + "sync_status_subtitle": "View and manage the sync system", + "sync_upload_album_setting_subtitle": "Create and upload your photos and videos to the selected albums on Immich", + "system_theme": "System theme", + "system_theme_command_description": "Use the system theme ({value})", + "tag": "Tag", + "tag_assets": "Tag assets", + "tag_created": "Created tag: {tag}", + "tag_face": "Tag face", + "tag_feature_description": "Browsing photos and videos grouped by logical tag topics", + "tag_not_found_question": "Cannot find a tag? Create a new tag.", + "tag_people": "Tag People", + "tag_updated": "Updated tag: {tag}", + "tagged_assets": "Tagged {count, plural, one {# asset} other {# assets}}", + "tags": "Tags", + "tap_to_run_job": "Tap to run job", + "template": "Template", + "text_recognition": "Text recognition", + "theme": "Theme", + "theme_selection": "Theme selection", + "theme_selection_description": "Automatically set the theme to light or dark based on your browser's system preference", + "theme_setting_asset_list_storage_indicator_title": "Show storage indicator on asset tiles", + "theme_setting_asset_list_tiles_per_row_title": "Number of assets per row ({count})", + "theme_setting_colorful_interface_subtitle": "Apply primary colour to background surfaces.", + "theme_setting_colorful_interface_title": "Colourful interface", + "theme_setting_image_viewer_quality_subtitle": "Adjust the quality of the detail image viewer", + "theme_setting_image_viewer_quality_title": "Image viewer quality", + "theme_setting_primary_color_subtitle": "Pick a colour for primary actions and accents.", + "theme_setting_primary_color_title": "Primary colour", + "theme_setting_system_primary_color_title": "Use system colour", + "theme_setting_system_theme_switch": "Automatic (Follow system setting)", + "theme_setting_theme_subtitle": "Choose the app's theme setting", + "theme_setting_three_stage_loading_subtitle": "Three-stage loading might increase the loading performance but causes significantly higher network load", + "theme_setting_three_stage_loading_title": "Enable three-stage loading", + "then": "Then", + "they_will_be_merged_together": "They will be merged together", + "third_party_resources": "Third-Party Resources", + "time": "Time", + "time_based_memories": "Time-based memories", + "time_based_memories_duration": "Number of seconds to display each image.", + "timeline": "Timeline", + "timezone": "Timezone", + "to_archive": "Archive", + "to_change_password": "Change password", + "to_favorite": "Favourite", + "to_login": "Login", + "to_multi_select": "to multi-select", + "to_parent": "Go to parent", + "to_select": "to select", + "to_trash": "Bin", + "toggle_settings": "Toggle settings", + "toggle_theme_description": "Toggle theme", + "total": "Total", + "total_usage": "Total usage", + "trash": "Bin", + "trash_action_prompt": "{count} moved to bin", + "trash_all": "Bin All", + "trash_count": "Bin {count, number}", + "trash_delete_asset": "Bin/Delete Asset", + "trash_emptied": "Emptied bin", + "trash_no_results_message": "Binned photos and videos will show up here.", + "trash_page_delete_all": "Delete All", + "trash_page_empty_trash_dialog_content": "Do you want to empty your binned assets? These items will be permanently removed from Immich", + "trash_page_info": "Binned items will be permanently deleted after {days} days", + "trash_page_no_assets": "No binned assets", + "trash_page_restore_all": "Restore All", + "trash_page_select_assets_btn": "Select assets", + "trash_page_title": "Bin ({count})", + "trashed_items_will_be_permanently_deleted_after": "Binned items will be permanently deleted after {days, plural, one {# day} other {# days}}.", + "trigger": "Trigger", + "trigger_asset_metadata_extraction": "Asset Metadata Extraction", + "trigger_asset_metadata_extraction_description": "Triggered when the EXIF metadata of an asset is extracted", + "trigger_asset_uploaded": "Asset Upload", + "trigger_asset_uploaded_description": "Triggered when a new asset is uploaded", + "trigger_description": "An event that kicks off the workflow", + "trigger_person_recognized": "Person Recognised", + "trigger_person_recognized_description": "Triggered when a person is recognised", + "trigger_type": "Trigger type", + "troubleshoot": "Troubleshoot", + "type": "Type", + "unable_to_change_pin_code": "Unable to change PIN code", + "unable_to_check_version": "Unable to check app or server version", + "unable_to_setup_pin_code": "Unable to setup PIN code", + "unarchive": "Unarchive", + "unarchive_action_prompt": "{count} removed from Archive", + "unarchived_count": "{count, plural, other {Unarchived #}}", + "undo": "Undo", + "unfavorite": "Unfavourite", + "unfavorite_action_prompt": "{count} removed from Favourites", + "unhide_person": "Unhide person", + "unknown": "Unknown", + "unknown_country": "Unknown Country", + "unknown_date": "Unknown date", + "unknown_year": "Unknown Year", + "unlimited": "Unlimited", + "unlink_motion_video": "Unlink motion video", + "unlink_oauth": "Unlink OAuth", + "unlinked_oauth_account": "Unlinked OAuth account", + "unmute_memories": "Unmute Memories", + "unnamed_album": "Unnamed Album", + "unnamed_album_delete_confirmation": "Are you sure you want to delete this album?", + "unnamed_share": "Unnamed Share", + "unsaved_change": "Unsaved change", + "unselect_all": "Unselect all", + "unselect_all_duplicates": "Unselect all duplicates", + "unselect_all_in": "Unselect all in {group}", + "unstack": "Un-stack", + "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", + "up_next": "Up next", + "update_location_action_prompt": "Update the location of {count} selected assets with:", + "updated_at": "Updated", + "updated_password": "Updated password", + "upload": "Upload", + "upload_concurrency": "Upload concurrency", + "upload_day_count": "{date}: {count, plural, one {# upload} other {# uploads}}", + "upload_details": "Upload Details", + "upload_dialog_info": "Do you want to backup the selected Asset(s) to the server?", + "upload_dialog_title": "Upload Asset", + "upload_error_with_count": "Upload error for {count, plural, one {# asset} other {# assets}}", + "upload_errors": "Upload completed with {count, plural, one {# error} other {# errors}}, refresh the page to see new upload assets.", + "upload_finished": "Upload finished", + "upload_progress": "Remaining {remaining, number} - Processed {processed, number}/{total, number}", + "upload_skipped_duplicates": "Skipped {count, plural, one {# duplicate asset} other {# duplicate assets}}", + "upload_status_duplicates": "Duplicates", + "upload_status_errors": "Errors", + "upload_status_uploaded": "Uploaded", + "upload_success": "Upload success, refresh the page to see new upload assets.", + "upload_to_immich": "Upload to Immich ({count})", + "uploading": "Uploading", + "uploading_media": "Uploading media", + "uploads": "Uploads", + "uploads_count": "{count, plural, one {# upload} other {# uploads}}", + "url": "URL", + "usage": "Usage", + "use_biometric": "Use biometric", + "use_browser_locale": "Use browser locale", + "use_browser_locale_description": "Format dates, times, and numbers based on your browser locale", + "use_current_connection": "Use current connection", + "use_custom_date_range": "Use custom date range instead", + "use_template": "Use template", + "user": "User", + "user_has_been_deleted": "This user has been deleted.", + "user_id": "User ID", + "user_liked": "{user} liked {type, select, photo {this photo} video {this video} asset {this asset} other {it}}", + "user_pin_code_settings": "PIN Code", + "user_pin_code_settings_description": "Manage your PIN code", + "user_privacy": "User Privacy", + "user_purchase_settings": "Purchase", + "user_purchase_settings_description": "Manage your purchase", + "user_role_set": "Set {user} as {role}", + "user_usage_detail": "User usage detail", + "user_usage_stats": "Account usage statistics", + "user_usage_stats_description": "View account usage statistics", + "username": "Username", + "users": "Users", + "users_added_to_album_count": "Added {count, plural, one {# user} other {# users}} to the album", + "utilities": "Utilities", + "validate": "Validate", + "validate_endpoint_error": "Please enter a valid URL", + "validation_error": "Validation error", + "variables": "Variables", + "version": "Version", + "version_announcement_closing": "Your friend, Alex", + "version_announcement_message": "Hi there! A new version of Immich is available. Please take some time to read the release notes to ensure your setup is up-to-date to prevent any misconfigurations, especially if you use WatchTower or any mechanism that handles updating your Immich instance automatically.", + "version_history": "Version History", + "version_history_item": "Installed {version} on {date}", + "video": "Video", + "video_hover_setting": "Play video thumbnail on hover", + "video_hover_setting_description": "Play video thumbnail when mouse is hovering over item. Even when disabled, playback can be started by hovering over the play icon.", + "video_quality": "Video quality", + "videos": "Videos", + "videos_count": "{count, plural, one {# Video} other {# Videos}}", + "videos_only": "Videos only", + "view": "View", + "view_album": "View Album", + "view_all": "View All", + "view_all_users": "View all users", + "view_asset_owners": "View asset owners", + "view_details": "View Details", + "view_in_timeline": "View in timeline", + "view_link": "View link", + "view_links": "View links", + "view_name": "View", + "view_next_asset": "View next asset", + "view_previous_asset": "View previous asset", + "view_qr_code": "View QR code", + "view_similar_photos": "View similar photos", + "view_stack": "View Stack", + "view_user": "View User", + "viewer_remove_from_stack": "Remove from Stack", + "viewer_stack_use_as_main_asset": "Use as Main Asset", + "viewer_unstack": "Un-Stack", + "visibility": "Visibility", + "visibility_changed": "Visibility changed for {count, plural, one {# person} other {# people}}", + "visual": "Visual", + "visual_builder": "Visual builder", + "waiting": "Waiting", + "waiting_count": "Waiting: {count}", + "warning": "Warning", + "week": "Week", + "welcome": "Welcome", + "welcome_to_immich": "Welcome to Immich", + "when": "When", + "width": "Width", + "wifi_name": "Wi-Fi Name", + "workflow": "Workflow", + "workflow_delete_prompt": "Are you sure you want to delete this workflow?", + "workflow_deleted": "Workflow deleted", + "workflow_description": "Workflow description", + "workflow_info": "Workflow info", + "workflow_json": "Workflow JSON", + "workflow_json_help": "Edit the workflow configuration in JSON format. Changes will sync to the visual builder.", + "workflow_name": "Workflow name", + "workflow_navigation_prompt": "Are you sure you want to leave without saving your changes?", + "workflow_summary": "Workflow summary", + "workflow_templates": "Workflow templates", + "workflow_update_success": "Workflow updated successfully", + "workflow_updated": "Workflow updated", + "workflows": "Workflows", + "workflows_help_text": "Workflows automate actions on your assets based on triggers and filters", + "wrong_pin_code": "Wrong PIN code", + "x_of_total": "{x}/{total}", + "year": "Year", + "years_ago": "{years, plural, one {# year} other {# years}} ago", + "yes": "Yes", + "you_dont_have_any_shared_links": "You don't have any shared links", + "your_wifi_name": "Your Wi-Fi name", + "zero_to_clear_rating": "press 0 to clear asset rating", + "zoom_image": "Zoom Image", + "zoom_to_bounds": "Zoom to bounds" +} diff --git a/i18n/es.json b/i18n/es.json index cd2ae85c67..79d880a0f5 100644 --- a/i18n/es.json +++ b/i18n/es.json @@ -189,18 +189,23 @@ "machine_learning_smart_search_enabled": "Habilitar búsqueda inteligente", "machine_learning_smart_search_enabled_description": "Al desactivarlo las imágenes no se procesarán para usar la búsqueda inteligente.", "machine_learning_url_description": "La URL del servidor de aprendizaje automático. Si se proporciona más de una URL se intentará acceder a cada servidor sucesivamente hasta que uno responda correctamente en el orden especificado. Los servidores que no respondan serán ignorados temporalmente hasta que vuelvan a estar en línea.", + "maintenance_backup_management": "Gestión de respaldos", "maintenance_delete_backup": "Eliminar copia de seguridad", "maintenance_delete_backup_description": "Este archivo será eliminado de forma permanente.", "maintenance_delete_error": "Fallo al eliminar la copia de seguridad.", + "maintenance_integrity_check": "Verificar", "maintenance_integrity_check_all": "Comprobar todo", "maintenance_integrity_checksum_mismatch": "Discrepancia de checksum", + "maintenance_integrity_checksum_mismatch_description": "Archivos cuya suma de verificación en disco no coincide con la suma de verificación que Immich tiene almacenada en su base de datos.", "maintenance_integrity_checksum_mismatch_job": "Comprobar las discrepancias de checksum", "maintenance_integrity_checksum_mismatch_refresh_job": "Actualizar reportes de discrepancia de checksum", "maintenance_integrity_missing_file": "Archivos faltantes", + "maintenance_integrity_missing_file_description": "Archivos que Immich ha rastreado en su base de datos pero que no existen en el sistema de archivos.", "maintenance_integrity_missing_file_job": "Comprueba archivos faltantes", "maintenance_integrity_missing_file_refresh_job": "Actualizar informes de archivos faltantes", "maintenance_integrity_report": "Informe de integridad", "maintenance_integrity_untracked_file": "Archivos no rastreados", + "maintenance_integrity_untracked_file_description": "Archivos en los directorios de Immich de los que Immich no tiene ningún registro.", "maintenance_integrity_untracked_file_job": "Comprobar archivos no rastreados", "maintenance_integrity_untracked_file_refresh_job": "Actualizar informes de archivos no rastreados", "maintenance_restore_backup": "Restaurar copia de seguridad", @@ -2390,12 +2395,12 @@ "trashed_items_will_be_permanently_deleted_after": "Los elementos en la papelera serán eliminados permanentemente tras {days, plural, one {# día} other {# días}}.", "trigger": "Disparador", "trigger_asset_metadata_extraction": "Extracción de metadatos de los elementos", - "trigger_asset_metadata_extraction_description": "Se activa cuando se extraen los datos EXIF de un elemento", + "trigger_asset_metadata_extraction_description": "Se activa cuando se extraigan los datos EXIF de un elemento", "trigger_asset_uploaded": "Recurso subido", "trigger_asset_uploaded_description": "Se activa cuando se carga un nuevo recurso", "trigger_description": "Un evento que inicia el flujo de trabajo", "trigger_person_recognized": "Persona reconocida", - "trigger_person_recognized_description": "Se activa cuando se detecta una persona", + "trigger_person_recognized_description": "Se activa cuando se reconoce una persona", "trigger_type": "Tipo de disparador", "troubleshoot": "Solucionar problemas", "type": "Tipo", diff --git a/i18n/fr.json b/i18n/fr.json index f62c216975..2abc30143e 100644 --- a/i18n/fr.json +++ b/i18n/fr.json @@ -8,7 +8,7 @@ "action_description": "Un ensemble d'actions applicables sur des médias filtrés", "actions": "Actions", "active": "En cours", - "active_count": "Actif : {count}", + "active_count": "En cours : {count}", "activity": "Activité", "activity_changed": "Activité {enabled, select, true {activée} other {désactivée}}", "add": "Ajouter", @@ -189,19 +189,24 @@ "machine_learning_smart_search_enabled": "Activer la recherche intelligente", "machine_learning_smart_search_enabled_description": "Si cette option est désactivée, les images ne seront pas encodées pour la recherche intelligente.", "machine_learning_url_description": "L’URL du serveur d'apprentissage automatique. Si plusieurs URL sont fournies, chaque serveur sera essayé un par un jusqu’à ce que l’un d’eux réponde avec succès, dans l’ordre de la première à la dernière. Les serveurs ne répondant pas seront temporairement ignorés jusqu'à ce qu'ils soient de nouveau opérationnels.", + "maintenance_backup_management": "Gestion des sauvegardes", "maintenance_delete_backup": "Supprimer la sauvegarde", "maintenance_delete_backup_description": "Ce fichier sera définitivement supprimé.", "maintenance_delete_error": "Échec de la suppression de la sauvegarde.", + "maintenance_integrity_check": "Vérifier", "maintenance_integrity_check_all": "Tout cocher", "maintenance_integrity_checksum_mismatch": "Non correspondance de la somme de contrôle", + "maintenance_integrity_checksum_mismatch_description": "Fichiers dont la somme de contrôle sur le disque ne correspond pas à celle stockée dans la base de données d'Immich.", "maintenance_integrity_checksum_mismatch_job": "Vérifier la correspondance de la somme de contrôle", "maintenance_integrity_checksum_mismatch_refresh_job": "Rafraîchir les rapports de correspondance de la somme de contrôle", "maintenance_integrity_missing_file": "Fichiers manquants", + "maintenance_integrity_missing_file_description": "Fichiers suivis dans la base de données d'Immich mais inexistants sur le système de fichiers.", "maintenance_integrity_missing_file_job": "Détecter les fichiers manquants", "maintenance_integrity_missing_file_refresh_job": "Rafraîchir les rapports sur les fichiers manquants", "maintenance_integrity_report": "Rapport d'intégrité", "maintenance_integrity_untracked_file": "Fichiers non suivis", - "maintenance_integrity_untracked_file_job": "Détecter les fichiers non suivis", + "maintenance_integrity_untracked_file_description": "Fichiers présents dans les répertoires d'Immich mais absents de la base de données.", + "maintenance_integrity_untracked_file_job": "Vérifier les fichiers non suivis", "maintenance_integrity_untracked_file_refresh_job": "Rafraîchir les rapports de fichiers non suivis", "maintenance_restore_backup": "Restaurer la sauvegarde", "maintenance_restore_backup_description": "Immich sera effacé et restauré à partir de la sauvegarde choisie. Une sauvegarde sera créée avant de continuer.", @@ -2390,12 +2395,12 @@ "trashed_items_will_be_permanently_deleted_after": "Les éléments dans la corbeille seront supprimés définitivement après {days, plural, one {# jour} other {# jours}}.", "trigger": "Déclencheur", "trigger_asset_metadata_extraction": "Extraction des métadonnées du média", - "trigger_asset_metadata_extraction_description": "Déclenché quand les données EXIF d'un média sont extraites", + "trigger_asset_metadata_extraction_description": "Déclenché quand les métadonnées EXIF d'un média sont extraites", "trigger_asset_uploaded": "Téléversement du média", "trigger_asset_uploaded_description": "Déclenché lorsqu'un nouveau média est téléversé", "trigger_description": "Un événement qui active le flux de traitement", "trigger_person_recognized": "Personne reconnue", - "trigger_person_recognized_description": "Déclenché lorsqu'une personne est détectée", + "trigger_person_recognized_description": "Déclenché lorsqu'une personne est reconnue", "trigger_type": "Type de déclencheur", "troubleshoot": "Dépannage", "type": "Type", diff --git a/i18n/ga.json b/i18n/ga.json index 071c2242d8..5d930c2ecc 100644 --- a/i18n/ga.json +++ b/i18n/ga.json @@ -79,6 +79,7 @@ "cron_expression_description": "Socraigh an t-eatramh scanadh ag baint úsáide as an bhformáid cron. Le haghaidh tuilleadh eolais féach ar m.sh. Crontab Guru", "cron_expression_presets": "Réamhshocruithe léirithe Cron", "disable_login": "Díchumasaigh logáil isteach", + "download_csv": "Íoslódáil CSV", "duplicate_detection_job_description": "Rith foghlaim meaisín ar shócmhainní chun íomhánna comhchosúla a bhrath. Braitheann sé ar Chuardach Cliste", "exclusion_pattern_description": "Le patrúin eisiaimh, is féidir leat neamhaird a dhéanamh de chomhaid agus fillteáin agus tú ag scanadh do leabharlann. Tá sé seo úsáideach má tá fillteáin agat ina bhfuil comhaid nach mian leat a allmhairiú, amhail comhaid RAW.", "export_config_as_json_description": "Íoslódáil cumraíocht reatha an chórais mar chomhad JSON", @@ -191,6 +192,17 @@ "maintenance_delete_backup": "Scrios Cúltaca", "maintenance_delete_backup_description": "Scriosfar an comhad seo go neamh-inchúlghairthe.", "maintenance_delete_error": "Theip ar an gcúltaca a scriosadh.", + "maintenance_integrity_check_all": "Seiceáil Gach Rud", + "maintenance_integrity_checksum_mismatch": "Mí-chomhoiriúnacht suime seiceála", + "maintenance_integrity_checksum_mismatch_job": "Seiceáil le haghaidh mí-oiriúnuithe suime seiceála", + "maintenance_integrity_checksum_mismatch_refresh_job": "Athnuachan tuairiscí mí-oiriúnachta suime seiceála", + "maintenance_integrity_missing_file": "Comhaid ar Iarraidh", + "maintenance_integrity_missing_file_job": "Seiceáil le haghaidh comhaid atá ar iarraidh", + "maintenance_integrity_missing_file_refresh_job": "Athnuachan tuairiscí ar chomhaid atá ar iarraidh", + "maintenance_integrity_report": "Tuarascáil Ionracais", + "maintenance_integrity_untracked_file": "Comhaid Gan Rianú", + "maintenance_integrity_untracked_file_job": "Seiceáil le haghaidh comhaid neamhrianaithe", + "maintenance_integrity_untracked_file_refresh_job": "Athnuachan tuarascálacha comhad neamhrianaithe", "maintenance_restore_backup": "Athchóirigh Cúltaca", "maintenance_restore_backup_description": "Scriosfar agus athchóireofar Immich ón gcúltaca roghnaithe. Cruthófar cúltaca sula leanfar ar aghaidh.", "maintenance_restore_backup_different_version": "Cruthaíodh an cúltaca seo le leagan difriúil de Immich!", @@ -915,6 +927,8 @@ "deduplicate_all": "Dídhúblaigh Gach Rud", "default_locale": "Logán Réamhshocraithe", "default_locale_description": "Formáidigh dátaí agus uimhreacha bunaithe ar shuíomh do bhrabhsálaí", + "default_quality_subtitle": "Cáilíocht a úsáidtear agus tú ag tapáil ar an gcnaipe 'roinn'. Brúigh an cnaipe 'roinn' ar feadh tamaill le roghnú gach uair.", + "default_share_quality": "Cáilíocht réamhshocraithe roinnte", "delete": "Scrios", "delete_action_confirmation_message": "An bhfuil tú cinnte gur mian leat an tsócmhainn seo a scriosadh? Bogfaidh an gníomh seo an tsócmhainn go dtí bruscar an fhreastalaí agus fiafróidh sé díot an mian leat í a scriosadh go háitiúil", "delete_action_prompt": "{count} scriosta", @@ -1224,6 +1238,7 @@ "failed": "Theip air", "failed_count": "Theip ar: {count}", "failed_to_authenticate": "Theip ar fhíordheimhniú", + "failed_to_delete_file": "Theip ar an gcomhad a scriosadh", "failed_to_load_assets": "Theip ar shócmhainní a lódáil", "failed_to_load_folder": "Theip ar an bhfillteán a luchtú", "favorite": "Ceanán", @@ -1354,6 +1369,7 @@ "individual_share": "Sciar aonair", "individual_shares": "Scaireanna aonair", "info": "Eolas", + "integrity_checks": "Seiceálacha Ionracais", "interval": { "day_at_onepm": "Gach lá ag 1pm", "hours": "Gach {hours, plural, one {uair an chloig} other {{hours, number} uair an chloig}}", @@ -1426,6 +1442,7 @@ "linked_oauth_account": "Cuntas OAuth nasctha", "list": "Liosta", "live": "Beo", + "load_more": "Luchtaigh Tuilleadh", "loading": "Ag luchtú", "loading_search_results_failed": "Theip ar lódáil na dtorthaí cuardaigh", "local": "Áitiúil", @@ -2084,6 +2101,7 @@ "select_person": "Roghnaigh duine", "select_person_to_tag": "Roghnaigh duine le clibeáil", "select_photos": "Roghnaigh grianghraif", + "select_quality": "Roghnaigh cáilíocht", "select_trash_all": "Roghnaigh gach rud sa bhruscar", "select_user_for_sharing_page_err_album": "Theip ar albam a chruthú", "selected": "Roghnaithe", @@ -2147,6 +2165,8 @@ "share_assets_selected": "{count} roghnaithe", "share_dialog_preparing": "Ag ullmhú...", "share_link": "Comhroinn an Nasc", + "share_original": "Úsáid an bunleagan (mór)", + "share_preview": "Úsáid mionsamhail (beag)", "shared": "Roinnte", "shared_album_activities_input_disable": "Tá trácht díchumasaithe", "shared_album_activity_remove_content": "Ar mhaith leat an ghníomhaíocht seo a scriosadh?", @@ -2248,6 +2268,7 @@ "slideshow_repeat_description": "Lúb ar ais go dtí an tús nuair a chríochnaíonn an sleamhnán", "slideshow_settings": "Socruithe sleamhnán", "smart_album": "Albam cliste", + "some_assets_already_have_a_location_warning": "Tá suíomh ag cuid de na sócmhainní roghnaithe cheana féin", "sort_albums_by": "Sórtáil albaim de réir...", "sort_created": "Dáta cruthaithe", "sort_items": "Líon na míreanna", @@ -2368,11 +2389,13 @@ "trash_page_title": "Bruscar ({count})", "trashed_items_will_be_permanently_deleted_after": "Scriosfar míreanna atá curtha sa bhruscar go buan i ndiaidh {days, plural, one {# lá} other {# laethanta}}.", "trigger": "Spriocdhíriú", + "trigger_asset_metadata_extraction": "Eastóscadh Meiteashonraí Sócmhainní", + "trigger_asset_metadata_extraction_description": "Spreagtha nuair a bhaintear meiteashonraí EXIF sócmhainne", "trigger_asset_uploaded": "Uaslódáil Sócmhainní", "trigger_asset_uploaded_description": "Spreagtha nuair a uaslódálfar sócmhainn nua", "trigger_description": "Imeacht a chuireann tús leis an sreabhadh oibre", "trigger_person_recognized": "Duine Aitheanta", - "trigger_person_recognized_description": "Spreagtar nuair a bhraitear duine", + "trigger_person_recognized_description": "Spreagtar nuair a aithnítear duine", "trigger_type": "Cineál spreagthóra", "troubleshoot": "Fabhtcheartaigh", "type": "Cineál", diff --git a/i18n/hu.json b/i18n/hu.json index 49e345c401..dddcdeeee8 100644 --- a/i18n/hu.json +++ b/i18n/hu.json @@ -189,9 +189,11 @@ "machine_learning_smart_search_enabled": "Okos keresés engedélyezése", "machine_learning_smart_search_enabled_description": "Ha ki van kapcsolva, a képek nem lesznek átalakítva Okos kereséshez.", "machine_learning_url_description": "Gépi tanulás szerver URL címe. Ha többi, mint egy URL van megadva, mindegyik szervert egyenként próbálja meg, amíg az egyik sikeresen nem válaszol, sorrendben az elsőtől az utólsóig. A nem elérhető szervereket átmenetileg figyelmen kívül lesznek hagyva, amíg újra online nem lesznek.", + "maintenance_backup_management": "backup kezelés", "maintenance_delete_backup": "Biztonsági mentés törlése", "maintenance_delete_backup_description": "A fájl törlése nem visszafordítható.", "maintenance_delete_error": "A biztonsági mentés törlése sikertelen volt.", + "maintenance_integrity_check": "Ellenőrizze", "maintenance_integrity_check_all": "Mind ellenőrzése", "maintenance_integrity_checksum_mismatch": "Ellenőrzőösszeg-eltérés", "maintenance_integrity_checksum_mismatch_job": "Az ellenőrzőösszegek eltéréseinek ellenőrzése", @@ -2020,13 +2022,13 @@ "search_albums": "Albumok keresése", "search_by_context": "Keresés tartalom alapján", "search_by_description": "Keresés leírás alapján", - "search_by_description_example": "Túrázós nap Szapában", + "search_by_description_example": "Például: túrázós nap a hegyekben", "search_by_filename": "Keresés fájlnév vagy kiterjesztés alapján", "search_by_filename_example": "például IMG_1234.JPG vagy PNG", "search_by_full_path": "Keresés teljes elérési út vagy mappa alapján", "search_by_full_path_example": "/Jancsi/Projektek/3D_nyomtatás/2026-07-01 – kereshetsz a Projektek, 3D, Nyomtatás, 2026 stb. kifejezésekre.", "search_by_ocr": "Keresés szövegfelismeréssel (OCR)", - "search_by_ocr_example": "Latte", + "search_by_ocr_example": "Például: számla", "search_camera_lens_model": "Keresés objektívmodell alapján...", "search_camera_make": "Kameragyártó keresése...", "search_camera_model": "Kameramodell keresése...", @@ -2308,7 +2310,7 @@ "submit": "Beküldés", "success": "Siker", "suggestions": "Javaslatok", - "sunrise_on_the_beach": "Napkelte a tengerparton", + "sunrise_on_the_beach": "Például: napfelkelte a tengerparton", "support": "Támogatás", "support_and_feedback": "Támogatás és visszajelzés", "support_third_party_description": "Az Immich telepítésedet egy harmadik fél csomagolta. Mivel elképzelhető, hogy az esetlegesen felmerülő problémákat ez a csomag okozza, ezért kérjük, először velük közöld a problémákat az alábbi linkek segítségével.", @@ -2393,7 +2395,7 @@ "trigger_asset_metadata_extraction_description": "A művelet akkor indult el, amikor az elem EXIF-adatai kinyerésre kerültek", "trigger_asset_uploaded": "Elem feltöltés", "trigger_asset_uploaded_description": "Új elem feltöltésekor indul el", - "trigger_description": "Egy esemény, ami elindítja a folyamatot", + "trigger_description": "A munkafolyamatot elindító esemény", "trigger_person_recognized": "Személy felismerve", "trigger_person_recognized_description": "Személy felismerésekor indul el", "trigger_type": "Feltétel típusa", diff --git a/i18n/id.json b/i18n/id.json index c68f0df6f6..921a6ef02a 100644 --- a/i18n/id.json +++ b/i18n/id.json @@ -79,6 +79,7 @@ "cron_expression_description": "Tetapkan interval pemindaian menggunakan format cron. Untuk informasi lebih lanjut, silakan merujuk misalnya ke Crontab Guru", "cron_expression_presets": "Prasetel ekspresi cron", "disable_login": "Nonaktifkan log masuk", + "download_csv": "Unduh CSV", "duplicate_detection_job_description": "Jalankan pembelajaran mesin pada aset untuk mendeteksi gambar yang serupa. Bergantung pada Pencarian Cerdas", "exclusion_pattern_description": "Pola pengecualian dapat digunakan untuk mengabaikan file dan folder ketika memindai pustaka Anda. Ini berguna jika Anda memiliki folder yang berisi file yang tidak ingin diimpor, seperti file RAW.", "export_config_as_json_description": "Unduh konfigurasi sistem saat ini sebagai file JSON", @@ -188,9 +189,25 @@ "machine_learning_smart_search_enabled": "Aktifkan pencarian cerdas", "machine_learning_smart_search_enabled_description": "Jika dinonaktifkan, gambar tidak akan dienkode untuk pencarian cerdas.", "machine_learning_url_description": "URL server pembelajaran mesin. Jika lebih dari satu URL disediakan, setiap server akan dicoba satu per satu hingga salah satu berhasil merespons, dari urutan pertama sampai terakhir. Server yang tidak merespons akan diabaikan sementara hingga kembali online.", + "maintenance_backup_management": "Pengelolaan cadangan", "maintenance_delete_backup": "Hapus Cadangan", "maintenance_delete_backup_description": "File ini akan dihapus secara permanen.", "maintenance_delete_error": "Gagal menghapus cadangan.", + "maintenance_integrity_check": "Periksa", + "maintenance_integrity_check_all": "Periksa Semua", + "maintenance_integrity_checksum_mismatch": "Checksum Tidak Cocok", + "maintenance_integrity_checksum_mismatch_description": "File yang checksum di penyimpanannya tidak cocok dengan checksum yang disimpan Immich di basis data.", + "maintenance_integrity_checksum_mismatch_job": "Periksa ketidakcocokan checksum", + "maintenance_integrity_checksum_mismatch_refresh_job": "Segarkan laporan ketidakcocokan checksum", + "maintenance_integrity_missing_file": "File Hilang", + "maintenance_integrity_missing_file_description": "File yang dilacak Immich di basis datanya tetapi tidak ada di sistem file.", + "maintenance_integrity_missing_file_job": "Periksa file yang hilang", + "maintenance_integrity_missing_file_refresh_job": "Segarkan laporan file yang hilang", + "maintenance_integrity_report": "Laporan Integritas", + "maintenance_integrity_untracked_file": "File Tidak Terlacak", + "maintenance_integrity_untracked_file_description": "File di direktori Immich yang tidak memiliki catatan apa pun di Immich.", + "maintenance_integrity_untracked_file_job": "Periksa file yang tidak terlacak", + "maintenance_integrity_untracked_file_refresh_job": "Segarkan laporan file yang tidak terlacak", "maintenance_restore_backup": "Memulihkan Cadangan", "maintenance_restore_backup_description": "Immich akan dihapus dan dipulihkan dari cadangan yang dipilih. Sebuah cadangan akan dibuat sebelum dilanjutkan.", "maintenance_restore_backup_different_version": "Cadangan ini dibuat dengan versi Immich yang berbeda!", @@ -915,6 +932,8 @@ "deduplicate_all": "Hapus semua duplikat", "default_locale": "Bahasa Default", "default_locale_description": "Sesuaikan format tanggal dan angka sesuai dengan pengaturan wilayah browser Anda", + "default_quality_subtitle": "Kualitas yang digunakan saat mengetuk bagikan. Tekan lama tombol bagikan untuk memilih setiap kali.", + "default_share_quality": "Kualitas bagikan default", "delete": "Hapus", "delete_action_confirmation_message": "Yakin ingin menghapus aset ini? Tindakan ini akan memindahkan aset ke tempat sampah pada server dan akan mengkonfirmasi apakah Anda ingin menghapusnya juga secara lokal", "delete_action_prompt": "{count} item telah dihapus", @@ -1224,6 +1243,7 @@ "failed": "Gagal", "failed_count": "Gagal: {count}", "failed_to_authenticate": "Autentikasi gagal", + "failed_to_delete_file": "Gagal menghapus file", "failed_to_load_assets": "Gagal memuat aset", "failed_to_load_folder": "Gagal memuat folder", "favorite": "Favorit", @@ -1354,6 +1374,7 @@ "individual_share": "Bagikan individu", "individual_shares": "Pembagian individu", "info": "Info", + "integrity_checks": "Pemeriksaan Integritas", "interval": { "day_at_onepm": "Setiap hari pada 13.00", "hours": "Setiap {hours, plural, one {jam} other {{hours, number} jam}}", @@ -1426,6 +1447,7 @@ "linked_oauth_account": "Akun OAuth tertaut", "list": "Daftar", "live": "Langsung", + "load_more": "Muat Lebih Banyak", "loading": "Memuat", "loading_search_results_failed": "Pemuatan hasil pencarian gagal", "local": "Lokal", @@ -2084,6 +2106,7 @@ "select_person": "Pilih orang", "select_person_to_tag": "Pilih orang untuk diberi tag", "select_photos": "Pilih foto", + "select_quality": "Pilih kualitas", "select_trash_all": "Pilih buang semua", "select_user_for_sharing_page_err_album": "Gagal membuat album", "selected": "Dipilih", @@ -2147,6 +2170,8 @@ "share_assets_selected": "{count} dipilih", "share_dialog_preparing": "Menyiapkan...", "share_link": "Bagikan Tautan", + "share_original": "Gunakan versi asli (besar)", + "share_preview": "Gunakan thumbnail (kecil)", "shared": "Dibagikan", "shared_album_activities_input_disable": "Komentar dinonaktifkan", "shared_album_activity_remove_content": "Ingin menghapus aktivitas ini?", @@ -2248,6 +2273,7 @@ "slideshow_repeat_description": "Ulangi dari awal saat salindia berakhir", "slideshow_settings": "Pengaturan salindia", "smart_album": "Album cerdas", + "some_assets_already_have_a_location_warning": "Sebagian aset yang dipilih sudah memiliki lokasi", "sort_albums_by": "Urutkan album berdasarkan...", "sort_created": "Tanggal dibuat", "sort_items": "Jumlah item", @@ -2368,11 +2394,13 @@ "trash_page_title": "Sampah ({count})", "trashed_items_will_be_permanently_deleted_after": "Item yang dibuang akan dihapus secara permanen setelah {days, plural, one {# hari} other {# hari}}.", "trigger": "Pemicu", + "trigger_asset_metadata_extraction": "Ekstraksi Metadata Aset", + "trigger_asset_metadata_extraction_description": "Dipicu saat metadata EXIF dari sebuah aset diekstrak", "trigger_asset_uploaded": "Unggah Aset", "trigger_asset_uploaded_description": "Terpicu saat aset baru telah diunggah", "trigger_description": "Sebuah peristiwa yang memicu alur kerja", "trigger_person_recognized": "Orang Dikenali", - "trigger_person_recognized_description": "Terpicu saat seseorang terdeteksi", + "trigger_person_recognized_description": "Dipicu saat seseorang dikenali", "trigger_type": "Tipe pemicu", "troubleshoot": "Pemecahan Masalah", "type": "Jenis", diff --git a/i18n/it.json b/i18n/it.json index 8b7d265168..1aaf0abb1f 100644 --- a/i18n/it.json +++ b/i18n/it.json @@ -19,13 +19,13 @@ "add_action": "Aggiungi azione", "add_action_description": "Fare clic per aggiungere un'azione da eseguire", "add_assets": "Aggiungi risorse", - "add_birthday": "Aggiungi compleanno", - "add_endpoint": "Aggiungi un endpoint", - "add_exclusion_pattern": "Aggiungi un pattern di esclusione", + "add_birthday": "Aggiungi un compleanno", + "add_endpoint": "Aggiungi endpoint", + "add_exclusion_pattern": "Aggiungi pattern di esclusione", "add_location": "Aggiungi posizione", "add_more_users": "Aggiungi altri utenti", "add_partner": "Aggiungi partner", - "add_path": "Aggiungi un percorso", + "add_path": "Aggiungi percorso", "add_photos": "Aggiungi foto", "add_step": "Aggiungi passo", "add_tag": "Aggiungi tag", @@ -195,8 +195,13 @@ "maintenance_integrity_check_all": "Verifica Tutto", "maintenance_integrity_checksum_mismatch": "I checksum non corrispondono", "maintenance_integrity_checksum_mismatch_job": "Verifica corrispondenza dei checksum", + "maintenance_integrity_checksum_mismatch_refresh_job": "Aggiorna report corrispondenze dei checksum", "maintenance_integrity_missing_file": "File mancanti", + "maintenance_integrity_missing_file_job": "Verifica file mancanti", + "maintenance_integrity_missing_file_refresh_job": "Aggiorna report sui file mancanti", "maintenance_integrity_report": "Report di integrità", + "maintenance_integrity_untracked_file": "File non tracciati", + "maintenance_integrity_untracked_file_job": "Verifica presenza file non tracciati", "maintenance_integrity_untracked_file_refresh_job": "Aggiorna il report dei file non tracciati", "maintenance_restore_backup": "Ripristina backup", "maintenance_restore_backup_description": "Immich verrà cancellato e ripristinato dal backup scelto. Prima di procedere, verrà creato un backup.", @@ -1107,10 +1112,10 @@ "failed_to_update_notification_status": "Impossibile aggiornare lo stato delle notifiche", "incorrect_email_or_password": "Email o password non corretta", "library_folder_already_exists": "Questo path di importazione esiste già.", - "page_not_found": "Impossibile trovare la pagina", + "page_not_found": "Pagina non trovata", "paths_validation_failed": "{paths, plural, one {La convalida di # percorso non è riuscita} other {La convalida di # percorsi non è riuscita}}", "profile_picture_transparent_pixels": "Le foto profilo non possono avere pixel trasparenti. Riprova ingrandendo e/o muovendo l'immagine.", - "quota_higher_than_disk_size": "Hai impostato un limite più alto della dimensione del disco", + "quota_higher_than_disk_size": "Hai impostato una quota più alta della dimensione del disco", "something_went_wrong": "Qualcosa è andato storto", "unable_to_add_album_users": "Impossibile aggiungere utenti all'album", "unable_to_add_assets_to_shared_link": "Impossibile aggiungere le risorse al link condiviso", @@ -1123,55 +1128,55 @@ "unable_to_change_album_user_role": "Impossibile modificare il ruolo dell'utente nell'album", "unable_to_change_date": "Impossibile modificare la data", "unable_to_change_description": "Impossibile modificare la descrizione", - "unable_to_change_favorite": "Errore durante il cambio di stato preferito della risorsa", + "unable_to_change_favorite": "Impossibile modificare lo stato preferito della risorsa", "unable_to_change_location": "Impossibile modificare posizione", "unable_to_change_password": "Impossibile modificare password", - "unable_to_change_visibility": "Errore durante la modifica della visibilità per {count, plural, one {# persona} other {# persone}}", - "unable_to_complete_oauth_login": "Errore durante l'accesso tramite OAuth", + "unable_to_change_visibility": "Impossibile modificare la visibilità per {count, plural, one {# persona} other {# persone}}", + "unable_to_complete_oauth_login": "Impossibile accedere tramite OAuth", "unable_to_connect": "Impossibile connettersi", "unable_to_copy_to_clipboard": "Impossibile copiare negli appunti, assicurati di aver aperto la pagina in https", "unable_to_create": "Impossibile creare la sequenza", - "unable_to_create_admin_account": "Impossibile creare un account admin", + "unable_to_create_admin_account": "Impossibile creare un account amministratore", "unable_to_create_api_key": "Impossibile creare una nuova chiave API", "unable_to_create_library": "Impossibile creare la libreria", - "unable_to_create_user": "Impossibile creare utente", - "unable_to_delete_album": "Impossibile cancellare album", - "unable_to_delete_asset": "Impossibile cancellare la risorsa", + "unable_to_create_user": "Impossibile creare l'utente", + "unable_to_delete_album": "Impossibile eliminare l'album", + "unable_to_delete_asset": "Impossibile eliminare la risorsa", "unable_to_delete_assets": "Errore durante l'eliminazione delle risorse", - "unable_to_delete_exclusion_pattern": "Impossibile cancellare pattern di esclusione", - "unable_to_delete_shared_link": "Impossibile cancellare link condiviso", - "unable_to_delete_user": "Impossibile cancellare utente", + "unable_to_delete_exclusion_pattern": "Impossibile eliminare il pattern di esclusione", + "unable_to_delete_shared_link": "Impossibile eliminare il link condiviso", + "unable_to_delete_user": "Impossibile eliminare l'utente", "unable_to_delete_workflow": "Impossibile eliminare la sequenza", "unable_to_download_files": "Impossibile scaricare i file", - "unable_to_edit_exclusion_pattern": "Impossibile modificare pattern di esclusione", + "unable_to_edit_exclusion_pattern": "Impossibile modificare il pattern di esclusione", "unable_to_empty_trash": "Impossibile svuotare il cestino", "unable_to_enter_fullscreen": "Impossibile aprire l'applicazione a schermo intero", "unable_to_exit_fullscreen": "Impossibile uscire dallo schermo intero", "unable_to_get_comments_number": "Impossibile ottenere il numero di commenti", "unable_to_get_shared_link": "Impossibile ottenere il link condivisibile", - "unable_to_hide_person": "Impossibile nascondere persona", + "unable_to_hide_person": "Impossibile nascondere la persona", "unable_to_link_motion_video": "Impossibile collegare video in movimento", "unable_to_link_oauth_account": "Impossibile collegare l'account OAuth", "unable_to_log_out_all_devices": "Impossibile eseguire il logout da tutti i dispositivi", "unable_to_log_out_device": "Impossibile eseguire il logout dal dispositivo", "unable_to_login_with_oauth": "Impossibile effettuare l'accesso tramite OAuth", "unable_to_play_video": "Impossibile riprodurre il video", - "unable_to_reassign_assets_existing_person": "Errore durante la riassegnazione delle risorse a {name, select, null {una persona esistente} other {{name}}}", - "unable_to_reassign_assets_new_person": "Errore durante la riassegnazione delle risorse ad una nuova persona", + "unable_to_reassign_assets_existing_person": "Impossibile riassegnare le risorse a {name, select, null {una persona esistente} other {{name}}}", + "unable_to_reassign_assets_new_person": "Impossibile riassegnare le risorse ad una nuova persona", "unable_to_refresh_user": "Impossibile aggiornare l'utente", "unable_to_remove_album_users": "Impossibile rimuovere gli utenti dall'album", "unable_to_remove_api_key": "Impossibile rimuovere la chiave API", - "unable_to_remove_assets_from_shared_link": "Errore durante la rimozione delle risorse dal link condiviso", - "unable_to_remove_library": "Impossibile rimuovere libreria", + "unable_to_remove_assets_from_shared_link": "Impossibile rimuovere le risorse dal link condiviso", + "unable_to_remove_library": "Impossibile rimuovere la libreria", "unable_to_remove_partner": "Impossibile rimuovere compagno", - "unable_to_remove_reaction": "Impossibile rimuovere reazione", + "unable_to_remove_reaction": "Impossibile rimuovere la reazione", "unable_to_reset_password": "Impossibile reimpostare la password", - "unable_to_reset_pin_code": "Impossibile resettare il codice PIN", + "unable_to_reset_pin_code": "Impossibile reimpostare il codice PIN", "unable_to_resolve_duplicate": "Impossibile risolvere duplicato", "unable_to_restore_assets": "Impossibile ripristinare le risorse", - "unable_to_restore_trash": "Impossibile ripristinare cestino", - "unable_to_restore_user": "Impossibile ripristinare utente", - "unable_to_save_album": "Impossibile salvare album", + "unable_to_restore_trash": "Impossibile ripristinare il cestino", + "unable_to_restore_user": "Impossibile ripristinare l'utente", + "unable_to_save_album": "Impossibile salvare l'album", "unable_to_save_api_key": "Impossibile salvare chiave API", "unable_to_save_date_of_birth": "Impossible salvare la data di nascita", "unable_to_save_name": "Impossibile salvare il nome", @@ -1186,7 +1191,7 @@ "unable_to_trash_asset": "Impossibile cestinare la risorsa", "unable_to_unlink_account": "Impossibile scollegare l'account", "unable_to_unlink_motion_video": "Impossibile scollegare video in movimento", - "unable_to_update_album_cover": "Errore durante l'aggiornamento della copertina dell'album", + "unable_to_update_album_cover": "Impossibile aggiornare la copertina dell'album", "unable_to_update_album_info": "Impossibile aggiornare le informazioni sull'album", "unable_to_update_library": "Impossibile aggiornare la libreria", "unable_to_update_location": "Impossibile aggiornare la posizione", @@ -1199,7 +1204,7 @@ "errors_text": "Errori", "exclusion_pattern": "Pattern di esclusione", "exif": "Exif", - "exif_bottom_sheet_description": "Aggiungi una descrizione...", + "exif_bottom_sheet_description": "Aggiungi descrizione...", "exif_bottom_sheet_description_error": "Errore durante l'aggiornamento della descrizione", "exif_bottom_sheet_details": "DETTAGLI", "exif_bottom_sheet_location": "POSIZIONE", @@ -1240,7 +1245,7 @@ "favorite_action_prompt": "{count} elementi aggiunti ai preferiti", "favorite_or_unfavorite_photo": "Aggiungi o rimuovi foto da preferiti", "favorites": "Preferiti", - "favorites_page_no_favorites": "Nessun preferito", + "favorites_page_no_favorites": "Nessuna risorsa preferita trovata", "feature_photo_updated": "Foto in evidenza aggiornata", "features": "Funzionalità", "features_in_development": "Funzionalità in fase di sviluppo", @@ -1266,16 +1271,16 @@ "folders_feature_description": "Navigare la visualizzazione a cartelle per le foto e i video sul file system", "forgot_pin_code_question": "Hai dimenticato il tuo PIN?", "forward": "Avanti", - "free_up_space": "Libera Spazio", + "free_up_space": "Libera spazio", "free_up_space_description": "Sposta le foto e i video del tuo dispositivo nel cestino per liberare spazio. Le copie sul server rimarranno al sicuro.", "free_up_space_settings_subtitle": "Libera spazio sul dispositivo", "full_path": "Percorso completo: {path}", - "full_path_or_folder": "Percorso assoluto o Cartella", - "gcast_enabled": "Google Cast Abilitato", + "full_path_or_folder": "Percorso assoluto o cartella", + "gcast_enabled": "Google Cast", "gcast_enabled_description": "Questa funzione carica risorse esterne da Google per poter funzionare.", "general": "Generale", "geolocation_instruction_location": "Fai clic su una risorsa con coordinate GPS per utilizzare la sua posizione oppure seleziona una posizione direttamente dalla mappa", - "get_help": "Chiedi Aiuto", + "get_help": "Chiedi aiuto", "get_people_error": "Errore nel ritrovare le persone", "get_wifiname_error": "Non sono riuscito a recuperare il nome della rete Wi-Fi. Accertati di aver concesso i permessi necessari e di essere connesso ad una rete Wi-Fi", "getting_started": "Iniziamo", @@ -1288,7 +1293,7 @@ "group_albums_by": "Raggruppa album in base a...", "group_country": "Raggruppa per paese", "group_no": "Nessun raggruppamento", - "group_owner": "Raggruppa in base al proprietario", + "group_owner": "Raggruppa per proprietario", "group_places_by": "Raggruppa posti per...", "group_year": "Raggruppa per anno", "haptic_feedback_switch": "Abilita feedback aptico", @@ -1437,6 +1442,7 @@ "linked_oauth_account": "Account OAuth collegato", "list": "Lista", "live": "Live", + "load_more": "Carica di più", "loading": "Caricamento", "loading_search_results_failed": "Impossibile caricare i risultati della ricerca", "local": "Locale", @@ -2383,11 +2389,13 @@ "trash_page_title": "Cestino ({count})", "trashed_items_will_be_permanently_deleted_after": "Gli elementi cestinati saranno eliminati definitivamente dopo {days, plural, one {# giorno} other {# giorni}}.", "trigger": "Evento di attivazione", + "trigger_asset_metadata_extraction": "Estrazione dei metadati delle risorse", + "trigger_asset_metadata_extraction_description": "Attivato quando i metadati EXIF di una risorsa vengono estratti", "trigger_asset_uploaded": "Caricamento risorsa", "trigger_asset_uploaded_description": "Attivato quando una nuova risorsa viene caricata", "trigger_description": "Un evento che attiva la sequenza", "trigger_person_recognized": "Persona Riconosciuta", - "trigger_person_recognized_description": "Attivato quando è rilevata una persona", + "trigger_person_recognized_description": "Attivato quando è riconosciuta una persona", "trigger_type": "Tipo di trigger", "troubleshoot": "Risoluzione dei problemi", "type": "Tipo", diff --git a/i18n/ja.json b/i18n/ja.json index 22ddde9b06..5244a07aeb 100644 --- a/i18n/ja.json +++ b/i18n/ja.json @@ -79,6 +79,7 @@ "cron_expression_description": "cron形式で実行タイミングを設定します。詳しくは Crontab Guru を参照してください", "cron_expression_presets": "スケジュール(プリセット)", "disable_login": "ログインを無効にする", + "download_csv": "CSVファイルをダウンロード", "duplicate_detection_job_description": "機械学習を用いて類似画像の検出を行います。(スマートサーチに依存)", "exclusion_pattern_description": "除外パターンを使用すると、ライブラリをスキャンする際にファイルやフォルダを無視することができます。RAWファイルなど、インポートしたくないファイルを含むフォルダがある場合に便利です。", "export_config_as_json_description": "現在のシステムコンフィグをJSONファイルとしてダウンロード", @@ -188,9 +189,16 @@ "machine_learning_smart_search_enabled": "スマートサーチを有効にします", "machine_learning_smart_search_enabled_description": "無効にすると、画像はスマートサーチ用にエンコードされません。", "machine_learning_url_description": "機械学習サーバーのURL。複数のURLが設定された場合は1つずつサーバーが正常に応答するまで接続を試みます。応答のないサーバーはオンラインになるまで一時的に無視されます。", + "maintenance_backup_management": "バックアップの管理", "maintenance_delete_backup": "バックアップを削除", "maintenance_delete_backup_description": "このファイルは不可逆的に削除されます。", "maintenance_delete_error": "バックアップの削除に失敗しました。", + "maintenance_integrity_check": "チェックする", + "maintenance_integrity_check_all": "すべてチェック", + "maintenance_integrity_checksum_mismatch": "チェックサム不一致", + "maintenance_integrity_checksum_mismatch_description": "ディスク上のチェックサムが、Immichのデータベースに保存されているチェックサムと一致しないファイル。", + "maintenance_integrity_checksum_mismatch_job": "チェックサム不一致を検出する", + "maintenance_integrity_checksum_mismatch_refresh_job": "チェックサム不一致レポートを再生成", "maintenance_restore_backup": "バックアップを復元", "maintenance_restore_backup_description": "現在のImmichは削除され、選択したバックアップから復元されます。続行前にバックアップが作成されます。", "maintenance_restore_backup_different_version": "このバックアップは異なるバージョンのImmichにより作成されたものです!", diff --git a/i18n/ko.json b/i18n/ko.json index 57154e0a18..ed75b6114f 100644 --- a/i18n/ko.json +++ b/i18n/ko.json @@ -79,6 +79,7 @@ "cron_expression_description": "Cron 표현식으로 스캔 주기를 설정합니다. 자세한 내용은 Crontab Guru를 확인하세요.", "cron_expression_presets": "Cron 표현식 프리셋", "disable_login": "로그인 비활성화", + "download_csv": "CSV 다운로드", "duplicate_detection_job_description": "기계 학습으로 유사한 이미지를 감지합니다. 스마트 검색이 활성화되어 있어야 합니다.", "exclusion_pattern_description": "라이브러리 스캔에서 제외할 파일이나 폴더 규칙을 설정합니다. 가져오지 않을 파일(RAW 파일 등)이 포함된 폴더가 있을 때 사용합니다.", "export_config_as_json_description": "현재 시스템 구성을 JSON 파일로 다운로드합니다.", @@ -191,6 +192,17 @@ "maintenance_delete_backup": "백업 삭제", "maintenance_delete_backup_description": "이 파일이 영구적으로 삭제됩니다.", "maintenance_delete_error": "백업 삭제에 실패했습니다.", + "maintenance_integrity_check_all": "전체선택", + "maintenance_integrity_checksum_mismatch": "체크섬 불일치", + "maintenance_integrity_checksum_mismatch_job": "파일 무결성 검사", + "maintenance_integrity_checksum_mismatch_refresh_job": "무결성 오류 보고서 새로고침", + "maintenance_integrity_missing_file": "누락된 파일", + "maintenance_integrity_missing_file_job": "누락된 파일 확인", + "maintenance_integrity_missing_file_refresh_job": "누락된 파일 보고서 새로고침", + "maintenance_integrity_report": "무결성 보고서", + "maintenance_integrity_untracked_file": "추적되지 않은 파일", + "maintenance_integrity_untracked_file_job": "추적되지 않은 파일 확인", + "maintenance_integrity_untracked_file_refresh_job": "추적되지 않은 파일 보고서 새로고침", "maintenance_restore_backup": "백업 복원", "maintenance_restore_backup_description": "Immich가 초기화된 후 선택한 백업으로 복원됩니다. 계속하기 전에 백업이 자동으로 생성됩니다.", "maintenance_restore_backup_different_version": "이 백업은 다른 버전의 Immich에서 생성되었습니다!", @@ -305,6 +317,8 @@ "refreshing_all_libraries": "모든 라이브러리를 새로고침합니다.", "registration": "관리자 등록", "registration_description": "첫 번째 사용자이므로 관리자 권한이 부여됩니다. 관리 작업 및 사용자 생성이 가능합니다.", + "release_channel_release_candidate": "릴리스 후보 버전", + "release_channel_stable": "안정화 버전", "remove_failed_jobs": "실패한 작업 삭제", "require_password_change_on_login": "최초 로그인 시 비밀번호 변경 요구", "reset_settings_to_default": "설정을 기본값으로 복원", @@ -399,6 +413,10 @@ "transcoding_preferred_hardware_device_description": "(VAAPI 및 QSV인 경우) 하드웨어 트랜스코딩에 사용할 dri 노드를 지정합니다.", "transcoding_preset_preset": "프리셋 (-preset)", "transcoding_preset_preset_description": "압축 속도를 설정합니다. 동일 비트레이트에서 느린 속도를 선택하면 상대적으로 파일 크기가 감소하며 품질이 향상됩니다. VP9는 'faster' 이상의 속도를 무시합니다.", + "transcoding_realtime": "실시간 트랜스코딩 [실험 기능]", + "transcoding_realtime_description": "동영상 스트리밍 중 실시간 트랜스코딩을 수행합니다. 이를 통해 재생 중 화질을 변경할 수 있지만, 서버 성능에 따라 재생 지연이나 끊김 현상이 발생할 수 있습니다.", + "transcoding_realtime_enabled": "실시간 트랜스코딩 활성화", + "transcoding_realtime_enabled_description": "이 기능을 비활성화하면 새로운 실시간 트랜스코딩 작업을 시작할 수 없습니다.", "transcoding_reference_frames": "참조 프레임 수", "transcoding_reference_frames_description": "특정 프레임을 압축할 때 참조할 프레임 수를 설정합니다. 값을 높이면 압축 효율이 향상되지만 인코딩 속도가 느려집니다. 0을 입력하면 자동으로 설정합니다.", "transcoding_required_description": "허용 포맷이 아닌 동영상만 트랜스코딩", @@ -442,6 +460,8 @@ "user_settings_description": "사용자 설정을 관리합니다.", "user_successfully_removed": "사용자 {email}님이 성공적으로 삭제되었습니다.", "users_page_description": "관리자 사용자 페이지", + "version_check_channel": "배포 채널", + "version_check_channel_description": "버전 업데이트 알림을 받을 배포 채널을 선택하세요", "version_check_enabled_description": "버전 확인 활성화", "version_check_implications": "주기적으로 {server}에 요청을 보내 새 버전을 확인합니다.", "version_check_settings": "버전 확인", @@ -562,6 +582,7 @@ "asset_added_to_album": "앨범에 추가되었습니다.", "asset_adding_to_album": "앨범에 추가 중…", "asset_created": "자산 생성됨", + "asset_day_count": "{date}: 자산 {count}개", "asset_description_updated": "항목 설명이 업데이트되었습니다.", "asset_filename_is_offline": "{filename} 항목 누락됨", "asset_has_unassigned_faces": "항목에 할당되지 않은 얼굴이 있음", @@ -691,6 +712,7 @@ "backup_settings_subtitle": "업로드 설정을 관리합니다.", "backup_upload_details_page_more_details": "탭하여 상세보기", "backward": "뒤로", + "battery_optimization_backup_reliability": "배터리 최적화를 해제하면 백그라운드 백업이 더욱 안정적으로 동작할 수 있습니다", "biometric_auth_enabled": "생체 인증이 활성화되었습니다.", "biometric_locked_out": "생체 인증이 일시적으로 비활성화되었습니다.", "biometric_no_options": "사용 가능한 생체 인증 옵션 없음", @@ -698,6 +720,7 @@ "birthdate_saved": "생년월일이 저장되었습니다.", "birthdate_set_description": "생년월일은 사진 촬영 당시 인물의 나이를 계산하는 데 사용됩니다.", "blurred_background": "흐린 배경", + "browse_templates": "템플릿 둘러보기", "bugs_and_feature_requests": "버그 제보 & 기능 요청", "build": "빌드", "build_image": "빌드 이미지", @@ -731,6 +754,7 @@ "cannot_update_the_description": "설명을 변경할 수 없습니다.", "cast": "캐스트", "cast_description": "사용 가능한 캐스트 기기 구성", + "change": "변경", "change_date": "날짜 변경", "change_description": "설명 변경", "change_display_order": "표시 순서 변경", @@ -759,6 +783,7 @@ "check_corrupt_asset_backup_description": "이 검사는 모든 항목이 백업된 후 Wi-Fi가 연결된 상태에서만 실행하세요. 이 작업은 몇 분 정도 소요될 수 있습니다.", "check_logs": "로그 확인", "checksum": "체크섬", + "choose": "선택", "choose_matching_people_to_merge": "병합할 인물 선택", "city": "도시", "cleanup_confirm_description": "Immich 서버에서 안전하게 백업된 항목 {count}개({date} 이전에 생성됨)를 찾았습니다. 이 기기에서 로컬 복사복을 삭제하시겠습니까?", @@ -776,7 +801,7 @@ "clear": "지우기", "clear_all": "모두 지우기", "clear_all_recent_searches": "검색 기록 전체 삭제", - "clear_failed_count": "명확한 실패 ({count})", + "clear_failed_count": "실패 항목 삭제 ({count})", "clear_file_cache": "파일 캐시 지우기", "clear_message": "메시지 지우기", "clear_value": "값 지우기", @@ -808,6 +833,7 @@ "comments_are_disabled": "댓글이 비활성화되었습니다.", "common_create_new_album": "앨범 생성", "completed": "완료됨", + "configuration": "설정", "confirm": "확인", "confirm_admin_password": "관리자 비밀번호 확인", "confirm_delete_face": "항목에서 {name}의 얼굴을 삭제하시겠습니까?", @@ -836,6 +862,7 @@ "copy_error": "오류 복사", "copy_file_path": "파일 경로 복사", "copy_image": "이미지 복사", + "copy_json": "JSON 복사", "copy_link": "링크 복사", "copy_link_to_clipboard": "링크를 클립보드에 복사", "copy_password": "비밀번호 복사", @@ -894,12 +921,14 @@ "date_of_birth": "생년월일", "date_of_birth_saved": "생년월일이 저장되었습니다.", "date_range": "날짜 범위", - "date_time_original": "날짜/시간 고유", + "date_time_original": "원본 촬영 일시", "day": "일", "days": "일", "deduplicate_all": "모두 삭제", "default_locale": "기본 로케일", "default_locale_description": "브라우저 로케일 설정에 따라 날짜 및 숫자 형식을 지정합니다", + "default_quality_subtitle": "공유 시 사용할 기본 화질입니다. 공유 버튼을 길게 누르면 매번 화질을 선택할 수 있습니다.", + "default_share_quality": "기본 공유 화질", "delete": "삭제", "delete_action_confirmation_message": "이 항목을 삭제하시겠습니까? 서버에서는 항목을 휴지통으로 이동시키며, 로컬에서도 삭제할 것인지 확인 메시지가 표시됩니다.", "delete_action_prompt": "{count}개 항목 삭제됨", @@ -973,7 +1002,10 @@ "downloading_asset_filename": "{filename} 다운로드 중...", "downloading_from_icloud": "iCloud에서 다운로드 중", "downloading_media": "미디어 다운로드 중", + "drag_to_reorder": "드래그하여 순서 변경", "drop_files_to_upload": "아무 곳에나 파일을 드롭하여 업로드", + "duplicate": "복제", + "duplicate_workflow": "워크플로우 복제", "duplicates": "비슷한 항목", "duplicates_description": "각 그룹을 확인하고, 비슷한 항목을 선택해 삭제 여부를 결정하세요.", "duration": "기간", @@ -1075,6 +1107,7 @@ "failed_to_remove_product_key": "제품 키 제거에 실패했습니다.", "failed_to_reset_pin_code": "PIN 코드 초기화 실패", "failed_to_stack_assets": "항목 스택에 실패했습니다.", + "failed_to_tag_assets": "항목에 태그를 추가하지 못했습니다", "failed_to_unstack_assets": "항목 스택 풀기에 실패했습니다.", "failed_to_update_notification_status": "알림 상태 업데이트 실패", "incorrect_email_or_password": "잘못된 이메일 또는 비밀번호", @@ -1200,10 +1233,12 @@ "external_libraries": "외부 라이브러리", "external_network": "외부 네트워크", "external_network_sheet_info": "선호하는 Wi-Fi 네트워크에 연결되어 있지 않은 경우, 앱은 아래 나열된 URL 중 위에서부터 순서대로 사용 가능한 첫 번째 URL을 사용하여 연결합니다.", + "f_number": "조리개 값(F값)", "face_unassigned": "알 수 없음", "failed": "실패함", "failed_count": "실패: {count}", "failed_to_authenticate": "인증에 실패했습니다.", + "failed_to_delete_file": "파일을 삭제하지 못했습니다", "failed_to_load_assets": "항목 로드 실패", "failed_to_load_folder": "폴더 로드 실패", "favorite": "즐겨찾기", @@ -1229,6 +1264,7 @@ "find_them_fast": "이름으로 검색하여 빠르게 찾기", "first": "첫 번째", "fix_incorrect_match": "잘못된 분류 수정", + "focal_length": "초점 거리", "folder": "폴더", "folder_not_found": "폴더를 찾을 수 없음", "folders": "폴더", @@ -1333,6 +1369,7 @@ "individual_share": "개인 공유", "individual_shares": "개별 공유", "info": "정보", + "integrity_checks": "무결성 검사", "interval": { "day_at_onepm": "매일 오후 1시", "hours": "매 {hours, plural, one {시간} other {{hours, number}시간}}", @@ -1349,6 +1386,7 @@ "ios_debug_info_no_sync_yet": "백그라운드 동기화 작업이 아직 실행되지 않음", "ios_debug_info_processes_queued": "{count, plural, one {백그라운드 작업 {count}개 대기 중} other {백그라운드 작업 {count}개 대기 중}}", "ios_debug_info_processing_ran_at": "{dateTime}에 처리됨", + "iso": "ISO", "items_count": "{count, plural, one {#개} other {#개}} 항목", "jobs": "작업", "json_editor": "JSON 편집기", @@ -1379,6 +1417,7 @@ "leave": "나가기", "leave_album": "앨범에서 나가기", "lens_model": "카메라 렌즈 모델", + "less": "간략히 보기", "let_others_respond": "다른 사용자의 반응 허용", "level": "레벨", "library": "라이브러리", @@ -1402,6 +1441,8 @@ "link_to_oauth": "OAuth에 연결", "linked_oauth_account": "OAuth 계정이 연결되었습니다.", "list": "목록", + "live": "라이브", + "load_more": "더 불러오기", "loading": "로드 중", "loading_search_results_failed": "검색 결과 로드 실패", "local": "로컬", @@ -1526,10 +1567,32 @@ "media_chrome": { "auto": "자동", "captions": "자막", - "closed_captions": "닫힌 캡션", + "captions_off": "해제", + "closed_captions": "자막(Cc)", + "decode_error": "디코딩 오류", + "disable_captions": "자막 끄기", + "enable_captions": "자막 켜기", + "enter_fullscreen_mode": "전체 화면으로 보기", + "exit_fullscreen_mode": "전체 화면 종료", + "loop": "반복", + "media_error_description": "미디어 오류가 발생하여 재생을 계속할 수 없습니다. 파일이 손상되었거나 브라우저에서 지원하지 않는 형식일 수 있습니다.", + "media_loading": "미디어 로딩 중", + "mute": "음소거", "network_error": "Network 오류", - "not_supported_error": "Source 지원되지 않음", + "network_error_description": "네트워크 오류로 인해 미디어 다운로드에 실패했습니다.", + "not_supported_error": "지원되지 않는 소스", + "playback_rate": "재생 속도", + "playback_rate_current": "현재 재생 속도", + "playback_rate_value": "재생 속도 {playbackRate}", + "playback_time": "재생 시간", + "quality": "화질", + "second": "초", + "seconds": "초", + "time_value_of_total_time": "{currentTime} (총 {totalTime})", "time_value_remaining": "{time} 남음", + "unmute": "음소거 해제", + "unsupported_error_description": "알 수 없는 오류가 발생했습니다. 서버 또는 네트워크에 문제가 있거나 브라우저에서 해당 형식을 지원하지 않을 수 있습니다.", + "video_not_loaded_unknown_time": "동영상을 불러오지 못했습니다. 재생 시간을 확인할 수 없습니다.", "video_player": "비디오 플레이어", "volume": "볼륨" }, @@ -1549,6 +1612,8 @@ "merge_people_prompt": "인물들을 병합하시겠습니까? 이 작업은 되돌릴 수 없습니다.", "merge_people_successfully": "선택한 인물을 합쳤습니다.", "merged_people_count": "인물 {count, plural, one {#명} other {#명}}을 합쳤습니다.", + "minFaces": "최소 인식 얼굴 수", + "minFaces_description": "인물 목록에 표시되기 위해 필요한 최소 얼굴 인식 횟수를 설정합니다", "minimize": "최소화", "minute": "분", "minutes": "분", @@ -1561,6 +1626,7 @@ "modify_date": "수정일", "month": "월", "more": "더보기", + "motion": "모션 사진", "move": "이동", "move_down": "아래로 이동", "move_off_locked_folder": "잠금 폴더에서 해제", @@ -1634,6 +1700,7 @@ "no_results": "결과 없음", "no_results_description": "동의어 또는 더 일반적인 단어를 사용해 보세요.", "no_shared_albums_message": "앨범을 만들어 주변 사람들과 사진 및 동영상을 공유하세요.", + "no_steps": "아직 추가된 단계가 없습니다", "no_uploads_in_progress": "진행 중인 업로드 없음", "none": "None", "not_allowed": "허용되지 않음", @@ -1642,6 +1709,7 @@ "not_selected": "선택되지 않음", "notes": "참고", "nothing_here_yet": "아직 아무것도 없음", + "notification_backup_reliability": "백그라운드 백업의 안정성을 높이려면 알림을 활성화하세요", "notification_permission_dialog_content": "알림을 활성화하려면 설정에서 알림 권한을 허용하세요.", "notification_permission_list_tile_content": "알림을 활성화하려면 권한을 부여하세요.", "notification_permission_list_tile_enable_button": "알림 활성화", @@ -1772,6 +1840,7 @@ "play_transcoded_video": "트랜스코딩 동영상 재생", "please_auth_to_access": "계속 진행하려면 인증하세요.", "plugin_method_filter_type": "필터", + "plugin_method_filter_type_description": "이 메서드는 이벤트를 필터링하며, 특정 조건에서 다음 단계가 실행되지 않도록 할 수 있습니다", "port": "포트", "preferences_settings_subtitle": "앱 개인 설정을 관리합니다.", "preferences_settings_title": "개인 설정", @@ -1793,6 +1862,7 @@ "profile_drawer_readonly_mode": "읽기 전용 모드 활성화. 사용자 아이콘을 길게 눌러 해제할 수 있습니다.", "profile_image_of_user": "{user}님의 프로필 이미지", "profile_picture_set": "프로필 사진이 설정되었습니다.", + "projection_type": "표시 방식", "public_album": "공개 앨범", "public_share": "모든 사용자와 공유", "purchase_account_info": "서포터", @@ -1953,6 +2023,8 @@ "search_by_description_example": "동해안에서 맞이한 새해 일출", "search_by_filename": "파일명 또는 확장자로 검색", "search_by_filename_example": "예: IMG_1234.JPG 또는 PNG", + "search_by_full_path": "전체 경로 또는 폴더로 검색", + "search_by_full_path_example": "예: /John/Projects/3D_Printing/2026-07-01 Projects, 3D, Printing, 2026 등 경로에 포함된 단어로 검색할 수 있습니다.", "search_by_ocr": "OCR로 검색", "search_by_ocr_example": "라떼", "search_camera_lens_model": "렌즈 모델 검색...", @@ -2029,6 +2101,7 @@ "select_person": "사람 선택", "select_person_to_tag": "태그할 인물을 선택하세요.", "select_photos": "사진 선택", + "select_quality": "화질 선택", "select_trash_all": "모두 삭제", "select_user_for_sharing_page_err_album": "앨범을 생성하지 못했습니다.", "selected": "선택됨", @@ -2092,6 +2165,8 @@ "share_assets_selected": "{count}개 선택됨", "share_dialog_preparing": "준비 중...", "share_link": "공유 링크", + "share_original": "원본 사용 (고해상도)", + "share_preview": "썸네일 사용 (저해상도)", "shared": "공유됨", "shared_album_activities_input_disable": "댓글이 비활성화되었습니다", "shared_album_activity_remove_content": "이 활동을 삭제하시겠습니까?", @@ -2160,7 +2235,9 @@ "show_in_timeline": "타임라인에 표시", "show_in_timeline_setting_description": "타임라인에 이 사용자의 사진과 동영상을 표시", "show_keyboard_shortcuts": "키보드 단축키 표시", + "show_less": "접기", "show_metadata": "메타데이터 표시", + "show_more_fields": "필드 {count}개 더 보기", "show_or_hide_info": "정보 표시 또는 숨기기", "show_password": "비밀번호 표시", "show_person_options": "인물 옵션 표시", @@ -2168,6 +2245,7 @@ "show_schema": "스키마 표시", "show_search_options": "검색 옵션 표시", "show_shared_links": "공유 링크 표시", + "show_slideshow_metadata_overlay": "이미지 정보 표시", "show_slideshow_transition": "슬라이드 전환 표시", "show_supporter_badge": "서포터 배지", "show_supporter_badge_description": "서포터 배지 표시", @@ -2183,9 +2261,14 @@ "skip_to_folders": "폴더로 건너뛰기", "skip_to_tags": "태그로 건너뛰기", "slideshow": "슬라이드 쇼", + "slideshow_metadata_overlay_mode": "표시할 정보", + "slideshow_metadata_overlay_mode_description_only": "설명만 보기", + "slideshow_metadata_overlay_mode_full": "전체 표시", "slideshow_repeat": "슬라이드 쇼 반복", "slideshow_repeat_description": "슬라이드 쇼가 끝나면 처음으로 되돌아갑니다", "slideshow_settings": "슬라이드 쇼 설정", + "smart_album": "스마트 앨범", + "some_assets_already_have_a_location_warning": "선택한 항목 중 일부에는 이미 위치 정보가 있습니다", "sort_albums_by": "다음으로 앨범 정렬...", "sort_created": "생성된 날짜", "sort_items": "항목 수", @@ -2208,6 +2291,11 @@ "start_date_before_end_date": "시작일은 종료일보다 이전이어야 합니다", "state": "지역", "status": "상태", + "step_delete": "단계 삭제", + "step_delete_confirm": "이 단계를 삭제하시겠습니까?", + "step_details": "단계 상세 정보", + "steps": "단계", + "steps_count": "단계 {count}개", "stop_casting": "캐스팅 중단", "stop_motion_photo": "모션 포토 정지", "stop_photo_sharing": "공유를 중단하시겠습니까?", @@ -2301,7 +2389,9 @@ "trash_page_title": "휴지통 ({count})", "trashed_items_will_be_permanently_deleted_after": "휴지통으로 이동된 항목은 {days, plural, one {#일} other {#일}} 후 영구적으로 삭제됩니다.", "trigger": "트리거", - "trigger_asset_uploaded": "자산 업로드됨", + "trigger_asset_metadata_extraction": "미디어 메타데이터 추출", + "trigger_asset_metadata_extraction_description": "사진 또는 동영상의 EXIF 메타데이터가 추출될 때 발생합니다", + "trigger_asset_uploaded": "미디어 업로드 완료", "trigger_asset_uploaded_description": "새로운 에셋이 업로드될 때 트리거됩니다", "trigger_description": "워크플로우를 시작하는 이벤트", "trigger_person_recognized": "신원 확인됨", @@ -2347,6 +2437,7 @@ "updated_password": "비밀번호가 변경되었습니다.", "upload": "업로드", "upload_concurrency": "업로드 동시성", + "upload_day_count": "{date}: {count}건 업로드", "upload_details": "업로드 상세", "upload_dialog_info": "선택한 항목을 서버에 백업하시겠습니까?", "upload_dialog_title": "항목 업로드", @@ -2362,6 +2453,8 @@ "upload_to_immich": "Immich에 업로드 ({count})", "uploading": "업로드 중", "uploading_media": "미디어 업로드 중...", + "uploads": "업로드", + "uploads_count": "{count}건 업로드", "url": "URL", "usage": "사용량", "use_biometric": "생체 인증 사용", @@ -2369,6 +2462,7 @@ "use_browser_locale_description": "브라우저 로케일 기반 날짜, 시간, 숫자 형식", "use_current_connection": "현재 네트워크 사용", "use_custom_date_range": "대신 맞춤 기간 사용", + "use_template": "템플릿 사용", "user": "사용자", "user_has_been_deleted": "이 사용자는 삭제되었습니다.", "user_id": "사용자 ID", @@ -2398,6 +2492,7 @@ "video": "동영상", "video_hover_setting": "섬네일 영상 미리보기", "video_hover_setting_description": "섬네일 위에 마우스를 올리면 미리보기를 재생합니다. 비활성화해도 재생 아이콘에 마우스를 올려 미리볼 수 있습니다.", + "video_quality": "동영상 화질", "videos": "동영상", "videos_count": "동영상 {count, plural, one {#개} other {#개}}", "videos_only": "동영상만", @@ -2430,8 +2525,10 @@ "week": "주", "welcome": "환영합니다", "welcome_to_immich": "환영합니다", + "when": "실행 조건", "width": "너비", "wifi_name": "W-Fi 이름", + "workflow": "작업 프로세스", "workflow_delete_prompt": "이 워크플로를 정말로 삭제하시겠습니까?", "workflow_deleted": "워크플로가 삭제되었습니다", "workflow_description": "워크플로 설명", @@ -2441,6 +2538,7 @@ "workflow_name": "워크플로 이름", "workflow_navigation_prompt": "변경 사항을 저장하지 않고 이동하시겠습니까?", "workflow_summary": "워크플로우 요약", + "workflow_templates": "자동화 템플릿", "workflow_update_success": "워크플로가 성공적으로 업데이트되었습니다", "workflow_updated": "워크플로가 업데이트되었습니다", "workflows": "워크플로", diff --git a/i18n/lt.json b/i18n/lt.json index 159e0aa5db..b6194eba1c 100644 --- a/i18n/lt.json +++ b/i18n/lt.json @@ -79,6 +79,7 @@ "cron_expression_description": "Nustatyti skenavimo intervalą naudojant cron formatą. Norėdami gauti daugiau informacijos žiūrėkite Crontab Guru", "cron_expression_presets": "Išankstiniai Cron nustatymai", "disable_login": "Išjungti prisijungimą", + "download_csv": "Parsisiųsti CSV", "duplicate_detection_job_description": "Vykdyti mašininį mokymąsi panašių vaizdų aptikimui. Priklauso nuo išmaniosios paieškos", "exclusion_pattern_description": "Išimčių šablonai leidžia nepaisyti failų ir aplankų skenuojant jūsų biblioteką. Tai yra naudinga, jei turite aplankų su failais, kurių nenorite importuoti, pavyzdžiui, RAW failai.", "export_config_as_json_description": "Atsisiųskite dabartinę sistemos konfigūraciją kaip JSON failą", @@ -191,6 +192,17 @@ "maintenance_delete_backup": "Ištrinti atsarginę kopiją", "maintenance_delete_backup_description": "Šis failas bus negrįžtamai ištrintas.", "maintenance_delete_error": "Nepavyko ištrinti atsarginės kopijos.", + "maintenance_integrity_check_all": "Tikrinti Visus", + "maintenance_integrity_checksum_mismatch": "Checksum neatitikimas", + "maintenance_integrity_checksum_mismatch_job": "Tikrinti checksum neatitikimų", + "maintenance_integrity_checksum_mismatch_refresh_job": "Atnaujinti checksum neatitikimo ataskaitas", + "maintenance_integrity_missing_file": "Trūkstami failai", + "maintenance_integrity_missing_file_job": "Tikrinti, ar nėra trūkstamų failų", + "maintenance_integrity_missing_file_refresh_job": "Atnaujinti trūkstamų failų ataskaitas", + "maintenance_integrity_report": "Vientisumo Ataskaita", + "maintenance_integrity_untracked_file": "Nesekami Failai", + "maintenance_integrity_untracked_file_job": "Patikrinti, ar nėra nesekamų failų", + "maintenance_integrity_untracked_file_refresh_job": "Atnaujinti nesekamų failų ataskaitas", "maintenance_restore_backup": "Atstatyti atsarginę kopiją", "maintenance_restore_backup_description": "Immich bus ištrintas ir atkurtas iš pasirinktos atsarginės kopijos. Prieš tęsiant bus sukurta atsarginė kopija.", "maintenance_restore_backup_different_version": "Ši atsarginė kopija buvo sukurta su skirtinga Immich versija!", @@ -306,6 +318,7 @@ "registration": "Administratoriaus registracija", "registration_description": "Kadangi esate pirmasis šio sistemos naudotojas, jums bus priskirta administratoriaus rolė, ir būsite atsakingas už administracines užduotis ir papildomų naudotojų kūrimą.", "release_channel_release_candidate": "Išleidimo kandidatas", + "release_channel_stable": "Stabili", "remove_failed_jobs": "Pašalinti nepavykusius darbus", "require_password_change_on_login": "Reikalauti, kad naudotojas pasikeistų slaptažodį po pirmojo prisijungimo", "reset_settings_to_default": "Atstatyti nustatymus į numatytuosius", @@ -400,6 +413,10 @@ "transcoding_preferred_hardware_device_description": "Galioja tik VAAPI ir QSV. Nustato dri mazgą aparatiniam perkodavimui.", "transcoding_preset_preset": "Iš anksto nustatytas (-preset)", "transcoding_preset_preset_description": "Kompresijos greitis. Siekiant tam tikro bitrate lėtesnis apdorojimas lems mažesnius failų dydžius ir padidins kokybę. VP9 ignoruos greičius virš \"gretesnis\" lygio.", + "transcoding_realtime": "Realaus laiko transkodavimas [EKSPERIMENTINIS]", + "transcoding_realtime_description": "Leidžia transkoduoti realiuoju laiku, kai vaizdo įrašas transliuojamas. Įgalina kokybės perjungimą, tačiau, priklausomai nuo serverio galimybių, atkūrimas gali strigti ar būti uždelstas.", + "transcoding_realtime_enabled": "Įgalinti transkodavimą realiuoju laiku", + "transcoding_realtime_enabled_description": "Jei išjungta, serveris atsisakys pradėti naujas transkodavimo sesijas realiuoju laiku.", "transcoding_reference_frames": "Nuorodiniai kadrai", "transcoding_reference_frames_description": "Kadrų, į kuriuos reikia remtis suspaudžiant duotą kadrą, skaičius. Aukštesnė reikšmė pagerina suspaudimo efektyvumą, bet sulėtina užkodavimą. 0 - nustato reikšmę automatiškai.", "transcoding_required_description": "Tik nepalaikomo formato vaizdo įrašai", @@ -443,6 +460,8 @@ "user_settings_description": "Valdyti naudotojo nustatymus", "user_successfully_removed": "Naudotojas {email} sėkmingai pašalintas.", "users_page_description": "Administratorių vartotojų puslapis", + "version_check_channel": "Išleidimo kanalas", + "version_check_channel_description": "Pasirinkite leidimo kanalą, kurio versijų pranešimus norite gauti", "version_check_enabled_description": "Įgalinti versijų tikrinimą", "version_check_implications": "Versijų tikrinimas reikalauja periodiškos komunikacijos su {server}", "version_check_settings": "Versijos tikrinimas", @@ -563,6 +582,7 @@ "asset_added_to_album": "Pridėta į albumą", "asset_adding_to_album": "Pridedama į albumą…", "asset_created": "Elementas sukurtas", + "asset_day_count": "{date}: {count, plural, one {# elementas} few {# elementai} other {# elementų}}", "asset_description_updated": "Elemento aprašymas buvo atnaujintas", "asset_filename_is_offline": "Elementas {filename} nepasiekiamas", "asset_has_unassigned_faces": "Elementas turi nepriskirtų veidų", @@ -692,6 +712,7 @@ "backup_settings_subtitle": "Tvarkyti įkėlimo nustatymus", "backup_upload_details_page_more_details": "Bakstelėkite detalesnei informacijai", "backward": "Atgalinis", + "battery_optimization_backup_reliability": "Išjungus akumuliatoriaus optimizavimą, galima pagerinti foninio atsarginio kopijavimo patikimumą", "biometric_auth_enabled": "Biometrinis autentifikavimas įgalintas", "biometric_locked_out": "Jūs esate užblokuotas biometrinio autentifikavimo funkcijai", "biometric_no_options": "Nėra galimų biometrinių nustatymų", @@ -906,6 +927,8 @@ "deduplicate_all": "Šalinti visus dublikatus", "default_locale": "Numatytoji Vietovė", "default_locale_description": "Formatuoti datas ir skaičius pagal savo naršyklės lokalę", + "default_quality_subtitle": "Kokybė, naudojama paliečiant bendrinimą. Kiekvieną kartą pasirinksite paspaudę ir ilgai spausdami bendrinimo mygtuką.", + "default_share_quality": "Numatytoji bendrinimo kokybė", "delete": "Ištrinti", "delete_action_confirmation_message": "Ar tikrai norite ištrinti šį elementą? Šis veiksmas perkels elementą į serverio šiukšliadėžę ir paklaus ar norite ištrinti vietiniame įrenginyje", "delete_action_prompt": "{count} ištrinta", @@ -1215,6 +1238,7 @@ "failed": "Įvyko klaida", "failed_count": "Nepavykę: {count}", "failed_to_authenticate": "Nepavyko autentifikuoti", + "failed_to_delete_file": "Nepavyko ištrinti failo", "failed_to_load_assets": "Nepavyko įkelti elementų", "failed_to_load_folder": "Nepavyko įkelti katalogą", "favorite": "Mėgstamiausias", @@ -1345,6 +1369,7 @@ "individual_share": "Pavienis pasidalinimas", "individual_shares": "Pavieniai pasidalinimai", "info": "Informacija", + "integrity_checks": "Vientisumo Patikrinimai", "interval": { "day_at_onepm": "Kiekvieną dieną 13:00", "hours": "Kas{hours, plural, one {valandą} few {#valandas} other {{hours, number} valandų}}", @@ -1392,6 +1417,7 @@ "leave": "Išeiti", "leave_album": "Palikti albumą", "lens_model": "Lęšių modelis", + "less": "Mažiau", "let_others_respond": "Leisti kitiems reaguoti", "level": "Lygis", "library": "Biblioteka", @@ -1416,6 +1442,7 @@ "linked_oauth_account": "Susieta OAuth paskyra", "list": "Sąrašas", "live": "Tiesiogiai", + "load_more": "Įkelti Daugiau", "loading": "Kraunama", "loading_search_results_failed": "Nepavyko užkrauti paieškos rezultatų", "local": "Vietinis", @@ -1585,6 +1612,8 @@ "merge_people_prompt": "Ar norite sujungti šiuos asmenis? Šis veiksmas yra negrįžtamas.", "merge_people_successfully": "Asmenys sėkmingai sujungti", "merged_people_count": "{count, plural, one {Sujungtas # asmuo} few {Sujungti # asmenys} other {Sujungta # asmenų}}", + "minFaces": "Minimalus veidų skaičius", + "minFaces_description": "Minimalus atpažintų veidų skaičius, kad būtų rodomas asmuo", "minimize": "Sumažinti", "minute": "Minutė", "minutes": "Minutės", @@ -1680,6 +1709,7 @@ "not_selected": "Nepasirinkta", "notes": "Pastabos", "nothing_here_yet": "Kol kas tuščia", + "notification_backup_reliability": "Įjunkite pranešimus, kad pagerintumėte foninių atsarginių kopijų patikimumą", "notification_permission_dialog_content": "Pranešimų įgalinimui eikite į Nustatymus ir pasirinkite Leisti.", "notification_permission_list_tile_content": "Suteikti leidimą pranešimų įgalinimui.", "notification_permission_list_tile_enable_button": "Įjungti pranešimus", @@ -2071,6 +2101,7 @@ "select_person": "Pasirinkti asmenį", "select_person_to_tag": "Pasirinkti asmenį žymai", "select_photos": "Pasirinkti nuotraukas", + "select_quality": "Pasirinkite kokybę", "select_trash_all": "Visus pažymėti \"Išmesti\"", "select_user_for_sharing_page_err_album": "Nepavyko sukurti albumo", "selected": "Pasirinkta", @@ -2134,6 +2165,8 @@ "share_assets_selected": "{count} pažymėta", "share_dialog_preparing": "Ruošiama...", "share_link": "Bendrinti nuorodą", + "share_original": "Naudoti originalą (didelį)", + "share_preview": "Naudoti miniatiūrą (mažą)", "shared": "Bendrinami", "shared_album_activities_input_disable": "Komentarai išjungti", "shared_album_activity_remove_content": "Ar norite ištrinti šią veiklą?", @@ -2235,6 +2268,7 @@ "slideshow_repeat_description": "Pradėti iš pradžių, kai skaidrės baigiasi", "slideshow_settings": "Skaidrių peržiūros nustatymai", "smart_album": "Išmanus albumas", + "some_assets_already_have_a_location_warning": "Kai kurie pasirinkti elementai jau turi vietovę", "sort_albums_by": "Rikiuoti albumus pagal...", "sort_created": "Sukūrimo data", "sort_items": "Elementų skaičių", @@ -2355,11 +2389,13 @@ "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": "Trigeris", + "trigger_asset_metadata_extraction": "Elemento Metaduomenų Ištraukimas", + "trigger_asset_metadata_extraction_description": "Suaktyvinama, kai išgaunami elemento EXIF metaduomenys", "trigger_asset_uploaded": "Elemento Išsiuntimas", "trigger_asset_uploaded_description": "Pradės, kai naujas elementas bus išsiųstas", "trigger_description": "Įvykis, kuris pradeda darbo eigą", "trigger_person_recognized": "Asmuo Atpažintas", - "trigger_person_recognized_description": "Pradės, kai asmuo yra aptiktas", + "trigger_person_recognized_description": "Suaktyvinama, kai asmuo yra atpažintas", "trigger_type": "Trigerio tipas", "troubleshoot": "Šalinti triktis", "type": "Tipas", @@ -2401,6 +2437,7 @@ "updated_password": "Slaptažodis atnaujintas", "upload": "Įkelti", "upload_concurrency": "Įkėlimo lygiagretumas", + "upload_day_count": "{date}: {count, plural, one {# išsiuntimas} few {# išsiuntimai} other {# išsiuntimų}}", "upload_details": "Įkėlimo Detalės", "upload_dialog_info": "Ar norite sukurti pasirinkto(-ų) turinio(-ų) atsarginę kopiją serveryje?", "upload_dialog_title": "Įkelti turinį", @@ -2416,6 +2453,8 @@ "upload_to_immich": "Įkelti į Immich ({count})", "uploading": "Įkeliama", "uploading_media": "Įkeliama medija", + "uploads": "Išsiuntimai", + "uploads_count": "{count, plural, one {# išsiuntimas} few {# išsiuntimai} other {# išsiuntimų}}", "url": "URL", "usage": "Naudojimas", "use_biometric": "Naudoti biometriją", @@ -2453,6 +2492,7 @@ "video": "Vaizdo įrašas", "video_hover_setting": "Paleisti vaizdo įrašo miniatiūrą užvedus pele", "video_hover_setting_description": "Atkurti vaizdo įrašo miniatiūrą, kai pelė užvedama ant elemento. Net ir išjungus, atkūrimą galima pradėti užvedus pelės žymeklį ant atkūrimo piktogramos.", + "video_quality": "Vaizdo įrašo kokybė", "videos": "Video", "videos_count": "{count, plural, one {# vaizdo įrašas} few {# vaizdo įrašai} other {# vaizdo įrašų}}", "videos_only": "Tik Video", diff --git a/i18n/lv.json b/i18n/lv.json index 241f401c07..37afd3e2dd 100644 --- a/i18n/lv.json +++ b/i18n/lv.json @@ -27,6 +27,7 @@ "add_partner": "Pievienot partneri", "add_path": "Pievienot ceļu", "add_photos": "Pievienot fotoattēlus", + "add_step": "Pievienot soli", "add_tag": "Pievienot atzīmi", "add_to": "Pievienot…", "add_to_album": "Pievienot albumam", @@ -78,6 +79,7 @@ "cron_expression_description": "Iestatiet skenēšanas intervālu, izmantojot cron formātu. Papildu informācijai skatiet, piemēram, Crontab Guru", "cron_expression_presets": "Cron izteiksmju sagataves", "disable_login": "Atspējot pieteikšanos", + "download_csv": "Lejupielādēt CSV", "duplicate_detection_job_description": "Analizēt failus ar mašīnmācīšanos, lai noteiktu līdzīgus attēlus. Šī funkcija izmanto viedo meklēšanu", "exclusion_pattern_description": "Izslēgšanas šabloni ļauj ignorēt failus un mapes, skenējot bibliotēku. Tas ir noderīgi, ja jums ir mapes, kas satur failus, kurus nevēlaties importēt, piemēram, RAW failus.", "export_config_as_json_description": "Lejupielādēt pašreizējo sistēmas konfigurāciju kā JSON failu", @@ -190,6 +192,7 @@ "maintenance_delete_backup": "Dzēst rezerves kopiju", "maintenance_delete_backup_description": "Šis fails tiks neatgriezeniski dzēsts.", "maintenance_delete_error": "Neizdevās dzēst rezerves kopiju.", + "maintenance_integrity_report": "Integritātes pārbaude", "maintenance_restore_backup": "Atjaunot no rezerves kopijas", "maintenance_restore_backup_description": "Immich dati tiks dzēsti un atjaunoti no izvēlētā dublējuma. Tiks izveidots dublējums pirms turpinājuma.", "maintenance_restore_backup_different_version": "Šī rezerves kopija tika izveidota ar citu Immich versiju!", diff --git a/i18n/ms.json b/i18n/ms.json index cdc53c0e51..a07a418667 100644 --- a/i18n/ms.json +++ b/i18n/ms.json @@ -479,6 +479,17 @@ "downloading": "Memuat turun", "search_by_description": "Carian secara huraian", "search_by_description_example": "Hari mendaki di Sapa", + "some_assets_already_have_a_location_warning": "Beberapa aset yang dipilih telah memiliki lokasi", + "sort_albums_by": "Susun album mengikut...", + "sort_created": "Tarikh dicipta", + "sort_items": "Bilanganitem", + "sort_modified": "Tarikh diubah", + "sort_newest": "Foto terbaru", + "sort_oldest": "Foto Tertua", + "sort_people_by_similarity": "Susun orang mengikut kesamaan", + "sort_recent": "Foto paling terbaru", + "sort_title": "Tajuk", + "source": "Sumber", "text_recognition": "Pengecaman teks", "theme": "Tema", "theme_selection": "Pemilihan tema", diff --git a/i18n/nb_NO.json b/i18n/nb_NO.json index 32c7a1fab0..1ead05e75e 100644 --- a/i18n/nb_NO.json +++ b/i18n/nb_NO.json @@ -192,6 +192,17 @@ "maintenance_delete_backup": "Slett sikkerhetskopi", "maintenance_delete_backup_description": "Denne filen vil bli permanent slettet.", "maintenance_delete_error": "Feilet ved sletting av sikkerhetskopi.", + "maintenance_integrity_check_all": "Velg alle", + "maintenance_integrity_checksum_mismatch": "Sjekksum er feil", + "maintenance_integrity_checksum_mismatch_job": "Sjekk for feilede sjekksummer", + "maintenance_integrity_checksum_mismatch_refresh_job": "Oppdater feilede sjekksum rapporter", + "maintenance_integrity_missing_file": "Manglende filer", + "maintenance_integrity_missing_file_job": "Sjekk etter manglende filer", + "maintenance_integrity_missing_file_refresh_job": "Oppdater rapporten for manglende filer", + "maintenance_integrity_report": "Integritetsrapport", + "maintenance_integrity_untracked_file": "Usporede filer", + "maintenance_integrity_untracked_file_job": "Sjekk etter usporede filer", + "maintenance_integrity_untracked_file_refresh_job": "Oppdater rapporten for usporede filer", "maintenance_restore_backup": "Gjenopprett Sikkerhetskopi", "maintenance_restore_backup_description": "Immich vil bli sletter og gjenopprettet fra en valgt sikkerhetskopi. En sikkerhetskopi vil utføres før handlingen fortsetter.", "maintenance_restore_backup_different_version": "Denne sikkerhetskopien ble laget med en annen versjon av Immich!", @@ -434,7 +445,7 @@ "unlink_all_oauth_accounts_description": "Husk å koble fra alle OAuth-kontoer før du migrerer til ny leverandør.", "unlink_all_oauth_accounts_prompt": "Vil du virkelig koble fra alle OAuth-kontoer? Dette vil nullstille OAuth ID for hver bruker, og kan ikke angres.", "user_cleanup_job": "Bruker opprydning", - "user_delete_delay": "{user}s konto og elementer vil legges i kø for permanent sletting om {delay, plural, one {# dag} other {# dager}}.", + "user_delete_delay": "{user}'s konto og elementer vil legges i kø for permanent sletting om {delay, plural, one {# dag} other {# dager}}.", "user_delete_delay_settings": "Sletteforsinkelse", "user_delete_delay_settings_description": "Antall dager etter fjerning før en brukerkonto og dens filer permanent slettes. Brukerfjerningsjobben kjører ved midnatt for å sjekke etter brukere som er klare for sletting. Endringer i denne innstillingen vil bli evaluert ved neste utførelse.", "user_delete_immediately": "{user}s konto og elementer vil bli lagt i kø for permanent sletting umiddelbart.", @@ -443,7 +454,7 @@ "user_management": "Brukeradministrasjon", "user_password_has_been_reset": "Passordet til brukeren har blitt tilbakestilt:", "user_password_reset_description": "Vennligst oppgi det midlertidige passordet til brukeren og informer dem om at de må endre passordet ved neste pålogging.", - "user_restore_description": "{user}s konto vil bli gjenopprettet.", + "user_restore_description": "{user}'s konto vil bli gjenopprettet.", "user_restore_scheduled_removal": "Gjenopprett bruker - planlagt sletting den {date, date, long}", "user_settings": "Brukerinnstillinger", "user_settings_description": "Administrer brukerinnstillinger", @@ -916,6 +927,8 @@ "deduplicate_all": "De-dupliser alle", "default_locale": "Standardspråk", "default_locale_description": "Formater datoer og tall basert på din nettlesers språkinnstillinger", + "default_quality_subtitle": "Kvalitet brukt når du trykker på del. Trykk lenge på deleknappen for å velge hver gang.", + "default_share_quality": "Standard delingskvalitet", "delete": "Slett", "delete_action_confirmation_message": "Vil du virkelig slette dette elementet? Dette vil flytte elementet til papirkurven og vil gi deg beskjed om du vil slette det lokalt", "delete_action_prompt": "{count} slettet", @@ -1225,6 +1238,7 @@ "failed": "Mislyktes", "failed_count": "Feilede: {count}", "failed_to_authenticate": "Kunne ikke autentisere", + "failed_to_delete_file": "Feilet sletting av fil", "failed_to_load_assets": "Mislyktes med å laste fil", "failed_to_load_folder": "Kunne ikke laste inn mappe", "favorite": "Favoritt", @@ -1355,6 +1369,7 @@ "individual_share": "Individuell deling", "individual_shares": "Individuelle delinger", "info": "Info", + "integrity_checks": "Integritetssjekker", "interval": { "day_at_onepm": "Hver dag klokken 13:00", "hours": "Hver {hours, plural, one {time} other {{hours, number} timer}}", @@ -1427,6 +1442,7 @@ "linked_oauth_account": "Lenket til OAuth-konto", "list": "Liste", "live": "Direkte", + "load_more": "Last mer", "loading": "Laster", "loading_search_results_failed": "Klarte ikke å laste inn søkeresultater", "local": "Lokal", @@ -2085,6 +2101,7 @@ "select_person": "Valgt person", "select_person_to_tag": "Velg en person å tagge", "select_photos": "Velg bilder", + "select_quality": "Velg kvalitet", "select_trash_all": "Velg å flytte alt til papirkurven", "select_user_for_sharing_page_err_album": "Mislyktes ved oppretting av album", "selected": "Valgt", @@ -2148,6 +2165,8 @@ "share_assets_selected": "{count} valgt", "share_dialog_preparing": "Forbereder ...", "share_link": "Del link", + "share_original": "Bruk original (stor)", + "share_preview": "Bruk miniatyrbilde (lite)", "shared": "Delt", "shared_album_activities_input_disable": "Kommenterer er deaktivert", "shared_album_activity_remove_content": "Vil du slette denne aktiviteten?", @@ -2249,6 +2268,7 @@ "slideshow_repeat_description": "Gå tilbake til begynnelsen når lysbildeserien er slutt", "slideshow_settings": "Lysbildefremvisning innstillinger", "smart_album": "Smartalbum", + "some_assets_already_have_a_location_warning": "Noen av de valgte objektene har allerede en lokasjon", "sort_albums_by": "Sorter album etter...", "sort_created": "Dato opprettet", "sort_items": "Antall enheter", @@ -2369,6 +2389,8 @@ "trash_page_title": "Søppelbøtte ({count})", "trashed_items_will_be_permanently_deleted_after": "Elementer i papirkurven vil bli permanent slettet etter {days, plural, one {# dag} other {# dager}}.", "trigger": "Utløser", + "trigger_asset_metadata_extraction": "Hent ut metadata fra objekter", + "trigger_asset_metadata_extraction_description": "Trigges når EXIF metadata fra ett objekt blir uthentet", "trigger_asset_uploaded": "Last opp objekt", "trigger_asset_uploaded_description": "Utløser når ett nytt objekt er lastet opp", "trigger_description": "En hendelse som utløser arbeidsflyten", diff --git a/i18n/nl.json b/i18n/nl.json index 8c702a05c1..804d07c311 100644 --- a/i18n/nl.json +++ b/i18n/nl.json @@ -63,8 +63,8 @@ "backup_onboarding_footer": "Raadpleeg de documentatie voor meer informatie over het maken van back-ups van Immich.", "backup_onboarding_parts_title": "Een 3-2-1 back-up omvat:", "backup_onboarding_title": "Back-ups", - "backup_settings": "Database dump instellingen", - "backup_settings_description": "Beheer database dump instellingen.", + "backup_settings": "Database back-up instellingen", + "backup_settings_description": "Beheer database back-up instellingen.", "cleared_jobs": "Taken gewist voor: {job}", "config_set_by_file": "Instellingen worden momenteel beheerd door een configuratiebestand", "confirm_delete_library": "Weet je zeker dat je de bibliotheek {library} wilt verwijderen?", @@ -189,31 +189,36 @@ "machine_learning_smart_search_enabled": "Slim zoeken inschakelen", "machine_learning_smart_search_enabled_description": "Indien uitgeschakeld, worden afbeeldingen niet verwerkt voor slim zoeken.", "machine_learning_url_description": "De URL van de machine learning server. Als er meer dan één URL is opgegeven, wordt elke server geprobeerd totdat er een succesvol reageert, op volgorde van eerste tot laatste. Servers die geen reactie geven zullen tijdelijk genegeerd worden tot zij terug online komen.", + "maintenance_backup_management": "Back-upbeheer", "maintenance_delete_backup": "Backup verwijderen", "maintenance_delete_backup_description": "Dit bestand wordt onomkeerbaar verwijderd.", "maintenance_delete_error": "Backup verwijderen mislukt.", + "maintenance_integrity_check": "Controleer", "maintenance_integrity_check_all": "Alles checken", "maintenance_integrity_checksum_mismatch": "Controlegetalafwijking", + "maintenance_integrity_checksum_mismatch_description": "Bestanden waarvan het controlegetal afwijkt van het getal dat Immich in de database heeft opgeslagen.", "maintenance_integrity_checksum_mismatch_job": "Controleer op afwijkingen in controlegetallen", "maintenance_integrity_checksum_mismatch_refresh_job": "Rapport over controlegetalafwijkingen vernieuwen", "maintenance_integrity_missing_file": "Ontbrekende bestanden", + "maintenance_integrity_missing_file_description": "Bestanden die in de database zijn opgeslagen, maar in het bestandssysteem niet bestaan.", "maintenance_integrity_missing_file_job": "Controleer op ontbrekende bestanden", "maintenance_integrity_missing_file_refresh_job": "Rapport over ontbrekende bestanden vernieuwen", "maintenance_integrity_report": "Integriteitsstatus", "maintenance_integrity_untracked_file": "Zwerfbestanden", + "maintenance_integrity_untracked_file_description": "Bestanden die in Immich' mappen voorkomen, maar niet in de database geregistreerd zijn.", "maintenance_integrity_untracked_file_job": "Controleer op zwerfbestanden", "maintenance_integrity_untracked_file_refresh_job": "Rapport over zwerfbestanden vernieuwen", "maintenance_restore_backup": "Backup herstellen", "maintenance_restore_backup_description": "Immich wordt gereset en hersteld vanaf de gekozen backup. Er wordt een backup gemaakt voor deze actie uitgevoerd wordt.", "maintenance_restore_backup_different_version": "Deze backup is gemaakt met een andere versie van Immich!", "maintenance_restore_backup_unknown_version": "Kan versie van backup niet bepalen.", - "maintenance_restore_database_backup": "Database backup terugzetten", - "maintenance_restore_database_backup_description": "Een eerdere versie van de database terugzetten door middel van een backup bestand", + "maintenance_restore_database_backup": "Database back-up terugzetten", + "maintenance_restore_database_backup_description": "Een eerdere versie van de database terugzetten door middel van een back-up bestand", "maintenance_settings": "Onderhoud", "maintenance_settings_description": "Zet Immich in onderhouds­modus.", "maintenance_start": "Onderhouds­modus activeren", "maintenance_start_error": "Onderhouds­modus starten mislukt.", - "maintenance_upload_backup": "Upload database backup bestand", + "maintenance_upload_backup": "Upload database back-up", "maintenance_upload_backup_error": "Kon backup niet uploaden, is het een .sql/.sql.gz bestand?", "manage_concurrency": "Beheer gelijktijdigheid", "manage_concurrency_description": "Navigeer naar de taken­pagina om de gelijk­tijdigheid van taken te beheren", @@ -1500,7 +1505,7 @@ "loop_videos_description": "Inschakelen om video's automatisch te herhalen in de detailweergave.", "main_branch_warning": "Je gebruikt een ontwikkelingsversie. We raden je ten zeerste aan een releaseversie te gebruiken!", "main_menu": "Hoofdmenu", - "maintenance_action_restore": "Database herstellen", + "maintenance_action_restore": "Database wordt hersteld", "maintenance_description": "Immich is in de onderhouds­modus gezet.", "maintenance_end": "Onderhouds­modus beëindigen", "maintenance_end_error": "Onderhouds­modus beëindigen mislukt.", @@ -1508,7 +1513,7 @@ "maintenance_restore_from_backup": "Herstellen vanaf backup", "maintenance_restore_library": "Bibliotheek herstellen", "maintenance_restore_library_confirm": "Als dit er goed uit ziet ga dan verder om de backup terug te zetten!", - "maintenance_restore_library_description": "Database herstellen", + "maintenance_restore_library_description": "Database wordt hersteld", "maintenance_restore_library_folder_has_files": "{folder} heeft {count} map(pen)", "maintenance_restore_library_folder_no_files": "{folder} mist bestanden!", "maintenance_restore_library_folder_pass": "leesbaar en schrijfbaar", @@ -1518,8 +1523,8 @@ "maintenance_restore_library_hint_regenerate_later": "Deze kun je later opnieuw genereren in de instellingen", "maintenance_restore_library_hint_storage_template_missing_files": "Gebruik je een opslagtemplate? Je mist misschien bestanden", "maintenance_restore_library_loading": "Integriteitscontrole en heuristieken laden…", - "maintenance_task_backup": "Backup van bestaande database maken…", - "maintenance_task_migrations": "Bezig met database migraties…", + "maintenance_task_backup": "Back-up van bestaande database maken…", + "maintenance_task_migrations": "Bezig met databasemigraties…", "maintenance_task_restore": "De gekozen backup terugzetten…", "maintenance_task_rollback": "Terugzetten backup mislukt, herstelpunt terugzetten…", "maintenance_title": "Tijdelijk niet beschikbaar", diff --git a/i18n/pl.json b/i18n/pl.json index 2c9ac090de..a92ef20f1a 100644 --- a/i18n/pl.json +++ b/i18n/pl.json @@ -189,18 +189,23 @@ "machine_learning_smart_search_enabled": "Włącz inteligentne wyszukiwanie", "machine_learning_smart_search_enabled_description": "Jeżeli wyłączone, obrazy nie będą przygotowywane do inteligentnego wyszukiwania.", "machine_learning_url_description": "URL serwera uczenia maszynowego. Jeżeli podano więcej niż jeden URL, do każdego serwera po kolei będzie wysłane żądanie dopóki chociaż jeden nie odpowie, w kolejności od pierwszego do ostatniego. Serwery które nie odpowiedzą, zostaną tymczasowo ignorowane aż do momentu ich przejścia w stan online.", + "maintenance_backup_management": "Zarządzanie kopiami zapasowymi", "maintenance_delete_backup": "Usuń kopię zapasową", "maintenance_delete_backup_description": "Ten plik zostanie nieodwracalnie usunięty.", "maintenance_delete_error": "Nie udało się usunąć kopii zapasowej.", + "maintenance_integrity_check": "Sprawdź", "maintenance_integrity_check_all": "Sprawdź wszystko", "maintenance_integrity_checksum_mismatch": "Niezgodność sumy kontrolnej", + "maintenance_integrity_checksum_mismatch_description": "Pliki, których suma kontrolna na dysku nie zgadza się z sumą kontrolną przechowywaną przez Immich w bazie danych.", "maintenance_integrity_checksum_mismatch_job": "Sprawdź, czy nie występują rozbieżności w sumach kontrolnych", "maintenance_integrity_checksum_mismatch_refresh_job": "Odśwież raporty dotyczące niezgodności sum kontrolnych", "maintenance_integrity_missing_file": "Brakujące pliki", + "maintenance_integrity_missing_file_description": "Pliki, które Immich zlokalizował w swojej bazie danych, ale które nie istnieją w systemie plików.", "maintenance_integrity_missing_file_job": "Sprawdź, czy nie brakuje żadnych plików", "maintenance_integrity_missing_file_refresh_job": "Odśwież raporty dotyczące brakujących plików", "maintenance_integrity_report": "Raport dotyczący integralności", "maintenance_integrity_untracked_file": "Pliki nieśledzone", + "maintenance_integrity_untracked_file_description": "Pliki znajdujące się w katalogach Immicha, o których Immich nie ma żadnych informacji.", "maintenance_integrity_untracked_file_job": "Sprawdź, czy są pliki, które nie są śledzone", "maintenance_integrity_untracked_file_refresh_job": "Odśwież raporty dotyczące plików, które nie są śledzone", "maintenance_restore_backup": "Przywróć kopię zapasową", @@ -2165,8 +2170,8 @@ "share_assets_selected": "Wybrano {count}", "share_dialog_preparing": "Przygotowywanie…", "share_link": "Udostępnij link", - "share_original": "Użyj orginału (dużej)", - "share_preview": "Użyj miniatury (małej)", + "share_original": "Użyj orginału (duży)", + "share_preview": "Użyj miniatury (mała)", "shared": "Udostępnione", "shared_album_activities_input_disable": "Komentarz jest wyłączony", "shared_album_activity_remove_content": "Czy chcesz usunąć tę aktywność?", @@ -2390,12 +2395,12 @@ "trashed_items_will_be_permanently_deleted_after": "Wyrzucone zasoby zostaną trwale usunięte po {days, plural, one {jednym dniu} other {# dniach}}.", "trigger": "Wyzwalacz", "trigger_asset_metadata_extraction": "Ekstrakcja metadanych zasobów", - "trigger_asset_metadata_extraction_description": "Wyzwalane, gdy wyodrębniony zostanie plik EXIF zasobu", + "trigger_asset_metadata_extraction_description": "Wyzwalane po wyodrębnieniu metadanych EXIF z zasobu", "trigger_asset_uploaded": "Przesyłanie zasobu", "trigger_asset_uploaded_description": "Wyzwalane gdy przesłany zostanie nowy zasób", "trigger_description": "Wydarzenie, które uruchamia przepływ pracy", "trigger_person_recognized": "Osoba rozpoznana", - "trigger_person_recognized_description": "Wyzwalane gdy zostanie wykryta osoba", + "trigger_person_recognized_description": "Wyzwalane gdy osoba zostanie rozpoznana", "trigger_type": "Rodzaj wyzwalacza", "troubleshoot": "Rozwiąż problemy", "type": "Typ", diff --git a/i18n/pt.json b/i18n/pt.json index 1f9288434c..df05defcca 100644 --- a/i18n/pt.json +++ b/i18n/pt.json @@ -79,6 +79,7 @@ "cron_expression_description": "Definir o intervalo de análise utilizando o formato Cron. Para mais informações, por favor consulte o Crontab Guru", "cron_expression_presets": "Predefinições das expressões Cron", "disable_login": "Desativar inicio de sessão", + "download_csv": "Descarregar CSV", "duplicate_detection_job_description": "Executa a aprendizagem de máquina em ficheiros para detetar imagens semelhantes. Depende da Pesquisa Inteligente", "exclusion_pattern_description": "Os padrões de exclusão permitem ignorar ficheiros e pastas ao analisar a sua biblioteca. Isto é útil se tiver pastas que contenham ficheiros que não deseja importar, como ficheiros RAW.", "export_config_as_json_description": "Descarregar a configuração atual do sistema como um ficheiro JSON", @@ -191,6 +192,17 @@ "maintenance_delete_backup": "Eliminar Cópia de Segurança", "maintenance_delete_backup_description": "Este ficheiro irá ser apagado para sempre.", "maintenance_delete_error": "Ocorreu um erro ao eliminar a cópia de segurança.", + "maintenance_integrity_check_all": "Verificar tudo", + "maintenance_integrity_checksum_mismatch": "Checksum não corresponde", + "maintenance_integrity_checksum_mismatch_job": "Verificar se existem erros de checksum", + "maintenance_integrity_checksum_mismatch_refresh_job": "Atualizar relatórios de erros de checksum", + "maintenance_integrity_missing_file": "Ficheiros em falta", + "maintenance_integrity_missing_file_job": "Verificar se existem ficheiros em falta", + "maintenance_integrity_missing_file_refresh_job": "Atualizar relatórios de ficheiros em falta", + "maintenance_integrity_report": "Relatório de integridade", + "maintenance_integrity_untracked_file": "Ficheiros não monitorizados", + "maintenance_integrity_untracked_file_job": "Verificar se existem ficheiros não monitorizados", + "maintenance_integrity_untracked_file_refresh_job": "Atualizar relatórios de ficheiros não monitorizados", "maintenance_restore_backup": "Restaurar Cópia de Segurança", "maintenance_restore_backup_description": "O Immich irá ser apagado e de seguida restaurado a partir da cópia de segurança selecionada. Irá ser criada uma cópia de segurança antes de continuar.", "maintenance_restore_backup_different_version": "Esta cópia de segurança foi criada com uma versão diferente do Immich!", @@ -915,6 +927,8 @@ "deduplicate_all": "Remover todos os duplicados", "default_locale": "Localização Padrão", "default_locale_description": "Formatar datas e números baseados na definição de localização do navegador", + "default_quality_subtitle": "Qualidade utilizada ao tocar no botão de partilhar. Toque e segure no botão de partilhar para escolher a qualidade a cada vez.", + "default_share_quality": "Qualidade de partilha padrão", "delete": "Eliminar", "delete_action_confirmation_message": "Tem a certeza de que quer eliminar este ficheiro? Está ação irá mover o ficheiro para a reciclagem do servidor e perguntar se quer apagá-lo localmente", "delete_action_prompt": "{count} eliminados", @@ -1224,6 +1238,7 @@ "failed": "Ocorreu um erro", "failed_count": "Falhadas: {count}", "failed_to_authenticate": "Não foi possível autenticar", + "failed_to_delete_file": "Ocorreu um erro ao eliminar ficheiro", "failed_to_load_assets": "Ocorreu um erro ao carregar ficheiros", "failed_to_load_folder": "Ocorreu um erro ao carregar a pasta", "favorite": "Favorito", @@ -1354,6 +1369,7 @@ "individual_share": "Partilha individual", "individual_shares": "Partilhas individuais", "info": "Informações", + "integrity_checks": "Verificações de integridade", "interval": { "day_at_onepm": "Todos os dias, às 13:00", "hours": "A cada {hours, plural, one {hora} other {{hours, number} horas}}", @@ -1426,6 +1442,7 @@ "linked_oauth_account": "Conta OAuth Associada", "list": "Lista", "live": "Em direto", + "load_more": "Carregar Mais", "loading": "A Carregar", "loading_search_results_failed": "Ocorreu um erro ao carregar os resultados da pesquisa", "local": "Local", @@ -2084,6 +2101,7 @@ "select_person": "Selecionar pessoa", "select_person_to_tag": "Selecione uma pessoa para etiquetar", "select_photos": "Selecionar fotos", + "select_quality": "Escolha a qualidade", "select_trash_all": "Selecionar todos para reciclagem", "select_user_for_sharing_page_err_album": "Ocorreu um erro ao criar o álbum", "selected": "Selecionados", @@ -2147,6 +2165,8 @@ "share_assets_selected": "{count} selecionados", "share_dialog_preparing": "Preparando...", "share_link": "Partilhar ligação", + "share_original": "Utilizar original (grande)", + "share_preview": "Utilizar miniatura (pequeno)", "shared": "Partilhado", "shared_album_activities_input_disable": "Comentários desativados", "shared_album_activity_remove_content": "Deseja apagar esta atividade?", @@ -2248,6 +2268,7 @@ "slideshow_repeat_description": "Repetir do inicio quando a apresentação acabar", "slideshow_settings": "Definições de apresentação", "smart_album": "Álbum inteligente", + "some_assets_already_have_a_location_warning": "Alguns dos ficheiros selecionados já possuem localização", "sort_albums_by": "Ordenar álbuns por...", "sort_created": "Data de criação", "sort_items": "Número de itens", @@ -2368,11 +2389,13 @@ "trash_page_title": "Reciclagem ({count})", "trashed_items_will_be_permanently_deleted_after": "Os itens da reciclagem são eliminados permanentemente após {days, plural, one {# dia} other {# dias}}.", "trigger": "Ativador", + "trigger_asset_metadata_extraction": "Extração de Metadados do Ficheiro", + "trigger_asset_metadata_extraction_description": "Acionado quando os metadados EXIF de um ficheiro forem extraídos", "trigger_asset_uploaded": "Carregamento de ficheiro", "trigger_asset_uploaded_description": "Ativado quando um novo ficheiro é carregado", "trigger_description": "Um evento que irá começar o fluxo de trabalho", "trigger_person_recognized": "Pessoa Reconhecida", - "trigger_person_recognized_description": "Ativado quando uma pessoa for detetada", + "trigger_person_recognized_description": "Acionado quando uma pessoa for reconhecida", "trigger_type": "Tipo de ativador", "troubleshoot": "Diagnosticar problemas", "type": "Tipo", diff --git a/i18n/pt_BR.json b/i18n/pt_BR.json index 036670f34f..cbb96657db 100644 --- a/i18n/pt_BR.json +++ b/i18n/pt_BR.json @@ -2389,11 +2389,13 @@ "trash_page_title": "Lixeira ({count})", "trashed_items_will_be_permanently_deleted_after": "Os itens da lixeira serão deletados permanentemente após {days, plural, one {# dia} other {# dias}}.", "trigger": "Gatilho", + "trigger_asset_metadata_extraction": "Extrair Metadado do item", + "trigger_asset_metadata_extraction_description": "Acionado quando o metadado EXIF de um item for extraído", "trigger_asset_uploaded": "Arquivo enviado", "trigger_asset_uploaded_description": "Acionado quando um novo arquivo é enviado", "trigger_description": "Um evento que dá início ao fluxo", "trigger_person_recognized": "Pessoa reconhecida", - "trigger_person_recognized_description": "Acionado quando uma pessoa é detectada", + "trigger_person_recognized_description": "Acionado quando uma pessoa é reconhecida", "trigger_type": "Tipo de gatilho", "troubleshoot": "Diagnosticar", "type": "Tipo", diff --git a/i18n/ru.json b/i18n/ru.json index b92490cb1e..7aca149e69 100644 --- a/i18n/ru.json +++ b/i18n/ru.json @@ -189,18 +189,23 @@ "machine_learning_smart_search_enabled": "Включить интеллектуальный поиск", "machine_learning_smart_search_enabled_description": "При отключении этой функции изображения не будут кодироваться для интеллектуального поиска.", "machine_learning_url_description": "URL-адрес сервера машинного обучения. Если указано несколько, запросы будут отправляться по очереди на каждый, пока от одного из них не будет получен успешный ответ. Серверы, которые не отвечают, будут временно игнорироваться до тех пор, пока не станут снова доступны.", + "maintenance_backup_management": "Управление резервным копированием", "maintenance_delete_backup": "Удалить резервную копию", "maintenance_delete_backup_description": "Эта резервная копия будет безвозвратно удалена.", "maintenance_delete_error": "Не удалось удалить резервную копию.", + "maintenance_integrity_check": "Проверить", "maintenance_integrity_check_all": "Проверить все", "maintenance_integrity_checksum_mismatch": "Ошибки контрольных сумм", + "maintenance_integrity_checksum_mismatch_description": "Файлы, контрольная сумма которых не совпадает с контрольной суммой, хранящейся в базе данных Immich.", "maintenance_integrity_checksum_mismatch_job": "Проверка соответствия контрольных сумм", "maintenance_integrity_checksum_mismatch_refresh_job": "Обновить количество ошибок контрольных сумм", "maintenance_integrity_missing_file": "Отсутствующие файлы", + "maintenance_integrity_missing_file_description": "Файлы, записи о которых имеются в базе данных Immich, но сами файлы отсутствуют на диске.", "maintenance_integrity_missing_file_job": "Проверка наличия отсутствующих файлов", "maintenance_integrity_missing_file_refresh_job": "Обновить количество отсутствующих файлов", "maintenance_integrity_report": "Проверка целостности", "maintenance_integrity_untracked_file": "Неотслеживаемые файлы", + "maintenance_integrity_untracked_file_description": "Файлы, находящиеся в каталогах Immich, но о которых в базе данных Immich нет никаких сведений.", "maintenance_integrity_untracked_file_job": "Проверка наличия неотслеживаемых файлов", "maintenance_integrity_untracked_file_refresh_job": "Обновить количество неотслеживаемых файлов", "maintenance_restore_backup": "Восстановить резервную копию", @@ -2390,7 +2395,7 @@ "trashed_items_will_be_permanently_deleted_after": "Объекты, хранящиеся в корзине более {days, plural, one {# дня} other {# дней}}, удаляются автоматически.", "trigger": "Триггер", "trigger_asset_metadata_extraction": "Извлечение метаданных объекта", - "trigger_asset_metadata_extraction_description": "Срабатывает при извлечении EXIF-данных объекта", + "trigger_asset_metadata_extraction_description": "Срабатывает при извлечении EXIF метаданных объекта", "trigger_asset_uploaded": "Загрузка объекта", "trigger_asset_uploaded_description": "Срабатывает при загрузке нового объекта", "trigger_description": "Событие, которое запускает сценарий", diff --git a/i18n/sk.json b/i18n/sk.json index 06632cf90a..d15eb00dee 100644 --- a/i18n/sk.json +++ b/i18n/sk.json @@ -114,7 +114,7 @@ "image_thumbnail_quality_description": "Kvalita miniatúry v stupnici od 1 do 100. Vyššia hodnota znamená lepšiu kvalitu, ale produkuje väčšie súbory a môže znížiť odozvu aplikácie.", "image_thumbnail_title": "Miniatúry", "import_config_from_json_description": "Importovať konfiguráciu systému nahraním konfiguračného súboru JSON", - "job_concurrency": "Súbežnosť úlohy - {job}", + "job_concurrency": "Súbežné úlohy - {job}", "job_created": "Úloha bola vytvorená", "job_not_concurrency_safe": "Táto úloha nie je bezpečná pre súbežné spracovanie.", "job_settings": "Úlohy", @@ -2390,12 +2390,12 @@ "trashed_items_will_be_permanently_deleted_after": "Položky v koši sa natrvalo vymažú po {days, plural, one {# dni} other {# dňoch}}.", "trigger": "Spúšťač", "trigger_asset_metadata_extraction": "Extrakcia metadát položky", - "trigger_asset_metadata_extraction_description": "Spustí sa pri extrakcii údajov EXIF z mediálneho súboru", + "trigger_asset_metadata_extraction_description": "Spustí sa pri extrakcii EXIF metadát z mediálneho súboru", "trigger_asset_uploaded": "Nahranie položiek", "trigger_asset_uploaded_description": "Spustí sa pri nahratí novej položky", "trigger_description": "Udalosť, ktorá spustí pracovný postup", "trigger_person_recognized": "Osoba bola rozpoznaná", - "trigger_person_recognized_description": "Spustí sa, keď bude objavená osoba", + "trigger_person_recognized_description": "Spustí sa, keď sa rozpozná osoba", "trigger_type": "Typ spúšťača", "troubleshoot": "Riešenie problémov", "type": "Typ", @@ -2496,7 +2496,7 @@ "videos": "Videá", "videos_count": "{count, plural, one {# Video} few {# Videá} other {# Videí}}", "videos_only": "Iba videá", - "view": "Zobrazenie", + "view": "Zobraziť", "view_album": "Zobraziť Album", "view_all": "Zobraziť všetky", "view_all_users": "Zobraziť všetkých používateľov", diff --git a/i18n/sq.json b/i18n/sq.json index 9738a274df..8ffc1ea435 100644 --- a/i18n/sq.json +++ b/i18n/sq.json @@ -146,7 +146,185 @@ "machine_learning_availability_checks_enabled": "Aktivizo kontrollet e disponueshmërisë", "machine_learning_availability_checks_interval": "Kontrolli i intervalit", "machine_learning_availability_checks_interval_description": "Intervali në milisekonda midis kontrolleve të disponueshmërisë", - "machine_learning_availability_checks_timeout": "Kërko timeout" + "machine_learning_availability_checks_timeout": "Kërko timeout", + "machine_learning_availability_checks_timeout_description": "Kohëzgjatja në milisekonda për kontrollet e disponueshmërisë", + "machine_learning_clip_model": "Modeli CLIP", + "machine_learning_clip_model_description": "Emri i një modeli CLIP është listuar këtu. Vini re se duhet ta riekzekutoni punën 'Kërkim i Mençur' për të gjitha imazhet pas ndryshimit të një modeli.", + "machine_learning_duplicate_detection": "Zbulimi i dublikatave", + "machine_learning_duplicate_detection_enabled": "Aktivizo zbulimin e dublikatave", + "machine_learning_duplicate_detection_enabled_description": "Nëse çaktivizohet, asetet saktësisht identike do të hiqen nga dublikimet.", + "machine_learning_duplicate_detection_setting_description": "Përdorni ngulitje CLIP për të gjetur dublikata të mundshme", + "machine_learning_enabled": "Aktivizo të mësuarit automatik", + "machine_learning_enabled_description": "Nëse çaktivizohet, të gjitha veçoritë e ML do të çaktivizohen pavarësisht nga cilësimet e mëposhtme.", + "machine_learning_facial_recognition": "Njohja e fytyrës", + "machine_learning_facial_recognition_description": "Zbuloni, njihni dhe gruponi fytyrat në imazhe", + "machine_learning_facial_recognition_model": "Modeli i njohjes së fytyrës", + "machine_learning_facial_recognition_model_description": "Modelet renditen në rend zbritës të madhësisë. Modelet më të mëdha janë më të ngadalta dhe përdorin më shumë memorie, por japin rezultate më të mira. Vini re se duhet ta riekzekutoni punën e Zbulimit të Fytyrës për të gjitha imazhet pas ndryshimit të një modeli.", + "machine_learning_facial_recognition_setting": "Aktivizo njohjen e fytyrës", + "machine_learning_facial_recognition_setting_description": "Nëse çaktivizohet, imazhet nuk do të kodohen për njohjen e fytyrës dhe nuk do të popullojnë seksionin e Njerëzve në faqen Eksploro.", + "machine_learning_max_detection_distance": "Distanca maksimale e zbulimit", + "machine_learning_max_detection_distance_description": "Distanca maksimale midis dy imazheve për t'i konsideruar ato si dublikate, duke filluar nga 0.001-0.1. Vlerat më të larta do të zbulojnë më shumë dublikate, por mund të rezultojnë në pozitive të rreme.", + "machine_learning_max_recognition_distance": "Distanca maksimale e njohjes", + "machine_learning_max_recognition_distance_description": "Distanca maksimale midis dy fytyrave për t'u konsideruar i njëjti person, varion nga 0-2. Ulja e kësaj distance mund të parandalojë etiketimin e dy personave si i njëjti person, ndërsa rritja e saj mund të parandalojë etiketimin e të njëjtit person si dy persona të ndryshëm. Vini re se është më e lehtë të bashkoni dy persona sesa të ndani një person në dy, prandaj zgjidhni një prag më të ulët kur është e mundur.", + "machine_learning_min_detection_score": "Rezultati minimal i zbulimit", + "machine_learning_min_detection_score_description": "Rezultati minimal i besimit për një fytyrë që do të zbulohet është nga 0-1. Vlerat më të ulëta do të zbulojnë më shumë fytyra, por mund të rezultojnë në rezultate të rreme pozitive.", + "machine_learning_min_recognized_faces": "Fytyrat minimale të njohura", + "machine_learning_min_recognized_faces_description": "Numri minimal i fytyrave të njohura që duhet të krijohet për një person. Rritja e kësaj e bën Njohjen e Fytyrës më të saktë me koston e rritjes së mundësisë që një fytyrë të mos i caktohet një personi.", + "machine_learning_ocr": "OCR", + "machine_learning_ocr_description": "Përdorni të mësuarit automatik për të njohur tekstin në imazhe", + "machine_learning_ocr_enabled": "Aktivizo OCR-në", + "machine_learning_ocr_enabled_description": "Nëse çaktivizohet, imazhet nuk do t'i nënshtrohen njohjes së tekstit.", + "machine_learning_ocr_max_resolution": "Rezolucioni maksimal", + "machine_learning_ocr_max_resolution_description": "Pamjet paraprake mbi këtë rezolucion do të ndryshohen në madhësi duke ruajtur raportin e aspektit. Vlerat më të larta janë më të sakta, por kërkojnë më shumë kohë për t'u përpunuar dhe përdorin më shumë memorie.", + "machine_learning_ocr_min_detection_score": "Rezultati minimal i zbulimit", + "machine_learning_ocr_min_detection_score_description": "Rezultati minimal i besimit për tekstin që duhet zbuluar është nga 0-1. Vlerat më të ulëta do të zbulojnë më shumë tekst, por mund të rezultojnë në pozitive të rreme.", + "machine_learning_ocr_min_recognition_score": "Rezultati minimal i njohjes", + "machine_learning_ocr_min_score_recognition_description": "Rezultati minimal i besimit për tekstin e zbuluar që duhet të njihet nga 0-1. Vlerat më të ulëta do të njohin më shumë tekst, por mund të rezultojnë në pozitive të rreme.", + "machine_learning_ocr_model": "Modeli OCR", + "machine_learning_ocr_model_description": "Modelet e serverit janë më të sakta se modelet mobile, por kërkojnë më shumë kohë për t'u përpunuar dhe përdorin më shumë memorie.", + "machine_learning_settings": "Cilësimet e të Mësuarit Automatik", + "machine_learning_settings_description": "Menaxho veçoritë dhe cilësimet e të mësuarit automatik", + "machine_learning_smart_search": "Kërkim i Mençur", + "machine_learning_smart_search_description": "Kërko për imazhe semantikisht duke përdorur ngulitje CLIP", + "machine_learning_smart_search_enabled": "Aktivizo kërkimin inteligjent", + "machine_learning_smart_search_enabled_description": "Nëse çaktivizohet, imazhet nuk do të kodohen për kërkim inteligjent.", + "machine_learning_url_description": "URL-ja e serverit të të mësuarit automatik. Nëse jepet më shumë se një URL, secili server do të provohet një nga një derisa njëri të përgjigjet me sukses, në rend nga i pari tek i fundit. Serverët që nuk përgjigjen do të injorohen përkohësisht derisa të kthehen në linjë.", + "maintenance_delete_backup": "Fshi kopjen rezervë", + "maintenance_delete_backup_description": "Ky skedar do të fshihet në mënyrë të pakthyeshme.", + "maintenance_delete_error": "Fshirja e kopjes rezervë dështoi.", + "maintenance_integrity_check_all": "Kontrollo të gjitha", + "maintenance_integrity_checksum_mismatch": "Mospërputhje e shumës së kontrollit", + "maintenance_integrity_checksum_mismatch_job": "Kontrolloni për mospërputhje të shumës së kontrollit", + "maintenance_integrity_checksum_mismatch_refresh_job": "Rifresko raportet e mospërputhjes së shumës së kontrollit", + "maintenance_integrity_missing_file": "Skedarët që mungojnë", + "maintenance_integrity_missing_file_job": "Kontrolloni për skedarë që mungojnë", + "maintenance_integrity_missing_file_refresh_job": "Rifresko raportet e skedarëve që mungojnë", + "maintenance_integrity_report": "Raporti i Integritetit", + "maintenance_integrity_untracked_file": "Skedarët e Pagjurmuar", + "maintenance_integrity_untracked_file_job": "Kontrolloni për skedarë të pagjurmuar", + "maintenance_integrity_untracked_file_refresh_job": "Rifresko raportet e skedarëve të pagjurmuar", + "maintenance_restore_backup": "Rivendos rezervën", + "maintenance_restore_backup_description": "Immich do të fshihet dhe do të rikthehet nga kopja rezervë e zgjedhur. Një kopje rezervë do të krijohet përpara se të vazhdohet.", + "maintenance_restore_backup_different_version": "Ky kopje rezervë u krijua me një version të ndryshëm të Immich!", + "maintenance_restore_backup_unknown_version": "Nuk mund të përcaktohej versioni i rezervimit.", + "maintenance_restore_database_backup": "Rivendos kopjen rezervë të bazës së të dhënave", + "maintenance_restore_database_backup_description": "Rikthim në një gjendje më të hershme të bazës së të dhënave duke përdorur një skedar rezervë", + "maintenance_settings": "Mirëmbajtje", + "maintenance_settings_description": "Vendos Immich në modalitetin e mirëmbajtjes.", + "maintenance_start": "Kaloni në modalitetin e mirëmbajtjes", + "maintenance_start_error": "Dështoi në nisjen e modalitetit të mirëmbajtjes.", + "maintenance_upload_backup": "Ngarko skedarin rezervë të bazës së të dhënave", + "maintenance_upload_backup_error": "Nuk mund të ngarkohet kopja rezervë, a është një skedar .sql/.sql.gz?", + "manage_concurrency": "Menaxho Konkurrencën", + "manage_concurrency_description": "Shko te faqja e punëve për të menaxhuar paralelisht punën", + "manage_log_settings": "Menaxho cilësimet e regjistrit", + "map_dark_style": "Stil i errët", + "map_enable_description": "Aktivizo veçoritë e hartës", + "map_gps_settings": "Cilësimet e Hartës dhe GPS-it", + "map_gps_settings_description": "Menaxho Cilësimet e Hartës dhe GPS-it (Gjeokodimi i Anasjelltë)", + "map_implications": "Funksioni i hartës mbështetet në një shërbim të jashtëm me pllaka (tiles.immich.cloud)", + "map_light_style": "Stil i lehtë", + "map_manage_reverse_geocoding_settings": "Menaxho cilësimet e Gjeokodimit të kundërt", + "map_reverse_geocoding": "Gjeokodimi i kundërt", + "map_reverse_geocoding_enable_description": "Aktivizo gjeokodimin e kundërt", + "map_reverse_geocoding_settings": "Cilësimet e Gjeokodimit të Anasjelltë", + "map_settings": "Hartë", + "map_settings_description": "Menaxho cilësimet e hartës", + "map_style_description": "URL-ja e një teme harte style.json", + "memory_cleanup_job": "Pastrimi i kujtesës", + "memory_generate_job": "Gjenerimi i kujtesës", + "metadata_extraction_job": "Ekstraktoni metadatat", + "metadata_extraction_job_description": "Nxirrni informacionin e meta-tadatave nga çdo aset, siç janë GPS, fytyrat dhe rezolucioni", + "metadata_faces_import_setting": "Aktivizo importimin e fytyrës", + "metadata_faces_import_setting_description": "Importo fytyrat nga të dhënat EXIF të imazhit dhe skedarët e karrocës anësore", + "metadata_settings": "Cilësimet e meta të dhënave", + "metadata_settings_description": "Menaxho cilësimet e meta-të dhënave", + "migration_job": "Migrimi", + "migration_job_description": "Migro miniaturat për asetet dhe fytyrat në strukturën më të fundit të dosjeve", + "nightly_tasks_cluster_faces_setting_description": "Ekzekutoni njohjen e fytyrës në fytyrat e zbuluara rishtazi", + "nightly_tasks_cluster_new_faces_setting": "Grumbulloni fytyra të reja", + "nightly_tasks_database_cleanup_setting": "Detyrat e pastrimit të bazës së të dhënave", + "nightly_tasks_database_cleanup_setting_description": "Pastroni të dhënat e vjetra dhe të skaduara nga baza e të dhënave", + "nightly_tasks_generate_memories_setting": "Gjeneroni kujtime", + "nightly_tasks_generate_memories_setting_description": "Krijo kujtime të reja nga asetet", + "nightly_tasks_missing_thumbnails_setting": "Gjenero miniaturat që mungojnë", + "nightly_tasks_missing_thumbnails_setting_description": "Vendosni në radhë asetet pa miniatura për gjenerimin e miniaturave", + "nightly_tasks_settings": "Cilësimet e Detyrave të Natës", + "nightly_tasks_settings_description": "Menaxho detyrat e natës", + "nightly_tasks_start_time_setting": "Ora e fillimit", + "nightly_tasks_start_time_setting_description": "Koha në të cilën serveri fillon të ekzekutojë detyrat e natës", + "nightly_tasks_sync_quota_usage_setting": "Përdorimi i kuotës së sinkronizimit", + "nightly_tasks_sync_quota_usage_setting_description": "Përditëso kuotën e ruajtjes së përdoruesit, bazuar në përdorimin aktual", + "no_paths_added": "Nuk janë shtuar shtigje", + "no_pattern_added": "Nuk është shtuar asnjë model", + "note_apply_storage_label_previous_assets": "Shënim: Për të aplikuar Etiketën e Ruajtjes në asetet e ngarkuara më parë, ekzekutoni", + "note_cannot_be_changed_later": "SHËNIM: Kjo nuk mund të ndryshohet më vonë!", + "notification_email_from_address": "Adresa nga", + "notification_email_from_address_description": "Adresa e email-it të dërguesit, për shembull: \"Immich Photo Server \". Sigurohuni që të përdorni një adresë nga e cila lejoheni të dërgoni email-e.", + "notification_email_host_description": "Strehuesi i serverit të email-it (p.sh. smtp.immich.app)", + "notification_email_ignore_certificate_errors": "Injoro gabimet e certifikatës", + "notification_email_ignore_certificate_errors_description": "Injoroni gabimet e validimit të certifikatës TLS (nuk rekomandohet)", + "notification_email_password_description": "Fjalëkalimi që duhet përdorur gjatë autentifikimit me serverin e email-it", + "notification_email_port_description": "Porta e serverit të email-it (p.sh. 25, 465 ose 587)", + "notification_email_secure": "SMTPS", + "notification_email_secure_description": "Përdorni SMTPS (SMTP mbi TLS)", + "notification_email_sent_test_email_button": "Dërgo email-in e provës dhe ruaj", + "notification_email_setting_description": "Cilësimet për dërgimin e njoftimeve me email", + "notification_email_test_email": "Dërgo email testimi", + "notification_email_test_email_failed": "Dërgimi i email-it të testimit dështoi, kontrolloni vlerat tuaja", + "notification_email_test_email_sent": "Një email provë është dërguar te {email}. Ju lutemi kontrolloni kutinë tuaj hyrëse.", + "notification_email_username_description": "Emri i përdoruesit që do të përdoret gjatë autentifikimit me serverin e email-it", + "notification_enable_email_notifications": "Aktivizo njoftimet me email", + "notification_settings": "Cilësimet e njoftimeve", + "notification_settings_description": "Menaxho cilësimet e njoftimeve, duke përfshirë email-in", + "oauth_allow_insecure_requests": "Lejo kërkesa të pasigurta", + "oauth_allow_insecure_requests_description": "KUJDES: Kjo çaktivizon validimin e certifikatës TLS për kërkesat OAuth dhe mund t'ju ekspozojë ndaj sulmeve MITM.", + "oauth_auto_launch": "Nisja automatike", + "oauth_auto_launch_description": "Filloni automatikisht rrjedhën e hyrjes në OAuth sapo të shkoni në faqen e hyrjes", + "oauth_auto_register": "Regjistrim automatik", + "oauth_auto_register_description": "Regjistro automatikisht përdoruesit e rinj pas hyrjes me OAuth", + "oauth_button_text": "Teksti i butonit", + "oauth_client_secret_description": "E detyrueshme për klient konfidencial, ose nëse PKCE (Çelësi i Provës për Shkëmbimin e Kodit) nuk mbështetet për klientin publik.", + "oauth_enable_description": "Kyçu me OAuth", + "oauth_end_session_url_description": "Ridrejto përdoruesin në këtë URI kur të dalë.", + "oauth_mobile_redirect_uri": "URL-ja e ridrejtimit për celular", + "oauth_mobile_redirect_uri_override": "Mbivendosja e URI-së së ridrejtimit celular", + "oauth_mobile_redirect_uri_override_description": "Aktivizo kur ofruesi i OAuth nuk lejon një URI celular, si p.sh. ''{callback}''", + "oauth_prompt_description": "Parametri i kërkesës (p.sh. select_account, login, consent)", + "oauth_role_claim": "Pretendimi për Rol", + "oauth_role_claim_description": "Jep automatikisht akses administratori bazuar në praninë e këtij pretendimi. Pretendimi mund të ketë ose 'përdorues' ose 'administrator'.", + "oauth_settings": "OAuth", + "oauth_settings_description": "Menaxho cilësimet e hyrjes në OAuth", + "oauth_settings_more_details": "Për më shumë detaje rreth kësaj veçorie, referojuni dokumenteve.", + "oauth_storage_label_claim": "Pretendimi për etiketën e ruajtjes", + "oauth_storage_label_claim_description": "Cakto automatikisht etiketën e ruajtjes së përdoruesit në vlerën e këtij pretendimi.", + "oauth_storage_quota_claim": "Pretendim për kuotën e ruajtjes së të dhënave", + "oauth_storage_quota_claim_description": "Cakto automatikisht kuotën e ruajtjes së përdoruesit në vlerën e këtij pretendimi.", + "oauth_storage_quota_default": "Kuota e parazgjedhur e ruajtjes (GiB)", + "oauth_storage_quota_default_description": "Kuota në GiB do të përdoret kur nuk paraqitet asnjë kërkesë.", + "oauth_timeout": "Kërkesë për skadimin e kohës", + "oauth_timeout_description": "Kohëzgjatja e pritjes për kërkesat në milisekonda", + "ocr_job_description": "Përdorni të mësuarit automatik për të njohur tekstin në imazhe", + "password_enable_description": "Kyçu me email dhe fjalëkalim", + "password_settings": "Fjalëkalimi Hyrje", + "password_settings_description": "Menaxho cilësimet e hyrjes me fjalëkalim", + "paths_validated_successfully": "Të gjitha shtigjet u validuan me sukses", + "person_cleanup_job": "Pastrim personash", + "queue_details": "Detajet e radhës", + "queues": "Radhët e Punës", + "queues_page_description": "Faqja e radhëve të punës së administratorit", + "quota_size_gib": "Madhësia e Kuotës (GiB)", + "refreshing_all_libraries": "Duke rifreskuar të gjitha bibliotekat", + "registration": "Regjistrimi i Administratorit", + "registration_description": "Meqenëse jeni përdoruesi i parë në sistem, do të caktoheni si Administrator dhe do të jeni përgjegjës për detyrat administrative, dhe përdorues të tjerë do të krijohen nga ju.", + "release_channel_release_candidate": "Kandidat për lirim", + "release_channel_stable": "I Qëndrueshëm", + "remove_failed_jobs": "Hiq punët e dështuara", + "require_password_change_on_login": "Kërkon që përdoruesi të ndryshojë fjalëkalimin në hyrjen e parë", + "reset_settings_to_default": "Rivendos cilësimet në ato të parazgjedhura", + "reset_settings_to_recent_saved": "Rivendos cilësimet në cilësimet e ruajtura së fundmi", + "scanning_library": "Duke skanuar bibliotekën", + "search_jobs": "Kërko punë…" }, "download_original": "Shkarko origjinalin", "download_paused": "Shkarkimi u pezullua", diff --git a/i18n/uk.json b/i18n/uk.json index 81460eead8..78812084ed 100644 --- a/i18n/uk.json +++ b/i18n/uk.json @@ -79,6 +79,7 @@ "cron_expression_description": "Установіть інтервал сканування у форматі cron. Додаткова інформація: Crontab Guru", "cron_expression_presets": "Шаблони Cron-виразів", "disable_login": "Вимкнути вхід", + "download_csv": "Завантажити CSV", "duplicate_detection_job_description": "Виконати машинне навчання для виявлення схожих зображень. Потребує розумного пошуку", "exclusion_pattern_description": "Шаблони винятків дають змогу ігнорувати файли та папки під час сканування бібліотеки. Це корисно для папок із небажаними для імпорту файлами, наприклад файлами RAW.", "export_config_as_json_description": "Завантажити поточну конфігурацію системи у форматі JSON", @@ -191,6 +192,11 @@ "maintenance_delete_backup": "Видалити резервну копію", "maintenance_delete_backup_description": "Цей файл буде безповоротно видалено.", "maintenance_delete_error": "Не вдалося видалити резервну копію.", + "maintenance_integrity_check_all": "Перевірити все", + "maintenance_integrity_checksum_mismatch": "Контрольна сума не сходиться", + "maintenance_integrity_missing_file": "Файли що відсутні", + "maintenance_integrity_missing_file_job": "Перевірка відсутніх файлів", + "maintenance_integrity_missing_file_refresh_job": "Оновити звіт про відсутні файли", "maintenance_restore_backup": "Відновити резервну копію", "maintenance_restore_backup_description": "Immich буде стерто та відновлено з вибраної резервної копії. Перед продовженням буде створено резервну копію.", "maintenance_restore_backup_different_version": "Цю резервну копію було створено за допомогою іншої версії Immich!", diff --git a/i18n/yue_Hant.json b/i18n/yue_Hant.json index 8cb6aeb6b4..e19f05c88c 100644 --- a/i18n/yue_Hant.json +++ b/i18n/yue_Hant.json @@ -7,8 +7,8 @@ "action_common_update": "更新", "action_description": "針對篩選後嘅資源執行嘅一系列動作", "actions": "動作", - "active": "正在處理", - "active_count": "正在處理:{count}", + "active": "處理緊", + "active_count": "處理緊:{count}", "activity": "活動", "activity_changed": "活動已{enabled, select, true {啟動} other {停止}}", "add": "加", @@ -17,7 +17,7 @@ "add_a_name": "加一個姓名", "add_a_title": "加一個標題", "add_action": "加動作", - "add_action_description": "點擊以加動作", + "add_action_description": "撳呢度加動作", "add_assets": "加資源", "add_birthday": "加一個生日", "add_endpoint": "加端點", @@ -29,21 +29,21 @@ "add_photos": "加多張相片", "add_step": "加步驟", "add_tag": "加標籤", - "add_to": "加至…", - "add_to_album": "加至相簿", - "add_to_album_bottom_sheet_added": "已加至{album}", - "add_to_album_bottom_sheet_already_exists": "已在 {album} 中", - "add_to_album_bottom_sheet_some_local_assets": "無法加部分本機資源至相簿", - "add_to_album_toggle": "選擇{album}相簿", - "add_to_albums": "加至相簿", - "add_to_albums_count": "加 ({count}) 個項目至相簿", - "add_to_bottom_bar": "加至", - "add_to_shared_album": "加至共享相簿", + "add_to": "加到…", + "add_to_album": "加到相簿", + "add_to_album_bottom_sheet_added": "已加到{album}", + "add_to_album_bottom_sheet_already_exists": "已經喺 {album} 中", + "add_to_album_bottom_sheet_some_local_assets": "加唔到一啲本機資源到相簿", + "add_to_album_toggle": "揀 {album} 相簿", + "add_to_albums": "加到相簿", + "add_to_albums_count": "加 ({count}) 個項目到相簿", + "add_to_bottom_bar": "加到", + "add_to_shared_album": "加到共享相簿", "add_upload_to_stack": "新增上傳到堆疊", "add_url": "加網址", - "added_to_archive": "已添至封存", - "added_to_favorites": "已加至最愛", - "added_to_favorites_count": "已加{count, number} 個項目至最愛", + "added_to_archive": "已加咗入封存", + "added_to_favorites": "已加咗到最愛", + "added_to_favorites_count": "已加咗{count, number} 個項目到最愛", "admin": { "add_exclusion_pattern_description": "添加排除模式。支持使用 *、** 同? 嘅萬用字元比對 (Globbing)。例如,使用「**/Raw/**」忽略任何raw檔案,或者已「**/*.tif」忽略全部以「.tif」結尾的檔案;如果要忽略特定嘅絕對路徑請使用「/path/to/ignore/**」。", "admin_user": "管理員用戶", @@ -79,6 +79,7 @@ "cron_expression_description": "使用 Cron 格式嚟設定掃描嘅間隔。更多嘅資訊請查閱 Crontab Guru", "cron_expression_presets": "Cron 表達式預設選項", "disable_login": "停止使用登入", + "download_csv": "下載CSV檔案", "duplicate_detection_job_description": "運用機械學習,依靠智慧搜尋嚟偵測相似嘅相片", "exclusion_pattern_description": "你可以用排除模式喺掃描媒體庫時忽略特定嘅檔案同資料夾。喺某啲資料夾有你唔想加入嘅檔案(例如RAW相)嘅情況下呢個功能將會好有用。", "export_config_as_json_description": "將目前嘅系統設定下載為 JSON 檔案", @@ -100,7 +101,7 @@ "image_prefer_wide_gamut": "傾向廣色域", "image_prefer_wide_gamut_setting_description": "使用 Display P3 製作縮圖:可以更好地保留廣色域影像嘅鮮豔度,但係喺舊裝置同舊版瀏覽器上,影像呈現嘅效果可能會有所唔同。sRGB 影像會保留為 sRGB,以避免色彩偏移。", "image_preview_description": "中等尺寸嘅圖片,用嚟檢視單一影像同埋機器學習", - "image_preview_quality_description": "從1-100選擇預覽嘅質素。數值越高越品質好,但會產生較大嘅檔案同影響app嘅反應速度。設定低嘅數值有機會影響機器學習嘅品質。", + "image_preview_quality_description": "從1-100揀預覽嘅質素。數值越高越品質好,但會產生較大嘅檔案同影響app嘅反應速度。設定低嘅數值有機會影響機器學習嘅品質。", "image_preview_title": "預覽設定", "image_progressive": "逐步", "image_progressive_description": "對 JPEG 圖片採用漸進式編碼,以實現漸進式載入顯示。呢個選項唔會影響 WebP 圖片。", @@ -114,15 +115,15 @@ "image_thumbnail_title": "縮圖設定", "import_config_from_json_description": "透過上傳 JSON 設定嚟導入系統設定", "job_concurrency": "{job} 並行數", - "job_created": "已建立任務", + "job_created": "建立咗任務", "job_not_concurrency_safe": "呢個任務唔支援並行執行。", "job_settings": "任務設定", "job_settings_description": "管理任務並行數", "jobs_delayed": "{jobCount, plural, other {# 個任務推遲}}", "jobs_failed": "{jobCount, plural, other {# 個任務失敗}}", "jobs_over_time": "任務數量趨勢", - "library_created": "已建立媒體庫:{library}", - "library_deleted": "媒體庫已刪除", + "library_created": "建立咗媒體庫:{library}", + "library_deleted": "媒體庫刪除咗", "library_details": "媒體庫詳細資訊", "library_folder_description": "指定要導入嘅文件夾。系統將會掃描呢個文件夾(包含子文件夾)中所有嘅相同埋影片。", "library_remove_exclusion_pattern_prompt": "係唔係確定要移除呢個排除模式?", @@ -133,7 +134,7 @@ "library_settings": "外部媒體庫", "library_settings_description": "管理外部媒體庫設定", "library_tasks_description": "掃描外部媒體庫以搵出新增同埋變更嘅文件", - "library_updated": "已更新媒體庫", + "library_updated": "更新咗媒體庫", "library_watching_enable_description": "監視外部媒體庫嘅檔案變化", "library_watching_settings": "媒體庫監控 [實驗性]", "library_watching_settings_description": "自動監控檔案嘅變化", @@ -166,6 +167,21 @@ "machine_learning_max_recognition_distance": "最大識別距離", "machine_learning_max_recognition_distance_description": "判斷兩個面孔是否屬於同一人嘅最大距離,範圍由 0 到 2。降低呢個數值可以避免將兩個人誤判為同一人,而提高此數值可以避免將同一個人誤判為兩個人。請注意,合併兩個人比將一個人拆分成兩個人更容易,因此建議盡可能選擇較低嘅數值。", "machine_learning_min_detection_score": "最低偵測分數", + "machine_learning_min_detection_score_description": "臉孔偵測最低信心嘅分數,範圍係 0 到 1。低啲嘅數值會偵測到多啲面孔,但可能會唔啱。", + "machine_learning_min_recognized_faces": "最低嘅面孔辨識數量", + "machine_learning_min_recognized_faces_description": "建立新人物需要嘅最低已辨識面孔數量。提高呢個數值會令面孔辨識更精確,但同時會大啲機會指派唔到面孔俾任何人物。", + "machine_learning_ocr": "文字辨識(OCR)", + "machine_learning_ocr_description": "用機械學習辨識相裏面嘅文字", + "machine_learning_ocr_enabled": "用文字識別(OCR)", + "machine_learning_ocr_enabled_description": "如果唔用,相唔會進行文字辨識。", + "machine_learning_ocr_max_resolution": "最大解析度", + "machine_learning_ocr_max_resolution_description": "解析度高過此值嘅預覽相片會喺保持長寬比例嘅情況下調整大細。數值越高越準確,但係處理時間會更長,同埋會用更多記憶體。", + "machine_learning_ocr_min_detection_score": "最低檢測分數", + "machine_learning_ocr_min_detection_score_description": "文字偵測嘅最低信心分數,範圍係 0 至 1。較低嘅數值會偵測到多啲文字,但可能會唔啱。", + "machine_learning_ocr_min_recognition_score": "最低辨識分數", + "machine_learning_ocr_min_score_recognition_description": "已偵測到文字偵測嘅最低信心分數,範圍係 0 至 1。較低嘅數值會偵測到多啲字,但可能會唔啱。", + "machine_learning_ocr_model": "OCR 模型", + "machine_learning_ocr_model_description": "伺服器嘅模型比行動裝置嘅模型準確啲,但係處理時間長啲,同埋會用多啲記憶體。", "machine_learning_settings": "機器學習設定", "machine_learning_settings_description": "管理機器學習嘅功能同埋設定", "machine_learning_smart_search": "智能搜尋", @@ -173,13 +189,29 @@ "machine_learning_smart_search_enabled": "啟用智慧搜尋", "machine_learning_smart_search_enabled_description": "如果停用,相片唔會進行智能搜尋編碼。", "machine_learning_url_description": "機器學習伺服器嘅 URL。如果你提供多個 URL,系統會逐一嘗試,直到有一個成功回應為止(由前到後)。未回應嘅伺服器將被暫時忽略,直到佢重新上線為止。", + "maintenance_backup_management": "管理備份", "maintenance_delete_backup": "刪除備份", "maintenance_delete_backup_description": "此檔案將被永久刪除。", "maintenance_delete_error": "刪除備份失敗。", + "maintenance_integrity_check": "檢查", + "maintenance_integrity_check_all": "全部檢查", + "maintenance_integrity_checksum_mismatch": "檢查碼唔對", + "maintenance_integrity_checksum_mismatch_description": "檔案嘅總和檢查碼同資料庫嘅唔對。", + "maintenance_integrity_checksum_mismatch_job": "檢查有冇檢查碼唔對", + "maintenance_integrity_checksum_mismatch_refresh_job": "刷新檢查碼唔對報告", + "maintenance_integrity_missing_file": "搵唔到檔案", + "maintenance_integrity_missing_file_description": "喺資料庫追蹤緊,但喺檔案系統唔見嘅檔案。", + "maintenance_integrity_missing_file_job": "檢查唔見嘅檔案", + "maintenance_integrity_missing_file_refresh_job": "刷新唔見檔案報告", + "maintenance_integrity_report": "完整性報告", + "maintenance_integrity_untracked_file": "未追蹤嘅檔案", + "maintenance_integrity_untracked_file_description": "喺 Immich 目錄裏面,但冇任何紀錄嘅檔案。", + "maintenance_integrity_untracked_file_job": "檢查未追蹤嘅檔案", + "maintenance_integrity_untracked_file_refresh_job": "刷新未追蹤檔案報告", "maintenance_restore_backup": "還原備份", "maintenance_restore_backup_description": "Immich 的資料將會被清除,並還原你揀嘅備份。喺繼續操作前,系統會先建立目前嘅資料備份。", "maintenance_restore_backup_different_version": "呢個備份係由不同版本嘅 Immich 所建立!", - "maintenance_restore_backup_unknown_version": "無法確定備份版本。", + "maintenance_restore_backup_unknown_version": "確定唔到備份版本。", "maintenance_restore_database_backup": "還原資料庫備份", "maintenance_restore_database_backup_description": "使用備份文件將數據庫還原到較早嘅狀態", "maintenance_settings": "維修", @@ -199,6 +231,7 @@ "map_light_style": "淺色風格", "map_manage_reverse_geocoding_settings": "管理 逆向地理編碼 嘅設定", "map_reverse_geocoding": "反向地理編碼", + "map_reverse_geocoding_enable_description": "用反向地理編碼", "map_reverse_geocoding_settings": "反向地理編碼設定", "map_settings": "地圖", "map_settings_description": "管理地圖設定", @@ -206,14 +239,67 @@ "memory_cleanup_job": "回憶清理", "memory_generate_job": "產生回憶", "metadata_extraction_job": "抽取元數據", - "metadata_extraction_job_description": "喺每個項目中抽取元數據資訊,例如 GPS、臉孔同埋解析度" + "metadata_extraction_job_description": "喺每個項目中抽取元數據資訊,例如 GPS、臉孔同埋解析度", + "metadata_faces_import_setting": "啟用面孔匯入", + "metadata_faces_import_setting_description": "由相片 EXIF 資料同附屬檔案匯入面孔", + "metadata_settings": "詮釋資料設定", + "metadata_settings_description": "管理詮釋資料設定", + "migration_job": "遷移", + "migration_job_description": "將項目同臉孔預覽縮圖遷移到最新嘅資料夾結構", + "nightly_tasks_cluster_faces_setting_description": "辨識新偵測到嘅面孔", + "nightly_tasks_cluster_new_faces_setting": "分群新面孔", + "nightly_tasks_database_cleanup_setting": "資料庫清理任務", + "nightly_tasks_database_cleanup_setting_description": "清除資料庫舊同過咗期嘅資料", + "nightly_tasks_generate_memories_setting": "產生回憶", + "nightly_tasks_generate_memories_setting_description": "由項目建立新回憶", + "nightly_tasks_missing_thumbnails_setting": "產生唔見嘅預覽縮圖", + "nightly_tasks_missing_thumbnails_setting_description": "將唔見嘅預覽縮圖加入到產生排程", + "nightly_tasks_settings": "夜間任務設定", + "nightly_tasks_settings_description": "管理夜間任務", + "nightly_tasks_start_time_setting": "開始時間", + "nightly_tasks_start_time_setting_description": "伺服器開始執行夜間任務嘅時間", + "nightly_tasks_sync_quota_usage_setting": "同步限額使用情況", + "nightly_tasks_sync_quota_usage_setting_description": "根據目前嘅使用量更新使用者嘅儲存限額", + "no_paths_added": "冇新增咗嘅路徑", + "queue_details": "隊列資訊", + "queues": "任務隊列", + "queues_page_description": "管理員任務隊列頁面", + "quota_size_gib": "配額大細(GiB)", + "refreshing_all_libraries": "重新整理緊所有媒體庫", + "registration": "管理者註冊", + "registration_description": "由於您係系統上第一個使用者,您會被指派為系統管理員,並負責管理相關事務,之後其餘嘅使用者都由您建立。", + "release_channel_release_candidate": "候選發布版", + "release_channel_stable": "稳定版", + "remove_failed_jobs": "移除失敗任務", + "require_password_change_on_login": "要求使用者喺第一次登入時改密碼", + "reset_settings_to_default": "將設定重設到預設值", + "reset_settings_to_recent_saved": "將設定重設到最近儲存嘅設定", + "scanning_library": "掃描緊媒體庫", + "search_jobs": "搵緊任務…", + "send_welcome_email": "傳送歡迎電郵", + "server_external_domain_settings": "外部網域", + "server_external_domain_settings_description": "外部超連結的網域", + "server_public_users": "公開使用者", + "server_public_users_description": "將使用者加到共享相簿時,會列出所有使用者(姓名同電郵)。如果唔用,淨係管理員先可以睇到使用者清單。", + "server_settings": "伺服器設定", + "server_settings_description": "管理伺服器設定", + "server_stats_page_description": "管理伺服器統計頁面", + "server_welcome_message": "歡迎訊息", + "server_welcome_message_description": "喺登入頁面顯示嘅訊息。", + "settings_page_description": "管理設定頁面", + "sidecar_job": "附屬檔案詮釋資料", + "sidecar_job_description": "由檔案系統偵測或者同步附屬檔案詮釋資料", + "slideshow_duration_description": "每張相展示嘅秒數", + "smart_search_job_description": "對項目做機械學習,之後可以用智慧搜尋", + "storage_template_date_time_description": "檔案的建立時間會用喺日期同時間資訊", + "storage_template_date_time_sample": "抽樣時間 {date}" }, "main_menu": "主選單", "maintenance_action_restore": "還原緊數據庫", "onboarding_user_welcome_description": "我哋而家開始喇!", "onboarding_welcome_user": "歡迎,{user}", "online": "已上線", - "only_favorites": "只顯示最愛", + "only_favorites": "淨係顯示最愛", "open": "開", "open_in_map_view": "用地圖開", "open_in_openstreetmap": "用 OpenStreetMap 開", @@ -231,10 +317,10 @@ "wrong_pin_code": "PIN 碼唔啱", "year": "年", "years_ago": "{years, plural, one {#年} other {#年}}前", - "yes": "是", - "you_dont_have_any_shared_links": "你無共享連結", - "your_wifi_name": "你嘅 Wi-Fi 名稱", - "zero_to_clear_rating": "按0以清除資源評級", + "yes": "係", + "you_dont_have_any_shared_links": "您冇任何嘅共享連結", + "your_wifi_name": "您嘅 Wi-Fi 名稱", + "zero_to_clear_rating": "撳 0 清除資源嘅評級", "zoom_image": "縮放相片", - "zoom_to_bounds": "縮放至邊界" + "zoom_to_bounds": "縮放到邊界" } diff --git a/i18n/zh_Hans.json b/i18n/zh_Hans.json index 4161df5ce4..a2e5ce1431 100644 --- a/i18n/zh_Hans.json +++ b/i18n/zh_Hans.json @@ -79,6 +79,7 @@ "cron_expression_description": "使用Cron格式设置扫描间隔。更多信息请参考 Crontab Guru 等网站", "cron_expression_presets": "Cron表达式预设", "disable_login": "禁用登录", + "download_csv": "下载CSV文件", "duplicate_detection_job_description": "运行机器学习来检测相似图像,此功能依赖于智能搜索", "exclusion_pattern_description": "排除规则允许您在扫描资源库时忽略特定的文件和文件夹。如果您有某些包含不希望导入的文件(例如 RAW 格式文件)的文件夹,此功能将非常有用。", "export_config_as_json_description": "将当前系统配置下载为 JSON 文件", @@ -188,9 +189,25 @@ "machine_learning_smart_search_enabled": "启用智能搜索", "machine_learning_smart_search_enabled_description": "若禁用,图片将不会被编码以用于智能搜索。", "machine_learning_url_description": "机器学习服务器的 URL。若提供多个 URL,系统将按从前往后的顺序逐个尝试连接,直至有服务器成功响应为止。未能响应的服务器将被暂时忽略,直至其恢复在线。", + "maintenance_backup_management": "备份管理", "maintenance_delete_backup": "删除备份", "maintenance_delete_backup_description": "此文件将被永久删除。", "maintenance_delete_error": "删除备份失败。", + "maintenance_integrity_check": "检查", + "maintenance_integrity_check_all": "检查全部", + "maintenance_integrity_checksum_mismatch": "校验和不匹配", + "maintenance_integrity_checksum_mismatch_description": "文件的校验与数据库的不匹配。", + "maintenance_integrity_checksum_mismatch_job": "校验和不匹配检查", + "maintenance_integrity_checksum_mismatch_refresh_job": "刷新校验和不匹配报告", + "maintenance_integrity_missing_file": "缺失文件", + "maintenance_integrity_missing_file_description": "已在数据库中追踪,但档案系统中并不存在的文件。", + "maintenance_integrity_missing_file_job": "检查缺失文件", + "maintenance_integrity_missing_file_refresh_job": "刷新缺失文件报告", + "maintenance_integrity_report": "完整性报告", + "maintenance_integrity_untracked_file": "未跟踪文件", + "maintenance_integrity_untracked_file_description": "在 Immich 的目录中,但没有任何纪录的文件。", + "maintenance_integrity_untracked_file_job": "检查未跟踪文件", + "maintenance_integrity_untracked_file_refresh_job": "刷新未跟踪文件报告", "maintenance_restore_backup": "恢复备份", "maintenance_restore_backup_description": "Immich数据将被清除,并从选定的备份中恢复。在继续之前,将先创建一个当前数据的备份。", "maintenance_restore_backup_different_version": "此备份是由不同版本的 Immich 创建的!", @@ -915,6 +932,8 @@ "deduplicate_all": "删除所有重复项", "default_locale": "默认语言", "default_locale_description": "根据您的浏览器区域格式化日期和数字", + "default_quality_subtitle": "点击分享时使用的画质。长按分享按钮可每次手动选择。", + "default_share_quality": "默认分享画质", "delete": "删除", "delete_action_confirmation_message": "您确定要删除此素材吗?此操作会将该素材移至服务器的回收站,并提示您是否将其在本地设备上删除", "delete_action_prompt": "已删除 {count} 项", @@ -1224,6 +1243,7 @@ "failed": "失败", "failed_count": "失败: {count}次", "failed_to_authenticate": "身份验证失败", + "failed_to_delete_file": "文件删除失败", "failed_to_load_assets": "照片/视频加载失败", "failed_to_load_folder": "文件夹加载失败", "favorite": "收藏", @@ -1354,6 +1374,7 @@ "individual_share": "单独分享", "individual_shares": "单独分享", "info": "信息", + "integrity_checks": "完整性检查", "interval": { "day_at_onepm": "每天下午 1 点", "hours": "每隔 {hours, plural, one {小时} other {{hours, number} 小时}}", @@ -1426,6 +1447,7 @@ "linked_oauth_account": "已绑定的 OAuth 账户", "list": "列表", "live": "在线", + "load_more": "加载更多", "loading": "加载中", "loading_search_results_failed": "加载搜索结果失败", "local": "本地", @@ -2084,6 +2106,7 @@ "select_person": "选择人物", "select_person_to_tag": "选择要标记的人物", "select_photos": "选择照片", + "select_quality": "选择画质", "select_trash_all": "全部删除", "select_user_for_sharing_page_err_album": "创建相簿失败", "selected": "已选择", @@ -2147,6 +2170,8 @@ "share_assets_selected": "{count}已选择", "share_dialog_preparing": "准备中...", "share_link": "分享链接", + "share_original": "使用原图(大)", + "share_preview": "使用缩略图(小)", "shared": "共享", "shared_album_activities_input_disable": "评论已禁用", "shared_album_activity_remove_content": "是否删除此活动?", @@ -2248,6 +2273,7 @@ "slideshow_repeat_description": "幻灯片结束后循环播放", "slideshow_settings": "放映设置", "smart_album": "智能相册", + "some_assets_already_have_a_location_warning": "部分所选项目已有位置信息", "sort_albums_by": "相簿排序...", "sort_created": "创建日期", "sort_items": "项目数量", @@ -2368,11 +2394,13 @@ "trash_page_title": "回收站 ({count})", "trashed_items_will_be_permanently_deleted_after": "回收站中的项目将在{days, plural, one {#天} other {#天}}后被永久删除。", "trigger": "触发条件", + "trigger_asset_metadata_extraction": "资源元数据提取", + "trigger_asset_metadata_extraction_description": "当资源的EXIF元数据被提取时触发", "trigger_asset_uploaded": "资产上传", "trigger_asset_uploaded_description": "当上传新项目时触发", "trigger_description": "启动工作流的事件", "trigger_person_recognized": "人物已识别", - "trigger_person_recognized_description": "当检测到人物时触发", + "trigger_person_recognized_description": "当识别到人物时触发", "trigger_type": "触发类型", "troubleshoot": "故障排除", "type": "类型", diff --git a/i18n/zh_Hant.json b/i18n/zh_Hant.json index be6b21fc0d..039f2e3631 100644 --- a/i18n/zh_Hant.json +++ b/i18n/zh_Hant.json @@ -27,7 +27,8 @@ "add_partner": "新增親友", "add_path": "新增路徑", "add_photos": "加入相片", - "add_tag": "加入標籤", + "add_step": "添加步驟", + "add_tag": "新增標籤", "add_to": "加入至…", "add_to_album": "加入到相簿", "add_to_album_bottom_sheet_added": "已新增至 {album}", @@ -78,6 +79,7 @@ "cron_expression_description": "使用 Cron 格式設定掃描間隔。更多資訊請參閱 Crontab Guru", "cron_expression_presets": "Cron 表達式預設值", "disable_login": "停用登入", + "download_csv": "下載CSV檔案", "duplicate_detection_job_description": "針對資產執行機器學習以偵測相似圖片。需依賴「智慧搜尋」功能", "exclusion_pattern_description": "排除模式可讓您在掃描媒體庫時忽略特定檔案與資料夾。若某些資料夾包含您不想匯入的檔案(例如 RAW 檔),此功能將非常有用。", "export_config_as_json_description": "將目前系統設定下載為 JSON 檔案", @@ -187,9 +189,25 @@ "machine_learning_smart_search_enabled": "啟用智慧搜尋", "machine_learning_smart_search_enabled_description": "若停用,影像將不會進行智慧搜尋編碼。", "machine_learning_url_description": "機器學習伺服器的 URL。若提供多個 URL,系統會依序逐一嘗試,直到其中一臺成功回應為止(由前到後)。未回應的伺服器將被暫時忽略,直到其重新上線。", + "maintenance_backup_management": "管理備份", "maintenance_delete_backup": "刪除備份", "maintenance_delete_backup_description": "此檔案將被永久刪除且無法復原。", "maintenance_delete_error": "刪除備份失敗。", + "maintenance_integrity_check": "檢查", + "maintenance_integrity_check_all": "全部檢查", + "maintenance_integrity_checksum_mismatch": "檢查碼不符", + "maintenance_integrity_checksum_mismatch_description": "檔案的總和檢查碼與資料庫的不符。", + "maintenance_integrity_checksum_mismatch_job": "檢查有否檢查碼不符", + "maintenance_integrity_checksum_mismatch_refresh_job": "刷新檢查碼不符報告", + "maintenance_integrity_missing_file": "缺失檔案", + "maintenance_integrity_missing_file_description": "已在資料庫中追蹤,但檔案系統中並不存在的檔案。", + "maintenance_integrity_missing_file_job": "檢查缺失檔案", + "maintenance_integrity_missing_file_refresh_job": "刷新缺失檔案報告", + "maintenance_integrity_report": "完整性報告", + "maintenance_integrity_untracked_file": "未追蹤檔案", + "maintenance_integrity_untracked_file_description": "在 Immich 的目錄中,但沒有任何紀錄的檔案。", + "maintenance_integrity_untracked_file_job": "檢查未追蹤檔案", + "maintenance_integrity_untracked_file_refresh_job": "刷新未追蹤檔案報告", "maintenance_restore_backup": "還原備份", "maintenance_restore_backup_description": "Immich 的資料將被清除,並從選取的備份還原。在繼續操作前,系統會先建立目前的資料備份。", "maintenance_restore_backup_different_version": "此備份是由不同版本的 Immich 所建立!", @@ -299,11 +317,13 @@ "person_cleanup_job": "清理人物", "queue_details": "佇列資訊", "queues": "任務佇列", - "queues_page_description": "管理員任務佇列頁面", + "queues_page_description": "管理員任務序列頁面", "quota_size_gib": "配額大小(GiB)", "refreshing_all_libraries": "正在重新整理所有媒體庫", "registration": "管理者註冊", "registration_description": "由於您是系統上的第一位使用者,您將被指派為系統管理員,並負責管理相關事務,後續的其他使用者也將由您建立。", + "release_channel_release_candidate": "候選發布版", + "release_channel_stable": "稳定版", "remove_failed_jobs": "移除失敗任務", "require_password_change_on_login": "要求使用者在首次登入時變更密碼", "reset_settings_to_default": "將設定重設為預設值", @@ -398,6 +418,10 @@ "transcoding_preferred_hardware_device_description": "僅適用於 VAAPI 和 QSV。設定用於硬體轉碼的 dri 節點。", "transcoding_preset_preset": "預設值(-preset)", "transcoding_preset_preset_description": "壓縮速度。較慢的預設值可產生體積較小的檔案,並在指定位元率時提升品質。VP9 會忽略高於「faster」的設定。", + "transcoding_realtime": "即時轉碼 [實驗性功能]", + "transcoding_realtime_description": "允許在影片串流傳輸(播放)的同時即時進行轉碼。此功能支援動態切換畫質,但根據伺服器效能的不同,可能會導致較高的播放延遲或畫面卡頓。", + "transcoding_realtime_enabled": "啟用即時轉碼", + "transcoding_realtime_enabled_description": "如果停用,伺服器將拒絕啟動新的即時轉碼工作階段。", "transcoding_reference_frames": "參考幀", "transcoding_reference_frames_description": "在壓縮特定幀時所參考的幀數量。數值越高可提升壓縮效率,但會降低編碼速度。設為 0 則自動決定此數值。", "transcoding_required_description": "僅限格式不被接受的影片", @@ -441,6 +465,8 @@ "user_settings_description": "管理使用者設定", "user_successfully_removed": "已成功刪除使用者 {email}。", "users_page_description": "管理使用者頁面", + "version_check_channel": "發佈渠道", + "version_check_channel_description": "選擇您想要接收版本更新公告的發布渠道", "version_check_enabled_description": "啟用版本檢查", "version_check_implications": "版本檢查功能仰賴與 {server} 的定期通訊", "version_check_settings": "版本檢查", @@ -561,6 +587,7 @@ "asset_added_to_album": "已新增至相簿", "asset_adding_to_album": "新增到相簿…", "asset_created": "項目已建立", + "asset_day_count": "{date}: {count, plural, one {# 個資源} other {# 個資源}}", "asset_description_updated": "項目說明已更新", "asset_filename_is_offline": "項目 {filename} 已離線", "asset_has_unassigned_faces": "項目有未指派的臉孔", @@ -690,6 +717,7 @@ "backup_settings_subtitle": "管理上傳設定", "backup_upload_details_page_more_details": "點擊查看更多詳細資訊", "backward": "由舊至新", + "battery_optimization_backup_reliability": "停用最佳化電池充電可提高背景備份的可靠性", "biometric_auth_enabled": "生物辨識驗證已啟用", "biometric_locked_out": "生物辨識驗證已被鎖定", "biometric_no_options": "沒有生物辨識選項可用", @@ -697,6 +725,7 @@ "birthdate_saved": "出生日期儲存成功", "birthdate_set_description": "出生日期用於計算此人在相片拍攝時的年齡。", "blurred_background": "背景模糊", + "browse_templates": "瀏覽範本", "bugs_and_feature_requests": "錯誤及功能請求", "build": "建置編號", "build_image": "建置映像", @@ -730,6 +759,7 @@ "cannot_update_the_description": "無法更新描述", "cast": "投放", "cast_description": "設定可用的投放裝置", + "change": "更改", "change_date": "變更日期", "change_description": "變更描述", "change_display_order": "變更顯示順序", @@ -758,6 +788,7 @@ "check_corrupt_asset_backup_description": "僅在已連線至 Wi-Fi 且所有項目已完成備份後執行此檢查。此程式可能需要數分鐘。", "check_logs": "檢查紀錄", "checksum": "校驗碼", + "choose": "選擇", "choose_matching_people_to_merge": "選擇要合併的相符人物", "city": "城市", "cleanup_confirm_description": "Immich 發現有 {count} 個項目(建立於 {date} 之前)已安全備份至伺服器。是否要從此裝置中刪除本機副本?", @@ -775,6 +806,7 @@ "clear": "清空", "clear_all": "全部清除", "clear_all_recent_searches": "清除所有最近的搜尋", + "clear_failed_count": "清除失敗 ({count})", "clear_file_cache": "清除檔案快取", "clear_message": "清除訊息", "clear_value": "清除值", @@ -806,6 +838,7 @@ "comments_are_disabled": "留言已停用", "common_create_new_album": "建立新相簿", "completed": "已完成", + "configuration": "設定", "confirm": "確認", "confirm_admin_password": "確認管理員密碼", "confirm_delete_face": "您確定要從該項目中刪除 {name} 的臉孔嗎?", @@ -820,6 +853,7 @@ "contain": "等比內縮", "context": "脈絡", "continue": "繼續", + "control_bottom_app_bar_add_tags": "新增標籤", "control_bottom_app_bar_create_new_album": "建立新相簿", "control_bottom_app_bar_delete_from_immich": "從 Immich 伺服器中刪除", "control_bottom_app_bar_delete_from_local": "從裝置中刪除", @@ -833,6 +867,7 @@ "copy_error": "複製錯誤", "copy_file_path": "複製檔案路徑", "copy_image": "複製圖片", + "copy_json": "複製 JSON", "copy_link": "複製連結", "copy_link_to_clipboard": "複製連結到剪貼簿", "copy_password": "複製密碼", @@ -891,11 +926,14 @@ "date_of_birth": "出生日期", "date_of_birth_saved": "出生日期儲存成功", "date_range": "日期範圍", + "date_time_original": "原始日期/時間", "day": "日", "days": "日", "deduplicate_all": "刪除所有重複項目", "default_locale": "預設語言", "default_locale_description": "使用你的瀏覽器區域以格式日期和數字", + "default_quality_subtitle": "點擊分享時使用的畫質。長按分享按鈕可每次手動選擇。", + "default_share_quality": "預設分享畫質", "delete": "刪除", "delete_action_confirmation_message": "您確定要刪除此項目嗎?此動作會將該項目移至伺服器的垃圾桶,並詢問您是否要在本機同步刪除", "delete_action_prompt": "{count} 個已刪除", @@ -969,7 +1007,10 @@ "downloading_asset_filename": "正在下載項目 {filename}", "downloading_from_icloud": "正從 iCloud 下載", "downloading_media": "正在下載媒體", + "drag_to_reorder": "拖曳以重新排序", "drop_files_to_upload": "將檔案拖放到任何位置以上傳", + "duplicate": "複製", + "duplicate_workflow": "複製工作流程", "duplicates": "重複項目", "duplicates_description": "逐一檢查每個群組,並標示其中是否有重複項目。", "duration": "顯示時長", @@ -1071,6 +1112,7 @@ "failed_to_remove_product_key": "移除產品金鑰失敗", "failed_to_reset_pin_code": "重設 PIN 碼失敗", "failed_to_stack_assets": "項目堆疊失敗", + "failed_to_tag_assets": "標記資源失敗", "failed_to_unstack_assets": "解除項目堆疊失敗", "failed_to_update_notification_status": "無法更新通知狀態", "incorrect_email_or_password": "電子郵件或密碼錯誤", @@ -1190,15 +1232,18 @@ "export_as_json": "匯出為 JSON", "export_database": "匯出資料庫", "export_database_description": "匯出 SQLite 資料庫", + "exposure_time": "曝光時間", "extension": "副檔名", "external": "外部", "external_libraries": "外部媒體庫", "external_network": "外部網路", "external_network_sheet_info": "若未連網至偏好的 Wi-Fi,將依清單從上到下選擇可連線的伺服器網址", + "f_number": "光圈值", "face_unassigned": "未指派", "failed": "失敗", "failed_count": "失敗:{count}", "failed_to_authenticate": "身份驗證失敗", + "failed_to_delete_file": "無法刪除檔案", "failed_to_load_assets": "項目載入失敗", "failed_to_load_folder": "無法載入資料夾", "favorite": "收藏", @@ -1224,6 +1269,7 @@ "find_them_fast": "透過搜尋姓名快速找到他們", "first": "第一個", "fix_incorrect_match": "修復不相符的", + "focal_length": "焦距", "folder": "資料夾", "folder_not_found": "找不到資料夾", "folders": "資料夾", @@ -1328,6 +1374,7 @@ "individual_share": "個別分享", "individual_shares": "個別分享", "info": "資訊", + "integrity_checks": "完整性檢查", "interval": { "day_at_onepm": "每天下午 1 點", "hours": "每 {hours, plural, one {小時} other {{hours, number} 小時}}", @@ -1344,6 +1391,7 @@ "ios_debug_info_no_sync_yet": "尚未執行任何背景同步任務", "ios_debug_info_processes_queued": "{count, plural, one {{count} 個背景程式已排程} other {{count} 個背景程式已排程}}", "ios_debug_info_processing_ran_at": "於 {dateTime} 執行處理", + "iso": "ISO", "items_count": "{count, plural, one {# 個項目} other {# 個項目}}", "jobs": "任務", "json_editor": "JSON 編輯器", @@ -1374,6 +1422,7 @@ "leave": "離開", "leave_album": "離開相簿", "lens_model": "鏡頭型號", + "less": "收起", "let_others_respond": "允許他人回覆", "level": "等級", "library": "媒體庫", @@ -1397,7 +1446,8 @@ "link_to_oauth": "連結 OAuth", "linked_oauth_account": "已連結 OAuth 帳號", "list": "清單", - "live": "Live", + "live": "線上", + "load_more": "載入更多", "loading": "載入中", "loading_search_results_failed": "載入搜尋結果失敗", "local": "本機", @@ -1567,6 +1617,8 @@ "merge_people_prompt": "您要合併這些人物嗎?此操作無法撤銷。", "merge_people_successfully": "成功合併人物", "merged_people_count": "已合併 {count, plural, other {# 位人物}}", + "minFaces": "最少人臉數", + "minFaces_description": "顯示該人物所需的最少已識別人臉數量", "minimize": "最小化", "minute": "分", "minutes": "分鐘", @@ -1576,9 +1628,10 @@ "mobile_app": "行動應用程式", "mobile_app_download_onboarding_note": "請使用以下選項下載隨附的行動應用程式", "model": "型號", + "modify_date": "修改日期", "month": "月", "more": "更多", - "motion": "Motion", + "motion": "動作", "move": "移動", "move_down": "向下移動", "move_off_locked_folder": "移出「已上鎖的資料夾」", @@ -1652,6 +1705,7 @@ "no_results": "沒有結果", "no_results_description": "試試同義詞或更通用的關鍵字吧", "no_shared_albums_message": "建立共享相簿以分享相片與影片", + "no_steps": "未添加任何步驟", "no_uploads_in_progress": "沒有正在上傳的項目", "none": "無", "not_allowed": "不允許", @@ -1660,6 +1714,7 @@ "not_selected": "未選取", "notes": "提示", "nothing_here_yet": "暫無訊息", + "notification_backup_reliability": "啟用通知可提高背景備份的可靠性", "notification_permission_dialog_content": "開啟通知,請前往「設定」,並選擇「允許」。", "notification_permission_list_tile_content": "開啟通知權限。", "notification_permission_list_tile_enable_button": "開啟通知", @@ -1697,6 +1752,7 @@ "organize_into_albums": "整理成相簿", "organize_into_albums_description": "使用目前同步設定將現有相片放入相簿", "organize_your_library": "整理您的相簿", + "orientation": "方向", "original": "原圖", "other": "其他", "other_devices": "其他裝置", @@ -1788,6 +1844,8 @@ "play_original_video_setting_description": "優先播放原始影片而非轉碼後的影片。若原始項目不相容,可能無法正常播放。", "play_transcoded_video": "播放轉碼影片", "please_auth_to_access": "請進行身份驗證才能存取", + "plugin_method_filter_type": "篩選", + "plugin_method_filter_type_description": "此方法可篩選事件,並有條件地阻止後續步驟執行", "port": "連接埠", "preferences_settings_subtitle": "管理應用程式偏好設定", "preferences_settings_title": "偏好設定", @@ -1809,6 +1867,7 @@ "profile_drawer_readonly_mode": "唯讀模式已啟用。長按使用者個人圖示即可關閉。", "profile_image_of_user": "{user} 的個人資料圖片", "profile_picture_set": "已設定個人資料圖片。", + "projection_type": "投影類型", "public_album": "公開相簿", "public_share": "公開分享", "purchase_account_info": "支持者", @@ -2047,6 +2106,7 @@ "select_person": "選取人物", "select_person_to_tag": "選擇要標記的人物", "select_photos": "選相片", + "select_quality": "選擇畫質", "select_trash_all": "全部刪除", "select_user_for_sharing_page_err_album": "建立相簿失敗", "selected": "已選取", @@ -2110,6 +2170,8 @@ "share_assets_selected": "已選取 {count} 項", "share_dialog_preparing": "正在準備...", "share_link": "分享連結", + "share_original": "使用原圖 (大)", + "share_preview": "使用縮圖(小)", "shared": "共享", "shared_album_activities_input_disable": "留言功能已停用", "shared_album_activity_remove_content": "您確定要刪除此活動嗎?", @@ -2178,7 +2240,9 @@ "show_in_timeline": "在時間軸中顯示", "show_in_timeline_setting_description": "在您的時間軸中顯示這位使用者的相片和影片", "show_keyboard_shortcuts": "顯示鍵盤快捷鍵", + "show_less": "收起", "show_metadata": "顯示詮釋資料", + "show_more_fields": "{count, plural, one {顯示 # 個更多字段} other {顯示 # 個更多字段}}", "show_or_hide_info": "顯示或隱藏資訊", "show_password": "顯示密碼", "show_person_options": "顯示人物選項", @@ -2208,6 +2272,8 @@ "slideshow_repeat": "重複投影片", "slideshow_repeat_description": "循環播放", "slideshow_settings": "幻燈片設定", + "smart_album": "智能相簿", + "some_assets_already_have_a_location_warning": "部分所選項目已有位置資訊", "sort_albums_by": "相簿排序依據...", "sort_created": "建立日期", "sort_items": "項目數量", @@ -2230,6 +2296,11 @@ "start_date_before_end_date": "開始日期必須早於結束日期", "state": "地區", "status": "狀態", + "step_delete": "刪除步驟", + "step_delete_confirm": "確定要刪除此步驟嗎?", + "step_details": "步驟詳情", + "steps": "步驟", + "steps_count": "{count, plural, one {# 個步驟} other {# 個步驟}}", "stop_casting": "停止投放", "stop_motion_photo": "停止動態相片", "stop_photo_sharing": "要停止分享您的相片嗎?", @@ -2323,11 +2394,13 @@ "trash_page_title": "垃圾桶 ({count})", "trashed_items_will_be_permanently_deleted_after": "垃圾桶中的項目會在 {days, plural, other {# 天}}後永久刪除。", "trigger": "觸發", - "trigger_asset_uploaded": "項目已上傳", + "trigger_asset_metadata_extraction": "資源後設資料提取", + "trigger_asset_metadata_extraction_description": "當資源的EXIF後設資料被提取時觸發", + "trigger_asset_uploaded": "上傳項目", "trigger_asset_uploaded_description": "在上傳新項目時觸發", "trigger_description": "觸發工作流程的事件", "trigger_person_recognized": "已辨識人物", - "trigger_person_recognized_description": "偵測到人物時觸發", + "trigger_person_recognized_description": "識別到人物時觸發", "trigger_type": "觸發類型", "troubleshoot": "疑難排解", "type": "類型", @@ -2369,6 +2442,7 @@ "updated_password": "已更新密碼", "upload": "上傳", "upload_concurrency": "上傳並行數", + "upload_day_count": "{date}: {count, plural, one {# 個上傳} other {# 個上傳}}", "upload_details": "上傳詳細資訊", "upload_dialog_info": "是否要將所選項目備份到伺服器?", "upload_dialog_title": "上傳項目", @@ -2384,6 +2458,8 @@ "upload_to_immich": "上傳至 Immich ({count})", "uploading": "上傳中", "uploading_media": "項目上傳中", + "uploads": "上傳", + "uploads_count": "{count, plural, one {# 個上傳} other {# 個上傳}}", "url": "網址", "usage": "用量", "use_biometric": "使用生物辨識", @@ -2391,6 +2467,7 @@ "use_browser_locale_description": "根據你瀏覽器的語言和地區設定來更改日期,時間和數字的格式", "use_current_connection": "使用目前的連線", "use_custom_date_range": "改用自訂日期範圍", + "use_template": "使用範本", "user": "使用者", "user_has_been_deleted": "此使用者已被刪除。", "user_id": "使用者 ID", @@ -2420,6 +2497,7 @@ "video": "影片", "video_hover_setting": "滑鼠懸停時播放影片預覽", "video_hover_setting_description": "當滑鼠停在項目上時播放影片縮圖。即使停用此功能,仍可透過將滑鼠停在播放圖示上來開始播放。", + "video_quality": "影片畫質", "videos": "影片", "videos_count": "{count, plural, other {# 部影片}}", "videos_only": "只允許影片", @@ -2452,8 +2530,10 @@ "week": "週", "welcome": "歡迎", "welcome_to_immich": "歡迎使用 Immich", + "when": "當", "width": "寬度", "wifi_name": "Wi-Fi 名稱", + "workflow": "工作流程", "workflow_delete_prompt": "確定要刪除此工作流程嗎?", "workflow_deleted": "工作流程已刪除", "workflow_description": "工作流程說明", @@ -2463,6 +2543,7 @@ "workflow_name": "工作流程名稱", "workflow_navigation_prompt": "您確定要不儲存變更就離開嗎?", "workflow_summary": "工作流程摘要", + "workflow_templates": "工作流程範本", "workflow_update_success": "已成功更新工作流程", "workflow_updated": "工作流程已更新", "workflows": "工作流程", From c9aa9ba711ea5b97617b66fee6f2a3a52f533ba8 Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 16 Jun 2026 19:50:41 +0000 Subject: [PATCH 23/64] chore: version v3.0.0-rc.1 --- docs/static/archived-versions.json | 4 ++-- e2e/package.json | 2 +- machine-learning/pyproject.toml | 2 +- machine-learning/uv.lock | 2 +- mobile/android/fastlane/Fastfile | 8 ++++---- mobile/openapi/README.md | 2 +- mobile/pubspec.yaml | 2 +- open-api/immich-openapi-specs.json | 2 +- package.json | 2 +- packages/cli/package.json | 2 +- packages/sdk/package.json | 2 +- packages/sdk/src/fetch-client.ts | 2 +- server/package.json | 2 +- web/package.json | 2 +- 14 files changed, 18 insertions(+), 18 deletions(-) diff --git a/docs/static/archived-versions.json b/docs/static/archived-versions.json index b90598974b..a86a09c037 100644 --- a/docs/static/archived-versions.json +++ b/docs/static/archived-versions.json @@ -1,7 +1,7 @@ [ { - "label": "v3.0.0-rc.0", - "url": "https://docs.v3.0.0-rc.0.archive.immich.app" + "label": "v3.0.0-rc.1", + "url": "https://docs.v3.0.0-rc.1.archive.immich.app" }, { "label": "v2.7.5", diff --git a/e2e/package.json b/e2e/package.json index 1a6017e2d9..9d54d08677 100644 --- a/e2e/package.json +++ b/e2e/package.json @@ -1,6 +1,6 @@ { "name": "immich-e2e", - "version": "3.0.0-rc.0", + "version": "3.0.0-rc.1", "description": "", "main": "index.js", "type": "module", diff --git a/machine-learning/pyproject.toml b/machine-learning/pyproject.toml index 7150fcb31e..a3a1caf0b8 100644 --- a/machine-learning/pyproject.toml +++ b/machine-learning/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "immich-ml" -version = "3.0.0rc0" +version = "3.0.0rc1" description = "" authors = [{ name = "Hau Tran", email = "alex.tran1502@gmail.com" }] requires-python = ">=3.11,<4.0" diff --git a/machine-learning/uv.lock b/machine-learning/uv.lock index 88c99f9431..bb0d20f102 100644 --- a/machine-learning/uv.lock +++ b/machine-learning/uv.lock @@ -974,7 +974,7 @@ wheels = [ [[package]] name = "immich-ml" -version = "3.0.0rc0" +version = "3.0.0rc1" source = { editable = "." } dependencies = [ { name = "aiocache" }, diff --git a/mobile/android/fastlane/Fastfile b/mobile/android/fastlane/Fastfile index 412d7ed681..a8cd7c5c47 100644 --- a/mobile/android/fastlane/Fastfile +++ b/mobile/android/fastlane/Fastfile @@ -22,8 +22,8 @@ platform :android do task: 'bundle', build_type: 'Release', properties: { - "android.injected.version.code" => 3048, - "android.injected.version.name" => "3.0.0-rc.0", + "android.injected.version.code" => 3049, + "android.injected.version.name" => "3.0.0-rc.1", } ) upload_to_play_store(skip_upload_apk: true, skip_upload_images: true, skip_upload_screenshots: true, aab: '../build/app/outputs/bundle/release/app-release.aab', track: 'beta') @@ -35,8 +35,8 @@ platform :android do task: 'bundle', build_type: 'Release', properties: { - "android.injected.version.code" => 3048, - "android.injected.version.name" => "3.0.0-rc.0", + "android.injected.version.code" => 3049, + "android.injected.version.name" => "3.0.0-rc.1", } ) upload_to_play_store(skip_upload_apk: true, skip_upload_images: true, skip_upload_screenshots: true, aab: '../build/app/outputs/bundle/release/app-release.aab') diff --git a/mobile/openapi/README.md b/mobile/openapi/README.md index 14fc7f5ecb..c8ac38a9fe 100644 --- a/mobile/openapi/README.md +++ b/mobile/openapi/README.md @@ -3,7 +3,7 @@ Immich API This Dart package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project: -- API version: 3.0.0-rc.0 +- API version: 3.0.0-rc.1 - Generator version: 7.22.0 - Build package: org.openapitools.codegen.languages.DartClientCodegen diff --git a/mobile/pubspec.yaml b/mobile/pubspec.yaml index f4c7191553..2322d0fa39 100644 --- a/mobile/pubspec.yaml +++ b/mobile/pubspec.yaml @@ -2,7 +2,7 @@ name: immich_mobile description: Immich - selfhosted backup media file on mobile phone publish_to: 'none' -version: 3.0.0-rc.0+3048 +version: 3.0.0-rc.1+3049 environment: sdk: '>=3.12.0 <4.0.0' diff --git a/open-api/immich-openapi-specs.json b/open-api/immich-openapi-specs.json index 5e36725451..481f94b3dd 100644 --- a/open-api/immich-openapi-specs.json +++ b/open-api/immich-openapi-specs.json @@ -16197,7 +16197,7 @@ "info": { "title": "Immich", "description": "Immich API", - "version": "3.0.0-rc.0", + "version": "3.0.0-rc.1", "contact": {} }, "tags": [ diff --git a/package.json b/package.json index c33b8e292c..9af979ad2d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "immich-monorepo", - "version": "3.0.0-rc.0", + "version": "3.0.0-rc.1", "description": "Monorepo for Immich", "type": "module", "private": true, diff --git a/packages/cli/package.json b/packages/cli/package.json index 925bdf7e24..67bf68a7d6 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,6 +1,6 @@ { "name": "@immich/cli", - "version": "3.0.0-rc.0", + "version": "3.0.0-rc.1", "description": "Command Line Interface (CLI) for Immich", "repository": { "type": "git", diff --git a/packages/sdk/package.json b/packages/sdk/package.json index ca08805f73..9d9b4d8099 100644 --- a/packages/sdk/package.json +++ b/packages/sdk/package.json @@ -1,6 +1,6 @@ { "name": "@immich/sdk", - "version": "3.0.0-rc.0", + "version": "3.0.0-rc.1", "description": "Auto-generated TypeScript SDK for the Immich API", "repository": { "type": "git", diff --git a/packages/sdk/src/fetch-client.ts b/packages/sdk/src/fetch-client.ts index 1e3fe6add7..b7202c2a1a 100644 --- a/packages/sdk/src/fetch-client.ts +++ b/packages/sdk/src/fetch-client.ts @@ -1,6 +1,6 @@ /** * Immich - * 3.0.0-rc.0 + * 3.0.0-rc.1 * DO NOT MODIFY - This file has been generated using oazapfts. * See https://www.npmjs.com/package/oazapfts */ diff --git a/server/package.json b/server/package.json index 09e1bc1b8b..30eaa22d4f 100644 --- a/server/package.json +++ b/server/package.json @@ -1,6 +1,6 @@ { "name": "immich", - "version": "3.0.0-rc.0", + "version": "3.0.0-rc.1", "description": "", "author": "", "private": true, diff --git a/web/package.json b/web/package.json index 50071c2b72..de74a5d6ed 100644 --- a/web/package.json +++ b/web/package.json @@ -1,6 +1,6 @@ { "name": "immich-web", - "version": "3.0.0-rc.0", + "version": "3.0.0-rc.1", "license": "GNU Affero General Public License version 3", "type": "module", "scripts": { From 8d30cfa2ce6d0d450b748d2e892ac219c63f9c33 Mon Sep 17 00:00:00 2001 From: Savely Krasovsky Date: Wed, 17 Jun 2026 01:09:53 +0200 Subject: [PATCH 24/64] chore(ml): update intel graphics compiler and compute runtime (#29163) chore(ml): update Intel graphics compiler and compute runtime to latest versions --- machine-learning/Dockerfile | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/machine-learning/Dockerfile b/machine-learning/Dockerfile index a1fdfa15d3..283d1f24d4 100644 --- a/machine-learning/Dockerfile +++ b/machine-learning/Dockerfile @@ -48,14 +48,14 @@ FROM python:3.13-slim-trixie@sha256:f82c96458eedc847b233e582eb31336f4954b39cae02 RUN apt-get update && \ apt-get install --no-install-recommends -yqq ocl-icd-libopencl1 wget && \ - wget -nv https://github.com/intel/intel-graphics-compiler/releases/download/v2.34.4/intel-igc-core-2_2.34.4+21428_amd64.deb && \ - wget -nv https://github.com/intel/intel-graphics-compiler/releases/download/v2.34.4/intel-igc-opencl-2_2.34.4+21428_amd64.deb && \ - wget -nv https://github.com/intel/compute-runtime/releases/download/26.18.38308.1/intel-opencl-icd_26.18.38308.1-0_amd64.deb && \ + wget -nv https://github.com/intel/intel-graphics-compiler/releases/download/v2.36.3/intel-igc-core-2_2.36.3+21719_amd64.deb && \ + wget -nv https://github.com/intel/intel-graphics-compiler/releases/download/v2.36.3/intel-igc-opencl-2_2.36.3+21719_amd64.deb && \ + wget -nv https://github.com/intel/compute-runtime/releases/download/26.22.38646.4/intel-opencl-icd_26.22.38646.4-0_amd64.deb && \ wget -nv https://github.com/intel/intel-graphics-compiler/releases/download/igc-1.0.17537.24/intel-igc-core_1.0.17537.24_amd64.deb && \ wget -nv https://github.com/intel/intel-graphics-compiler/releases/download/igc-1.0.17537.24/intel-igc-opencl_1.0.17537.24_amd64.deb && \ wget -nv https://github.com/intel/compute-runtime/releases/download/24.35.30872.36/intel-opencl-icd-legacy1_24.35.30872.36_amd64.deb && \ # TODO: Figure out how to get renovate to manage this differently versioned libigdgmm file - wget -nv https://github.com/intel/compute-runtime/releases/download/26.18.38308.1/libigdgmm12_22.10.0_amd64.deb && \ + wget -nv https://github.com/intel/compute-runtime/releases/download/26.22.38646.4/libigdgmm12_22.10.0_amd64.deb && \ dpkg -i *.deb && \ rm *.deb && \ apt-get remove wget -yqq && \ From fbb0bc6e3968b39875997d9eedc16a0077e4bbe0 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 17 Jun 2026 09:17:25 +0000 Subject: [PATCH 25/64] chore(deps): update ghcr.io/jdx/mise docker tag to v2026.6.10 (#29153) --- server/Dockerfile | 2 +- server/Dockerfile.dev | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/server/Dockerfile b/server/Dockerfile index 058938a42a..1df476dccd 100644 --- a/server/Dockerfile +++ b/server/Dockerfile @@ -56,7 +56,7 @@ FROM builder AS plugins ARG TARGETPLATFORM -COPY --from=ghcr.io/jdx/mise:2026.5.18@sha256:5bb3311994fa78cef307ca3077cdb18f9551da0886371fc26ea91ab56220ffc5 /usr/local/bin/mise /usr/local/bin/mise +COPY --from=ghcr.io/jdx/mise:2026.6.10@sha256:f57ac375a262f52f8ac3f9101348dbff2187d5e4b59612154f2f2808dbe46ef6 /usr/local/bin/mise /usr/local/bin/mise WORKDIR /app COPY ./mise.toml ./mise.toml diff --git a/server/Dockerfile.dev b/server/Dockerfile.dev index 83fdc3eb02..b54e10831c 100644 --- a/server/Dockerfile.dev +++ b/server/Dockerfile.dev @@ -2,7 +2,7 @@ FROM ghcr.io/immich-app/base-server-dev:202606161235@sha256:9f88b07acc8b7bf37a1dd3d5a19193f664443eaaab4e08e9f9341414c5e4b23f AS dev -COPY --from=ghcr.io/jdx/mise:2026.5.18@sha256:5bb3311994fa78cef307ca3077cdb18f9551da0886371fc26ea91ab56220ffc5 /usr/local/bin/mise /usr/local/bin/mise +COPY --from=ghcr.io/jdx/mise:2026.6.10@sha256:f57ac375a262f52f8ac3f9101348dbff2187d5e4b59612154f2f2808dbe46ef6 /usr/local/bin/mise /usr/local/bin/mise RUN echo "devdir=/buildcache/node-gyp" >> /usr/local/etc/npmrc && \ echo "store-dir=/buildcache/pnpm-store" >> /usr/local/etc/npmrc && \ From 430a2bbfd3cc2100b5aeb0ce8fd86f89214f516a Mon Sep 17 00:00:00 2001 From: Mees Frensel <33722705+meesfrensel@users.noreply.github.com> Date: Wed, 17 Jun 2026 12:04:41 +0200 Subject: [PATCH 26/64] chore(server): add switch case exhaustiveness lint (#29029) --- server/eslint.config.mjs | 1 + server/src/commands/schema-check.ts | 6 +++++- server/src/cores/storage.core.ts | 9 ++++++++- .../maintenance/maintenance-worker.service.ts | 9 ++++++--- server/src/repositories/config.repository.ts | 18 ++++++++++-------- server/src/repositories/media.repository.ts | 4 +++- server/src/services/database-backup.service.ts | 3 +++ server/src/services/job.service.ts | 2 ++ server/src/services/library.service.ts | 3 +++ server/src/services/metadata.service.ts | 4 +++- 10 files changed, 44 insertions(+), 15 deletions(-) diff --git a/server/eslint.config.mjs b/server/eslint.config.mjs index bdbac34da6..c86bc3d72f 100644 --- a/server/eslint.config.mjs +++ b/server/eslint.config.mjs @@ -51,6 +51,7 @@ export default typescriptEslint.config([ 'unicorn/no-array-sort': 'off', '@typescript-eslint/await-thenable': 'error', '@typescript-eslint/no-misused-promises': 'error', + '@typescript-eslint/switch-exhaustiveness-check': ['error', { considerDefaultExhaustiveForUnions: true }], 'require-await': 'off', '@typescript-eslint/require-await': 'error', curly: 2, diff --git a/server/src/commands/schema-check.ts b/server/src/commands/schema-check.ts index e0ccae8469..fc38254dde 100644 --- a/server/src/commands/schema-check.ts +++ b/server/src/commands/schema-check.ts @@ -28,9 +28,13 @@ export class SchemaCheck extends CommandRunner { } case 'missing': { - console.log(` - ${migration.name} exists, but has not been applied to the database`); + console.log(` - ${migration.name} exists on disk, but has not been applied to the database`); break; } + + case 'applied': { + break; // happy path, do nothing + } } } } diff --git a/server/src/cores/storage.core.ts b/server/src/cores/storage.core.ts index 8802145020..6c7d6f0e3e 100644 --- a/server/src/cores/storage.core.ts +++ b/server/src/cores/storage.core.ts @@ -9,6 +9,7 @@ import { PersonPathType, RawExtractedFormat, StorageFolder, + UserPathType, } from 'src/enum'; import { AssetRepository } from 'src/repositories/asset.repository'; import { ConfigRepository } from 'src/repositories/config.repository'; @@ -327,13 +328,19 @@ export class StorageCore { case AssetFileType.EncodedVideo: case AssetFileType.Thumbnail: case AssetFileType.Preview: - case AssetFileType.Sidecar: { + case AssetFileType.Sidecar: + case AssetPathType.EncodedVideo: { return this.assetRepository.upsertFile({ assetId: id, type: pathType as AssetFileType, path: newPath }); } case PersonPathType.Face: { return this.personRepository.update({ id, thumbnailPath: newPath }); } + + case UserPathType.Profile: { + this.logger.warn('Unexpected path type:', pathType); + return; + } } } diff --git a/server/src/maintenance/maintenance-worker.service.ts b/server/src/maintenance/maintenance-worker.service.ts index 61958a0d8a..f2c9086e87 100644 --- a/server/src/maintenance/maintenance-worker.service.ts +++ b/server/src/maintenance/maintenance-worker.service.ts @@ -281,17 +281,20 @@ export class MaintenanceWorkerService { async runAction(action: SetMaintenanceModeDto) { switch (action.action) { - case MaintenanceAction.Start: { + case MaintenanceAction.Start: + case MaintenanceAction.SelectDatabaseRestore: { return; } case MaintenanceAction.End: { return this.endMaintenance(); } - case MaintenanceAction.SelectDatabaseRestore: { - return; + case MaintenanceAction.RestoreDatabase: { + return this.runRestoreDatabase(action); } } + } + async runRestoreDatabase(action: SetMaintenanceModeDto) { const lock = await this.databaseRepository.tryLock(DatabaseLock.MaintenanceOperation); if (!lock) { return; diff --git a/server/src/repositories/config.repository.ts b/server/src/repositories/config.repository.ts index f88deca09d..909d6d62dd 100644 --- a/server/src/repositories/config.repository.ts +++ b/server/src/repositories/config.repository.ts @@ -243,14 +243,16 @@ const getEnv = (): EnvData => { }; let vectorExtension: VectorExtension | undefined; - switch (dto.DB_VECTOR_EXTENSION) { - case 'pgvector': { - vectorExtension = DatabaseExtension.Vector; - break; - } - case 'vectorchord': { - vectorExtension = DatabaseExtension.VectorChord; - break; + if (dto.DB_VECTOR_EXTENSION) { + switch (dto.DB_VECTOR_EXTENSION) { + case 'pgvector': { + vectorExtension = DatabaseExtension.Vector; + break; + } + case 'vectorchord': { + vectorExtension = DatabaseExtension.VectorChord; + break; + } } } diff --git a/server/src/repositories/media.repository.ts b/server/src/repositories/media.repository.ts index c2ec95636a..5f8449e692 100644 --- a/server/src/repositories/media.repository.ts +++ b/server/src/repositories/media.repository.ts @@ -478,8 +478,10 @@ export class MediaRepository { case 'av1': { return this.parseEnum(Av1Profile, profile); } + default: { + return null; + } } - return null; } private compareStreams(a: FfprobeStream, b: FfprobeStream): number { diff --git a/server/src/services/database-backup.service.ts b/server/src/services/database-backup.service.ts index 6afc46c7da..55d69d37b7 100644 --- a/server/src/services/database-backup.service.ts +++ b/server/src/services/database-backup.service.ts @@ -163,6 +163,9 @@ export class DatabaseBackupService { ); switch (bin) { + case 'pg_dump': { + break; + } case 'pg_dumpall': { args.push('--database'); break; diff --git a/server/src/services/job.service.ts b/server/src/services/job.service.ts index 00105103e8..6d4f04df37 100644 --- a/server/src/services/job.service.ts +++ b/server/src/services/job.service.ts @@ -257,6 +257,8 @@ export class JobService extends BaseService { } break; } + + // no default } } } diff --git a/server/src/services/library.service.ts b/server/src/services/library.service.ts index 085650be6f..7e84a8ec52 100644 --- a/server/src/services/library.service.ts +++ b/server/src/services/library.service.ts @@ -498,6 +498,9 @@ export class LibraryService extends BaseService { const stat = stats[i]; const action = this.checkExistingAsset(asset, stat); switch (action) { + case AssetSyncResult.DO_NOTHING: { + break; + } case AssetSyncResult.OFFLINE: { if (asset.status === AssetStatus.Trashed) { trashedAssetIdsToOffline.push(asset.id); diff --git a/server/src/services/metadata.service.ts b/server/src/services/metadata.service.ts index dfa254b78a..a4639db262 100644 --- a/server/src/services/metadata.service.ts +++ b/server/src/services/metadata.service.ts @@ -1138,7 +1138,9 @@ export class MetadataService extends BaseService { case 3: { return ExifOrientation.Rotate90CW; } + default: { + return null; + } } - return null; } } From 3f2e51c5d4f489313193a095981bbe18606fb185 Mon Sep 17 00:00:00 2001 From: Timon Date: Wed, 17 Jun 2026 14:50:17 +0200 Subject: [PATCH 27/64] refactor(server): use uuids in schemas (#29140) --- open-api/immich-openapi-specs.json | 182 ++++++++++++++++++++ server/src/dtos/album.dto.ts | 6 +- server/src/dtos/api-key.dto.ts | 2 +- server/src/dtos/asset-ids.response.dto.ts | 4 +- server/src/dtos/asset-media-response.dto.ts | 4 +- server/src/dtos/asset-response.dto.ts | 10 +- server/src/dtos/asset.dto.ts | 2 +- server/src/dtos/auth.dto.ts | 2 +- server/src/dtos/download.dto.ts | 2 +- server/src/dtos/duplicate.dto.ts | 2 +- server/src/dtos/integrity.dto.ts | 2 +- server/src/dtos/library.dto.ts | 4 +- server/src/dtos/map.dto.ts | 2 +- server/src/dtos/memory.dto.ts | 4 +- server/src/dtos/notification.dto.ts | 2 +- server/src/dtos/person.dto.ts | 4 +- server/src/dtos/plugin.dto.ts | 2 +- server/src/dtos/server.dto.ts | 4 +- server/src/dtos/session.dto.ts | 2 +- server/src/dtos/shared-link.dto.ts | 4 +- server/src/dtos/stack.dto.ts | 4 +- server/src/dtos/sync.dto.ts | 100 +++++------ server/src/dtos/tag.dto.ts | 2 +- server/src/dtos/user-profile.dto.ts | 2 +- server/src/dtos/workflow.dto.ts | 2 +- 25 files changed, 269 insertions(+), 87 deletions(-) diff --git a/open-api/immich-openapi-specs.json b/open-api/immich-openapi-specs.json index 481f94b3dd..199dca8d76 100644 --- a/open-api/immich-openapi-specs.json +++ b/open-api/immich-openapi-specs.json @@ -16508,7 +16508,9 @@ }, "albumThumbnailAssetId": { "description": "Thumbnail asset ID", + "format": "uuid", "nullable": true, + "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$", "type": "string" }, "albumUsers": { @@ -16551,6 +16553,8 @@ }, "id": { "description": "Album ID", + "format": "uuid", + "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$", "type": "string" }, "isActivityEnabled": { @@ -16793,6 +16797,8 @@ }, "id": { "description": "API key ID", + "format": "uuid", + "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$", "type": "string" }, "name": { @@ -17001,6 +17007,8 @@ }, "id": { "description": "Asset ID", + "format": "uuid", + "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$", "type": "string" }, "isTrashed": { @@ -17379,6 +17387,8 @@ "properties": { "assetId": { "description": "Asset ID", + "format": "uuid", + "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$", "type": "string" }, "error": { @@ -17494,6 +17504,8 @@ "properties": { "id": { "description": "Asset media ID", + "format": "uuid", + "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$", "type": "string" }, "status": { @@ -17562,6 +17574,8 @@ "properties": { "assetId": { "description": "Asset ID", + "format": "uuid", + "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$", "type": "string" }, "key": { @@ -17809,7 +17823,9 @@ }, "duplicateId": { "description": "Duplicate group ID", + "format": "uuid", "nullable": true, + "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$", "type": "string" }, "duration": { @@ -17845,6 +17861,8 @@ }, "id": { "description": "Asset ID", + "format": "uuid", + "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$", "type": "string" }, "isArchived": { @@ -17923,6 +17941,8 @@ }, "ownerId": { "description": "Owner user ID", + "format": "uuid", + "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$", "type": "string" }, "people": { @@ -18020,10 +18040,14 @@ }, "id": { "description": "Stack ID", + "format": "uuid", + "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$", "type": "string" }, "primaryAssetId": { "description": "Primary asset ID", + "format": "uuid", + "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$", "type": "string" } }, @@ -18159,6 +18183,8 @@ }, "id": { "description": "ID", + "format": "uuid", + "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$", "type": "string" }, "success": { @@ -18337,6 +18363,8 @@ }, "userId": { "description": "User ID", + "format": "uuid", + "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$", "type": "string" } }, @@ -18441,6 +18469,8 @@ }, "userId": { "description": "User ID", + "format": "uuid", + "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$", "type": "string" } }, @@ -18600,6 +18630,8 @@ "assetIds": { "description": "Asset IDs in this archive", "items": { + "format": "uuid", + "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$", "type": "string" }, "type": "array" @@ -18785,6 +18817,8 @@ }, "duplicateId": { "description": "Duplicate group ID", + "format": "uuid", + "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$", "type": "string" }, "suggestedKeepAssetIds": { @@ -19101,6 +19135,8 @@ "properties": { "id": { "description": "Integrity report item id", + "format": "uuid", + "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$", "type": "string" }, "path": { @@ -19275,6 +19311,8 @@ }, "id": { "description": "Library ID", + "format": "uuid", + "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$", "type": "string" }, "importPaths": { @@ -19290,6 +19328,8 @@ }, "ownerId": { "description": "Owner user ID", + "format": "uuid", + "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$", "type": "string" }, "refreshedAt": { @@ -19444,6 +19484,8 @@ }, "userId": { "description": "User ID", + "format": "uuid", + "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$", "type": "string" } }, @@ -19634,6 +19676,8 @@ }, "id": { "description": "Asset ID", + "format": "uuid", + "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$", "type": "string" }, "lat": { @@ -19834,6 +19878,8 @@ }, "id": { "description": "Memory ID", + "format": "uuid", + "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$", "type": "string" }, "isSaved": { @@ -19849,6 +19895,8 @@ }, "ownerId": { "description": "Owner user ID", + "format": "uuid", + "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$", "type": "string" }, "seenAt": { @@ -20310,6 +20358,8 @@ }, "id": { "description": "Notification ID", + "format": "uuid", + "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$", "type": "string" }, "level": { @@ -20754,6 +20804,8 @@ }, "id": { "description": "Person ID", + "format": "uuid", + "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$", "type": "string" }, "isFavorite": { @@ -20989,6 +21041,8 @@ }, "id": { "description": "Person ID", + "format": "uuid", + "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$", "type": "string" }, "isFavorite": { @@ -21244,6 +21298,8 @@ }, "id": { "description": "Plugin ID", + "format": "uuid", + "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$", "type": "string" }, "methods": { @@ -22639,6 +22695,8 @@ }, "id": { "description": "Version history entry ID", + "format": "uuid", + "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$", "type": "string" }, "version": { @@ -22743,6 +22801,8 @@ }, "id": { "description": "Session ID", + "format": "uuid", + "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$", "type": "string" }, "isPendingSyncReset": { @@ -22800,6 +22860,8 @@ }, "id": { "description": "Session ID", + "format": "uuid", + "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$", "type": "string" }, "isPendingSyncReset": { @@ -23022,6 +23084,8 @@ }, "id": { "description": "Shared link ID", + "format": "uuid", + "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$", "type": "string" }, "key": { @@ -23047,6 +23111,8 @@ }, "userId": { "description": "Owner user ID", + "format": "uuid", + "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$", "type": "string" } }, @@ -23388,10 +23454,14 @@ }, "id": { "description": "Stack ID", + "format": "uuid", + "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$", "type": "string" }, "primaryAssetId": { "description": "Primary asset ID", + "format": "uuid", + "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$", "type": "string" } }, @@ -23665,6 +23735,8 @@ "properties": { "albumId": { "description": "Album ID", + "format": "uuid", + "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$", "type": "string" } }, @@ -23677,10 +23749,14 @@ "properties": { "albumId": { "description": "Album ID", + "format": "uuid", + "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$", "type": "string" }, "assetId": { "description": "Asset ID", + "format": "uuid", + "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$", "type": "string" } }, @@ -23694,10 +23770,14 @@ "properties": { "albumId": { "description": "Album ID", + "format": "uuid", + "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$", "type": "string" }, "assetId": { "description": "Asset ID", + "format": "uuid", + "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$", "type": "string" } }, @@ -23711,10 +23791,14 @@ "properties": { "albumId": { "description": "Album ID", + "format": "uuid", + "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$", "type": "string" }, "userId": { "description": "User ID", + "format": "uuid", + "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$", "type": "string" } }, @@ -23728,6 +23812,8 @@ "properties": { "albumId": { "description": "Album ID", + "format": "uuid", + "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$", "type": "string" }, "role": { @@ -23735,6 +23821,8 @@ }, "userId": { "description": "User ID", + "format": "uuid", + "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$", "type": "string" } }, @@ -23760,6 +23848,8 @@ }, "id": { "description": "Album ID", + "format": "uuid", + "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$", "type": "string" }, "isActivityEnabled": { @@ -23775,6 +23865,8 @@ }, "ownerId": { "description": "Owner ID", + "format": "uuid", + "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$", "type": "string" }, "thumbnailAssetId": { @@ -23818,6 +23910,8 @@ }, "id": { "description": "Album ID", + "format": "uuid", + "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$", "type": "string" }, "isActivityEnabled": { @@ -23860,6 +23954,8 @@ "properties": { "assetId": { "description": "Asset ID", + "format": "uuid", + "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$", "type": "string" } }, @@ -23872,6 +23968,8 @@ "properties": { "editId": { "description": "Edit ID", + "format": "uuid", + "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$", "type": "string" } }, @@ -23887,10 +23985,14 @@ }, "assetId": { "description": "Asset ID", + "format": "uuid", + "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$", "type": "string" }, "id": { "description": "Edit ID", + "format": "uuid", + "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$", "type": "string" }, "parameters": { @@ -23918,6 +24020,8 @@ "properties": { "assetId": { "description": "Asset ID", + "format": "uuid", + "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$", "type": "string" }, "city": { @@ -24095,6 +24199,8 @@ "properties": { "assetFaceId": { "description": "Asset face ID", + "format": "uuid", + "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$", "type": "string" } }, @@ -24107,6 +24213,8 @@ "properties": { "assetId": { "description": "Asset ID", + "format": "uuid", + "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$", "type": "string" }, "boundingBoxX1": { @@ -24135,6 +24243,8 @@ }, "id": { "description": "Asset face ID", + "format": "uuid", + "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$", "type": "string" }, "imageHeight": { @@ -24177,6 +24287,8 @@ "properties": { "assetId": { "description": "Asset ID", + "format": "uuid", + "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$", "type": "string" }, "boundingBoxX1": { @@ -24213,6 +24325,8 @@ }, "id": { "description": "Asset face ID", + "format": "uuid", + "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$", "type": "string" }, "imageHeight": { @@ -24261,6 +24375,8 @@ "properties": { "assetId": { "description": "Asset ID", + "format": "uuid", + "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$", "type": "string" }, "key": { @@ -24278,6 +24394,8 @@ "properties": { "assetId": { "description": "Asset ID", + "format": "uuid", + "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$", "type": "string" }, "key": { @@ -24326,6 +24444,8 @@ "properties": { "assetId": { "description": "Asset ID", + "format": "uuid", + "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$", "type": "string" }, "boxScore": { @@ -24335,6 +24455,8 @@ }, "id": { "description": "OCR entry ID", + "format": "uuid", + "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$", "type": "string" }, "isVisible": { @@ -24461,6 +24583,8 @@ }, "id": { "description": "Asset ID", + "format": "uuid", + "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$", "type": "string" }, "isEdited": { @@ -24495,6 +24619,8 @@ }, "ownerId": { "description": "Owner ID", + "format": "uuid", + "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$", "type": "string" }, "stackId": { @@ -24599,6 +24725,8 @@ }, "id": { "description": "Asset ID", + "format": "uuid", + "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$", "type": "string" }, "isEdited": { @@ -24633,6 +24761,8 @@ }, "ownerId": { "description": "Owner ID", + "format": "uuid", + "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$", "type": "string" }, "stackId": { @@ -24711,6 +24841,8 @@ }, "id": { "description": "User ID", + "format": "uuid", + "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$", "type": "string" }, "isAdmin": { @@ -24845,10 +24977,14 @@ "properties": { "assetId": { "description": "Asset ID", + "format": "uuid", + "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$", "type": "string" }, "memoryId": { "description": "Memory ID", + "format": "uuid", + "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$", "type": "string" } }, @@ -24862,10 +24998,14 @@ "properties": { "assetId": { "description": "Asset ID", + "format": "uuid", + "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$", "type": "string" }, "memoryId": { "description": "Memory ID", + "format": "uuid", + "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$", "type": "string" } }, @@ -24879,6 +25019,8 @@ "properties": { "memoryId": { "description": "Memory ID", + "format": "uuid", + "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$", "type": "string" } }, @@ -24919,6 +25061,8 @@ }, "id": { "description": "Memory ID", + "format": "uuid", + "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$", "type": "string" }, "isSaved": { @@ -24934,6 +25078,8 @@ }, "ownerId": { "description": "Owner ID", + "format": "uuid", + "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$", "type": "string" }, "seenAt": { @@ -24983,10 +25129,14 @@ "properties": { "sharedById": { "description": "Shared by ID", + "format": "uuid", + "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$", "type": "string" }, "sharedWithId": { "description": "Shared with ID", + "format": "uuid", + "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$", "type": "string" } }, @@ -25004,10 +25154,14 @@ }, "sharedById": { "description": "Shared by ID", + "format": "uuid", + "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$", "type": "string" }, "sharedWithId": { "description": "Shared with ID", + "format": "uuid", + "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$", "type": "string" } }, @@ -25022,6 +25176,8 @@ "properties": { "personId": { "description": "Person ID", + "format": "uuid", + "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$", "type": "string" } }, @@ -25059,6 +25215,8 @@ }, "id": { "description": "Person ID", + "format": "uuid", + "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$", "type": "string" }, "isFavorite": { @@ -25075,6 +25233,8 @@ }, "ownerId": { "description": "Owner ID", + "format": "uuid", + "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$", "type": "string" }, "updatedAt": { @@ -25140,6 +25300,8 @@ "properties": { "stackId": { "description": "Stack ID", + "format": "uuid", + "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$", "type": "string" } }, @@ -25159,14 +25321,20 @@ }, "id": { "description": "Stack ID", + "format": "uuid", + "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$", "type": "string" }, "ownerId": { "description": "Owner ID", + "format": "uuid", + "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$", "type": "string" }, "primaryAssetId": { "description": "Primary asset ID", + "format": "uuid", + "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$", "type": "string" }, "updatedAt": { @@ -25209,6 +25377,8 @@ "properties": { "userId": { "description": "User ID", + "format": "uuid", + "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$", "type": "string" } }, @@ -25224,6 +25394,8 @@ }, "userId": { "description": "User ID", + "format": "uuid", + "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$", "type": "string" } }, @@ -25240,6 +25412,8 @@ }, "userId": { "description": "User ID", + "format": "uuid", + "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$", "type": "string" }, "value": { @@ -25283,6 +25457,8 @@ }, "id": { "description": "User ID", + "format": "uuid", + "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$", "type": "string" }, "name": { @@ -26466,6 +26642,8 @@ }, "id": { "description": "Tag ID", + "format": "uuid", + "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$", "type": "string" }, "name": { @@ -26989,6 +27167,8 @@ }, "userId": { "description": "User ID", + "format": "uuid", + "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$", "type": "string" }, "userName": { @@ -27631,6 +27811,8 @@ }, "id": { "description": "Workflow ID", + "format": "uuid", + "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$", "type": "string" }, "name": { diff --git a/server/src/dtos/album.dto.ts b/server/src/dtos/album.dto.ts index ee6f2c07eb..a66f912972 100644 --- a/server/src/dtos/album.dto.ts +++ b/server/src/dtos/album.dto.ts @@ -100,21 +100,21 @@ const AlbumUserResponseSchema = z const ContributorCountResponseSchema = z .object({ - userId: z.string().describe('User ID'), + userId: z.uuidv4().describe('User ID'), assetCount: z.int().min(0).describe('Number of assets contributed'), }) .meta({ id: 'ContributorCountResponseDto' }); export const AlbumResponseSchema = z .object({ - id: z.string().describe('Album ID'), + id: z.uuidv4().describe('Album ID'), albumName: z.string().describe('Album name'), description: z.string().describe('Album description'), // TODO: use `isoDatetimeToDate` when using `ZodSerializerDto` on the controllers. createdAt: z.string().meta({ format: 'date-time' }).describe('Creation date'), // TODO: use `isoDatetimeToDate` when using `ZodSerializerDto` on the controllers. updatedAt: z.string().meta({ format: 'date-time' }).describe('Last update date'), - albumThumbnailAssetId: z.string().nullable().describe('Thumbnail asset ID'), + albumThumbnailAssetId: z.uuidv4().nullable().describe('Thumbnail asset ID'), shared: z.boolean().describe('Is shared album'), albumUsers: z .array(AlbumUserResponseSchema) diff --git a/server/src/dtos/api-key.dto.ts b/server/src/dtos/api-key.dto.ts index 176812cc4f..470808e430 100644 --- a/server/src/dtos/api-key.dto.ts +++ b/server/src/dtos/api-key.dto.ts @@ -21,7 +21,7 @@ const ApiKeyUpdateSchema = z const ApiKeyResponseSchema = z .object({ - id: z.string().describe('API key ID'), + id: z.uuidv4().describe('API key ID'), name: z.string().describe('API key name'), createdAt: isoDatetimeToDate.describe('Creation date'), updatedAt: isoDatetimeToDate.describe('Last update date'), diff --git a/server/src/dtos/asset-ids.response.dto.ts b/server/src/dtos/asset-ids.response.dto.ts index 346829e644..e86eee0973 100644 --- a/server/src/dtos/asset-ids.response.dto.ts +++ b/server/src/dtos/asset-ids.response.dto.ts @@ -16,7 +16,7 @@ const AssetIdErrorReasonSchema = z /** @deprecated Use `BulkIdResponseDto` instead */ const AssetIdsResponseSchema = z .object({ - assetId: z.string().describe('Asset ID'), + assetId: z.uuidv4().describe('Asset ID'), success: z.boolean().describe('Whether operation succeeded'), error: AssetIdErrorReasonSchema.optional(), }) @@ -43,7 +43,7 @@ export const BulkIdsSchema = z const BulkIdResponseSchema = z .object({ - id: z.string().describe('ID'), + id: z.uuidv4().describe('ID'), success: z.boolean().describe('Whether operation succeeded'), error: BulkIdErrorReasonSchema.optional(), errorMessage: z.string().optional(), diff --git a/server/src/dtos/asset-media-response.dto.ts b/server/src/dtos/asset-media-response.dto.ts index 0f27fc5974..b0c50794b9 100644 --- a/server/src/dtos/asset-media-response.dto.ts +++ b/server/src/dtos/asset-media-response.dto.ts @@ -11,7 +11,7 @@ const AssetMediaStatusSchema = z.enum(AssetMediaStatus).describe('Upload status' const AssetMediaResponseSchema = z .object({ status: AssetMediaStatusSchema, - id: z.string().describe('Asset media ID'), + id: z.uuidv4().describe('Asset media ID'), }) .meta({ id: 'AssetMediaResponseDto' }); @@ -34,7 +34,7 @@ const AssetRejectReasonSchema = z const AssetBulkUploadCheckResultSchema = z .object({ - id: z.string().describe('Asset ID'), + id: z.uuidv4().describe('Asset ID'), action: AssetUploadActionSchema, reason: AssetRejectReasonSchema.optional(), assetId: z.string().optional().describe('Existing asset ID if duplicate'), diff --git a/server/src/dtos/asset-response.dto.ts b/server/src/dtos/asset-response.dto.ts index b5b0b04a2d..ba64286647 100644 --- a/server/src/dtos/asset-response.dto.ts +++ b/server/src/dtos/asset-response.dto.ts @@ -24,7 +24,7 @@ import z from 'zod'; const SanitizedAssetResponseSchema = z .object({ - id: z.string().describe('Asset ID'), + id: z.uuidv4().describe('Asset ID'), type: AssetTypeSchema, thumbhash: z .string() @@ -52,8 +52,8 @@ export class SanitizedAssetResponseDto extends createZodDto(SanitizedAssetRespon const AssetStackResponseSchema = z .object({ - id: z.string().describe('Stack ID'), - primaryAssetId: z.string().describe('Primary asset ID'), + id: z.uuidv4().describe('Stack ID'), + primaryAssetId: z.uuidv4().describe('Primary asset ID'), assetCount: z.int().min(0).describe('Number of assets in stack'), }) .meta({ id: 'AssetStackResponseDto' }); @@ -65,7 +65,7 @@ export const AssetResponseSchema = SanitizedAssetResponseSchema.extend( .string() .meta({ format: 'date-time' }) .describe('The UTC timestamp when the asset was originally uploaded to Immich.'), - ownerId: z.string().describe('Owner user ID'), + ownerId: z.uuidv4().describe('Owner user ID'), owner: UserResponseSchema.optional(), libraryId: z .uuidv4() @@ -103,7 +103,7 @@ export const AssetResponseSchema = SanitizedAssetResponseSchema.extend( people: z.array(PersonResponseSchema).optional(), checksum: z.string().describe('Base64 encoded SHA1 hash'), stack: AssetStackResponseSchema.nullish(), - duplicateId: z.string().nullish().describe('Duplicate group ID'), + duplicateId: z.uuidv4().nullish().describe('Duplicate group ID'), resized: z .boolean() .optional() diff --git a/server/src/dtos/asset.dto.ts b/server/src/dtos/asset.dto.ts index 3dddcfaa3e..26c983a7de 100644 --- a/server/src/dtos/asset.dto.ts +++ b/server/src/dtos/asset.dto.ts @@ -148,7 +148,7 @@ const AssetMetadataResponseSchema = z .meta({ id: 'AssetMetadataResponseDto' }); const AssetMetadataBulkResponseSchema = AssetMetadataResponseSchema.extend({ - assetId: z.string().describe('Asset ID'), + assetId: z.uuidv4().describe('Asset ID'), }).meta({ id: 'AssetMetadataBulkResponseDto' }); const AssetCopySchema = z diff --git a/server/src/dtos/auth.dto.ts b/server/src/dtos/auth.dto.ts index 1f75401e33..40b4e25b6d 100644 --- a/server/src/dtos/auth.dto.ts +++ b/server/src/dtos/auth.dto.ts @@ -29,7 +29,7 @@ const LoginCredentialSchema = z const LoginResponseSchema = z .object({ accessToken: z.string().describe('Access token'), - userId: z.string().describe('User ID'), + userId: z.uuidv4().describe('User ID'), userEmail: toEmail.describe('User email'), name: z.string().describe('User name'), profileImagePath: z.string().describe('Profile image path'), diff --git a/server/src/dtos/download.dto.ts b/server/src/dtos/download.dto.ts index b44a6a7afc..c37fa5c113 100644 --- a/server/src/dtos/download.dto.ts +++ b/server/src/dtos/download.dto.ts @@ -14,7 +14,7 @@ const DownloadInfoSchema = z const DownloadArchiveInfoSchema = z .object({ size: z.int().describe('Archive size in bytes'), - assetIds: z.array(z.string()).describe('Asset IDs in this archive'), + assetIds: z.array(z.uuidv4()).describe('Asset IDs in this archive'), }) .meta({ id: 'DownloadArchiveInfo' }); diff --git a/server/src/dtos/duplicate.dto.ts b/server/src/dtos/duplicate.dto.ts index 55427e36aa..66d14e605b 100644 --- a/server/src/dtos/duplicate.dto.ts +++ b/server/src/dtos/duplicate.dto.ts @@ -4,7 +4,7 @@ import z from 'zod'; const DuplicateResponseSchema = z .object({ - duplicateId: z.string().describe('Duplicate group ID'), + duplicateId: z.uuidv4().describe('Duplicate group ID'), assets: z.array(AssetResponseSchema).describe('Duplicate assets'), suggestedKeepAssetIds: z.array(z.uuidv4()).describe('Suggested asset IDs to keep based on file size and EXIF data'), }) diff --git a/server/src/dtos/integrity.dto.ts b/server/src/dtos/integrity.dto.ts index b4faf6005e..3b89b117ea 100644 --- a/server/src/dtos/integrity.dto.ts +++ b/server/src/dtos/integrity.dto.ts @@ -27,7 +27,7 @@ const IntegrityDeleteReportSchema = z.object({ type: IntegrityReport }).meta({ i export class IntegrityDeleteReportDto extends createZodDto(IntegrityDeleteReportSchema) {} const IntegrityReportResponseItemSchema = z.object({ - id: z.string().describe('Integrity report item id'), + id: z.uuidv4().describe('Integrity report item id'), type: IntegrityReportSchema, path: z.string().describe('Integrity report item path'), }); diff --git a/server/src/dtos/library.dto.ts b/server/src/dtos/library.dto.ts index aafdd9f793..0819be278e 100644 --- a/server/src/dtos/library.dto.ts +++ b/server/src/dtos/library.dto.ts @@ -62,8 +62,8 @@ const ValidateLibraryResponseSchema = z const LibraryResponseSchema = z .object({ - id: z.string().describe('Library ID'), - ownerId: z.string().describe('Owner user ID'), + id: z.uuidv4().describe('Library ID'), + ownerId: z.uuidv4().describe('Owner user ID'), name: z.string().describe('Library name'), assetCount: z.int().describe('Number of assets'), importPaths: z.array(z.string()).describe('Import paths'), diff --git a/server/src/dtos/map.dto.ts b/server/src/dtos/map.dto.ts index 6a4776d49d..f442850936 100644 --- a/server/src/dtos/map.dto.ts +++ b/server/src/dtos/map.dto.ts @@ -30,7 +30,7 @@ const MapMarkerSchema = z const MapMarkerResponseSchema = z .object({ - id: z.string().describe('Asset ID'), + id: z.uuidv4().describe('Asset ID'), lat: z.number().meta({ format: 'double' }).describe('Latitude'), lon: z.number().meta({ format: 'double' }).describe('Longitude'), city: z.string().nullable().describe('City name'), diff --git a/server/src/dtos/memory.dto.ts b/server/src/dtos/memory.dto.ts index ce2e9fda6c..324474a1e1 100644 --- a/server/src/dtos/memory.dto.ts +++ b/server/src/dtos/memory.dto.ts @@ -59,7 +59,7 @@ const MemoryStatisticsResponseSchema = z const MemoryResponseSchema = z .object({ - id: z.string().describe('Memory ID'), + id: z.uuidv4().describe('Memory ID'), createdAt: isoDatetimeToDate.describe('Creation date'), updatedAt: isoDatetimeToDate.describe('Last update date'), deletedAt: isoDatetimeToDate.optional().describe('Deletion date'), @@ -67,7 +67,7 @@ const MemoryResponseSchema = z seenAt: isoDatetimeToDate.optional().describe('Date when memory was seen'), showAt: isoDatetimeToDate.optional().describe('Date when memory should be shown'), hideAt: isoDatetimeToDate.optional().describe('Date when memory should be hidden'), - ownerId: z.string().describe('Owner user ID'), + ownerId: z.uuidv4().describe('Owner user ID'), type: MemoryTypeSchema, data: OnThisDaySchema, isSaved: z.boolean().describe('Is memory saved'), diff --git a/server/src/dtos/notification.dto.ts b/server/src/dtos/notification.dto.ts index f474cfc0a1..04f937fc00 100644 --- a/server/src/dtos/notification.dto.ts +++ b/server/src/dtos/notification.dto.ts @@ -24,7 +24,7 @@ const TemplateSchema = z const NotificationSchema = z .object({ - id: z.string().describe('Notification ID'), + id: z.uuidv4().describe('Notification ID'), createdAt: isoDatetimeToDate.describe('Creation date'), level: NotificationLevelSchema, type: NotificationTypeSchema, diff --git a/server/src/dtos/person.dto.ts b/server/src/dtos/person.dto.ts index 38e856b8c1..fa56ded176 100644 --- a/server/src/dtos/person.dto.ts +++ b/server/src/dtos/person.dto.ts @@ -33,7 +33,7 @@ const PersonUpdateSchema = PersonCreateSchema.extend({ }).meta({ id: 'PersonUpdateDto' }); const PeopleUpdateItemSchema = PersonUpdateSchema.extend({ - id: z.string().describe('Person ID'), + id: z.uuidv4().describe('Person ID'), }).meta({ id: 'PeopleUpdateItem' }); const PeopleUpdateSchema = z @@ -60,7 +60,7 @@ const PersonSearchSchema = z export const PersonResponseSchema = z .object({ - id: z.string().describe('Person ID'), + id: z.uuidv4().describe('Person ID'), name: z.string().describe('Person name'), // TODO: use `isoDateToDate` when using `ZodSerializerDto` on the controllers. birthDate: z.string().meta({ format: 'date' }).describe('Person date of birth').nullable(), diff --git a/server/src/dtos/plugin.dto.ts b/server/src/dtos/plugin.dto.ts index 8ee695d61c..777380a107 100644 --- a/server/src/dtos/plugin.dto.ts +++ b/server/src/dtos/plugin.dto.ts @@ -32,7 +32,7 @@ const PluginMethodResponseSchema = z const PluginResponseSchema = z .object({ - id: z.string().describe('Plugin ID'), + id: z.uuidv4().describe('Plugin ID'), name: z.string().describe('Plugin name'), title: z.string().describe('Plugin title'), description: z.string().describe('Plugin description'), diff --git a/server/src/dtos/server.dto.ts b/server/src/dtos/server.dto.ts index 03d45fab1c..0215558aab 100644 --- a/server/src/dtos/server.dto.ts +++ b/server/src/dtos/server.dto.ts @@ -73,7 +73,7 @@ const ServerVersionResponseSchema = z const ServerVersionHistoryResponseSchema = z .object({ - id: z.string().describe('Version history entry ID'), + id: z.uuidv4().describe('Version history entry ID'), createdAt: isoDatetimeToDate.describe('When this version was first seen'), version: z.string().describe('Version string'), }) @@ -81,7 +81,7 @@ const ServerVersionHistoryResponseSchema = z const UsageByUserSchema = z .object({ - userId: z.string().describe('User ID'), + userId: z.uuidv4().describe('User ID'), userName: z.string().describe('User name'), photos: z.int().describe('Number of photos'), videos: z.int().describe('Number of videos'), diff --git a/server/src/dtos/session.dto.ts b/server/src/dtos/session.dto.ts index 424d104053..c81dac6d79 100644 --- a/server/src/dtos/session.dto.ts +++ b/server/src/dtos/session.dto.ts @@ -18,7 +18,7 @@ const SessionUpdateSchema = z const SessionResponseSchema = z .object({ - id: z.string().describe('Session ID'), + id: z.uuidv4().describe('Session ID'), createdAt: z.string().describe('Creation date'), updatedAt: z.string().describe('Last update date'), expiresAt: z.string().optional().describe('Expiration date'), diff --git a/server/src/dtos/shared-link.dto.ts b/server/src/dtos/shared-link.dto.ts index aebe6fcab1..6763f6ab74 100644 --- a/server/src/dtos/shared-link.dto.ts +++ b/server/src/dtos/shared-link.dto.ts @@ -53,10 +53,10 @@ const SharedLinkLoginSchema = z const SharedLinkResponseSchema = z .object({ - id: z.string().describe('Shared link ID'), + id: z.uuidv4().describe('Shared link ID'), description: z.string().nullable().describe('Link description'), password: z.string().nullable().describe('Has password'), - userId: z.string().describe('Owner user ID'), + userId: z.uuidv4().describe('Owner user ID'), key: z.string().describe('Encryption key (base64url)'), type: SharedLinkTypeSchema, createdAt: isoDatetimeToDate.describe('Creation date'), diff --git a/server/src/dtos/stack.dto.ts b/server/src/dtos/stack.dto.ts index 48354cec6b..1956974ba1 100644 --- a/server/src/dtos/stack.dto.ts +++ b/server/src/dtos/stack.dto.ts @@ -24,8 +24,8 @@ const StackUpdateSchema = z const StackResponseSchema = z .object({ - id: z.string().describe('Stack ID'), - primaryAssetId: z.string().describe('Primary asset ID'), + id: z.uuidv4().describe('Stack ID'), + primaryAssetId: z.uuidv4().describe('Primary asset ID'), assets: z.array(AssetResponseSchema), }) .describe('Stack response') diff --git a/server/src/dtos/sync.dto.ts b/server/src/dtos/sync.dto.ts index 531ac6277c..1d5fe64aa1 100644 --- a/server/src/dtos/sync.dto.ts +++ b/server/src/dtos/sync.dto.ts @@ -19,7 +19,7 @@ import z from 'zod'; const SyncUserV1Schema = z .object({ - id: z.string().describe('User ID'), + id: z.uuidv4().describe('User ID'), name: z.string().describe('User name'), email: z.string().describe('User email'), avatarColor: UserAvatarColorSchema.nullish(), @@ -40,27 +40,27 @@ const SyncAuthUserV1Schema = SyncUserV1Schema.merge( }), ).meta({ id: 'SyncAuthUserV1' }); -const SyncUserDeleteV1Schema = z.object({ userId: z.string().describe('User ID') }).meta({ id: 'SyncUserDeleteV1' }); +const SyncUserDeleteV1Schema = z.object({ userId: z.uuidv4().describe('User ID') }).meta({ id: 'SyncUserDeleteV1' }); const SyncPartnerV1Schema = z .object({ - sharedById: z.string().describe('Shared by ID'), - sharedWithId: z.string().describe('Shared with ID'), + sharedById: z.uuidv4().describe('Shared by ID'), + sharedWithId: z.uuidv4().describe('Shared with ID'), inTimeline: z.boolean().describe('In timeline'), }) .meta({ id: 'SyncPartnerV1' }); const SyncPartnerDeleteV1Schema = z .object({ - sharedById: z.string().describe('Shared by ID'), - sharedWithId: z.string().describe('Shared with ID'), + sharedById: z.uuidv4().describe('Shared by ID'), + sharedWithId: z.uuidv4().describe('Shared with ID'), }) .meta({ id: 'SyncPartnerDeleteV1' }); const SyncAssetV1Schema = z .object({ - id: z.string().describe('Asset ID'), - ownerId: z.string().describe('Owner ID'), + id: z.uuidv4().describe('Asset ID'), + ownerId: z.uuidv4().describe('Owner ID'), originalFileName: z.string().describe('Original file name'), thumbhash: z.string().nullable().describe('Thumbhash'), checksum: z.string().describe('Checksum'), @@ -84,8 +84,8 @@ const SyncAssetV1Schema = z const SyncAssetV2Schema = z .object({ - id: z.string().describe('Asset ID'), - ownerId: z.string().describe('Owner ID'), + id: z.uuidv4().describe('Asset ID'), + ownerId: z.uuidv4().describe('Owner ID'), originalFileName: z.string().describe('Original file name'), thumbhash: z.string().nullable().describe('Thumbhash'), checksum: z.string().describe('Checksum'), @@ -123,12 +123,12 @@ export class SyncAssetV1 extends createZodDto(SyncAssetV1Schema) {} export class SyncAssetV2 extends createZodDto(SyncAssetV2Schema) {} const SyncAssetDeleteV1Schema = z - .object({ assetId: z.string().describe('Asset ID') }) + .object({ assetId: z.uuidv4().describe('Asset ID') }) .meta({ id: 'SyncAssetDeleteV1' }); const SyncAssetExifV1Schema = z .object({ - assetId: z.string().describe('Asset ID'), + assetId: z.uuidv4().describe('Asset ID'), description: z.string().nullable().describe('Description'), exifImageWidth: z.int().nullable().describe('Exif image width'), exifImageHeight: z.int().nullable().describe('Exif image height'), @@ -158,7 +158,7 @@ const SyncAssetExifV1Schema = z const SyncAssetMetadataV1Schema = z .object({ - assetId: z.string().describe('Asset ID'), + assetId: z.uuidv4().describe('Asset ID'), key: z.string().describe('Key'), value: z.record(z.string(), z.unknown()).describe('Value'), }) @@ -166,15 +166,15 @@ const SyncAssetMetadataV1Schema = z const SyncAssetMetadataDeleteV1Schema = z .object({ - assetId: z.string().describe('Asset ID'), + assetId: z.uuidv4().describe('Asset ID'), key: z.string().describe('Key'), }) .meta({ id: 'SyncAssetMetadataDeleteV1' }); const SyncAssetEditV1Schema = z .object({ - id: z.string().describe('Edit ID'), - assetId: z.string().describe('Asset ID'), + id: z.uuidv4().describe('Edit ID'), + assetId: z.uuidv4().describe('Asset ID'), action: AssetEditActionSchema, parameters: z.record(z.string(), z.unknown()).describe('Edit parameters'), sequence: z.int().describe('Edit sequence'), @@ -182,7 +182,7 @@ const SyncAssetEditV1Schema = z .meta({ id: 'SyncAssetEditV1' }); const SyncAssetEditDeleteV1Schema = z - .object({ editId: z.string().describe('Edit ID') }) + .object({ editId: z.uuidv4().describe('Edit ID') }) .meta({ id: 'SyncAssetEditDeleteV1' }); @ExtraModel() @@ -199,28 +199,28 @@ export class SyncAssetEditV1 extends createZodDto(SyncAssetEditV1Schema) {} class SyncAssetEditDeleteV1 extends createZodDto(SyncAssetEditDeleteV1Schema) {} const SyncAlbumDeleteV1Schema = z - .object({ albumId: z.string().describe('Album ID') }) + .object({ albumId: z.uuidv4().describe('Album ID') }) .meta({ id: 'SyncAlbumDeleteV1' }); const SyncAlbumUserDeleteV1Schema = z .object({ - albumId: z.string().describe('Album ID'), - userId: z.string().describe('User ID'), + albumId: z.uuidv4().describe('Album ID'), + userId: z.uuidv4().describe('User ID'), }) .meta({ id: 'SyncAlbumUserDeleteV1' }); const SyncAlbumUserV1Schema = z .object({ - albumId: z.string().describe('Album ID'), - userId: z.string().describe('User ID'), + albumId: z.uuidv4().describe('Album ID'), + userId: z.uuidv4().describe('User ID'), role: AlbumUserRoleSchema, }) .meta({ id: 'SyncAlbumUserV1' }); const SyncAlbumV1Schema = z .object({ - id: z.string().describe('Album ID'), - ownerId: z.string().describe('Owner ID'), + id: z.uuidv4().describe('Album ID'), + ownerId: z.uuidv4().describe('Owner ID'), name: z.string().describe('Album name'), description: z.string().describe('Album description'), createdAt: isoDatetimeToDate.describe('Created at'), @@ -233,7 +233,7 @@ const SyncAlbumV1Schema = z const SyncAlbumV2Schema = z .object({ - id: z.string().describe('Album ID'), + id: z.uuidv4().describe('Album ID'), name: z.string().describe('Album name'), description: z.string().describe('Album description'), createdAt: isoDatetimeToDate.describe('Created at'), @@ -246,15 +246,15 @@ const SyncAlbumV2Schema = z const SyncAlbumToAssetV1Schema = z .object({ - albumId: z.string().describe('Album ID'), - assetId: z.string().describe('Asset ID'), + albumId: z.uuidv4().describe('Album ID'), + assetId: z.uuidv4().describe('Asset ID'), }) .meta({ id: 'SyncAlbumToAssetV1' }); const SyncAlbumToAssetDeleteV1Schema = z .object({ - albumId: z.string().describe('Album ID'), - assetId: z.string().describe('Asset ID'), + albumId: z.uuidv4().describe('Album ID'), + assetId: z.uuidv4().describe('Asset ID'), }) .meta({ id: 'SyncAlbumToAssetDeleteV1' }); @@ -284,11 +284,11 @@ export function syncAlbumV2ToV1( const SyncMemoryV1Schema = z .object({ - id: z.string().describe('Memory ID'), + id: z.uuidv4().describe('Memory ID'), createdAt: isoDatetimeToDate.describe('Created at'), updatedAt: isoDatetimeToDate.describe('Updated at'), deletedAt: isoDatetimeToDate.nullable().describe('Deleted at'), - ownerId: z.string().describe('Owner ID'), + ownerId: z.uuidv4().describe('Owner ID'), type: MemoryTypeSchema, data: z.record(z.string(), z.unknown()).describe('Data'), isSaved: z.boolean().describe('Is saved'), @@ -300,43 +300,43 @@ const SyncMemoryV1Schema = z .meta({ id: 'SyncMemoryV1' }); const SyncMemoryDeleteV1Schema = z - .object({ memoryId: z.string().describe('Memory ID') }) + .object({ memoryId: z.uuidv4().describe('Memory ID') }) .meta({ id: 'SyncMemoryDeleteV1' }); const SyncMemoryAssetV1Schema = z .object({ - memoryId: z.string().describe('Memory ID'), - assetId: z.string().describe('Asset ID'), + memoryId: z.uuidv4().describe('Memory ID'), + assetId: z.uuidv4().describe('Asset ID'), }) .meta({ id: 'SyncMemoryAssetV1' }); const SyncMemoryAssetDeleteV1Schema = z .object({ - memoryId: z.string().describe('Memory ID'), - assetId: z.string().describe('Asset ID'), + memoryId: z.uuidv4().describe('Memory ID'), + assetId: z.uuidv4().describe('Asset ID'), }) .meta({ id: 'SyncMemoryAssetDeleteV1' }); const SyncStackV1Schema = z .object({ - id: z.string().describe('Stack ID'), + id: z.uuidv4().describe('Stack ID'), createdAt: isoDatetimeToDate.describe('Created at'), updatedAt: isoDatetimeToDate.describe('Updated at'), - primaryAssetId: z.string().describe('Primary asset ID'), - ownerId: z.string().describe('Owner ID'), + primaryAssetId: z.uuidv4().describe('Primary asset ID'), + ownerId: z.uuidv4().describe('Owner ID'), }) .meta({ id: 'SyncStackV1' }); const SyncStackDeleteV1Schema = z - .object({ stackId: z.string().describe('Stack ID') }) + .object({ stackId: z.uuidv4().describe('Stack ID') }) .meta({ id: 'SyncStackDeleteV1' }); const SyncPersonV1Schema = z .object({ - id: z.string().describe('Person ID'), + id: z.uuidv4().describe('Person ID'), createdAt: isoDatetimeToDate.describe('Created at'), updatedAt: isoDatetimeToDate.describe('Updated at'), - ownerId: z.string().describe('Owner ID'), + ownerId: z.uuidv4().describe('Owner ID'), name: z.string().describe('Person name'), birthDate: isoDatetimeToDate.nullable().describe('Birth date'), isHidden: z.boolean().describe('Is hidden'), @@ -347,13 +347,13 @@ const SyncPersonV1Schema = z .meta({ id: 'SyncPersonV1' }); const SyncPersonDeleteV1Schema = z - .object({ personId: z.string().describe('Person ID') }) + .object({ personId: z.uuidv4().describe('Person ID') }) .meta({ id: 'SyncPersonDeleteV1' }); const SyncAssetFaceV1Schema = z .object({ - id: z.string().describe('Asset face ID'), - assetId: z.string().describe('Asset ID'), + id: z.uuidv4().describe('Asset face ID'), + assetId: z.uuidv4().describe('Asset ID'), personId: z.string().nullable().describe('Person ID'), imageWidth: z.int().describe('Image width'), imageHeight: z.int().describe('Image height'), @@ -371,12 +371,12 @@ const SyncAssetFaceV2Schema = SyncAssetFaceV1Schema.extend({ }).meta({ id: 'SyncAssetFaceV2' }); const SyncAssetFaceDeleteV1Schema = z - .object({ assetFaceId: z.string().describe('Asset face ID') }) + .object({ assetFaceId: z.uuidv4().describe('Asset face ID') }) .meta({ id: 'SyncAssetFaceDeleteV1' }); const SyncUserMetadataV1Schema = z .object({ - userId: z.string().describe('User ID'), + userId: z.uuidv4().describe('User ID'), key: UserMetadataKeySchema, value: z.record(z.string(), z.unknown()).describe('User metadata value'), }) @@ -384,7 +384,7 @@ const SyncUserMetadataV1Schema = z const SyncUserMetadataDeleteV1Schema = z .object({ - userId: z.string().describe('User ID'), + userId: z.uuidv4().describe('User ID'), key: UserMetadataKeySchema, }) .meta({ id: 'SyncUserMetadataDeleteV1' }); @@ -404,8 +404,8 @@ class SyncMemoryAssetDeleteV1 extends createZodDto(SyncMemoryAssetDeleteV1Schema const SyncAssetOcrV1Schema = z .object({ - id: z.string().describe('OCR entry ID'), - assetId: z.string().describe('Asset ID'), + id: z.uuidv4().describe('OCR entry ID'), + assetId: z.uuidv4().describe('Asset ID'), x1: z.number().meta({ format: 'double' }).describe('Top-left X coordinate (normalized 0–1)'), y1: z.number().meta({ format: 'double' }).describe('Top-left Y coordinate (normalized 0–1)'), diff --git a/server/src/dtos/tag.dto.ts b/server/src/dtos/tag.dto.ts index dd679c97cb..cfbae551a8 100644 --- a/server/src/dtos/tag.dto.ts +++ b/server/src/dtos/tag.dto.ts @@ -40,7 +40,7 @@ const TagBulkAssetsResponseSchema = z export const TagResponseSchema = z .object({ - id: z.string().describe('Tag ID'), + id: z.uuidv4().describe('Tag ID'), parentId: z.string().optional().describe('Parent tag ID'), name: z.string().describe('Tag name'), value: z.string().describe('Tag value (full path)'), diff --git a/server/src/dtos/user-profile.dto.ts b/server/src/dtos/user-profile.dto.ts index c3c91d3d95..e4ab29b6d5 100644 --- a/server/src/dtos/user-profile.dto.ts +++ b/server/src/dtos/user-profile.dto.ts @@ -11,7 +11,7 @@ export class CreateProfileImageDto { const CreateProfileImageResponseSchema = z .object({ - userId: z.string().describe('User ID'), + userId: z.uuidv4().describe('User ID'), profileChangedAt: isoDatetimeToDate.describe('Profile image change date'), profileImagePath: z.string().describe('Profile image file path'), }) diff --git a/server/src/dtos/workflow.dto.ts b/server/src/dtos/workflow.dto.ts index 1a2c2ac9f9..b4269ea0c9 100644 --- a/server/src/dtos/workflow.dto.ts +++ b/server/src/dtos/workflow.dto.ts @@ -58,7 +58,7 @@ const WorkflowUpdateSchema = z const WorkflowResponseSchema = z .object({ - id: z.string().describe('Workflow ID'), + id: z.uuidv4().describe('Workflow ID'), trigger: WorkflowTriggerSchema.describe('Workflow trigger type'), name: z.string().nullable().describe('Workflow name'), description: z.string().nullable().describe('Workflow description'), From f9db76433e82e8822a3e01c1aced61a2e7672432 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 17 Jun 2026 09:54:19 -0400 Subject: [PATCH 28/64] chore(deps): update github-actions to v1.313.0 (#29154) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/build-mobile.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-mobile.yml b/.github/workflows/build-mobile.yml index 224f673ff9..ea40ab6e1c 100644 --- a/.github/workflows/build-mobile.yml +++ b/.github/workflows/build-mobile.yml @@ -237,7 +237,7 @@ jobs: run: flutter build ios --config-only --no-codesign - name: Setup Ruby - uses: ruby/setup-ruby@12fd324f1d0b43274fdc8130f6980590a667c455 # v1.312.0 + uses: ruby/setup-ruby@89f90524b88a01fe6e0b732220432cc6142926af # v1.313.0 with: ruby-version: '3.3' bundler-cache: true From a364b56b1c296a1ef747441f5533373b3aabb294 Mon Sep 17 00:00:00 2001 From: Jeevan Mohan Pawar <35501212+jeevan6996@users.noreply.github.com> Date: Wed, 17 Jun 2026 14:54:20 +0100 Subject: [PATCH 29/64] fix(server): skip existing users when sharing albums (#28884) Co-authored-by: Daniel Dietzler --- e2e/src/specs/server/api/album.e2e-spec.ts | 8 ++-- server/src/services/album.service.spec.ts | 45 +++++++++++++++++++--- server/src/services/album.service.ts | 2 +- 3 files changed, 44 insertions(+), 11 deletions(-) diff --git a/e2e/src/specs/server/api/album.e2e-spec.ts b/e2e/src/specs/server/api/album.e2e-spec.ts index 1d3be1248c..0aa7b7ec03 100644 --- a/e2e/src/specs/server/api/album.e2e-spec.ts +++ b/e2e/src/specs/server/api/album.e2e-spec.ts @@ -730,8 +730,8 @@ describe('/albums', () => { .set('Authorization', `Bearer ${user1.accessToken}`) .send({ albumUsers: [{ userId: user1.userId, role: AlbumUserRole.Editor }] }); - expect(status).toBe(400); - expect(body).toEqual(errorDto.badRequest('User already added')); + expect(status).toBe(200); + expect(body.albumUsers.length).toEqual(1); }); it('should not be able to add existing user to shared album', async () => { @@ -745,8 +745,8 @@ describe('/albums', () => { .set('Authorization', `Bearer ${user1.accessToken}`) .send({ albumUsers: [{ userId: user2.userId, role: AlbumUserRole.Editor }] }); - expect(status).toBe(400); - expect(body).toEqual(errorDto.badRequest('User already added')); + expect(status).toBe(200); + expect(body.albumUsers.length).toEqual(2); }); }); diff --git a/server/src/services/album.service.spec.ts b/server/src/services/album.service.spec.ts index 374cd58a0e..f1d125993c 100644 --- a/server/src/services/album.service.spec.ts +++ b/server/src/services/album.service.spec.ts @@ -472,17 +472,19 @@ describe(AlbumService.name, () => { expect(mocks.album.update).not.toHaveBeenCalled(); }); - it('should throw an error if the userId is already added', async () => { + it('should skip if the userId is already added', async () => { const userId = newUuid(); const album = AlbumFactory.from().albumUser({ userId }).build(); const { user: owner } = album.albumUsers.find(({ role }) => role === AlbumUserRole.Owner)!; mocks.access.album.checkOwnerAccess.mockResolvedValue(new Set([album.id])); mocks.album.getById.mockResolvedValue(getForAlbum(album)); - await expect( - sut.addUsers(AuthFactory.create(owner), album.id, { albumUsers: [{ userId }] }), - ).rejects.toBeInstanceOf(BadRequestException); + await expect(sut.addUsers(AuthFactory.create(owner), album.id, { albumUsers: [{ userId }] })).resolves.toEqual( + expect.objectContaining({ id: album.id }), + ); expect(mocks.album.update).not.toHaveBeenCalled(); expect(mocks.user.get).not.toHaveBeenCalled(); + expect(mocks.albumUser.create).not.toHaveBeenCalled(); + expect(mocks.event.emit).not.toHaveBeenCalled(); }); it('should throw an error if the userId does not exist', async () => { @@ -498,7 +500,7 @@ describe(AlbumService.name, () => { expect(mocks.user.get).toHaveBeenCalledWith('unknown-user', {}); }); - it('should throw an error if the userId is the ownerId', async () => { + it('should skip if the userId is the ownerId', async () => { const album = AlbumFactory.create(); const { user: owner } = album.albumUsers.find(({ role }) => role === AlbumUserRole.Owner)!; mocks.access.album.checkOwnerAccess.mockResolvedValue(new Set([album.id])); @@ -507,9 +509,11 @@ describe(AlbumService.name, () => { sut.addUsers(AuthFactory.create(owner), album.id, { albumUsers: [{ userId: owner.id }], }), - ).rejects.toBeInstanceOf(BadRequestException); + ).resolves.toEqual(expect.objectContaining({ id: album.id })); expect(mocks.album.update).not.toHaveBeenCalled(); expect(mocks.user.get).not.toHaveBeenCalled(); + expect(mocks.albumUser.create).not.toHaveBeenCalled(); + expect(mocks.event.emit).not.toHaveBeenCalled(); }); it('should add valid shared users', async () => { @@ -534,6 +538,35 @@ describe(AlbumService.name, () => { senderName: owner.name, }); }); + + it('should add new users when already-added users are included', async () => { + const existingUserId = newUuid(); + const album = AlbumFactory.from().albumUser({ userId: existingUserId }).build(); + const { user: owner } = album.albumUsers.find(({ role }) => role === AlbumUserRole.Owner)!; + const user = UserFactory.create(); + mocks.access.album.checkOwnerAccess.mockResolvedValue(new Set([album.id])); + mocks.album.getById.mockResolvedValue(getForAlbum(album)); + mocks.user.get.mockResolvedValue(user); + mocks.albumUser.create.mockResolvedValue(AlbumUserFactory.from().album(album).user(user).build()); + + await sut.addUsers(AuthFactory.create(owner), album.id, { + albumUsers: [{ userId: existingUserId }, { userId: user.id }], + }); + + expect(mocks.user.get).toHaveBeenCalledTimes(1); + expect(mocks.user.get).toHaveBeenCalledWith(user.id, {}); + expect(mocks.albumUser.create).toHaveBeenCalledTimes(1); + expect(mocks.albumUser.create).toHaveBeenCalledWith({ + userId: user.id, + albumId: album.id, + }); + expect(mocks.event.emit).toHaveBeenCalledTimes(1); + expect(mocks.event.emit).toHaveBeenCalledWith('AlbumInvite', { + id: album.id, + userId: user.id, + senderName: owner.name, + }); + }); }); describe('removeUser', () => { diff --git a/server/src/services/album.service.ts b/server/src/services/album.service.ts index cc0b0d899c..5f4bc56d98 100644 --- a/server/src/services/album.service.ts +++ b/server/src/services/album.service.ts @@ -290,7 +290,7 @@ export class AlbumService extends BaseService { const exists = album.albumUsers.find(({ user: { id } }) => id === userId); if (exists) { - throw new BadRequestException('User already added'); + continue; } const user = await this.userRepository.get(userId, {}); From 3be803d0c0d5c8105697951ce045cc4e76bbe889 Mon Sep 17 00:00:00 2001 From: Tom Vincent Date: Wed, 17 Jun 2026 15:19:04 +0100 Subject: [PATCH 30/64] docs(mobile-app): add Play App Signing certificate hash (#29168) --- docs/docs/features/mobile-app.mdx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/docs/features/mobile-app.mdx b/docs/docs/features/mobile-app.mdx index 59a4844c46..1b7c7e21d5 100644 --- a/docs/docs/features/mobile-app.mdx +++ b/docs/docs/features/mobile-app.mdx @@ -13,7 +13,9 @@ import MobileAppBackup from '/docs/partials/_mobile-app-backup.md'; :::info Android verification Below are the SHA-256 fingerprints for the certificates signing the android applications. -- Playstore / Github releases: +- Google Play releases: + `5A:22:C1:83:47:54:05:F5:49:C4:EB:9F:B2:6C:2E:93:A3:EF:9C:57:66:15:0A:7A:F3:8C:8D:3F:E5:15:CC:D6` +- GitHub releases: `86:C5:C4:55:DF:AF:49:85:92:3A:8F:35:AD:B3:1D:0C:9E:0B:95:7D:7F:94:C2:D2:AF:6A:24:38:AA:96:00:20` - F-Droid releases: `FA:8B:43:95:F4:A6:47:71:A0:53:D1:C7:57:73:5F:A2:30:13:74:F5:3D:58:0D:D1:75:AA:F7:A1:35:72:9C:BF` From 327521fa279704b14e11044c2d214fed5d571aa3 Mon Sep 17 00:00:00 2001 From: Adam Gastineau Date: Wed, 17 Jun 2026 07:22:45 -0700 Subject: [PATCH 31/64] docs(mobile): point users towards shared setup docs (#29078) --- mobile/README.md | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/mobile/README.md b/mobile/README.md index 1f0860ced6..4115891e99 100644 --- a/mobile/README.md +++ b/mobile/README.md @@ -4,20 +4,7 @@ The Immich mobile app is a Flutter-based solution leveraging the Isar Database f ## Setup -1. [Install mise](https://mise.jdx.dev/installing-mise.html). -2. Change to the immich directory and trust the mise config with `mise trust`. -3. Install tools with mise: `mise install`. -4. Run `flutter pub get` to install the dependencies. -5. Run `make translation` to generate the translation file. -6. Run `flutter run` to start the app. - -## Translation - -To add a new translation text, enter the key-value pair in the `i18n/en.json` in the root of the immich project. Then, from the `mobile/` directory, run - -```bash -make translation -``` +See [setup](https://docs.immich.app/developer/setup) for how to set up the mobile build environment. ## Static Analysis From 14f6f2c04f97143834e48b8b72cee3b942eddf20 Mon Sep 17 00:00:00 2001 From: Mees Frensel <33722705+meesfrensel@users.noreply.github.com> Date: Wed, 17 Jun 2026 16:31:49 +0200 Subject: [PATCH 32/64] refactor(web): simplify places page controls and use ui's `Select` (#29102) --- web/src/lib/utils/places-utils.ts | 32 ---------- .../(user)/places/PlacesControls.svelte | 62 ++++--------------- .../routes/(user)/places/PlacesList.svelte | 9 ++- 3 files changed, 17 insertions(+), 86 deletions(-) diff --git a/web/src/lib/utils/places-utils.ts b/web/src/lib/utils/places-utils.ts index b100d004d0..08ba2588a8 100644 --- a/web/src/lib/utils/places-utils.ts +++ b/web/src/lib/utils/places-utils.ts @@ -13,38 +13,6 @@ export interface PlacesGroup { places: AssetResponseDto[]; } -export interface PlacesGroupOptionMetadata { - id: PlacesGroupBy; - isDisabled: () => boolean; -} - -export const groupOptionsMetadata: PlacesGroupOptionMetadata[] = [ - { - id: PlacesGroupBy.None, - isDisabled: () => false, - }, - { - id: PlacesGroupBy.Country, - isDisabled: () => false, - }, -]; - -export const findGroupOptionMetadata = (groupBy: string) => { - // Default is no grouping - const defaultGroupOption = groupOptionsMetadata[0]; - return groupOptionsMetadata.find(({ id }) => groupBy === id) ?? defaultGroupOption; -}; - -export const getSelectedPlacesGroupOption = (settings: PlacesViewSettings) => { - const defaultGroupOption = PlacesGroupBy.None; - const albumGroupOption = settings.groupBy ?? defaultGroupOption; - - if (findGroupOptionMetadata(albumGroupOption).isDisabled()) { - return defaultGroupOption; - } - return albumGroupOption; -}; - /** * ---------------------------- * Places Groups Collapse/Expand diff --git a/web/src/routes/(user)/places/PlacesControls.svelte b/web/src/routes/(user)/places/PlacesControls.svelte index ae1308fdd3..f3fa38cb28 100644 --- a/web/src/routes/(user)/places/PlacesControls.svelte +++ b/web/src/routes/(user)/places/PlacesControls.svelte @@ -1,24 +1,11 @@ - - - ({ - title: placesGroupByNames[id], - icon: groupIcon, - disabled: isDisabled(), - })} -/> +
+