Merge branch 'main' of https://github.com/immich-app/immich into fix/modal-sticky-bottom
This commit is contained in:
@@ -8,13 +8,11 @@ Immich supports the option to send notifications via Email for the following eve
|
||||
|
||||
## SMTP settings
|
||||
|
||||
You can access the settings panel from the web at `Administration -> Settings -> Notification settings`
|
||||
You can access the settings panel from the web at `Administration -> Settings -> Notification settings`.
|
||||
|
||||
Under Email, enter the following details to connect with SMTP servers.
|
||||
Under Email, enter the required details to connect with an SMTP server.
|
||||
|
||||
You can use the following [guide](/docs/guides/smtp-gmail) to use Gmail's SMTP server.
|
||||
|
||||
<img src={require('./img/email-settings.png').default} width="80%" title="SMTP settings" />
|
||||
You can use [this guide](/docs/guides/smtp-gmail) to use Gmail's SMTP server.
|
||||
|
||||
## User's notifications settings
|
||||
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 218 KiB |
@@ -80,6 +80,10 @@ The Compose file './docker-compose.yml' is invalid because:
|
||||
See the previous paragraph about installing from the official docker repository.
|
||||
:::
|
||||
|
||||
:::info Health check start interval
|
||||
If you get an error `can't set healthcheck.start_interval as feature require Docker Engine v25 or later`, it helps to comment out the line for `start_interval` in the `database` section of the `docker-compose.yml` file.
|
||||
:::
|
||||
|
||||
:::tip
|
||||
For more information on how to use the application, please refer to the [Post Installation](/docs/install/post-install.mdx) guide.
|
||||
:::
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
ARG DEVICE=cpu
|
||||
|
||||
FROM python:3.11-bookworm@sha256:3cd9b520be95c671135ea1318f32be6912876024ee16d0f472669d3878801651 AS builder-cpu
|
||||
FROM python:3.11-bookworm@sha256:157a371e60389919fe4a72dff71ce86eaa5234f59114c23b0b346d0d02c74d39 AS builder-cpu
|
||||
|
||||
FROM builder-cpu AS builder-openvino
|
||||
|
||||
@@ -34,7 +34,7 @@ RUN python3 -m venv /opt/venv
|
||||
COPY poetry.lock pyproject.toml ./
|
||||
RUN poetry install --sync --no-interaction --no-ansi --no-root --with ${DEVICE} --without dev
|
||||
|
||||
FROM python:3.11-slim-bookworm@sha256:50ec89bdac0a845ec1751f91cb6187a3d8adb2b919d6e82d17acf48d1a9743fc AS prod-cpu
|
||||
FROM python:3.11-slim-bookworm@sha256:669bbd08353610485a94d5d0c976b4b6498c55280fe42c00f7581f85ee9f3121 AS prod-cpu
|
||||
|
||||
FROM prod-cpu AS prod-openvino
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM mambaorg/micromamba:bookworm-slim@sha256:b10f75974a30a6889b03519ac48d3e1510fd13d0689468c2c443033a15d84f1b AS builder
|
||||
FROM mambaorg/micromamba:bookworm-slim@sha256:5f32c5742e2248f2ca07ccae6861371321aba37372bf8e1a80d6f728f1ab4418 AS builder
|
||||
|
||||
ENV TRANSFORMERS_CACHE=/cache \
|
||||
PYTHONDONTWRITEBYTECODE=1 \
|
||||
|
||||
18
machine-learning/poetry.lock
generated
18
machine-learning/poetry.lock
generated
@@ -680,13 +680,13 @@ test = ["pytest (>=6)"]
|
||||
|
||||
[[package]]
|
||||
name = "fastapi-slim"
|
||||
version = "0.114.0"
|
||||
version = "0.114.2"
|
||||
description = "FastAPI framework, high performance, easy to learn, fast to code, ready for production"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "fastapi_slim-0.114.0-py3-none-any.whl", hash = "sha256:83c8e95301c75c6575f7f6c4b885bf42a4c0b4a85e936e2faca25055470d0afe"},
|
||||
{file = "fastapi_slim-0.114.0.tar.gz", hash = "sha256:2299d5e0b8818f264725bd13dd91c80b904589be06c98c3d8115132576e5e2dd"},
|
||||
{file = "fastapi_slim-0.114.2-py3-none-any.whl", hash = "sha256:52ae76c53a30ad0fa96beb84c1bf4bef9c72e88c2f7c0473e836f01d7ac3ca6b"},
|
||||
{file = "fastapi_slim-0.114.2.tar.gz", hash = "sha256:76d0a450826fb0fa740268be55ef04c44807da87a94fbbf5f16338b5a4a2d321"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
@@ -2473,13 +2473,13 @@ files = [
|
||||
|
||||
[[package]]
|
||||
name = "pytest"
|
||||
version = "8.3.2"
|
||||
version = "8.3.3"
|
||||
description = "pytest: simple powerful testing with Python"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "pytest-8.3.2-py3-none-any.whl", hash = "sha256:4ba08f9ae7dcf84ded419494d229b48d0903ea6407b030eaec46df5e6a73bba5"},
|
||||
{file = "pytest-8.3.2.tar.gz", hash = "sha256:c132345d12ce551242c87269de812483f5bcc87cdbb4722e48487ba194f9fdce"},
|
||||
{file = "pytest-8.3.3-py3-none-any.whl", hash = "sha256:a6853c7375b2663155079443d2e45de913a911a11d669df02a50814944db57b2"},
|
||||
{file = "pytest-8.3.3.tar.gz", hash = "sha256:70b98107bd648308a7952b06e6ca9a50bc660be218d53c257cc1fc94fda10181"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
@@ -2816,13 +2816,13 @@ use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"]
|
||||
|
||||
[[package]]
|
||||
name = "rich"
|
||||
version = "13.8.0"
|
||||
version = "13.8.1"
|
||||
description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal"
|
||||
optional = false
|
||||
python-versions = ">=3.7.0"
|
||||
files = [
|
||||
{file = "rich-13.8.0-py3-none-any.whl", hash = "sha256:2e85306a063b9492dffc86278197a60cbece75bcb766022f3436f567cae11bdc"},
|
||||
{file = "rich-13.8.0.tar.gz", hash = "sha256:a5ac1f1cd448ade0d59cc3356f7db7a7ccda2c8cbae9c7a90c28ff463d3e91f4"},
|
||||
{file = "rich-13.8.1-py3-none-any.whl", hash = "sha256:1760a3c0848469b97b558fc61c85233e3dafb69c7a071b4d60c38099d3cd4c06"},
|
||||
{file = "rich-13.8.1.tar.gz", hash = "sha256:8260cda28e3db6bf04d2d1ef4dbc03ba80a824c88b0e7668a0f23126a424844a"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
|
||||
@@ -164,12 +164,13 @@ class Album {
|
||||
}
|
||||
|
||||
extension AssetsHelper on IsarCollection<Album> {
|
||||
Future<void> store(Album a) async {
|
||||
Future<Album> store(Album a) async {
|
||||
await put(a);
|
||||
await a.owner.save();
|
||||
await a.thumbnail.save();
|
||||
await a.sharedUsers.save();
|
||||
await a.assets.save();
|
||||
return a;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
21
mobile/lib/interfaces/album.interface.dart
Normal file
21
mobile/lib/interfaces/album.interface.dart
Normal file
@@ -0,0 +1,21 @@
|
||||
import 'package:immich_mobile/entities/album.entity.dart';
|
||||
import 'package:immich_mobile/entities/asset.entity.dart';
|
||||
import 'package:immich_mobile/entities/user.entity.dart';
|
||||
|
||||
abstract interface class IAlbumRepository {
|
||||
Future<int> count({bool? local});
|
||||
Future<Album> create(Album album);
|
||||
Future<Album?> getById(int id);
|
||||
Future<Album?> getByName(
|
||||
String name, {
|
||||
bool? shared,
|
||||
bool? remote,
|
||||
});
|
||||
Future<Album> update(Album album);
|
||||
Future<void> delete(int albumId);
|
||||
Future<List<Album>> getAll({bool? shared});
|
||||
Future<void> removeUsers(Album album, List<User> users);
|
||||
Future<void> addAssets(Album album, List<Asset> assets);
|
||||
Future<void> removeAssets(Album album, List<Asset> assets);
|
||||
Future<Album> recalculateMetadata(Album album);
|
||||
}
|
||||
8
mobile/lib/interfaces/asset.interface.dart
Normal file
8
mobile/lib/interfaces/asset.interface.dart
Normal file
@@ -0,0 +1,8 @@
|
||||
import 'package:immich_mobile/entities/album.entity.dart';
|
||||
import 'package:immich_mobile/entities/asset.entity.dart';
|
||||
import 'package:immich_mobile/entities/user.entity.dart';
|
||||
|
||||
abstract interface class IAssetRepository {
|
||||
Future<List<Asset>> getByAlbum(Album album, {User? notOwnedBy});
|
||||
Future<void> deleteById(List<int> ids);
|
||||
}
|
||||
5
mobile/lib/interfaces/backup.interface.dart
Normal file
5
mobile/lib/interfaces/backup.interface.dart
Normal file
@@ -0,0 +1,5 @@
|
||||
import 'package:immich_mobile/entities/backup_album.entity.dart';
|
||||
|
||||
abstract interface class IBackupRepository {
|
||||
Future<List<String>> getIdsBySelection(BackupSelection backup);
|
||||
}
|
||||
5
mobile/lib/interfaces/user.interface.dart
Normal file
5
mobile/lib/interfaces/user.interface.dart
Normal file
@@ -0,0 +1,5 @@
|
||||
import 'package:immich_mobile/entities/user.entity.dart';
|
||||
|
||||
abstract interface class IUserRepository {
|
||||
Future<List<User>> getByIds(List<String> ids);
|
||||
}
|
||||
85
mobile/lib/repositories/album.repository.dart
Normal file
85
mobile/lib/repositories/album.repository.dart
Normal file
@@ -0,0 +1,85 @@
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/entities/album.entity.dart';
|
||||
import 'package:immich_mobile/entities/asset.entity.dart';
|
||||
import 'package:immich_mobile/entities/user.entity.dart';
|
||||
import 'package:immich_mobile/interfaces/album.interface.dart';
|
||||
import 'package:immich_mobile/providers/db.provider.dart';
|
||||
import 'package:isar/isar.dart';
|
||||
|
||||
final albumRepositoryProvider =
|
||||
Provider((ref) => AlbumRepository(ref.watch(dbProvider)));
|
||||
|
||||
class AlbumRepository implements IAlbumRepository {
|
||||
final Isar _db;
|
||||
|
||||
AlbumRepository(
|
||||
this._db,
|
||||
);
|
||||
|
||||
@override
|
||||
Future<int> count({bool? local}) {
|
||||
if (local == true) return _db.albums.where().localIdIsNotNull().count();
|
||||
if (local == false) return _db.albums.where().remoteIdIsNotNull().count();
|
||||
return _db.albums.count();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Album> create(Album album) =>
|
||||
_db.writeTxn(() => _db.albums.store(album));
|
||||
|
||||
@override
|
||||
Future<Album?> getByName(String name, {bool? shared, bool? remote}) {
|
||||
var query = _db.albums.filter().nameEqualTo(name);
|
||||
if (shared != null) {
|
||||
query = query.sharedEqualTo(shared);
|
||||
}
|
||||
if (remote == true) {
|
||||
query = query.localIdIsNull();
|
||||
} else if (remote == false) {
|
||||
query = query.remoteIdIsNull();
|
||||
}
|
||||
return query.findFirst();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Album> update(Album album) =>
|
||||
_db.writeTxn(() => _db.albums.store(album));
|
||||
|
||||
@override
|
||||
Future<void> delete(int albumId) =>
|
||||
_db.writeTxn(() => _db.albums.delete(albumId));
|
||||
|
||||
@override
|
||||
Future<List<Album>> getAll({bool? shared}) {
|
||||
final baseQuery = _db.albums.filter();
|
||||
QueryBuilder<Album, Album, QAfterFilterCondition>? query;
|
||||
if (shared != null) {
|
||||
query = baseQuery.sharedEqualTo(true);
|
||||
}
|
||||
return query?.findAll() ?? _db.albums.where().findAll();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Album?> getById(int id) => _db.albums.get(id);
|
||||
|
||||
@override
|
||||
Future<void> removeUsers(Album album, List<User> users) =>
|
||||
_db.writeTxn(() => album.sharedUsers.update(unlink: users));
|
||||
|
||||
@override
|
||||
Future<void> addAssets(Album album, List<Asset> assets) =>
|
||||
_db.writeTxn(() => album.assets.update(link: assets));
|
||||
|
||||
@override
|
||||
Future<void> removeAssets(Album album, List<Asset> assets) =>
|
||||
_db.writeTxn(() => album.assets.update(unlink: assets));
|
||||
|
||||
@override
|
||||
Future<Album> recalculateMetadata(Album album) async {
|
||||
album.startDate = await album.assets.filter().fileCreatedAtProperty().min();
|
||||
album.endDate = await album.assets.filter().fileCreatedAtProperty().max();
|
||||
album.lastModifiedAssetTimestamp =
|
||||
await album.assets.filter().updatedAtProperty().max();
|
||||
return album;
|
||||
}
|
||||
}
|
||||
31
mobile/lib/repositories/asset.repository.dart
Normal file
31
mobile/lib/repositories/asset.repository.dart
Normal file
@@ -0,0 +1,31 @@
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/entities/album.entity.dart';
|
||||
import 'package:immich_mobile/entities/asset.entity.dart';
|
||||
import 'package:immich_mobile/entities/user.entity.dart';
|
||||
import 'package:immich_mobile/interfaces/asset.interface.dart';
|
||||
import 'package:immich_mobile/providers/db.provider.dart';
|
||||
import 'package:isar/isar.dart';
|
||||
|
||||
final assetRepositoryProvider =
|
||||
Provider((ref) => AssetRepository(ref.watch(dbProvider)));
|
||||
|
||||
class AssetRepository implements IAssetRepository {
|
||||
final Isar _db;
|
||||
|
||||
AssetRepository(
|
||||
this._db,
|
||||
);
|
||||
|
||||
@override
|
||||
Future<List<Asset>> getByAlbum(Album album, {User? notOwnedBy}) {
|
||||
var query = album.assets.filter();
|
||||
if (notOwnedBy != null) {
|
||||
query = query.not().ownerIdEqualTo(notOwnedBy.isarId);
|
||||
}
|
||||
return query.findAll();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> deleteById(List<int> ids) =>
|
||||
_db.writeTxn(() => _db.assets.deleteAll(ids));
|
||||
}
|
||||
20
mobile/lib/repositories/backup.repository.dart
Normal file
20
mobile/lib/repositories/backup.repository.dart
Normal file
@@ -0,0 +1,20 @@
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/entities/backup_album.entity.dart';
|
||||
import 'package:immich_mobile/interfaces/backup.interface.dart';
|
||||
import 'package:immich_mobile/providers/db.provider.dart';
|
||||
import 'package:isar/isar.dart';
|
||||
|
||||
final backupRepositoryProvider =
|
||||
Provider((ref) => BackupRepository(ref.watch(dbProvider)));
|
||||
|
||||
class BackupRepository implements IBackupRepository {
|
||||
final Isar _db;
|
||||
|
||||
BackupRepository(
|
||||
this._db,
|
||||
);
|
||||
|
||||
@override
|
||||
Future<List<String>> getIdsBySelection(BackupSelection backup) =>
|
||||
_db.backupAlbums.filter().selectionEqualTo(backup).idProperty().findAll();
|
||||
}
|
||||
20
mobile/lib/repositories/user.repository.dart
Normal file
20
mobile/lib/repositories/user.repository.dart
Normal file
@@ -0,0 +1,20 @@
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/entities/user.entity.dart';
|
||||
import 'package:immich_mobile/interfaces/user.interface.dart';
|
||||
import 'package:immich_mobile/providers/db.provider.dart';
|
||||
import 'package:isar/isar.dart';
|
||||
|
||||
final userRepositoryProvider =
|
||||
Provider((ref) => UserRepository(ref.watch(dbProvider)));
|
||||
|
||||
class UserRepository implements IUserRepository {
|
||||
final Isar _db;
|
||||
|
||||
UserRepository(
|
||||
this._db,
|
||||
);
|
||||
|
||||
@override
|
||||
Future<List<User>> getByIds(List<String> ids) async =>
|
||||
(await _db.users.getAllById(ids)).cast();
|
||||
}
|
||||
@@ -5,6 +5,10 @@ import 'dart:io';
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/interfaces/album.interface.dart';
|
||||
import 'package:immich_mobile/interfaces/asset.interface.dart';
|
||||
import 'package:immich_mobile/interfaces/backup.interface.dart';
|
||||
import 'package:immich_mobile/interfaces/user.interface.dart';
|
||||
import 'package:immich_mobile/models/albums/album_add_asset_response.model.dart';
|
||||
import 'package:immich_mobile/entities/backup_album.entity.dart';
|
||||
import 'package:immich_mobile/entities/album.entity.dart';
|
||||
@@ -12,11 +16,13 @@ import 'package:immich_mobile/entities/asset.entity.dart';
|
||||
import 'package:immich_mobile/entities/store.entity.dart';
|
||||
import 'package:immich_mobile/entities/user.entity.dart';
|
||||
import 'package:immich_mobile/providers/api.provider.dart';
|
||||
import 'package:immich_mobile/providers/db.provider.dart';
|
||||
import 'package:immich_mobile/repositories/album.repository.dart';
|
||||
import 'package:immich_mobile/repositories/asset.repository.dart';
|
||||
import 'package:immich_mobile/repositories/backup.repository.dart';
|
||||
import 'package:immich_mobile/repositories/user.repository.dart';
|
||||
import 'package:immich_mobile/services/api.service.dart';
|
||||
import 'package:immich_mobile/services/sync.service.dart';
|
||||
import 'package:immich_mobile/services/user.service.dart';
|
||||
import 'package:isar/isar.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:openapi/api.dart';
|
||||
import 'package:photo_manager/photo_manager.dart';
|
||||
@@ -26,7 +32,10 @@ final albumServiceProvider = Provider(
|
||||
ref.watch(apiServiceProvider),
|
||||
ref.watch(userServiceProvider),
|
||||
ref.watch(syncServiceProvider),
|
||||
ref.watch(dbProvider),
|
||||
ref.watch(albumRepositoryProvider),
|
||||
ref.watch(assetRepositoryProvider),
|
||||
ref.watch(userRepositoryProvider),
|
||||
ref.watch(backupRepositoryProvider),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -34,7 +43,10 @@ class AlbumService {
|
||||
final ApiService _apiService;
|
||||
final UserService _userService;
|
||||
final SyncService _syncService;
|
||||
final Isar _db;
|
||||
final IAlbumRepository _albumRepository;
|
||||
final IAssetRepository _assetRepository;
|
||||
final IUserRepository _userRepository;
|
||||
final IBackupRepository _backupAlbumRepository;
|
||||
final Logger _log = Logger('AlbumService');
|
||||
Completer<bool> _localCompleter = Completer()..complete(false);
|
||||
Completer<bool> _remoteCompleter = Completer()..complete(false);
|
||||
@@ -43,16 +55,12 @@ class AlbumService {
|
||||
this._apiService,
|
||||
this._userService,
|
||||
this._syncService,
|
||||
this._db,
|
||||
this._albumRepository,
|
||||
this._assetRepository,
|
||||
this._userRepository,
|
||||
this._backupAlbumRepository,
|
||||
);
|
||||
|
||||
QueryBuilder<BackupAlbum, BackupAlbum, QAfterFilterCondition>
|
||||
selectedAlbumsQuery() =>
|
||||
_db.backupAlbums.filter().selectionEqualTo(BackupSelection.select);
|
||||
QueryBuilder<BackupAlbum, BackupAlbum, QAfterFilterCondition>
|
||||
excludedAlbumsQuery() =>
|
||||
_db.backupAlbums.filter().selectionEqualTo(BackupSelection.exclude);
|
||||
|
||||
/// Checks all selected device albums for changes of albums and their assets
|
||||
/// Updates the local database and returns `true` if there were any changes
|
||||
Future<bool> refreshDeviceAlbums() async {
|
||||
@@ -65,12 +73,12 @@ class AlbumService {
|
||||
final Stopwatch sw = Stopwatch()..start();
|
||||
bool changes = false;
|
||||
try {
|
||||
final List<String> excludedIds =
|
||||
await excludedAlbumsQuery().idProperty().findAll();
|
||||
final List<String> selectedIds =
|
||||
await selectedAlbumsQuery().idProperty().findAll();
|
||||
final List<String> excludedIds = await _backupAlbumRepository
|
||||
.getIdsBySelection(BackupSelection.exclude);
|
||||
final List<String> selectedIds = await _backupAlbumRepository
|
||||
.getIdsBySelection(BackupSelection.select);
|
||||
if (selectedIds.isEmpty) {
|
||||
final numLocal = await _db.albums.where().localIdIsNotNull().count();
|
||||
final numLocal = await _albumRepository.count(local: true);
|
||||
if (numLocal > 0) {
|
||||
_syncService.removeAllLocalAlbumsAndAssets();
|
||||
}
|
||||
@@ -194,8 +202,8 @@ class AlbumService {
|
||||
),
|
||||
);
|
||||
if (remote != null) {
|
||||
Album album = await Album.remote(remote);
|
||||
await _db.writeTxn(() => _db.albums.store(album));
|
||||
final Album album = await Album.remote(remote);
|
||||
await _albumRepository.create(album);
|
||||
return album;
|
||||
}
|
||||
} catch (e) {
|
||||
@@ -212,8 +220,7 @@ class AlbumService {
|
||||
for (int round = 0;; round++) {
|
||||
final proposedName = "$baseName${round == 0 ? "" : " ($round)"}";
|
||||
|
||||
if (null ==
|
||||
await _db.albums.filter().nameEqualTo(proposedName).findFirst()) {
|
||||
if (null == await _albumRepository.getByName(proposedName)) {
|
||||
return proposedName;
|
||||
}
|
||||
}
|
||||
@@ -268,20 +275,15 @@ class AlbumService {
|
||||
|
||||
Future<void> _updateAssets(
|
||||
int albumId, {
|
||||
Iterable<Asset> add = const [],
|
||||
Iterable<Asset> remove = const [],
|
||||
}) {
|
||||
return _db.writeTxn(() async {
|
||||
final album = await _db.albums.get(albumId);
|
||||
if (album == null) return;
|
||||
await album.assets.update(link: add, unlink: remove);
|
||||
album.startDate =
|
||||
await album.assets.filter().fileCreatedAtProperty().min();
|
||||
album.endDate = await album.assets.filter().fileCreatedAtProperty().max();
|
||||
album.lastModifiedAssetTimestamp =
|
||||
await album.assets.filter().updatedAtProperty().max();
|
||||
await _db.albums.put(album);
|
||||
});
|
||||
List<Asset> add = const [],
|
||||
List<Asset> remove = const [],
|
||||
}) async {
|
||||
final album = await _albumRepository.getById(albumId);
|
||||
if (album == null) return;
|
||||
await _albumRepository.addAssets(album, add);
|
||||
await _albumRepository.removeAssets(album, remove);
|
||||
await _albumRepository.recalculateMetadata(album);
|
||||
await _albumRepository.update(album);
|
||||
}
|
||||
|
||||
Future<bool> addAdditionalUserToAlbum(
|
||||
@@ -298,13 +300,9 @@ class AlbumService {
|
||||
AddUsersDto(albumUsers: albumUsers),
|
||||
);
|
||||
if (result != null) {
|
||||
album.sharedUsers
|
||||
.addAll((await _db.users.getAllById(sharedUserIds)).cast());
|
||||
album.sharedUsers.addAll(await _userRepository.getByIds(sharedUserIds));
|
||||
album.shared = result.shared;
|
||||
await _db.writeTxn(() async {
|
||||
await _db.albums.put(album);
|
||||
await album.sharedUsers.save();
|
||||
});
|
||||
await _albumRepository.update(album);
|
||||
return true;
|
||||
}
|
||||
} catch (e) {
|
||||
@@ -321,7 +319,7 @@ class AlbumService {
|
||||
);
|
||||
if (result != null) {
|
||||
album.activityEnabled = enabled;
|
||||
await _db.writeTxn(() => _db.albums.put(album));
|
||||
await _albumRepository.update(album);
|
||||
return true;
|
||||
}
|
||||
} catch (e) {
|
||||
@@ -332,29 +330,29 @@ class AlbumService {
|
||||
|
||||
Future<bool> deleteAlbum(Album album) async {
|
||||
try {
|
||||
final userId = Store.get(StoreKey.currentUser).isarId;
|
||||
if (album.owner.value?.isarId == userId) {
|
||||
final user = Store.get(StoreKey.currentUser);
|
||||
if (album.owner.value?.isarId == user.isarId) {
|
||||
await _apiService.albumsApi.deleteAlbum(album.remoteId!);
|
||||
}
|
||||
if (album.shared) {
|
||||
final foreignAssets =
|
||||
await album.assets.filter().not().ownerIdEqualTo(userId).findAll();
|
||||
await _db.writeTxn(() => _db.albums.delete(album.id));
|
||||
final List<Album> albums =
|
||||
await _db.albums.filter().sharedEqualTo(true).findAll();
|
||||
await _assetRepository.getByAlbum(album, notOwnedBy: user);
|
||||
await _albumRepository.delete(album.id);
|
||||
|
||||
final List<Album> albums = await _albumRepository.getAll(shared: true);
|
||||
final List<Asset> existing = [];
|
||||
for (Album a in albums) {
|
||||
for (Album album in albums) {
|
||||
existing.addAll(
|
||||
await a.assets.filter().not().ownerIdEqualTo(userId).findAll(),
|
||||
await _assetRepository.getByAlbum(album, notOwnedBy: user),
|
||||
);
|
||||
}
|
||||
final List<int> idsToRemove =
|
||||
_syncService.sharedAssetsToRemove(foreignAssets, existing);
|
||||
if (idsToRemove.isNotEmpty) {
|
||||
await _db.writeTxn(() => _db.assets.deleteAll(idsToRemove));
|
||||
await _assetRepository.deleteById(idsToRemove);
|
||||
}
|
||||
} else {
|
||||
await _db.writeTxn(() => _db.albums.delete(album.id));
|
||||
await _albumRepository.delete(album.id);
|
||||
}
|
||||
return true;
|
||||
} catch (e) {
|
||||
@@ -390,7 +388,7 @@ class AlbumService {
|
||||
: response
|
||||
.where((e) => e.success)
|
||||
.map((e) => assets.firstWhere((a) => a.remoteId == e.id));
|
||||
await _updateAssets(album.id, remove: toRemove);
|
||||
await _updateAssets(album.id, remove: toRemove.toList());
|
||||
return true;
|
||||
}
|
||||
} catch (e) {
|
||||
@@ -410,12 +408,10 @@ class AlbumService {
|
||||
);
|
||||
|
||||
album.sharedUsers.remove(user);
|
||||
await _db.writeTxn(() async {
|
||||
await album.sharedUsers.update(unlink: [user]);
|
||||
final a = await _db.albums.get(album.id);
|
||||
// trigger watcher
|
||||
await _db.albums.put(a!);
|
||||
});
|
||||
await _albumRepository.removeUsers(album, [user]);
|
||||
final a = await _albumRepository.getById(album.id);
|
||||
// trigger watcher
|
||||
await _albumRepository.update(a!);
|
||||
|
||||
return true;
|
||||
} catch (e) {
|
||||
@@ -436,7 +432,7 @@ class AlbumService {
|
||||
),
|
||||
);
|
||||
album.name = newAlbumTitle;
|
||||
await _db.writeTxn(() => _db.albums.put(album));
|
||||
await _albumRepository.update(album);
|
||||
|
||||
return true;
|
||||
} catch (e) {
|
||||
@@ -445,14 +441,8 @@ class AlbumService {
|
||||
}
|
||||
}
|
||||
|
||||
Future<Album?> getAlbumByName(String name, bool remoteOnly) async {
|
||||
return _db.albums
|
||||
.filter()
|
||||
.optional(remoteOnly, (q) => q.localIdIsNull())
|
||||
.nameEqualTo(name)
|
||||
.sharedEqualTo(false)
|
||||
.findFirst();
|
||||
}
|
||||
Future<Album?> getAlbumByName(String name, bool remoteOnly) =>
|
||||
_albumRepository.getByName(name, remote: remoteOnly ? true : null);
|
||||
|
||||
///
|
||||
/// Add the uploaded asset to the selected albums
|
||||
|
||||
@@ -12,6 +12,10 @@ import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/main.dart';
|
||||
import 'package:immich_mobile/models/backup/backup_candidate.model.dart';
|
||||
import 'package:immich_mobile/models/backup/success_upload_asset.model.dart';
|
||||
import 'package:immich_mobile/repositories/album.repository.dart';
|
||||
import 'package:immich_mobile/repositories/asset.repository.dart';
|
||||
import 'package:immich_mobile/repositories/backup.repository.dart';
|
||||
import 'package:immich_mobile/repositories/user.repository.dart';
|
||||
import 'package:immich_mobile/services/album.service.dart';
|
||||
import 'package:immich_mobile/services/hash.service.dart';
|
||||
import 'package:immich_mobile/services/localization.service.dart';
|
||||
@@ -355,12 +359,23 @@ class BackgroundService {
|
||||
AppSettingsService settingService = AppSettingsService();
|
||||
AppSettingsService settingsService = AppSettingsService();
|
||||
PartnerService partnerService = PartnerService(apiService, db);
|
||||
AlbumRepository albumRepository = AlbumRepository(db);
|
||||
AssetRepository assetRepository = AssetRepository(db);
|
||||
UserRepository userRepository = UserRepository(db);
|
||||
BackupRepository backupAlbumRepository = BackupRepository(db);
|
||||
HashService hashService = HashService(db, this);
|
||||
SyncService syncSerive = SyncService(db, hashService);
|
||||
UserService userService =
|
||||
UserService(apiService, db, syncSerive, partnerService);
|
||||
AlbumService albumService =
|
||||
AlbumService(apiService, userService, syncSerive, db);
|
||||
AlbumService albumService = AlbumService(
|
||||
apiService,
|
||||
userService,
|
||||
syncSerive,
|
||||
albumRepository,
|
||||
assetRepository,
|
||||
userRepository,
|
||||
backupAlbumRepository,
|
||||
);
|
||||
BackupService backupService =
|
||||
BackupService(apiService, db, settingService, albumService);
|
||||
|
||||
|
||||
3
mobile/openapi/README.md
generated
3
mobile/openapi/README.md
generated
@@ -124,6 +124,7 @@ Class | Method | HTTP request | Description
|
||||
*FileReportsApi* | [**fixAuditFiles**](doc//FileReportsApi.md#fixauditfiles) | **POST** /reports/fix |
|
||||
*FileReportsApi* | [**getAuditFiles**](doc//FileReportsApi.md#getauditfiles) | **GET** /reports |
|
||||
*FileReportsApi* | [**getFileChecksums**](doc//FileReportsApi.md#getfilechecksums) | **POST** /reports/checksum |
|
||||
*JobsApi* | [**createJob**](doc//JobsApi.md#createjob) | **POST** /jobs |
|
||||
*JobsApi* | [**getAllJobsStatus**](doc//JobsApi.md#getalljobsstatus) | **GET** /jobs |
|
||||
*JobsApi* | [**sendJobCommand**](doc//JobsApi.md#sendjobcommand) | **PUT** /jobs/{id} |
|
||||
*LibrariesApi* | [**createLibrary**](doc//LibrariesApi.md#createlibrary) | **POST** /libraries |
|
||||
@@ -330,6 +331,7 @@ Class | Method | HTTP request | Description
|
||||
- [JobCommand](doc//JobCommand.md)
|
||||
- [JobCommandDto](doc//JobCommandDto.md)
|
||||
- [JobCountsDto](doc//JobCountsDto.md)
|
||||
- [JobCreateDto](doc//JobCreateDto.md)
|
||||
- [JobName](doc//JobName.md)
|
||||
- [JobSettingsDto](doc//JobSettingsDto.md)
|
||||
- [JobStatusDto](doc//JobStatusDto.md)
|
||||
@@ -341,6 +343,7 @@ Class | Method | HTTP request | Description
|
||||
- [LoginCredentialDto](doc//LoginCredentialDto.md)
|
||||
- [LoginResponseDto](doc//LoginResponseDto.md)
|
||||
- [LogoutResponseDto](doc//LogoutResponseDto.md)
|
||||
- [ManualJobName](doc//ManualJobName.md)
|
||||
- [MapMarkerResponseDto](doc//MapMarkerResponseDto.md)
|
||||
- [MapReverseGeocodeResponseDto](doc//MapReverseGeocodeResponseDto.md)
|
||||
- [MapTheme](doc//MapTheme.md)
|
||||
|
||||
2
mobile/openapi/lib/api.dart
generated
2
mobile/openapi/lib/api.dart
generated
@@ -144,6 +144,7 @@ part 'model/image_format.dart';
|
||||
part 'model/job_command.dart';
|
||||
part 'model/job_command_dto.dart';
|
||||
part 'model/job_counts_dto.dart';
|
||||
part 'model/job_create_dto.dart';
|
||||
part 'model/job_name.dart';
|
||||
part 'model/job_settings_dto.dart';
|
||||
part 'model/job_status_dto.dart';
|
||||
@@ -155,6 +156,7 @@ part 'model/log_level.dart';
|
||||
part 'model/login_credential_dto.dart';
|
||||
part 'model/login_response_dto.dart';
|
||||
part 'model/logout_response_dto.dart';
|
||||
part 'model/manual_job_name.dart';
|
||||
part 'model/map_marker_response_dto.dart';
|
||||
part 'model/map_reverse_geocode_response_dto.dart';
|
||||
part 'model/map_theme.dart';
|
||||
|
||||
39
mobile/openapi/lib/api/jobs_api.dart
generated
39
mobile/openapi/lib/api/jobs_api.dart
generated
@@ -16,6 +16,45 @@ class JobsApi {
|
||||
|
||||
final ApiClient apiClient;
|
||||
|
||||
/// Performs an HTTP 'POST /jobs' operation and returns the [Response].
|
||||
/// Parameters:
|
||||
///
|
||||
/// * [JobCreateDto] jobCreateDto (required):
|
||||
Future<Response> createJobWithHttpInfo(JobCreateDto jobCreateDto,) async {
|
||||
// ignore: prefer_const_declarations
|
||||
final path = r'/jobs';
|
||||
|
||||
// ignore: prefer_final_locals
|
||||
Object? postBody = jobCreateDto;
|
||||
|
||||
final queryParams = <QueryParam>[];
|
||||
final headerParams = <String, String>{};
|
||||
final formParams = <String, String>{};
|
||||
|
||||
const contentTypes = <String>['application/json'];
|
||||
|
||||
|
||||
return apiClient.invokeAPI(
|
||||
path,
|
||||
'POST',
|
||||
queryParams,
|
||||
postBody,
|
||||
headerParams,
|
||||
formParams,
|
||||
contentTypes.isEmpty ? null : contentTypes.first,
|
||||
);
|
||||
}
|
||||
|
||||
/// Parameters:
|
||||
///
|
||||
/// * [JobCreateDto] jobCreateDto (required):
|
||||
Future<void> createJob(JobCreateDto jobCreateDto,) async {
|
||||
final response = await createJobWithHttpInfo(jobCreateDto,);
|
||||
if (response.statusCode >= HttpStatus.badRequest) {
|
||||
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
|
||||
}
|
||||
}
|
||||
|
||||
/// Performs an HTTP 'GET /jobs' operation and returns the [Response].
|
||||
Future<Response> getAllJobsStatusWithHttpInfo() async {
|
||||
// ignore: prefer_const_declarations
|
||||
|
||||
4
mobile/openapi/lib/api_client.dart
generated
4
mobile/openapi/lib/api_client.dart
generated
@@ -343,6 +343,8 @@ class ApiClient {
|
||||
return JobCommandDto.fromJson(value);
|
||||
case 'JobCountsDto':
|
||||
return JobCountsDto.fromJson(value);
|
||||
case 'JobCreateDto':
|
||||
return JobCreateDto.fromJson(value);
|
||||
case 'JobName':
|
||||
return JobNameTypeTransformer().decode(value);
|
||||
case 'JobSettingsDto':
|
||||
@@ -365,6 +367,8 @@ class ApiClient {
|
||||
return LoginResponseDto.fromJson(value);
|
||||
case 'LogoutResponseDto':
|
||||
return LogoutResponseDto.fromJson(value);
|
||||
case 'ManualJobName':
|
||||
return ManualJobNameTypeTransformer().decode(value);
|
||||
case 'MapMarkerResponseDto':
|
||||
return MapMarkerResponseDto.fromJson(value);
|
||||
case 'MapReverseGeocodeResponseDto':
|
||||
|
||||
3
mobile/openapi/lib/api_helper.dart
generated
3
mobile/openapi/lib/api_helper.dart
generated
@@ -97,6 +97,9 @@ String parameterToString(dynamic value) {
|
||||
if (value is LogLevel) {
|
||||
return LogLevelTypeTransformer().encode(value).toString();
|
||||
}
|
||||
if (value is ManualJobName) {
|
||||
return ManualJobNameTypeTransformer().encode(value).toString();
|
||||
}
|
||||
if (value is MapTheme) {
|
||||
return MapThemeTypeTransformer().encode(value).toString();
|
||||
}
|
||||
|
||||
98
mobile/openapi/lib/model/job_create_dto.dart
generated
Normal file
98
mobile/openapi/lib/model/job_create_dto.dart
generated
Normal file
@@ -0,0 +1,98 @@
|
||||
//
|
||||
// AUTO-GENERATED FILE, DO NOT MODIFY!
|
||||
//
|
||||
// @dart=2.18
|
||||
|
||||
// ignore_for_file: unused_element, unused_import
|
||||
// ignore_for_file: always_put_required_named_parameters_first
|
||||
// ignore_for_file: constant_identifier_names
|
||||
// ignore_for_file: lines_longer_than_80_chars
|
||||
|
||||
part of openapi.api;
|
||||
|
||||
class JobCreateDto {
|
||||
/// Returns a new [JobCreateDto] instance.
|
||||
JobCreateDto({
|
||||
required this.name,
|
||||
});
|
||||
|
||||
ManualJobName name;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) => identical(this, other) || other is JobCreateDto &&
|
||||
other.name == name;
|
||||
|
||||
@override
|
||||
int get hashCode =>
|
||||
// ignore: unnecessary_parenthesis
|
||||
(name.hashCode);
|
||||
|
||||
@override
|
||||
String toString() => 'JobCreateDto[name=$name]';
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final json = <String, dynamic>{};
|
||||
json[r'name'] = this.name;
|
||||
return json;
|
||||
}
|
||||
|
||||
/// Returns a new [JobCreateDto] instance and imports its values from
|
||||
/// [value] if it's a [Map], null otherwise.
|
||||
// ignore: prefer_constructors_over_static_methods
|
||||
static JobCreateDto? fromJson(dynamic value) {
|
||||
if (value is Map) {
|
||||
final json = value.cast<String, dynamic>();
|
||||
|
||||
return JobCreateDto(
|
||||
name: ManualJobName.fromJson(json[r'name'])!,
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static List<JobCreateDto> listFromJson(dynamic json, {bool growable = false,}) {
|
||||
final result = <JobCreateDto>[];
|
||||
if (json is List && json.isNotEmpty) {
|
||||
for (final row in json) {
|
||||
final value = JobCreateDto.fromJson(row);
|
||||
if (value != null) {
|
||||
result.add(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result.toList(growable: growable);
|
||||
}
|
||||
|
||||
static Map<String, JobCreateDto> mapFromJson(dynamic json) {
|
||||
final map = <String, JobCreateDto>{};
|
||||
if (json is Map && json.isNotEmpty) {
|
||||
json = json.cast<String, dynamic>(); // ignore: parameter_assignments
|
||||
for (final entry in json.entries) {
|
||||
final value = JobCreateDto.fromJson(entry.value);
|
||||
if (value != null) {
|
||||
map[entry.key] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
// maps a json object with a list of JobCreateDto-objects as value to a dart map
|
||||
static Map<String, List<JobCreateDto>> mapListFromJson(dynamic json, {bool growable = false,}) {
|
||||
final map = <String, List<JobCreateDto>>{};
|
||||
if (json is Map && json.isNotEmpty) {
|
||||
// ignore: parameter_assignments
|
||||
json = json.cast<String, dynamic>();
|
||||
for (final entry in json.entries) {
|
||||
map[entry.key] = JobCreateDto.listFromJson(entry.value, growable: growable,);
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
/// The list of required keys that must be present in a JSON.
|
||||
static const requiredKeys = <String>{
|
||||
'name',
|
||||
};
|
||||
}
|
||||
|
||||
88
mobile/openapi/lib/model/manual_job_name.dart
generated
Normal file
88
mobile/openapi/lib/model/manual_job_name.dart
generated
Normal file
@@ -0,0 +1,88 @@
|
||||
//
|
||||
// AUTO-GENERATED FILE, DO NOT MODIFY!
|
||||
//
|
||||
// @dart=2.18
|
||||
|
||||
// ignore_for_file: unused_element, unused_import
|
||||
// ignore_for_file: always_put_required_named_parameters_first
|
||||
// ignore_for_file: constant_identifier_names
|
||||
// ignore_for_file: lines_longer_than_80_chars
|
||||
|
||||
part of openapi.api;
|
||||
|
||||
|
||||
class ManualJobName {
|
||||
/// Instantiate a new enum with the provided [value].
|
||||
const ManualJobName._(this.value);
|
||||
|
||||
/// The underlying value of this enum member.
|
||||
final String value;
|
||||
|
||||
@override
|
||||
String toString() => value;
|
||||
|
||||
String toJson() => value;
|
||||
|
||||
static const personCleanup = ManualJobName._(r'person-cleanup');
|
||||
static const tagCleanup = ManualJobName._(r'tag-cleanup');
|
||||
static const userCleanup = ManualJobName._(r'user-cleanup');
|
||||
|
||||
/// List of all possible values in this [enum][ManualJobName].
|
||||
static const values = <ManualJobName>[
|
||||
personCleanup,
|
||||
tagCleanup,
|
||||
userCleanup,
|
||||
];
|
||||
|
||||
static ManualJobName? fromJson(dynamic value) => ManualJobNameTypeTransformer().decode(value);
|
||||
|
||||
static List<ManualJobName> listFromJson(dynamic json, {bool growable = false,}) {
|
||||
final result = <ManualJobName>[];
|
||||
if (json is List && json.isNotEmpty) {
|
||||
for (final row in json) {
|
||||
final value = ManualJobName.fromJson(row);
|
||||
if (value != null) {
|
||||
result.add(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result.toList(growable: growable);
|
||||
}
|
||||
}
|
||||
|
||||
/// Transformation class that can [encode] an instance of [ManualJobName] to String,
|
||||
/// and [decode] dynamic data back to [ManualJobName].
|
||||
class ManualJobNameTypeTransformer {
|
||||
factory ManualJobNameTypeTransformer() => _instance ??= const ManualJobNameTypeTransformer._();
|
||||
|
||||
const ManualJobNameTypeTransformer._();
|
||||
|
||||
String encode(ManualJobName data) => data.value;
|
||||
|
||||
/// Decodes a [dynamic value][data] to a ManualJobName.
|
||||
///
|
||||
/// If [allowNull] is true and the [dynamic value][data] cannot be decoded successfully,
|
||||
/// then null is returned. However, if [allowNull] is false and the [dynamic value][data]
|
||||
/// cannot be decoded successfully, then an [UnimplementedError] is thrown.
|
||||
///
|
||||
/// The [allowNull] is very handy when an API changes and a new enum value is added or removed,
|
||||
/// and users are still using an old app with the old code.
|
||||
ManualJobName? decode(dynamic data, {bool allowNull = true}) {
|
||||
if (data != null) {
|
||||
switch (data) {
|
||||
case r'person-cleanup': return ManualJobName.personCleanup;
|
||||
case r'tag-cleanup': return ManualJobName.tagCleanup;
|
||||
case r'user-cleanup': return ManualJobName.userCleanup;
|
||||
default:
|
||||
if (!allowNull) {
|
||||
throw ArgumentError('Unknown enum value to decode: $data');
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Singleton [ManualJobNameTypeTransformer] instance.
|
||||
static ManualJobNameTypeTransformer? _instance;
|
||||
}
|
||||
|
||||
13
mobile/test/repository.mocks.dart
Normal file
13
mobile/test/repository.mocks.dart
Normal file
@@ -0,0 +1,13 @@
|
||||
import 'package:immich_mobile/interfaces/album.interface.dart';
|
||||
import 'package:immich_mobile/interfaces/asset.interface.dart';
|
||||
import 'package:immich_mobile/interfaces/backup.interface.dart';
|
||||
import 'package:immich_mobile/interfaces/user.interface.dart';
|
||||
import 'package:mocktail/mocktail.dart';
|
||||
|
||||
class MockAlbumRepository extends Mock implements IAlbumRepository {}
|
||||
|
||||
class MockAssetRepository extends Mock implements IAssetRepository {}
|
||||
|
||||
class MockUserRepository extends Mock implements IUserRepository {}
|
||||
|
||||
class MockBackupRepository extends Mock implements IBackupRepository {}
|
||||
10
mobile/test/service.mocks.dart
Normal file
10
mobile/test/service.mocks.dart
Normal file
@@ -0,0 +1,10 @@
|
||||
import 'package:immich_mobile/services/api.service.dart';
|
||||
import 'package:immich_mobile/services/sync.service.dart';
|
||||
import 'package:immich_mobile/services/user.service.dart';
|
||||
import 'package:mocktail/mocktail.dart';
|
||||
|
||||
class MockApiService extends Mock implements ApiService {}
|
||||
|
||||
class MockUserService extends Mock implements UserService {}
|
||||
|
||||
class MockSyncService extends Mock implements SyncService {}
|
||||
52
mobile/test/services/album.service.test.dart
Normal file
52
mobile/test/services/album.service.test.dart
Normal file
@@ -0,0 +1,52 @@
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:immich_mobile/entities/backup_album.entity.dart';
|
||||
import 'package:immich_mobile/services/album.service.dart';
|
||||
import 'package:mocktail/mocktail.dart';
|
||||
import '../repository.mocks.dart';
|
||||
import '../service.mocks.dart';
|
||||
|
||||
void main() {
|
||||
late AlbumService sut;
|
||||
late MockApiService apiService;
|
||||
late MockUserService userService;
|
||||
late MockSyncService syncService;
|
||||
late MockAlbumRepository albumRepository;
|
||||
late MockAssetRepository assetRepository;
|
||||
late MockUserRepository userRepository;
|
||||
late MockBackupRepository backupRepository;
|
||||
|
||||
setUp(() {
|
||||
apiService = MockApiService();
|
||||
userService = MockUserService();
|
||||
syncService = MockSyncService();
|
||||
albumRepository = MockAlbumRepository();
|
||||
assetRepository = MockAssetRepository();
|
||||
userRepository = MockUserRepository();
|
||||
backupRepository = MockBackupRepository();
|
||||
|
||||
sut = AlbumService(
|
||||
apiService,
|
||||
userService,
|
||||
syncService,
|
||||
albumRepository,
|
||||
assetRepository,
|
||||
userRepository,
|
||||
backupRepository,
|
||||
);
|
||||
});
|
||||
|
||||
group('refreshDeviceAlbums', () {
|
||||
test('empty selection with one album in db', () async {
|
||||
when(() => backupRepository.getIdsBySelection(BackupSelection.exclude))
|
||||
.thenAnswer((_) async => []);
|
||||
when(() => backupRepository.getIdsBySelection(BackupSelection.select))
|
||||
.thenAnswer((_) async => []);
|
||||
when(() => albumRepository.count(local: true)).thenAnswer((_) async => 1);
|
||||
when(() => syncService.removeAllLocalAlbumsAndAssets())
|
||||
.thenAnswer((_) async => true);
|
||||
final result = await sut.refreshDeviceAlbums();
|
||||
expect(result, false);
|
||||
verify(() => syncService.removeAllLocalAlbumsAndAssets());
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -2561,6 +2561,39 @@
|
||||
"tags": [
|
||||
"Jobs"
|
||||
]
|
||||
},
|
||||
"post": {
|
||||
"operationId": "createJob",
|
||||
"parameters": [],
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/JobCreateDto"
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": true
|
||||
},
|
||||
"responses": {
|
||||
"201": {
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"bearer": []
|
||||
},
|
||||
{
|
||||
"cookie": []
|
||||
},
|
||||
{
|
||||
"api_key": []
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
"Jobs"
|
||||
]
|
||||
}
|
||||
},
|
||||
"/jobs/{id}": {
|
||||
@@ -9269,6 +9302,17 @@
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"JobCreateDto": {
|
||||
"properties": {
|
||||
"name": {
|
||||
"$ref": "#/components/schemas/ManualJobName"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"name"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"JobName": {
|
||||
"enum": [
|
||||
"thumbnailGeneration",
|
||||
@@ -9511,6 +9555,14 @@
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"ManualJobName": {
|
||||
"enum": [
|
||||
"person-cleanup",
|
||||
"tag-cleanup",
|
||||
"user-cleanup"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"MapMarkerResponseDto": {
|
||||
"properties": {
|
||||
"city": {
|
||||
|
||||
@@ -548,6 +548,9 @@ export type AllJobStatusResponseDto = {
|
||||
thumbnailGeneration: JobStatusDto;
|
||||
videoConversion: JobStatusDto;
|
||||
};
|
||||
export type JobCreateDto = {
|
||||
name: ManualJobName;
|
||||
};
|
||||
export type JobCommandDto = {
|
||||
command: JobCommand;
|
||||
force: boolean;
|
||||
@@ -1941,6 +1944,15 @@ export function getAllJobsStatus(opts?: Oazapfts.RequestOpts) {
|
||||
...opts
|
||||
}));
|
||||
}
|
||||
export function createJob({ jobCreateDto }: {
|
||||
jobCreateDto: JobCreateDto;
|
||||
}, opts?: Oazapfts.RequestOpts) {
|
||||
return oazapfts.ok(oazapfts.fetchText("/jobs", oazapfts.json({
|
||||
...opts,
|
||||
method: "POST",
|
||||
body: jobCreateDto
|
||||
})));
|
||||
}
|
||||
export function sendJobCommand({ id, jobCommandDto }: {
|
||||
id: JobName;
|
||||
jobCommandDto: JobCommandDto;
|
||||
@@ -3364,6 +3376,11 @@ export enum EntityType {
|
||||
Asset = "ASSET",
|
||||
Album = "ALBUM"
|
||||
}
|
||||
export enum ManualJobName {
|
||||
PersonCleanup = "person-cleanup",
|
||||
TagCleanup = "tag-cleanup",
|
||||
UserCleanup = "user-cleanup"
|
||||
}
|
||||
export enum JobName {
|
||||
ThumbnailGeneration = "thumbnailGeneration",
|
||||
MetadataExtraction = "metadataExtraction",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Body, Controller, Get, Param, Put } from '@nestjs/common';
|
||||
import { Body, Controller, Get, Param, Post, Put } from '@nestjs/common';
|
||||
import { ApiTags } from '@nestjs/swagger';
|
||||
import { AllJobStatusResponseDto, JobCommandDto, JobIdParamDto, JobStatusDto } from 'src/dtos/job.dto';
|
||||
import { AllJobStatusResponseDto, JobCommandDto, JobCreateDto, JobIdParamDto, JobStatusDto } from 'src/dtos/job.dto';
|
||||
import { Authenticated } from 'src/middleware/auth.guard';
|
||||
import { JobService } from 'src/services/job.service';
|
||||
|
||||
@@ -15,6 +15,12 @@ export class JobController {
|
||||
return this.service.getAllJobsStatus();
|
||||
}
|
||||
|
||||
@Post()
|
||||
@Authenticated({ admin: true })
|
||||
createJob(@Body() dto: JobCreateDto): Promise<void> {
|
||||
return this.service.create(dto);
|
||||
}
|
||||
|
||||
@Put(':id')
|
||||
@Authenticated({ admin: true })
|
||||
sendJobCommand(@Param() { id }: JobIdParamDto, @Body() dto: JobCommandDto): Promise<JobStatusDto> {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { IsEnum, IsNotEmpty } from 'class-validator';
|
||||
import { ManualJobName } from 'src/enum';
|
||||
import { JobCommand, QueueName } from 'src/interfaces/job.interface';
|
||||
import { ValidateBoolean } from 'src/validation';
|
||||
|
||||
@@ -20,6 +21,12 @@ export class JobCommandDto {
|
||||
force!: boolean;
|
||||
}
|
||||
|
||||
export class JobCreateDto {
|
||||
@IsEnum(ManualJobName)
|
||||
@ApiProperty({ type: 'string', enum: ManualJobName, enumName: 'ManualJobName' })
|
||||
name!: ManualJobName;
|
||||
}
|
||||
|
||||
export class JobCountsDto {
|
||||
@ApiProperty({ type: 'integer' })
|
||||
active!: number;
|
||||
|
||||
@@ -186,3 +186,9 @@ export enum SourceType {
|
||||
MACHINE_LEARNING = 'machine-learning',
|
||||
EXIF = 'exif',
|
||||
}
|
||||
|
||||
export enum ManualJobName {
|
||||
PERSON_CLEANUP = 'person-cleanup',
|
||||
TAG_CLEANUP = 'tag-cleanup',
|
||||
USER_CLEANUP = 'user-cleanup',
|
||||
}
|
||||
|
||||
@@ -60,6 +60,9 @@ export enum JobName {
|
||||
STORAGE_TEMPLATE_MIGRATION = 'storage-template-migration',
|
||||
STORAGE_TEMPLATE_MIGRATION_SINGLE = 'storage-template-migration-single',
|
||||
|
||||
// tags
|
||||
TAG_CLEANUP = 'tag-cleanup',
|
||||
|
||||
// migration
|
||||
QUEUE_MIGRATION = 'queue-migration',
|
||||
MIGRATE_ASSET = 'migrate-asset',
|
||||
@@ -262,6 +265,9 @@ export type JobItem =
|
||||
| { name: JobName.CLEAN_OLD_AUDIT_LOGS; data?: IBaseJob }
|
||||
| { name: JobName.CLEAN_OLD_SESSION_TOKENS; data?: IBaseJob }
|
||||
|
||||
// Tags
|
||||
| { name: JobName.TAG_CLEANUP; data?: IBaseJob }
|
||||
|
||||
// Asset Deletion
|
||||
| { name: JobName.PERSON_CLEANUP; data?: IBaseJob }
|
||||
| { name: JobName.ASSET_DELETION; data: IAssetDeleteJob }
|
||||
|
||||
@@ -17,4 +17,5 @@ export interface ITagRepository extends IBulkAsset {
|
||||
|
||||
upsertAssetTags({ assetId, tagIds }: { assetId: string; tagIds: string[] }): Promise<void>;
|
||||
upsertAssetIds(items: AssetTagItem[]): Promise<AssetTagItem[]>;
|
||||
deleteEmptyTags(): Promise<void>;
|
||||
}
|
||||
|
||||
@@ -41,6 +41,9 @@ export const JOBS_TO_QUEUE: Record<JobName, QueueName> = {
|
||||
[JobName.GENERATE_THUMBHASH]: QueueName.THUMBNAIL_GENERATION,
|
||||
[JobName.GENERATE_PERSON_THUMBNAIL]: QueueName.THUMBNAIL_GENERATION,
|
||||
|
||||
// tags
|
||||
[JobName.TAG_CLEANUP]: QueueName.BACKGROUND_TASK,
|
||||
|
||||
// metadata
|
||||
[JobName.QUEUE_METADATA_EXTRACTION]: QueueName.METADATA_EXTRACTION,
|
||||
[JobName.METADATA_EXTRACTION]: QueueName.METADATA_EXTRACTION,
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { InjectDataSource, InjectRepository } from '@nestjs/typeorm';
|
||||
import { Chunked, ChunkedSet, DummyValue, GenerateSql } from 'src/decorators';
|
||||
import { TagEntity } from 'src/entities/tag.entity';
|
||||
import { ILoggerRepository } from 'src/interfaces/logger.interface';
|
||||
import { AssetTagItem, ITagRepository } from 'src/interfaces/tag.interface';
|
||||
import { Instrumentation } from 'src/utils/instrumentation';
|
||||
import { DataSource, In, Repository } from 'typeorm';
|
||||
import { DataSource, In, Repository, TreeRepository } from 'typeorm';
|
||||
|
||||
@Instrumentation()
|
||||
@Injectable()
|
||||
@@ -12,7 +13,11 @@ export class TagRepository implements ITagRepository {
|
||||
constructor(
|
||||
@InjectDataSource() private dataSource: DataSource,
|
||||
@InjectRepository(TagEntity) private repository: Repository<TagEntity>,
|
||||
) {}
|
||||
@InjectRepository(TagEntity) private tree: TreeRepository<TagEntity>,
|
||||
@Inject(ILoggerRepository) private logger: ILoggerRepository,
|
||||
) {
|
||||
this.logger.setContext(TagRepository.name);
|
||||
}
|
||||
|
||||
get(id: string): Promise<TagEntity | null> {
|
||||
return this.repository.findOne({ where: { id } });
|
||||
@@ -174,6 +179,34 @@ export class TagRepository implements ITagRepository {
|
||||
});
|
||||
}
|
||||
|
||||
async deleteEmptyTags() {
|
||||
await this.dataSource.transaction(async (manager) => {
|
||||
const ids = new Set<string>();
|
||||
const tags = await manager.find(TagEntity);
|
||||
for (const tag of tags) {
|
||||
const count = await manager
|
||||
.createQueryBuilder('assets', 'asset')
|
||||
.innerJoin(
|
||||
'asset.tags',
|
||||
'asset_tags',
|
||||
'asset_tags.id IN (SELECT id_descendant FROM tags_closure WHERE id_ancestor = :tagId)',
|
||||
{ tagId: tag.id },
|
||||
)
|
||||
.getCount();
|
||||
|
||||
if (count === 0) {
|
||||
this.logger.debug(`Found empty tag: ${tag.id} - ${tag.value}`);
|
||||
ids.add(tag.id);
|
||||
}
|
||||
}
|
||||
|
||||
if (ids.size > 0) {
|
||||
await manager.delete(TagEntity, { id: In([...ids]) });
|
||||
this.logger.log(`Deleted ${ids.size} empty tags`);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private async save(partial: Partial<TagEntity>): Promise<TagEntity> {
|
||||
const { id } = await this.repository.save(partial);
|
||||
return this.repository.findOneOrFail({ where: { id } });
|
||||
|
||||
@@ -2,8 +2,8 @@ import { BadRequestException, Inject, Injectable } from '@nestjs/common';
|
||||
import { snakeCase } from 'lodash';
|
||||
import { SystemConfigCore } from 'src/cores/system-config.core';
|
||||
import { mapAsset } from 'src/dtos/asset-response.dto';
|
||||
import { AllJobStatusResponseDto, JobCommandDto, JobStatusDto } from 'src/dtos/job.dto';
|
||||
import { AssetType } from 'src/enum';
|
||||
import { AllJobStatusResponseDto, JobCommandDto, JobCreateDto, JobStatusDto } from 'src/dtos/job.dto';
|
||||
import { AssetType, ManualJobName } from 'src/enum';
|
||||
import { IAssetRepository } from 'src/interfaces/asset.interface';
|
||||
import { ClientEvent, IEventRepository } from 'src/interfaces/event.interface';
|
||||
import {
|
||||
@@ -22,6 +22,26 @@ import { IMetricRepository } from 'src/interfaces/metric.interface';
|
||||
import { IPersonRepository } from 'src/interfaces/person.interface';
|
||||
import { ISystemMetadataRepository } from 'src/interfaces/system-metadata.interface';
|
||||
|
||||
const asJobItem = (dto: JobCreateDto): JobItem => {
|
||||
switch (dto.name) {
|
||||
case ManualJobName.TAG_CLEANUP: {
|
||||
return { name: JobName.TAG_CLEANUP };
|
||||
}
|
||||
|
||||
case ManualJobName.PERSON_CLEANUP: {
|
||||
return { name: JobName.PERSON_CLEANUP };
|
||||
}
|
||||
|
||||
case ManualJobName.USER_CLEANUP: {
|
||||
return { name: JobName.USER_DELETE_CHECK };
|
||||
}
|
||||
|
||||
default: {
|
||||
throw new BadRequestException('Invalid job name');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@Injectable()
|
||||
export class JobService {
|
||||
private configCore: SystemConfigCore;
|
||||
@@ -39,6 +59,10 @@ export class JobService {
|
||||
this.configCore = SystemConfigCore.create(systemMetadataRepository, logger);
|
||||
}
|
||||
|
||||
async create(dto: JobCreateDto): Promise<void> {
|
||||
await this.jobRepository.queue(asJobItem(dto));
|
||||
}
|
||||
|
||||
async handleCommand(queueName: QueueName, dto: JobCommandDto): Promise<JobStatusDto> {
|
||||
this.logger.debug(`Handling command: queue=${queueName},force=${dto.force}`);
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ import { SessionService } from 'src/services/session.service';
|
||||
import { SmartInfoService } from 'src/services/smart-info.service';
|
||||
import { StorageTemplateService } from 'src/services/storage-template.service';
|
||||
import { StorageService } from 'src/services/storage.service';
|
||||
import { TagService } from 'src/services/tag.service';
|
||||
import { UserService } from 'src/services/user.service';
|
||||
import { VersionService } from 'src/services/version.service';
|
||||
import { otelShutdown } from 'src/utils/instrumentation';
|
||||
@@ -34,6 +35,7 @@ export class MicroservicesService {
|
||||
private sessionService: SessionService,
|
||||
private storageTemplateService: StorageTemplateService,
|
||||
private storageService: StorageService,
|
||||
private tagService: TagService,
|
||||
private userService: UserService,
|
||||
private duplicateService: DuplicateService,
|
||||
private versionService: VersionService,
|
||||
@@ -93,6 +95,7 @@ export class MicroservicesService {
|
||||
[JobName.NOTIFY_ALBUM_INVITE]: (data) => this.notificationService.handleAlbumInvite(data),
|
||||
[JobName.NOTIFY_ALBUM_UPDATE]: (data) => this.notificationService.handleAlbumUpdate(data),
|
||||
[JobName.NOTIFY_SIGNUP]: (data) => this.notificationService.handleUserSignup(data),
|
||||
[JobName.TAG_CLEANUP]: () => this.tagService.handleTagCleanup(),
|
||||
[JobName.VERSION_CHECK]: () => this.versionService.handleVersionCheck(),
|
||||
});
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ import { TagEntity } from 'src/entities/tag.entity';
|
||||
import { Permission } from 'src/enum';
|
||||
import { IAccessRepository } from 'src/interfaces/access.interface';
|
||||
import { IEventRepository } from 'src/interfaces/event.interface';
|
||||
import { JobStatus } from 'src/interfaces/job.interface';
|
||||
import { AssetTagItem, ITagRepository } from 'src/interfaces/tag.interface';
|
||||
import { checkAccess, requireAccess } from 'src/utils/access';
|
||||
import { addAssets, removeAssets } from 'src/utils/asset.util';
|
||||
@@ -138,6 +139,11 @@ export class TagService {
|
||||
return results;
|
||||
}
|
||||
|
||||
async handleTagCleanup() {
|
||||
await this.repository.deleteEmptyTags();
|
||||
return JobStatus.SUCCESS;
|
||||
}
|
||||
|
||||
private async findOrFail(id: string) {
|
||||
const tag = await this.repository.get(id);
|
||||
if (!tag) {
|
||||
|
||||
@@ -17,5 +17,6 @@ export const newTagRepositoryMock = (): Mocked<ITagRepository> => {
|
||||
addAssetIds: vitest.fn(),
|
||||
removeAssetIds: vitest.fn(),
|
||||
upsertAssetIds: vitest.fn(),
|
||||
deleteEmptyTags: vitest.fn(),
|
||||
};
|
||||
};
|
||||
|
||||
@@ -71,7 +71,7 @@
|
||||
<div>
|
||||
<div in:fade={{ duration: 500 }}>
|
||||
<form autocomplete="off" on:submit|preventDefault>
|
||||
<div class="ml-4 mt-4 flex flex-col gap-4">
|
||||
<div class="ml-4 mt-4 flex flex-col">
|
||||
<SettingAccordion
|
||||
key="oauth"
|
||||
title={$t('admin.oauth_settings')}
|
||||
|
||||
@@ -220,7 +220,7 @@
|
||||
role="listbox"
|
||||
id={listboxId}
|
||||
transition:fly={{ duration: 250 }}
|
||||
class="absolute text-left text-sm w-full max-h-64 overflow-y-auto bg-white dark:bg-gray-800 border-t-0 border-gray-300 dark:border-gray-900 rounded-b-xl z-10"
|
||||
class="absolute text-left text-sm w-full max-h-64 overflow-y-auto bg-white dark:bg-gray-800 border-t-0 border-gray-300 dark:border-gray-900 rounded-b-xl z-[10000]"
|
||||
class:border={isOpen}
|
||||
tabindex="-1"
|
||||
>
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
import { slide } from 'svelte/transition';
|
||||
import { getAccordionState } from './setting-accordion-state.svelte';
|
||||
import { onDestroy } from 'svelte';
|
||||
import Icon from '$lib/components/elements/icon.svelte';
|
||||
|
||||
const accordionState = getAccordionState();
|
||||
|
||||
@@ -10,6 +11,7 @@
|
||||
export let key: string;
|
||||
export let isOpen = $accordionState.has(key);
|
||||
export let autoScrollTo = false;
|
||||
export let icon = '';
|
||||
|
||||
let accordionElement: HTMLDivElement;
|
||||
|
||||
@@ -38,7 +40,12 @@
|
||||
});
|
||||
</script>
|
||||
|
||||
<div class="border-b-[1px] border-gray-200 py-4 dark:border-gray-700" bind:this={accordionElement}>
|
||||
<div
|
||||
class="border rounded-2xl my-4 px-6 py-4 transition-all {isOpen
|
||||
? 'border-immich-primary/40 dark:border-immich-dark-primary/50 shadow-md'
|
||||
: 'dark:border-gray-800'}"
|
||||
bind:this={accordionElement}
|
||||
>
|
||||
<button
|
||||
type="button"
|
||||
aria-expanded={isOpen}
|
||||
@@ -46,12 +53,17 @@
|
||||
class="flex w-full place-items-center justify-between text-left"
|
||||
>
|
||||
<div>
|
||||
<h2 class="font-medium text-immich-primary dark:text-immich-dark-primary">
|
||||
{title}
|
||||
</h2>
|
||||
<div class="flex gap-2 place-items-center">
|
||||
{#if icon}
|
||||
<Icon path={icon} class="text-immich-primary dark:text-immich-dark-primary" size="24" ariaHidden />
|
||||
{/if}
|
||||
<h2 class="font-medium text-immich-primary dark:text-immich-dark-primary">
|
||||
{title}
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
<slot name="subtitle">
|
||||
<p class="text-sm dark:text-immich-dark-fg">{subtitle}</p>
|
||||
<p class="text-sm dark:text-immich-dark-fg mt-1">{subtitle}</p>
|
||||
</slot>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@
|
||||
<section class="my-4">
|
||||
<div in:fade={{ duration: 500 }}>
|
||||
<form autocomplete="off" on:submit|preventDefault>
|
||||
<div class="ml-4 mt-4 flex flex-col gap-4">
|
||||
<div class="ml-4 mt-4 flex flex-col">
|
||||
<SettingAccordion key="folders" title={$t('folders')} subtitle={$t('folders_feature_description')}>
|
||||
<div class="ml-4 mt-6">
|
||||
<SettingSwitch title={$t('enable')} bind:checked={foldersEnabled} />
|
||||
|
||||
@@ -19,6 +19,19 @@
|
||||
import DownloadSettings from '$lib/components/user-settings-page/download-settings.svelte';
|
||||
import UserPurchaseSettings from '$lib/components/user-settings-page/user-purchase-settings.svelte';
|
||||
import FeatureSettings from '$lib/components/user-settings-page/feature-settings.svelte';
|
||||
import {
|
||||
mdiAccountGroupOutline,
|
||||
mdiAccountOutline,
|
||||
mdiApi,
|
||||
mdiBellOutline,
|
||||
mdiCogOutline,
|
||||
mdiDevices,
|
||||
mdiDownload,
|
||||
mdiFeatureSearchOutline,
|
||||
mdiKeyOutline,
|
||||
mdiOnepassword,
|
||||
mdiTwoFactorAuthentication,
|
||||
} from '@mdi/js';
|
||||
|
||||
export let keys: ApiKeyResponseDto[] = [];
|
||||
export let sessions: SessionResponseDto[] = [];
|
||||
@@ -29,23 +42,34 @@
|
||||
</script>
|
||||
|
||||
<SettingAccordionState queryParam={QueryParameter.IS_OPEN}>
|
||||
<SettingAccordion key="app-settings" title={$t('app_settings')} subtitle={$t('manage_the_app_settings')}>
|
||||
<SettingAccordion
|
||||
icon={mdiCogOutline}
|
||||
key="app-settings"
|
||||
title={$t('app_settings')}
|
||||
subtitle={$t('manage_the_app_settings')}
|
||||
>
|
||||
<AppSettings />
|
||||
</SettingAccordion>
|
||||
|
||||
<SettingAccordion key="account" title={$t('account')} subtitle={$t('manage_your_account')}>
|
||||
<SettingAccordion icon={mdiAccountOutline} key="account" title={$t('account')} subtitle={$t('manage_your_account')}>
|
||||
<UserProfileSettings />
|
||||
</SettingAccordion>
|
||||
|
||||
<SettingAccordion key="api-keys" title={$t('api_keys')} subtitle={$t('manage_your_api_keys')}>
|
||||
<SettingAccordion icon={mdiApi} key="api-keys" title={$t('api_keys')} subtitle={$t('manage_your_api_keys')}>
|
||||
<UserAPIKeyList bind:keys />
|
||||
</SettingAccordion>
|
||||
|
||||
<SettingAccordion key="authorized-devices" title={$t('authorized_devices')} subtitle={$t('manage_your_devices')}>
|
||||
<SettingAccordion
|
||||
icon={mdiDevices}
|
||||
key="authorized-devices"
|
||||
title={$t('authorized_devices')}
|
||||
subtitle={$t('manage_your_devices')}
|
||||
>
|
||||
<DeviceList bind:devices={sessions} />
|
||||
</SettingAccordion>
|
||||
|
||||
<SettingAccordion
|
||||
icon={mdiDownload}
|
||||
key="download-settings"
|
||||
title={$t('download_settings')}
|
||||
subtitle={$t('download_settings_description')}
|
||||
@@ -53,16 +77,27 @@
|
||||
<DownloadSettings />
|
||||
</SettingAccordion>
|
||||
|
||||
<SettingAccordion key="feature" title={$t('features')} subtitle={$t('features_setting_description')}>
|
||||
<SettingAccordion
|
||||
icon={mdiFeatureSearchOutline}
|
||||
key="feature"
|
||||
title={$t('features')}
|
||||
subtitle={$t('features_setting_description')}
|
||||
>
|
||||
<FeatureSettings />
|
||||
</SettingAccordion>
|
||||
|
||||
<SettingAccordion key="notifications" title={$t('notifications')} subtitle={$t('notifications_setting_description')}>
|
||||
<SettingAccordion
|
||||
icon={mdiBellOutline}
|
||||
key="notifications"
|
||||
title={$t('notifications')}
|
||||
subtitle={$t('notifications_setting_description')}
|
||||
>
|
||||
<NotificationsSettings />
|
||||
</SettingAccordion>
|
||||
|
||||
{#if $featureFlags.loaded && $featureFlags.oauth}
|
||||
<SettingAccordion
|
||||
icon={mdiTwoFactorAuthentication}
|
||||
key="oauth"
|
||||
title={$t('oauth')}
|
||||
subtitle={$t('manage_your_oauth_connection')}
|
||||
@@ -72,15 +107,21 @@
|
||||
</SettingAccordion>
|
||||
{/if}
|
||||
|
||||
<SettingAccordion key="password" title={$t('password')} subtitle={$t('change_your_password')}>
|
||||
<SettingAccordion icon={mdiOnepassword} key="password" title={$t('password')} subtitle={$t('change_your_password')}>
|
||||
<ChangePasswordSettings />
|
||||
</SettingAccordion>
|
||||
|
||||
<SettingAccordion key="partner-sharing" title={$t('partner_sharing')} subtitle={$t('manage_sharing_with_partners')}>
|
||||
<SettingAccordion
|
||||
icon={mdiAccountGroupOutline}
|
||||
key="partner-sharing"
|
||||
title={$t('partner_sharing')}
|
||||
subtitle={$t('manage_sharing_with_partners')}
|
||||
>
|
||||
<PartnerSettings user={$user} />
|
||||
</SettingAccordion>
|
||||
|
||||
<SettingAccordion
|
||||
icon={mdiKeyOutline}
|
||||
key="user-purchase-settings"
|
||||
title={$t('user_purchase_settings')}
|
||||
subtitle={$t('user_purchase_settings_description')}
|
||||
|
||||
@@ -148,7 +148,7 @@
|
||||
"note_cannot_be_changed_later": "ملاحظة: لا يمكن تغيير هذا لاحقًا!",
|
||||
"note_unlimited_quota": "ملاحظة: أدخل 0 للحصول على حصة غير محدودة",
|
||||
"notification_email_from_address": "عنوان المرسل",
|
||||
"notification_email_from_address_description": "عنوان البريد الإلكتروني للمرسل، على سبيل المثال: \"Immich Photo Server noreply@immich.app\"",
|
||||
"notification_email_from_address_description": "عنوان البريد الإلكتروني للمرسل، على سبيل المثال: \"Immich Photo Server noreply@example.com\"",
|
||||
"notification_email_host_description": "مضيف خادم البريد الإلكتروني (مثلًا: smtp.immich.app)",
|
||||
"notification_email_ignore_certificate_errors": "تجاهل أخطاء الشهادة",
|
||||
"notification_email_ignore_certificate_errors_description": "تجاهل أخطاء التحقق من صحة شهادة TLS (غير مستحسن)",
|
||||
|
||||
@@ -137,7 +137,7 @@
|
||||
"map_settings_description": "Управление на настройките на картата",
|
||||
"map_style_description": "URL адрес към файл \"style.json\" за задаване на стил на картата",
|
||||
"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": "Опции за метаданни",
|
||||
@@ -150,7 +150,7 @@
|
||||
"note_cannot_be_changed_later": "ВНИМАНИЕ: Това не може да бъде променено по-късно!",
|
||||
"note_unlimited_quota": "Бележка: Въведете 0 за да нямате лимит на квотата",
|
||||
"notification_email_from_address": "От адрес",
|
||||
"notification_email_from_address_description": "Електронна поща на изпращача, например: \"Immich Photo Server <noreply@immich.app>\"",
|
||||
"notification_email_from_address_description": "Електронна поща на изпращача, например: \"Immich Photo Server <noreply@example.com>\"",
|
||||
"notification_email_host_description": "Хост на сървъра за електронна поща (например: smtp.immich.app)",
|
||||
"notification_email_ignore_certificate_errors": "Игорнорирайте сертификационни грешки",
|
||||
"notification_email_ignore_certificate_errors_description": "Игнорирай грешки свързани с валидация на TLS сертификат (не се препоръчва)",
|
||||
@@ -176,7 +176,7 @@
|
||||
"oauth_issuer_url": "URL на издателя",
|
||||
"oauth_mobile_redirect_uri": "URI за мобилно пренасочване",
|
||||
"oauth_mobile_redirect_uri_override": "URI пренасочване за мобилни устройства",
|
||||
"oauth_mobile_redirect_uri_override_description": "Разреши когато 'app.immich:/' е невалиден пренасочвар адрес/URI.",
|
||||
"oauth_mobile_redirect_uri_override_description": "Разреши когато доставчика за OAuth удостоверяване не позволява за мобилни URI идентификатори, като '{callback}'",
|
||||
"oauth_profile_signing_algorithm": "Алгоритъм за създаване на профили",
|
||||
"oauth_profile_signing_algorithm_description": "Алгоритъм излпозлван за вписване на потребителски профил.",
|
||||
"oauth_scope": "Област/обхват на приложение",
|
||||
@@ -244,7 +244,7 @@
|
||||
"thumbnail_generation_job": "Генериране на миниатюри",
|
||||
"thumbnail_generation_job_description": "Генерирайте големи, малки и замъглени миниатюри за всеки актив, както и миниатюри за всеки човек",
|
||||
"transcoding_acceleration_api": "API за ускоряване",
|
||||
"transcoding_acceleration_api_description": "API, който ще взаимодейства с вашето устройство, за да ускори транскодирането. Тази настройка е „best effort“: тя ще се върне към софтуерно транскодиране при повреда. VP9 може или не може да работи в зависимост от вашия хардуер.",
|
||||
"transcoding_acceleration_api_description": "API интерфейсът, който ще взаимодейства с вашето устройство, за да ускори транскодирането. Тази настройка е „възможно най-доброто“: тя ще се върне към софтуерно транскодиране при повреда. VP9 може и да не работи в зависимост от вашия хардуер.",
|
||||
"transcoding_acceleration_nvenc": "NVENC (необходим NVIDIA GPU)",
|
||||
"transcoding_acceleration_qsv": "Quick Sync (необходим 7th поколение Intel CPU или по-ново)",
|
||||
"transcoding_acceleration_rkmpp": "RKMPP (само на Rockchip SOCs)",
|
||||
@@ -252,9 +252,9 @@
|
||||
"transcoding_accepted_audio_codecs": "Допустими аудио кодеци",
|
||||
"transcoding_accepted_audio_codecs_description": "Изберете кои аудио кодеци не са нужни за разкодиране. Използва се само за определени правила за разкодиране.",
|
||||
"transcoding_accepted_containers": "Приети контейнери",
|
||||
"transcoding_accepted_containers_description": "Изберете кои формати на контейнери не трябва да се пренасочват към MP4. Използва се само за определени правила за разкодиране.",
|
||||
"transcoding_accepted_containers_description": "Изберете кои формати на контейнери не е нужно да бъдат преобразувани в MP4 формат. Използва се само за определени правила за разкодиране.",
|
||||
"transcoding_accepted_video_codecs": "Приети видео кодеци",
|
||||
"transcoding_accepted_video_codecs_description": "Изберете кои видео кодеци не трябва да се разкодиране. Използва се само за определени правила за разкодиране.",
|
||||
"transcoding_accepted_video_codecs_description": "Изберете кои видео кодеци не трябват за разкодиране. Използва се само за определени правила за разкодиране.",
|
||||
"transcoding_advanced_options_description": "Опции, които повечето потребители не трябва да променят",
|
||||
"transcoding_audio_codec": "Аудио кодек",
|
||||
"transcoding_audio_codec_description": "Opus е опцията с най-високо качество, но има по-ниска съвместимост със стари устройства или софтуер.",
|
||||
@@ -446,7 +446,7 @@
|
||||
"copy_to_clipboard": "Копиране в клипборда",
|
||||
"country": "Държава",
|
||||
"cover": "",
|
||||
"covers": "",
|
||||
"covers": "Обложка",
|
||||
"create": "Създай",
|
||||
"create_album": "Създай албум",
|
||||
"create_library": "Създай библиотека",
|
||||
@@ -938,19 +938,22 @@
|
||||
"search_city": "",
|
||||
"search_country": "",
|
||||
"search_for_existing_person": "",
|
||||
"search_people": "",
|
||||
"search_places": "",
|
||||
"search_people": "Търсете на хора",
|
||||
"search_places": "Търсене на места",
|
||||
"search_state": "",
|
||||
"search_timezone": "",
|
||||
"search_type": "",
|
||||
"search_your_photos": "",
|
||||
"search_tags": "Търсене на етикети...",
|
||||
"search_timezone": "Търсене на часова зона...",
|
||||
"search_type": "Тип на търсене",
|
||||
"search_your_photos": "Търсете вашите снимки",
|
||||
"searching_locales": "",
|
||||
"second": "Секунда",
|
||||
"select_album_cover": "",
|
||||
"select_all": "",
|
||||
"select_avatar_color": "",
|
||||
"select_face": "",
|
||||
"see_all_people": "Вижте всички хора",
|
||||
"select_album_cover": "Изберете обложка на албум",
|
||||
"select_all": "Изберете всички",
|
||||
"select_avatar_color": "Изберете цвят на аватара",
|
||||
"select_face": "Изберете лице",
|
||||
"select_featured_photo": "",
|
||||
"select_from_computer": "Изберете от компютъра",
|
||||
"select_keep_all": "",
|
||||
"select_library_owner": "Изберете собственик на библиотека",
|
||||
"select_new_face": "Изберете ново лице",
|
||||
@@ -998,28 +1001,40 @@
|
||||
"show_metadata": "Покажи метаданни",
|
||||
"show_or_hide_info": "Покажи или скрий информацията",
|
||||
"show_password": "Покажи паролата",
|
||||
"show_person_options": "",
|
||||
"show_progress_bar": "",
|
||||
"show_search_options": "",
|
||||
"show_person_options": "Показване на опции за лица",
|
||||
"show_progress_bar": "Показване на прогрес бара",
|
||||
"show_search_options": "Показване на опциите за търсене",
|
||||
"show_supporter_badge": "Значка поддръжник",
|
||||
"show_supporter_badge_description": "Покажи значка поддръжник",
|
||||
"shuffle": "Разбъркване",
|
||||
"sign_out": "",
|
||||
"sign_up": "",
|
||||
"sidebar": "Странична лента",
|
||||
"sidebar_display_description": "Показване на връзка към изгледа в страничната лента",
|
||||
"sign_out": "Отписване",
|
||||
"sign_up": "Запиши се",
|
||||
"size": "Размер",
|
||||
"skip_to_content": "",
|
||||
"skip_to_content": "Премини към съдържанието",
|
||||
"skip_to_folders": "Премини към папките",
|
||||
"skip_to_tags": "Премини към етикетите",
|
||||
"slideshow": "Слайдшоу",
|
||||
"slideshow_settings": "",
|
||||
"sort_albums_by": "",
|
||||
"slideshow_settings": "Настройки за слайдшоу",
|
||||
"sort_albums_by": "Сортиране на албуми по...",
|
||||
"sort_created": "Дата на създаване",
|
||||
"sort_items": "Брой елементи",
|
||||
"sort_modified": "Дата на промяна",
|
||||
"sort_oldest": "Най-старата снимка",
|
||||
"sort_recent": "Най-новата снимка",
|
||||
"sort_title": "Заглавие",
|
||||
"source": "Източник",
|
||||
"stack": "",
|
||||
"stack_selected_photos": "",
|
||||
"stack_duplicates": "Подреждане на дубликати",
|
||||
"stack_selected_photos": "Подреждане на избрани снимки",
|
||||
"stacktrace": "",
|
||||
"start": "Старт",
|
||||
"start_date": "",
|
||||
"start_date": "Начална дата",
|
||||
"state": "",
|
||||
"status": "Статус",
|
||||
"stop_motion_photo": "",
|
||||
"stop_photo_sharing": "Да спрете ли споделянето на вашите снимки?",
|
||||
"stop_photo_sharing": "Да спра ли споделянето на вашите снимки?",
|
||||
"stop_photo_sharing_description": "{partner} вече няма достъп до вашите снимки.",
|
||||
"stop_sharing_photos_with_user": "Прекратете споделянето на снимки с този потребител",
|
||||
"storage": "Пространство на хранилището",
|
||||
@@ -1030,6 +1045,12 @@
|
||||
"sunrise_on_the_beach": "Изгрев на плажа",
|
||||
"swap_merge_direction": "Размяна посоката на сливане",
|
||||
"sync": "Синхронизиране",
|
||||
"tag": "Таг",
|
||||
"tag_created": "Създаден етикет: {tag}",
|
||||
"tag_feature_description": "Разглеждане на снимки и видеоклипове, групирани по теми с логически тагове",
|
||||
"tag_not_found_question": "Не можете да намерите етикет? Създайте такъв <link>тук</link>",
|
||||
"tag_updated": "Актуализиран етикет: {tag}",
|
||||
"tags": "Етикет",
|
||||
"template": "Шаблон",
|
||||
"theme": "Тема",
|
||||
"theme_selection": "Избор на тема",
|
||||
@@ -1048,7 +1069,7 @@
|
||||
"total_usage": "Общо използвано",
|
||||
"trash": "кошче",
|
||||
"trash_all": "Изхвърли всички",
|
||||
"trash_count": "",
|
||||
"trash_count": "Кошче {count, number}",
|
||||
"trash_no_results_message": "Изтритите снимки и видеоклипове ще се показват тук.",
|
||||
"trashed_items_will_be_permanently_deleted_after": "Изхвърлените в кошчето елементи ще бъдат изтрити за постоянно след {days, plural, one {# day} other {# days}}.",
|
||||
"type": "Тип",
|
||||
@@ -1062,6 +1083,7 @@
|
||||
"unlink_oauth": "",
|
||||
"unlinked_oauth_account": "",
|
||||
"unnamed_album": "Албум без име",
|
||||
"unnamed_album_delete_confirmation": "Сигурни ли сте, че искате да изтриете този албум?",
|
||||
"unnamed_share": "Споделяне без име",
|
||||
"unsaved_change": "Незапазена промяна",
|
||||
"unselect_all": "Деселектирайте всички",
|
||||
@@ -1085,7 +1107,7 @@
|
||||
"user_purchase_settings": "Покупка",
|
||||
"user_purchase_settings_description": "Управлявай покупката си",
|
||||
"user_role_set": "Задай {user} като {role}",
|
||||
"user_usage_detail": "",
|
||||
"user_usage_detail": "Подробности за използването на потребителя",
|
||||
"username": "Потребителско име",
|
||||
"users": "Потребители",
|
||||
"utilities": "Инструменти",
|
||||
@@ -1103,9 +1125,11 @@
|
||||
"view_album": "Разгледай албума",
|
||||
"view_all": "Преглед на всички",
|
||||
"view_all_users": "Преглед на всички потребители",
|
||||
"view_in_timeline": "Покажи във времева линия",
|
||||
"view_links": "Преглед на връзките",
|
||||
"view_next_asset": "Преглед на следващия файл",
|
||||
"view_previous_asset": "Преглед на предишния файл",
|
||||
"view_stack": "Покажи в стек",
|
||||
"viewer": "",
|
||||
"waiting": "в изчакване",
|
||||
"warning": "Внимание",
|
||||
|
||||
@@ -129,16 +129,21 @@
|
||||
"map_enable_description": "Habilita característiques del mapa",
|
||||
"map_gps_settings": "Configuració de mapa i GPS",
|
||||
"map_gps_settings_description": "Gestiona la configuració de mapa i GPS (Geocodificació inversa)",
|
||||
"map_implications": "La funció mapa depèn del servei extern de tesel·les (tiles.immich.cloud)",
|
||||
"map_light_style": "Tema clar",
|
||||
"map_manage_reverse_geocoding_settings": "Gestiona els paràmetres de <link>geocodificació inversa</link>",
|
||||
"map_reverse_geocoding": "Geocodificació inversa",
|
||||
"map_reverse_geocoding_enable_description": "Habilita la geocodificació inversa",
|
||||
"map_reverse_geocoding_settings": "Configuració de Geocodificació Inversa",
|
||||
"map_settings": "Configuració del mapa i GPS",
|
||||
"map_settings": "Mapa",
|
||||
"map_settings_description": "Gestiona la configuració del mapa",
|
||||
"map_style_description": "URL a un tema del mapa style.json",
|
||||
"metadata_extraction_job": "Extreure metadades",
|
||||
"metadata_extraction_job_description": "Extreu la informació de metadades de cada element, com per exemple el GPS i la resolució",
|
||||
"metadata_faces_import_setting": "Activar la importació de cares",
|
||||
"metadata_faces_import_setting_description": "Importar cares des de les metadades EXIF de les imatges i arxius auxiliars",
|
||||
"metadata_settings": "Configuració de les metadades",
|
||||
"metadata_settings_description": "Administrar la configuració de les metadades",
|
||||
"migration_job": "Migració",
|
||||
"migration_job_description": "Migra les miniatures d'elements i cares cap a la nova estructura de carpetes",
|
||||
"no_paths_added": "Cap camí afegit",
|
||||
@@ -147,7 +152,7 @@
|
||||
"note_cannot_be_changed_later": "NOTA: Això és irreversible!",
|
||||
"note_unlimited_quota": "Nota: Intruduïu 0 per a quota il·limitada",
|
||||
"notification_email_from_address": "Des de l'adreça",
|
||||
"notification_email_from_address_description": "Adreça de correu electrònic del remitent, per exemple: \"Immich Photo Server <noreply@immich.app>\"",
|
||||
"notification_email_from_address_description": "Adreça de correu electrònic del remitent, per exemple: \"Immich Photo Server <noreply@example.com>\"",
|
||||
"notification_email_host_description": "Amfitrió del servidor de correu electrònic (p.ex. smtp.immich.app)",
|
||||
"notification_email_ignore_certificate_errors": "Ignora els errors de certificat",
|
||||
"notification_email_ignore_certificate_errors_description": "Ignora els errors de validació de certificat TLS (no recomanat)",
|
||||
@@ -173,7 +178,7 @@
|
||||
"oauth_issuer_url": "URL de l'emissor",
|
||||
"oauth_mobile_redirect_uri": "URI de redirecció mòbil",
|
||||
"oauth_mobile_redirect_uri_override": "Sobreescriu l'URI de redirecció mòbil",
|
||||
"oauth_mobile_redirect_uri_override_description": "Habilita quan 'app.immich:/' és una URI de redirecció invàlida.",
|
||||
"oauth_mobile_redirect_uri_override_description": "Habilita quan el proveïdor d'OAuth no permet una URI mòbil, com ara '{callback}'",
|
||||
"oauth_profile_signing_algorithm": "Algoritme de signatura del perfil",
|
||||
"oauth_profile_signing_algorithm_description": "Algoritme utilitzat per signar el perfil d’usuari.",
|
||||
"oauth_scope": "Abast",
|
||||
@@ -278,7 +283,7 @@
|
||||
"transcoding_preferred_hardware_device": "Dispositiu de maquinari preferit",
|
||||
"transcoding_preferred_hardware_device_description": "S'aplica només a VAAPI i QSV. Estableix el node dri utilitzat per a la transcodificació de maquinari.",
|
||||
"transcoding_preset_preset": "Preestablert (-preset)",
|
||||
"transcoding_preset_preset_description": "Velocitat de compressió. Els valors predefinits més lents produeixen fitxers més petits i augmenten la qualitat quan s'orienta a una taxa de bits determinada. VP9 ignora les velocitats superiors a \"més ràpides\".",
|
||||
"transcoding_preset_preset_description": "Velocitat de compressió. Els valors predefinits més lents produeixen fitxers més petits i augmenten la qualitat quan s'orienta a una taxa de bits determinada. VP9 ignora les velocitats superiors a 'més ràpides'.",
|
||||
"transcoding_reference_frames": "Fotogrames de referència",
|
||||
"transcoding_reference_frames_description": "El nombre de fotogrames a fer referència en comprimir un fotograma determinat. Els valors més alts milloren l'eficiència de la compressió, però alenteixen la codificació. 0 estableix aquest valor automàticament.",
|
||||
"transcoding_required_description": "Només vídeos que no tenen un format acceptat",
|
||||
@@ -320,7 +325,8 @@
|
||||
"user_settings": "Configuració d'usuaris",
|
||||
"user_settings_description": "Gestiona la configuració dels usuaris",
|
||||
"user_successfully_removed": "L'usuari {email} s'ha eliminat correctament.",
|
||||
"version_check_enabled_description": "Activa sol·licituds periòdiques a GitHub per comprovar si hi ha versions noves",
|
||||
"version_check_enabled_description": "Activa la comprovació de la versió",
|
||||
"version_check_implications": "La funció de comprovació de versions depèn de comunicacions periòdiques amb github.com",
|
||||
"version_check_settings": "Comprovació de versió",
|
||||
"version_check_settings_description": "Activa/desactiva la notificació de nova versió",
|
||||
"video_conversion_job": "Transcodificació de vídeos",
|
||||
@@ -336,7 +342,8 @@
|
||||
"album_added": "Àlbum afegit",
|
||||
"album_added_notification_setting_description": "Rep una notificació per correu quan siguis afegit a un àlbum compartit",
|
||||
"album_cover_updated": "Portada de l'àlbum actualitzada",
|
||||
"album_delete_confirmation": "N'esteu segur que voleu suprimir l'àlbum {album}?\nSi aquest àlbum és compartit, altres usuaris no hi podran accedir més.",
|
||||
"album_delete_confirmation": "Esteu segur que voleu suprimir l'àlbum {album}?",
|
||||
"album_delete_confirmation_description": "Si aquest àlbum es comparteix, els altres usuaris ja no podran accedir-hi.",
|
||||
"album_info_updated": "Informació de l'àlbum actualitzada",
|
||||
"album_leave": "Sortir de l'àlbum?",
|
||||
"album_leave_confirmation": "N'esteu segur que voleu sortir de {album}?",
|
||||
@@ -360,6 +367,7 @@
|
||||
"allow_edits": "Permet editar",
|
||||
"allow_public_user_to_download": "Permet que l'usuari públic pugui descarregar",
|
||||
"allow_public_user_to_upload": "Permet que l'usuari públic pugui carregar",
|
||||
"anti_clockwise": "En sentit antihorari",
|
||||
"api_key": "Clau API",
|
||||
"api_key_description": "Aquest valor només es mostrarà una vegada. Assegureu-vos de copiar-lo abans de tancar la finestra.",
|
||||
"api_key_empty": "El nom de la clau de l'API no pot estar buit",
|
||||
@@ -383,6 +391,7 @@
|
||||
"asset_offline": "Element fora de línia",
|
||||
"asset_offline_description": "Aquest element està fora de línia. L'Immich no pot accedir a la seva ubicació. Si us plau, assegureu-vos que l'actiu està disponible i després torneu la llibreria.",
|
||||
"asset_skipped": "Saltat",
|
||||
"asset_skipped_in_trash": "A la paperera",
|
||||
"asset_uploaded": "Carregat",
|
||||
"asset_uploading": "S'està carregant...",
|
||||
"assets": "Elements",
|
||||
@@ -440,9 +449,11 @@
|
||||
"clear_all_recent_searches": "Esborra totes les cerques recents",
|
||||
"clear_message": "Neteja el missatge",
|
||||
"clear_value": "Neteja el valor",
|
||||
"clockwise": "En sentit horari",
|
||||
"close": "Tanca",
|
||||
"collapse": "Tanca",
|
||||
"collapse_all": "Redueix-ho tot",
|
||||
"color": "Color",
|
||||
"color_theme": "Tema de color",
|
||||
"comment_deleted": "Comentari esborrat",
|
||||
"comment_options": "Opcions de comentari",
|
||||
@@ -476,6 +487,8 @@
|
||||
"create_new_person": "Crea una nova persona",
|
||||
"create_new_person_hint": "Assigna els elements seleccionats a una persona nova",
|
||||
"create_new_user": "Crea un usuari nou",
|
||||
"create_tag": "Crear etiqueta",
|
||||
"create_tag_description": "Crear una nova etiqueta. Per les etiquetes aniuades, escriu la ruta comperta de l'etiqueta, incloses les barres diagonals.",
|
||||
"create_user": "Crea un usuari",
|
||||
"created": "Creat",
|
||||
"current_device": "Dispositiu actual",
|
||||
@@ -499,6 +512,8 @@
|
||||
"delete_library": "Suprimeix la llibreria",
|
||||
"delete_link": "Esborra l'enllaç",
|
||||
"delete_shared_link": "Odstranit sdílený odkaz",
|
||||
"delete_tag": "Eliminar etiqueta",
|
||||
"delete_tag_confirmation_prompt": "Estàs segur que vols eliminar l'etiqueta {tagName}?",
|
||||
"delete_user": "Suprimeix l'usuari",
|
||||
"deleted_shared_link": "Suprimeix l'enllaç compartit",
|
||||
"description": "Descripció",
|
||||
@@ -516,6 +531,8 @@
|
||||
"do_not_show_again": "No tornis a mostrar aquest missatge",
|
||||
"done": "Fet",
|
||||
"download": "Descarregar",
|
||||
"download_include_embedded_motion_videos": "Vídeos incrustats",
|
||||
"download_include_embedded_motion_videos_description": "Incloure vídeos incrustats en fotografies en moviment com un arxiu separat",
|
||||
"download_settings": "Descarregar",
|
||||
"download_settings_description": "Gestioneu la configuració relacionada amb la descàrrega de recursos",
|
||||
"downloading": "Baixant",
|
||||
@@ -545,10 +562,15 @@
|
||||
"edit_location": "Edita ubicació",
|
||||
"edit_name": "Edita el nom",
|
||||
"edit_people": "Edita la gent",
|
||||
"edit_tag": "Editar etiqueta",
|
||||
"edit_title": "Edita títol",
|
||||
"edit_user": "Edita l'usuari",
|
||||
"edited": "Editat",
|
||||
"editor": "Editor",
|
||||
"editor_close_without_save_prompt": "No es desaran els canvis",
|
||||
"editor_close_without_save_title": "Tancar l'editor?",
|
||||
"editor_crop_tool_h2_aspect_ratios": "Relació d'aspecte",
|
||||
"editor_crop_tool_h2_rotation": "Rotació",
|
||||
"email": "Correu electrònic",
|
||||
"empty": "",
|
||||
"empty_album": "",
|
||||
@@ -638,6 +660,7 @@
|
||||
"unable_to_get_comments_number": "No es pot obtenir el nombre de comentaris",
|
||||
"unable_to_get_shared_link": "No s'ha pogut obtenir l'enllaç compartit",
|
||||
"unable_to_hide_person": "No es pot amagar la persona",
|
||||
"unable_to_link_motion_video": "No es pot enllaçar el vídeo en moviment",
|
||||
"unable_to_link_oauth_account": "No es pot enllaçar el compte OAuth",
|
||||
"unable_to_load_album": "No es pot carregar l'àlbum",
|
||||
"unable_to_load_asset_activity": "No es pot carregar l'activitat dels recursos",
|
||||
@@ -678,6 +701,7 @@
|
||||
"unable_to_submit_job": "No es pot enviar la tasca",
|
||||
"unable_to_trash_asset": "No es pot eliminar el recurs a la paperera",
|
||||
"unable_to_unlink_account": "No es pot desenllaçar el compte",
|
||||
"unable_to_unlink_motion_video": "No es pot desvincular el vídeo en moviment",
|
||||
"unable_to_update_album_cover": "No es pot actualitzar la portada de l'àlbum",
|
||||
"unable_to_update_album_info": "No es pot actualitzar la informació de l'àlbum",
|
||||
"unable_to_update_library": "No es pot actualitzar la biblioteca",
|
||||
@@ -698,6 +722,7 @@
|
||||
"expired": "Caducat",
|
||||
"expires_date": "Caduca el {date}",
|
||||
"explore": "Explorar",
|
||||
"explorer": "Explorador",
|
||||
"export": "Exporta",
|
||||
"export_as_json": "Exportar com a JSON",
|
||||
"extension": "Extensió",
|
||||
@@ -711,6 +736,8 @@
|
||||
"feature": "",
|
||||
"feature_photo_updated": "Foto destacada actualitzada",
|
||||
"featurecollection": "",
|
||||
"features": "Característiques",
|
||||
"features_setting_description": "Administrar les funcions de l'aplicació",
|
||||
"file_name": "Nom de l'arxiu",
|
||||
"file_name_or_extension": "Nom de l'arxiu o extensió",
|
||||
"filename": "Nom del fitxer",
|
||||
@@ -719,6 +746,8 @@
|
||||
"filter_people": "Filtra persones",
|
||||
"find_them_fast": "Trobeu-los ràpidament pel nom amb la cerca",
|
||||
"fix_incorrect_match": "Corregiu la coincidència incorrecta",
|
||||
"folders": "Carpetes",
|
||||
"folders_feature_description": "Explorar la vista de carpetes per les fotos i vídeos del sistema d'arxius",
|
||||
"force_re-scan_library_files": "Força a tornar a escanejar tots els fitxers de la biblioteca",
|
||||
"forward": "Endavant",
|
||||
"general": "General",
|
||||
@@ -803,6 +832,7 @@
|
||||
"license_trial_info_3": "{accountAge, plural, one {# dia} other {# dies}}",
|
||||
"light": "Llum",
|
||||
"like_deleted": "M'agrada suprimit",
|
||||
"link_motion_video": "Enllaçar vídeo en moviment",
|
||||
"link_options": "Opcions d'enllaç",
|
||||
"link_to_oauth": "Enllaç a OAuth",
|
||||
"linked_oauth_account": "Compte OAuth enllaçat",
|
||||
@@ -896,12 +926,14 @@
|
||||
"ok": "D'acord",
|
||||
"oldest_first": "El més vell primer",
|
||||
"onboarding": "Onboarding",
|
||||
"onboarding_privacy_description": "Les següents funcions (opcionals) depenen de serveis externs i poden desactivarse en qualsevol moment de dels ajustos.",
|
||||
"onboarding_theme_description": "Trieu un tema de color per a la vostra instància. Podeu canviar-ho més endavant a la vostra configuració.",
|
||||
"onboarding_welcome_description": "Configurem la vostra instància amb alguns paràmetres habituals.",
|
||||
"onboarding_welcome_user": "Benvingut, {user}",
|
||||
"online": "En línia",
|
||||
"only_favorites": "Només preferits",
|
||||
"only_refreshes_modified_files": "Només actualitza els fitxers modificats",
|
||||
"open_in_map_view": "Obrir a la vista del mapa",
|
||||
"open_in_openstreetmap": "Obre a OpenStreetMap",
|
||||
"open_the_search_filters": "Obriu els filtres de cerca",
|
||||
"options": "Opcions",
|
||||
@@ -936,6 +968,7 @@
|
||||
"pending": "Pendent",
|
||||
"people": "Persones",
|
||||
"people_edits_count": "{count, plural, one {# persona editada} other {# persones editades}}",
|
||||
"people_feature_description": "Explorar fotos i vídeos agrupades per persona",
|
||||
"people_sidebar_description": "Mostrar un enllaç a Persones a la barra lateral",
|
||||
"perform_library_tasks": "",
|
||||
"permanent_deletion_warning": "Avís d'eliminació permanent",
|
||||
@@ -967,6 +1000,7 @@
|
||||
"previous_memory": "Memòria anterior",
|
||||
"previous_or_next_photo": "Foto anterior o següent",
|
||||
"primary": "Primària",
|
||||
"privacy": "Privacitat",
|
||||
"profile_image_of_user": "Imatge de perfil de {user}",
|
||||
"profile_picture_set": "Imatge de perfil configurada.",
|
||||
"public_album": "Àlbum públic",
|
||||
@@ -1004,6 +1038,10 @@
|
||||
"purchase_server_title": "Servidor",
|
||||
"purchase_settings_server_activated": "La clau de producte del servidor la gestiona l'administrador",
|
||||
"range": "",
|
||||
"rating": "Valoració",
|
||||
"rating_clear": "Esborrar valoració",
|
||||
"rating_count": "{count, plural, one {# estrella} other {# estrelles}}",
|
||||
"rating_description": "Mostrar la valoració EXIF al panell d'informació",
|
||||
"raw": "",
|
||||
"reaction_options": "Opcions de reacció",
|
||||
"read_changelog": "Llegeix el registre de canvis",
|
||||
@@ -1036,6 +1074,7 @@
|
||||
"removed_from_archive": "Eliminat de l'arxiu",
|
||||
"removed_from_favorites": "Eliminat dels preferits",
|
||||
"removed_from_favorites_count": "{count, plural, other {# eliminats}} dels preferits",
|
||||
"removed_tagged_assets": "Etiqueta eliminada de {count, plural, one {# actiu} other {# actius}}",
|
||||
"rename": "Canviar nom",
|
||||
"repair": "Reparació",
|
||||
"repair_no_results_message": "Els fitxers sense seguiment i que falten es mostraran aquí",
|
||||
@@ -1082,9 +1121,11 @@
|
||||
"search_for_existing_person": "Busca una persona existent",
|
||||
"search_no_people": "Cap persona",
|
||||
"search_no_people_named": "Cap persona anomenada \"{name}\"",
|
||||
"search_options": "Opcions de cerca",
|
||||
"search_people": "Buscar persones",
|
||||
"search_places": "Buscar llocs",
|
||||
"search_state": "Buscar per regió...",
|
||||
"search_tags": "Cercant etiquetes...",
|
||||
"search_timezone": "Buscar per fus horari...",
|
||||
"search_type": "Buscar per tipus",
|
||||
"search_your_photos": "Cerca les teves fotos",
|
||||
@@ -1126,6 +1167,7 @@
|
||||
"shared_by_user": "Compartit per {user}",
|
||||
"shared_by_you": "Compartit per tu",
|
||||
"shared_from_partner": "Fotos de {partner}",
|
||||
"shared_link_options": "Opcions d'enllaços compartits",
|
||||
"shared_links": "Enllaços compartits",
|
||||
"shared_photos_and_videos_count": "{assetCount, plural, other {# fotos i vídeos compartits.}}",
|
||||
"shared_with_partner": "Compartit amb {partner}",
|
||||
@@ -1134,6 +1176,7 @@
|
||||
"sharing_sidebar_description": "Mostra un enllaç a Compartit a la barra lateral",
|
||||
"shift_to_permanent_delete": "premeu ⇧ per suprimir el recurs permanentment",
|
||||
"show_album_options": "Mostra les opcions d'àlbum",
|
||||
"show_albums": "Mostrar àlbums",
|
||||
"show_all_people": "Veure totes les persones",
|
||||
"show_and_hide_people": "Mostra i amaga persones",
|
||||
"show_file_location": "Mostra l'ubicació del fitxer",
|
||||
@@ -1151,10 +1194,14 @@
|
||||
"show_supporter_badge": "Insígnia de contribuent",
|
||||
"show_supporter_badge_description": "Mostra una insígnia de contributor",
|
||||
"shuffle": "Mescla",
|
||||
"sidebar": "Barra lateral",
|
||||
"sidebar_display_description": "Mostra un enllaç a la vista a la barra lateral",
|
||||
"sign_out": "Tanca sessió",
|
||||
"sign_up": "Registrar-se",
|
||||
"size": "Mida",
|
||||
"skip_to_content": "Salta al contingut",
|
||||
"skip_to_folders": "Anar a carpetes",
|
||||
"skip_to_tags": "Anar a etiquetes",
|
||||
"slideshow": "Diapositives",
|
||||
"slideshow_settings": "Configuració de diapositives",
|
||||
"sort_albums_by": "Ordena àlbums per...",
|
||||
@@ -1166,6 +1213,8 @@
|
||||
"sort_title": "Títol",
|
||||
"source": "Font",
|
||||
"stack": "Apila",
|
||||
"stack_duplicates": "Aplicar duplicats",
|
||||
"stack_select_one_photo": "Selecciona una imatge principal per la pila",
|
||||
"stack_selected_photos": "Apila les fotos seleccionades",
|
||||
"stacked_assets_count": "Apilats {count, plural, one {# element} other {# elements}}",
|
||||
"stacktrace": "Traça de pila",
|
||||
@@ -1185,6 +1234,14 @@
|
||||
"sunrise_on_the_beach": "Albada a la platja",
|
||||
"swap_merge_direction": "Canvia la direcció d'unió",
|
||||
"sync": "Sincronitza",
|
||||
"tag": "Etiqueta",
|
||||
"tag_assets": "Etiquetar actius",
|
||||
"tag_created": "Etiqueta creada: {tag}",
|
||||
"tag_feature_description": "Exploreu fotos i vídeos agrupats per temes d'etiquetes lògiques",
|
||||
"tag_not_found_question": "No trobeu una etiqueta? Creeu-ne una <link>aquí</link>",
|
||||
"tag_updated": "Etiqueta actualizada: {tag}",
|
||||
"tagged_assets": "{count, plural, one {#Etiquetat} other {#Etiquetats}} {count, plural, one {# actiu} other {# actius}}",
|
||||
"tags": "Etiquetes",
|
||||
"template": "Plantilla",
|
||||
"theme": "Tema",
|
||||
"theme_selection": "Selecció de tema",
|
||||
@@ -1196,9 +1253,10 @@
|
||||
"to_change_password": "Canviar la contrasenya",
|
||||
"to_favorite": "Prefereix",
|
||||
"to_login": "Iniciar sessió",
|
||||
"to_parent": "Anar als pares",
|
||||
"to_trash": "Paperera",
|
||||
"toggle_settings": "Canvia configuració",
|
||||
"toggle_theme": "Canvia tema",
|
||||
"toggle_theme": "Alternar tema",
|
||||
"toggle_visibility": "Canvia visibilitat",
|
||||
"total_usage": "Ús total",
|
||||
"trash": "Paperera",
|
||||
@@ -1217,9 +1275,11 @@
|
||||
"unknown_album": "Àlbum desconegut",
|
||||
"unknown_year": "Any desconegut",
|
||||
"unlimited": "Il·limitat",
|
||||
"unlink_motion_video": "Desvincular vídeo en moviment",
|
||||
"unlink_oauth": "Desvincula OAuth",
|
||||
"unlinked_oauth_account": "Compte Oauth desvinculat",
|
||||
"unnamed_album": "Àlbum sense nom",
|
||||
"unnamed_album_delete_confirmation": "Segur que voleu esborrar aquest àlbum?",
|
||||
"unnamed_share": "Compartit sense nom",
|
||||
"unsaved_change": "Canvi no desat",
|
||||
"unselect_all": "Deselecciona-ho tot",
|
||||
@@ -1267,6 +1327,7 @@
|
||||
"view_album": "Veure l'àlbum",
|
||||
"view_all": "Veure tot",
|
||||
"view_all_users": "Mostra tot els usuaris",
|
||||
"view_in_timeline": "Mostrar a la línia de temps",
|
||||
"view_links": "Mostra enllaços",
|
||||
"view_next_asset": "Mostra el següent element",
|
||||
"view_previous_asset": "Mostra l'element anterior",
|
||||
|
||||
@@ -152,7 +152,7 @@
|
||||
"note_cannot_be_changed_later": "UPOZORNĚNÍ: Toto nelze později změnit!",
|
||||
"note_unlimited_quota": "Upozornění: Pro neomezenou kvótu zadejte 0",
|
||||
"notification_email_from_address": "Adresa Od",
|
||||
"notification_email_from_address_description": "E-mailová adresa odesílatele, např.: \"Immich Photo Server <noreply@immich.app>\"",
|
||||
"notification_email_from_address_description": "E-mailová adresa odesílatele, např.: \"Immich Photo Server <noreply@example.com>\"",
|
||||
"notification_email_host_description": "Adresa e-mailového serveru (např. smtp.immich.app)",
|
||||
"notification_email_ignore_certificate_errors": "Ignorovat chyby certifikátů",
|
||||
"notification_email_ignore_certificate_errors_description": "Ignorovat chyby ověření certifikátu TLS (nedoporučuje se)",
|
||||
@@ -661,6 +661,7 @@
|
||||
"unable_to_get_comments_number": "Nelze načíst počet komentářů",
|
||||
"unable_to_get_shared_link": "Nepodařilo se získat sdílený odkaz",
|
||||
"unable_to_hide_person": "Nelze skrýt osobu",
|
||||
"unable_to_link_motion_video": "Nelze připojit pohyblivé video",
|
||||
"unable_to_link_oauth_account": "Nelze propojit OAuth účet",
|
||||
"unable_to_load_album": "Nelze načíst album",
|
||||
"unable_to_load_asset_activity": "Nelze načíst aktivitu položky",
|
||||
@@ -701,6 +702,7 @@
|
||||
"unable_to_submit_job": "Nelze odeslat úlohu",
|
||||
"unable_to_trash_asset": "Nelze vyhodit položku do koše",
|
||||
"unable_to_unlink_account": "Nelze zrušit propojení účtu",
|
||||
"unable_to_unlink_motion_video": "Nelze odpojit pohyblivé video",
|
||||
"unable_to_update_album_cover": "Nelze aktualizovat obal alba",
|
||||
"unable_to_update_album_info": "Nelze aktualizovat informace o albu",
|
||||
"unable_to_update_library": "Nelze aktualizovat knihovnu",
|
||||
@@ -1292,6 +1294,7 @@
|
||||
"unknown_album": "Neznámé album",
|
||||
"unknown_year": "Neznámý rok",
|
||||
"unlimited": "Neomezeně",
|
||||
"unlink_motion_video": "Odpojit pohyblivé video",
|
||||
"unlink_oauth": "Zrušit OAuth propojení",
|
||||
"unlinked_oauth_account": "OAuth účet odpojen",
|
||||
"unnamed_album": "Nepojmenované album",
|
||||
|
||||
@@ -140,6 +140,10 @@
|
||||
"map_style_description": "URL til en style.json for et korttema",
|
||||
"metadata_extraction_job": "Udtræk metadata",
|
||||
"metadata_extraction_job_description": "Udtræk metadataoplysninger fra hvert Billede/Video, såsom GPS og opløsning",
|
||||
"metadata_faces_import_setting": "Aktivér for at importere ansigter",
|
||||
"metadata_faces_import_setting_description": "Importerer ansigter fra billed EXIF-data og forbandt filer",
|
||||
"metadata_settings": "Metadatainstillinger",
|
||||
"metadata_settings_description": "Håndtér metadataindstillinger",
|
||||
"migration_job": "Migrering",
|
||||
"migration_job_description": "Migrér miniaturebilleder for aktiver og ansigter til den seneste mappestruktur",
|
||||
"no_paths_added": "Ingen stier tilføjet",
|
||||
@@ -148,7 +152,7 @@
|
||||
"note_cannot_be_changed_later": "BEMÆRK: Dette kan ikke ændres senere!",
|
||||
"note_unlimited_quota": "Bemærk: Indsæt 0 for uendelig kvote",
|
||||
"notification_email_from_address": "Fra adressse",
|
||||
"notification_email_from_address_description": "Afsenderemailadresse, for eksempel: \"Immich Billedserver <noreply@immich.app>\"",
|
||||
"notification_email_from_address_description": "Afsenderemailadresse, for eksempel: \"Immich Billedserver <noreply@example.com>\"",
|
||||
"notification_email_host_description": "Host af emailserver (fx smtp.immich.app)",
|
||||
"notification_email_ignore_certificate_errors": "Ignorér certifikatfejl",
|
||||
"notification_email_ignore_certificate_errors_description": "Ignorér TLS-certifikatgodkendelsesfejl (ikke anbefalet)",
|
||||
@@ -347,15 +351,25 @@
|
||||
"album_options": "Albumindstillinger",
|
||||
"album_remove_user": "Fjern bruger?",
|
||||
"album_remove_user_confirmation": "Er du sikker på at du vil fjerne {user}?",
|
||||
"album_share_no_users": "Det ser ud til at du har delt denne album med alle brugere, eller du har ikke nogen brugere til at dele med.",
|
||||
"album_updated": "Album opdateret",
|
||||
"album_updated_setting_description": "Modtag en emailnotifikation når et delt album får nye mediefiler",
|
||||
"album_user_left": "Forlod {album}",
|
||||
"album_user_removed": "Fjernede {user}",
|
||||
"albums": "Albummer",
|
||||
"albums_count": "{count, plural, one {{count, number} Album} other {{count, number} Albummer}}",
|
||||
"all": "Alt",
|
||||
"all_albums": "Alle albummer",
|
||||
"all_people": "Alle personer",
|
||||
"all_videos": "Alle videoer",
|
||||
"allow_dark_mode": "Tillad mørk tilstand",
|
||||
"allow_edits": "Tillad redigeringer",
|
||||
"allow_public_user_to_download": "Tillad offentlige brugere til at hente",
|
||||
"allow_public_user_to_upload": "Tillad offentlige brugere til at uploade",
|
||||
"anti_clockwise": "Mod uret",
|
||||
"api_key": "API-nøgle",
|
||||
"api_key_description": "Denne værdi vises kun én gang. Venligst kopiér den før du lukker vinduet.",
|
||||
"api_key_empty": "Din API-nøgle-navn burde ikke være tom",
|
||||
"api_keys": "API-nøgler",
|
||||
"app_settings": "Appindstillinger",
|
||||
"appears_in": "Optræder i",
|
||||
|
||||
@@ -152,7 +152,7 @@
|
||||
"note_cannot_be_changed_later": "HINWEIS: Dies kann später nicht mehr geändert werden!",
|
||||
"note_unlimited_quota": "Hinweis: 0 eingeben für unlimitiertes Kontingent",
|
||||
"notification_email_from_address": "Von",
|
||||
"notification_email_from_address_description": "E-Mail-Adresse des Senders, zum Beispiel: \"Immich Photo Server <noreply@immich.app>\"",
|
||||
"notification_email_from_address_description": "E-Mail-Adresse des Senders, zum Beispiel: \"Immich Photo Server <noreply@example.com>\"",
|
||||
"notification_email_host_description": "Host des E-Mail-Servers (z.B. smtp.immich.app)",
|
||||
"notification_email_ignore_certificate_errors": "Ignoriere Zertifikats-Fehler",
|
||||
"notification_email_ignore_certificate_errors_description": "TLS-Zertifikatsvalidierungsfehler ignorieren (nicht empfohlen)",
|
||||
@@ -1171,7 +1171,7 @@
|
||||
"server_stats": "Server-Statistiken",
|
||||
"server_version": "Server-Version",
|
||||
"set": "Speichern",
|
||||
"set_as_album_cover": "Als Albumcover gesetzt",
|
||||
"set_as_album_cover": "Als Albumcover festlegen",
|
||||
"set_as_profile_picture": "Als Profilbild festlegen",
|
||||
"set_date_of_birth": "Geburtsdatum festlegen",
|
||||
"set_profile_picture": "Profilbild einstellen",
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
"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?",
|
||||
"create_job": "Create job",
|
||||
"disable_login": "Disable login",
|
||||
"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.",
|
||||
@@ -68,6 +69,7 @@
|
||||
"image_thumbnail_resolution": "Thumbnail resolution",
|
||||
"image_thumbnail_resolution_description": "Used when viewing groups of photos (main timeline, album view, etc.). Higher resolutions can preserve more detail but take longer to encode, have larger file sizes, and can reduce app responsiveness.",
|
||||
"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",
|
||||
@@ -150,7 +152,7 @@
|
||||
"note_cannot_be_changed_later": "NOTE: This cannot be changed later!",
|
||||
"note_unlimited_quota": "Note: Enter 0 for unlimited quota",
|
||||
"notification_email_from_address": "From address",
|
||||
"notification_email_from_address_description": "Sender email address, for example: \"Immich Photo Server <noreply@immich.app>\"",
|
||||
"notification_email_from_address_description": "Sender email address, for example: \"Immich Photo Server <noreply@example.com>\"",
|
||||
"notification_email_host_description": "Host 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)",
|
||||
@@ -196,6 +198,7 @@
|
||||
"password_settings": "Password Login",
|
||||
"password_settings_description": "Manage password login settings",
|
||||
"paths_validated_successfully": "All paths validated successfully",
|
||||
"person_cleanup_job": "Person cleanup",
|
||||
"quota_size_gib": "Quota Size (GiB)",
|
||||
"refreshing_all_libraries": "Refreshing all libraries",
|
||||
"registration": "Admin Registration",
|
||||
@@ -209,6 +212,7 @@
|
||||
"reset_settings_to_recent_saved": "Reset settings to the recent saved settings",
|
||||
"scanning_library_for_changed_files": "Scanning library for changed files",
|
||||
"scanning_library_for_new_files": "Scanning library for new files",
|
||||
"search_jobs": "Search jobs...",
|
||||
"send_welcome_email": "Send welcome email",
|
||||
"server_external_domain_settings": "External domain",
|
||||
"server_external_domain_settings_description": "Domain for public shared links, including http(s)://",
|
||||
@@ -236,6 +240,7 @@
|
||||
"storage_template_settings_description": "Manage the folder structure and file name of the upload asset",
|
||||
"storage_template_user_label": "<code>{label}</code> is the user's Storage Label",
|
||||
"system_settings": "System Settings",
|
||||
"tag_cleanup_job": "Tag cleanup",
|
||||
"theme_custom_css_settings": "Custom CSS",
|
||||
"theme_custom_css_settings_description": "Cascading Style Sheets allow the design of Immich to be customized.",
|
||||
"theme_settings": "Theme Settings",
|
||||
@@ -309,6 +314,7 @@
|
||||
"trash_settings_description": "Manage trash settings",
|
||||
"untracked_files": "Untracked Files",
|
||||
"untracked_files_description": "These files are not tracked by the application. They can be the results of failed moves, interrupted uploads, or left behind due to a bug",
|
||||
"user_cleanup_job": "User cleanup",
|
||||
"user_delete_delay": "<b>{user}</b>'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.",
|
||||
@@ -1074,6 +1080,7 @@
|
||||
"search_options": "Search options",
|
||||
"search_people": "Search people",
|
||||
"search_places": "Search places",
|
||||
"search_settings": "Search settings",
|
||||
"search_state": "Search state...",
|
||||
"search_tags": "Search tags...",
|
||||
"search_timezone": "Search timezone...",
|
||||
|
||||
@@ -152,7 +152,7 @@
|
||||
"note_cannot_be_changed_later": "NOTA: No se puede cambiar posteriormente!",
|
||||
"note_unlimited_quota": "Nota: usa 0 para espacio sin límites",
|
||||
"notification_email_from_address": "Desde",
|
||||
"notification_email_from_address_description": "Dirección de correo electrónico del remitente, por ejemplo: \"Immich Photo Server <noreply@immich.app>\"",
|
||||
"notification_email_from_address_description": "Dirección de correo electrónico del remitente, por ejemplo: \"Immich Photo Server <noreply@example.com>\"",
|
||||
"notification_email_host_description": "Host del servidor de correo electrónico (por ejemplo: smtp.immich.app)",
|
||||
"notification_email_ignore_certificate_errors": "Ignorar errores de certificado",
|
||||
"notification_email_ignore_certificate_errors_description": "Ignorar los errores de validación del certificado TLS (no recomendado)",
|
||||
@@ -312,7 +312,7 @@
|
||||
"trash_settings_description": "Administrar la configuración de la papelera",
|
||||
"untracked_files": "Archivos sin seguimiento",
|
||||
"untracked_files_description": "La aplicación no rastrea estos archivos. Puede ser el resultado de movimientos fallidos, cargas interrumpidas o sin procesar debido a un error",
|
||||
"user_delete_delay": "La cuenta <b>{user}</b> y los archivos se programarán para su eliminación permanente en {delay, plural, one {# day} other {# days}}.",
|
||||
"user_delete_delay": "La cuenta <b>{user}</b> y los archivos se programarán para su eliminación permanente en {delay, plural, one {# día} other {# días}}.",
|
||||
"user_delete_delay_settings": "Eliminar retardo",
|
||||
"user_delete_delay_settings_description": "Número de días después de la eliminación para eliminar permanentemente la cuenta y los activos de un usuario. El trabajo de eliminación de usuarios se ejecuta a medianoche para comprobar si hay usuarios que estén listos para su eliminación. Los cambios a esta configuración se evaluarán en la próxima ejecución.",
|
||||
"user_delete_immediately": "La cuenta <b>{user}</b> y los archivos se pondrán en cola para su eliminación permanente <b>inmediatamente</b>.",
|
||||
@@ -336,8 +336,8 @@
|
||||
"admin_password": "Contraseña del Administrador",
|
||||
"administration": "Administración",
|
||||
"advanced": "Avanzada",
|
||||
"age_months": "Tiempo {months, plural, one {# month} other {# months}}",
|
||||
"age_year_months": "1 año, {months, plural, one {# month} other {# months}}",
|
||||
"age_months": "Tiempo {months, plural, one {# mes} other {# meses}}",
|
||||
"age_year_months": "1 año, {months, plural, one {# mes} other {# meses}}",
|
||||
"age_years": "Edad {years, plural, one {# año} other {# años}}",
|
||||
"album_added": "Álbum añadido",
|
||||
"album_added_notification_setting_description": "Reciba una notificación por correo electrónico cuando lo agreguen a un álbum compartido",
|
||||
@@ -400,12 +400,12 @@
|
||||
"assets_added_to_name_count": "Añadido {count, plural, one {# asset} other {# assets}} a {hasName, select, true {<b>{name}</b>} other {new album}}",
|
||||
"assets_count": "{count, plural, one {# activo} other {# activos}}",
|
||||
"assets_moved_to_trash": "Se movió {count, plural, one {# activo} other {# activos}} a la papelera",
|
||||
"assets_moved_to_trash_count": "Movido {count, plural, one {# asset} other {# assets}} a la papelera",
|
||||
"assets_permanently_deleted_count": "Eliminado permanentemente {count, plural, one {# asset} other {# assets}}",
|
||||
"assets_removed_count": "Eliminado {count, plural, one {# asset} other {# assets}}",
|
||||
"assets_moved_to_trash_count": "Movido {count, plural, one {# elemento} other {# elementos}} a la papelera",
|
||||
"assets_permanently_deleted_count": "Eliminado permanentemente {count, plural, one {# elemento} other {# elementos}}",
|
||||
"assets_removed_count": "Eliminado {count, plural, one {# elemento} other {# elementos}}",
|
||||
"assets_restore_confirmation": "¿Está seguro de que desea restaurar todos sus archivos eliminados? ¡No puedes deshacer esta acción!",
|
||||
"assets_restored_count": "Restaurado {count, plural, one {# asset} other {# assets}}",
|
||||
"assets_trashed_count": "Borrado {count, plural, one {# asset} other {# assets}}",
|
||||
"assets_restored_count": "Restaurado {count, plural, one {# elemento} other {# elementos}}",
|
||||
"assets_trashed_count": "Borrado {count, plural, one {# elemento} other {# elementos}}",
|
||||
"assets_were_part_of_album_count": "{count, plural, one {Asset was} other {Assets were}} ya forma parte del álbum",
|
||||
"authorized_devices": "Dispositivos Autorizados",
|
||||
"back": "Atrás",
|
||||
@@ -416,7 +416,7 @@
|
||||
"blurred_background": "Fondo borroso",
|
||||
"build": "Compilación",
|
||||
"build_image": "Construir Imagen",
|
||||
"bulk_delete_duplicates_confirmation": "¿Estás seguro de que deseas eliminar de forma masiva {count, plural, one {# duplicate asset} other {# duplicate assets}}? Esto mantendrá el activo más grande de cada grupo y eliminará permanentemente todos los demás duplicados. ¡Esta acción no se puede deshacer!",
|
||||
"bulk_delete_duplicates_confirmation": "¿Estás seguro de que deseas eliminar de forma masiva {count, plural, one {# elemento duplicado} other {# elementos duplicados}}? Esto mantendrá el activo más grande de cada grupo y eliminará permanentemente todos los demás duplicados. ¡Esta acción no se puede deshacer!",
|
||||
"bulk_keep_duplicates_confirmation": "¿Estas seguro de que desea mantener {count, plural, one {# duplicate asset} other {# duplicate assets}} archivos duplicados? Esto resolverá todos los grupos duplicados sin borrar nada.",
|
||||
"bulk_trash_duplicates_confirmation": "¿Estas seguro de que desea eliminar masivamente {count, plural, one {# duplicate asset} other {# duplicate assets}} archivos duplicados? Esto mantendrá el archivo más grande de cada grupo y eliminará todos los demás duplicados.",
|
||||
"buy": "Comprar Immich",
|
||||
@@ -589,7 +589,7 @@
|
||||
"cant_apply_changes": "No se pueden aplicar los cambios",
|
||||
"cant_change_activity": "No se puede realizar la actividad {enabled, select, true {disable} other {enable}}",
|
||||
"cant_change_asset_favorite": "No se puede cambiar favorito para este archivo",
|
||||
"cant_change_metadata_assets_count": "No se pueden cambiar los metadatos de {count, plural, one {# asset} other {# assets}}",
|
||||
"cant_change_metadata_assets_count": "No se pueden cambiar los metadatos de {count, plural, one {# elemento} other {# elementos}}",
|
||||
"cant_get_faces": "No se encuentran caras",
|
||||
"cant_get_number_of_comments": "No se puede obtener la cantidad de comentarios",
|
||||
"cant_search_people": "No se puede buscar a personas",
|
||||
@@ -616,7 +616,7 @@
|
||||
"failed_to_unstack_assets": "Error al desagrupar los archivos",
|
||||
"import_path_already_exists": "Esta ruta de importación ya existe.",
|
||||
"incorrect_email_or_password": "Contraseña o email incorrecto",
|
||||
"paths_validation_failed": "Falló la validación en {paths, plural, one {# carpetas} other {# carpetas}}",
|
||||
"paths_validation_failed": "Falló la validación en {paths, plural, one {# carpeta} other {# carpetas}}",
|
||||
"profile_picture_transparent_pixels": "Las imágenes de perfil no pueden tener píxeles transparentes. Por favor amplíe y/o mueva la imagen.",
|
||||
"quota_higher_than_disk_size": "Se ha establecido una cuota superior al tamaño del disco",
|
||||
"repair_unable_to_check_items": "No se puede verificar {count, select, one {elemento} other {elementos}}",
|
||||
@@ -634,7 +634,7 @@
|
||||
"unable_to_change_favorite": "Imposible cambiar el archivo favorito",
|
||||
"unable_to_change_location": "No se puede cambiar de ubicación",
|
||||
"unable_to_change_password": "No se puede cambiar la contraseña",
|
||||
"unable_to_change_visibility": "No se puede cambiar la visibilidad de {count, plural, one {# person} other {# people}}",
|
||||
"unable_to_change_visibility": "No se puede cambiar la visibilidad de {count, plural, one {# persona} other {# personas}}",
|
||||
"unable_to_check_item": "",
|
||||
"unable_to_check_items": "",
|
||||
"unable_to_complete_oauth_login": "No se puede completar el inicio de sesión de OAuth",
|
||||
@@ -661,6 +661,7 @@
|
||||
"unable_to_get_comments_number": "No se puede obtener el número de comentarios",
|
||||
"unable_to_get_shared_link": "Error al obtener el enlace compartido",
|
||||
"unable_to_hide_person": "No se puede ocultar a la persona",
|
||||
"unable_to_link_motion_video": "No se puede enlazar el vídeo en movimiento",
|
||||
"unable_to_link_oauth_account": "No se puede vincular la cuenta OAuth",
|
||||
"unable_to_load_album": "No se puede cargar el álbum",
|
||||
"unable_to_load_asset_activity": "No se puede cargar la actividad de los archivos",
|
||||
@@ -701,6 +702,7 @@
|
||||
"unable_to_submit_job": "No se puede enviar el trabajo",
|
||||
"unable_to_trash_asset": "No se puede eliminar el archivo",
|
||||
"unable_to_unlink_account": "No se puede desvincular la cuenta",
|
||||
"unable_to_unlink_motion_video": "No se puede desvincular el vídeo en movimiento",
|
||||
"unable_to_update_album_cover": "No se puede actualizar la portada del álbum",
|
||||
"unable_to_update_album_info": "No se puede actualizar la información del álbum",
|
||||
"unable_to_update_library": "No se puede actualizar la biblioteca",
|
||||
@@ -846,6 +848,7 @@
|
||||
"license_trial_info_4": "Por favor, considera la compra de una licencia para apoyar el desarrollo continuo del servicio",
|
||||
"light": "Claro",
|
||||
"like_deleted": "Me gusta eliminado",
|
||||
"link_motion_video": "Enlazar vídeo en movimiento",
|
||||
"link_options": "Opciones de enlace",
|
||||
"link_to_oauth": "Enlace a OAuth",
|
||||
"linked_oauth_account": "Cuenta OAuth vinculada",
|
||||
@@ -888,7 +891,7 @@
|
||||
"merge_people_limit": "Solo puedes fusionar hasta 5 caras a la vez",
|
||||
"merge_people_prompt": "¿Quieres fusionar a estas personas? Esta acción es irreversible.",
|
||||
"merge_people_successfully": "Personas fusionadas correctamente",
|
||||
"merged_people_count": "Fusionar {count, plural, one {# person} other {# people}}",
|
||||
"merged_people_count": "Fusionada {count, plural, one {# persona} other {# personas}}",
|
||||
"minimize": "Minimizar",
|
||||
"minute": "Minuto",
|
||||
"missing": "Perdido",
|
||||
@@ -969,9 +972,9 @@
|
||||
"password_required": "Contraseña requerida",
|
||||
"password_reset_success": "Restablecimiento de contraseña exitoso",
|
||||
"past_durations": {
|
||||
"days": "Pasados {days, plural, one {day} other {# days}}",
|
||||
"hours": "Pasadas {hours, plural, one {hour} other {# hours}}",
|
||||
"years": "Pasado(s) {years, plural, one {year} other {# years}}"
|
||||
"days": "Pasados {days, plural, one {día} other {# días}}",
|
||||
"hours": "Pasadas {hours, plural, one {hora} other {# horas}}",
|
||||
"years": "Pasado(s) {years, plural, one {año} other {# años}}"
|
||||
},
|
||||
"path": "Ruta",
|
||||
"pattern": "Patrón",
|
||||
@@ -980,18 +983,18 @@
|
||||
"paused": "Detenido",
|
||||
"pending": "Pendiente",
|
||||
"people": "Personas",
|
||||
"people_edits_count": "Editado {count, plural, one {# person} other {# people}}",
|
||||
"people_edits_count": "Editada {count, plural, one {# persona} other {# personas}}",
|
||||
"people_feature_description": "Explorar fotos y vídeos agrupados por personas",
|
||||
"people_sidebar_description": "Mostrar un enlace a Personas en la barra lateral",
|
||||
"perform_library_tasks": "",
|
||||
"permanent_deletion_warning": "Advertencia de eliminación permanente",
|
||||
"permanent_deletion_warning_setting_description": "Mostrar una advertencia al eliminar archivos permanentemente",
|
||||
"permanently_delete": "Borrar permanentemente",
|
||||
"permanently_delete_assets_count": "Eliminar permanentemente {count, plural, one {asset} other {assets}}",
|
||||
"permanently_delete_assets_prompt": "¿Está seguro de que desea eliminar permanentemente {count, plural, one {¿este activo?} other {¿estos <b>#</b> activos?}} Esto también eliminará {count, plural, one {de tu} other {de tus}} álbum(es).",
|
||||
"permanently_delete_assets_count": "Eliminar permanentemente {count, plural, one {elemento} other {elementos}}",
|
||||
"permanently_delete_assets_prompt": "¿Está seguro de que desea eliminar permanentemente {count, plural, one {este activo?} other {estos <b>#</b> activos?}} Esto también eliminará {count, plural, one {de tu} other {de tus}} álbum(es).",
|
||||
"permanently_deleted_asset": "Archivo eliminado permanentemente",
|
||||
"permanently_deleted_assets": "Eliminado permanentemente {count, plural, one {# activo} other {# activos}}",
|
||||
"permanently_deleted_assets_count": "Eliminado permanentemente {count, plural, one {# asset} other {# assets}}",
|
||||
"permanently_deleted_assets_count": "Eliminado permanentemente {count, plural, one {# elemento} other {# elementos}}",
|
||||
"person": "Persona",
|
||||
"person_hidden": "{name}{hidden, select, true { (oculto)} other {}}",
|
||||
"photo_shared_all_users": "Parece que compartiste tus fotos con todos los usuarios o no tienes ningún usuario con quien compartirlas.",
|
||||
@@ -1060,8 +1063,8 @@
|
||||
"reaction_options": "Opciones de reacción",
|
||||
"read_changelog": "Leer registro de cambios",
|
||||
"reassign": "Reasignar",
|
||||
"reassigned_assets_to_existing_person": "Reasignado {count, plural, one {# asset} other {# assets}} to {name, select, null {an existing person} other {{name}}}",
|
||||
"reassigned_assets_to_new_person": "Reasignado {count, plural, one {# asset} other {# assets}} a un nuevo usuario",
|
||||
"reassigned_assets_to_existing_person": "Reasignado {count, plural, one {# elemento} other {# elementos}} a {name, select, null {una persona existente} other {{name}}}",
|
||||
"reassigned_assets_to_new_person": "Reasignado {count, plural, one {# elemento} other {# elementos}} a un nuevo usuario",
|
||||
"reassing_hint": "Asignar archivos seleccionados a una persona existente",
|
||||
"recent": "Reciente",
|
||||
"recent_searches": "Búsquedas recientes",
|
||||
@@ -1075,8 +1078,8 @@
|
||||
"refreshing_metadata": "Recargando metadatos",
|
||||
"regenerating_thumbnails": "Recargando miniaturas",
|
||||
"remove": "Eliminar",
|
||||
"remove_assets_album_confirmation": "¿Estás seguro que quieres eliminar {count, plural, one {# asset} other {# assets}} del álbum?",
|
||||
"remove_assets_shared_link_confirmation": "¿Estás seguro que quieres eliminar {count, plural, one {# asset} other {# assets}} del enlace compartido?",
|
||||
"remove_assets_album_confirmation": "¿Estás seguro que quieres eliminar {count, plural, one {# elemento} other {# elementos}} del álbum?",
|
||||
"remove_assets_shared_link_confirmation": "¿Estás seguro que quieres eliminar {count, plural, one {# elemento} other {# elementos}} del enlace compartido?",
|
||||
"remove_assets_title": "¿Eliminar activos?",
|
||||
"remove_custom_date_range": "Eliminar intervalo de fechas personalizado",
|
||||
"remove_from_album": "Eliminar del álbum",
|
||||
@@ -1087,7 +1090,7 @@
|
||||
"removed_api_key": "Clave API eliminada: {name}",
|
||||
"removed_from_archive": "Eliminado del archivo",
|
||||
"removed_from_favorites": "Eliminado de favoritos",
|
||||
"removed_from_favorites_count": "{count, plural, other {Removed #}} de favoritos",
|
||||
"removed_from_favorites_count": "{count, plural, other {Eliminados #}} de favoritos",
|
||||
"removed_tagged_assets": "Etiqueta eliminada de {count, plural, one {# activo} other {# activos}}",
|
||||
"rename": "Renombrar",
|
||||
"repair": "Reparar",
|
||||
@@ -1135,6 +1138,7 @@
|
||||
"search_for_existing_person": "Buscar persona existente",
|
||||
"search_no_people": "Ninguna persona",
|
||||
"search_no_people_named": "Ninguna persona llamada \"{name}\"",
|
||||
"search_options": "Opciones de búsqueda",
|
||||
"search_people": "Buscar personas",
|
||||
"search_places": "Buscar lugar",
|
||||
"search_state": "Buscar región/estado...",
|
||||
@@ -1229,7 +1233,7 @@
|
||||
"stack_duplicates": "Apilar duplicados",
|
||||
"stack_select_one_photo": "Selecciona una imagen principal para la pila",
|
||||
"stack_selected_photos": "Apilar fotos seleccionadas",
|
||||
"stacked_assets_count": "Apilados {count, plural, one {# asset} other {# assets}}",
|
||||
"stacked_assets_count": "Apilado(s) {count, plural, one {# activo} other {# activos}}",
|
||||
"stacktrace": "Stacktrace",
|
||||
"start": "Inicio",
|
||||
"start_date": "Fecha de inicio",
|
||||
@@ -1289,6 +1293,7 @@
|
||||
"unknown_album": "Álbum desconocido",
|
||||
"unknown_year": "Año desconocido",
|
||||
"unlimited": "Ilimitado",
|
||||
"unlink_motion_video": "Desvincular vídeo en movimiento",
|
||||
"unlink_oauth": "Desvincular OAuth",
|
||||
"unlinked_oauth_account": "Cuenta OAuth desconectada",
|
||||
"unnamed_album": "Album sin nombre",
|
||||
@@ -1298,14 +1303,14 @@
|
||||
"unselect_all": "Limpiar selección",
|
||||
"unselect_all_duplicates": "Deseleccionar todos los duplicados",
|
||||
"unstack": "Desapilar",
|
||||
"unstacked_assets_count": "Sin apilar {count, plural, one {# asset} other {# assets}}",
|
||||
"unstacked_assets_count": "Desapilado(s) {count, plural, one {# elemento} other {# elementos}}",
|
||||
"untracked_files": "Archivos no monitorizados",
|
||||
"untracked_files_decription": "Estos archivos no están siendo monitorizados por la aplicación. Es posible que sean resultado de errores al moverlos, cargas interrumpidas o por un fallo de la aplicación",
|
||||
"up_next": "A continuación",
|
||||
"updated_password": "Contraseña actualizada",
|
||||
"upload": "Subir",
|
||||
"upload_concurrency": "Cargas simultáneas",
|
||||
"upload_errors": "Carga completada con {count, plural, one {# error} other {# errors}}, actualice la página para ver los nuevos recursos de carga.",
|
||||
"upload_errors": "Carga completada con {count, plural, one {# error} other {# errores}}, actualice la página para ver los nuevos recursos de carga.",
|
||||
"upload_progress": "Restante {remaining, number} - Procesado {processed, number}/{total, number}",
|
||||
"upload_skipped_duplicates": "Saltado {count, plural, one {# duplicate asset} other {# duplicate assets}}",
|
||||
"upload_status_duplicates": "Duplicados",
|
||||
@@ -1347,14 +1352,14 @@
|
||||
"view_previous_asset": "Mostrar elemento anterior",
|
||||
"view_stack": "Ver Pila",
|
||||
"viewer": "Visualizador",
|
||||
"visibility_changed": "Visibilidad cambiada para {count, plural, one {# person} other {# people}}",
|
||||
"visibility_changed": "Visibilidad cambiada para {count, plural, one {# persona} other {# personas}}",
|
||||
"waiting": "Esperando",
|
||||
"warning": "Advertencia",
|
||||
"week": "Semana",
|
||||
"welcome": "Bienvenido",
|
||||
"welcome_to_immich": "Bienvenido a immich",
|
||||
"year": "Año",
|
||||
"years_ago": "Hace {years, plural, one {# year} other {# years}}",
|
||||
"years_ago": "Hace {years, plural, one {# año} other {# años}}",
|
||||
"yes": "Sí",
|
||||
"you_dont_have_any_shared_links": "No tienes ningún enlace compartido",
|
||||
"zoom_image": "Acercar Imagen"
|
||||
|
||||
@@ -125,7 +125,7 @@
|
||||
"migration_job_description": "Migreeri üksuste ja nägude pisipildid uusimale kaustastruktuurile",
|
||||
"note_cannot_be_changed_later": "MÄRKUS: Seda ei saa hiljem muuta!",
|
||||
"notification_email_from_address": "Saatja aadress",
|
||||
"notification_email_from_address_description": "Saatja e-posti aadress, näiteks: \"Immich Photo Server <noreply@immich.app>\"",
|
||||
"notification_email_from_address_description": "Saatja e-posti aadress, näiteks: \"Immich Photo Server <noreply@example.com>\"",
|
||||
"notification_email_host_description": "E-posti serveri host (nt. smtp.immich.app)",
|
||||
"notification_email_ignore_certificate_errors": "Ignoreeri sertifikaadi vigu",
|
||||
"notification_email_ignore_certificate_errors_description": "Ignoreeri TLS sertifikaadi valideerimise vigu (mittesoovituslik)",
|
||||
|
||||
@@ -144,7 +144,7 @@
|
||||
"note_cannot_be_changed_later": "توجه: این را نمی توان بعداً تغییر داد!",
|
||||
"note_unlimited_quota": "توجه: برای سهمیه نامحدود، عدد 0 را وارد کنید",
|
||||
"notification_email_from_address": "آدرس فرستنده",
|
||||
"notification_email_from_address_description": "آدرس ایمیل فرستنده، به عنوان مثال:\"Immich سرور عکس <noreply@immich.app>\"",
|
||||
"notification_email_from_address_description": "آدرس ایمیل فرستنده، به عنوان مثال:\"Immich سرور عکس <noreply@example.com>\"",
|
||||
"notification_email_host_description": "میزبان سرور ایمیل (مثلاً smtp.immich.app)",
|
||||
"notification_email_ignore_certificate_errors": "خطاهای گواهی را نادیده بگیر",
|
||||
"notification_email_ignore_certificate_errors_description": "خطاهای اعتبارسنجی گواهی TLS را نادیده بگیر (توصیه نمیشود)",
|
||||
|
||||
@@ -140,6 +140,10 @@
|
||||
"map_style_description": "style.json -karttateeman URL",
|
||||
"metadata_extraction_job": "Kerää metadata",
|
||||
"metadata_extraction_job_description": "Poimi metatiedot aineistoista, kuten GPS ja resoluutio",
|
||||
"metadata_faces_import_setting": "Ota käyttöön kasvojen tuonti",
|
||||
"metadata_faces_import_setting_description": "Tuo kasvot kuvan EXIF -tiedoista ja kylkiäistiedostoista",
|
||||
"metadata_settings": "Metatietoasetukset",
|
||||
"metadata_settings_description": "Hallitse metatietoja",
|
||||
"migration_job": "Migrointi",
|
||||
"migration_job_description": "Migroi aineiston pikkukuvat ja kasvot uusimpaan kansiorakenteeseen",
|
||||
"no_paths_added": "Polkuja ei asetettu",
|
||||
@@ -148,7 +152,7 @@
|
||||
"note_cannot_be_changed_later": "Huom: Tätä ei voi enää myöhemmin vaihtaa!",
|
||||
"note_unlimited_quota": "Huom: Määritä 0 rajoittamattomaksi kiintiöksi",
|
||||
"notification_email_from_address": "Lähettäjän osoite",
|
||||
"notification_email_from_address_description": "Lähettäjän sähköpostiosoite. Esimerkiksi \"Immich Kuvapalvelin <noreply@immich.app>\"",
|
||||
"notification_email_from_address_description": "Lähettäjän sähköpostiosoite. Esimerkiksi \"Immich Kuvapalvelin <noreply@example.com>\"",
|
||||
"notification_email_host_description": "Sähköpostipalvelin (esim. smtp.immich.app)",
|
||||
"notification_email_ignore_certificate_errors": "Älä huomioi sertifikaattivirheitä",
|
||||
"notification_email_ignore_certificate_errors_description": "Älä huomioi TLS sertifikaattien validointivirheitä (ei suositeltu)",
|
||||
@@ -963,6 +967,7 @@
|
||||
"send_message": "Lähetä viesti",
|
||||
"send_welcome_email": "Lähetä tervetuloviesti",
|
||||
"server": "Palvelin",
|
||||
"server_online": "Palvelin on linjalla",
|
||||
"server_stats": "Palvelimen tilastot",
|
||||
"server_version": "Palvelimen versio",
|
||||
"set": "Aseta",
|
||||
@@ -1113,6 +1118,7 @@
|
||||
"view_album": "Näytä albumi",
|
||||
"view_all": "Näytä kaikki",
|
||||
"view_all_users": "Näytä kaikki käyttäjät",
|
||||
"view_in_timeline": "Näytä aikajanalla",
|
||||
"view_links": "Näytä linkit",
|
||||
"view_next_asset": "Näytä seuraava",
|
||||
"view_previous_asset": "Näytä edellinen",
|
||||
|
||||
@@ -148,7 +148,7 @@
|
||||
"migration_job_description": "Migration des miniatures pour les médias et les visages vers la dernière structure de dossiers",
|
||||
"no_paths_added": "Aucun chemin n'a été ajouté",
|
||||
"no_pattern_added": "Aucun schéma d'exclusion n'a été ajouté",
|
||||
"note_apply_storage_label_previous_assets": "Remarque : pour appliquer l'étiquette de stockage à des médias précédemment téléversés, exécutez la commande",
|
||||
"note_apply_storage_label_previous_assets": "Remarque : pour appliquer l'étiquette de stockage à des médias précédemment envoyés, exécutez la commande",
|
||||
"note_cannot_be_changed_later": "REMARQUE : Il n'est pas possible de modifier ce paramètre ultérieurement !",
|
||||
"note_unlimited_quota": "Note : saisir 0 pour un quota illimité",
|
||||
"notification_email_from_address": "Depuis l'adresse",
|
||||
@@ -228,14 +228,14 @@
|
||||
"storage_template_hash_verification_enabled": "Vérification du hachage activée",
|
||||
"storage_template_hash_verification_enabled_description": "Active la vérification du hachage, ne désactivez pas cette option à moins d'être sûr de ce que vous faites",
|
||||
"storage_template_migration": "Migration du modèle de stockage",
|
||||
"storage_template_migration_description": "Appliquer le modèle courant <link>{template}</link> aux médias précédemment téléchargés",
|
||||
"storage_template_migration_info": "Les changements de modèle ne s'appliqueront qu'aux nouveaux médias. Pour appliquer rétroactivement le modèle aux médias précédemment téléchargés, exécutez la tâche <link>{job}</link>.",
|
||||
"storage_template_migration_description": "Appliquer le modèle courant <link>{template}</link> aux médias précédemment envoyés",
|
||||
"storage_template_migration_info": "Les changements de modèle ne s'appliqueront qu'aux nouveaux médias. Pour appliquer rétroactivement le modèle aux médias précédemment envoyés, exécutez la tâche <link>{job}</link>.",
|
||||
"storage_template_migration_job": "Tâche de migration du modèle de stockage",
|
||||
"storage_template_more_details": "Pour plus de détails sur cette fonctionnalité, reportez-vous au <template-link>Modèle de stockage</template-link> et à ses <implications-link>implications</implications-link>",
|
||||
"storage_template_onboarding_description": "Lorsqu'elle est activée, cette fonctionnalité réorganise les fichiers basés sur un modèle défini par l'utilisateur. En raison de problèmes de stabilité, la fonction a été désactivée par défaut. Pour plus d'informations, veuillez consulter la <link>documentation</link>.",
|
||||
"storage_template_path_length": "Limite approximative de la longueur du chemin : <b>{length, number}</b>/{limit, number}",
|
||||
"storage_template_settings": "Modèle de stockage",
|
||||
"storage_template_settings_description": "Gérer la structure des dossiers et le nom des fichiers du média téléversé",
|
||||
"storage_template_settings_description": "Gérer la structure des dossiers et le nom des fichiers du média envoyé",
|
||||
"storage_template_user_label": "<code>{label}</code> est l'étiquette de stockage de l'utilisateur",
|
||||
"system_settings": "Paramètres du système",
|
||||
"theme_custom_css_settings": "CSS personnalisé",
|
||||
@@ -311,7 +311,7 @@
|
||||
"trash_settings": "Corbeille",
|
||||
"trash_settings_description": "Gérer les paramètres de la corbeille",
|
||||
"untracked_files": "Fichiers non suivis",
|
||||
"untracked_files_description": "Ces fichiers ne sont pas suivis par l'application. Ils peuvent être le résultat d'erreurs de déplacement, téléchargements interrompus, ou abandons en raison d'un bug",
|
||||
"untracked_files_description": "Ces fichiers ne sont pas suivis par l'application. Ils peuvent être le résultat d'erreurs de déplacement, d'envois interrompus, ou d'abandons en raison d'un bug",
|
||||
"user_delete_delay": "La suppression définitive du compte et des médias de <b>{user}</b> sera programmée dans {delay, plural, one {# jour} other {# jours}}.",
|
||||
"user_delete_delay_settings": "Délai de suppression",
|
||||
"user_delete_delay_settings_description": "Nombre de jours après la validation pour supprimer définitivement le compte et les médias d'un utilisateur. La suppression des utilisateurs se lance à minuit. Les modifications apportées à ce paramètre seront pris en compte lors de la prochaine exécution.",
|
||||
@@ -366,7 +366,7 @@
|
||||
"allow_dark_mode": "Autoriser le mode sombre",
|
||||
"allow_edits": "Autoriser les modifications",
|
||||
"allow_public_user_to_download": "Permettre aux utilisateurs non connectés de télécharger",
|
||||
"allow_public_user_to_upload": "Permettre aux utilisateurs non connectés de téléverser",
|
||||
"allow_public_user_to_upload": "Permettre l'envoi aux utilisateurs non connectés",
|
||||
"anti_clockwise": "Sens anti-horaire",
|
||||
"api_key": "Clé API",
|
||||
"api_key_description": "Cette valeur ne sera affichée qu'une seule fois. Assurez-vous de la copier avant de fermer la fenêtre.",
|
||||
@@ -391,8 +391,9 @@
|
||||
"asset_offline": "Média hors ligne",
|
||||
"asset_offline_description": "Ce média est hors ligne. Immich ne peut pas accéder à son emplacement physique. Veuillez vous assurez que le média est disponible, puis relancez l'analyse de la bibliothèque.",
|
||||
"asset_skipped": "Sauté",
|
||||
"asset_uploaded": "Téléversé",
|
||||
"asset_uploading": "Chargement...",
|
||||
"asset_skipped_in_trash": "À la corbeille",
|
||||
"asset_uploaded": "Envoyé",
|
||||
"asset_uploading": "Envoi...",
|
||||
"assets": "Médias",
|
||||
"assets_added_count": "{count, plural, one {# média ajouté} other {# médias ajoutés}}",
|
||||
"assets_added_to_album_count": "{count, plural, one {# média ajouté} other {# médias ajoutés}} à l'album",
|
||||
@@ -537,7 +538,7 @@
|
||||
"download_settings_description": "Gérer les paramètres de téléchargement des médias",
|
||||
"downloading": "Téléchargement",
|
||||
"downloading_asset_filename": "Téléchargement du média {filename}",
|
||||
"drop_files_to_upload": "Déposer des fichiers n'importe où pour téléverser",
|
||||
"drop_files_to_upload": "Déposez les fichiers n'importe où pour envoyer",
|
||||
"duplicates": "Doublons",
|
||||
"duplicates_description": "Examiner chaque groupe et indiquer s'il y a des doublons",
|
||||
"duration": "Durée",
|
||||
@@ -613,7 +614,7 @@
|
||||
"failed_to_remove_product_key": "Échec de suppression de la clé du produit",
|
||||
"failed_to_stack_assets": "Impossible d'empiler les médias",
|
||||
"failed_to_unstack_assets": "Impossible de dépiler les médias",
|
||||
"import_path_already_exists": "Ce chemin d'import existe déjà.",
|
||||
"import_path_already_exists": "Ce chemin d'importation existe déjà.",
|
||||
"incorrect_email_or_password": "Courriel ou mot de passe incorrect",
|
||||
"paths_validation_failed": "Validation échouée pour {paths, plural, one {# un chemin} other {# plusieurs chemins}}",
|
||||
"profile_picture_transparent_pixels": "Les images de profil ne peuvent pas avoir de pixels transparents. Veuillez agrandir et/ou déplacer l'image.",
|
||||
@@ -623,7 +624,7 @@
|
||||
"unable_to_add_assets_to_shared_link": "Impossible d'ajouter des médias au lien partagé",
|
||||
"unable_to_add_comment": "Impossible d'ajouter un commentaire",
|
||||
"unable_to_add_exclusion_pattern": "Impossible d'ajouter un schéma d'exclusion",
|
||||
"unable_to_add_import_path": "Impossible d'ajouter un chemin d'import",
|
||||
"unable_to_add_import_path": "Impossible d'ajouter le chemin d'importation",
|
||||
"unable_to_add_partners": "Impossible d'ajouter des partenaires",
|
||||
"unable_to_add_remove_archive": "Impossible {archived, select, true {de supprimer des médias de} other {d'ajouter des médias à}} l'archive",
|
||||
"unable_to_add_remove_favorites": "Impossible {favorite, select, true {d'ajouter des médias aux} other {de supprimer des médias des}} favoris",
|
||||
@@ -648,18 +649,19 @@
|
||||
"unable_to_delete_asset": "Suppression du média impossible",
|
||||
"unable_to_delete_assets": "Erreur lors de la suppression des médias",
|
||||
"unable_to_delete_exclusion_pattern": "Suppression du modèle d'exclusion impossible",
|
||||
"unable_to_delete_import_path": "Suppression du chemin d'import impossible",
|
||||
"unable_to_delete_import_path": "Suppression du chemin d'importation impossible",
|
||||
"unable_to_delete_shared_link": "Suppression du lien de partage impossible",
|
||||
"unable_to_delete_user": "Suppression de l'utilisateur impossible",
|
||||
"unable_to_download_files": "Impossible de télécharger les fichiers",
|
||||
"unable_to_edit_exclusion_pattern": "Modification du modèle d'exclusion impossible",
|
||||
"unable_to_edit_import_path": "Modification du chemin d'import impossible",
|
||||
"unable_to_edit_import_path": "Modification du chemin d'importation impossible",
|
||||
"unable_to_empty_trash": "Impossible de vider la corbeille",
|
||||
"unable_to_enter_fullscreen": "Mode plein écran indisponible",
|
||||
"unable_to_exit_fullscreen": "Sortie du mode plein écran impossible",
|
||||
"unable_to_get_comments_number": "Impossible d'obtenir le nombre de commentaires",
|
||||
"unable_to_get_shared_link": "Échec de la récupération du lien partagé",
|
||||
"unable_to_hide_person": "Impossible de cacher la personne",
|
||||
"unable_to_link_motion_video": "Impossible de lier la photo animée",
|
||||
"unable_to_link_oauth_account": "Impossible de lier le compte OAuth",
|
||||
"unable_to_load_album": "Impossible de charger l'album",
|
||||
"unable_to_load_asset_activity": "Impossible de charger l'activité du média",
|
||||
@@ -700,6 +702,7 @@
|
||||
"unable_to_submit_job": "Impossible d'exécuter la tâche",
|
||||
"unable_to_trash_asset": "Impossible de mettre le média à la corbeille",
|
||||
"unable_to_unlink_account": "Impossible de détacher le compte",
|
||||
"unable_to_unlink_motion_video": "Impossible de détacher la photo animée",
|
||||
"unable_to_update_album_cover": "Impossible de mettre à jour la couverture de l'album",
|
||||
"unable_to_update_album_info": "Impossible de mettre à jour les informations de l'album",
|
||||
"unable_to_update_library": "Impossible de mettre à jour la bibliothèque",
|
||||
@@ -707,7 +710,7 @@
|
||||
"unable_to_update_settings": "Impossible de mettre à jour les paramètres",
|
||||
"unable_to_update_timeline_display_status": "Impossible de mettre à jour le statut d'affichage de la timeline",
|
||||
"unable_to_update_user": "Impossible de mettre à jour l'utilisateur",
|
||||
"unable_to_upload_file": "Impossible de téléverser le fichier"
|
||||
"unable_to_upload_file": "Impossible d'envoyer le fichier"
|
||||
},
|
||||
"every_day_at_onepm": "",
|
||||
"every_night_at_midnight": "",
|
||||
@@ -845,6 +848,7 @@
|
||||
"license_trial_info_4": "Pensez à acheter une licence pour soutenir le développement du service",
|
||||
"light": "Clair",
|
||||
"like_deleted": "Réaction « j'aime » supprimée",
|
||||
"link_motion_video": "Lier la photo animée",
|
||||
"link_options": "Options de lien",
|
||||
"link_to_oauth": "Lien au service OAuth",
|
||||
"linked_oauth_account": "Compte OAuth rattaché",
|
||||
@@ -913,10 +917,10 @@
|
||||
"no_albums_with_name_yet": "Il semble que vous n'ayez pas encore d'albums avec ce nom.",
|
||||
"no_albums_yet": "Il semble que vous n'ayez pas encore d'album.",
|
||||
"no_archived_assets_message": "Archiver des photos et vidéos pour les masquer dans votre bibliothèque",
|
||||
"no_assets_message": "CLIQUER ICI POUR IMPORTER VOTRE PREMIÈRE PHOTO",
|
||||
"no_assets_message": "CLIQUER ICI POUR ENVOYER VOTRE PREMIÈRE PHOTO",
|
||||
"no_duplicates_found": "Aucun doublon n'a été trouvé.",
|
||||
"no_exif_info_available": "Aucune information exif disponible",
|
||||
"no_explore_results_message": "Importer plus de photos pour explorer votre collection.",
|
||||
"no_explore_results_message": "Envoyez plus de photos pour explorer votre collection.",
|
||||
"no_favorites_message": "Ajouter des photos et vidéos à vos favoris pour les retrouver plus rapidement",
|
||||
"no_libraries_message": "Créer une bibliothèque externe pour voir vos photos et vidéos dans un autre espace de stockage",
|
||||
"no_name": "Pas de nom",
|
||||
@@ -925,7 +929,7 @@
|
||||
"no_results_description": "Essayez un synonyme ou un mot-clé plus général",
|
||||
"no_shared_albums_message": "Créer un album pour partager vos photos et vidéos avec les personnes de votre réseau",
|
||||
"not_in_any_album": "Dans aucun album",
|
||||
"note_apply_storage_label_to_previously_uploaded assets": "Note : Pour appliquer l'étiquette de stockage aux médias déjà importés, lancer la",
|
||||
"note_apply_storage_label_to_previously_uploaded assets": "Note : Pour appliquer l'étiquette de stockage aux médias déjà envoyés, lancer la",
|
||||
"note_unlimited_quota": "Note : Saisir 0 pour définir un quota illimité",
|
||||
"notes": "Notes",
|
||||
"notification_toggle_setting_description": "Activer les notifications par courriel",
|
||||
@@ -1134,6 +1138,7 @@
|
||||
"search_for_existing_person": "Rechercher une personne existante",
|
||||
"search_no_people": "Aucune personne",
|
||||
"search_no_people_named": "Aucune personne nommée « {name} »",
|
||||
"search_options": "Rechercher une option",
|
||||
"search_people": "Rechercher une personne",
|
||||
"search_places": "Rechercher un lieu",
|
||||
"search_state": "Rechercher par état/région...",
|
||||
@@ -1288,6 +1293,7 @@
|
||||
"unknown_album": "",
|
||||
"unknown_year": "Année inconnue",
|
||||
"unlimited": "Illimité",
|
||||
"unlink_motion_video": "Détacher la photo animée",
|
||||
"unlink_oauth": "Déconnecter OAuth",
|
||||
"unlinked_oauth_account": "Compte OAuth non connecté",
|
||||
"unnamed_album": "Album sans nom",
|
||||
@@ -1299,18 +1305,18 @@
|
||||
"unstack": "Désempiler",
|
||||
"unstacked_assets_count": "{count, plural, one {# média dépilé} other {# médias dépilés}}",
|
||||
"untracked_files": "Fichiers non suivis",
|
||||
"untracked_files_decription": "Ces fichiers ne sont pas suivis par l'application. Ils peuvent être le résultat de déplacements échoués, de téléchargements interrompus ou laissés pour compte à cause d'un bug",
|
||||
"untracked_files_decription": "Ces fichiers ne sont pas suivis par l'application. Ils peuvent être le résultat de déplacements échoués, d'envois interrompus ou laissés pour compte à cause d'un bug",
|
||||
"up_next": "Suite",
|
||||
"updated_password": "Mot de passe mis à jour",
|
||||
"upload": "Téléverser",
|
||||
"upload_concurrency": "Envoi simultané",
|
||||
"upload_errors": "Le téléversement s'est achevé avec {count, plural, one {# erreur} other {# erreurs}}. Rafraîchir la page pour voir les nouveaux médias téléversés.",
|
||||
"upload": "Envoyer",
|
||||
"upload_concurrency": "Envois simultanés",
|
||||
"upload_errors": "L'envoi s'est achevé avec {count, plural, one {# erreur} other {# erreurs}}. Rafraîchir la page pour voir les nouveaux médias envoyés.",
|
||||
"upload_progress": "{remaining, number} restant(s) - {processed, number} traité(s)/{total, number}",
|
||||
"upload_skipped_duplicates": "{count, plural, one {# doublon ignoré} other {# doublons ignorés}}",
|
||||
"upload_status_duplicates": "Doublons",
|
||||
"upload_status_errors": "Erreurs",
|
||||
"upload_status_uploaded": "Téléversé",
|
||||
"upload_success": "Téléversement réussi. Rafraîchir la page pour voir les nouveaux médias téléversés.",
|
||||
"upload_status_uploaded": "Envoyé",
|
||||
"upload_success": "Envoi réussi. Rafraîchir la page pour voir les nouveaux médias envoyés.",
|
||||
"url": "URL",
|
||||
"usage": "Utilisation",
|
||||
"use_custom_date_range": "Utilisez une plage de date personnalisée à la place",
|
||||
|
||||
@@ -139,7 +139,11 @@
|
||||
"map_settings_description": "נהל הגדרות מפה",
|
||||
"map_style_description": "כתובת אתר לערכת נושא של מפה style.json",
|
||||
"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": "העבר תמונות ממוזערות של נכסים ופנים למבנה התיקיות העדכני ביותר",
|
||||
"no_paths_added": "לא נוספו נתיבים",
|
||||
@@ -148,7 +152,7 @@
|
||||
"note_cannot_be_changed_later": "הערה: אי אפשר לשנות זאת מאוחר יותר!",
|
||||
"note_unlimited_quota": "הערה: הזן 0 עבור מכסת אחסון בלתי מוגבלת",
|
||||
"notification_email_from_address": "מכתובת",
|
||||
"notification_email_from_address_description": "כתובת דוא\"ל של השולח, לדוגמה: \"Immich שרת תמונות <noreply@immich.app>\"",
|
||||
"notification_email_from_address_description": "כתובת דוא\"ל של השולח, לדוגמה: \"Immich שרת תמונות <noreply@example.com>\"",
|
||||
"notification_email_host_description": "מארח שרת הדוא\"ל (למשל smtp.immich.app)",
|
||||
"notification_email_ignore_certificate_errors": "התעלם משגיאות תעודה",
|
||||
"notification_email_ignore_certificate_errors_description": "התעלם משגיאות אימות תעודת TLS (לא מומלץ)",
|
||||
@@ -387,6 +391,7 @@
|
||||
"asset_offline": "נכס לא מקוון",
|
||||
"asset_offline_description": "הנכס הזה אינו מקוון. Immich לא יכול לגשת למיקום הקובץ שלו. נא לוודא שהנכס זמין ואז סרוק מחדש את הספרייה.",
|
||||
"asset_skipped": "דילג",
|
||||
"asset_skipped_in_trash": "באשפה",
|
||||
"asset_uploaded": "הועלה",
|
||||
"asset_uploading": "מעלה...",
|
||||
"assets": "נכסים",
|
||||
@@ -656,6 +661,7 @@
|
||||
"unable_to_get_comments_number": "לא ניתן להשיג את מספר התגובות",
|
||||
"unable_to_get_shared_link": "קבלת קישור משותף נכשלה",
|
||||
"unable_to_hide_person": "לא ניתן להסתיר אדם",
|
||||
"unable_to_link_motion_video": "לא ניתן לקשר סרטון תנועה",
|
||||
"unable_to_link_oauth_account": "לא ניתן לקשר חשבון OAuth",
|
||||
"unable_to_load_album": "לא ניתן לטעון אלבום",
|
||||
"unable_to_load_asset_activity": "לא ניתן לטעון את פעילות הנכס",
|
||||
@@ -696,6 +702,7 @@
|
||||
"unable_to_submit_job": "לא ניתן לשלוח משימה",
|
||||
"unable_to_trash_asset": "לא ניתן להעביר נכס לאשפה",
|
||||
"unable_to_unlink_account": "לא ניתן לבטל קישור חשבון",
|
||||
"unable_to_unlink_motion_video": "לא ניתן לבטל קישור סרטון תנועה",
|
||||
"unable_to_update_album_cover": "לא ניתן לעדכן עטיפת אלבום",
|
||||
"unable_to_update_album_info": "לא ניתן לעדכן פרטי אלבום",
|
||||
"unable_to_update_library": "לא ניתן לעדכן ספרייה",
|
||||
@@ -841,6 +848,7 @@
|
||||
"license_trial_info_4": "אנא שקול לרכוש רישיון כדי לתמוך בפיתוח המתמשך של השירות",
|
||||
"light": "בהיר",
|
||||
"like_deleted": "לייק נמחק",
|
||||
"link_motion_video": "קשר סרטון תנועה",
|
||||
"link_options": "אפשרויות קישור",
|
||||
"link_to_oauth": "קישור ל-OAuth",
|
||||
"linked_oauth_account": "חשבון OAuth מקושר",
|
||||
@@ -1130,6 +1138,7 @@
|
||||
"search_for_existing_person": "חפש אדם קיים",
|
||||
"search_no_people": "אין אנשים",
|
||||
"search_no_people_named": "אין אנשים בשם \"{name}\"",
|
||||
"search_options": "אפשרויות חיפוש",
|
||||
"search_people": "חפש אנשים",
|
||||
"search_places": "חפש מקומות",
|
||||
"search_state": "חפש מדינה...",
|
||||
@@ -1208,6 +1217,8 @@
|
||||
"sign_up": "הרשמה",
|
||||
"size": "גודל",
|
||||
"skip_to_content": "דלג לתוכן",
|
||||
"skip_to_folders": "דלג לתיקיות",
|
||||
"skip_to_tags": "דלג לתגים",
|
||||
"slideshow": "מצגת שקופיות",
|
||||
"slideshow_settings": "הגדרות מצגת שקופיות",
|
||||
"sort_albums_by": "מיין אלבומים לפי...",
|
||||
@@ -1282,6 +1293,7 @@
|
||||
"unknown_album": "אלבום לא ידוע",
|
||||
"unknown_year": "שנה לא ידועה",
|
||||
"unlimited": "בלתי מוגבל",
|
||||
"unlink_motion_video": "בטל קישור סרטון תנועה",
|
||||
"unlink_oauth": "בטל קישור OAuth",
|
||||
"unlinked_oauth_account": "בוטל קישור חשבון OAuth",
|
||||
"unnamed_album": "אלבום ללא שם",
|
||||
|
||||
@@ -147,7 +147,7 @@
|
||||
"note_cannot_be_changed_later": "नोट: इसे बाद में बदला नहीं जा सकता!",
|
||||
"note_unlimited_quota": "नोट: असीमित कोटा के लिए 0 दर्ज करें",
|
||||
"notification_email_from_address": "इस पते से",
|
||||
"notification_email_from_address_description": "प्रेषक का ईमेल पता, उदाहरण के लिए: \"इमिच फोटो सर्वर <noreply@immich.app>\"",
|
||||
"notification_email_from_address_description": "प्रेषक का ईमेल पता, उदाहरण के लिए: \"इमिच फोटो सर्वर <noreply@example.com>\"",
|
||||
"notification_email_host_description": "ईमेल सर्वर का होस्ट (उदा. smtp.immitch.app)",
|
||||
"notification_email_ignore_certificate_errors": "प्रमाणपत्र त्रुटियों पर ध्यान न दें",
|
||||
"notification_email_ignore_certificate_errors_description": "टीएलएस प्रमाणपत्र सत्यापन त्रुटियों पर ध्यान न दें (अनुशंसित नहीं)",
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -149,7 +149,7 @@
|
||||
"note_cannot_be_changed_later": "FIGYELEM: ezt később nem lehet megváltoztatni!",
|
||||
"note_unlimited_quota": "Megjegyzés: 0 - korlátlan kvóta",
|
||||
"notification_email_from_address": "Feladó cím",
|
||||
"notification_email_from_address_description": "Küldő email címe, például: \"Immich Fotószerver <noreply@immich.app>\"",
|
||||
"notification_email_from_address_description": "Küldő email címe, például: \"Immich Fotószerver <noreply@example.com>\"",
|
||||
"notification_email_host_description": "Email szerver kiszolgálója (pl. smtp.immich.app)",
|
||||
"notification_email_ignore_certificate_errors": "Tanúsítvány hibák figyelmen kívül hagyása",
|
||||
"notification_email_ignore_certificate_errors_description": "TLS tanúsítvány érvényességi hibák figyelmen kívül hagyása (nem ajánlott)",
|
||||
|
||||
@@ -150,7 +150,7 @@
|
||||
"note_cannot_be_changed_later": "CATATAN: Ini tidak akan dapat diubah lagi!",
|
||||
"note_unlimited_quota": "Catatan: Masukkan 0 untuk kuota tidak terbatas",
|
||||
"notification_email_from_address": "Dari alamat",
|
||||
"notification_email_from_address_description": "Alamat surel pengirim, misalnya: \"Server Foto Immich <noreply@immich.app>\"",
|
||||
"notification_email_from_address_description": "Alamat surel pengirim, misalnya: \"Server Foto Immich <noreply@example.com>\"",
|
||||
"notification_email_host_description": "Hos server surel (mis. smtp.immich.app)",
|
||||
"notification_email_ignore_certificate_errors": "Abaikan eror sertifikat",
|
||||
"notification_email_ignore_certificate_errors_description": "Abaikan eror validasi sertifikat TLS (tidak disarankan)",
|
||||
|
||||
@@ -152,7 +152,7 @@
|
||||
"note_cannot_be_changed_later": "NOTA: Non potrà essere modificato in futuro!",
|
||||
"note_unlimited_quota": "Nota: Inserisci 0 per una quota illimitata",
|
||||
"notification_email_from_address": "Indirizzo mittente",
|
||||
"notification_email_from_address_description": "Indirizzo email mittente, ad esempio: \"Server Foto Immich <noreply@immich.app>\"",
|
||||
"notification_email_from_address_description": "Indirizzo email mittente, ad esempio: \"Server Foto Immich <noreply@example.com>\"",
|
||||
"notification_email_host_description": "Host del server email (es. smtp.immich.app)",
|
||||
"notification_email_ignore_certificate_errors": "Ignora errori di certificato",
|
||||
"notification_email_ignore_certificate_errors_description": "Ignora errori di validazione del certificato TLS (sconsigliato)",
|
||||
@@ -661,6 +661,7 @@
|
||||
"unable_to_get_comments_number": "Impossibile ottenere il numero di commenti",
|
||||
"unable_to_get_shared_link": "Impossibile ottenere il link condiviso",
|
||||
"unable_to_hide_person": "Impossibile nascondere persona",
|
||||
"unable_to_link_motion_video": "Impossibile collegare video in movimento",
|
||||
"unable_to_link_oauth_account": "Impossibile collegare l'account OAuth",
|
||||
"unable_to_load_album": "Impossibile caricare l'album",
|
||||
"unable_to_load_asset_activity": "Impossibile caricare l'attività dell'asset",
|
||||
@@ -701,6 +702,7 @@
|
||||
"unable_to_submit_job": "Impossibile eseguire l'attività",
|
||||
"unable_to_trash_asset": "Impossibile cestinare l'asset",
|
||||
"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_info": "Impossibile aggiornare le informazioni sull'album",
|
||||
"unable_to_update_library": "Impossibile aggiornare la libreria",
|
||||
@@ -1290,6 +1292,7 @@
|
||||
"unknown_album": "Album sconosciuto",
|
||||
"unknown_year": "Anno sconosciuto",
|
||||
"unlimited": "Illimitato",
|
||||
"unlink_motion_video": "Scollega video in movimento",
|
||||
"unlink_oauth": "Scollega OAuth",
|
||||
"unlinked_oauth_account": "Scollega account OAuth",
|
||||
"unnamed_album": "Album senza nome",
|
||||
|
||||
@@ -148,7 +148,7 @@
|
||||
"note_cannot_be_changed_later": "注意: 後から変更できません!",
|
||||
"note_unlimited_quota": "注意: 無制限にする場合は0を入力してください",
|
||||
"notification_email_from_address": "送信メールアドレス",
|
||||
"notification_email_from_address_description": "送信メールアドレスを設定します(例: \"Immich Photo Server <noreply@immich.app>\" )",
|
||||
"notification_email_from_address_description": "送信メールアドレスを設定します(例: \"Immich Photo Server <noreply@example.com>\" )",
|
||||
"notification_email_host_description": "送信メールサーバーを設定します(例:smtp.immich.app)",
|
||||
"notification_email_ignore_certificate_errors": "証明書エラーを無視",
|
||||
"notification_email_ignore_certificate_errors_description": "TLS証明書の検証エラーを無視します(非推奨)",
|
||||
|
||||
@@ -139,7 +139,11 @@
|
||||
"map_settings_description": "지도 설정 관리",
|
||||
"map_style_description": "지도 테마 style.json URL",
|
||||
"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": "각 항목의 섬네일 및 인물의 얼굴을 최신 폴더 구조로 마이그레이션",
|
||||
"no_paths_added": "추가된 경로 없음",
|
||||
@@ -148,7 +152,7 @@
|
||||
"note_cannot_be_changed_later": "주의: 추후 변경할 수 없습니다!",
|
||||
"note_unlimited_quota": "참고: 할당량을 설정하지 않으려면 0을 입력하세요.",
|
||||
"notification_email_from_address": "보낸 사람 이메일",
|
||||
"notification_email_from_address_description": "보낸 사람의 이메일 주소, 예: \"Immich Photo Server <noreply@immich.app>\"",
|
||||
"notification_email_from_address_description": "보낸 사람의 이메일 주소, 예: \"Immich Photo Server <noreply@example.com>\"",
|
||||
"notification_email_host_description": "이메일 서버의 호스트 (예: smtp.immich.app)",
|
||||
"notification_email_ignore_certificate_errors": "인증서 오류 무시",
|
||||
"notification_email_ignore_certificate_errors_description": "TLS 인증서 유효성 검사 오류 무시 (권장되지 않음)",
|
||||
@@ -1114,6 +1118,7 @@
|
||||
"search_for_existing_person": "존재하는 인물 검색",
|
||||
"search_no_people": "인물이 없습니다.",
|
||||
"search_no_people_named": "\"{name}\" 인물을 찾을 수 없음",
|
||||
"search_options": "검색 옵션",
|
||||
"search_people": "인물 검색",
|
||||
"search_places": "장소 검색",
|
||||
"search_state": "지역 검색...",
|
||||
@@ -1243,6 +1248,7 @@
|
||||
"to_change_password": "비밀번호 변경",
|
||||
"to_favorite": "즐겨찾기",
|
||||
"to_login": "로그인",
|
||||
"to_parent": "상위 항목으로",
|
||||
"to_root": "루트",
|
||||
"to_trash": "삭제",
|
||||
"toggle_settings": "설정 변경",
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
"add_to_shared_album": "Pievienot koplietotam albumam",
|
||||
"added_to_archive": "Pievienots arhīvam",
|
||||
"added_to_favorites": "Pievienots izlasei",
|
||||
"added_to_favorites_count": "Pievienots {count} izlasei",
|
||||
"added_to_favorites_count": "Pievienots {count, number} izlasei",
|
||||
"admin": {
|
||||
"add_exclusion_pattern_description": "Pievienojiet izlaišanas shēmas. Aizstājējzīmju izmantoša *, **, un ? tiek atbalstīta. Lai ignorētu visus failus jebkurā direktorijā ar nosaukumu “RAW”, izmantojiet “**/RAW/**”. Lai ignorētu visus failus, kas beidzas ar “. tif”, izmantojiet “**/*. tif”. Lai ignorētu absolūto ceļu, izmantojiet “/path/to/ignore/**”.",
|
||||
"authentication_settings": "Autentifikācijas iestatījumi",
|
||||
@@ -44,6 +44,9 @@
|
||||
"disable_login": "Atspējot pieteikšanos",
|
||||
"disabled": "",
|
||||
"duplicate_detection_job_description": "Palaidiet mašīnmācīšanos uz līdzekļiem, lai noteiktu līdzīgus attēlus. Paļaujas uz Viedo Meklēšanu",
|
||||
"external_library_created_at": "Ārēja bibliotēka (izveidota {date})",
|
||||
"external_library_management": "Ārējo bibliotēku pārvaldība",
|
||||
"face_detection": "Seju noteikšana",
|
||||
"image_format_description": "",
|
||||
"image_prefer_embedded_preview": "",
|
||||
"image_prefer_embedded_preview_setting_description": "",
|
||||
@@ -82,7 +85,7 @@
|
||||
"machine_learning_enabled_description": "",
|
||||
"machine_learning_facial_recognition": "",
|
||||
"machine_learning_facial_recognition_description": "",
|
||||
"machine_learning_facial_recognition_model": "",
|
||||
"machine_learning_facial_recognition_model": "Seju atpazīšanas modelis",
|
||||
"machine_learning_facial_recognition_model_description": "",
|
||||
"machine_learning_facial_recognition_setting_description": "",
|
||||
"machine_learning_max_detection_distance": "",
|
||||
@@ -102,11 +105,13 @@
|
||||
"manage_log_settings": "",
|
||||
"map_dark_style": "",
|
||||
"map_enable_description": "",
|
||||
"map_gps_settings": "Kartes un GPS iestatījumi",
|
||||
"map_gps_settings_description": "Pārvaldīt karšu un GPS (apgrieztās ģeokodēšanas) iestatījumus",
|
||||
"map_light_style": "",
|
||||
"map_reverse_geocoding": "",
|
||||
"map_reverse_geocoding_enable_description": "",
|
||||
"map_reverse_geocoding_settings": "",
|
||||
"map_settings": "",
|
||||
"map_settings": "Karte",
|
||||
"map_settings_description": "",
|
||||
"map_style_description": "",
|
||||
"metadata_extraction_job_description": "",
|
||||
@@ -151,10 +156,12 @@
|
||||
"password_enable_description": "",
|
||||
"password_settings": "",
|
||||
"password_settings_description": "",
|
||||
"quota_size_gib": "Kvotas izmērs (GiB)",
|
||||
"require_password_change_on_login": "Pieprasīt lietotājam mainīt paroli pēc pirmās pieteikšanās",
|
||||
"server_external_domain_settings": "",
|
||||
"server_external_domain_settings_description": "",
|
||||
"server_settings": "",
|
||||
"server_settings_description": "",
|
||||
"server_settings": "Servera iestatījumi",
|
||||
"server_settings_description": "Pārvaldīt servera iestatījumus",
|
||||
"server_welcome_message": "",
|
||||
"server_welcome_message_description": "",
|
||||
"sidecar_job_description": "",
|
||||
@@ -234,38 +241,46 @@
|
||||
"trash_settings_description": "",
|
||||
"user_delete_delay_settings": "",
|
||||
"user_delete_delay_settings_description": "",
|
||||
"user_management": "Lietotāju pārvaldība",
|
||||
"user_settings": "",
|
||||
"user_settings_description": "",
|
||||
"version_check_enabled_description": "",
|
||||
"version_check_enabled_description": "Ieslēgt versijas pārbaudi",
|
||||
"version_check_implications": "Versiju pārbaudes funkcija ir atkarīga no periodiskas saziņas ar github.com",
|
||||
"version_check_settings": "",
|
||||
"version_check_settings_description": "",
|
||||
"video_conversion_job_description": ""
|
||||
},
|
||||
"admin_email": "",
|
||||
"admin_password": "",
|
||||
"administration": "",
|
||||
"admin_email": "Administratora e-pasts",
|
||||
"admin_password": "Administratora parole",
|
||||
"administration": "Administrēšana",
|
||||
"advanced": "Papildu",
|
||||
"album_added": "",
|
||||
"album_added": "Albums pievienots",
|
||||
"album_added_notification_setting_description": "",
|
||||
"album_cover_updated": "",
|
||||
"album_info_updated": "",
|
||||
"album_name": "",
|
||||
"album_cover_updated": "Albuma attēls atjaunināts",
|
||||
"album_info_updated": "Albuma informācija atjaunināta",
|
||||
"album_leave": "Pamest albumu?",
|
||||
"album_name": "Albuma nosaukums",
|
||||
"album_options": "",
|
||||
"album_updated": "",
|
||||
"album_remove_user": "Noņemt lietotāju?",
|
||||
"album_updated": "Albums atjaunināts",
|
||||
"album_updated_setting_description": "",
|
||||
"albums": "",
|
||||
"albums": "Albumi",
|
||||
"all": "Viss",
|
||||
"all_people": "",
|
||||
"all_albums": "Visi albumi",
|
||||
"all_people": "Visi cilvēki",
|
||||
"all_videos": "Visi video",
|
||||
"allow_dark_mode": "",
|
||||
"allow_edits": "",
|
||||
"api_key": "",
|
||||
"api_keys": "",
|
||||
"api_key": "API atslēga",
|
||||
"api_keys": "API atslēgas",
|
||||
"app_settings": "",
|
||||
"appears_in": "",
|
||||
"archive": "Arhīvs",
|
||||
"archive_or_unarchive_photo": "",
|
||||
"archive_size": "Arhīva izmērs",
|
||||
"archived": "",
|
||||
"asset_offline": "",
|
||||
"asset_uploading": "Augšupielādē...",
|
||||
"assets": "aktīvi",
|
||||
"authorized_devices": "",
|
||||
"back": "Atpakaļ",
|
||||
@@ -303,7 +318,7 @@
|
||||
"comments_are_disabled": "",
|
||||
"confirm": "Apstiprināt",
|
||||
"confirm_admin_password": "",
|
||||
"confirm_password": "Apstiprināt Paroli",
|
||||
"confirm_password": "Apstiprināt paroli",
|
||||
"contain": "",
|
||||
"context": "",
|
||||
"continue": "",
|
||||
@@ -324,8 +339,8 @@
|
||||
"create_link": "Izveidot saiti",
|
||||
"create_link_to_share": "Izveidot kopīgošanas saiti",
|
||||
"create_new_person": "",
|
||||
"create_new_user": "",
|
||||
"create_user": "",
|
||||
"create_new_user": "Izveidot jaunu lietotāju",
|
||||
"create_user": "Izveidot lietotāju",
|
||||
"created": "",
|
||||
"current_device": "",
|
||||
"custom_locale": "",
|
||||
@@ -344,7 +359,7 @@
|
||||
"delete_library": "",
|
||||
"delete_link": "",
|
||||
"delete_shared_link": "Dzēst Kopīgošanas saiti",
|
||||
"delete_user": "",
|
||||
"delete_user": "Dzēst lietotāju",
|
||||
"deleted_shared_link": "",
|
||||
"description": "Apraksts",
|
||||
"details": "INFORMĀCIJA",
|
||||
@@ -360,6 +375,7 @@
|
||||
"done": "Gatavs",
|
||||
"download": "Lejupielādēt",
|
||||
"downloading": "",
|
||||
"duplicates": "Dublikāti",
|
||||
"duration": "",
|
||||
"durations": {
|
||||
"days": "",
|
||||
@@ -382,7 +398,7 @@
|
||||
"edit_name": "Rediģēt vārdu",
|
||||
"edit_people": "",
|
||||
"edit_title": "",
|
||||
"edit_user": "",
|
||||
"edit_user": "Labot lietotāju",
|
||||
"edited": "",
|
||||
"editor": "",
|
||||
"email": "E-pasts",
|
||||
@@ -395,6 +411,7 @@
|
||||
"error": "",
|
||||
"error_loading_image": "",
|
||||
"errors": {
|
||||
"failed_to_create_album": "Neizdevās izveidot albumu",
|
||||
"unable_to_add_album_users": "",
|
||||
"unable_to_add_comment": "",
|
||||
"unable_to_add_partners": "",
|
||||
@@ -405,10 +422,10 @@
|
||||
"unable_to_check_items": "",
|
||||
"unable_to_create_admin_account": "",
|
||||
"unable_to_create_library": "",
|
||||
"unable_to_create_user": "",
|
||||
"unable_to_create_user": "Neizdevās izveidot lietotāju",
|
||||
"unable_to_delete_album": "",
|
||||
"unable_to_delete_asset": "",
|
||||
"unable_to_delete_user": "",
|
||||
"unable_to_delete_user": "Neizdevās dzēst lietotāju",
|
||||
"unable_to_empty_trash": "",
|
||||
"unable_to_enter_fullscreen": "",
|
||||
"unable_to_exit_fullscreen": "",
|
||||
@@ -450,11 +467,11 @@
|
||||
"every_night_at_midnight": "",
|
||||
"every_night_at_twoam": "",
|
||||
"every_six_hours": "",
|
||||
"exit_slideshow": "",
|
||||
"exit_slideshow": "Iziet no slīdrādes",
|
||||
"expand_all": "",
|
||||
"expire_after": "Derīguma termiņš beidzas pēc",
|
||||
"expired": "Derīguma termiņš beidzās",
|
||||
"explore": "",
|
||||
"explore": "Izpētīt",
|
||||
"extension": "",
|
||||
"external_libraries": "",
|
||||
"failed_to_get_people": "",
|
||||
@@ -471,6 +488,7 @@
|
||||
"filetype": "",
|
||||
"filter_people": "",
|
||||
"fix_incorrect_match": "",
|
||||
"folders": "Mapes",
|
||||
"force_re-scan_library_files": "",
|
||||
"forward": "",
|
||||
"general": "",
|
||||
@@ -480,7 +498,7 @@
|
||||
"go_to_search": "",
|
||||
"go_to_share_page": "",
|
||||
"group_albums_by": "",
|
||||
"has_quota": "",
|
||||
"has_quota": "Ir kvota",
|
||||
"hide_gallery": "",
|
||||
"hide_password": "",
|
||||
"hide_person": "",
|
||||
@@ -491,7 +509,7 @@
|
||||
"immich_logo": "",
|
||||
"import_path": "",
|
||||
"in_archive": "",
|
||||
"include_archived": "Iekļaut Arhivētos",
|
||||
"include_archived": "Iekļaut arhivētos",
|
||||
"include_shared_albums": "",
|
||||
"include_shared_partner_assets": "",
|
||||
"individual_share": "",
|
||||
@@ -537,8 +555,9 @@
|
||||
"manage_your_api_keys": "",
|
||||
"manage_your_devices": "",
|
||||
"manage_your_oauth_connection": "",
|
||||
"map": "",
|
||||
"map_marker_with_image": "",
|
||||
"map": "Karte",
|
||||
"map_marker_for_images": "Kartes marķieris attēliem, kas uzņemti {city}, {country}",
|
||||
"map_marker_with_image": "Kartes marķieris ar attēlu",
|
||||
"map_settings": "Kartes Iestatījumi",
|
||||
"media_type": "",
|
||||
"memories": "",
|
||||
@@ -559,9 +578,9 @@
|
||||
"name_or_nickname": "",
|
||||
"never": "nekad",
|
||||
"new_api_key": "",
|
||||
"new_password": "Jauna Parole",
|
||||
"new_password": "Jaunā parole",
|
||||
"new_person": "",
|
||||
"new_user_created": "",
|
||||
"new_user_created": "Izveidots jauns lietotājs",
|
||||
"newest_first": "",
|
||||
"next": "Nākošais",
|
||||
"next_memory": "",
|
||||
@@ -569,6 +588,7 @@
|
||||
"no_albums_message": "",
|
||||
"no_archived_assets_message": "",
|
||||
"no_assets_message": "",
|
||||
"no_duplicates_found": "Dublikāti netika atrasti.",
|
||||
"no_exif_info_available": "",
|
||||
"no_explore_results_message": "",
|
||||
"no_favorites_message": "",
|
||||
@@ -587,8 +607,9 @@
|
||||
"ok": "",
|
||||
"oldest_first": "",
|
||||
"online": "",
|
||||
"only_favorites": "",
|
||||
"only_favorites": "Tikai izlase",
|
||||
"only_refreshes_modified_files": "",
|
||||
"open_in_openstreetmap": "Atvērt OpenStreetMap",
|
||||
"open_the_search_filters": "",
|
||||
"options": "Iestatījumi",
|
||||
"organize_your_library": "",
|
||||
@@ -658,14 +679,17 @@
|
||||
"repair_no_results_message": "",
|
||||
"replace_with_upload": "",
|
||||
"require_password": "",
|
||||
"require_user_to_change_password_on_first_login": "Pieprasīt lietotājam mainīt paroli pēc pirmās pieteikšanās",
|
||||
"reset": "",
|
||||
"reset_password": "",
|
||||
"reset_people_visibility": "",
|
||||
"reset_settings_to_default": "",
|
||||
"resolve_duplicates": "Atrisināt dublēšanās gadījumus",
|
||||
"resolved_all_duplicates": "Visi dublikāti ir atrisināti",
|
||||
"restore": "Atjaunot",
|
||||
"restore_user": "",
|
||||
"retry_upload": "",
|
||||
"review_duplicates": "",
|
||||
"review_duplicates": "Pārskatīt dublikātus",
|
||||
"role": "",
|
||||
"save": "Saglabāt",
|
||||
"saved_profile": "",
|
||||
@@ -691,8 +715,9 @@
|
||||
"search_your_photos": "Meklēt Jūsu fotoattēlus",
|
||||
"searching_locales": "",
|
||||
"second": "",
|
||||
"select_album_cover": "",
|
||||
"select_album_cover": "Izvēlieties albuma vāciņu",
|
||||
"select_all": "",
|
||||
"select_all_duplicates": "Atlasīt visus dublikātus",
|
||||
"select_avatar_color": "",
|
||||
"select_face": "",
|
||||
"select_featured_photo": "",
|
||||
@@ -702,7 +727,8 @@
|
||||
"selected": "",
|
||||
"send_message": "",
|
||||
"server": "",
|
||||
"server_stats": "",
|
||||
"server_online": "Serveris tiešsaistē",
|
||||
"server_stats": "Servera statistika",
|
||||
"set": "",
|
||||
"set_as_album_cover": "",
|
||||
"set_as_profile_picture": "",
|
||||
@@ -715,7 +741,7 @@
|
||||
"shared": "Kopīgots",
|
||||
"shared_by": "",
|
||||
"shared_by_you": "",
|
||||
"shared_links": "Kopīgotas Saites",
|
||||
"shared_links": "Kopīgotās saites",
|
||||
"sharing": "Kopīgošana",
|
||||
"sharing_sidebar_description": "",
|
||||
"show_album_options": "",
|
||||
@@ -735,8 +761,8 @@
|
||||
"sign_up": "",
|
||||
"size": "",
|
||||
"skip_to_content": "",
|
||||
"slideshow": "",
|
||||
"slideshow_settings": "",
|
||||
"slideshow": "Slīdrāde",
|
||||
"slideshow_settings": "Slīdrādes iestatījumi",
|
||||
"sort_albums_by": "",
|
||||
"stack": "Steks",
|
||||
"stack_selected_photos": "",
|
||||
@@ -746,7 +772,7 @@
|
||||
"status": "",
|
||||
"stop_motion_photo": "",
|
||||
"stop_photo_sharing": "Beigt kopīgot jūsu fotogrāfijas?",
|
||||
"storage": "",
|
||||
"storage": "Uzglabāšanas vieta",
|
||||
"storage_label": "",
|
||||
"submit": "",
|
||||
"suggestions": "Ieteikumi",
|
||||
@@ -762,7 +788,7 @@
|
||||
"toggle_settings": "",
|
||||
"toggle_theme": "",
|
||||
"toggle_visibility": "",
|
||||
"total_usage": "",
|
||||
"total_usage": "Kopējais lietojums",
|
||||
"trash": "Atkritne",
|
||||
"trash_all": "",
|
||||
"trash_no_results_message": "",
|
||||
@@ -774,6 +800,7 @@
|
||||
"unknown": "",
|
||||
"unknown_album": "",
|
||||
"unknown_year": "",
|
||||
"unlimited": "Neierobežots",
|
||||
"unlink_oauth": "",
|
||||
"unlinked_oauth_account": "",
|
||||
"unselect_all": "",
|
||||
@@ -782,16 +809,17 @@
|
||||
"updated_password": "",
|
||||
"upload": "Augšupielādēt",
|
||||
"upload_concurrency": "",
|
||||
"upload_status_duplicates": "Dublikāti",
|
||||
"upload_status_errors": "Kļūdas",
|
||||
"upload_status_uploaded": "Augšupielādēts",
|
||||
"url": "",
|
||||
"usage": "",
|
||||
"usage": "Lietojums",
|
||||
"user": "Lietotājs",
|
||||
"user_id": "Lietotāja ID",
|
||||
"user_usage_detail": "",
|
||||
"user_usage_detail": "Informācija par lietotāju lietojumu",
|
||||
"username": "",
|
||||
"users": "Lietotāji",
|
||||
"utilities": "",
|
||||
"utilities": "Rīki",
|
||||
"validate": "",
|
||||
"variables": "",
|
||||
"version": "Versija",
|
||||
@@ -804,7 +832,7 @@
|
||||
"view_next_asset": "",
|
||||
"view_previous_asset": "",
|
||||
"viewer": "",
|
||||
"waiting": "",
|
||||
"waiting": "Gaida",
|
||||
"week": "",
|
||||
"welcome_to_immich": "",
|
||||
"year": "",
|
||||
|
||||
@@ -138,6 +138,8 @@
|
||||
"map_style_description": "URL til et style.json-karttema",
|
||||
"metadata_extraction_job": "Hent metadata",
|
||||
"metadata_extraction_job_description": "Hent metadatainformasjon fra hver fil, for eksempel GPS-posisjon og oppløsning",
|
||||
"metadata_settings": "Metadatainnstillinger",
|
||||
"metadata_settings_description": "Administrer metadatainnstillinger",
|
||||
"migration_job": "Migrering",
|
||||
"migration_job_description": "Migrer miniatyrbilder for filer og ansikter til den nyeste mappestrukturen",
|
||||
"no_paths_added": "Ingen filbaner lagt til",
|
||||
@@ -146,7 +148,7 @@
|
||||
"note_cannot_be_changed_later": "MERK: Dette kan ikke endres senere!",
|
||||
"note_unlimited_quota": "Merk: Skriv inn 0 for ubegrenset kvote",
|
||||
"notification_email_from_address": "Fra adresse",
|
||||
"notification_email_from_address_description": "Avsenderens e-postadresse, for eksempel: \"Immich Photo Server <noreply@immich.app>\"",
|
||||
"notification_email_from_address_description": "Avsenderens e-postadresse, for eksempel: \"Immich Photo Server <noreply@example.com>\"",
|
||||
"notification_email_host_description": "Verten til e-posts serveren (f.eks. smtp.immich.app)",
|
||||
"notification_email_ignore_certificate_errors": "Ignorer sertifikatfeil",
|
||||
"notification_email_ignore_certificate_errors_description": "Ignorer valideringsfeil for TLS-sertifikat (ikke anbefalt)",
|
||||
@@ -384,6 +386,7 @@
|
||||
"asset_offline": "Fil utilgjengelig",
|
||||
"asset_offline_description": "Dette elementet er offline. Immich kan ikke aksessere dets lokasjon. Vennlist påse at elementet er tilgijengelig og skann så biblioteket på nytt.",
|
||||
"asset_skipped": "Hoppet over",
|
||||
"asset_skipped_in_trash": "I søppelbøtten",
|
||||
"asset_uploaded": "Lastet opp",
|
||||
"asset_uploading": "Laster opp...",
|
||||
"assets": "Filer",
|
||||
|
||||
@@ -152,7 +152,7 @@
|
||||
"note_cannot_be_changed_later": "LET OP: Dit kan later niet meer worden gewijzigd!",
|
||||
"note_unlimited_quota": "Opmerking: voer 0 in voor onbeperkt",
|
||||
"notification_email_from_address": "Adres afzender",
|
||||
"notification_email_from_address_description": "E-mailadres van de afzender, bijvoorbeeld: \"Immich Foto Server <noreply@immich.app>\"",
|
||||
"notification_email_from_address_description": "E-mailadres van de afzender, bijvoorbeeld: \"Immich Foto Server <noreply@example.com>\"",
|
||||
"notification_email_host_description": "Host van de e-mailserver (bijv. smtp.immich.app)",
|
||||
"notification_email_ignore_certificate_errors": "Negeer certificaatfouten",
|
||||
"notification_email_ignore_certificate_errors_description": "Negeer TLS certificaat validatiefouten (niet aanbevolen)",
|
||||
@@ -391,6 +391,7 @@
|
||||
"asset_offline": "Asset offline",
|
||||
"asset_offline_description": "Deze asset is offline. Immich kan de bestandslocatie niet openen. Controleer of de asset beschikbaar is en scan de bibliotheek opnieuw.",
|
||||
"asset_skipped": "Overgeslagen",
|
||||
"asset_skipped_in_trash": "In prullenbak",
|
||||
"asset_uploaded": "Geüpload",
|
||||
"asset_uploading": "Uploaden...",
|
||||
"assets": "Assets",
|
||||
@@ -1135,6 +1136,7 @@
|
||||
"search_for_existing_person": "Zoek naar bestaande persoon",
|
||||
"search_no_people": "Geen mensen",
|
||||
"search_no_people_named": "Geen mensen genaamd \"{name}\"",
|
||||
"search_options": "Zoekopties",
|
||||
"search_people": "Zoek mensen",
|
||||
"search_places": "Zoek plaatsen",
|
||||
"search_state": "Zoek staat...",
|
||||
|
||||
@@ -152,7 +152,7 @@
|
||||
"note_cannot_be_changed_later": "UWAŻAJ: Nie można tego później zmienić!",
|
||||
"note_unlimited_quota": "Wpisz by wyłączyć limit",
|
||||
"notification_email_from_address": "Z adresu",
|
||||
"notification_email_from_address_description": "Adres e-mail nadawcy, na przykład: „Immich Photo Server <noreply@immich.app>”",
|
||||
"notification_email_from_address_description": "Adres e-mail nadawcy, na przykład: „Immich Photo Server <noreply@example.com>”",
|
||||
"notification_email_host_description": "Host serwera e-mail (np. smtp.immich.app)",
|
||||
"notification_email_ignore_certificate_errors": "Ignoruj niepoprawny certyfikat",
|
||||
"notification_email_ignore_certificate_errors_description": "Ignoruj błąd walidacji certyfikatu TLS (nie zalecane)",
|
||||
|
||||
@@ -149,7 +149,7 @@
|
||||
"note_cannot_be_changed_later": "NOTA: Isto não pode ser alterado posteriormente!",
|
||||
"note_unlimited_quota": "Observação: insira 0 para cota ilimitada",
|
||||
"notification_email_from_address": "A partir do endereço",
|
||||
"notification_email_from_address_description": "Endereço de e-mail do remetente, por exemplo: \"Immich Photo Server <noreply@immich.app>\"",
|
||||
"notification_email_from_address_description": "Endereço de e-mail do remetente, por exemplo: \"Immich Photo Server <noreply@example.com>\"",
|
||||
"notification_email_host_description": "Host do servidor de e-mail (por exemplo, smtp.immich.app)",
|
||||
"notification_email_ignore_certificate_errors": "Ignorar erros de certificado",
|
||||
"notification_email_ignore_certificate_errors_description": "Ignorar erros de validação de certificado TLS (não recomendado)",
|
||||
|
||||
@@ -148,7 +148,7 @@
|
||||
"note_cannot_be_changed_later": "NOTA: Isto não pode ser alterado posteriormente!",
|
||||
"note_unlimited_quota": "Observação: insira 0 para cota ilimitada",
|
||||
"notification_email_from_address": "A partir do endereço",
|
||||
"notification_email_from_address_description": "Endereço de e-mail do remetente, por exemplo: \"Immich Photo Server <noreply@immich.app>\"",
|
||||
"notification_email_from_address_description": "Endereço de e-mail do remetente, por exemplo: \"Immich Photo Server <noreply@example.com>\"",
|
||||
"notification_email_host_description": "Host do servidor de e-mail (por exemplo, smtp.immich.app)",
|
||||
"notification_email_ignore_certificate_errors": "Ignorar erros de certificado",
|
||||
"notification_email_ignore_certificate_errors_description": "Ignorar erros de validação de certificado TLS (não recomendado)",
|
||||
|
||||
@@ -152,7 +152,7 @@
|
||||
"note_cannot_be_changed_later": "NOTĂ: Nu se va mai putea modifica ulterior!",
|
||||
"note_unlimited_quota": "Notă: Introduceți 0 pentru cotă nelimitată",
|
||||
"notification_email_from_address": "De la adresa",
|
||||
"notification_email_from_address_description": "Adresa expeditorului, spre exemplu: „Immich Photo Server <noreply@immich.app>”",
|
||||
"notification_email_from_address_description": "Adresa expeditorului, spre exemplu: „Immich Photo Server <noreply@example.com>”",
|
||||
"notification_email_host_description": "Adresa serverului de email (e.g. smtp.immich.app)",
|
||||
"notification_email_ignore_certificate_errors": "Ingnoră erorile de certificat",
|
||||
"notification_email_ignore_certificate_errors_description": "Ignoră erorile de validare a certificatului TLS (nerecomandat)",
|
||||
@@ -235,95 +235,127 @@
|
||||
"storage_template_onboarding_description": "Atunci când este activată, această caracteristică va organiza automat fișierele pe baza unui șablon definit de utilizator. Din cauza unor probleme de stabilitate, aceasta caracteristică este dezactivată implicit. Pentru mai multe informații, te rog sa consulți <link>documentația</link>.",
|
||||
"storage_template_path_length": "Limita de lungime pentru calea aproximativă: <b>{length, number}</b>/{limit, number}",
|
||||
"storage_template_settings": "Șablon stocare",
|
||||
"storage_template_settings_description": "",
|
||||
"storage_template_settings_description": "Gestionează structura folderelor și numele fișierelor pentru activele încărcate",
|
||||
"storage_template_user_label": "<code>{label}</code> este eticheta de stocare a utilizatorului",
|
||||
"system_settings": "Setǎri de sistem",
|
||||
"theme_custom_css_settings": "CSS personalizat",
|
||||
"theme_custom_css_settings_description": "",
|
||||
"theme_settings": "",
|
||||
"theme_settings_description": "",
|
||||
"thumbnail_generation_job_description": "",
|
||||
"theme_custom_css_settings_description": "Foile de stil în cascadă (CSS) permit personalizarea designului Immich.",
|
||||
"theme_settings": "Setări temă",
|
||||
"theme_settings_description": "Gestionează personalizarea interfeței web Immich",
|
||||
"these_files_matched_by_checksum": "Aceste fișiere sunt comparate folosind sumele de control",
|
||||
"thumbnail_generation_job": "Gerează miniaturi",
|
||||
"thumbnail_generation_job_description": "Generează miniaturi mari, mici și estompate pentru fiecare resursă, precum și miniaturi pentru fiecare persoană",
|
||||
"transcode_policy_description": "",
|
||||
"transcoding_acceleration_api": "",
|
||||
"transcoding_acceleration_api_description": "",
|
||||
"transcoding_acceleration_api": "API de accelerare",
|
||||
"transcoding_acceleration_api_description": "API-ul care va interacționa cu dispozitivul tău pentru a accelera transcodarea. Această setare este 'best effort': va reveni la transcodarea software în caz de eșec. VP9 poate funcționa sau nu, în funcție de hardware-ul tău.",
|
||||
"transcoding_acceleration_nvenc": "NVENC (necesitǎ GPU NVIDIA)",
|
||||
"transcoding_acceleration_qsv": "Quick Sync (necesitǎ CPU Intel de generația a 7-a sau mai mare)",
|
||||
"transcoding_acceleration_rkmpp": "RKMPP (doar pe SOC-uri Rockchip)",
|
||||
"transcoding_acceleration_vaapi": "VAAPI",
|
||||
"transcoding_accepted_audio_codecs": "Codec-uri audio acceptate",
|
||||
"transcoding_accepted_audio_codecs_description": "",
|
||||
"transcoding_accepted_audio_codecs_description": "Selectează care codec-uri audio nu trebuie să fie transcodificate. Se utilizează doar pentru anumite politici de transcodare.",
|
||||
"transcoding_accepted_containers": "Containere acceptate",
|
||||
"transcoding_accepted_containers_description": "Selectează formatele de containere care nu trebuie să fie remuxate în MP4. Se utilizează doar pentru anumite politici de transcodare.",
|
||||
"transcoding_accepted_video_codecs": "Codec-uri video acceptate",
|
||||
"transcoding_accepted_video_codecs_description": "",
|
||||
"transcoding_advanced_options_description": "",
|
||||
"transcoding_accepted_video_codecs_description": "Selectează codec-urile video care nu trebuie să fie transcodificate. Se utilizează doar pentru anumite politici de transcodare.",
|
||||
"transcoding_advanced_options_description": "Opțiuni pe care majoritatea utilizatorilor nu ar trebui să fie necesar să le schimbe",
|
||||
"transcoding_audio_codec": "Codec audio",
|
||||
"transcoding_audio_codec_description": "",
|
||||
"transcoding_bitrate_description": "",
|
||||
"transcoding_constant_quality_mode": "",
|
||||
"transcoding_constant_quality_mode_description": "",
|
||||
"transcoding_constant_rate_factor": "",
|
||||
"transcoding_constant_rate_factor_description": "",
|
||||
"transcoding_disabled_description": "",
|
||||
"transcoding_hardware_acceleration": "",
|
||||
"transcoding_hardware_acceleration_description": "",
|
||||
"transcoding_hardware_decoding": "",
|
||||
"transcoding_hardware_decoding_setting_description": "",
|
||||
"transcoding_hevc_codec": "",
|
||||
"transcoding_audio_codec_description": "Opus este opțiunea cu cea mai bună calitate, dar are o compatibilitate mai scăzută cu dispozitivele sau software-ul mai vechi.",
|
||||
"transcoding_bitrate_description": "Videoclipuri cu un bitrate mai mare decât maximul acceptat sau care nu sunt într-un format acceptat",
|
||||
"transcoding_codecs_learn_more": "Pentru a afla mai multe despre terminologia folosită aici, consultă documentația FFmpeg pentru <h264-link>codec-ul H.264</h264-link>, <hevc-link>codec-ul HEVC</hevc-link> și <vp9-link>codec-ul VP9</vp9-link>.",
|
||||
"transcoding_constant_quality_mode": "Mod de calitate constantă",
|
||||
"transcoding_constant_quality_mode_description": "ICQ este mai bun decât CQP, dar unele dispozitive de accelerare hardware nu suportă acest mod. Setarea acestei opțiuni va prefera modul specificat atunci când folosești codificarea bazată pe calitate. Ignorat de NVENC deoarece nu suportă ICQ.",
|
||||
"transcoding_constant_rate_factor": "Factor de rată constantă (-crf)",
|
||||
"transcoding_constant_rate_factor_description": "Nivelul de calitate al videoclipului. Valorile tipice sunt 23 pentru H.264, 28 pentru HEVC, 31 pentru VP9 și 35 pentru AV1. Cu cât valoarea este mai mică, cu atât calitatea este mai bună, dar se generează fișiere mai mari.",
|
||||
"transcoding_disabled_description": "Nu transcodifică niciun videoclip; acest lucru poate afecta redarea pe anumite dispozitive",
|
||||
"transcoding_hardware_acceleration": "Accelerare Hardware",
|
||||
"transcoding_hardware_acceleration_description": "Experimental; mult mai rapid, dar va avea o calitate mai scăzută la același bitrate",
|
||||
"transcoding_hardware_decoding": "Decodare hardware",
|
||||
"transcoding_hardware_decoding_setting_description": "Se aplică doar pentru NVENC, QSV și RKMPP. Activează accelerarea completă în loc de doar accelerarea codificării. S-ar putea să nu funcționeze pentru toate videoclipurile.",
|
||||
"transcoding_hevc_codec": "codec HEVC",
|
||||
"transcoding_max_b_frames": "",
|
||||
"transcoding_max_b_frames_description": "",
|
||||
"transcoding_max_bitrate": "",
|
||||
"transcoding_max_bitrate_description": "",
|
||||
"transcoding_max_keyframe_interval": "",
|
||||
"transcoding_max_keyframe_interval_description": "",
|
||||
"transcoding_optimal_description": "",
|
||||
"transcoding_preferred_hardware_device": "",
|
||||
"transcoding_preferred_hardware_device_description": "",
|
||||
"transcoding_preset_preset": "",
|
||||
"transcoding_preset_preset_description": "",
|
||||
"transcoding_reference_frames": "",
|
||||
"transcoding_reference_frames_description": "",
|
||||
"transcoding_required_description": "",
|
||||
"transcoding_settings": "",
|
||||
"transcoding_settings_description": "",
|
||||
"transcoding_target_resolution": "",
|
||||
"transcoding_target_resolution_description": "",
|
||||
"transcoding_temporal_aq": "",
|
||||
"transcoding_temporal_aq_description": "",
|
||||
"transcoding_threads": "",
|
||||
"transcoding_threads_description": "",
|
||||
"transcoding_tone_mapping": "",
|
||||
"transcoding_tone_mapping_description": "",
|
||||
"transcoding_tone_mapping_npl": "",
|
||||
"transcoding_tone_mapping_npl_description": "",
|
||||
"transcoding_transcode_policy": "",
|
||||
"transcoding_two_pass_encoding": "",
|
||||
"transcoding_two_pass_encoding_setting_description": "",
|
||||
"transcoding_max_b_frames_description": "Valorile mai mari îmbunătățesc eficiența compresiei, dar încetinesc codarea. Este posibil să nu fie compatibile cu accelerarea hardware pe dispozitivele mai vechi. 0 dezactivează cadrele B, în timp ce -1 setează această valoare automat.",
|
||||
"transcoding_max_bitrate": "Bitrate maxim",
|
||||
"transcoding_max_bitrate_description": "Setarea unei rate maxime de biți poate face dimensiunile fișierelor mai previzibile, cu un cost minor asupra calității. La 720p, valorile tipice sunt 2600k pentru VP9 sau HEVC, sau 4500k pentru H.264. Dezactivat dacă este setat la 0.",
|
||||
"transcoding_max_keyframe_interval": "Interval maxim între cadre cheie",
|
||||
"transcoding_max_keyframe_interval_description": "Setează distanța maximă între cadrele cheie. Valorile mai mici reduc eficiența compresiei, dar îmbunătățesc timpii de căutare și pot îmbunătăți calitatea în scenele cu mișcare rapidă. 0 setează această valoare automat.",
|
||||
"transcoding_optimal_description": "Videoclipuri cu rezoluție mai mare decât cea țintă sau care nu sunt într-un format acceptat",
|
||||
"transcoding_preferred_hardware_device": "Dispozitiv hardware preferat",
|
||||
"transcoding_preferred_hardware_device_description": "Se aplică doar la VAAPI și QSV. Setează nodul DRI utilizat pentru transcodarea hardware.",
|
||||
"transcoding_preset_preset": "Presetare (-preset)",
|
||||
"transcoding_preset_preset_description": "Viteza de compresie. Presetările mai lente produc fișiere mai mici și îmbunătățesc calitatea atunci când vizezi o anumită rată de biți. VP9 ignoră vitezele de compresie mai mari decât 'mai rapid'.",
|
||||
"transcoding_reference_frames": "Cadre de referință",
|
||||
"transcoding_reference_frames_description": "Numărul de cadre de referință atunci când se comprimă un cadru dat. Valorile mai mari îmbunătățesc eficiența compresiei, dar încetinesc codarea. 0 setează această valoare automat.",
|
||||
"transcoding_required_description": "Numai videoclipuri care nu sunt într-un format acceptat",
|
||||
"transcoding_settings": "Setări de transcodare video",
|
||||
"transcoding_settings_description": "Gestionează rezoluția și informațiile de codare ale fișierelor video",
|
||||
"transcoding_target_resolution": "Rezoluția țintă",
|
||||
"transcoding_target_resolution_description": "Rezoluțiile mai mari pot păstra mai multe detalii, dar necesită mai mult timp pentru codare, au dimensiuni mai mari ale fișierelor și pot reduce răspunsul aplicației.",
|
||||
"transcoding_temporal_aq": "AQ temporal",
|
||||
"transcoding_temporal_aq_description": "Se aplică doar la NVENC. Îmbunătățește calitatea scenelor cu detalii mari și mișcare redusă. Poate să nu fie compatibil cu dispozitivele mai vechi.",
|
||||
"transcoding_threads": "Fire",
|
||||
"transcoding_threads_description": "Valorile mai mari conduc la o codare mai rapidă, dar lasă mai puțin spațiu serverului pentru a procesa alte sarcini în timp ce este activ. Această valoare nu ar trebui să fie mai mare decât numărul de nuclee CPU. Maximizați utilizarea dacă este setat la 0.",
|
||||
"transcoding_tone_mapping": "Mapare tonuri",
|
||||
"transcoding_tone_mapping_description": "Încearcă să păstreze aspectul videoclipurilor HDR atunci când sunt convertite în SDR. Fiecare algoritm face compromisuri diferite pentru culoare, detalii și strălucire. Hable păstrează detaliile, Mobius păstrează culoarea, iar Reinhard păstrează strălucirea.",
|
||||
"transcoding_tone_mapping_npl": "Mapare tonuri NPL",
|
||||
"transcoding_tone_mapping_npl_description": "Culorile vor fi ajustate pentru a arăta normal pe un ecran cu această strălucire. În mod contraintuitiv, valorile mai mici cresc strălucirea videoclipului și invers, deoarece compensează pentru strălucirea ecranului. 0 setează această valoare automat.",
|
||||
"transcoding_transcode_policy": "Politica de transcodare",
|
||||
"transcoding_transcode_policy_description": "Politica pentru când un videoclip ar trebui să fie transcodificat. Videoclipurile HDR vor fi întotdeauna transcodificate (cu excepția cazului în care transcodarea este dezactivată).",
|
||||
"transcoding_two_pass_encoding": "Codare în două treceri",
|
||||
"transcoding_two_pass_encoding_setting_description": "Transcodificare în două treceri pentru a produce videoclipuri codificate mai bine. Când rata maximă de biți este activată (necesară pentru a funcționa cu H.264 și HEVC), acest mod utilizează un interval de rată de biți bazat pe rata maximă de biți și ignoră CRF. Pentru VP9, CRF poate fi utilizat dacă rata maximă de biți este dezactivată.",
|
||||
"transcoding_video_codec": "Codec video",
|
||||
"transcoding_video_codec_description": "VP9 are eficiențǎ mare și compatibilitate web, însǎ transcodarea este de duratǎ mai mare. HEVC se comportǎ asemǎnǎtor, însǎ are compatibilitate web mai micǎ. H.264 este foarte compatibil și rapid în transcodare, însǎ genereazǎ fișiere mult mai mari. AV1 este cel mai eficient codec dar nu este compatibil cu dispozitivele mai vechi.",
|
||||
"trash_enabled_description": "",
|
||||
"trash_enabled_description": "Activează funcțiile Coș de gunoi",
|
||||
"trash_number_of_days": "Numǎr de zile",
|
||||
"trash_number_of_days_description": "Numǎr de zile pentru pǎstrarea fișierelor în coșul de gunoi pânǎ la ștergerea permanentǎ",
|
||||
"trash_settings": "Setǎri coș de gunoi",
|
||||
"trash_settings_description": "Gestioneazǎ setǎrile coșului de gunoi",
|
||||
"user_delete_delay_settings": "",
|
||||
"user_delete_delay_settings_description": "",
|
||||
"untracked_files": "Fișiere neurmărite",
|
||||
"untracked_files_description": "Aceste fișiere nu sunt urmărite de aplicație. Ele pot fi rezultatul unor mutări eșuate, încărcări întrerupte sau pot rămâne în urmă din cauza unei erori",
|
||||
"user_delete_delay": "Contul și resursele utilizatorului <b>{user}</b> vor fi programate pentru ștergere permanentă în {delay, plural, one {# zi} other {# zile}}.",
|
||||
"user_delete_delay_settings": "Întârziere la ștergere",
|
||||
"user_delete_delay_settings_description": "Numărul de zile după eliminare până la ștergerea permanentă a contului și a resurselor unui utilizator. Procesul de ștergere a utilizatorului rulează la miezul nopții pentru a verifica utilizatorii care sunt pregătiți pentru ștergere. Modificările aduse acestei setări vor fi evaluate la următoarea execuție.",
|
||||
"user_delete_immediately": "Contul și resursele utilizatorului <b>{user}</b> vor fi puse în coadă pentru ștergere permanentă <b>imediat</b>.",
|
||||
"user_delete_immediately_checkbox": "Pune utilizatorul și resursele în coadă pentru ștergere imediată",
|
||||
"user_management": "Gestionarea Utilizatorilor",
|
||||
"user_password_has_been_reset": "Parola utilizatorului a fost resetată:",
|
||||
"user_password_reset_description": "Vă rugăm să furnizați utilizatorului parola temporară și să îi informați că va trebui să o schimbe la următoarea autentificare.",
|
||||
"user_restore_description": "Contul utilizatorului <b>{user}</b> va fi restaurat.",
|
||||
"user_restore_scheduled_removal": "Restaurare utilizator - ștergere programată pe {date, date, long}",
|
||||
"user_settings": "Setǎri utilizator",
|
||||
"user_settings_description": "Gestioneazǎ setǎrile utilizatorului",
|
||||
"version_check_enabled_description": "Activeazǎ verificarea periodicǎ pe GitHub pentru versiuni noi",
|
||||
"user_successfully_removed": "Utilizatorul {email} a fost eliminat cu succes.",
|
||||
"version_check_enabled_description": "Activează verificarea versiunii",
|
||||
"version_check_implications": "Funcția de verificare a versiunii se bazează pe comunicarea periodică cu github.com",
|
||||
"version_check_settings": "Verificare versiune",
|
||||
"version_check_settings_description": "Activeazǎ/dezactiveazǎ notificarea unei noi versiuni",
|
||||
"video_conversion_job_description": "Transcodeazǎ videoclipurile pentru compatibilitate cu browsere și dispozitive"
|
||||
"video_conversion_job": "Transcodați videoclipuri",
|
||||
"video_conversion_job_description": "Transcodați videoclipurile pentru o compatibilitate mai mare cu browserele și dispozitivele"
|
||||
},
|
||||
"admin_email": "E-mailul administratorului",
|
||||
"admin_password": "Parola administratorului",
|
||||
"admin_password": "Parolă administrator",
|
||||
"administration": "Administrare",
|
||||
"advanced": "Avansat",
|
||||
"age_months": "Vârstă {months, plural, one {# lună} other {# luni}}",
|
||||
"age_year_months": "Vârstă de 1 an, {months, plural, one {# lună} other {# luni}}",
|
||||
"album_added": "Album adăugat",
|
||||
"album_added_notification_setting_description": "Primiți o notificare prin e-mail când sunteți adăugat la un album partajat",
|
||||
"album_cover_updated": "Coperta albumului a fost actualizată",
|
||||
"album_info_updated": "Informațiile albumului au fost actualizate",
|
||||
"album_name": "Nume de album",
|
||||
"album_options": "Opțiuni de album",
|
||||
"album_delete_confirmation": "Ești sigur că vrei să ștergi albumul {album}?",
|
||||
"album_delete_confirmation_description": "Dacă acest album este partajat, alți utilizatori nu vor mai putea accesa.",
|
||||
"album_info_updated": "Informații album actualizate",
|
||||
"album_leave": "Lăsați albumul?",
|
||||
"album_leave_confirmation": "Ești sigur că dorești să părăsești {album}?",
|
||||
"album_name": "Nume album",
|
||||
"album_options": "Opțiuni album",
|
||||
"album_remove_user": "Eliminare utilizator?",
|
||||
"album_remove_user_confirmation": "Ești sigur că dorești eliminarea {user}?",
|
||||
"album_share_no_users": "Se pare că ai partajat acest album cu toți utilizatorii sau nu ai niciun utilizator cu care să-l partajezi.",
|
||||
"album_updated": "Album actualizat",
|
||||
"album_updated_setting_description": "Primiți o notificare prin e-mail când un album partajat are elemente noi",
|
||||
"album_user_left": "A părăsit {album}",
|
||||
"album_user_removed": "{user} eliminat",
|
||||
"album_with_link_access": "Permite oricui cu link-ul să vadă fotografiile și persoanele din acest album.",
|
||||
"albums": "Albume",
|
||||
"albums_count": "{count, plural, one {{count, number} Album} other {{count, number} Albume}}",
|
||||
"all": "Toate",
|
||||
@@ -334,40 +366,58 @@
|
||||
"allow_edits": "Permite editări",
|
||||
"allow_public_user_to_download": "Permite utilizatorului public să descarce",
|
||||
"allow_public_user_to_upload": "Permite utilizatorului public să încarce",
|
||||
"anti_clockwise": "În sens invers acelor de ceasornic",
|
||||
"api_key": "Cheie API",
|
||||
"api_key_description": "Această valoare va fi afișată o singură dată. Vă rugăm să vă asigurați că o copiați înainte de a închide fereastra.",
|
||||
"api_key_empty": "Numele cheii API nu trebuie să fie gol",
|
||||
"api_keys": "Chei API",
|
||||
"app_settings": "Setări în aplicație",
|
||||
"app_settings": "Setări Aplicație",
|
||||
"appears_in": "Apare în",
|
||||
"archive": "Arhivă",
|
||||
"archive_or_unarchive_photo": "Arhiveazǎ sau dezarhiveazǎ fotografia",
|
||||
"archive_size": "Mărime arhivă",
|
||||
"archive_size_description": "Configurează dimensiunea arhivei pentru descărcări (în GiB)",
|
||||
"archived": "",
|
||||
"archived_count": "{count, plural, one {S-a arhivat #}, other {S-au arhivat #}}",
|
||||
"archived_count": "{count, plural, other {Arhivat/e#}}",
|
||||
"are_these_the_same_person": "Sunt aceștia aceeași persoană?",
|
||||
"are_you_sure_to_do_this": "Sunteți sigur că doriți să faceți acest lucru?",
|
||||
"asset_added_to_album": "Adăugat la album",
|
||||
"asset_adding_to_album": "Se adauga la album...",
|
||||
"asset_adding_to_album": "Se adaugă la album...",
|
||||
"asset_description_updated": "Descrierea activelor a fost actualizată",
|
||||
"asset_filename_is_offline": "Activul {filename} este offline",
|
||||
"asset_has_unassigned_faces": "Activul are fețe neatribuite",
|
||||
"asset_hashing": "Hasurare...",
|
||||
"asset_filename_is_offline": "Resursa {filename} este offline",
|
||||
"asset_has_unassigned_faces": "Resursa are fețe neatribuite",
|
||||
"asset_hashing": "Hașurare...",
|
||||
"asset_offline": "Resursă offline",
|
||||
"asset_offline_description": "Acest activ este offline. Immich nu poate accesa locația fișierului său. Vă rugăm să vă asigurați că activul este disponibil și apoi să efectuați o nouă scanare a bibliotecii.",
|
||||
"asset_offline_description": "Această resursă este offline. Immich nu poate accesa locația fișierului său. Vă rugăm să vă asigurați că resursa este disponibilă și apoi să efectuați o nouă scanare a bibliotecii.",
|
||||
"asset_skipped": "Sărit",
|
||||
"asset_skipped_in_trash": "În gunoi",
|
||||
"asset_uploaded": "Încărcat",
|
||||
"asset_uploading": "Se incărca...",
|
||||
"asset_uploading": "Se incarcă...",
|
||||
"assets": "Resurse",
|
||||
"assets_added_count": "Adăugat {count, plural, one {# resursă} other {# resurse}}",
|
||||
"assets_added_to_album_count": "Am adăugat {count, plural, one {# resursă} other {# resurse}} în album",
|
||||
"assets_added_to_name_count": "Am adăugat {count, plural, one {# resursă} other {# resurse}} în {hasName, select, true {<b>{name}</b>} other {albumul nou}}",
|
||||
"assets_count": "{count, plural, one {# resursă} other {# resurse}}",
|
||||
"assets_moved_to_trash_count": "Am mutat {count, plural, one {# resursă} other {# resurse}} în coșul de gunoi",
|
||||
"assets_permanently_deleted_count": "Șters permanent {count, plural, one {# resursă} other {# resurse}}",
|
||||
"assets_removed_count": "Eliminat {count, plural, one {# resursă} other {# resurse}}",
|
||||
"assets_restore_confirmation": "Ești sigur că vrei să restaurezi toate resursele tale din coșul de gunoi? Nu poți anula această acțiune!",
|
||||
"assets_restored_count": "Restaurat {count, plural, one {# resursă} other {# resurse}}",
|
||||
"assets_trashed_count": "Mutat în coșul de gunoi {count, plural, one {# resursă} other {# resurse}}",
|
||||
"assets_were_part_of_album_count": "{count, plural, one {Resursa era} other {Resursele erau}} deja parte din album",
|
||||
"authorized_devices": "Dispozitive autorizate",
|
||||
"back": "Înapoi",
|
||||
"back_close_deselect": "Înapoi, închidere sau deselectare",
|
||||
"backward": "Invers",
|
||||
"backward": "În sens invers",
|
||||
"birthdate_saved": "Data nașterii salvată cu succes",
|
||||
"birthdate_set_description": "Data nașterii este utilizată pentru a calcula vârsta acestei persoane la momentul realizării fotografiei.",
|
||||
"blurred_background": "Fundal neclar",
|
||||
"build": "Construiți",
|
||||
"build_image": "Construiți o imagine",
|
||||
"bulk_delete_duplicates_confirmation": "Sunteți sigur că doriți să ștergeți în masă {count, plural, one {# duplicate asset} other {# duplicate assets}}? Acest lucru va păstra cel mai mare activ din fiecare grup și va șterge definitiv toate celelalte duplicate. Nu puteți anula această acțiune!",
|
||||
"buy": "Cumpără Immich",
|
||||
"build_image": "Construiți imagine",
|
||||
"bulk_delete_duplicates_confirmation": "Ești sigur că vrei să ștergi în masă {count, plural, one {# resursă duplicată} other {# resurse duplicate}}? Aceasta va păstra cea mai mare resursă din fiecare grup și va șterge permanent toate celelalte duplicate. Nu poți anula această acțiune!",
|
||||
"bulk_keep_duplicates_confirmation": "Ești sigur că vrei să păstrezi {count, plural, one {# resursă duplicată} other {# resurse duplicate}}? Aceasta va rezolva toate grupurile duplicate fără a șterge nimic.",
|
||||
"bulk_trash_duplicates_confirmation": "Ești sigur că vrei să muți în coșul de gunoi {count, plural, one {# resursă duplicată} other {# resurse duplicate}}? Aceasta va păstra cea mai mare resursă din fiecare grup și va muta în coșul de gunoi toate celelalte duplicate.",
|
||||
"buy": "Achiziționează Immich",
|
||||
"camera": "Camerǎ",
|
||||
"camera_brand": "Marcǎ cameră",
|
||||
"camera_model": "Model cameră",
|
||||
@@ -381,37 +431,41 @@
|
||||
"cant_search_people": "",
|
||||
"cant_search_places": "",
|
||||
"change_date": "Schimbă dată",
|
||||
"change_expiration_time": "Shimbă data expirării",
|
||||
"change_expiration_time": "Shimbă dată expirare",
|
||||
"change_location": "Schimbă locația",
|
||||
"change_name": "Schimbă numele",
|
||||
"change_name_successfully": "Schimbă numele cu succes",
|
||||
"change_password": "Schimbă parola",
|
||||
"change_password_description": "Aceasta este fie prima dată când vă conectați la sistem, fie vi s-a solicitat să vă schimbați parola. Vă rugăm să introduceți noua parolă mai jos.",
|
||||
"change_name": "Schimbă nume",
|
||||
"change_name_successfully": "Schimbare nume cu succes",
|
||||
"change_password": "Schimbă Parolă",
|
||||
"change_password_description": "Aceasta este fie prima dată când te conectezi în sistem, fie s-a făcut o solicitare pentru a schimba parola ta. Te rog să introduci noua parolă mai jos.",
|
||||
"change_your_password": "Schimbă-ți parola",
|
||||
"changed_visibility_successfully": "Schimbă visibilitate cu succes",
|
||||
"check_logs": "Verificarea logurilor",
|
||||
"choose_matching_people_to_merge": "Alegeți persoanele potrivite pentru fuzionare",
|
||||
"changed_visibility_successfully": "Schimbare vizibilitate cu succes",
|
||||
"check_all": "Selectează Tot",
|
||||
"check_logs": "Verifică Jurnale",
|
||||
"choose_matching_people_to_merge": "Alegeți persoanele care se potrivesc pentru a le fuziona",
|
||||
"city": "Oraș",
|
||||
"clear": "ȘTERGE",
|
||||
"clear_all": "Șterge tot",
|
||||
"clear": "Curăță",
|
||||
"clear_all": "Curăță tot",
|
||||
"clear_all_recent_searches": "Curăță toate căutările recente",
|
||||
"clear_message": "Șterge mesajul",
|
||||
"clear_value": "Valoare clară",
|
||||
"clear_value": "Șterge valoare",
|
||||
"clockwise": "În sensul acelor de ceas",
|
||||
"close": "Închide",
|
||||
"collapse": "Colaps",
|
||||
"collapse_all": "Închideți pe toate",
|
||||
"collapse": "Restrânge",
|
||||
"collapse_all": "Restrânge pe toate",
|
||||
"color": "Culoare",
|
||||
"color_theme": "Tema de culoare",
|
||||
"comment_deleted": "Comentariu șters",
|
||||
"comment_options": "Opțiuni de comentariu",
|
||||
"comments_and_likes": "Comentarii și aprecieri",
|
||||
"comment_options": "Opțiuni comentariu",
|
||||
"comments_and_likes": "Comentarii & aprecieri",
|
||||
"comments_are_disabled": "Comentariile sunt dezactivate",
|
||||
"confirm": "Confirmați",
|
||||
"confirm_admin_password": "Confirmați parola de administrator",
|
||||
"confirm_delete_shared_link": "Sunteți sigur că doriți să ștergeți acest link partajat?",
|
||||
"confirm_password": "Confirmați parola",
|
||||
"contain": "Conține",
|
||||
"contain": "Încadrează",
|
||||
"context": "Context",
|
||||
"continue": "Continuați",
|
||||
"copied_image_to_clipboard": "Copiat imaginea în clipboard.",
|
||||
"copied_image_to_clipboard": "Imaginea copiată în clipboard.",
|
||||
"copied_to_clipboard": "Copiat în clipboard!",
|
||||
"copy_error": "Eroare de copiere",
|
||||
"copy_file_path": "Copiați calea fișierului",
|
||||
@@ -421,64 +475,70 @@
|
||||
"copy_password": "Copiați parola",
|
||||
"copy_to_clipboard": "Copiere în Clipboard",
|
||||
"country": "Țara",
|
||||
"cover": "Acoperire",
|
||||
"covers": "Acoperiri",
|
||||
"cover": "Umple fereastra",
|
||||
"covers": "Acoperă",
|
||||
"create": "Creează",
|
||||
"create_album": "Creează album",
|
||||
"create_library": "Crearea bibliotecii",
|
||||
"create_library": "Creează bibliotecă",
|
||||
"create_link": "Creează link",
|
||||
"create_link_to_share": "Creează link pentru a distribui",
|
||||
"create_link_to_share_description": "Permiteți oricui are link-ul să vadă fotografia (fotografiile) selectată(e)",
|
||||
"create_new_person": "Creați o persoană nouă",
|
||||
"create_new_person_hint": "Atribuiți activele selectate unei persoane noi",
|
||||
"create_new_user": "Crearea unui nou utilizator",
|
||||
"create_new_person_hint": "Atribuiți resursele selectate unei persoane noi",
|
||||
"create_new_user": "Creează utilizator nou",
|
||||
"create_tag": "Creează etichetă",
|
||||
"create_tag_description": "Creează o etichetă nouă. Pentru etichete imbricate, te rog să introduci calea completă a etichetei, inclusiv bare oblice (/).",
|
||||
"create_user": "Creează utilizator",
|
||||
"created": "Creat",
|
||||
"current_device": "Dispozitiv curent",
|
||||
"custom_locale": "Local personalizat",
|
||||
"custom_locale": "Setare regională personalizată",
|
||||
"custom_locale_description": "Formatați datele și numerele în funcție de limbă și regiune",
|
||||
"dark": "Întuneric",
|
||||
"date_after": "Data după",
|
||||
"dark": "Întunecat",
|
||||
"date_after": "Dată după",
|
||||
"date_and_time": "Dată și Oră",
|
||||
"date_before": "Data anterioară",
|
||||
"date_before": "Dată anterioară",
|
||||
"date_of_birth_saved": "Data nașterii salvată cu succes",
|
||||
"date_range": "Interval de date",
|
||||
"day": "Ziua",
|
||||
"day": "Zi",
|
||||
"deduplicate_all": "Deduplicați toate",
|
||||
"default_locale": "Local implicit",
|
||||
"default_locale_description": "Formatați datele și numerele în funcție de locația browserului dvs.",
|
||||
"default_locale": "Setare regionlă implicită",
|
||||
"default_locale_description": "Formatați datele și numerele în funcție de regiunea browserului dvs",
|
||||
"delete": "Șterge",
|
||||
"delete_album": "Șterge album",
|
||||
"delete_api_key_prompt": "Sunteți sigur că doriți să ștergeți această cheie API?",
|
||||
"delete_duplicates_confirmation": "Sunteți sigur că doriți să ștergeți permanent aceste duplicate?",
|
||||
"delete_key": "Tasta de ștergere",
|
||||
"delete_library": "Ștergeți biblioteca",
|
||||
"delete_link": "Ștergeți linkul",
|
||||
"delete_shared_link": "Ștergeți link-ul partajat",
|
||||
"delete_user": "Ștergeți utilizatorul",
|
||||
"delete_key": "Șterge cheie",
|
||||
"delete_library": "Șterge biblioteca",
|
||||
"delete_link": "Șterge linkul",
|
||||
"delete_shared_link": "Șterge link-ul partajat",
|
||||
"delete_tag": "Șterge etichetă",
|
||||
"delete_tag_confirmation_prompt": "Ești sigur că vrei să ștergi eticheta {tagName} ?",
|
||||
"delete_user": "Șterge utilizator",
|
||||
"deleted_shared_link": "Link partajat șters",
|
||||
"description": "Descriere",
|
||||
"details": "DETALII",
|
||||
"details": "Detalii",
|
||||
"direction": "Direcție",
|
||||
"disabled": "Dezactivat",
|
||||
"disallow_edits": "Interziceți editările",
|
||||
"disallow_edits": "Interzice modificările",
|
||||
"discover": "Descoperiți",
|
||||
"dismiss_all_errors": "Eliminați toate erorile",
|
||||
"dismiss_error": "Anulați eroarea",
|
||||
"dismiss_all_errors": "Ignoră toate erorile",
|
||||
"dismiss_error": "Ignorați eroarea",
|
||||
"display_options": "Opțiuni de afișare",
|
||||
"display_order": "Ordine de afișare",
|
||||
"display_original_photos": "Afișați fotografiile originale",
|
||||
"display_original_photos_setting_description": "Preferați să afișați fotografia originală atunci când vizualizați un bun în loc de miniaturi atunci când bunul original este compatibil cu web. Acest lucru poate duce la o viteză mai mică de afișare a fotografiilor.",
|
||||
"do_not_show_again": "Nu mai afișați acest mesaj",
|
||||
"display_original_photos_setting_description": "Preferă să afișezi fotografia originală atunci când vizualizezi o resursă, în loc de miniaturi, atunci când resursa originală este compatibilă cu web-ul. Aceasta poate duce la viteze mai lente de afișare a fotografiilor.",
|
||||
"do_not_show_again": "Nu mai afișa acest mesaj",
|
||||
"done": "Gata",
|
||||
"download": "Descarcă",
|
||||
"download_include_embedded_motion_videos": "Videoclipuri încorporate",
|
||||
"download_include_embedded_motion_videos_description": "Include videoclipurile încorporate în fotografiile în mișcare ca fișier separat",
|
||||
"download_settings": "Descarcă",
|
||||
"download_settings_description": "Gestionați setările legate de descărcarea activelor",
|
||||
"downloading": "Descărcare",
|
||||
"downloading_asset_filename": "Descărcarea activului {filename}",
|
||||
"drop_files_to_upload": "Aruncați fișiere oriunde pentru a le încărca",
|
||||
"download_settings_description": "Gestionați setările legate de descărcarea resurselor",
|
||||
"downloading": "Se descarcă",
|
||||
"downloading_asset_filename": "Se descarcă resursa {filename}",
|
||||
"drop_files_to_upload": "Trage fișierele aici pentru a le încărca",
|
||||
"duplicates": "Duplicate",
|
||||
"duplicates_description": "Rezolvați fiecare grup indicând care, dacă există, sunt duplicate",
|
||||
"duplicates_description": "Rezolvați fiecare grup indicând care sunt duplicate, dacă există",
|
||||
"duration": "Durată",
|
||||
"durations": {
|
||||
"days": "",
|
||||
@@ -487,13 +547,13 @@
|
||||
"months": "",
|
||||
"years": ""
|
||||
},
|
||||
"edit": "Editare",
|
||||
"edit_album": "Editare album",
|
||||
"edit_avatar": "Editare avatar",
|
||||
"edit_date": "Editează data",
|
||||
"edit_date_and_time": "Editarea datei și orei",
|
||||
"edit": "Modifică",
|
||||
"edit_album": "Modificare album",
|
||||
"edit_avatar": "Modificare avatar",
|
||||
"edit_date": "Modifică data",
|
||||
"edit_date_and_time": "Modifică data și ora",
|
||||
"edit_exclusion_pattern": "Editarea modelului de excludere",
|
||||
"edit_faces": "Editează fețele",
|
||||
"edit_faces": "Modifică fețele",
|
||||
"edit_import_path": "Editarea căii de import",
|
||||
"edit_import_paths": "Editarea căilor de import",
|
||||
"edit_key": "Tastă de editare",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"about": "О продукте",
|
||||
"account": "Учётная запись",
|
||||
"account_settings": "Настройки учётной записи",
|
||||
"account_settings": "Настройки аккаунта",
|
||||
"acknowledge": "Подтвердить",
|
||||
"action": "Действие",
|
||||
"actions": "Действия",
|
||||
@@ -152,7 +152,7 @@
|
||||
"note_cannot_be_changed_later": "ПРИМЕЧАНИЕ: Это невозможно изменить позже!",
|
||||
"note_unlimited_quota": "Примечание: Введите 0 для неограниченной квоты или оставьте пустым",
|
||||
"notification_email_from_address": "Адрес отправителя",
|
||||
"notification_email_from_address_description": "Адрес электронной почты отправителя, например: \"Immich Photo Server <noreply@immich.app>\"",
|
||||
"notification_email_from_address_description": "Адрес электронной почты отправителя, например: \"Immich Photo Server <noreply@example.com>\"",
|
||||
"notification_email_host_description": "Доменное имя почтового сервера (например, smtp.immich.app)",
|
||||
"notification_email_ignore_certificate_errors": "Игнорировать ошибки сертификата",
|
||||
"notification_email_ignore_certificate_errors_description": "Игнорировать ошибки проверки сертификата TLS (не рекомендуется)",
|
||||
@@ -661,6 +661,7 @@
|
||||
"unable_to_get_comments_number": "Не удалось получить количество комментариев",
|
||||
"unable_to_get_shared_link": "Не удалось получить общую ссылку",
|
||||
"unable_to_hide_person": "Невозможно скрыть персону",
|
||||
"unable_to_link_motion_video": "Не удается связать движущееся видео",
|
||||
"unable_to_link_oauth_account": "Не удается связать учетную запись OAuth",
|
||||
"unable_to_load_album": "Невозможно загрузить альбом",
|
||||
"unable_to_load_asset_activity": "Не удалось загрузить активность объекта",
|
||||
@@ -701,6 +702,7 @@
|
||||
"unable_to_submit_job": "Невозможно отправить задание",
|
||||
"unable_to_trash_asset": "Невозможно удалить актив",
|
||||
"unable_to_unlink_account": "Не удалось отсоединить учетную запись",
|
||||
"unable_to_unlink_motion_video": "Не удается отсоединить движущееся видео",
|
||||
"unable_to_update_album_cover": "Невозможно обновить обложку альбома",
|
||||
"unable_to_update_album_info": "Невозможно обновить информацию об альбоме",
|
||||
"unable_to_update_library": "Не удалось обновить библиотеку",
|
||||
@@ -1291,6 +1293,7 @@
|
||||
"unknown_album": "Неизвестный альбом",
|
||||
"unknown_year": "Неизвестный Год",
|
||||
"unlimited": "Не ограничено",
|
||||
"unlink_motion_video": "Отсоединить движущееся видео",
|
||||
"unlink_oauth": "Отключить OAuth",
|
||||
"unlinked_oauth_account": "Отключить аккаунт OAuth",
|
||||
"unnamed_album": "Альбом без названия",
|
||||
|
||||
@@ -112,7 +112,7 @@
|
||||
"map_reverse_geocoding": "",
|
||||
"map_reverse_geocoding_enable_description": "",
|
||||
"map_reverse_geocoding_settings": "",
|
||||
"map_settings": "",
|
||||
"map_settings": "Mapa",
|
||||
"map_settings_description": "",
|
||||
"map_style_description": "",
|
||||
"metadata_extraction_job_description": "",
|
||||
@@ -460,7 +460,7 @@
|
||||
"expand_all": "",
|
||||
"expire_after": "Expiruje po",
|
||||
"expired": "Vypršalo",
|
||||
"explore": "",
|
||||
"explore": "Preskúmať",
|
||||
"extension": "",
|
||||
"external_libraries": "",
|
||||
"failed_to_get_people": "",
|
||||
|
||||
@@ -152,7 +152,7 @@
|
||||
"note_cannot_be_changed_later": "НАПОМЕНА: Ovo se kasnije ne može promeniti!",
|
||||
"note_unlimited_quota": "Напомена: Unesite 0 za neograničenu kvotu",
|
||||
"notification_email_from_address": "Са адресе",
|
||||
"notification_email_from_address_description": "Адреса е-поште пошиљаоца, на пример: \"Immich foto server <noreply@immich.app>\"",
|
||||
"notification_email_from_address_description": "Адреса е-поште пошиљаоца, на пример: \"Immich foto server <noreply@example.com>\"",
|
||||
"notification_email_host_description": "Хост сервера е-поште (нпр. smtp.immich.app)",
|
||||
"notification_email_ignore_certificate_errors": "Занемарите грешке сертификата",
|
||||
"notification_email_ignore_certificate_errors_description": "Игноришите грешке у валидацији ТЛС сертификата (не препоручује се)",
|
||||
@@ -661,6 +661,7 @@
|
||||
"unable_to_get_comments_number": "Није могуће добити број коментара",
|
||||
"unable_to_get_shared_link": "Преузимање дељене везе није успело",
|
||||
"unable_to_hide_person": "Није могуће сакрити особу",
|
||||
"unable_to_link_motion_video": "Није могуће повезати (link) видео снимак",
|
||||
"unable_to_link_oauth_account": "Није могуће повезати OAuth налог",
|
||||
"unable_to_load_album": "Није могуће учитати албум",
|
||||
"unable_to_load_asset_activity": "Није могуће учитати активност средстава",
|
||||
@@ -701,6 +702,7 @@
|
||||
"unable_to_submit_job": "Није могуће предати задатак",
|
||||
"unable_to_trash_asset": "Није могуће избацити материјал у отпад",
|
||||
"unable_to_unlink_account": "Није могуће раскинути профил",
|
||||
"unable_to_unlink_motion_video": "Није могуће прекинути везу са видео снимком",
|
||||
"unable_to_update_album_cover": "Није могуће ажурирати насловницу албума",
|
||||
"unable_to_update_album_info": "Није могуће ажурирати информације о албуму",
|
||||
"unable_to_update_library": "Није могуће ажурирати библиотеку",
|
||||
@@ -1291,6 +1293,7 @@
|
||||
"unknown_album": "Nepoznat Album",
|
||||
"unknown_year": "Непозната Година",
|
||||
"unlimited": "Неограничено",
|
||||
"unlink_motion_video": "Прекините везу са видео снимком",
|
||||
"unlink_oauth": "Прекини везу са Oauth-om",
|
||||
"unlinked_oauth_account": "Опозвана веза OAuth налога",
|
||||
"unnamed_album": "Неименовани албум",
|
||||
|
||||
@@ -152,7 +152,7 @@
|
||||
"note_cannot_be_changed_later": "NAPOMENA: Ovo se kasnije ne može promeniti!",
|
||||
"note_unlimited_quota": "Napomena: Unesite 0 za neograničenu kvotu",
|
||||
"notification_email_from_address": "Sa adrese",
|
||||
"notification_email_from_address_description": "Adresa e-pošte pošiljaoca, na primer: \"Immich foto server <noreply@immich.app>\"",
|
||||
"notification_email_from_address_description": "Adresa e-pošte pošiljaoca, na primer: \"Immich foto server <noreply@example.com>\"",
|
||||
"notification_email_host_description": "Host servera e-pošte (npr. smtp.immich.app)",
|
||||
"notification_email_ignore_certificate_errors": "Zanemarite greške sertifikata",
|
||||
"notification_email_ignore_certificate_errors_description": "Ignorišite greške u validaciji TLS sertifikata (ne preporučuje se)",
|
||||
@@ -661,6 +661,7 @@
|
||||
"unable_to_get_comments_number": "Nije moguće dobiti broj komentara",
|
||||
"unable_to_get_shared_link": "Preuzimanje deljene veze nije uspelo",
|
||||
"unable_to_hide_person": "Nije moguće sakriti osobu",
|
||||
"unable_to_link_motion_video": "Nije moguće povezati video sa slikom",
|
||||
"unable_to_link_oauth_account": "Nije moguće povezati OAuth nalog",
|
||||
"unable_to_load_album": "Nije moguće učitati album",
|
||||
"unable_to_load_asset_activity": "Nije moguće učitati aktivnost sredstava",
|
||||
@@ -701,6 +702,7 @@
|
||||
"unable_to_submit_job": "Nije moguće predati zadatak",
|
||||
"unable_to_trash_asset": "Nije moguće izbaciti materijal u otpad",
|
||||
"unable_to_unlink_account": "Nije moguće raskinuti profil",
|
||||
"unable_to_unlink_motion_video": "Nije moguće odvezati video sa slikom",
|
||||
"unable_to_update_album_cover": "Nije moguće ažurirati naslovnicu albuma",
|
||||
"unable_to_update_album_info": "Nije moguće ažurirati informacije o albumu",
|
||||
"unable_to_update_library": "Nije moguće ažurirati biblioteku",
|
||||
@@ -1291,6 +1293,7 @@
|
||||
"unknown_album": "Nepoznat Album",
|
||||
"unknown_year": "Nepoznata Godina",
|
||||
"unlimited": "Neograničeno",
|
||||
"unlink_motion_video": "Odveži video od slike",
|
||||
"unlink_oauth": "Prekini vezu sa Oauth-om",
|
||||
"unlinked_oauth_account": "Opozvana veza OAuth naloga",
|
||||
"unnamed_album": "Neimenovani album",
|
||||
|
||||
@@ -152,7 +152,7 @@
|
||||
"note_cannot_be_changed_later": "OBS: Detta kan inte ändras i efterhand!",
|
||||
"note_unlimited_quota": "OBS: Skriv 0 för obegränsad kvota",
|
||||
"notification_email_from_address": "Från adress",
|
||||
"notification_email_from_address_description": "Avsändarens epost, t.ex.: \"Immich Fotoserver <noreply@immich.app>\"",
|
||||
"notification_email_from_address_description": "Avsändarens epost, t.ex.: \"Immich Fotoserver <noreply@example.com>\"",
|
||||
"notification_email_host_description": "Värd för epostservern (t.ex. smtp.immich.app)",
|
||||
"notification_email_ignore_certificate_errors": "Ignorera certifikatfel",
|
||||
"notification_email_ignore_certificate_errors_description": "Ignorera valideringsfel för TLS-certifikat (rekommenderas ej)",
|
||||
|
||||
@@ -143,7 +143,7 @@
|
||||
"note_cannot_be_changed_later": "குறிப்பு: இதை பின்னர் மாற்ற முடியாது!",
|
||||
"note_unlimited_quota": "குறிப்பு: வரம்பற்ற ஒதுக்கீட்டிற்கு 0 ஐ உள்ளிடவும்",
|
||||
"notification_email_from_address": "முகவரியிலிருந்து",
|
||||
"notification_email_from_address_description": "அனுப்புநரின் மின்னஞ்சல் முகவரி, எடுத்துக்காட்டாக: \"இம்மிச் புகைப்பட சேவையகம் <noreply@immich.app>\"",
|
||||
"notification_email_from_address_description": "அனுப்புநரின் மின்னஞ்சல் முகவரி, எடுத்துக்காட்டாக: \"இம்மிச் புகைப்பட சேவையகம் <noreply@example.com>\"",
|
||||
"notification_email_host_description": "மின்னஞ்சல் சேவையகத்தின் ஹோஸ்ட் (எடுத்துக்காட்டாக: smtp.immich.app)",
|
||||
"notification_email_ignore_certificate_errors": "சான்றிதழ் பிழைகளை புறக்கணிக்கவும்",
|
||||
"notification_email_ignore_certificate_errors_description": "TLS சான்றிதழ் சரிபார்ப்பு பிழைகளை புறக்கணிக்கவும் (பரிந்துரைக்கப்படவில்லை)",
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
"add_to_shared_album": "เพิ่มเข้าอัลบั้มที่แชร์",
|
||||
"added_to_archive": "เพิ่มเข้าที่เก็บถาวร",
|
||||
"added_to_favorites": "เพิ่มเข้ารายการโปรด",
|
||||
"added_to_favorites_count": "{count} รูปถูกเพิ่มเข้ารายการโปรด",
|
||||
"added_to_favorites_count": "{count, number} รูปถูกเพิ่มเข้ารายการโปรด",
|
||||
"admin": {
|
||||
"add_exclusion_pattern_description": "เพิ่มรูปแบบการยกเว้น การ Glob โดยใช้ *, ** และ ? ถูกรองรับ ถ้าต้องการละเว้นไฟล์ทั้งหมดในไดเร็กทอรีใดๆที่ชื่อว่า \"Raw\" ให้ใช้ \"**/Raw/**\" ถ้าต้องการละเว้นไฟล์ทั้งหมดที่ลงท้ายด้วย \".tif\" ให้ใช้ \"**/*.tif\" ถ้าต้องการละเว้นพาธที่เริ่มจากไดเรกทอรีบนสุดให้ใช้ \"/พาธ/ที่ต้องการ/ละเว้น/**\"",
|
||||
"authentication_settings": "ตั้งค่าการเข้าถึง",
|
||||
@@ -129,16 +129,21 @@
|
||||
"map_enable_description": "เปิดใช้งานแผนที่",
|
||||
"map_gps_settings": "การตั้งค่าแผนที่และ GPS",
|
||||
"map_gps_settings_description": "จัดการการตั้งค่าแผนที่และ GPS (Reverse Geocoding)",
|
||||
"map_implications": "ฟีเจอร์แผนที่ต้องการบริการแผ่นแผนที่จากภายนอก (tiles.immich.cloud)",
|
||||
"map_light_style": "แบบสว่าง",
|
||||
"map_manage_reverse_geocoding_settings": "จัดการการตั้งค่า<link>แปลงพิกัดภูมิศาสตร์ </link>",
|
||||
"map_reverse_geocoding": "ประมวลผลชื่อทางภูมิศาสตร์",
|
||||
"map_reverse_geocoding_enable_description": "เปิดใช้งานประมวลผลชื่อทางภูมิศาสตร์",
|
||||
"map_reverse_geocoding_settings": "การตั้งค่าประมวลผลชื่อทางภูมิศาสตร์",
|
||||
"map_settings": "การตั้งค่าแผนที่",
|
||||
"map_settings": "แผนที่",
|
||||
"map_settings_description": "จัดการการตั้งค่าแผนที่",
|
||||
"map_style_description": "URL ไปยังธีมแผนที่ style.json",
|
||||
"metadata_extraction_job": "ดึงข้อมูล metadata",
|
||||
"metadata_extraction_job_description": "ดึงข้อมูล metadata จากสื่อ เช่น GPS และความละเอียด",
|
||||
"metadata_extraction_job_description": "ดึงข้อมูล metadata จากสื่อ เช่น GPS ใบหน้าและความละเอียด",
|
||||
"metadata_faces_import_setting": "เปิดการนำเข้าข้อมูลใบหน้า",
|
||||
"metadata_faces_import_setting_description": "นำเข้าข้อมูลใบหน้าจาก EXIF ของไฟล์ภาพและไฟล์ประกอบ",
|
||||
"metadata_settings": "การตั้งค่า Metadata",
|
||||
"metadata_settings_description": "จัดการการตั้งค่า Metadata",
|
||||
"migration_job": "การโยกย้าย",
|
||||
"migration_job_description": "ย้ายภาพตัวอย่างสื่อและใบหน้าไปยังโครงสร้างโฟลเดอร์ล่าสุด",
|
||||
"no_paths_added": "ไม่ได้เพิ่มพาธ",
|
||||
@@ -147,7 +152,7 @@
|
||||
"note_cannot_be_changed_later": "หมายเหตุ: ไม่สามารถเปลี่ยนภายหลังได้!",
|
||||
"note_unlimited_quota": "หมายเหตุ: ใส่เลข 0 สําหรับโควต้าไม่จํากัด",
|
||||
"notification_email_from_address": "จากที่อยู่",
|
||||
"notification_email_from_address_description": "อีเมลผู้ส่ง อย่างเช่น \"Immich Photo Server <noreply@immich.app>\"",
|
||||
"notification_email_from_address_description": "อีเมลผู้ส่ง อย่างเช่น \"Immich Photo Server <noreply@example.com>\"",
|
||||
"notification_email_host_description": "ที่อยู่เซิร์ฟเวอร์อีเมล (เช่น smtp.immich.app)",
|
||||
"notification_email_ignore_certificate_errors": "ไม่สนใจข้อผิดพลาดเกี่ยวกับใบรับรอง",
|
||||
"notification_email_ignore_certificate_errors_description": "ไม่สนใจการยืนยันใบรับรอง TLS ผิดพลาด (ไม่แนะนำ)",
|
||||
@@ -173,7 +178,9 @@
|
||||
"oauth_issuer_url": "ผู้ออก URL",
|
||||
"oauth_mobile_redirect_uri": "URI เปลี่ยนเส้นทางบนโทรศัพท์",
|
||||
"oauth_mobile_redirect_uri_override": "แทนที่ URI เปลี่ยนเส้นทางบนโทรศัพท์",
|
||||
"oauth_mobile_redirect_uri_override_description": "เปิดเมื่อ 'app.immich:/' เป็น URI เปลี่ยนเส้นทางที่ไม่ถูกต้อง",
|
||||
"oauth_mobile_redirect_uri_override_description": "เปิดเมื่อ OAuth ไม่รองรับ URI บนอุปกรณ์ เช่น '{callback}'",
|
||||
"oauth_profile_signing_algorithm": "อัลกอริทึมการรับรองบัญชีผู้ใช้",
|
||||
"oauth_profile_signing_algorithm_description": "อัลกอริทึมใช้ในการรับรองบัญชีผู้ใช้",
|
||||
"oauth_scope": "ขอบเขต",
|
||||
"oauth_settings": "OAuth",
|
||||
"oauth_settings_description": "จัดการการตั้งค่าล็อกอินผ่าน OAuth",
|
||||
@@ -818,7 +825,7 @@
|
||||
"status": "สถานะ",
|
||||
"stop_motion_photo": "",
|
||||
"stop_photo_sharing": "หยุดแชร์รูปภาพ?",
|
||||
"storage": "ที่จัดเก็บ",
|
||||
"storage": "พื้นที่จัดเก็บ",
|
||||
"storage_label": "",
|
||||
"submit": "ส่ง",
|
||||
"suggestions": "ข้อเสนอแนะ",
|
||||
|
||||
@@ -151,7 +151,7 @@
|
||||
"note_cannot_be_changed_later": "NOT: Bu daha sonra değiştirilemez!",
|
||||
"note_unlimited_quota": "NOT: Sınırsız kota için 0 yazın",
|
||||
"notification_email_from_address": "Şu adresten",
|
||||
"notification_email_from_address_description": "Göndericinin email adresi, örnek: \"Immich Fotoğraf Sunucusu <noreply@immich.app>\"",
|
||||
"notification_email_from_address_description": "Göndericinin email adresi, örnek: \"Immich Fotoğraf Sunucusu <noreply@example.com>\"",
|
||||
"notification_email_host_description": "E-posta sunucusunun ana bilgisayarı (örneğin, smtp.immich.app)",
|
||||
"notification_email_ignore_certificate_errors": "Sertifika hatalarını görmezden gel",
|
||||
"notification_email_ignore_certificate_errors_description": "TLS sertifika doğrulama ayarlarını görmezden gel (Önerilmez)",
|
||||
|
||||
@@ -152,7 +152,7 @@
|
||||
"note_cannot_be_changed_later": "ПРИМІТКА: Це не можна змінити пізніше!",
|
||||
"note_unlimited_quota": "Примітка: Введіть 0 для необмеженого обсягу квоти",
|
||||
"notification_email_from_address": "З адреси",
|
||||
"notification_email_from_address_description": "Адреса електронної пошти відправника, наприклад: \"Immich Photo Server <noreply@immich.app>\"",
|
||||
"notification_email_from_address_description": "Адреса електронної пошти відправника, наприклад: \"Immich Photo Server <noreply@example.com>\"",
|
||||
"notification_email_host_description": "Хост поштового сервера (наприклад, smtp.immich.app)",
|
||||
"notification_email_ignore_certificate_errors": "Ігнорувати помилки сертифіката",
|
||||
"notification_email_ignore_certificate_errors_description": "Ігнорувати помилки перевірки сертифікатів TLS (не рекомендується)",
|
||||
@@ -660,6 +660,7 @@
|
||||
"unable_to_get_comments_number": "Не вдалося отримати кількість коментарів",
|
||||
"unable_to_get_shared_link": "Не вдалося отримати спільне посилання",
|
||||
"unable_to_hide_person": "Неможливо приховати людину",
|
||||
"unable_to_link_motion_video": "Не вдається зв'язати рухоме відео",
|
||||
"unable_to_link_oauth_account": "Не вдається прив'язати обліковий запис OAuth",
|
||||
"unable_to_load_album": "Неможливо завантажити альбом",
|
||||
"unable_to_load_asset_activity": "Неможливо завантажити активність активу",
|
||||
@@ -700,6 +701,7 @@
|
||||
"unable_to_submit_job": "Не вдалося відправити завдання",
|
||||
"unable_to_trash_asset": "Неможливо вилучити актив",
|
||||
"unable_to_unlink_account": "Не вдається відв'язати обліковий запис",
|
||||
"unable_to_unlink_motion_video": "Не вдається від'єднати рухоме відео",
|
||||
"unable_to_update_album_cover": "Неможливо оновити обкладинку альбому",
|
||||
"unable_to_update_album_info": "Неможливо оновити інформацію про альбом",
|
||||
"unable_to_update_library": "Не вдалося оновити бібліотеку",
|
||||
@@ -845,6 +847,7 @@
|
||||
"license_trial_info_4": "Будь ласка, розгляньте можливість придбання ліцензії для підтримки подальшого розвитку сервісу",
|
||||
"light": "Світла",
|
||||
"like_deleted": "Лайк видалено",
|
||||
"link_motion_video": "Посилання на рухоме відео",
|
||||
"link_options": "Налаштування посилання",
|
||||
"link_to_oauth": "Приєднання до OAuth",
|
||||
"linked_oauth_account": "Приєднаний акаунт OAuth",
|
||||
@@ -1288,6 +1291,7 @@
|
||||
"unknown_album": "",
|
||||
"unknown_year": "Невідомий рік",
|
||||
"unlimited": "Без обмежень",
|
||||
"unlink_motion_video": "Від'єднати рухоме відео",
|
||||
"unlink_oauth": "Від'єднайте OAuth",
|
||||
"unlinked_oauth_account": "Відключити акаунт OAuth",
|
||||
"unnamed_album": "Альбом без назви",
|
||||
|
||||
@@ -152,7 +152,7 @@
|
||||
"note_cannot_be_changed_later": "LƯU Ý: Cài đặt này không thể thay đổi được sau khi lưu!",
|
||||
"note_unlimited_quota": "Lưu ý: Nhập 0 để hạn mức không giới hạn",
|
||||
"notification_email_from_address": "Địa chỉ email người gửi",
|
||||
"notification_email_from_address_description": "Địa chỉ email của người gửi, ví dụ: \"Immich Photo Server <noreply@immich.app>\"",
|
||||
"notification_email_from_address_description": "Địa chỉ email của người gửi, ví dụ: \"Immich Photo Server <noreply@example.com>\"",
|
||||
"notification_email_host_description": "Địa chỉ máy chủ email (ví dụ: smtp.immich.app)",
|
||||
"notification_email_ignore_certificate_errors": "Bỏ qua các lỗi chứng chỉ",
|
||||
"notification_email_ignore_certificate_errors_description": "Bỏ qua lỗi xác thực chứng chỉ TLS (không khuyến nghị)",
|
||||
@@ -660,6 +660,7 @@
|
||||
"unable_to_get_comments_number": "Không thể lấy số lượng bình luận",
|
||||
"unable_to_get_shared_link": "Không thể lấy liên kết chia sẻ",
|
||||
"unable_to_hide_person": "Không thể ẩn người",
|
||||
"unable_to_link_motion_video": "Không thể liên kết video chuyển động",
|
||||
"unable_to_link_oauth_account": "Không thể liên kết tài khoản OAuth",
|
||||
"unable_to_load_album": "Không thể tải album",
|
||||
"unable_to_load_asset_activity": "Không thể tải hoạt động của ảnh",
|
||||
@@ -700,6 +701,7 @@
|
||||
"unable_to_submit_job": "Không thể gửi tác vụ",
|
||||
"unable_to_trash_asset": "Không thể chuyển ảnh vào thùng rác",
|
||||
"unable_to_unlink_account": "Không thể hủy liên kết tài khoản",
|
||||
"unable_to_unlink_motion_video": "Không thể hủy liên kết video chuyển động",
|
||||
"unable_to_update_album_cover": "Không thể cập nhật ảnh bìa album",
|
||||
"unable_to_update_album_info": "Không thể cập nhật thông tin album",
|
||||
"unable_to_update_library": "Không thể cập nhật thư viện",
|
||||
@@ -1261,6 +1263,7 @@
|
||||
"unknown_album": "",
|
||||
"unknown_year": "Năm không xác định",
|
||||
"unlimited": "Không giới hạn",
|
||||
"unlink_motion_video": "Hủy liên kết video chuyển động",
|
||||
"unlink_oauth": "Huỷ liên kết OAuth",
|
||||
"unlinked_oauth_account": "Đã huỷ liên kết tài khoản OAuth",
|
||||
"unnamed_album": "Album chưa đặt tên",
|
||||
|
||||
@@ -152,7 +152,7 @@
|
||||
"note_cannot_be_changed_later": "註:之後就無法更改嘍!",
|
||||
"note_unlimited_quota": "註:輸入 0 表示不限制配額",
|
||||
"notification_email_from_address": "寄件地址",
|
||||
"notification_email_from_address_description": "寄件者電子郵件地址(例:Immich Photo Server <noreply@immich.app>)",
|
||||
"notification_email_from_address_description": "寄件者電子郵件地址(例:Immich Photo Server <noreply@example.com>)",
|
||||
"notification_email_host_description": "電子郵件伺服器主機(例:smtp.immich.app)",
|
||||
"notification_email_ignore_certificate_errors": "忽略憑證錯誤",
|
||||
"notification_email_ignore_certificate_errors_description": "忽略 TLS 憑證驗證錯誤(不建議)",
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
"added_to_favorites": "添加到收藏",
|
||||
"added_to_favorites_count": "添加{count, number}项到收藏",
|
||||
"admin": {
|
||||
"add_exclusion_pattern_description": "添加排除规则。支持使用 *、** 和 ? 通配符。比如要忽略名为 “Raw” 的任何目录中的所有文件,请使用 “**/Raw/**”;要忽略所有以 “.tif” 结尾的文件,请使用 “**/*.tif”;要忽略绝对路径,请使用 “/path/to/ignore/**”。",
|
||||
"add_exclusion_pattern_description": "添加排除规则。支持使用 *、** 和 ? 通配符。比如要忽略任何名为 “Raw” 的文件夹中的所有文件,请使用 “**/Raw/**”;要忽略所有以 “.tif” 结尾的文件,请使用 “**/*.tif”;要忽略绝对路径,请使用 “/path/to/ignore/**”。",
|
||||
"authentication_settings": "认证设置",
|
||||
"authentication_settings_description": "管理密码、OAuth 和其它认证设置",
|
||||
"authentication_settings_disable_all": "确定要禁用所有的登录方式?此操作将完全禁止登录。",
|
||||
@@ -119,7 +119,7 @@
|
||||
"machine_learning_settings": "机器学习设置",
|
||||
"machine_learning_settings_description": "管理机器学习功能和设置",
|
||||
"machine_learning_smart_search": "智能搜索",
|
||||
"machine_learning_smart_search_description": "使用CLIP相似度进行图像语义搜索",
|
||||
"machine_learning_smart_search_description": "使用CLIP以文搜图、智能搜图",
|
||||
"machine_learning_smart_search_enabled": "启用智能搜索",
|
||||
"machine_learning_smart_search_enabled_description": "如果禁用,则不会对图像编码以用于智能搜索。",
|
||||
"machine_learning_url_description": "机器学习服务器的URL",
|
||||
@@ -152,8 +152,8 @@
|
||||
"note_cannot_be_changed_later": "注意:此项一旦设定,以后无法更改!",
|
||||
"note_unlimited_quota": "提示:输入0表示无限制",
|
||||
"notification_email_from_address": "发件人地址",
|
||||
"notification_email_from_address_description": "发件人邮箱地址,例如“Immich 服务器 <noreply@immich.app>”",
|
||||
"notification_email_host_description": "邮件服务器主机(例如 smtp.immich.app)",
|
||||
"notification_email_from_address_description": "发件人邮箱地址,例如“张三<12345@qq.com>”",
|
||||
"notification_email_host_description": "服务器地址:(例如:smtp.qq.com)",
|
||||
"notification_email_ignore_certificate_errors": "忽略证书错误",
|
||||
"notification_email_ignore_certificate_errors_description": "忽略TLS证书验证错误(不建议)",
|
||||
"notification_email_password_description": "与邮件服务器进行身份验证时使用的密码",
|
||||
@@ -171,7 +171,7 @@
|
||||
"oauth_auto_launch_description": "在登录页面自动启动OAuth登录",
|
||||
"oauth_auto_register": "自动注册",
|
||||
"oauth_auto_register_description": "使用OAuth登录后自动注册新用户",
|
||||
"oauth_button_text": "按钮文本",
|
||||
"oauth_button_text": "按钮名称",
|
||||
"oauth_client_id": "客户端ID",
|
||||
"oauth_client_secret": "客户端密钥",
|
||||
"oauth_enable_description": "使用OAuth登录",
|
||||
@@ -320,7 +320,7 @@
|
||||
"user_management": "用户管理",
|
||||
"user_password_has_been_reset": "该用户的密码被重置:",
|
||||
"user_password_reset_description": "请向用户提供临时密码,并告知他们下次登录时需要更改密码。",
|
||||
"user_restore_description": "<b>{user}</b>的账户将被恢复。",
|
||||
"user_restore_description": "账户“<b>{user}</b>”将被恢复。",
|
||||
"user_restore_scheduled_removal": "恢复用户 - 计划于{date, date, long}删除",
|
||||
"user_settings": "用户设置",
|
||||
"user_settings_description": "管理用户设置",
|
||||
@@ -465,7 +465,7 @@
|
||||
"confirm_delete_shared_link": "您确定要删除此共享链接吗?",
|
||||
"confirm_password": "确认密码",
|
||||
"contain": "包含",
|
||||
"context": "图像语义搜索",
|
||||
"context": "以文搜图",
|
||||
"continue": "继续",
|
||||
"copied_image_to_clipboard": "已复制图片至剪贴板。",
|
||||
"copied_to_clipboard": "已复制到剪切板!",
|
||||
@@ -496,12 +496,12 @@
|
||||
"custom_locale": "自定义地区",
|
||||
"custom_locale_description": "日期和数字显示格式跟随语言和地区",
|
||||
"dark": "深色",
|
||||
"date_after": "日期之后",
|
||||
"date_after": "开始日期",
|
||||
"date_and_time": "日期与时间",
|
||||
"date_before": "日期之前",
|
||||
"date_before": "结束日期",
|
||||
"date_of_birth_saved": "出生日期保存成功",
|
||||
"date_range": "日期范围",
|
||||
"day": "天",
|
||||
"day": "日",
|
||||
"deduplicate_all": "删除所有重复项",
|
||||
"default_locale": "默认地区",
|
||||
"default_locale_description": "根据您的浏览器地区设置日期和数字显示格式",
|
||||
@@ -681,7 +681,7 @@
|
||||
"unable_to_remove_library": "无法移除图库",
|
||||
"unable_to_remove_offline_files": "无法移除离线文件",
|
||||
"unable_to_remove_partner": "无法移除同伴",
|
||||
"unable_to_remove_reaction": "无法移除反应",
|
||||
"unable_to_remove_reaction": "无法移除回应",
|
||||
"unable_to_remove_user": "无法移除用户",
|
||||
"unable_to_repair_items": "无法修复项目",
|
||||
"unable_to_reset_password": "无法重置密码",
|
||||
@@ -761,7 +761,7 @@
|
||||
"group_no": "未分组",
|
||||
"group_owner": "按所有者分组",
|
||||
"group_year": "按年分组",
|
||||
"has_quota": "有限额",
|
||||
"has_quota": "配额大小",
|
||||
"hi_user": "你好,{name}({email})",
|
||||
"hide_all_people": "隐藏所有人物",
|
||||
"hide_gallery": "隐藏相册",
|
||||
@@ -769,7 +769,7 @@
|
||||
"hide_password": "隐藏密码",
|
||||
"hide_person": "隐藏人物",
|
||||
"hide_unnamed_people": "隐藏未命名的人物",
|
||||
"host": "主机",
|
||||
"host": "服务器",
|
||||
"hour": "时",
|
||||
"image": "图片",
|
||||
"image_alt_text_date": "在{date}拍摄的{isVideo, select, true {视频} other {照片}}",
|
||||
@@ -793,7 +793,7 @@
|
||||
"in_albums": "在{count, plural, one {#个相册} other {#个相册}}中",
|
||||
"in_archive": "在归档中",
|
||||
"include_archived": "包括已归档",
|
||||
"include_shared_albums": "包含共享相册",
|
||||
"include_shared_albums": "包括共享相册",
|
||||
"include_shared_partner_assets": "包括同伴共享项目",
|
||||
"individual_share": "个人分享",
|
||||
"info": "信息",
|
||||
@@ -930,7 +930,7 @@
|
||||
"no_shared_albums_message": "创建相册以共享照片和视频",
|
||||
"not_in_any_album": "不在任何相册中",
|
||||
"note_apply_storage_label_to_previously_uploaded assets": "提示:要将存储标签应用于之前上传的项目,运行以下命令",
|
||||
"note_unlimited_quota": "注:输入 0 表示无限制配额",
|
||||
"note_unlimited_quota": "注:输入 0 表示无限配额",
|
||||
"notes": "提示",
|
||||
"notification_toggle_setting_description": "启用邮件通知",
|
||||
"notifications": "通知",
|
||||
@@ -1060,7 +1060,7 @@
|
||||
"rating_count": "{count, plural, one {#星} other {#星}}",
|
||||
"rating_description": "在信息面板中展示EXIF星级",
|
||||
"raw": "Raw",
|
||||
"reaction_options": "反应选项",
|
||||
"reaction_options": "回应选项",
|
||||
"read_changelog": "阅读更新日志",
|
||||
"reassign": "重新指派",
|
||||
"reassigned_assets_to_existing_person": "重新指派{count, plural, one {#个项目} other {#个项目}}到{name, select, null {已存在的人物} other {{name}}}",
|
||||
@@ -1081,7 +1081,7 @@
|
||||
"remove_assets_album_confirmation": "确定要从项目中移除{count, plural, one {#个项目} other {#个项目}}?",
|
||||
"remove_assets_shared_link_confirmation": "确定要从共享链接中移除{count, plural, one {#个项目} other {#个项目}}?",
|
||||
"remove_assets_title": "移除项目?",
|
||||
"remove_custom_date_range": "根据自定义日期范围移除",
|
||||
"remove_custom_date_range": "取消自定义日期范围",
|
||||
"remove_from_album": "从相册中移除",
|
||||
"remove_from_favorites": "移出收藏",
|
||||
"remove_from_shared_link": "从共享链接中移除",
|
||||
@@ -1181,16 +1181,16 @@
|
||||
"share": "共享",
|
||||
"shared": "共享",
|
||||
"shared_by": "共享自",
|
||||
"shared_by_user": "由{user}共享",
|
||||
"shared_by_user": "由“{user}”共享",
|
||||
"shared_by_you": "你的共享",
|
||||
"shared_from_partner": "来自{partner}的照片",
|
||||
"shared_from_partner": "来自“{partner}”的照片",
|
||||
"shared_link_options": "共享链接选项",
|
||||
"shared_links": "共享链接",
|
||||
"shared_photos_and_videos_count": "{assetCount, plural, other {#项已共享照片&视频。}}",
|
||||
"shared_with_partner": "与{partner}共享",
|
||||
"shared_with_partner": "与“{partner}”共享",
|
||||
"sharing": "共享",
|
||||
"sharing_enter_password": "请输入密码后查看此页面。",
|
||||
"sharing_sidebar_description": "在侧边栏中显示共享链接",
|
||||
"sharing_sidebar_description": "在侧边栏中显示“共享”链接",
|
||||
"shift_to_permanent_delete": "按住Shift键永久删除项目",
|
||||
"show_album_options": "显示相册选项",
|
||||
"show_albums": "显示相册",
|
||||
@@ -1216,9 +1216,9 @@
|
||||
"sign_out": "注销",
|
||||
"sign_up": "注册",
|
||||
"size": "大小",
|
||||
"skip_to_content": "跳到内容",
|
||||
"skip_to_folders": "跳到文件夹",
|
||||
"skip_to_tags": "跳到标签",
|
||||
"skip_to_content": "跳转到内容",
|
||||
"skip_to_folders": "跳转到文件夹",
|
||||
"skip_to_tags": "跳转到标签",
|
||||
"slideshow": "幻灯片放映",
|
||||
"slideshow_settings": "放映设置",
|
||||
"sort_albums_by": "相册排序依据...",
|
||||
@@ -1241,15 +1241,15 @@
|
||||
"status": "状态",
|
||||
"stop_motion_photo": "定格照片",
|
||||
"stop_photo_sharing": "停止共享照片?",
|
||||
"stop_photo_sharing_description": "{partner}将不能访问你的照片。",
|
||||
"stop_photo_sharing_description": "“{partner}”将不能访问你的照片。",
|
||||
"stop_sharing_photos_with_user": "停止与此用户共享照片",
|
||||
"storage": "存储空间",
|
||||
"storage_label": "存储标签",
|
||||
"storage_usage": "总量:{available},已用{used}",
|
||||
"storage_usage": "总量:{available}/已用:{used}",
|
||||
"submit": "提交",
|
||||
"suggestions": "建议",
|
||||
"sunrise_on_the_beach": "海滩上的日出",
|
||||
"swap_merge_direction": "交换合并方向",
|
||||
"swap_merge_direction": "互换合并方向",
|
||||
"sync": "同步",
|
||||
"tag": "标签",
|
||||
"tag_assets": "标记项目",
|
||||
@@ -1262,7 +1262,7 @@
|
||||
"template": "模版",
|
||||
"theme": "主题",
|
||||
"theme_selection": "主题选项",
|
||||
"theme_selection_description": "根据浏览器的系统首选项自动设置主题色",
|
||||
"theme_selection_description": "跟随浏览器自动设置主题颜色",
|
||||
"they_will_be_merged_together": "项目将会合并到一起",
|
||||
"time_based_memories": "基于时间的回忆",
|
||||
"timezone": "时区",
|
||||
@@ -1319,15 +1319,15 @@
|
||||
"upload_success": "上传成功,刷新页面查看新上传的项目。",
|
||||
"url": "URL",
|
||||
"usage": "用量",
|
||||
"use_custom_date_range": "使用自定义日期范围",
|
||||
"use_custom_date_range": "自定义日期范围",
|
||||
"user": "用户",
|
||||
"user_id": "用户ID",
|
||||
"user_license_settings": "授权",
|
||||
"user_license_settings_description": "管理你的授权",
|
||||
"user_liked": "{user}点赞了{type, select, photo {该照片} video {该视频} asset {该项目} other {它}}",
|
||||
"user_liked": "“{user}”点赞了{type, select, photo {该照片} video {该视频} asset {该项目} other {它}}",
|
||||
"user_purchase_settings": "购买",
|
||||
"user_purchase_settings_description": "管理购买订单",
|
||||
"user_role_set": "设置{user}为{role}",
|
||||
"user_role_set": "设置“{user}”为“{role}”",
|
||||
"user_usage_detail": "用户用量详情",
|
||||
"username": "用户名",
|
||||
"users": "用户",
|
||||
@@ -1336,7 +1336,7 @@
|
||||
"variables": "变量",
|
||||
"version": "版本",
|
||||
"version_announcement_closing": "你的朋友,Alex",
|
||||
"version_announcement_message": "嗨,伙计,当前应用出新版本了,请抽空阅读一下<link>发行说明</link>,并及时更新你的<code>docker-compose.yml</code>和<code>.env</code>文件,避免存在错误配置,特别是当你是使用WatchTower或其它类似的自动升级工具时。",
|
||||
"version_announcement_message": "嗨,朋友,当前应用出新版本了,请抽空阅读一下<link>发行说明</link>,并及时更新你的<code>docker-compose.yml</code>和<code>.env</code>文件,避免存在配置错误,特别是当你是使用WatchTower或其它类似的自动升级工具时。",
|
||||
"video": "视频",
|
||||
"video_hover_setting": "鼠标悬停时播放视频缩略图",
|
||||
"video_hover_setting_description": "当鼠标悬停在项目上时播放视频缩略图。即使禁用了这个功能,也可以通过将鼠标悬停在播放图标上来开始播放。",
|
||||
@@ -1353,7 +1353,7 @@
|
||||
"view_stack": "查看堆叠项目",
|
||||
"viewer": "预览",
|
||||
"visibility_changed": "{count, plural, one {#个人物} other {#个人物}}的可见性已修改",
|
||||
"waiting": "队列中",
|
||||
"waiting": "准备处理",
|
||||
"warning": "警告",
|
||||
"week": "周",
|
||||
"welcome": "欢迎",
|
||||
|
||||
@@ -3,10 +3,17 @@
|
||||
import LinkButton from '$lib/components/elements/buttons/link-button.svelte';
|
||||
import Icon from '$lib/components/elements/icon.svelte';
|
||||
import UserPageLayout from '$lib/components/layouts/user-page-layout.svelte';
|
||||
import Combobox, { type ComboBoxOption } from '$lib/components/shared-components/combobox.svelte';
|
||||
import ConfirmDialog from '$lib/components/shared-components/dialog/confirm-dialog.svelte';
|
||||
import {
|
||||
notificationController,
|
||||
NotificationType,
|
||||
} from '$lib/components/shared-components/notification/notification';
|
||||
import { AppRoute } from '$lib/constants';
|
||||
import { asyncTimeout } from '$lib/utils';
|
||||
import { getAllJobsStatus, type AllJobStatusResponseDto } from '@immich/sdk';
|
||||
import { mdiCog } from '@mdi/js';
|
||||
import { handleError } from '$lib/utils/handle-error';
|
||||
import { createJob, getAllJobsStatus, ManualJobName, type AllJobStatusResponseDto } from '@immich/sdk';
|
||||
import { mdiCog, mdiPlus } from '@mdi/js';
|
||||
import { onDestroy, onMount } from 'svelte';
|
||||
import { t } from 'svelte-i18n';
|
||||
import type { PageData } from './$types';
|
||||
@@ -16,6 +23,8 @@
|
||||
let jobs: AllJobStatusResponseDto;
|
||||
|
||||
let running = true;
|
||||
let isOpen = false;
|
||||
let selectedJob: ComboBoxOption | undefined = undefined;
|
||||
|
||||
onMount(async () => {
|
||||
while (running) {
|
||||
@@ -27,10 +36,38 @@
|
||||
onDestroy(() => {
|
||||
running = false;
|
||||
});
|
||||
|
||||
const options = [
|
||||
{ title: $t('admin.person_cleanup_job'), value: ManualJobName.PersonCleanup },
|
||||
{ title: $t('admin.tag_cleanup_job'), value: ManualJobName.TagCleanup },
|
||||
{ title: $t('admin.user_cleanup_job'), value: ManualJobName.UserCleanup },
|
||||
].map(({ value, title }) => ({ id: value, label: title, value }));
|
||||
|
||||
const handleCancel = () => (isOpen = false);
|
||||
|
||||
const handleCreate = async () => {
|
||||
if (!selectedJob) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await createJob({ jobCreateDto: { name: selectedJob.value as ManualJobName } });
|
||||
notificationController.show({ message: $t('admin.job_created'), type: NotificationType.Info });
|
||||
handleCancel();
|
||||
} catch (error) {
|
||||
handleError(error, $t('errors.unable_to_submit_job'));
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<UserPageLayout title={data.meta.title} admin>
|
||||
<div class="flex justify-end" slot="buttons">
|
||||
<LinkButton on:click={() => (isOpen = true)}>
|
||||
<div class="flex place-items-center gap-2 text-sm">
|
||||
<Icon path={mdiPlus} size="18" />
|
||||
{$t('admin.create_job')}
|
||||
</div>
|
||||
</LinkButton>
|
||||
<LinkButton href="{AppRoute.ADMIN_SETTINGS}?isOpen=job">
|
||||
<div class="flex place-items-center gap-2 text-sm">
|
||||
<Icon path={mdiCog} size="18" />
|
||||
@@ -46,3 +83,24 @@
|
||||
</section>
|
||||
</section>
|
||||
</UserPageLayout>
|
||||
|
||||
{#if isOpen}
|
||||
<ConfirmDialog
|
||||
confirmColor="primary"
|
||||
title={$t('admin.create_job')}
|
||||
disabled={!selectedJob}
|
||||
onConfirm={handleCreate}
|
||||
onCancel={handleCancel}
|
||||
>
|
||||
<form on:submit|preventDefault={handleCreate} autocomplete="off" id="create-tag-form" slot="prompt" class="w-full">
|
||||
<div class="flex flex-col gap-1 text-left">
|
||||
<Combobox
|
||||
bind:selectedOption={selectedJob}
|
||||
label={$t('jobs')}
|
||||
{options}
|
||||
placeholder={$t('admin.search_jobs')}
|
||||
/>
|
||||
</div>
|
||||
</form>
|
||||
</ConfirmDialog>
|
||||
{/if}
|
||||
|
||||
@@ -27,11 +27,33 @@
|
||||
import { copyToClipboard } from '$lib/utils';
|
||||
import { downloadBlob } from '$lib/utils/asset-utils';
|
||||
import type { SystemConfigDto } from '@immich/sdk';
|
||||
import { mdiAlert, mdiContentCopy, mdiDownload, mdiUpload } from '@mdi/js';
|
||||
import {
|
||||
mdiAccountOutline,
|
||||
mdiAlert,
|
||||
mdiBellOutline,
|
||||
mdiBookshelf,
|
||||
mdiContentCopy,
|
||||
mdiDatabaseOutline,
|
||||
mdiDownload,
|
||||
mdiFileDocumentOutline,
|
||||
mdiFolderOutline,
|
||||
mdiImageOutline,
|
||||
mdiLockOutline,
|
||||
mdiMapMarkerOutline,
|
||||
mdiPaletteOutline,
|
||||
mdiRobotOutline,
|
||||
mdiServerOutline,
|
||||
mdiSync,
|
||||
mdiTrashCanOutline,
|
||||
mdiUpdate,
|
||||
mdiUpload,
|
||||
mdiVideoOutline,
|
||||
} from '@mdi/js';
|
||||
import type { PageData } from './$types';
|
||||
import { t } from 'svelte-i18n';
|
||||
import type { ComponentType, SvelteComponent } from 'svelte';
|
||||
import type { SettingsComponentProps } from '$lib/components/admin-page/settings/admin-settings';
|
||||
import SearchBar from '$lib/components/elements/search-bar.svelte';
|
||||
|
||||
export let data: PageData;
|
||||
|
||||
@@ -68,104 +90,128 @@
|
||||
title: string;
|
||||
subtitle: string;
|
||||
key: string;
|
||||
icon: string;
|
||||
}> = [
|
||||
{
|
||||
component: AuthSettings,
|
||||
title: $t('admin.authentication_settings'),
|
||||
subtitle: $t('admin.authentication_settings_description'),
|
||||
key: 'image',
|
||||
key: 'authentication',
|
||||
icon: mdiLockOutline,
|
||||
},
|
||||
{
|
||||
component: ImageSettings,
|
||||
title: $t('admin.image_settings'),
|
||||
subtitle: $t('admin.image_settings_description'),
|
||||
key: 'image',
|
||||
icon: mdiImageOutline,
|
||||
},
|
||||
{
|
||||
component: JobSettings,
|
||||
title: $t('admin.job_settings'),
|
||||
subtitle: $t('admin.job_settings_description'),
|
||||
key: 'job',
|
||||
icon: mdiSync,
|
||||
},
|
||||
{
|
||||
component: MetadataSettings,
|
||||
title: $t('admin.metadata_settings'),
|
||||
subtitle: $t('admin.metadata_settings_description'),
|
||||
key: 'metadata',
|
||||
icon: mdiDatabaseOutline,
|
||||
},
|
||||
{
|
||||
component: LibrarySettings,
|
||||
title: $t('admin.library_settings'),
|
||||
subtitle: $t('admin.library_settings_description'),
|
||||
key: 'external-library',
|
||||
icon: mdiBookshelf,
|
||||
},
|
||||
{
|
||||
component: LoggingSettings,
|
||||
title: $t('admin.logging_settings'),
|
||||
subtitle: $t('admin.manage_log_settings'),
|
||||
key: 'logging',
|
||||
icon: mdiFileDocumentOutline,
|
||||
},
|
||||
{
|
||||
component: MachineLearningSettings,
|
||||
title: $t('admin.machine_learning_settings'),
|
||||
subtitle: $t('admin.machine_learning_settings_description'),
|
||||
key: 'machine-learning',
|
||||
icon: mdiRobotOutline,
|
||||
},
|
||||
{
|
||||
component: MapSettings,
|
||||
title: $t('admin.map_gps_settings'),
|
||||
subtitle: $t('admin.map_gps_settings_description'),
|
||||
key: 'location',
|
||||
icon: mdiMapMarkerOutline,
|
||||
},
|
||||
{
|
||||
component: NotificationSettings,
|
||||
title: $t('admin.notification_settings'),
|
||||
subtitle: $t('admin.notification_settings_description'),
|
||||
key: 'notifications',
|
||||
icon: mdiBellOutline,
|
||||
},
|
||||
{
|
||||
component: ServerSettings,
|
||||
title: $t('admin.server_settings'),
|
||||
subtitle: $t('admin.server_settings_description'),
|
||||
key: 'server',
|
||||
icon: mdiServerOutline,
|
||||
},
|
||||
{
|
||||
component: StorageTemplateSettings,
|
||||
title: $t('admin.storage_template_settings'),
|
||||
subtitle: $t('admin.storage_template_settings_description'),
|
||||
key: 'storage-template',
|
||||
icon: mdiFolderOutline,
|
||||
},
|
||||
{
|
||||
component: ThemeSettings,
|
||||
title: $t('admin.theme_settings'),
|
||||
subtitle: $t('admin.theme_settings_description'),
|
||||
key: 'theme',
|
||||
icon: mdiPaletteOutline,
|
||||
},
|
||||
{
|
||||
component: TrashSettings,
|
||||
title: $t('admin.trash_settings'),
|
||||
subtitle: $t('admin.trash_settings_description'),
|
||||
key: 'trash',
|
||||
icon: mdiTrashCanOutline,
|
||||
},
|
||||
{
|
||||
component: UserSettings,
|
||||
title: $t('admin.user_settings'),
|
||||
subtitle: $t('admin.user_settings_description'),
|
||||
key: 'user-settings',
|
||||
icon: mdiAccountOutline,
|
||||
},
|
||||
{
|
||||
component: NewVersionCheckSettings,
|
||||
title: $t('admin.version_check_settings'),
|
||||
subtitle: $t('admin.version_check_settings_description'),
|
||||
key: 'version-check',
|
||||
icon: mdiUpdate,
|
||||
},
|
||||
{
|
||||
component: FFmpegSettings,
|
||||
title: $t('admin.transcoding_settings'),
|
||||
subtitle: $t('admin.transcoding_settings_description'),
|
||||
key: 'video-transcoding',
|
||||
icon: mdiVideoOutline,
|
||||
},
|
||||
];
|
||||
|
||||
let searchQuery = '';
|
||||
|
||||
$: filteredSettings = settings.filter(({ title, subtitle }) => {
|
||||
const query = searchQuery.toLowerCase();
|
||||
return title.toLowerCase().includes(query) || subtitle.toLowerCase().includes(query);
|
||||
});
|
||||
</script>
|
||||
|
||||
<input bind:this={inputElement} type="file" accept=".json" style="display: none" on:change={uploadConfig} />
|
||||
@@ -182,6 +228,9 @@
|
||||
|
||||
<UserPageLayout title={data.meta.title} admin>
|
||||
<div class="flex justify-end gap-2" slot="buttons">
|
||||
<div class="hidden lg:block">
|
||||
<SearchBar placeholder={$t('search_settings')} bind:name={searchQuery} showLoadingSpinner={false} />
|
||||
</div>
|
||||
<LinkButton on:click={() => copyToClipboard(JSON.stringify(config, null, 2))}>
|
||||
<div class="flex place-items-center gap-2 text-sm">
|
||||
<Icon path={mdiContentCopy} size="18" />
|
||||
@@ -206,10 +255,13 @@
|
||||
|
||||
<AdminSettings bind:config let:handleReset bind:handleSave let:savedConfig let:defaultConfig>
|
||||
<section id="setting-content" class="flex place-content-center sm:mx-4">
|
||||
<section class="w-full pb-28 sm:w-5/6 md:w-[850px]">
|
||||
<section class="w-full pb-28 sm:w-5/6 md:w-[896px]">
|
||||
<div class="block lg:hidden">
|
||||
<SearchBar placeholder={$t('search_settings')} bind:name={searchQuery} showLoadingSpinner={false} />
|
||||
</div>
|
||||
<SettingAccordionState queryParam={QueryParameter.IS_OPEN}>
|
||||
{#each settings as { component: Component, title, subtitle, key }}
|
||||
<SettingAccordion {title} {subtitle} {key}>
|
||||
{#each filteredSettings as { component: Component, title, subtitle, key, icon } (key)}
|
||||
<SettingAccordion {title} {subtitle} {key} {icon}>
|
||||
<Component
|
||||
onSave={(config) => handleSave(config)}
|
||||
onReset={(options) => handleReset(options)}
|
||||
|
||||
Reference in New Issue
Block a user