mirror of
https://github.com/immich-app/immich.git
synced 2025-12-10 01:10:21 +03:00
Compare commits
20 Commits
v1.38.0_60
...
v1.39.0_61
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
42e57547f7 | ||
|
|
b88e24678b | ||
|
|
de69d0031e | ||
|
|
8998a79ff9 | ||
|
|
e116f17c43 | ||
|
|
efa1781eb6 | ||
|
|
03e86ed147 | ||
|
|
c754c860fd | ||
|
|
391d00bcb9 | ||
|
|
d7297b567d | ||
|
|
e9cebedb4a | ||
|
|
2edbf64e69 | ||
|
|
1efcac0946 | ||
|
|
415550f16d | ||
|
|
aa554a9e77 | ||
|
|
2876c7ff97 | ||
|
|
651f56370a | ||
|
|
950adeebbf | ||
|
|
4e33a52290 | ||
|
|
f2cc7c2873 |
@@ -78,6 +78,7 @@ Spec: Free-tier Oracle VM - Amsterdam - 2.4Ghz quad-core ARM64 CPU, 24GB RAM
|
||||
| Virtual scroll | Yes | Yes |
|
||||
| OAuth Support | Yes | Yes |
|
||||
| LivePhotos Backup and Playback (iOS only) | Yes | Yes |
|
||||
| User-defined storage structure | Yes | Yes |
|
||||
|
||||
# Support the project
|
||||
|
||||
|
||||
BIN
docs/docs/usage/img/storage-template.png
Normal file
BIN
docs/docs/usage/img/storage-template.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 335 KiB |
@@ -14,7 +14,21 @@ The mobile app can be downloaded from
|
||||
- [Apple App Store](https://apps.apple.com/us/app/immich/id1613945652)
|
||||
- [F-Droid](https://f-droid.org/packages/app.alextran.immich)
|
||||
|
||||
## Step 2 - Register the admin user
|
||||
## Step 2 - Set storage template
|
||||
|
||||
Immich allows the admin user to set the pattern of how the files are uploaded to the Immich would look like. Both in the directory and the filename level.
|
||||
|
||||
The admin user can set the template by using the template builder in the `Administration -> Settings -> Storage Template`. Immich provides a set of variables that you can use in construting the template, along with additional custom text.
|
||||
|
||||
```bash title="Default template"
|
||||
Year/Year-Month-Day/Filename.Extension
|
||||
```
|
||||
|
||||
<img src={require('./img/storage-template.png').default} width="100%" title="Storage Template Setting" />
|
||||
|
||||
Immich also provides a mechanism to migrate between template so that if the template you set now doesn't work in the future, you can always migrate all the existing files to the new template. The mechanism is run as a job in the Job page.
|
||||
|
||||
## Step 3 - Register the admin user
|
||||
|
||||
The first user to register will be the admin user. The admin user will be able to add other users to the application.
|
||||
|
||||
@@ -24,19 +38,19 @@ To register for the admin user, access the web application at `http://<machine-i
|
||||
|
||||
Follow the prompts to register as the admin user and log in to the application.
|
||||
|
||||
## Step 3 - Create a new user (optional)
|
||||
## Step 4 - Create a new user (optional)
|
||||
|
||||
If you have a family member who wants to use the application, you can create a new account. The default password is `password`, and the user can change their password after logging in to the application for the first time.
|
||||
|
||||
<img src={require('./img/create-new-user.png').default} title="Admin Registration" />
|
||||
|
||||
## Step 4 - Access the mobile app
|
||||
## Step 5 - Access the mobile app
|
||||
|
||||
Login to the mobile app with the server endpoint URL at `http://<machine-ip-address>:2283/api`
|
||||
|
||||
<img src={require('./img/sign-in-phone.jpeg').default} width="50%" title="Mobile App Sign In" />
|
||||
|
||||
## Step 5 - Back up your photos and videos
|
||||
## Step 6 - Back up your photos and videos
|
||||
|
||||
Navigate to the backup screen by clicking on the cloud icon in the top right corner of the screen.
|
||||
|
||||
|
||||
@@ -1,26 +1,19 @@
|
||||
config_version: 1.0
|
||||
project_id: ead34689-ec52-41d9-b675-09bc85a6cbd7
|
||||
file_type: json
|
||||
branch: main
|
||||
upload:
|
||||
files:
|
||||
- file: mobile/assets/i18n/en-US.json
|
||||
locale_code: en-US
|
||||
- file: mobile/assets/i18n/de-DE.json
|
||||
locale_code: de-DE
|
||||
- file: mobile/assets/i18n/fr-FR.json
|
||||
locale_code: fr-FR
|
||||
- file: mobile/assets/i18n/it-IT.json
|
||||
locale_code: it-IT
|
||||
- file: mobile/assets/i18n/nl-NL.json
|
||||
locale_code: nl-NL
|
||||
- file: mobile/assets/i18n/ko-KR.json
|
||||
locale_code: ko-KR
|
||||
- file: mobile/assets/i18n/da-DK.json
|
||||
locale_code: da-DK
|
||||
download:
|
||||
params:
|
||||
export_empty_as: main
|
||||
files:
|
||||
- file: mobile/assets/i18n/en-US.json
|
||||
locale_code: en-US
|
||||
- file: mobile/assets/i18n/da-DK.json
|
||||
locale_code: da-DK
|
||||
- file: mobile/assets/i18n/de-DE.json
|
||||
locale_code: de-DE
|
||||
- file: mobile/assets/i18n/fr-FR.json
|
||||
@@ -31,5 +24,13 @@ download:
|
||||
locale_code: nl-NL
|
||||
- file: mobile/assets/i18n/ko-KR.json
|
||||
locale_code: ko-KR
|
||||
- file: mobile/assets/i18n/da-DK.json
|
||||
locale_code: da-DK
|
||||
- file: mobile/assets/i18n/es-ES.json
|
||||
locale_code: es-ES
|
||||
- file: mobile/assets/i18n/fi-FI.json
|
||||
locale_code: fi-FI
|
||||
- file: mobile/assets/i18n/ja-JP.json
|
||||
locale_code: ja-JP
|
||||
- file: mobile/assets/i18n/pt-BR.json
|
||||
locale_code: pt-BR
|
||||
- file: mobile/assets/i18n/pl-PL.json
|
||||
locale_code: pl-PL
|
||||
|
||||
@@ -35,8 +35,8 @@ platform :android do
|
||||
task: 'bundle',
|
||||
build_type: 'Release',
|
||||
properties: {
|
||||
"android.injected.version.code" => 60,
|
||||
"android.injected.version.name" => "1.38.0",
|
||||
"android.injected.version.code" => 62,
|
||||
"android.injected.version.name" => "1.39.0",
|
||||
}
|
||||
)
|
||||
upload_to_play_store(skip_upload_apk: true, skip_upload_images: true, skip_upload_screenshots: true, aab: '../build/app/outputs/bundle/release/app-release.aab')
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
* Hot fix: timeline crash when trying to group invalid date info.
|
||||
@@ -0,0 +1 @@
|
||||
* Add additional supported translation for CZ, SK, and CN
|
||||
@@ -5,17 +5,17 @@
|
||||
|
||||
|
||||
|
||||
<testcase classname="fastlane.lanes" name="0: default_platform" time="0.000201">
|
||||
<testcase classname="fastlane.lanes" name="0: default_platform" time="0.000213">
|
||||
|
||||
</testcase>
|
||||
|
||||
|
||||
<testcase classname="fastlane.lanes" name="1: bundleRelease" time="63.132489">
|
||||
<testcase classname="fastlane.lanes" name="1: bundleRelease" time="61.218233">
|
||||
|
||||
</testcase>
|
||||
|
||||
|
||||
<testcase classname="fastlane.lanes" name="2: upload_to_play_store" time="38.15883">
|
||||
<testcase classname="fastlane.lanes" name="2: upload_to_play_store" time="41.974053">
|
||||
|
||||
</testcase>
|
||||
|
||||
|
||||
194
mobile/assets/i18n/cs-CZ.json
Normal file
194
mobile/assets/i18n/cs-CZ.json
Normal file
@@ -0,0 +1,194 @@
|
||||
{
|
||||
"album_info_card_backup_album_excluded": "VYLOUČENO",
|
||||
"album_info_card_backup_album_included": "ZAHRNUTO",
|
||||
"album_thumbnail_card_item": "1 položka",
|
||||
"album_thumbnail_card_items": "{} položky",
|
||||
"album_thumbnail_card_shared": "Sdíleno",
|
||||
"album_viewer_appbar_share_delete": "odstranit album",
|
||||
"album_viewer_appbar_share_err_delete": "Nepodařilo se odstranit album",
|
||||
"album_viewer_appbar_share_err_leave": "Nepodařilo se ukončit album",
|
||||
"album_viewer_appbar_share_err_remove": "Při odstraňování souborů z alba se vyskytly problémy.",
|
||||
"album_viewer_appbar_share_err_title": "Nepodařilo se změnit název alba",
|
||||
"album_viewer_appbar_share_leave": "Opustit album",
|
||||
"album_viewer_appbar_share_remove": "Odstranit z alba",
|
||||
"album_viewer_page_share_add_users": "Přidat uživatele",
|
||||
"asset_list_settings_subtitle": "Nastavení rozložení mřížky fotografií",
|
||||
"asset_list_settings_title": "Fotografická mřížka",
|
||||
"backup_album_selection_page_albums_device": "Alba v zařízení ({})",
|
||||
"backup_album_selection_page_albums_tap": "Klepnutím na položku ji zahrnete, dvojím klepnutím ji vyloučíte",
|
||||
"backup_album_selection_page_assets_scatter": "Soubory mohou být roztroušeny ve více albech. To umožňuje zahrnout nebo vyloučit alba během procesu zálohování.",
|
||||
"backup_album_selection_page_select_albums": "Vybraná alba",
|
||||
"backup_album_selection_page_selection_info": "Informace o výběru",
|
||||
"backup_album_selection_page_total_assets": "Celkový počet jedinečných souborů",
|
||||
"backup_all": "Vše",
|
||||
"backup_background_service_backup_failed_message": "Zálohování zdrojů selhalo. Zkouším to znovu...",
|
||||
"backup_background_service_connection_failed_message": "Nepodařilo se připojit k serveru. Zkouším to znovu...",
|
||||
"backup_background_service_current_upload_notification": "Nahrávání {}",
|
||||
"backup_background_service_default_notification": "Kontrola nových zdrojů {}",
|
||||
"backup_background_service_error_title": "Chyba zálohování",
|
||||
"backup_background_service_in_progress_notification": "Vytvářím kopii vašich zdrojů...",
|
||||
"backup_background_service_upload_failure_notification": "Nepodařilo se nahrát {}",
|
||||
"backup_controller_page_albums": "Zálohovaná alba",
|
||||
"backup_controller_page_background_battery_info_link": "Ukaž mi jak",
|
||||
"backup_controller_page_background_battery_info_message": "Chcete-li dosáhnout nejlepších výsledků při zálohování na pozadí, vypněte všechny optimalizace baterie, které omezují aktivitu na pozadí pro Immich ve vašem zařízení. Jelikož to závisí na zařízení, zkontrolujte požadované informace pro výrobce vašeho zařízení.",
|
||||
"backup_controller_page_background_battery_info_ok": "OK",
|
||||
"backup_controller_page_background_battery_info_title": "Optimalizace baterie",
|
||||
"backup_controller_page_background_charging": "Pouze během nabíjení",
|
||||
"backup_controller_page_background_configure_error": "Nepodařilo se nakonfigurovat službu na pozadí",
|
||||
"backup_controller_page_background_delay": "Zpoždění zálohování nových zdrojů: {}",
|
||||
"backup_controller_page_background_description": "Povolte službu na pozadí pro automatické zálohování všech nových aktiv bez nutnosti otevření aplikace",
|
||||
"backup_controller_page_background_is_off": "Automatické zálohování na pozadí je vypnuto",
|
||||
"backup_controller_page_background_is_on": "Automatické zálohování na pozadí je zapnuto",
|
||||
"backup_controller_page_background_turn_off": "Zakázat službu na pozadí",
|
||||
"backup_controller_page_background_turn_on": "Povolit službu na pozadí",
|
||||
"backup_controller_page_background_wifi": "Jen na WiFi",
|
||||
"backup_controller_page_backup": "Zálohování",
|
||||
"backup_controller_page_backup_selected": "Vybrané: ",
|
||||
"backup_controller_page_backup_sub": "Zálohování fotografií a videí",
|
||||
"backup_controller_page_cancel": "Zrušit",
|
||||
"backup_controller_page_created": "Vytvořeno: {}",
|
||||
"backup_controller_page_desc_backup": "Zapněte zálohování na popředí, aby se nové položky automaticky nahrávaly na server při otevření aplikace.",
|
||||
"backup_controller_page_excluded": "Vyloučeno: ",
|
||||
"backup_controller_page_failed": "Nepodařilo se ({})",
|
||||
"backup_controller_page_filename": "Název souboru: {} [{}]",
|
||||
"backup_controller_page_id": "ID: {}",
|
||||
"backup_controller_page_info": "Informace o zálohování",
|
||||
"backup_controller_page_none_selected": "Žádné vybrané",
|
||||
"backup_controller_page_remainder": "Zbytek",
|
||||
"backup_controller_page_remainder_sub": "Zbývající fotografie a alba, která se mají zálohovat z výběru",
|
||||
"backup_controller_page_select": "Vybrat",
|
||||
"backup_controller_page_server_storage": "Serverové úložiště",
|
||||
"backup_controller_page_start_backup": "Spustit zálohování",
|
||||
"backup_controller_page_status_off": "Automatické zálohování na popředí je vypnuto",
|
||||
"backup_controller_page_status_on": "Automatické zálohování na popředí je zapnuto",
|
||||
"backup_controller_page_storage_format": "{} z {} použitých",
|
||||
"backup_controller_page_to_backup": "Alba, která mají být zálohována",
|
||||
"backup_controller_page_total": "Celkem",
|
||||
"backup_controller_page_total_sub": "Všechny jedinečné fotografie a videa z vybraných alb",
|
||||
"backup_controller_page_turn_off": "Zakázat zálohování na popředí",
|
||||
"backup_controller_page_turn_on": "Povolit zálohování na popředí",
|
||||
"backup_controller_page_uploading_file_info": "Nahrávání informací o souborech",
|
||||
"backup_err_only_album": "Nelze odstranit pouze album",
|
||||
"backup_info_card_assets": "položky",
|
||||
"cache_settings_album_thumbnails": "Náhledy stránek knihovny (položek {})",
|
||||
"cache_settings_clear_cache_button": "Vymazat vyrovnávací paměť",
|
||||
"cache_settings_clear_cache_button_title": "Vymaže vyrovnávací paměť aplikace. To výrazně ovlivní výkon aplikace, dokud se vyrovnávací paměť neobnoví.",
|
||||
"cache_settings_image_cache_size": "Velikost vyrovnávací paměti (položek {})",
|
||||
"cache_settings_statistics_album": "Knihovna náhledů",
|
||||
"cache_settings_statistics_assets": "{} položky ({})",
|
||||
"cache_settings_statistics_full": "Kompletní fotografie",
|
||||
"cache_settings_statistics_shared": "Sdílené náhledy alb",
|
||||
"cache_settings_statistics_thumbnail": "Náhledy",
|
||||
"cache_settings_statistics_title": "Použití vyrovnávací paměti",
|
||||
"cache_settings_subtitle": "Ovládání chování mobilní aplikace Immich v mezipaměti",
|
||||
"cache_settings_thumbnail_size": "Velikost vyrovnávací paměti náhledů (položek {})",
|
||||
"cache_settings_title": "Nastavení vyrovnávací paměti",
|
||||
"control_bottom_app_bar_add_to_album": "Přidat do alba",
|
||||
"control_bottom_app_bar_album_info": "{} položky",
|
||||
"control_bottom_app_bar_album_info_shared": "{} položky - sdílené",
|
||||
"control_bottom_app_bar_create_new_album": "Vytvořit nové album",
|
||||
"control_bottom_app_bar_delete": "Vymazat",
|
||||
"control_bottom_app_bar_share": "Sdílet",
|
||||
"create_album_page_untitled": "Bez názvu",
|
||||
"create_shared_album_page_create": "Vytvořit",
|
||||
"create_shared_album_page_share": "Sdílet",
|
||||
"create_shared_album_page_share_add_assets": "PŘIDAT",
|
||||
"create_shared_album_page_share_select_photos": "Vybrat fotografie",
|
||||
"daily_title_text_date": "EEEE, d MMMM",
|
||||
"daily_title_text_date_year": "EEEE, d MMMM y",
|
||||
"date_format": "EEEE, d MMMM y • H:mm",
|
||||
"delete_dialog_alert": "Tyto položky budou trvale odstraněny z Immich a z vašeho zařízení.",
|
||||
"delete_dialog_cancel": "Zrušit",
|
||||
"delete_dialog_ok": "Vymazat",
|
||||
"delete_dialog_title": "Vymazat trvale",
|
||||
"exif_bottom_sheet_description": "Přidat popis...",
|
||||
"exif_bottom_sheet_details": "PODROBNOSTI",
|
||||
"exif_bottom_sheet_location": "LOKALITA",
|
||||
"experimental_settings_new_asset_list_subtitle": "Probíhající práce",
|
||||
"experimental_settings_new_asset_list_title": "Povolení experimentální mřížky fotografií",
|
||||
"experimental_settings_subtitle": "Používejte na vlastní riziko!",
|
||||
"experimental_settings_title": "Experimentální",
|
||||
"home_page_add_to_album_conflicts": "Přidány {added} položky do alba {album}. {failed} položky jsou již v albu.",
|
||||
"home_page_add_to_album_success": "Přidány položky {added} do alba {album}.",
|
||||
"library_page_albums": "Alba",
|
||||
"library_page_new_album": "Nové album",
|
||||
"login_form_button_text": "Přihlášení",
|
||||
"login_form_email_hint": "tvůjmail@email.com",
|
||||
"login_form_endpoint_hint": "http://ip-tvého-serveru:port/api",
|
||||
"login_form_endpoint_url": "URL adresa serveru",
|
||||
"login_form_err_http": "Prosím, uveďte http:// nebo https://",
|
||||
"login_form_err_invalid_email": "Neplatný e-mail",
|
||||
"login_form_err_leading_whitespace": "Úvodní mezera",
|
||||
"login_form_err_trailing_whitespace": "Koncová mezera",
|
||||
"login_form_failed_get_oauth_server_config": "Chyba přihlášení pomocí OAuth, zkontrolujte adresu URL serveru",
|
||||
"login_form_failed_get_oauth_server_disable": "Funkce OAuth není na tomto serveru dostupná",
|
||||
"login_form_failed_login": "Chyba přihlášení, zkontrolujte url adresu serveru, e-mail a heslo.",
|
||||
"login_form_label_email": "E-mail",
|
||||
"login_form_label_password": "Heslo",
|
||||
"login_form_password_hint": "heslo",
|
||||
"login_form_save_login": "Zůstat přihlášen",
|
||||
"monthly_title_text_date_format": "LLLL y",
|
||||
"profile_drawer_app_logs": "Logy",
|
||||
"profile_drawer_client_server_up_to_date": "Klient a server jsou aktuální",
|
||||
"profile_drawer_settings": "Nastavení",
|
||||
"profile_drawer_sign_out": "Odhlásit se",
|
||||
"search_bar_hint": "Prohledejte své obrázky",
|
||||
"search_page_no_objects": "Žádné informace o objektech",
|
||||
"search_page_no_places": "Žádné informace o místě",
|
||||
"search_page_places": "Místa",
|
||||
"search_page_things": "Věci",
|
||||
"search_result_page_new_search_hint": "Nové vyhledávání",
|
||||
"select_additional_user_for_sharing_page_suggestions": "Návrhy",
|
||||
"select_user_for_sharing_page_err_album": "Nepodařilo se vytvořit album",
|
||||
"select_user_for_sharing_page_share_suggestions": "Návrhy",
|
||||
"setting_image_viewer_help": "V prohlížeči detailů se nejprve načte malá miniatura, poté se načte náhled střední velikosti (je-li povolen) a nakonec se načte originál (je-li povolen).",
|
||||
"setting_image_viewer_original_subtitle": "Umožňuje načíst původní obrázek v plném rozlišení (velký!). Zakázat pro snížení používání dat (v síti iv mezipaměti zařízení).",
|
||||
"setting_image_viewer_original_title": "Načíst původní obrázek",
|
||||
"setting_image_viewer_preview_subtitle": "Umožňuje načíst obrázek se středním rozlišením. Zakažte, pokud chcete přímo načíst originál nebo použít pouze miniaturu.",
|
||||
"setting_image_viewer_preview_title": "Načíst náhled obrázku",
|
||||
"setting_notifications_notify_failures_grace_period": "Oznámení o selhání zálohování na pozadí: {}",
|
||||
"setting_notifications_notify_hours": "{} hodin",
|
||||
"setting_notifications_notify_immediately": "okamžitě",
|
||||
"setting_notifications_notify_minutes": "{} minut",
|
||||
"setting_notifications_notify_never": "nikdy",
|
||||
"setting_notifications_notify_seconds": "{} sekundy",
|
||||
"setting_notifications_single_progress_subtitle": "Podrobné informace o průběhu nahrávání pro položku",
|
||||
"setting_notifications_single_progress_title": "Zobrazit průběh detailů zálohování na pozadí",
|
||||
"setting_notifications_subtitle": "Přizpůsobení předvoleb oznámení",
|
||||
"setting_notifications_title": "Oznámení",
|
||||
"setting_notifications_total_progress_subtitle": "Celkový průběh nahrávání (hotové/celkové položky)",
|
||||
"setting_notifications_total_progress_title": "Zobrazit celkový průběh zálohování na pozadí",
|
||||
"setting_pages_app_bar_settings": "nastavení",
|
||||
"settings_require_restart": "Pro použití tohoto nastavení restartujte Immich",
|
||||
"share_add": "Přidat",
|
||||
"share_add_photos": "Přidat fotografie",
|
||||
"share_add_title": "Přidat název",
|
||||
"share_create_album": "Vytvořit album",
|
||||
"share_dialog_preparing": "Připravuji...",
|
||||
"share_invite": "Pozvat do alba",
|
||||
"sharing_page_album": "Shared albums",
|
||||
"sharing_page_description": "Vytvářejte sdílená alba a sdílejte fotografie a videa s lidmi ve vaší síti.",
|
||||
"sharing_page_empty_list": "Prázný dopis",
|
||||
"sharing_silver_appbar_create_shared_album": "Vytvořit sdílené album",
|
||||
"sharing_silver_appbar_share_partner": "Sdílet s partnerem",
|
||||
"tab_controller_nav_library": "Knihovna",
|
||||
"tab_controller_nav_photos": "Fotografie",
|
||||
"tab_controller_nav_search": "Vyhledávání",
|
||||
"tab_controller_nav_sharing": "Sdílení",
|
||||
"theme_setting_asset_list_storage_indicator_title": "Zobrazit indikátor úložiště na dlaždicích zdrojů",
|
||||
"theme_setting_asset_list_tiles_per_row_title": "Počet aktiv na řádek ({})",
|
||||
"theme_setting_dark_mode_switch": "Tmavé téma",
|
||||
"theme_setting_image_viewer_quality_subtitle": "Přizpůsobení kvality prohlížeče detailů",
|
||||
"theme_setting_image_viewer_quality_title": "Kvalita prohlížeče obrázků",
|
||||
"theme_setting_system_theme_switch": "Automaticky (podle systemového nastavení)",
|
||||
"theme_setting_theme_subtitle": "Vyberte nastavení tématu aplikace",
|
||||
"theme_setting_theme_title": "Téma",
|
||||
"theme_setting_three_stage_loading_subtitle": "Třístupňové načítání může zvýšit výkonnost načítání, ale vede k výrazně vyššímu zatížení sítě.",
|
||||
"theme_setting_three_stage_loading_title": "Povolení třístupňového načítání",
|
||||
"version_announcement_overlay_ack": "Potvrdit",
|
||||
"version_announcement_overlay_release_notes": "poznámky k vydání",
|
||||
"version_announcement_overlay_text_1": "Ahoj, je zde nová verze",
|
||||
"version_announcement_overlay_text_2": "najděte si čas na návštěvu ",
|
||||
"version_announcement_overlay_text_3": " a ujistěte se, že vaše konfigurace docker-compose a .env je aktuální, abyste předešli nesprávné konfiguraci, zvláště pokud používáte WatchTower nebo jakýkoli mechanismus, který podporuje automatické aktualizace serverových aplikací.",
|
||||
"version_announcement_overlay_title": "K dispozici je nová verze serveru \uD83C\uDF89"
|
||||
}
|
||||
@@ -1,6 +1,9 @@
|
||||
{
|
||||
"album_info_card_backup_album_excluded": "EKSKLUDERET",
|
||||
"album_info_card_backup_album_included": "INKLUDERET",
|
||||
"album_thumbnail_card_item": "1 genstand",
|
||||
"album_thumbnail_card_items": "{} genstande",
|
||||
"album_thumbnail_card_shared": ". Delt",
|
||||
"album_viewer_appbar_share_delete": "Slet album",
|
||||
"album_viewer_appbar_share_err_delete": "Fejlede sletning af album",
|
||||
"album_viewer_appbar_share_err_leave": "Fejlede i at forlade album",
|
||||
@@ -9,6 +12,8 @@
|
||||
"album_viewer_appbar_share_leave": "Forlad album",
|
||||
"album_viewer_appbar_share_remove": "Fjern fra album",
|
||||
"album_viewer_page_share_add_users": "Tilføj brugere",
|
||||
"asset_list_settings_subtitle": "Indstillinger for billedgitterlayout",
|
||||
"asset_list_settings_title": "Billedgitter",
|
||||
"backup_album_selection_page_albums_device": "Albummer på enhed ({})",
|
||||
"backup_album_selection_page_albums_tap": "Tryk en gang for at inkludere, tryk to gange for at ekskludere",
|
||||
"backup_album_selection_page_assets_scatter": "Elementer kan være spredt på tværs af flere albummer. Albummer kan således inkluderes eller udelukkes under sikkerhedskopieringsprocessen.",
|
||||
@@ -16,7 +21,27 @@
|
||||
"backup_album_selection_page_selection_info": "Oplysninger om valgte",
|
||||
"backup_album_selection_page_total_assets": "Samlede unikke elementer",
|
||||
"backup_all": "Alt",
|
||||
"backup_controller_page_albums": "Sikkerhedskopier albummer",
|
||||
"backup_background_service_backup_failed_message": "Backup af billeder og videoer fejlede. Forsøger igen...",
|
||||
"backup_background_service_connection_failed_message": "Forbindelsen til serveren blev tabt. Forsøger igen...",
|
||||
"backup_background_service_current_upload_notification": "Uploader {}",
|
||||
"backup_background_service_default_notification": "Checking for new assets…",
|
||||
"backup_background_service_error_title": "Fejl med backup",
|
||||
"backup_background_service_in_progress_notification": "Tager backup af dine billeder og videoer...",
|
||||
"backup_background_service_upload_failure_notification": "Failed to upload {}",
|
||||
"backup_controller_page_albums": "Sikkerhedskopiér albummer",
|
||||
"backup_controller_page_background_battery_info_link": "Vis mig hvordan",
|
||||
"backup_controller_page_background_battery_info_message": "For den bedste oplevelse med baggrundsbackup, bør du slå batterioptimering, der begrænder baggrundsaktivitet, fra.\n\nSiden dette er afhængigt af enheden, bør du undersøge denne information leveret af din enheds producent.",
|
||||
"backup_controller_page_background_battery_info_ok": "OK",
|
||||
"backup_controller_page_background_battery_info_title": "Batterioptimering",
|
||||
"backup_controller_page_background_charging": "Kun under opladning",
|
||||
"backup_controller_page_background_configure_error": "Fejlede konfigureringen af baggrundsbackup",
|
||||
"backup_controller_page_background_delay": "Udskyd backup af nye billeder og videoer: {}",
|
||||
"backup_controller_page_background_description": "Slå baggrundsbackup til, for automatisk at tage backup af nye billeder og videoer, uden at skulle åbne appen",
|
||||
"backup_controller_page_background_is_off": "Automatisk baggrundsbackup er slået fra",
|
||||
"backup_controller_page_background_is_on": "Automatisk baggrundsbackup er slået til",
|
||||
"backup_controller_page_background_turn_off": "Slå baggrundsbackup fra",
|
||||
"backup_controller_page_background_turn_on": "Slå baggrundsbackup til",
|
||||
"backup_controller_page_background_wifi": "Kun med WiFi",
|
||||
"backup_controller_page_backup": "Sikkerhedskopier",
|
||||
"backup_controller_page_backup_selected": "Valgte: ",
|
||||
"backup_controller_page_backup_sub": "Sikkerhedskopierede billeder og videoer",
|
||||
@@ -45,7 +70,27 @@
|
||||
"backup_controller_page_uploading_file_info": "Uploader filinformation",
|
||||
"backup_err_only_album": "Kan ikke slette det eneste album",
|
||||
"backup_info_card_assets": "elementer",
|
||||
"cache_settings_album_thumbnails": "Biblioteksminiaturebilleder ({} billeder og videoer)",
|
||||
"cache_settings_clear_cache_button": "Fjern cache",
|
||||
"cache_settings_clear_cache_button_title": "Fjern appens cache. Dette vil i stor grad påvirke appens ydeevne indtil cachen er genopbygget.",
|
||||
"cache_settings_image_cache_size": "Størrelse af billedecache ({} billeder og videoer)",
|
||||
"cache_settings_statistics_album": "Biblioteksminiaturer",
|
||||
"cache_settings_statistics_assets": "{} billeder og videoer ({})",
|
||||
"cache_settings_statistics_full": "Fulde billeder",
|
||||
"cache_settings_statistics_shared": "Miniaturebilleder til delte albummer",
|
||||
"cache_settings_statistics_thumbnail": "Miniaturebilleder",
|
||||
"cache_settings_statistics_title": "Cacheforbrug",
|
||||
"cache_settings_subtitle": "Håndter cache-adfærden for Immich-appen.",
|
||||
"cache_settings_thumbnail_size": "Størrelse af miniaturebillede cache ({} billeder og videoer)",
|
||||
"cache_settings_title": "Cache-indstillinger",
|
||||
"control_bottom_app_bar_add_to_album": "Tilføj til album",
|
||||
"control_bottom_app_bar_album_info": "{} genstande",
|
||||
"control_bottom_app_bar_album_info_shared": "{} genstande • Delt",
|
||||
"control_bottom_app_bar_create_new_album": "Opret nyt album",
|
||||
"control_bottom_app_bar_delete": "Slet",
|
||||
"control_bottom_app_bar_share": "Del",
|
||||
"create_album_page_untitled": "Uden titel",
|
||||
"create_shared_album_page_create": "Opret",
|
||||
"create_shared_album_page_share": "Del",
|
||||
"create_shared_album_page_share_add_assets": "TILFØJ ELEMENT",
|
||||
"create_shared_album_page_share_select_photos": "Vælg billeder",
|
||||
@@ -59,6 +104,14 @@
|
||||
"exif_bottom_sheet_description": "Tilføj beskrivelse...",
|
||||
"exif_bottom_sheet_details": "DETALJER",
|
||||
"exif_bottom_sheet_location": "LOKATION",
|
||||
"experimental_settings_new_asset_list_subtitle": "Under udarbejdelse",
|
||||
"experimental_settings_new_asset_list_title": "Aktiver eksperimentelt fotogitter",
|
||||
"experimental_settings_subtitle": "Brug på eget ansvar!",
|
||||
"experimental_settings_title": "Eksperimentelle",
|
||||
"home_page_add_to_album_conflicts": "Tilføjede {added} billeder og videoer til album {album}. {failed} billeder og videoer er allerede i albummet.",
|
||||
"home_page_add_to_album_success": "Tilføjede {added} billeder og videoer til album {album}.",
|
||||
"library_page_albums": "Albummer",
|
||||
"library_page_new_album": "Nyt album",
|
||||
"login_form_button_text": "Log ind",
|
||||
"login_form_email_hint": "din-email@email.com",
|
||||
"login_form_endpoint_hint": "http://din-server-ip:port/api",
|
||||
@@ -67,13 +120,17 @@
|
||||
"login_form_err_invalid_email": "Ugyldig email",
|
||||
"login_form_err_leading_whitespace": "Mellemrum før",
|
||||
"login_form_err_trailing_whitespace": "Mellemrum efter",
|
||||
"login_form_failed_get_oauth_server_config": "Fejl med at logge på med OAuth. Tjek serveres URL",
|
||||
"login_form_failed_get_oauth_server_disable": "OAuth er ikke tilgængelig på denne server",
|
||||
"login_form_failed_login": "Der opstod en vejl ved at logge ind. Tjek server URL, email og kodeordet",
|
||||
"login_form_label_email": "Email",
|
||||
"login_form_label_password": "Kodeord",
|
||||
"login_form_password_hint": "kodeord",
|
||||
"login_form_save_login": "Forbliv logget ind",
|
||||
"monthly_title_text_date_format": "MMMM y",
|
||||
"profile_drawer_app_logs": "Log",
|
||||
"profile_drawer_client_server_up_to_date": "Klient og server er ajour",
|
||||
"profile_drawer_settings": "Indstillinger",
|
||||
"profile_drawer_sign_out": "Log ud",
|
||||
"search_bar_hint": "Søg i dine billeder",
|
||||
"search_page_no_objects": "Ingen elementer er tilgængelige",
|
||||
@@ -84,19 +141,50 @@
|
||||
"select_additional_user_for_sharing_page_suggestions": "Anbefalinger",
|
||||
"select_user_for_sharing_page_err_album": "Fejlede i at oprette et nyt album",
|
||||
"select_user_for_sharing_page_share_suggestions": "Anbefalinger",
|
||||
"setting_image_viewer_help": "Detaljeret visning indlæser miniaturebilleder først. Herefter indlæses mediumstørrelse forhåndsvisning af billedet (hvis dette er slået til), for til sidst at vise originalen (hvis dette er slået til).",
|
||||
"setting_image_viewer_original_subtitle": "Slå indlæsning af originalbillede i fuld størrelse til (stort!). Deaktiver for at reducere dataforbruget (både på netværket og for enhedscache).",
|
||||
"setting_image_viewer_original_title": "Indlæs originalbillede",
|
||||
"setting_image_viewer_preview_subtitle": "Slå indlæsning af et mediumstørrelse billede til. Slå fra for enten direkte at indlæse originalen eller kun at bruge miniaturebilledet.",
|
||||
"setting_image_viewer_preview_title": "Indlæs forhåndsvisning af billedet",
|
||||
"setting_notifications_notify_failures_grace_period": "Giv besked om baggrundsbackupfejl: {}",
|
||||
"setting_notifications_notify_hours": "{} timer",
|
||||
"setting_notifications_notify_immediately": "med det samme",
|
||||
"setting_notifications_notify_minutes": "{} minutter",
|
||||
"setting_notifications_notify_never": "aldrig",
|
||||
"setting_notifications_notify_seconds": "{} sekunder",
|
||||
"setting_notifications_single_progress_subtitle": "Detaljeret uploadstatus pr. billed og video",
|
||||
"setting_notifications_single_progress_title": "Vis detaljeret baggrundsuploadstatus",
|
||||
"setting_notifications_subtitle": "Tilpas dine notifikationspræferencer",
|
||||
"setting_notifications_title": "Notifikationer",
|
||||
"setting_notifications_total_progress_subtitle": "Samlet uploadstatus (færdige/samlede billeder og videoer)",
|
||||
"setting_notifications_total_progress_title": "Vis samlet baggrundsuploadstatus",
|
||||
"setting_pages_app_bar_settings": "Indstillinger",
|
||||
"settings_require_restart": "Genstart venligst Immich for at anvende denne ændring",
|
||||
"share_add": "Tilføj",
|
||||
"share_add_photos": "Tilføj billeder",
|
||||
"share_add_title": "Tilføj en titel",
|
||||
"share_create_album": "Opret album",
|
||||
"share_dialog_preparing": "Forbereder...",
|
||||
"share_invite": "Inviter til album",
|
||||
"sharing_page_album": "Delt albums",
|
||||
"sharing_page_description": "Opret delte albummer for at dele billeder og video med personer på dit netværk.",
|
||||
"sharing_page_empty_list": "TOM LISTE",
|
||||
"sharing_silver_appbar_create_shared_album": "Opret delt album",
|
||||
"sharing_silver_appbar_share_partner": "Del med partner",
|
||||
"tab_controller_nav_library": "Bibliotek",
|
||||
"tab_controller_nav_photos": "Billeder",
|
||||
"tab_controller_nav_search": "Søg",
|
||||
"tab_controller_nav_sharing": "Deling",
|
||||
"theme_setting_asset_list_storage_indicator_title": "Vis opbevaringsindikator på filer",
|
||||
"theme_setting_asset_list_tiles_per_row_title": "Antal billeder og videoer per række ({})",
|
||||
"theme_setting_dark_mode_switch": "Mørk tilstand",
|
||||
"theme_setting_image_viewer_quality_subtitle": "Juster kvaliteten i billedfremviseren",
|
||||
"theme_setting_image_viewer_quality_title": "Billedfremviserkvalitet",
|
||||
"theme_setting_system_theme_switch": "Automatisk (Følg systemindstillinger)",
|
||||
"theme_setting_theme_subtitle": "Vælg appens temaindstilling",
|
||||
"theme_setting_theme_title": "Tema",
|
||||
"theme_setting_three_stage_loading_subtitle": "Tre-trins indlæsning kan øge ydeevnen, men kan ligeledes føre til højere netværksbelastning",
|
||||
"theme_setting_three_stage_loading_title": "Slå tre-trins indlæsning til",
|
||||
"version_announcement_overlay_ack": "Vedkend",
|
||||
"version_announcement_overlay_release_notes": "udgivelsesnoter",
|
||||
"version_announcement_overlay_text_1": "Hej vej, der er en ny version af",
|
||||
|
||||
@@ -12,6 +12,8 @@
|
||||
"album_viewer_appbar_share_leave": "Album verlassen",
|
||||
"album_viewer_appbar_share_remove": "Entferne vom Album",
|
||||
"album_viewer_page_share_add_users": "Nutzer hinzufügen",
|
||||
"asset_list_settings_subtitle": "Photo grid layout settings",
|
||||
"asset_list_settings_title": "Photo Grid",
|
||||
"backup_album_selection_page_albums_device": "Alben auf dem Gerät ({})",
|
||||
"backup_album_selection_page_albums_tap": "Tippen um einzuschließen, doppelt tippen um zu entfernen",
|
||||
"backup_album_selection_page_assets_scatter": "Elemente können sich über mehrere Alben verteilen. Daher können diese vor der Sicherung eingeschlossen oder ausgeschlossen werden",
|
||||
@@ -19,12 +21,31 @@
|
||||
"backup_album_selection_page_selection_info": "Auswahl",
|
||||
"backup_album_selection_page_total_assets": "Elemente",
|
||||
"backup_all": "Alle",
|
||||
"backup_background_service_backup_failed_message": "Failed to backup assets. Retrying…",
|
||||
"backup_background_service_connection_failed_message": "Failed to connect to the server. Retrying…",
|
||||
"backup_background_service_current_upload_notification": "Uploading {}",
|
||||
"backup_background_service_default_notification": "Suche nach neuen assets…",
|
||||
"backup_background_service_error_title": "Backup error",
|
||||
"backup_background_service_in_progress_notification": "Backing up your assets…",
|
||||
"backup_background_service_upload_failure_notification": "Failed to upload {}",
|
||||
"backup_controller_page_albums": "Gesicherte Alben",
|
||||
"backup_controller_page_background_battery_info_link": "Show me how",
|
||||
"backup_controller_page_background_battery_info_message": "For the best background backup experience, please disable any battery optimizations restricting background activity for Immich.\n\nSince this is device-specific, please lookup the required information for your device manufacturer.",
|
||||
"backup_controller_page_background_battery_info_ok": "OK",
|
||||
"backup_controller_page_background_battery_info_title": "Battery optimizations",
|
||||
"backup_controller_page_background_charging": "Only while charging",
|
||||
"backup_controller_page_background_configure_error": "Failed to configure the background service",
|
||||
"backup_controller_page_background_delay": "Delay new assets backup: {}",
|
||||
"backup_controller_page_background_description": "Turn on the background service to automatically backup any new assets without needing to open the app",
|
||||
"backup_controller_page_background_is_off": "Automatic background backup is off",
|
||||
"backup_controller_page_background_is_on": "Automatic background backup is on",
|
||||
"backup_controller_page_background_turn_off": "Turn off background service",
|
||||
"backup_controller_page_background_turn_on": "Turn on background service",
|
||||
"backup_controller_page_background_wifi": "Only on WiFi",
|
||||
"backup_controller_page_backup": "Sicherung",
|
||||
"backup_controller_page_backup_selected": "Ausgewählt: ",
|
||||
"backup_controller_page_backup_sub": "Gesicherte Fotos und Videos",
|
||||
"backup_controller_page_cancel": "Abbrechen",
|
||||
"backup_background_service_default_notification": "Suche nach neuen assets…",
|
||||
"backup_controller_page_created": "Erstellt: {}",
|
||||
"backup_controller_page_desc_backup": "Aktiviere die Sicherung um Elemente automatisch auf den Server zu laden.",
|
||||
"backup_controller_page_excluded": "Ausgeschlossen: ",
|
||||
@@ -49,6 +70,23 @@
|
||||
"backup_controller_page_uploading_file_info": "Informationen",
|
||||
"backup_err_only_album": "Das einzige Album kann nicht entfernt werden",
|
||||
"backup_info_card_assets": "Elemente",
|
||||
"cache_settings_album_thumbnails": "Library page thumbnails ({} assets)",
|
||||
"cache_settings_clear_cache_button": "Clear cache",
|
||||
"cache_settings_clear_cache_button_title": "Clears the app's cache. This will significantly impact the app's performance until the cache has rebuilt.",
|
||||
"cache_settings_image_cache_size": "Image cache size ({} assets)",
|
||||
"cache_settings_statistics_album": "Library thumbnails",
|
||||
"cache_settings_statistics_assets": "{} assets ({})",
|
||||
"cache_settings_statistics_full": "Full images",
|
||||
"cache_settings_statistics_shared": "Shared album thumbnails",
|
||||
"cache_settings_statistics_thumbnail": "Vorschaubilder",
|
||||
"cache_settings_statistics_title": "Cache usage",
|
||||
"cache_settings_subtitle": "Control the caching behaviour of the Immich mobile application",
|
||||
"cache_settings_thumbnail_size": "Thumbnail cache size ({} assets)",
|
||||
"cache_settings_title": "Caching Settings",
|
||||
"control_bottom_app_bar_add_to_album": "Add to album",
|
||||
"control_bottom_app_bar_album_info": "{} items",
|
||||
"control_bottom_app_bar_album_info_shared": "{} items · Shared",
|
||||
"control_bottom_app_bar_create_new_album": "Create new album",
|
||||
"control_bottom_app_bar_delete": "Löschen",
|
||||
"control_bottom_app_bar_share": "Teilen",
|
||||
"create_album_page_untitled": "Unbenannt",
|
||||
@@ -66,6 +104,12 @@
|
||||
"exif_bottom_sheet_description": "Beschreibung hinzufügen...",
|
||||
"exif_bottom_sheet_details": "DETAILS",
|
||||
"exif_bottom_sheet_location": "STANDORT",
|
||||
"experimental_settings_new_asset_list_subtitle": "In Arbeit",
|
||||
"experimental_settings_new_asset_list_title": "Enable experimental photo grid",
|
||||
"experimental_settings_subtitle": "Use at your own risk!",
|
||||
"experimental_settings_title": "Experimentell",
|
||||
"home_page_add_to_album_conflicts": "Added {added} assets to album {album}. {failed} assets are already in the album.",
|
||||
"home_page_add_to_album_success": "Added {added} assets to album {album}.",
|
||||
"library_page_albums": "Alben",
|
||||
"library_page_new_album": "Neues Album",
|
||||
"login_form_button_text": "Anmelden",
|
||||
@@ -76,12 +120,15 @@
|
||||
"login_form_err_invalid_email": "Ungültige E-Mail",
|
||||
"login_form_err_leading_whitespace": "Führendes Leerzichen",
|
||||
"login_form_err_trailing_whitespace": "Folgendes Leerzeichen",
|
||||
"login_form_failed_get_oauth_server_config": "Error logging using OAuth, check server URL",
|
||||
"login_form_failed_get_oauth_server_disable": "OAuth feature is not available on this server",
|
||||
"login_form_failed_login": "Error logging you in, check server url, email and password",
|
||||
"login_form_label_email": "E-Mail",
|
||||
"login_form_label_password": "Passwort",
|
||||
"login_form_password_hint": "password",
|
||||
"login_form_save_login": "Angemeldet bleiben",
|
||||
"monthly_title_text_date_format": "MMMM y",
|
||||
"profile_drawer_app_logs": "Logs",
|
||||
"profile_drawer_client_server_up_to_date": "App und Server sind aktuell",
|
||||
"profile_drawer_settings": "Einstellungen",
|
||||
"profile_drawer_sign_out": "Abmelden",
|
||||
@@ -94,7 +141,25 @@
|
||||
"select_additional_user_for_sharing_page_suggestions": "Vorschläge",
|
||||
"select_user_for_sharing_page_err_album": "Album konnte nicht erstellt werden",
|
||||
"select_user_for_sharing_page_share_suggestions": "Suggestions",
|
||||
"setting_image_viewer_help": "The detail viewer loads the small thumbnail first, then loads the medium-size preview (if enabled), finally loads the original (if enabled).",
|
||||
"setting_image_viewer_original_subtitle": "Enable to load the original full-resolution image (large!). Disable to reduce data usage (both network and on device cache).",
|
||||
"setting_image_viewer_original_title": "Load original image",
|
||||
"setting_image_viewer_preview_subtitle": "Enable to load a medium-resolution image. Disable to either directly load the original or only use the thumbnail.",
|
||||
"setting_image_viewer_preview_title": "Load preview image",
|
||||
"setting_notifications_notify_failures_grace_period": "Notify background backup failures: {}",
|
||||
"setting_notifications_notify_hours": "{} hours",
|
||||
"setting_notifications_notify_immediately": "immediately",
|
||||
"setting_notifications_notify_minutes": "{} minutes",
|
||||
"setting_notifications_notify_never": "never",
|
||||
"setting_notifications_notify_seconds": "{} seconds",
|
||||
"setting_notifications_single_progress_subtitle": "Detaillierte Upload Informationen für jedes Element.",
|
||||
"setting_notifications_single_progress_title": "Show background backup detail progress",
|
||||
"setting_notifications_subtitle": "Adjust your notification preferences",
|
||||
"setting_notifications_title": "Notifications",
|
||||
"setting_notifications_total_progress_subtitle": "Overall upload progress (done/total assets)",
|
||||
"setting_notifications_total_progress_title": "Show background backup total progress",
|
||||
"setting_pages_app_bar_settings": "Einstellungen",
|
||||
"settings_require_restart": "Bitte starte Immich neu, um diese Einstellung anzuwenden.",
|
||||
"share_add": "Hinzufügen",
|
||||
"share_add_photos": "Fotos hinzufügen",
|
||||
"share_add_title": "Titel hinzufügen",
|
||||
@@ -110,6 +175,8 @@
|
||||
"tab_controller_nav_photos": "Fotos",
|
||||
"tab_controller_nav_search": "Suche",
|
||||
"tab_controller_nav_sharing": "Teilen",
|
||||
"theme_setting_asset_list_storage_indicator_title": "Show storage indicator on asset tiles",
|
||||
"theme_setting_asset_list_tiles_per_row_title": "Number of assets per row ({})",
|
||||
"theme_setting_dark_mode_switch": "Dunkler Modus",
|
||||
"theme_setting_image_viewer_quality_subtitle": "Einstellen der Qualität des Detailbildbetrachters",
|
||||
"theme_setting_image_viewer_quality_title": "Qualität des Bildbetrachters",
|
||||
@@ -124,4 +191,4 @@
|
||||
"version_announcement_overlay_text_2": "Bitte nehm dir die Zeit und lese das ",
|
||||
"version_announcement_overlay_text_3": " und achte darauf, dass deine docker-compose und .env Dateien aktuell sind, vor allem wenn du ein System für automatische Updates benutzt (z.B. Watchtower).",
|
||||
"version_announcement_overlay_title": "Neue Server-Version verfügbar \uD83C\uDF89"
|
||||
}
|
||||
}
|
||||
@@ -35,13 +35,13 @@
|
||||
"backup_controller_page_background_battery_info_title": "Battery optimizations",
|
||||
"backup_controller_page_background_charging": "Only while charging",
|
||||
"backup_controller_page_background_configure_error": "Failed to configure the background service",
|
||||
"backup_controller_page_background_delay": "Delay new assets backup: {}",
|
||||
"backup_controller_page_background_description": "Turn on the background service to automatically backup any new assets without needing to open the app",
|
||||
"backup_controller_page_background_is_off": "Automatic background backup is off",
|
||||
"backup_controller_page_background_is_on": "Automatic background backup is on",
|
||||
"backup_controller_page_background_turn_off": "Turn off background service",
|
||||
"backup_controller_page_background_turn_on": "Turn on background service",
|
||||
"backup_controller_page_background_wifi": "Only on WiFi",
|
||||
"backup_controller_page_background_delay": "Delay new assets backup: {}",
|
||||
"backup_controller_page_backup": "Backup",
|
||||
"backup_controller_page_backup_selected": "Selected: ",
|
||||
"backup_controller_page_backup_sub": "Backed up photos and videos",
|
||||
@@ -83,6 +83,10 @@
|
||||
"cache_settings_subtitle": "Control the caching behaviour of the Immich mobile application",
|
||||
"cache_settings_thumbnail_size": "Thumbnail cache size ({} assets)",
|
||||
"cache_settings_title": "Caching Settings",
|
||||
"control_bottom_app_bar_add_to_album": "Add to album",
|
||||
"control_bottom_app_bar_album_info": "{} items",
|
||||
"control_bottom_app_bar_album_info_shared": "{} items · Shared",
|
||||
"control_bottom_app_bar_create_new_album": "Create new album",
|
||||
"control_bottom_app_bar_delete": "Delete",
|
||||
"control_bottom_app_bar_share": "Share",
|
||||
"create_album_page_untitled": "Untitled",
|
||||
@@ -100,6 +104,12 @@
|
||||
"exif_bottom_sheet_description": "Add Description...",
|
||||
"exif_bottom_sheet_details": "DETAILS",
|
||||
"exif_bottom_sheet_location": "LOCATION",
|
||||
"experimental_settings_new_asset_list_subtitle": "Work in progress",
|
||||
"experimental_settings_new_asset_list_title": "Enable experimental photo grid",
|
||||
"experimental_settings_subtitle": "Use at your own risk!",
|
||||
"experimental_settings_title": "Experimental",
|
||||
"home_page_add_to_album_conflicts": "Added {added} assets to album {album}. {failed} assets are already in the album.",
|
||||
"home_page_add_to_album_success": "Added {added} assets to album {album}.",
|
||||
"library_page_albums": "Albums",
|
||||
"library_page_new_album": "New album",
|
||||
"login_form_button_text": "Login",
|
||||
@@ -110,18 +120,18 @@
|
||||
"login_form_err_invalid_email": "Invalid Email",
|
||||
"login_form_err_leading_whitespace": "Leading whitespace",
|
||||
"login_form_err_trailing_whitespace": "Trailing whitespace",
|
||||
"login_form_failed_login": "Error logging you in, check server URL, email and password",
|
||||
"login_form_failed_get_oauth_server_config": "Error logging using OAuth, check server URL",
|
||||
"login_form_failed_get_oauth_server_disable": "OAuth feature is not available on this server",
|
||||
"login_form_failed_login": "Error logging you in, check server URL, email and password",
|
||||
"login_form_label_email": "Email",
|
||||
"login_form_label_password": "Password",
|
||||
"login_form_password_hint": "password",
|
||||
"login_form_save_login": "Stay logged in",
|
||||
"monthly_title_text_date_format": "MMMM y",
|
||||
"profile_drawer_app_logs": "Logs",
|
||||
"profile_drawer_client_server_up_to_date": "Client and Server are up-to-date",
|
||||
"profile_drawer_settings": "Settings",
|
||||
"profile_drawer_sign_out": "Sign Out",
|
||||
"profile_drawer_app_logs": "Logs",
|
||||
"search_bar_hint": "Search your photos",
|
||||
"search_page_no_objects": "No Objects Info Available",
|
||||
"search_page_no_places": "No Places Info Available",
|
||||
@@ -131,24 +141,25 @@
|
||||
"select_additional_user_for_sharing_page_suggestions": "Suggestions",
|
||||
"select_user_for_sharing_page_err_album": "Failed to create album",
|
||||
"select_user_for_sharing_page_share_suggestions": "Suggestions",
|
||||
"setting_image_viewer_help": "The detail viewer loads the small thumbnail first, then loads the medium-size preview (if enabled), finally loads the original (if enabled).",
|
||||
"setting_image_viewer_original_subtitle": "Enable to load the original full-resolution image (large!). Disable to reduce data usage (both network and on device cache).",
|
||||
"setting_image_viewer_original_title": "Load original image",
|
||||
"setting_image_viewer_preview_subtitle": "Enable to load a medium-resolution image. Disable to either directly load the original or only use the thumbnail.",
|
||||
"setting_image_viewer_preview_title": "Load preview image",
|
||||
"setting_notifications_notify_failures_grace_period": "Notify background backup failures: {}",
|
||||
"setting_notifications_notify_hours": "{} hours",
|
||||
"setting_notifications_notify_immediately": "immediately",
|
||||
"setting_notifications_notify_minutes": "{} minutes",
|
||||
"setting_notifications_notify_seconds": "{} seconds",
|
||||
"setting_notifications_notify_never": "never",
|
||||
"setting_notifications_notify_seconds": "{} seconds",
|
||||
"setting_notifications_single_progress_subtitle": "Detailed upload progress information per asset",
|
||||
"setting_notifications_single_progress_title": "Show background backup detail progress",
|
||||
"setting_notifications_subtitle": "Adjust your notification preferences",
|
||||
"setting_notifications_title": "Notifications",
|
||||
"setting_notifications_total_progress_title": "Show background backup total progress",
|
||||
"setting_notifications_total_progress_subtitle": "Overall upload progress (done/total assets)",
|
||||
"setting_notifications_single_progress_title": "Show background backup detail progress",
|
||||
"setting_notifications_single_progress_subtitle": "Detailed upload progress information per asset",
|
||||
"setting_image_viewer_help": "The detail viewer loads the small thumbnail first, then loads the medium-size preview (if enabled), finally loads the original (if enabled).",
|
||||
"setting_image_viewer_preview_title": "Load preview image",
|
||||
"setting_image_viewer_preview_subtitle": "Enable to load a medium-resolution image. Disable to either directly load the original or only use the thumbnail.",
|
||||
"setting_image_viewer_original_title": "Load original image",
|
||||
"setting_image_viewer_original_subtitle": "Enable to load the original full-resolution image (large!). Disable to reduce data usage (both network and on device cache).",
|
||||
"setting_notifications_total_progress_title": "Show background backup total progress",
|
||||
"setting_pages_app_bar_settings": "Settings",
|
||||
"settings_require_restart": "Please restart Immich to apply this setting",
|
||||
"share_add": "Add",
|
||||
"share_add_photos": "Add photos",
|
||||
"share_add_title": "Add a title",
|
||||
@@ -172,18 +183,12 @@
|
||||
"theme_setting_system_theme_switch": "Automatic (Follow system setting)",
|
||||
"theme_setting_theme_subtitle": "Choose the app's theme setting",
|
||||
"theme_setting_theme_title": "Theme",
|
||||
"theme_setting_three_stage_loading_subtitle": "Three-stage loading might increase the loading performance but causes significantly higher network load",
|
||||
"theme_setting_three_stage_loading_title": "Enable three-stage loading",
|
||||
"version_announcement_overlay_ack": "Acknowledge",
|
||||
"version_announcement_overlay_release_notes": "release notes",
|
||||
"version_announcement_overlay_text_1": "Hi friend, there is a new release of",
|
||||
"version_announcement_overlay_text_2": "please take your time to visit the ",
|
||||
"version_announcement_overlay_text_3": " and ensure your docker-compose and .env setup is up-to-date to prevent any misconfigurations, especially if you use WatchTower or any mechanism that handles updating your server application automatically.",
|
||||
"version_announcement_overlay_title": "New Server Version Available \uD83C\uDF89",
|
||||
"experimental_settings_title": "Experimental",
|
||||
"experimental_settings_subtitle": "Use at your own risk!",
|
||||
"control_bottom_app_bar_add_to_album": "Add to album",
|
||||
"home_page_add_to_album_success": "Added {added} assets to album {album}.",
|
||||
"home_page_add_to_album_conflicts": "Added {added} assets to album {album}. {failed} assets are already in the album.",
|
||||
"control_bottom_app_bar_album_info": "{} items",
|
||||
"control_bottom_app_bar_album_info_shared": "{} items · Shared",
|
||||
"control_bottom_app_bar_create_new_album": "Create new album"
|
||||
}
|
||||
"version_announcement_overlay_title": "New Server Version Available \uD83C\uDF89"
|
||||
}
|
||||
@@ -1,6 +1,9 @@
|
||||
{
|
||||
"album_info_card_backup_album_excluded": "EXCLUIDOS",
|
||||
"album_info_card_backup_album_included": "INCLUIDOS",
|
||||
"album_thumbnail_card_item": "1 item",
|
||||
"album_thumbnail_card_items": "{} items",
|
||||
"album_thumbnail_card_shared": " · Shared",
|
||||
"album_viewer_appbar_share_delete": "Eliminar álbum ",
|
||||
"album_viewer_appbar_share_err_delete": "No ha podido eliminar el álbum",
|
||||
"album_viewer_appbar_share_err_leave": "No ha podido dejar el álbum",
|
||||
@@ -9,6 +12,8 @@
|
||||
"album_viewer_appbar_share_leave": "Abandonar álbum ",
|
||||
"album_viewer_appbar_share_remove": "Eliminar del álbum ",
|
||||
"album_viewer_page_share_add_users": "Añadir usuarios",
|
||||
"asset_list_settings_subtitle": "Photo grid layout settings",
|
||||
"asset_list_settings_title": "Photo Grid",
|
||||
"backup_album_selection_page_albums_device": "Álbumes en el dispositivo ({})",
|
||||
"backup_album_selection_page_albums_tap": "Toque para incluir, doble toque para excluir",
|
||||
"backup_album_selection_page_assets_scatter": "Los activos pueden dispersarse en varios álbumes. De este modo, los álbumes pueden ser incluidos o excluidos durante el proceso de copia de seguridad.",
|
||||
@@ -16,13 +21,37 @@
|
||||
"backup_album_selection_page_selection_info": "Información sobre la Selección",
|
||||
"backup_album_selection_page_total_assets": "Total de activos únicos",
|
||||
"backup_all": "Todos",
|
||||
"backup_background_service_backup_failed_message": "Failed to backup assets. Retrying…",
|
||||
"backup_background_service_connection_failed_message": "Failed to connect to the server. Retrying…",
|
||||
"backup_background_service_current_upload_notification": "Uploading {}",
|
||||
"backup_background_service_default_notification": "Checking for new assets…",
|
||||
"backup_background_service_error_title": "Backup error",
|
||||
"backup_background_service_in_progress_notification": "Backing up your assets…",
|
||||
"backup_background_service_upload_failure_notification": "Failed to upload {}",
|
||||
"backup_controller_page_albums": "Álbumes de copia de seguridad",
|
||||
"backup_controller_page_background_battery_info_link": "Show me how",
|
||||
"backup_controller_page_background_battery_info_message": "For the best background backup experience, please disable any battery optimizations restricting background activity for Immich.\n\nSince this is device-specific, please lookup the required information for your device manufacturer.",
|
||||
"backup_controller_page_background_battery_info_ok": "OK",
|
||||
"backup_controller_page_background_battery_info_title": "Battery optimizations",
|
||||
"backup_controller_page_background_charging": "Only while charging",
|
||||
"backup_controller_page_background_configure_error": "Failed to configure the background service",
|
||||
"backup_controller_page_background_delay": "Delay new assets backup: {}",
|
||||
"backup_controller_page_background_description": "Turn on the background service to automatically backup any new assets without needing to open the app",
|
||||
"backup_controller_page_background_is_off": "Automatic background backup is off",
|
||||
"backup_controller_page_background_is_on": "Automatic background backup is on",
|
||||
"backup_controller_page_background_turn_off": "Turn off background service",
|
||||
"backup_controller_page_background_turn_on": "Turn on background service",
|
||||
"backup_controller_page_background_wifi": "Only on WiFi",
|
||||
"backup_controller_page_backup": "Copia de Seguridad",
|
||||
"backup_controller_page_backup_selected": "Seleccionado:",
|
||||
"backup_controller_page_backup_sub": "Copia de seguridad de fotos y vídeos",
|
||||
"backup_controller_page_cancel": "Cancelar",
|
||||
"backup_controller_page_created": "Created on: {}",
|
||||
"backup_controller_page_desc_backup": "Active la copia de seguridad para cargar automáticamente los nuevos activos al servidor.",
|
||||
"backup_controller_page_excluded": "Excluido:",
|
||||
"backup_controller_page_failed": "Failed ({})",
|
||||
"backup_controller_page_filename": "File name: {} [{}]",
|
||||
"backup_controller_page_id": "ID: {}",
|
||||
"backup_controller_page_info": "Información de la Copia de Seguridad",
|
||||
"backup_controller_page_none_selected": "Ninguno seleccionado",
|
||||
"backup_controller_page_remainder": "Remanente",
|
||||
@@ -38,9 +67,30 @@
|
||||
"backup_controller_page_total_sub": "Todas las fotos y vídeos únicos de los álbumes seleccionados",
|
||||
"backup_controller_page_turn_off": "Apagar la copia de seguridad",
|
||||
"backup_controller_page_turn_on": "Activar la copia de seguridad",
|
||||
"backup_controller_page_uploading_file_info": "Uploading file info",
|
||||
"backup_err_only_album": "No se puede eliminar el único álbum",
|
||||
"backup_info_card_assets": "activos",
|
||||
"cache_settings_album_thumbnails": "Library page thumbnails ({} assets)",
|
||||
"cache_settings_clear_cache_button": "Clear cache",
|
||||
"cache_settings_clear_cache_button_title": "Clears the app's cache. This will significantly impact the app's performance until the cache has rebuilt.",
|
||||
"cache_settings_image_cache_size": "Image cache size ({} assets)",
|
||||
"cache_settings_statistics_album": "Library thumbnails",
|
||||
"cache_settings_statistics_assets": "{} assets ({})",
|
||||
"cache_settings_statistics_full": "Full images",
|
||||
"cache_settings_statistics_shared": "Shared album thumbnails",
|
||||
"cache_settings_statistics_thumbnail": "Thumbnails",
|
||||
"cache_settings_statistics_title": "Cache usage",
|
||||
"cache_settings_subtitle": "Control the caching behaviour of the Immich mobile application",
|
||||
"cache_settings_thumbnail_size": "Thumbnail cache size ({} assets)",
|
||||
"cache_settings_title": "Caching Settings",
|
||||
"control_bottom_app_bar_add_to_album": "Add to album",
|
||||
"control_bottom_app_bar_album_info": "{} items",
|
||||
"control_bottom_app_bar_album_info_shared": "{} items · Shared",
|
||||
"control_bottom_app_bar_create_new_album": "Create new album",
|
||||
"control_bottom_app_bar_delete": "Eliminar",
|
||||
"control_bottom_app_bar_share": "Share",
|
||||
"create_album_page_untitled": "Untitled",
|
||||
"create_shared_album_page_create": "Create",
|
||||
"create_shared_album_page_share": "Compartir",
|
||||
"create_shared_album_page_share_add_assets": "AÑADIR ACTIVOS",
|
||||
"create_shared_album_page_share_select_photos": "Seleccionar Fotos",
|
||||
@@ -54,6 +104,14 @@
|
||||
"exif_bottom_sheet_description": "Añadir Descripción...",
|
||||
"exif_bottom_sheet_details": "DETALLES",
|
||||
"exif_bottom_sheet_location": "LOCALZACIÓN",
|
||||
"experimental_settings_new_asset_list_subtitle": "Work in progress",
|
||||
"experimental_settings_new_asset_list_title": "Enable experimental photo grid",
|
||||
"experimental_settings_subtitle": "Use at your own risk!",
|
||||
"experimental_settings_title": "Experimental",
|
||||
"home_page_add_to_album_conflicts": "Added {added} assets to album {album}. {failed} assets are already in the album.",
|
||||
"home_page_add_to_album_success": "Added {added} assets to album {album}.",
|
||||
"library_page_albums": "Albums",
|
||||
"library_page_new_album": "New album",
|
||||
"login_form_button_text": "Iniciar Sesión",
|
||||
"login_form_email_hint": "tucorreo@correo.com",
|
||||
"login_form_endpoint_hint": "http://tu-ip-de-servidor:puerto/api",
|
||||
@@ -62,33 +120,71 @@
|
||||
"login_form_err_invalid_email": "Correo electrónico no válido",
|
||||
"login_form_err_leading_whitespace": "Espacio en blanco inicial",
|
||||
"login_form_err_trailing_whitespace": "Espacio en blanco al final",
|
||||
"login_form_failed_get_oauth_server_config": "Error logging using OAuth, check server URL",
|
||||
"login_form_failed_get_oauth_server_disable": "OAuth feature is not available on this server",
|
||||
"login_form_failed_login": "Error logging you in, check server URL, email and password",
|
||||
"login_form_label_email": "Correo",
|
||||
"login_form_label_password": "Contraseña",
|
||||
"login_form_password_hint": "contraseña",
|
||||
"login_form_save_login": "Mantener la sesión iniciada",
|
||||
"monthly_title_text_date_format": "MMMM y",
|
||||
"profile_drawer_app_logs": "Logs",
|
||||
"profile_drawer_client_server_up_to_date": "El Cliente y el Servidor están actualizados",
|
||||
"profile_drawer_settings": "Settings",
|
||||
"profile_drawer_sign_out": "Cerrar Sesión",
|
||||
"search_bar_hint": "Busca tus fotos",
|
||||
"search_page_no_objects": "No Objects Info Available",
|
||||
"search_page_no_places": "No hay información de lugares disponibles",
|
||||
"search_page_places": "Lugares",
|
||||
"search_page_things": "Cosas",
|
||||
"search_result_page_new_search_hint": "Nueva Busqueda",
|
||||
"select_additional_user_for_sharing_page_suggestions": "Sugerencias",
|
||||
"select_user_for_sharing_page_err_album": "Fallo al crear el álbum",
|
||||
"select_user_for_sharing_page_share_suggestions": "Suggestions",
|
||||
"setting_image_viewer_help": "The detail viewer loads the small thumbnail first, then loads the medium-size preview (if enabled), finally loads the original (if enabled).",
|
||||
"setting_image_viewer_original_subtitle": "Enable to load the original full-resolution image (large!). Disable to reduce data usage (both network and on device cache).",
|
||||
"setting_image_viewer_original_title": "Load original image",
|
||||
"setting_image_viewer_preview_subtitle": "Enable to load a medium-resolution image. Disable to either directly load the original or only use the thumbnail.",
|
||||
"setting_image_viewer_preview_title": "Load preview image",
|
||||
"setting_notifications_notify_failures_grace_period": "Notify background backup failures: {}",
|
||||
"setting_notifications_notify_hours": "{} hours",
|
||||
"setting_notifications_notify_immediately": "immediately",
|
||||
"setting_notifications_notify_minutes": "{} minutes",
|
||||
"setting_notifications_notify_never": "never",
|
||||
"setting_notifications_notify_seconds": "{} seconds",
|
||||
"setting_notifications_single_progress_subtitle": "Detailed upload progress information per asset",
|
||||
"setting_notifications_single_progress_title": "Show background backup detail progress",
|
||||
"setting_notifications_subtitle": "Adjust your notification preferences",
|
||||
"setting_notifications_title": "Notifications",
|
||||
"setting_notifications_total_progress_subtitle": "Overall upload progress (done/total assets)",
|
||||
"setting_notifications_total_progress_title": "Show background backup total progress",
|
||||
"setting_pages_app_bar_settings": "Settings",
|
||||
"settings_require_restart": "Please restart Immich to apply this setting",
|
||||
"share_add": "Añadir",
|
||||
"share_add_photos": "Añadir fotos",
|
||||
"share_add_title": "Añadir un título",
|
||||
"share_create_album": "Crear álbum",
|
||||
"share_dialog_preparing": "Preparing...",
|
||||
"share_invite": "Invitar al álbum",
|
||||
"sharing_page_album": "Álbumes compartidos",
|
||||
"sharing_page_description": "Crea álbumes compartidos para compartir fotos y vídeos con las personas de tu red.",
|
||||
"sharing_page_empty_list": "LISTA VACIA",
|
||||
"sharing_silver_appbar_create_shared_album": "Crear un álbum compartido",
|
||||
"sharing_silver_appbar_share_partner": "Compartir con el compañero",
|
||||
"tab_controller_nav_library": "Library",
|
||||
"tab_controller_nav_photos": "Fotos",
|
||||
"tab_controller_nav_search": "Buscar",
|
||||
"tab_controller_nav_sharing": "Compartiendo",
|
||||
"theme_setting_asset_list_storage_indicator_title": "Show storage indicator on asset tiles",
|
||||
"theme_setting_asset_list_tiles_per_row_title": "Number of assets per row ({})",
|
||||
"theme_setting_dark_mode_switch": "Dark mode",
|
||||
"theme_setting_image_viewer_quality_subtitle": "Adjust the quality of the detail image viewer",
|
||||
"theme_setting_image_viewer_quality_title": "Image viewer quality",
|
||||
"theme_setting_system_theme_switch": "Automatic (Follow system setting)",
|
||||
"theme_setting_theme_subtitle": "Choose the app's theme setting",
|
||||
"theme_setting_theme_title": "Theme",
|
||||
"theme_setting_three_stage_loading_subtitle": "Three-stage loading might increase the loading performance but causes significantly higher network load",
|
||||
"theme_setting_three_stage_loading_title": "Enable three-stage loading",
|
||||
"version_announcement_overlay_ack": "Reconocer",
|
||||
"version_announcement_overlay_release_notes": "notas de versión",
|
||||
"version_announcement_overlay_text_1": "Hola amigo, hay una nueva versión de",
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
{
|
||||
"album_info_card_backup_album_excluded": "JÄTETTY POIS",
|
||||
"album_info_card_backup_album_included": "SISÄLLYTETTY",
|
||||
"album_thumbnail_card_item": "1 kohde",
|
||||
"album_thumbnail_card_items": "{} kohdetta",
|
||||
"album_thumbnail_card_shared": "Jaettu",
|
||||
"album_viewer_appbar_share_delete": "Poista albumi",
|
||||
"album_viewer_appbar_share_err_delete": "Albumin poistaminen epäonnistui",
|
||||
"album_viewer_appbar_share_err_leave": "Albumista poistuminen epäonnistui",
|
||||
@@ -9,6 +12,8 @@
|
||||
"album_viewer_appbar_share_leave": "Poistu albumista",
|
||||
"album_viewer_appbar_share_remove": "Poista albumista",
|
||||
"album_viewer_page_share_add_users": "Lisää käyttäjiä",
|
||||
"asset_list_settings_subtitle": "Kuvaruudukon asettelu",
|
||||
"asset_list_settings_title": "Kuvaruudukko",
|
||||
"backup_album_selection_page_albums_device": "Laitteen albumit ({})",
|
||||
"backup_album_selection_page_albums_tap": "Napauta sisällyttääksesi, kaksoisnapauta jättääksesi pois",
|
||||
"backup_album_selection_page_assets_scatter": "Kohteet voivat olla hajaantuneina useisiin albumeihin. Albumeita voidaan sisällyttää varmuuskopiointiin tai jättää siitä pois.",
|
||||
@@ -16,7 +21,27 @@
|
||||
"backup_album_selection_page_selection_info": "Valintatiedot",
|
||||
"backup_album_selection_page_total_assets": "Uniikkeja kohteita yhteensä",
|
||||
"backup_all": "Kaikki",
|
||||
"backup_background_service_backup_failed_message": "Kohteiden varmuuskopiointi epäonnistui. Yritetään uudelleen...",
|
||||
"backup_background_service_connection_failed_message": "Palvelimeen ei saatu yhteyttä. Yritetään uudelleen...",
|
||||
"backup_background_service_current_upload_notification": "Lähetetään {}",
|
||||
"backup_background_service_default_notification": "Tarkistetaan uusia kohteita...",
|
||||
"backup_background_service_error_title": "Virhe varmuuskopioinnissa",
|
||||
"backup_background_service_in_progress_notification": "Varmuuskopioidaan kohteita...",
|
||||
"backup_background_service_upload_failure_notification": "Lähetys palvelimelle epäonnistui {}",
|
||||
"backup_controller_page_albums": "Varmuuskopioi albumit",
|
||||
"backup_controller_page_background_battery_info_link": "Näytä minulle miten",
|
||||
"backup_controller_page_background_battery_info_message": "Kytke pois päältä kaikki Immichin taustatyöskentelyyn liittyvät akun optimoinnit, jotta varmistat taustavarmuuskopioinnin parhaan mahdollisen toiminnan.\n\nKoska tämä on laitekohtaista, tarkista tarvittavat toimet laitevalmistajan ohjeista.",
|
||||
"backup_controller_page_background_battery_info_ok": "OK",
|
||||
"backup_controller_page_background_battery_info_title": "Akun optimointi",
|
||||
"backup_controller_page_background_charging": "Vain laitteen ollessa kytkettynä laturiin",
|
||||
"backup_controller_page_background_configure_error": "Taustapalvelun asettaminen epäonnistui",
|
||||
"backup_controller_page_background_delay": "Delay new assets backup: {}",
|
||||
"backup_controller_page_background_description": "Kytke taustapalvelu päälle varmuuskopioidaksesi uudet kohteet automaattisesti, ilman sovelluksen avaamista",
|
||||
"backup_controller_page_background_is_off": "Automaattinen varmuuskopiointi taustalla on pois päältä",
|
||||
"backup_controller_page_background_is_on": "Automaattinen varmuuskopiointi taustalla on päällä",
|
||||
"backup_controller_page_background_turn_off": "Kytke taustapalvelu pois päältä",
|
||||
"backup_controller_page_background_turn_on": "Kytke taustapalvelu päälle",
|
||||
"backup_controller_page_background_wifi": "Vain WiFi-verkossa",
|
||||
"backup_controller_page_backup": "Varmuuskopioitu",
|
||||
"backup_controller_page_backup_selected": "Valittu:",
|
||||
"backup_controller_page_backup_sub": "Varmuuskopioidut kuvat ja videot",
|
||||
@@ -45,10 +70,33 @@
|
||||
"backup_controller_page_uploading_file_info": "Tiedostojen lähetystiedot",
|
||||
"backup_err_only_album": "Vähintään yhden albumin tulee olla valittuna",
|
||||
"backup_info_card_assets": "kohdetta",
|
||||
"cache_settings_album_thumbnails": "Kirjastosivun esikatselukuvat ({} kohdetta)",
|
||||
"cache_settings_clear_cache_button": "Tyhjennä välimuisti",
|
||||
"cache_settings_clear_cache_button_title": "Tyhjennä sovelluksen välimuisti. Tämä vaikuttaa merkittävästi sovelluksen suorituskykyyn, kunnes välimuisti on rakennettu uudelleen.",
|
||||
"cache_settings_image_cache_size": "Kuvien välimuistin koko ({} kohdetta)",
|
||||
"cache_settings_statistics_album": "Kirjaston esikatselukuvat",
|
||||
"cache_settings_statistics_assets": "{} kohdetta ({})",
|
||||
"cache_settings_statistics_full": "Täysikokoiset kuvat",
|
||||
"cache_settings_statistics_shared": "Jaettujen albumien esikatselukuvat",
|
||||
"cache_settings_statistics_thumbnail": "Esikatselukuvat",
|
||||
"cache_settings_statistics_title": "Välimuistin käyttö",
|
||||
"cache_settings_subtitle": "Hallitse Immich-mobiilisovelluksen välimuistin käyttöä",
|
||||
"cache_settings_thumbnail_size": "Esikatselukuvien välimuistin koko ({} kohdetta)",
|
||||
"cache_settings_title": "Välimuistin asetukset",
|
||||
"control_bottom_app_bar_add_to_album": "Add to album",
|
||||
"control_bottom_app_bar_album_info": "{} items",
|
||||
"control_bottom_app_bar_album_info_shared": "{} items · Shared",
|
||||
"control_bottom_app_bar_create_new_album": "Create new album",
|
||||
"control_bottom_app_bar_delete": "Poista",
|
||||
"control_bottom_app_bar_share": "Jaa",
|
||||
"create_album_page_untitled": "Nimetön",
|
||||
"create_shared_album_page_create": "Luo",
|
||||
"create_shared_album_page_share": "Jaa",
|
||||
"create_shared_album_page_share_add_assets": "LISÄÄ KOHTEITA",
|
||||
"create_shared_album_page_share_select_photos": "Valitse kuvat",
|
||||
"daily_title_text_date": "E, MMM dd",
|
||||
"daily_title_text_date_year": "E, MMM dd, yyyy",
|
||||
"date_format": "E, LLL d, y • h:mm a",
|
||||
"delete_dialog_alert": "Nämä kohteet poistetaan pysyvästi Immich:stä ja laitteeltasi",
|
||||
"delete_dialog_cancel": "Peruuta",
|
||||
"delete_dialog_ok": "Poista",
|
||||
@@ -56,6 +104,14 @@
|
||||
"exif_bottom_sheet_description": "Lisää kuvaus…",
|
||||
"exif_bottom_sheet_details": "TIEDOT",
|
||||
"exif_bottom_sheet_location": "SIJAINTI",
|
||||
"experimental_settings_new_asset_list_subtitle": "Työn alla",
|
||||
"experimental_settings_new_asset_list_title": "Ota käyttöön kokeellinen kuvaruudukko",
|
||||
"experimental_settings_subtitle": "Käyttö omalla vastuulla!",
|
||||
"experimental_settings_title": "Kokeellinen",
|
||||
"home_page_add_to_album_conflicts": "Added {added} assets to album {album}. {failed} assets are already in the album.",
|
||||
"home_page_add_to_album_success": "Added {added} assets to album {album}.",
|
||||
"library_page_albums": "Albumit",
|
||||
"library_page_new_album": "Uusi albumi",
|
||||
"login_form_button_text": "Kirjaudu",
|
||||
"login_form_email_hint": "sahkopostisi@esimerkki.fi",
|
||||
"login_form_endpoint_hint": "http://palvelimesi-osoite:portti/api",
|
||||
@@ -64,12 +120,17 @@
|
||||
"login_form_err_invalid_email": "Virheellinen sähköpostiosoite",
|
||||
"login_form_err_leading_whitespace": "Alussa välilyönti",
|
||||
"login_form_err_trailing_whitespace": "Lopussa välilyönti",
|
||||
"login_form_failed_get_oauth_server_config": "Error logging using OAuth, check server URL",
|
||||
"login_form_failed_get_oauth_server_disable": "OAuth feature is not available on this server",
|
||||
"login_form_failed_login": "Virhe kirjautumisessa. Tarkista palvelimen URL, sähköpostiosoite ja salasana.",
|
||||
"login_form_label_email": "Sähköposti",
|
||||
"login_form_label_password": "Salasana",
|
||||
"login_form_password_hint": "salasana",
|
||||
"login_form_save_login": "Pysy kirjautuneena",
|
||||
"monthly_title_text_date_format": "MMMM y",
|
||||
"profile_drawer_app_logs": "Logs",
|
||||
"profile_drawer_client_server_up_to_date": "Asiakassovellus ja palvelin ovat ajan tasalla",
|
||||
"profile_drawer_settings": "Asetukset",
|
||||
"profile_drawer_sign_out": "Kirjaudu ulos",
|
||||
"search_bar_hint": "Etsi kuvia",
|
||||
"search_page_no_objects": "Objektitietoja ei ole saatavilla",
|
||||
@@ -80,19 +141,50 @@
|
||||
"select_additional_user_for_sharing_page_suggestions": "Ehdotukset",
|
||||
"select_user_for_sharing_page_err_album": "Albumin luonti epäonnistui",
|
||||
"select_user_for_sharing_page_share_suggestions": "Ehdotukset",
|
||||
"setting_image_viewer_help": "The detail viewer loads the small thumbnail first, then loads the medium-size preview (if enabled), finally loads the original (if enabled).",
|
||||
"setting_image_viewer_original_subtitle": "Enable to load the original full-resolution image (large!). Disable to reduce data usage (both network and on device cache).",
|
||||
"setting_image_viewer_original_title": "Load original image",
|
||||
"setting_image_viewer_preview_subtitle": "Enable to load a medium-resolution image. Disable to either directly load the original or only use the thumbnail.",
|
||||
"setting_image_viewer_preview_title": "Load preview image",
|
||||
"setting_notifications_notify_failures_grace_period": "Ilmoita taustavarmuuskopioinnin epäonnistumisista: {}",
|
||||
"setting_notifications_notify_hours": "{} tunnin välein",
|
||||
"setting_notifications_notify_immediately": "heti",
|
||||
"setting_notifications_notify_minutes": "{} minuutin välein",
|
||||
"setting_notifications_notify_never": "ei koskaan",
|
||||
"setting_notifications_notify_seconds": "{} seconds",
|
||||
"setting_notifications_single_progress_subtitle": "Yksityiskohtainen tieto palvelimelle lähettämisen edistymisestä kohteittain",
|
||||
"setting_notifications_single_progress_title": "Näytä taustavarmuuskopioinnin eidstminen",
|
||||
"setting_notifications_subtitle": "Ilmoitusasetusten määrittely",
|
||||
"setting_notifications_title": "Ilmoitukset",
|
||||
"setting_notifications_total_progress_subtitle": "Lähetyksen yleinen edistyminen (kohteita lähetetty/yhteensä)",
|
||||
"setting_notifications_total_progress_title": "Näytä taustavarmuuskopioinnin kokonaisedistyminen",
|
||||
"setting_pages_app_bar_settings": "Asetukset",
|
||||
"settings_require_restart": "Käynnistä Immich uudelleen ottaaksesti tämän asetuksen käyttöön",
|
||||
"share_add": "Lisää",
|
||||
"share_add_photos": "Lisää kuvia",
|
||||
"share_add_title": "Lisää nimi",
|
||||
"share_create_album": "Luo albumi",
|
||||
"share_dialog_preparing": "Valmistellaan...",
|
||||
"share_invite": "Kutsu albumiin",
|
||||
"sharing_page_album": "Jaetut albumit",
|
||||
"sharing_page_description": "Luo jaettuja albumeja jakaaksesi kuvia ja videoita läheisillesi.",
|
||||
"sharing_page_empty_list": "TYHJÄ LISTA",
|
||||
"sharing_silver_appbar_create_shared_album": "Luo jaettu albumi",
|
||||
"sharing_silver_appbar_share_partner": "Jaa kumppanille",
|
||||
"tab_controller_nav_library": "Kirjasto",
|
||||
"tab_controller_nav_photos": "Kuvat",
|
||||
"tab_controller_nav_search": "Haku",
|
||||
"tab_controller_nav_sharing": "Jakaminen",
|
||||
"theme_setting_asset_list_storage_indicator_title": "Näytä tallennustilainidikaattori kohteiden kuvakkeissa",
|
||||
"theme_setting_asset_list_tiles_per_row_title": "Kohteiden määrä rivillä ({})",
|
||||
"theme_setting_dark_mode_switch": "Tumma teema",
|
||||
"theme_setting_image_viewer_quality_subtitle": "Säädä kuvien katselun laatua",
|
||||
"theme_setting_image_viewer_quality_title": "Kuvien katseluohjelman laatu",
|
||||
"theme_setting_system_theme_switch": "Automaattinen (seuraa järjestelmän asetusta)",
|
||||
"theme_setting_theme_subtitle": "Valitse sovelluksen teema-asetukset",
|
||||
"theme_setting_theme_title": "Teema",
|
||||
"theme_setting_three_stage_loading_subtitle": "Kolmivaiheinen lataaminen saattaa parantaa latauksen suorituskykyä, mutta lisää kaistankäyttöä huomattavasti.",
|
||||
"theme_setting_three_stage_loading_title": "Ota kolmivaiheinen lataus käyttöön",
|
||||
"version_announcement_overlay_ack": "Tiedostan",
|
||||
"version_announcement_overlay_release_notes": "julkaisutiedoissa",
|
||||
"version_announcement_overlay_text_1": "Hei, kaveri! Uusi palvelinversio on saatavilla sovelluksesta",
|
||||
|
||||
@@ -12,6 +12,8 @@
|
||||
"album_viewer_appbar_share_leave": "Quitter l'album",
|
||||
"album_viewer_appbar_share_remove": "Retirer de l'album",
|
||||
"album_viewer_page_share_add_users": "Ajouter des utilisateurs",
|
||||
"asset_list_settings_subtitle": "Paramètres de disposition de la grille de photos",
|
||||
"asset_list_settings_title": "Grille de photos",
|
||||
"backup_album_selection_page_albums_device": "Albums sur l'appareil ({})",
|
||||
"backup_album_selection_page_albums_tap": "Tapez pour inclure, tapez deux fois pour exclure",
|
||||
"backup_album_selection_page_assets_scatter": "Les éléments peuvent être répartis sur plusieurs albums. De ce fait, les albums peuvent être inclus ou exclus pendant le processus de sauvegarde.",
|
||||
@@ -19,7 +21,27 @@
|
||||
"backup_album_selection_page_selection_info": "Informations sur la sélection",
|
||||
"backup_album_selection_page_total_assets": "Total des éléments uniques",
|
||||
"backup_all": "Tout",
|
||||
"backup_background_service_backup_failed_message": "Échec de la sauvegarde des éléments. Nouvelle tentative...",
|
||||
"backup_background_service_connection_failed_message": "Impossible de se connecter au serveur. Nouvelle tentative...",
|
||||
"backup_background_service_current_upload_notification": "Transfert {}",
|
||||
"backup_background_service_default_notification": "Recherche de nouveaux éléments...",
|
||||
"backup_background_service_error_title": "Erreur de sauvegarde",
|
||||
"backup_background_service_in_progress_notification": "Sauvegarde de vos éléments...",
|
||||
"backup_background_service_upload_failure_notification": "Impossible de transférer {}",
|
||||
"backup_controller_page_albums": "Sauvegarder les albums",
|
||||
"backup_controller_page_background_battery_info_link": "Montrez-moi comment",
|
||||
"backup_controller_page_background_battery_info_message": "Pour une expérience optimale de la sauvegarde en arrière-plan, veuillez désactiver toute optimisation de la batterie limitant l'activité en arrière-plan pour Immich.\n\nÉtant donné que cela est spécifique à chaque appareil, veuillez consulter les informations requises pour le fabricant de votre appareil.",
|
||||
"backup_controller_page_background_battery_info_ok": "OK",
|
||||
"backup_controller_page_background_battery_info_title": "Optimisation de la batterie",
|
||||
"backup_controller_page_background_charging": "Seulement pendant la charge",
|
||||
"backup_controller_page_background_configure_error": "Échec de la configuration du service d'arrière-plan",
|
||||
"backup_controller_page_background_delay": "Delay new assets backup: {}",
|
||||
"backup_controller_page_background_description": "Activez le service d'arrière-plan pour sauvegarder automatiquement tous les nouveaux éléments sans avoir à ouvrir l'application.",
|
||||
"backup_controller_page_background_is_off": "La sauvegarde automatique en arrière-plan est désactivée",
|
||||
"backup_controller_page_background_is_on": "La sauvegarde automatique en arrière-plan est activée",
|
||||
"backup_controller_page_background_turn_off": "Désactiver le service d'arrière-plan",
|
||||
"backup_controller_page_background_turn_on": "Activer le service d'arrière-plan",
|
||||
"backup_controller_page_background_wifi": "Uniquement en WiFi",
|
||||
"backup_controller_page_backup": "Sauvegardé",
|
||||
"backup_controller_page_backup_selected": "Sélectionné : ",
|
||||
"backup_controller_page_backup_sub": "Photos et vidéos sauvegardées",
|
||||
@@ -45,9 +67,26 @@
|
||||
"backup_controller_page_total_sub": "Toutes les photos et vidéos uniques des albums sélectionnés",
|
||||
"backup_controller_page_turn_off": "Désactiver la sauvegarde",
|
||||
"backup_controller_page_turn_on": "Activer la sauvegarde",
|
||||
"backup_controller_page_uploading_file_info": "Envoi d'informations sur le fichier",
|
||||
"backup_controller_page_uploading_file_info": "Transfert des informations du fichier",
|
||||
"backup_err_only_album": "Impossible de retirer le seul album",
|
||||
"backup_info_card_assets": "éléments",
|
||||
"cache_settings_album_thumbnails": "Miniatures de la page bibliothèque ({} éléments)",
|
||||
"cache_settings_clear_cache_button": "Effacer le cache",
|
||||
"cache_settings_clear_cache_button_title": "Efface le cache de l'application. Cela aura un impact significatif sur les performances de l'application jusqu'à ce que le cache soit reconstruit.",
|
||||
"cache_settings_image_cache_size": "Taille du cache des images ({} éléments)",
|
||||
"cache_settings_statistics_album": "Miniatures de la bibliothèque",
|
||||
"cache_settings_statistics_assets": "{} éléments ({})",
|
||||
"cache_settings_statistics_full": "Images complètes",
|
||||
"cache_settings_statistics_shared": "Miniatures d'albums partagés",
|
||||
"cache_settings_statistics_thumbnail": "Miniatures",
|
||||
"cache_settings_statistics_title": "Utilisation du cache",
|
||||
"cache_settings_subtitle": "Contrôler le comportement de mise en cache de l'application mobile Immich",
|
||||
"cache_settings_thumbnail_size": "Taille du cache des miniatures ({} éléments)",
|
||||
"cache_settings_title": "Paramètres de mise en cache",
|
||||
"control_bottom_app_bar_add_to_album": "Add to album",
|
||||
"control_bottom_app_bar_album_info": "{} items",
|
||||
"control_bottom_app_bar_album_info_shared": "{} items · Shared",
|
||||
"control_bottom_app_bar_create_new_album": "Create new album",
|
||||
"control_bottom_app_bar_delete": "Supprimer",
|
||||
"control_bottom_app_bar_share": "Partager",
|
||||
"create_album_page_untitled": "Sans titre",
|
||||
@@ -65,6 +104,12 @@
|
||||
"exif_bottom_sheet_description": "Ajouter une description...",
|
||||
"exif_bottom_sheet_details": "DÉTAILS",
|
||||
"exif_bottom_sheet_location": "LOCALISATION",
|
||||
"experimental_settings_new_asset_list_subtitle": "En cours de développement",
|
||||
"experimental_settings_new_asset_list_title": "Activez la grille de photos expérimentale",
|
||||
"experimental_settings_subtitle": "Utilisez à vos dépends !",
|
||||
"experimental_settings_title": "Expérimental",
|
||||
"home_page_add_to_album_conflicts": "Added {added} assets to album {album}. {failed} assets are already in the album.",
|
||||
"home_page_add_to_album_success": "Added {added} assets to album {album}.",
|
||||
"library_page_albums": "Albums",
|
||||
"library_page_new_album": "Nouvel album",
|
||||
"login_form_button_text": "Connexion",
|
||||
@@ -75,12 +120,15 @@
|
||||
"login_form_err_invalid_email": "Email invalide",
|
||||
"login_form_err_leading_whitespace": "Espace en début de ligne",
|
||||
"login_form_err_trailing_whitespace": "Espace de fin de ligne",
|
||||
"login_form_failed_get_oauth_server_config": "Error logging using OAuth, check server URL",
|
||||
"login_form_failed_get_oauth_server_disable": "OAuth feature is not available on this server",
|
||||
"login_form_failed_login": "Erreur de connexion, vérifiez l'url du serveur, l'email et le mot de passe",
|
||||
"login_form_label_email": "Email",
|
||||
"login_form_label_password": "Mot de passe",
|
||||
"login_form_password_hint": "mot de passe",
|
||||
"login_form_save_login": "Rester connecté",
|
||||
"monthly_title_text_date_format": "MMMM y",
|
||||
"profile_drawer_app_logs": "Logs",
|
||||
"profile_drawer_client_server_up_to_date": "Le client et le serveur sont à jour",
|
||||
"profile_drawer_settings": "Paramètres",
|
||||
"profile_drawer_sign_out": "Se déconnecter",
|
||||
@@ -93,6 +141,25 @@
|
||||
"select_additional_user_for_sharing_page_suggestions": "Suggestions",
|
||||
"select_user_for_sharing_page_err_album": "Échec de la création de l'album",
|
||||
"select_user_for_sharing_page_share_suggestions": "Suggestions",
|
||||
"setting_image_viewer_help": "The detail viewer loads the small thumbnail first, then loads the medium-size preview (if enabled), finally loads the original (if enabled).",
|
||||
"setting_image_viewer_original_subtitle": "Enable to load the original full-resolution image (large!). Disable to reduce data usage (both network and on device cache).",
|
||||
"setting_image_viewer_original_title": "Load original image",
|
||||
"setting_image_viewer_preview_subtitle": "Enable to load a medium-resolution image. Disable to either directly load the original or only use the thumbnail.",
|
||||
"setting_image_viewer_preview_title": "Load preview image",
|
||||
"setting_notifications_notify_failures_grace_period": "Notifier les échecs de la sauvegarde en arrière-plan : {}",
|
||||
"setting_notifications_notify_hours": "{} heures",
|
||||
"setting_notifications_notify_immediately": "immédiatement",
|
||||
"setting_notifications_notify_minutes": "{} minutes",
|
||||
"setting_notifications_notify_never": "jamais",
|
||||
"setting_notifications_notify_seconds": "{} seconds",
|
||||
"setting_notifications_single_progress_subtitle": "Informations détaillées sur la progression du transfert par élément",
|
||||
"setting_notifications_single_progress_title": "Afficher la progression du détail de la sauvegarde en arrière-plan",
|
||||
"setting_notifications_subtitle": "Ajustez vos préférences de notification",
|
||||
"setting_notifications_title": "Notifications",
|
||||
"setting_notifications_total_progress_subtitle": "Progrès global du transfert (effectué/total des éléments)",
|
||||
"setting_notifications_total_progress_title": "Afficher la progression totale de la sauvegarde en arrière-plan",
|
||||
"setting_pages_app_bar_settings": "Paramètres",
|
||||
"settings_require_restart": "Veuillez redémarrer Immich pour appliquer ce paramètre",
|
||||
"share_add": "Ajouter",
|
||||
"share_add_photos": "Ajouter des photos",
|
||||
"share_add_title": "Ajouter un titre",
|
||||
@@ -108,6 +175,16 @@
|
||||
"tab_controller_nav_photos": "Photos",
|
||||
"tab_controller_nav_search": "Recherche",
|
||||
"tab_controller_nav_sharing": "Partage",
|
||||
"theme_setting_asset_list_storage_indicator_title": "Afficher l'indicateur de stockage sur les tuiles des éléments",
|
||||
"theme_setting_asset_list_tiles_per_row_title": "Nombre d'éléments par ligne ({})",
|
||||
"theme_setting_dark_mode_switch": "Mode sombre",
|
||||
"theme_setting_image_viewer_quality_subtitle": "Ajustez la qualité de la visionneuse d'images détaillées",
|
||||
"theme_setting_image_viewer_quality_title": "Qualité de la visualisation des images",
|
||||
"theme_setting_system_theme_switch": "Automatique (suivre les paramètres du système)",
|
||||
"theme_setting_theme_subtitle": "Choisissez le thème de l'application",
|
||||
"theme_setting_theme_title": "Thème",
|
||||
"theme_setting_three_stage_loading_subtitle": "Le chargement en trois étapes peut améliorer les performances de chargement, mais entraîne une augmentation significative de la charge du réseau.",
|
||||
"theme_setting_three_stage_loading_title": "Activer le chargement en trois étapes",
|
||||
"version_announcement_overlay_ack": "Confirmer",
|
||||
"version_announcement_overlay_release_notes": "notes de mise à jour",
|
||||
"version_announcement_overlay_text_1": "Bonjour, une nouvelle version de",
|
||||
|
||||
@@ -5,10 +5,10 @@
|
||||
"album_thumbnail_card_items": "{} elementi",
|
||||
"album_thumbnail_card_shared": "Condiviso",
|
||||
"album_viewer_appbar_share_delete": "Elimina album ",
|
||||
"album_viewer_appbar_share_err_delete": "Errore nel cancellare l'album ",
|
||||
"album_viewer_appbar_share_err_leave": "Errore nel lasciare l'album ",
|
||||
"album_viewer_appbar_share_err_delete": "Impossibile cancellare l'album ",
|
||||
"album_viewer_appbar_share_err_leave": "Impossibile lasciare l'album ",
|
||||
"album_viewer_appbar_share_err_remove": "Ci sono problemi nel rimuovere oggetti dall'album ",
|
||||
"album_viewer_appbar_share_err_title": "Errore nel cambiare il titolo dell'album ",
|
||||
"album_viewer_appbar_share_err_title": "Impossibile cambiare il titolo dell'album ",
|
||||
"album_viewer_appbar_share_leave": "Lascia album",
|
||||
"album_viewer_appbar_share_remove": "Rimuovere dall'album ",
|
||||
"album_viewer_page_share_add_users": "Aggiungi utenti",
|
||||
@@ -21,22 +21,23 @@
|
||||
"backup_album_selection_page_selection_info": "Informazioni sulla selezione ",
|
||||
"backup_album_selection_page_total_assets": "Numero totale di oggetti unici",
|
||||
"backup_all": "Tutti",
|
||||
"backup_background_service_backup_failed_message": "Impossibile caricare contenuti. Nuovo tentativo…",
|
||||
"backup_background_service_connection_failed_message": "Impossibile connettersi al server. Nuovo tentativo…",
|
||||
"backup_background_service_backup_failed_message": "Impossibile caricare i contenuti. Riprovo…",
|
||||
"backup_background_service_connection_failed_message": "Impossibile connettersi al server. Riprovo…",
|
||||
"backup_background_service_current_upload_notification": "Caricamento {}",
|
||||
"backup_background_service_default_notification": "Verifica di nuovi contenuti…",
|
||||
"backup_background_service_default_notification": "Ricerca di nuovi contenuti…",
|
||||
"backup_background_service_error_title": "Errore di Backup",
|
||||
"backup_background_service_in_progress_notification": "Backing dei tuoi contenuti…",
|
||||
"backup_background_service_upload_failure_notification": "Impossibile caricare {}",
|
||||
"backup_controller_page_albums": "Backup Album",
|
||||
"backup_controller_page_background_battery_info_link": "Mostrami come",
|
||||
"backup_controller_page_background_battery_info_message": "Per una migliore esperienza di backup, disabilita le ottimisazioni della batteria per l'app Immich.\n\nDal momento che è una funzionalità specifica del dispositivo, per favore consulta il manuale del produttore.",
|
||||
"backup_controller_page_background_battery_info_message": "Per una migliore esperienza di backup, disabilita le ottimizzazioni della batteria per l'app Immich.\n\nDal momento che è una funzionalità specifica del dispositivo, per favore consulta il manuale del produttore.",
|
||||
"backup_controller_page_background_battery_info_ok": "OK",
|
||||
"backup_controller_page_background_battery_info_title": "Ottimizzazioni batteria",
|
||||
"backup_controller_page_background_charging": "Solo durante la ricarica",
|
||||
"backup_controller_page_background_configure_error": "Impossibile configurare i servizi in background",
|
||||
"backup_controller_page_background_description": "Abilita i servizi in background per sincronizzare tutti i nuovi contenuti senza la necessità di aprire l'app",
|
||||
"backup_controller_page_background_is_off": "Backup automatico spento",
|
||||
"backup_controller_page_background_delay": "Ritarda il backup di nuovi elementi: {}",
|
||||
"backup_controller_page_background_description": "Abilita i servizi in background per fare il backup di tutti i nuovi contenuti senza la necessità di aprire l'app",
|
||||
"backup_controller_page_background_is_off": "Backup automatico disattivato",
|
||||
"backup_controller_page_background_is_on": "Backup automatico attivo",
|
||||
"backup_controller_page_background_turn_off": "Disabilita servizi in background",
|
||||
"backup_controller_page_background_turn_on": "Abilita servizi in background",
|
||||
@@ -66,12 +67,12 @@
|
||||
"backup_controller_page_total_sub": "Tutte le foto e i video unici caricati dagli album selezionati ",
|
||||
"backup_controller_page_turn_off": "Disattiva backup",
|
||||
"backup_controller_page_turn_on": "Attiva backup ",
|
||||
"backup_controller_page_uploading_file_info": "Info sul file caricato",
|
||||
"backup_controller_page_uploading_file_info": "Caricando informazioni sul file",
|
||||
"backup_err_only_album": "Non è possibile rimuovere l'unico album",
|
||||
"backup_info_card_assets": "oggetti ",
|
||||
"cache_settings_album_thumbnails": "Anteprime pagine librerie ({} assets)",
|
||||
"cache_settings_clear_cache_button": "Cancella cache",
|
||||
"cache_settings_clear_cache_button_title": "Cancella cache app. Questo impatterà sulle prestazioni applicative fino a quando la cache non sarà rigenerata.",
|
||||
"cache_settings_clear_cache_button_title": "Cancella la cache dell'app. Questo impatterà significativamente le prestazioni dell''app fino a quando la cache non sarà rigenerata.",
|
||||
"cache_settings_image_cache_size": "Dimensione cache foto ({} assets)",
|
||||
"cache_settings_statistics_album": "Anteprime librerie",
|
||||
"cache_settings_statistics_assets": "{} contenuti ({})",
|
||||
@@ -79,9 +80,13 @@
|
||||
"cache_settings_statistics_shared": "Anteprime album condivisi",
|
||||
"cache_settings_statistics_thumbnail": "Anteprime",
|
||||
"cache_settings_statistics_title": "Uso della cache",
|
||||
"cache_settings_subtitle": "Controlla il comportamento della cache",
|
||||
"cache_settings_subtitle": "Controlla il comportamento della cache dell'applicazione mobile immich",
|
||||
"cache_settings_thumbnail_size": "Dimensione cache anteprime ({} assets)",
|
||||
"cache_settings_title": "Impostazioni della Cache",
|
||||
"control_bottom_app_bar_add_to_album": "Aggiungi all'album",
|
||||
"control_bottom_app_bar_album_info": "{} elementi",
|
||||
"control_bottom_app_bar_album_info_shared": "{} elementi · Condivisi",
|
||||
"control_bottom_app_bar_create_new_album": "Crea nuovo album",
|
||||
"control_bottom_app_bar_delete": "Elimina",
|
||||
"control_bottom_app_bar_share": "Condividi",
|
||||
"create_album_page_untitled": "Senza titolo",
|
||||
@@ -99,22 +104,31 @@
|
||||
"exif_bottom_sheet_description": "Aggiungi una descrizione...",
|
||||
"exif_bottom_sheet_details": "DETTAGLI",
|
||||
"exif_bottom_sheet_location": "POSIZIONE",
|
||||
"experimental_settings_new_asset_list_subtitle": "Work in progress",
|
||||
"experimental_settings_new_asset_list_title": "Attiva griglia di foto sperimentale",
|
||||
"experimental_settings_subtitle": "Usalo a tuo rischio!",
|
||||
"experimental_settings_title": "Sperimentale",
|
||||
"home_page_add_to_album_conflicts": "Aggiunti {added} elementi all'album {album}. {failed} elementi erano già presenti nell'album.",
|
||||
"home_page_add_to_album_success": "Aggiunti {added} elementi all'album {album}",
|
||||
"library_page_albums": "Album",
|
||||
"library_page_new_album": "Nuovo Album",
|
||||
"login_form_button_text": "Login",
|
||||
"login_form_email_hint": "tuaemail@email.com",
|
||||
"login_form_endpoint_hint": "http://tuo-ip-del-server:port/api",
|
||||
"login_form_endpoint_hint": "http://ip-del-tuo-server:port/api",
|
||||
"login_form_endpoint_url": "Server Endpoint URL",
|
||||
"login_form_err_http": "Per favore specificare http:// o https://",
|
||||
"login_form_err_invalid_email": "Email non valida",
|
||||
"login_form_err_leading_whitespace": "Spazio bianco all'inizio ",
|
||||
"login_form_err_trailing_whitespace": "Spazio bianco alla fine",
|
||||
"login_form_err_leading_whitespace": "Whitespace all'inizio ",
|
||||
"login_form_err_trailing_whitespace": "Whitespace alla fine",
|
||||
"login_form_failed_get_oauth_server_config": "Errore di login usando OAuth, controlla l'URL del server",
|
||||
"login_form_failed_get_oauth_server_disable": "OAuth non è disponibile su questo server",
|
||||
"login_form_failed_login": "Errore nel login, controlla URL del server e le credenziali (email e password)",
|
||||
"login_form_label_email": "Email",
|
||||
"login_form_label_password": "Password",
|
||||
"login_form_password_hint": "password ",
|
||||
"login_form_save_login": "Rimani connesso ",
|
||||
"monthly_title_text_date_format": "MMMM y",
|
||||
"profile_drawer_app_logs": "Logs",
|
||||
"profile_drawer_client_server_up_to_date": "Client e server sono aggiornati",
|
||||
"profile_drawer_settings": "Impostazioni ",
|
||||
"profile_drawer_sign_out": "Logout",
|
||||
@@ -125,24 +139,35 @@
|
||||
"search_page_things": "Oggetti",
|
||||
"search_result_page_new_search_hint": "Nuova ricerca ",
|
||||
"select_additional_user_for_sharing_page_suggestions": "Suggerimenti ",
|
||||
"select_user_for_sharing_page_err_album": "Errore nel creare l'album ",
|
||||
"select_user_for_sharing_page_err_album": "Impossibile nel creare l'album ",
|
||||
"select_user_for_sharing_page_share_suggestions": "Suggerimenti",
|
||||
"setting_image_viewer_help": "Il visualizzatore dettagliato carica una piccola thumbnail per prima, per poi caricare un immagine di media grandezza (se abilitato). Ed infine carica l'originale (se abilitato).",
|
||||
"setting_image_viewer_original_subtitle": "Abilita per caricare l'immagine originale a risoluzione massima (grande!). Disabilita per ridurre l'utilizzo di banda (sia sul network che nella cache del dispositivo).",
|
||||
"setting_image_viewer_original_title": "Carica l'immagine originale",
|
||||
"setting_image_viewer_preview_subtitle": "Abilita per caricare un'immagine a risoluzione media.\nDisabilita per caricare direttamente l'immagine originale o usare la thumbnail.",
|
||||
"setting_image_viewer_preview_title": "Carica immagine di preview",
|
||||
"setting_notifications_notify_failures_grace_period": "Notifica caricamenti falliti in background: {}",
|
||||
"setting_notifications_notify_hours": "{} Ore",
|
||||
"setting_notifications_notify_immediately": "Immediatamente",
|
||||
"setting_notifications_notify_minutes": "{} Minuti",
|
||||
"setting_notifications_notify_never": "Mai",
|
||||
"setting_notifications_notify_hours": "{} ore",
|
||||
"setting_notifications_notify_immediately": "immediatamente",
|
||||
"setting_notifications_notify_minutes": "{} minuti",
|
||||
"setting_notifications_notify_never": "mai",
|
||||
"setting_notifications_notify_seconds": "{} secondi",
|
||||
"setting_notifications_single_progress_subtitle": "Informazioni dettagliate sul caricamento dell'immagine",
|
||||
"setting_notifications_single_progress_title": "Mostra dettagli del processo di backup in background",
|
||||
"setting_notifications_subtitle": "Cambia le impostazioni di notifica",
|
||||
"setting_notifications_title": "Notifiche",
|
||||
"setting_notifications_total_progress_subtitle": "Progresso di caricamento generale (eseguiti/totale)",
|
||||
"setting_notifications_total_progress_title": "Mostra il progresso di backup totale in background",
|
||||
"setting_pages_app_bar_settings": "Impostazioni",
|
||||
"settings_require_restart": "Si prega di riavviare Immich perché vengano applicate le impostazioni",
|
||||
"share_add": "Aggiungi",
|
||||
"share_add_photos": "Aggiungi foto",
|
||||
"share_add_title": "Aggiungi un titolo ",
|
||||
"share_create_album": "Crea album",
|
||||
"share_dialog_preparing": "Preparo…",
|
||||
"share_invite": "Invitare nell'album ",
|
||||
"share_invite": "Invita nell'album ",
|
||||
"sharing_page_album": "Album condivisi",
|
||||
"sharing_page_description": "Crea un album condiviso per condividere foto e video con persone nel tuo network",
|
||||
"sharing_page_description": "Crea un album condiviso per condividere foto e video con persone sul tuo network",
|
||||
"sharing_page_empty_list": "LISTA VUOTA",
|
||||
"sharing_silver_appbar_create_shared_album": "Crea album condiviso",
|
||||
"sharing_silver_appbar_share_partner": "Condividi con il partner",
|
||||
@@ -155,15 +180,15 @@
|
||||
"theme_setting_dark_mode_switch": "Dark mode",
|
||||
"theme_setting_image_viewer_quality_subtitle": "Cambia la qualità del dettaglio dell'immagine",
|
||||
"theme_setting_image_viewer_quality_title": "Qualità immagine",
|
||||
"theme_setting_system_theme_switch": "Automatico (Vai alle impostazioni di sistema)",
|
||||
"theme_setting_theme_subtitle": "Scegli un'impostazione per il tema",
|
||||
"theme_setting_system_theme_switch": "Automatico (Segue le impostazioni di sistema)",
|
||||
"theme_setting_theme_subtitle": "Scegli un'impostazione per il tema dell'app",
|
||||
"theme_setting_theme_title": "Tema",
|
||||
"theme_setting_three_stage_loading_subtitle": "Il caricamento in 3 stage aumenterà le performance di caricamento ma anche il consumo di banda",
|
||||
"theme_setting_three_stage_loading_subtitle": "Il caricamento a tre stage aumenterà le performance di caricamento ma anche il consumo di banda",
|
||||
"theme_setting_three_stage_loading_title": "Abilita il caricamento a tre stage",
|
||||
"version_announcement_overlay_ack": "Riconosci ",
|
||||
"version_announcement_overlay_ack": "Presa visione",
|
||||
"version_announcement_overlay_release_notes": "note di rilascio ",
|
||||
"version_announcement_overlay_text_1": "Ciao amico, c'è una nuova versione di",
|
||||
"version_announcement_overlay_text_2": "per favore prenditi il tuo tempo per controllare il",
|
||||
"version_announcement_overlay_text_3": "e verifica che il tuo docker-compose e il file .env siano aggiornati per impedire qualsiasi errore nella configurazione, specialmente se utilizzate WatchTower o altri strumenti per l'aggiornamento automatico delle immagini docker.",
|
||||
"version_announcement_overlay_title": "Nuova versione del server disponibile! \uD83C\uDF89"
|
||||
"version_announcement_overlay_text_1": "Ciao, c'è una nuova versione di",
|
||||
"version_announcement_overlay_text_2": "per favore prenditi il tuo tempo per visitare il",
|
||||
"version_announcement_overlay_text_3": "e verifica che il tuo docker-compose e il file .env siano aggiornati per impedire qualsiasi errore di configurazione, specialmente se utilizzate WatchTower o altri strumenti per l'aggiornamento automatico dell'applicativo",
|
||||
"version_announcement_overlay_title": "Nuova versione del server disponibile \uD83C\uDF89"
|
||||
}
|
||||
@@ -1,6 +1,9 @@
|
||||
{
|
||||
"album_info_card_backup_album_excluded": "除外",
|
||||
"album_info_card_backup_album_included": "選択",
|
||||
"album_info_card_backup_album_excluded": "除外中",
|
||||
"album_info_card_backup_album_included": "選択中",
|
||||
"album_thumbnail_card_item": "項目数: 1",
|
||||
"album_thumbnail_card_items": "項目数: {}",
|
||||
"album_thumbnail_card_shared": "共有済み",
|
||||
"album_viewer_appbar_share_delete": "アルバムを削除",
|
||||
"album_viewer_appbar_share_err_delete": "削除に失敗...",
|
||||
"album_viewer_appbar_share_err_leave": "退会に失敗...",
|
||||
@@ -9,17 +12,39 @@
|
||||
"album_viewer_appbar_share_leave": "アルバムから退会",
|
||||
"album_viewer_appbar_share_remove": "アルバムから除外",
|
||||
"album_viewer_page_share_add_users": "ユーザーを追加",
|
||||
"asset_list_settings_subtitle": "グリッドに関する設定",
|
||||
"asset_list_settings_title": "グリッド",
|
||||
"backup_album_selection_page_albums_device": "端末上のアルバム数は {} だよ",
|
||||
"backup_album_selection_page_albums_tap": "タップで選択、ダブルタップで除外だよ",
|
||||
"backup_album_selection_page_assets_scatter": "写真がいろんなアルバムに登録されてる事があるから、アルバムを含めたり除外したりしてどの写真を保存するか選択できるよ。",
|
||||
"backup_album_selection_page_assets_scatter": "同じ写真がいろんなアルバムに登録されてる事があるから、アルバムを含めたり除外したりしてどの写真を保存するか選択できるよ。",
|
||||
"backup_album_selection_page_select_albums": "アルバムを選択",
|
||||
"backup_album_selection_page_selection_info": "選択、又は除外されてるアルバム",
|
||||
"backup_album_selection_page_selection_info": "選択、又は除外されているアルバム",
|
||||
"backup_album_selection_page_total_assets": "選択されたアルバムの写真と動画の数",
|
||||
"backup_all": "全て",
|
||||
"backup_background_service_backup_failed_message": "アップロードに失敗しました。リトライ中",
|
||||
"backup_background_service_connection_failed_message": "サーバーに接続できません。リトライ中",
|
||||
"backup_background_service_current_upload_notification": " {} をアップロード中",
|
||||
"backup_background_service_default_notification": "新しい写真をチェックしています",
|
||||
"backup_background_service_error_title": "バックアップエラー",
|
||||
"backup_background_service_in_progress_notification": "バックアップ中",
|
||||
"backup_background_service_upload_failure_notification": "{} のアップロードに失敗",
|
||||
"backup_controller_page_albums": "アルバム",
|
||||
"backup_controller_page_backup": "バックアップ",
|
||||
"backup_controller_page_backup_selected": "選択されてる:",
|
||||
"backup_controller_page_backup_sub": "バックアップされた写真と動画の数だよ",
|
||||
"backup_controller_page_background_battery_info_link": "方法を見る",
|
||||
"backup_controller_page_background_battery_info_message": "バックグラウンドバックアップが正常に動作するためにImmichに適用されてるバッテリーの最適化と自動調整をオフにしてね。\n\n端末によって方法が変わるから各々調べてね",
|
||||
"backup_controller_page_background_battery_info_ok": "了解",
|
||||
"backup_controller_page_background_battery_info_title": "バッテリーの最適化",
|
||||
"backup_controller_page_background_charging": "充電中のみに行う",
|
||||
"backup_controller_page_background_configure_error": "バックグラウンドサービスの構築に失敗しました",
|
||||
"backup_controller_page_background_delay": "Delay new assets backup: {}",
|
||||
"backup_controller_page_background_description": "バックグラウンドバックアップをオンにしてアプリを開かなくても自動で画像をアップロードするようにします",
|
||||
"backup_controller_page_background_is_off": "自動バックグラウンドバックアップはオフになってます",
|
||||
"backup_controller_page_background_is_on": "自動バックグラウンドバックアップはオンになってます",
|
||||
"backup_controller_page_background_turn_off": "バックグラウンドサービスをオフにする",
|
||||
"backup_controller_page_background_turn_on": "バックグラウンドサービスをオンにする",
|
||||
"backup_controller_page_background_wifi": "WiFi接続中のみに行う",
|
||||
"backup_controller_page_backup": "バックアップ済み",
|
||||
"backup_controller_page_backup_selected": "選択済み:",
|
||||
"backup_controller_page_backup_sub": "バックアップされた写真と動画の数",
|
||||
"backup_controller_page_cancel": "キャンセルするよ",
|
||||
"backup_controller_page_created": "{} に作成されたよ",
|
||||
"backup_controller_page_desc_backup": "ONにすれば自動的に新しい写真などがバックアップされるようになるよ",
|
||||
@@ -29,29 +54,49 @@
|
||||
"backup_controller_page_id": "ID: {}",
|
||||
"backup_controller_page_info": "バックアップ情報",
|
||||
"backup_controller_page_none_selected": "何も選んでないよ",
|
||||
"backup_controller_page_remainder": "リマインダー",
|
||||
"backup_controller_page_remainder_sub": "残りの写真と動画の数だよ",
|
||||
"backup_controller_page_remainder": "残り",
|
||||
"backup_controller_page_remainder_sub": "残りの写真と動画の数",
|
||||
"backup_controller_page_select": "選択",
|
||||
"backup_controller_page_server_storage": "サーバーの容量",
|
||||
"backup_controller_page_start_backup": "バックアップを開始するよ",
|
||||
"backup_controller_page_status_off": "バックアップがOFFになってるよ",
|
||||
"backup_controller_page_status_on": "バックアップがONになってるよ",
|
||||
"backup_controller_page_storage_format": "{}中、 {}を使用中だよ",
|
||||
"backup_controller_page_start_backup": "バックアップを開始",
|
||||
"backup_controller_page_status_off": "バックアップがOFFだよ",
|
||||
"backup_controller_page_status_on": "バックアップがONだよ",
|
||||
"backup_controller_page_storage_format": "使用済み: {}/{}",
|
||||
"backup_controller_page_to_backup": "バックアップされるアルバム",
|
||||
"backup_controller_page_total": "トータル",
|
||||
"backup_controller_page_total_sub": "選択されたアルバムの写真と動画の数だよ",
|
||||
"backup_controller_page_total_sub": "選択されたアルバムの写真と動画の数",
|
||||
"backup_controller_page_turn_off": "バックアップOFF",
|
||||
"backup_controller_page_turn_on": "バックアップON",
|
||||
"backup_controller_page_uploading_file_info": "アップロードされてるファイルに関する情報",
|
||||
"backup_err_only_album": "唯一のアルバムを除外する事はできないよ",
|
||||
"backup_err_only_album": "唯一のアルバムを削除する事はできないよ",
|
||||
"backup_info_card_assets": "写真と動画",
|
||||
"cache_settings_album_thumbnails": "ライブラリのサムネイル ({}枚)",
|
||||
"cache_settings_clear_cache_button": "キャッシュをクリア",
|
||||
"cache_settings_clear_cache_button_title": "キャッシュを削除するけど、キャッシュを作り直すまでアプリのパフォーマンスが著しく低下するよ",
|
||||
"cache_settings_image_cache_size": "キャッシュのサイズ ({}枚) ",
|
||||
"cache_settings_statistics_album": "ライブラリのサムネイル",
|
||||
"cache_settings_statistics_assets": "{} 枚 ({}枚中)",
|
||||
"cache_settings_statistics_full": "フル画像",
|
||||
"cache_settings_statistics_shared": "共有アルバムのサムネイル",
|
||||
"cache_settings_statistics_thumbnail": "サムネイル",
|
||||
"cache_settings_statistics_title": "キャッシュ",
|
||||
"cache_settings_subtitle": "キャッシュの動作を変更できるよ",
|
||||
"cache_settings_thumbnail_size": "サムネイルのキャッシュのサイズ ({}枚)",
|
||||
"cache_settings_title": "キャッシュの設定",
|
||||
"control_bottom_app_bar_add_to_album": "Add to album",
|
||||
"control_bottom_app_bar_album_info": "{} items",
|
||||
"control_bottom_app_bar_album_info_shared": "{} items · Shared",
|
||||
"control_bottom_app_bar_create_new_album": "Create new album",
|
||||
"control_bottom_app_bar_delete": "削除",
|
||||
"control_bottom_app_bar_share": "共有",
|
||||
"create_album_page_untitled": "タイトル無し",
|
||||
"create_shared_album_page_create": "作成",
|
||||
"create_shared_album_page_share": "共有",
|
||||
"create_shared_album_page_share_add_assets": "写真や動画を追加",
|
||||
"create_shared_album_page_share_add_assets": "写真を追加",
|
||||
"create_shared_album_page_share_select_photos": "写真を選択",
|
||||
"daily_title_text_date": "E, MM月 dd日",
|
||||
"daily_title_text_date_year": "E, yyyy年 MM月 dd日",
|
||||
"date_format": "E, MM月 dd日 • hh時mm分",
|
||||
"daily_title_text_date": "MM月 DD日, EE",
|
||||
"daily_title_text_date_year": "yyyy年 MM月 DD日, EE",
|
||||
"date_format": "MM月 DD日, EE • hh時mm分",
|
||||
"delete_dialog_alert": "サーバーからも端末からも永久的に削除されるけど良いの?",
|
||||
"delete_dialog_cancel": "キャンセル",
|
||||
"delete_dialog_ok": "削除",
|
||||
@@ -59,6 +104,14 @@
|
||||
"exif_bottom_sheet_description": "概要を追加",
|
||||
"exif_bottom_sheet_details": "詳細な情報",
|
||||
"exif_bottom_sheet_location": "撮影地",
|
||||
"experimental_settings_new_asset_list_subtitle": "進行中",
|
||||
"experimental_settings_new_asset_list_title": "試験的なグリッドを有効",
|
||||
"experimental_settings_subtitle": "試験的だから自己責任でね",
|
||||
"experimental_settings_title": "試験的",
|
||||
"home_page_add_to_album_conflicts": "Added {added} assets to album {album}. {failed} assets are already in the album.",
|
||||
"home_page_add_to_album_success": "Added {added} assets to album {album}.",
|
||||
"library_page_albums": "アルバム",
|
||||
"library_page_new_album": "新しいアルバム",
|
||||
"login_form_button_text": "ログイン",
|
||||
"login_form_email_hint": "example@email.com",
|
||||
"login_form_endpoint_hint": "https://example.com:port/api",
|
||||
@@ -67,36 +120,71 @@
|
||||
"login_form_err_invalid_email": "メールアドレスが有効じゃないよ",
|
||||
"login_form_err_leading_whitespace": "最初に半角スペースが含まれてるよ",
|
||||
"login_form_err_trailing_whitespace": "最後に半角スペースが含まれてるよ",
|
||||
"login_form_failed_get_oauth_server_config": "Error logging using OAuth, check server URL",
|
||||
"login_form_failed_get_oauth_server_disable": "OAuth feature is not available on this server",
|
||||
"login_form_failed_login": "ログインエラー。サーバーのURL、メールアドレスとパスワードを再確認してね",
|
||||
"login_form_label_email": "メールアドレス",
|
||||
"login_form_label_password": "パスワード",
|
||||
"login_form_password_hint": "パスワード",
|
||||
"login_form_save_login": "ログインしたままにする",
|
||||
"monthly_title_text_date_format": "yyyy年 MM月",
|
||||
"profile_drawer_app_logs": "Logs",
|
||||
"profile_drawer_client_server_up_to_date": "サーバーとクライアント、両方最新バージョンだよ",
|
||||
"profile_drawer_settings": "設定",
|
||||
"profile_drawer_sign_out": "サインアウト",
|
||||
"search_bar_hint": "写真を検索",
|
||||
"search_page_no_objects": "被写体に関するデータがないよ",
|
||||
"search_page_no_places": "場所に関するデータがないよ",
|
||||
"search_page_no_objects": "被写体に関するデータがなし",
|
||||
"search_page_no_places": "場所に関するデータがなし",
|
||||
"search_page_places": "撮影地",
|
||||
"search_page_things": "カテゴリ",
|
||||
"search_result_page_new_search_hint": "検索",
|
||||
"select_additional_user_for_sharing_page_suggestions": "ユーザーリスト",
|
||||
"select_user_for_sharing_page_err_album": "アルバム作成に失敗...",
|
||||
"select_user_for_sharing_page_share_suggestions": "ユーザーの一覧だよ",
|
||||
"select_user_for_sharing_page_share_suggestions": "ユーザーの一覧",
|
||||
"setting_image_viewer_help": "The detail viewer loads the small thumbnail first, then loads the medium-size preview (if enabled), finally loads the original (if enabled).",
|
||||
"setting_image_viewer_original_subtitle": "Enable to load the original full-resolution image (large!). Disable to reduce data usage (both network and on device cache).",
|
||||
"setting_image_viewer_original_title": "Load original image",
|
||||
"setting_image_viewer_preview_subtitle": "Enable to load a medium-resolution image. Disable to either directly load the original or only use the thumbnail.",
|
||||
"setting_image_viewer_preview_title": "Load preview image",
|
||||
"setting_notifications_notify_failures_grace_period": "バックアップ失敗の通知: {}",
|
||||
"setting_notifications_notify_hours": "{}時間後",
|
||||
"setting_notifications_notify_immediately": "すぐに行う",
|
||||
"setting_notifications_notify_minutes": "{}分後",
|
||||
"setting_notifications_notify_never": "行わない",
|
||||
"setting_notifications_notify_seconds": "{} seconds",
|
||||
"setting_notifications_single_progress_subtitle": "アップロード中の写真の詳細",
|
||||
"setting_notifications_single_progress_title": "バックグランドバックアップの詳細を表示",
|
||||
"setting_notifications_subtitle": "通知設定を変更する",
|
||||
"setting_notifications_title": "通知",
|
||||
"setting_notifications_total_progress_subtitle": "アップロードの進行状況 (完了済み/全体) ",
|
||||
"setting_notifications_total_progress_title": "バックグラウンドバックアップの進行状況を表示",
|
||||
"setting_pages_app_bar_settings": "設定",
|
||||
"settings_require_restart": "設定の適用にImmichの再起動が必要だよ",
|
||||
"share_add": "追加",
|
||||
"share_add_photos": "写真を追加",
|
||||
"share_add_title": "タイトルを追加",
|
||||
"share_create_album": "アルバムを作成",
|
||||
"share_dialog_preparing": "準備中...ちょっと待ってね",
|
||||
"share_invite": "アルバムに参加",
|
||||
"sharing_page_album": "共有アルバム",
|
||||
"sharing_page_description": "共有アルバムを作成して同じネットワークにいる仲間に写真を共有してみよう!",
|
||||
"sharing_page_empty_list": "誰も居ないね ( T_T)\(^-^ ) ドンマイ",
|
||||
"sharing_page_description": "共有アルバムを作成して同じネットワークにいる人たちに写真を共有してみよう!",
|
||||
"sharing_page_empty_list": "共有アルバムが無いよ",
|
||||
"sharing_silver_appbar_create_shared_album": "共有アルバムを作成",
|
||||
"sharing_silver_appbar_share_partner": "パートナーと共有",
|
||||
"tab_controller_nav_library": "ライブラリ",
|
||||
"tab_controller_nav_photos": "写真",
|
||||
"tab_controller_nav_search": "検索",
|
||||
"tab_controller_nav_sharing": "共有",
|
||||
"theme_setting_asset_list_storage_indicator_title": "ストレージに関する情報を表示",
|
||||
"theme_setting_asset_list_tiles_per_row_title": "一列のの写真の数: {} ",
|
||||
"theme_setting_dark_mode_switch": "ダークモード",
|
||||
"theme_setting_image_viewer_quality_subtitle": "画像ビューワの画質の設定",
|
||||
"theme_setting_image_viewer_quality_title": "画像ビューワ",
|
||||
"theme_setting_system_theme_switch": "自動 (端末の設定を反映) ",
|
||||
"theme_setting_theme_subtitle": "アプリの見た目の設定",
|
||||
"theme_setting_theme_title": "テーマ",
|
||||
"theme_setting_three_stage_loading_subtitle": "三段階読み込みを有効にするとパフォーマンスが改善する可能性があるけど、データ使用量が凄く増えるよ",
|
||||
"theme_setting_three_stage_loading_title": "三段階読み込みをオンにする",
|
||||
"version_announcement_overlay_ack": "了解",
|
||||
"version_announcement_overlay_release_notes": "更新情報",
|
||||
"version_announcement_overlay_text_1": "こんにちは、又はこんばんは!新しい",
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
{
|
||||
"album_info_card_backup_album_excluded": "WYKLUCZONE",
|
||||
"album_info_card_backup_album_included": "WŁĄCZONE",
|
||||
"album_thumbnail_card_item": "1 pozycja",
|
||||
"album_thumbnail_card_items": "{} pozycje",
|
||||
"album_thumbnail_card_shared": "Udostępniony",
|
||||
"album_viewer_appbar_share_delete": "Usuń album",
|
||||
"album_viewer_appbar_share_err_delete": "Nie udało się usunąć albumu",
|
||||
"album_viewer_appbar_share_err_leave": "Nie udało się wyjść z albumu",
|
||||
@@ -9,6 +12,8 @@
|
||||
"album_viewer_appbar_share_leave": "Opuść album",
|
||||
"album_viewer_appbar_share_remove": "Usuń z albumu",
|
||||
"album_viewer_page_share_add_users": "Dodaj użytkowników",
|
||||
"asset_list_settings_subtitle": "Ustawienia układu siatki zdjęć",
|
||||
"asset_list_settings_title": "Siatka Zdjęć",
|
||||
"backup_album_selection_page_albums_device": "Albumy na urządzeniu ({})",
|
||||
"backup_album_selection_page_albums_tap": "Stuknij, aby włączyć, stuknij dwukrotnie, aby wykluczyć",
|
||||
"backup_album_selection_page_assets_scatter": "Pliki mogą być rozproszone w wielu albumach. Dzięki temu albumy mogą być włączane lub wyłączane podczas procesu tworzenia kopii zapasowej.",
|
||||
@@ -16,13 +21,33 @@
|
||||
"backup_album_selection_page_selection_info": "Info o wyborze",
|
||||
"backup_album_selection_page_total_assets": "Łącznie unikalnych plików",
|
||||
"backup_all": "Wszystkie",
|
||||
"backup_background_service_backup_failed_message": "Nie udało się wykonać kopii zapasowej zasobów. Próbuję ponownie...",
|
||||
"backup_background_service_connection_failed_message": "Nie udało się połączyć z serwerem. Próbuję ponownie...",
|
||||
"backup_background_service_current_upload_notification": "Wysyłanie {}",
|
||||
"backup_background_service_default_notification": "Sprawdzanie nowych zasobów...",
|
||||
"backup_background_service_error_title": "Błąd kopii zapasowej",
|
||||
"backup_background_service_in_progress_notification": "Tworzę kopię twoich zasobów...",
|
||||
"backup_background_service_upload_failure_notification": "Nie udało się przesłać {}",
|
||||
"backup_controller_page_albums": "Backup Albumów",
|
||||
"backup_controller_page_backup": "Backup",
|
||||
"backup_controller_page_background_battery_info_link": "Pokaż mi jak",
|
||||
"backup_controller_page_background_battery_info_message": "Aby uzyskać najlepsze rezultaty podczas tworzenia kopii zapasowej w tle, należy wyłączyć wszelkie optymalizacje baterii ograniczające aktywność w tle dla Immich w urządzeniu.\n\nPonieważ jest to zależne od urządzenia, proszę sprawdzić wymagane informacje dla producenta urządzenia.",
|
||||
"backup_controller_page_background_battery_info_ok": "OK",
|
||||
"backup_controller_page_background_battery_info_title": "Optymalizacja Baterii",
|
||||
"backup_controller_page_background_charging": "Tylko podczas ładowania",
|
||||
"backup_controller_page_background_configure_error": "Nie udało się skonfigurować usługi w tle",
|
||||
"backup_controller_page_background_delay": "Delay new assets backup: {}",
|
||||
"backup_controller_page_background_description": "Włącz usługę w tle, aby automatycznie tworzyć kopie zapasowe wszelkich nowych zasobów bez konieczności otwierania aplikacji",
|
||||
"backup_controller_page_background_is_off": "Automatyczna kopia zapasowa w tle jest wyłączona",
|
||||
"backup_controller_page_background_is_on": "Automatyczna kopia zapasowa w tle jest włączona",
|
||||
"backup_controller_page_background_turn_off": "Wyłącz usługę w tle",
|
||||
"backup_controller_page_background_turn_on": "Włącz usługę w tle",
|
||||
"backup_controller_page_background_wifi": "Tylko na WiFi",
|
||||
"backup_controller_page_backup": "Kopia Zapasowa",
|
||||
"backup_controller_page_backup_selected": "Zaznaczone: ",
|
||||
"backup_controller_page_backup_sub": "Tworzenie kopii zapasowych zdjęć i filmów",
|
||||
"backup_controller_page_cancel": "Anuluj",
|
||||
"backup_controller_page_created": "Utworzony na: {}",
|
||||
"backup_controller_page_desc_backup": "Włącz backup, aby automatycznie przesyłać nowe zasoby na serwer.",
|
||||
"backup_controller_page_desc_backup": "Włącz kopię zapasową, aby automatycznie przesyłać nowe zasoby na serwer.",
|
||||
"backup_controller_page_excluded": "Wykluczone: ",
|
||||
"backup_controller_page_failed": "Nieudane ({})",
|
||||
"backup_controller_page_filename": "Nazwa pliku: {} [{}]",
|
||||
@@ -33,21 +58,41 @@
|
||||
"backup_controller_page_remainder_sub": "Pozostałe zdjęcia i albumy do wykonania kopii zapasowej z wyboru",
|
||||
"backup_controller_page_select": "Zaznacz",
|
||||
"backup_controller_page_server_storage": "Pamięć Serwera",
|
||||
"backup_controller_page_start_backup": "Rozpocznij Backup",
|
||||
"backup_controller_page_status_off": "Backup jest wyłączony",
|
||||
"backup_controller_page_status_on": "Backup jest włączony",
|
||||
"backup_controller_page_start_backup": "Rozpocznij Kopię Zapasową",
|
||||
"backup_controller_page_status_off": "Kopia Zapasowa jest wyłaczona",
|
||||
"backup_controller_page_status_on": "Kopia Zapasowa jest włączona",
|
||||
"backup_controller_page_storage_format": "{} z {} wykorzystanych",
|
||||
"backup_controller_page_to_backup": "Albumy do backupu",
|
||||
"backup_controller_page_total": "Łącznie",
|
||||
"backup_controller_page_total_sub": "Wszystkie unikalne zdjęcia i filmy z wybranych albumów",
|
||||
"backup_controller_page_turn_off": "Wyłącz Backup",
|
||||
"backup_controller_page_turn_on": "Włącz Backup",
|
||||
"backup_controller_page_turn_off": "Wyłącz Kopię Zapasową",
|
||||
"backup_controller_page_turn_on": "Włącz Kopię Zapasową",
|
||||
"backup_controller_page_uploading_file_info": "Przesyłanie informacji o pliku",
|
||||
"backup_err_only_album": "Nie można usunąć tylko i wyłącznie albumu",
|
||||
"backup_info_card_assets": "pliki",
|
||||
"backup_info_card_assets": "zasoby",
|
||||
"cache_settings_album_thumbnails": "Miniatury stron bibliotek ({} zasobów)",
|
||||
"cache_settings_clear_cache_button": "Wyczyść Cache",
|
||||
"cache_settings_clear_cache_button_title": "Czyści pamięć podręczną aplikacji. Wpłynie to znacząco na wydajność aplikacji, dopóki pamięć podręczna nie zostanie odbudowana.",
|
||||
"cache_settings_image_cache_size": "Rozmiar pamięci podręcznej obrazów ({} zasobów)",
|
||||
"cache_settings_statistics_album": "Biblioteka miniatur",
|
||||
"cache_settings_statistics_assets": "{} zasoby ({})",
|
||||
"cache_settings_statistics_full": "Pełne Zdjęcia",
|
||||
"cache_settings_statistics_shared": "Udostępnione miniatury albumów",
|
||||
"cache_settings_statistics_thumbnail": "Miniatury",
|
||||
"cache_settings_statistics_title": "Użycie Cache",
|
||||
"cache_settings_subtitle": "Kontrolowanie zachowania buforowania aplikacji mobilnej Immich",
|
||||
"cache_settings_thumbnail_size": "Rozmiar pamięci podręcznej miniatur ({} zasobów)",
|
||||
"cache_settings_title": "Ustawienia Buforowania",
|
||||
"control_bottom_app_bar_add_to_album": "Add to album",
|
||||
"control_bottom_app_bar_album_info": "{} items",
|
||||
"control_bottom_app_bar_album_info_shared": "{} items · Shared",
|
||||
"control_bottom_app_bar_create_new_album": "Create new album",
|
||||
"control_bottom_app_bar_delete": "Usuń",
|
||||
"control_bottom_app_bar_share": "Udostępnij",
|
||||
"create_album_page_untitled": "Bez tytułu",
|
||||
"create_shared_album_page_create": "Utwórz",
|
||||
"create_shared_album_page_share": "Udostępnij",
|
||||
"create_shared_album_page_share_add_assets": "DODAJ PLIKI",
|
||||
"create_shared_album_page_share_add_assets": "DODAJ ZASOBY",
|
||||
"create_shared_album_page_share_select_photos": "Zaznacz Zdjęcia",
|
||||
"daily_title_text_date": "E, MMM dd",
|
||||
"daily_title_text_date_year": "E, MMM dd, yyyy",
|
||||
@@ -56,24 +101,36 @@
|
||||
"delete_dialog_cancel": "Anuluj",
|
||||
"delete_dialog_ok": "Usuń",
|
||||
"delete_dialog_title": "Usuń trwale",
|
||||
"exif_bottom_sheet_description": "Dodaj opis...",
|
||||
"exif_bottom_sheet_description": "Dodaj Opis...",
|
||||
"exif_bottom_sheet_details": "SZCZEGÓŁY",
|
||||
"exif_bottom_sheet_location": "LOKALIZACJA",
|
||||
"experimental_settings_new_asset_list_subtitle": "Work in progress",
|
||||
"experimental_settings_new_asset_list_title": "Enable experimental photo grid",
|
||||
"experimental_settings_subtitle": "Use at your own risk!",
|
||||
"experimental_settings_title": "Experimental",
|
||||
"home_page_add_to_album_conflicts": "Added {added} assets to album {album}. {failed} assets are already in the album.",
|
||||
"home_page_add_to_album_success": "Added {added} assets to album {album}.",
|
||||
"library_page_albums": "Albumy",
|
||||
"library_page_new_album": "Nowy album",
|
||||
"login_form_button_text": "Login",
|
||||
"login_form_email_hint": "twojmail@email.com",
|
||||
"login_form_endpoint_hint": "http://ip-twojego-serwera:port/api",
|
||||
"login_form_endpoint_url": "URL Serwera",
|
||||
"login_form_err_http": "Proszę określić http:// lub https://",
|
||||
"login_form_err_invalid_email": "Niepoprawny emaill",
|
||||
"login_form_err_invalid_email": "Niepoprawny Email",
|
||||
"login_form_err_leading_whitespace": "Białe znaki",
|
||||
"login_form_err_trailing_whitespace": "Białe znaki po przecinku",
|
||||
"login_form_failed_get_oauth_server_config": "Error logging using OAuth, check server URL",
|
||||
"login_form_failed_get_oauth_server_disable": "OAuth feature is not available on this server",
|
||||
"login_form_failed_login": "Błąd logowania, sprawdź adres url serwera, email i hasło.",
|
||||
"login_form_label_email": "Email",
|
||||
"login_form_label_password": "Hasło",
|
||||
"login_form_password_hint": "hasło",
|
||||
"login_form_save_login": "Pozostań zalogowany",
|
||||
"monthly_title_text_date_format": "MMMM y",
|
||||
"profile_drawer_app_logs": "Logs",
|
||||
"profile_drawer_client_server_up_to_date": "Klient i serwer są aktualne",
|
||||
"profile_drawer_settings": "Ustawienia",
|
||||
"profile_drawer_sign_out": "Wyloguj się",
|
||||
"search_bar_hint": "Szukaj swoich zdjęć",
|
||||
"search_page_no_objects": "Brak informacji o obiektach",
|
||||
@@ -84,20 +141,51 @@
|
||||
"select_additional_user_for_sharing_page_suggestions": "Propozycje",
|
||||
"select_user_for_sharing_page_err_album": "Nie udało się utworzyć albumu",
|
||||
"select_user_for_sharing_page_share_suggestions": "Propozycje",
|
||||
"setting_image_viewer_help": "The detail viewer loads the small thumbnail first, then loads the medium-size preview (if enabled), finally loads the original (if enabled).",
|
||||
"setting_image_viewer_original_subtitle": "Enable to load the original full-resolution image (large!). Disable to reduce data usage (both network and on device cache).",
|
||||
"setting_image_viewer_original_title": "Load original image",
|
||||
"setting_image_viewer_preview_subtitle": "Enable to load a medium-resolution image. Disable to either directly load the original or only use the thumbnail.",
|
||||
"setting_image_viewer_preview_title": "Load preview image",
|
||||
"setting_notifications_notify_failures_grace_period": "Powiadomienie o awariach kopii zapasowych w tle: {}",
|
||||
"setting_notifications_notify_hours": "{} godzin",
|
||||
"setting_notifications_notify_immediately": "natychmiast",
|
||||
"setting_notifications_notify_minutes": "{} minut",
|
||||
"setting_notifications_notify_never": "nigdy",
|
||||
"setting_notifications_notify_seconds": "{} seconds",
|
||||
"setting_notifications_single_progress_subtitle": "Detailed upload progress information per asset",
|
||||
"setting_notifications_single_progress_title": "Show background backup detail progress",
|
||||
"setting_notifications_subtitle": "Dostosuj preferencje powiadomień",
|
||||
"setting_notifications_title": "Powiadomienia",
|
||||
"setting_notifications_total_progress_subtitle": "Overall upload progress (done/total assets)",
|
||||
"setting_notifications_total_progress_title": "Show background backup total progress",
|
||||
"setting_pages_app_bar_settings": "Ustawienia",
|
||||
"settings_require_restart": "Please restart Immich to apply this setting",
|
||||
"share_add": "Dodaj",
|
||||
"share_add_photos": "Dodaj zdjęcia",
|
||||
"share_add_title": "Dodaj tytuł",
|
||||
"share_create_album": "Utwórz album",
|
||||
"share_dialog_preparing": "Przygotowywanie...",
|
||||
"share_invite": "Zaproś do albumu",
|
||||
"sharing_page_album": "Udostępnione albumy",
|
||||
"sharing_page_description": "Twórz wspóldzielone albumy, aby udostępniać zdjęcia i filmy osobom w sieci.",
|
||||
"sharing_page_empty_list": "PUSTA LISTA",
|
||||
"sharing_silver_appbar_create_shared_album": "Utwórz współdzielony album",
|
||||
"sharing_silver_appbar_share_partner": "Udostępnij partnerce/partnerowi",
|
||||
"tab_controller_nav_library": "Biblioteka",
|
||||
"tab_controller_nav_photos": "Zdjęcia",
|
||||
"tab_controller_nav_search": "Szukaj",
|
||||
"tab_controller_nav_sharing": "Udostępnianie",
|
||||
"version_announcement_overlay_ack": "Potwierdzenie",
|
||||
"theme_setting_asset_list_storage_indicator_title": "Pokaż wskaźnik przechowywania na kafelkach zasobów",
|
||||
"theme_setting_asset_list_tiles_per_row_title": "Number of assets per row ({})",
|
||||
"theme_setting_dark_mode_switch": "Ciemny Motyw",
|
||||
"theme_setting_image_viewer_quality_subtitle": "Dostosuj jakość podglądu szczegółowości",
|
||||
"theme_setting_image_viewer_quality_title": "Jakość przeglądania obrazów",
|
||||
"theme_setting_system_theme_switch": "Automatyczny (Postępuj zgodnie z ustawieniami systemu)",
|
||||
"theme_setting_theme_subtitle": "Wybierz ustawienia motywu aplikacji",
|
||||
"theme_setting_theme_title": "Motyw",
|
||||
"theme_setting_three_stage_loading_subtitle": "Trójstopniowe ładowanie może zwiększyć wydajność ładowania, ale powoduje znacznie większe obciążenie sieci",
|
||||
"theme_setting_three_stage_loading_title": "Włączenie trójstopniowego ładowania",
|
||||
"version_announcement_overlay_ack": "Potwierdzam",
|
||||
"version_announcement_overlay_release_notes": "informacje o wydaniu",
|
||||
"version_announcement_overlay_text_1": "Cześć przyjacielu, jest nowe wydanie",
|
||||
"version_announcement_overlay_text_2": "prosimy o poświęcenie czasu na odwiedzenie ",
|
||||
|
||||
194
mobile/assets/i18n/pt-PT.json
Normal file
194
mobile/assets/i18n/pt-PT.json
Normal file
@@ -0,0 +1,194 @@
|
||||
{
|
||||
"album_info_card_backup_album_excluded": "DELETADO",
|
||||
"album_info_card_backup_album_included": "INCLUÍDO",
|
||||
"album_thumbnail_card_item": "1 item",
|
||||
"album_thumbnail_card_items": "{} itens",
|
||||
"album_thumbnail_card_shared": "Compartilhado",
|
||||
"album_viewer_appbar_share_delete": "Deletar álbum",
|
||||
"album_viewer_appbar_share_err_delete": "Falha ao deletar álbum",
|
||||
"album_viewer_appbar_share_err_leave": "Falha ao sair do álbum",
|
||||
"album_viewer_appbar_share_err_remove": "Houveram problemas ao remover itens do álbum",
|
||||
"album_viewer_appbar_share_err_title": "Falha ao alterar título do álbum",
|
||||
"album_viewer_appbar_share_leave": "Deixar álbum",
|
||||
"album_viewer_appbar_share_remove": "Remover do álbum",
|
||||
"album_viewer_page_share_add_users": "Adicionar usuários",
|
||||
"asset_list_settings_subtitle": "Configurações de layout da grade de fotos",
|
||||
"asset_list_settings_title": "Grade de fotos",
|
||||
"backup_album_selection_page_albums_device": "Álbuns no dispositivo ({})",
|
||||
"backup_album_selection_page_albums_tap": "Toque para incluir, duplo toque para exluir",
|
||||
"backup_album_selection_page_assets_scatter": "Os itens podem estar espalhados por vários álbuns. Assim, os álbuns podem ser incluídos ou excluídos durante o processo de backup.",
|
||||
"backup_album_selection_page_select_albums": "Selecione Álbuns",
|
||||
"backup_album_selection_page_selection_info": "Informações da Seleção",
|
||||
"backup_album_selection_page_total_assets": "Total de itens únicos",
|
||||
"backup_all": "Tudo",
|
||||
"backup_background_service_backup_failed_message": "Falha ao fazer backup dos itens. Tentando novamente…",
|
||||
"backup_background_service_connection_failed_message": "Falha na conexão com o servidor. Tentando novamente...",
|
||||
"backup_background_service_current_upload_notification": "Carregando {}",
|
||||
"backup_background_service_default_notification": "Verificando novos itens…",
|
||||
"backup_background_service_error_title": "Erro de backup",
|
||||
"backup_background_service_in_progress_notification": "Fazendo backup de seus itens…",
|
||||
"backup_background_service_upload_failure_notification": "Falha ao carregar {}",
|
||||
"backup_controller_page_albums": "Backup Álbuns",
|
||||
"backup_controller_page_background_battery_info_link": "Mostre-me como",
|
||||
"backup_controller_page_background_battery_info_message": "Para obter a melhor experiência de backup em segundo plano, desative todas as otimizações de bateria que restrinjam a atividade em segundo plano do Immich.\n\nComo isso é específico do dispositivo, consulte as informações necessárias do fabricante do dispositivo.",
|
||||
"backup_controller_page_background_battery_info_ok": "OK",
|
||||
"backup_controller_page_background_battery_info_title": "Otimizações de bateria",
|
||||
"backup_controller_page_background_charging": "Somente durante o carregamento",
|
||||
"backup_controller_page_background_configure_error": "Falha ao configurar o serviço em segundo plano",
|
||||
"backup_controller_page_background_delay": "Delay new assets backup: {}",
|
||||
"backup_controller_page_background_description": "Ative o serviço em segundo plano para fazer backup automático de novos itens sem precisar abrir o aplicativo",
|
||||
"backup_controller_page_background_is_off": "O backup automático em segundo plano está desativado",
|
||||
"backup_controller_page_background_is_on": "O backup automático em segundo plano está ativado",
|
||||
"backup_controller_page_background_turn_off": "Desativar o serviço em segundo plano",
|
||||
"backup_controller_page_background_turn_on": "Ativar o serviço em segundo plano",
|
||||
"backup_controller_page_background_wifi": "Apenas Wi-Fi",
|
||||
"backup_controller_page_backup": "Backup",
|
||||
"backup_controller_page_backup_selected": "Selecionado:",
|
||||
"backup_controller_page_backup_sub": "Fotos e vídeos salvos em backup",
|
||||
"backup_controller_page_cancel": "Cancelar",
|
||||
"backup_controller_page_created": "Criado em: {}",
|
||||
"backup_controller_page_desc_backup": "Ligue o backup para fazer o upload automático de novos itens para o servidor. ",
|
||||
"backup_controller_page_excluded": "Excluídos:",
|
||||
"backup_controller_page_failed": "Falhou ({})",
|
||||
"backup_controller_page_filename": "Nome do arquivo: {} [{}]",
|
||||
"backup_controller_page_id": "ID:{}",
|
||||
"backup_controller_page_info": "Informações do backup",
|
||||
"backup_controller_page_none_selected": "Nenhum selecionado",
|
||||
"backup_controller_page_remainder": "Restante",
|
||||
"backup_controller_page_remainder_sub": "Fotos e vídeos restantes para fazer backup da seleção",
|
||||
"backup_controller_page_select": "Selecione",
|
||||
"backup_controller_page_server_storage": "Espaço no Servidor",
|
||||
"backup_controller_page_start_backup": "Iniciar Backup",
|
||||
"backup_controller_page_status_off": "Backup está desligado",
|
||||
"backup_controller_page_status_on": "Backup está ligado",
|
||||
"backup_controller_page_storage_format": "{} de {} usado",
|
||||
"backup_controller_page_to_backup": "Álbuns para fazer backup",
|
||||
"backup_controller_page_total": "Total",
|
||||
"backup_controller_page_total_sub": "Todas as fotos e vídeos dos álbuns selecionados",
|
||||
"backup_controller_page_turn_off": "Desligar backup",
|
||||
"backup_controller_page_turn_on": "Ativar backup",
|
||||
"backup_controller_page_uploading_file_info": "Carregando informações do arquivo",
|
||||
"backup_err_only_album": "Não é possível remover apenas o álbum",
|
||||
"backup_info_card_assets": "itens",
|
||||
"cache_settings_album_thumbnails": "Miniaturas da página da biblioteca ({} itens)",
|
||||
"cache_settings_clear_cache_button": "Limpar cache",
|
||||
"cache_settings_clear_cache_button_title": "Limpa o cache do aplicativo. Isso afetará significativamente o desempenho do aplicativo até que o cache seja reconstruído.",
|
||||
"cache_settings_image_cache_size": "Tamanho do cache de imagem ({} itens)",
|
||||
"cache_settings_statistics_album": "Miniaturas da biblioteca",
|
||||
"cache_settings_statistics_assets": "{} itens ({})",
|
||||
"cache_settings_statistics_full": "Imagens completas",
|
||||
"cache_settings_statistics_shared": "Miniaturas de álbuns compartilhados",
|
||||
"cache_settings_statistics_thumbnail": "Miniaturas",
|
||||
"cache_settings_statistics_title": "Uso de cache",
|
||||
"cache_settings_subtitle": "Controle o comportamento de cache do aplicativo Immich",
|
||||
"cache_settings_thumbnail_size": "Tamanho do cache de miniaturas ({} itens)",
|
||||
"cache_settings_title": "Configurações de cache",
|
||||
"control_bottom_app_bar_add_to_album": "Add to album",
|
||||
"control_bottom_app_bar_album_info": "{} items",
|
||||
"control_bottom_app_bar_album_info_shared": "{} items · Shared",
|
||||
"control_bottom_app_bar_create_new_album": "Create new album",
|
||||
"control_bottom_app_bar_delete": "Deletar",
|
||||
"control_bottom_app_bar_share": "Compartilhar",
|
||||
"create_album_page_untitled": "Sem título",
|
||||
"create_shared_album_page_create": "Criar",
|
||||
"create_shared_album_page_share": "Compartilhar",
|
||||
"create_shared_album_page_share_add_assets": "ADICIONAR ITENS",
|
||||
"create_shared_album_page_share_select_photos": "Selecionar Fotos",
|
||||
"daily_title_text_date": "E, MMM dd",
|
||||
"daily_title_text_date_year": "E, MMM dd, yyyy",
|
||||
"date_format": "E, LLL d, y • h:mm a",
|
||||
"delete_dialog_alert": "Esses itens serão permanentemente deletados do Immich e do seu dispositivo",
|
||||
"delete_dialog_cancel": "Cancelar",
|
||||
"delete_dialog_ok": "Deletar",
|
||||
"delete_dialog_title": "Deletar Permanentemente",
|
||||
"exif_bottom_sheet_description": "Adicionar Descrição...",
|
||||
"exif_bottom_sheet_details": "DETALHES",
|
||||
"exif_bottom_sheet_location": "LOCALIZAÇÃO",
|
||||
"experimental_settings_new_asset_list_subtitle": "Trabalho em andamento",
|
||||
"experimental_settings_new_asset_list_title": "Ativar visualização de grade experimental",
|
||||
"experimental_settings_subtitle": "Use por sua conta e risco!",
|
||||
"experimental_settings_title": "Experimental",
|
||||
"home_page_add_to_album_conflicts": "Added {added} assets to album {album}. {failed} assets are already in the album.",
|
||||
"home_page_add_to_album_success": "Added {added} assets to album {album}.",
|
||||
"library_page_albums": "Álbuns",
|
||||
"library_page_new_album": "Novo Album",
|
||||
"login_form_button_text": "Login",
|
||||
"login_form_email_hint": "seuemail@email.com",
|
||||
"login_form_endpoint_hint": "http://ip-do-seu-servidor:porta/api",
|
||||
"login_form_endpoint_url": "URL do endpoint do servidor",
|
||||
"login_form_err_http": "Por favor especifique http:// ou https://",
|
||||
"login_form_err_invalid_email": "Email Inválido",
|
||||
"login_form_err_leading_whitespace": "Espaço em branco no início",
|
||||
"login_form_err_trailing_whitespace": "Espaço em branco no fim",
|
||||
"login_form_failed_get_oauth_server_config": "Error logging using OAuth, check server URL",
|
||||
"login_form_failed_get_oauth_server_disable": "OAuth feature is not available on this server",
|
||||
"login_form_failed_login": "Erro ao fazer login, verifique a url do servidor, email e senha",
|
||||
"login_form_label_email": "Email",
|
||||
"login_form_label_password": "Senha",
|
||||
"login_form_password_hint": "senha",
|
||||
"login_form_save_login": "Permanecer logado",
|
||||
"monthly_title_text_date_format": "MMMM y",
|
||||
"profile_drawer_app_logs": "Logs",
|
||||
"profile_drawer_client_server_up_to_date": "Cliente e Servidor atualizados",
|
||||
"profile_drawer_settings": "Configurações",
|
||||
"profile_drawer_sign_out": "Sair",
|
||||
"search_bar_hint": "Busque suas fotos",
|
||||
"search_page_no_objects": "Nenhuma informação de objeto disponível",
|
||||
"search_page_no_places": "Nenhuma informação de lugares disponível",
|
||||
"search_page_places": "Lugares",
|
||||
"search_page_things": "Objetos",
|
||||
"search_result_page_new_search_hint": "Nova Busca",
|
||||
"select_additional_user_for_sharing_page_suggestions": "Sugestões",
|
||||
"select_user_for_sharing_page_err_album": "Falha ao criar o álbum",
|
||||
"select_user_for_sharing_page_share_suggestions": "Sugestões",
|
||||
"setting_image_viewer_help": "The detail viewer loads the small thumbnail first, then loads the medium-size preview (if enabled), finally loads the original (if enabled).",
|
||||
"setting_image_viewer_original_subtitle": "Enable to load the original full-resolution image (large!). Disable to reduce data usage (both network and on device cache).",
|
||||
"setting_image_viewer_original_title": "Load original image",
|
||||
"setting_image_viewer_preview_subtitle": "Enable to load a medium-resolution image. Disable to either directly load the original or only use the thumbnail.",
|
||||
"setting_image_viewer_preview_title": "Load preview image",
|
||||
"setting_notifications_notify_failures_grace_period": "Notifique falhas de backup em segundo plano: {}",
|
||||
"setting_notifications_notify_hours": "{} horas",
|
||||
"setting_notifications_notify_immediately": "imediatamente",
|
||||
"setting_notifications_notify_minutes": "{} minutos",
|
||||
"setting_notifications_notify_never": "Nunca",
|
||||
"setting_notifications_notify_seconds": "{} seconds",
|
||||
"setting_notifications_single_progress_subtitle": "Informações detalhadas sobre o progresso do upload por ativo",
|
||||
"setting_notifications_single_progress_title": "Mostrar progresso detalhado do backup em segundo plano",
|
||||
"setting_notifications_subtitle": "Ajuste suas preferências de notificação",
|
||||
"setting_notifications_title": "Notificações",
|
||||
"setting_notifications_total_progress_subtitle": "Progresso geral do upload (ativos concluídos/total)",
|
||||
"setting_notifications_total_progress_title": "Mostrar progresso total do backup em segundo plano",
|
||||
"setting_pages_app_bar_settings": "Configurações",
|
||||
"settings_require_restart": "Reinicie o Immich para aplicar essa configuração",
|
||||
"share_add": "Adicionar",
|
||||
"share_add_photos": "Adicionar fotos",
|
||||
"share_add_title": "Adicione um título",
|
||||
"share_create_album": "Criar álbum",
|
||||
"share_dialog_preparing": "Preparando...",
|
||||
"share_invite": "Convidar para álbum",
|
||||
"sharing_page_album": "Álbuns compartilhados",
|
||||
"sharing_page_description": "Criar álbuns compartilhados para compartilhas fotos e vídeos com pessoas na sua rede.",
|
||||
"sharing_page_empty_list": "LISTA VAZIA",
|
||||
"sharing_silver_appbar_create_shared_album": "Criar um álgum compartilhado",
|
||||
"sharing_silver_appbar_share_partner": "Compartilhar com parceiro",
|
||||
"tab_controller_nav_library": "Biblioteca",
|
||||
"tab_controller_nav_photos": "Fotos",
|
||||
"tab_controller_nav_search": "Buscar",
|
||||
"tab_controller_nav_sharing": "Compartilhando",
|
||||
"theme_setting_asset_list_storage_indicator_title": "Mostrar indicador de armazenamento em blocos de ativos",
|
||||
"theme_setting_asset_list_tiles_per_row_title": "Número de itens por linha ({})",
|
||||
"theme_setting_dark_mode_switch": "Modo escuro",
|
||||
"theme_setting_image_viewer_quality_subtitle": "Ajuste a qualidade do visualizador de imagens detalhadas",
|
||||
"theme_setting_image_viewer_quality_title": "Qualidade do visualizador de imagens",
|
||||
"theme_setting_system_theme_switch": "Automático (Siga a configuração do sistema)",
|
||||
"theme_setting_theme_subtitle": "Escolha a configuração do tema do aplicativo",
|
||||
"theme_setting_theme_title": "Tema",
|
||||
"theme_setting_three_stage_loading_subtitle": "O carregamento em três estágios pode aumentar o desempenho do carregamento, mas causa uma carga de rede significativamente maior",
|
||||
"theme_setting_three_stage_loading_title": "Habilitar carregamento em três estágios",
|
||||
"version_announcement_overlay_ack": "Need Context",
|
||||
"version_announcement_overlay_release_notes": "notas de lançamento",
|
||||
"version_announcement_overlay_text_1": "Olá, há um novo lançamento de",
|
||||
"version_announcement_overlay_text_2": "por favor, tome o seu tempo para visitar o",
|
||||
"version_announcement_overlay_text_3": "e certifique-se de que a configuração do docker-compose e do .env estejam atualizadas para evitar configurações incorretas, especialmente se você usar o WatchTower ou qualquer mecanismo que lide com a atualização automática do aplicativo do servidor.",
|
||||
"version_announcement_overlay_title": "Nova versão do servidor disponível \uD83C\uDF89"
|
||||
}
|
||||
194
mobile/assets/i18n/ru-RU.json
Normal file
194
mobile/assets/i18n/ru-RU.json
Normal file
@@ -0,0 +1,194 @@
|
||||
{
|
||||
"album_info_card_backup_album_excluded": "EXCLUDED",
|
||||
"album_info_card_backup_album_included": "INCLUDED",
|
||||
"album_thumbnail_card_item": "1 item",
|
||||
"album_thumbnail_card_items": "{} items",
|
||||
"album_thumbnail_card_shared": " · Shared",
|
||||
"album_viewer_appbar_share_delete": "Delete album",
|
||||
"album_viewer_appbar_share_err_delete": "Failed to delete album",
|
||||
"album_viewer_appbar_share_err_leave": "Failed to leave album",
|
||||
"album_viewer_appbar_share_err_remove": "There are problems in removing assets from album",
|
||||
"album_viewer_appbar_share_err_title": "Failed to change album title",
|
||||
"album_viewer_appbar_share_leave": "Leave album",
|
||||
"album_viewer_appbar_share_remove": "Remove from album",
|
||||
"album_viewer_page_share_add_users": "Add users",
|
||||
"asset_list_settings_subtitle": "Photo grid layout settings",
|
||||
"asset_list_settings_title": "Photo Grid",
|
||||
"backup_album_selection_page_albums_device": "Albums on device ({})",
|
||||
"backup_album_selection_page_albums_tap": "Tap to include, double tap to exclude",
|
||||
"backup_album_selection_page_assets_scatter": "Assets can scatter across multiple albums. Thus, albums can be included or excluded during the backup process.",
|
||||
"backup_album_selection_page_select_albums": "Select albums",
|
||||
"backup_album_selection_page_selection_info": "Selection Info",
|
||||
"backup_album_selection_page_total_assets": "Total unique assets",
|
||||
"backup_all": "All",
|
||||
"backup_background_service_backup_failed_message": "Не удалось выполнить резервное копирование. Повторная попытка…",
|
||||
"backup_background_service_connection_failed_message": "Не удалось подключиться к серверу. Повторная попытка...",
|
||||
"backup_background_service_current_upload_notification": "Uploading {}",
|
||||
"backup_background_service_default_notification": "Checking for new assets…",
|
||||
"backup_background_service_error_title": "Ошибка резервного копирования",
|
||||
"backup_background_service_in_progress_notification": "Backing up your assets…",
|
||||
"backup_background_service_upload_failure_notification": "Failed to upload {}",
|
||||
"backup_controller_page_albums": "Backup Albums",
|
||||
"backup_controller_page_background_battery_info_link": "Показать как",
|
||||
"backup_controller_page_background_battery_info_message": "Для наилучшего фонового резервного копирования отключите любые настройки оптимизации батареи, ограничивающие фоновую активность для Immich.\n\nПоскольку это зависит от устройства, найдите необходимую информацию для производителя вашего устройства.",
|
||||
"backup_controller_page_background_battery_info_ok": "ОК",
|
||||
"backup_controller_page_background_battery_info_title": "Battery optimizations",
|
||||
"backup_controller_page_background_charging": "Только во время зарядки",
|
||||
"backup_controller_page_background_configure_error": "Failed to configure the background service",
|
||||
"backup_controller_page_background_delay": "Delay new assets backup: {}",
|
||||
"backup_controller_page_background_description": "Turn on the background service to automatically backup any new assets without needing to open the app",
|
||||
"backup_controller_page_background_is_off": "Automatic background backup is off",
|
||||
"backup_controller_page_background_is_on": "Automatic background backup is on",
|
||||
"backup_controller_page_background_turn_off": "Выключить фоновый сервис",
|
||||
"backup_controller_page_background_turn_on": "Включить фоновый сервис",
|
||||
"backup_controller_page_background_wifi": "Только на WiFi",
|
||||
"backup_controller_page_backup": "Backup",
|
||||
"backup_controller_page_backup_selected": "Selected: ",
|
||||
"backup_controller_page_backup_sub": "Backed up photos and videos",
|
||||
"backup_controller_page_cancel": "Cancel",
|
||||
"backup_controller_page_created": "Created on: {}",
|
||||
"backup_controller_page_desc_backup": "Turn on foreground backup to automatically upload new assets to the server when opening the app.",
|
||||
"backup_controller_page_excluded": "Excluded: ",
|
||||
"backup_controller_page_failed": "Failed ({})",
|
||||
"backup_controller_page_filename": "File name: {} [{}]",
|
||||
"backup_controller_page_id": "ID: {}",
|
||||
"backup_controller_page_info": "Backup Information",
|
||||
"backup_controller_page_none_selected": "None selected",
|
||||
"backup_controller_page_remainder": "Remainder",
|
||||
"backup_controller_page_remainder_sub": "Remaining photos and videos to back up from selection",
|
||||
"backup_controller_page_select": "Select",
|
||||
"backup_controller_page_server_storage": "Server Storage",
|
||||
"backup_controller_page_start_backup": "Start Backup",
|
||||
"backup_controller_page_status_off": "Automatic foreground backup is off",
|
||||
"backup_controller_page_status_on": "Automatic foreground backup is on",
|
||||
"backup_controller_page_storage_format": "{} of {} used",
|
||||
"backup_controller_page_to_backup": "Albums to be backup",
|
||||
"backup_controller_page_total": "Total",
|
||||
"backup_controller_page_total_sub": "All unique photos and videos from selected albums",
|
||||
"backup_controller_page_turn_off": "Turn off foreground backup",
|
||||
"backup_controller_page_turn_on": "Turn on foreground backup",
|
||||
"backup_controller_page_uploading_file_info": "Uploading file info",
|
||||
"backup_err_only_album": "Cannot remove the only album",
|
||||
"backup_info_card_assets": "assets",
|
||||
"cache_settings_album_thumbnails": "Library page thumbnails ({} assets)",
|
||||
"cache_settings_clear_cache_button": "Clear cache",
|
||||
"cache_settings_clear_cache_button_title": "Clears the app's cache. This will significantly impact the app's performance until the cache has rebuilt.",
|
||||
"cache_settings_image_cache_size": "Image cache size ({} assets)",
|
||||
"cache_settings_statistics_album": "Library thumbnails",
|
||||
"cache_settings_statistics_assets": "{} assets ({})",
|
||||
"cache_settings_statistics_full": "Full images",
|
||||
"cache_settings_statistics_shared": "Shared album thumbnails",
|
||||
"cache_settings_statistics_thumbnail": "Thumbnails",
|
||||
"cache_settings_statistics_title": "Cache usage",
|
||||
"cache_settings_subtitle": "Control the caching behaviour of the Immich mobile application",
|
||||
"cache_settings_thumbnail_size": "Thumbnail cache size ({} assets)",
|
||||
"cache_settings_title": "Caching Settings",
|
||||
"control_bottom_app_bar_add_to_album": "Add to album",
|
||||
"control_bottom_app_bar_album_info": "{} items",
|
||||
"control_bottom_app_bar_album_info_shared": "{} items · Shared",
|
||||
"control_bottom_app_bar_create_new_album": "Create new album",
|
||||
"control_bottom_app_bar_delete": "Удалить",
|
||||
"control_bottom_app_bar_share": "Поделиться",
|
||||
"create_album_page_untitled": "Untitled",
|
||||
"create_shared_album_page_create": "Создать",
|
||||
"create_shared_album_page_share": "Share",
|
||||
"create_shared_album_page_share_add_assets": "ADD ASSETS",
|
||||
"create_shared_album_page_share_select_photos": "Select Photos",
|
||||
"daily_title_text_date": "E, MMM dd",
|
||||
"daily_title_text_date_year": "E, MMM dd, yyyy",
|
||||
"date_format": "E, LLL d, y • h:mm a",
|
||||
"delete_dialog_alert": "These items will be permanently deleted from Immich and from your device",
|
||||
"delete_dialog_cancel": "Отменить",
|
||||
"delete_dialog_ok": "Удалить",
|
||||
"delete_dialog_title": "Удалить навсегда",
|
||||
"exif_bottom_sheet_description": "Add Description...",
|
||||
"exif_bottom_sheet_details": "DETAILS",
|
||||
"exif_bottom_sheet_location": "LOCATION",
|
||||
"experimental_settings_new_asset_list_subtitle": "Work in progress",
|
||||
"experimental_settings_new_asset_list_title": "Enable experimental photo grid",
|
||||
"experimental_settings_subtitle": "Используйте на свой страх и риск!",
|
||||
"experimental_settings_title": "Экспериментальное",
|
||||
"home_page_add_to_album_conflicts": "Added {added} assets to album {album}. {failed} assets are already in the album.",
|
||||
"home_page_add_to_album_success": "Added {added} assets to album {album}.",
|
||||
"library_page_albums": "Альбомы",
|
||||
"library_page_new_album": "Новый альбом",
|
||||
"login_form_button_text": "Login",
|
||||
"login_form_email_hint": "youremail@email.com",
|
||||
"login_form_endpoint_hint": "http://your-server-ip:port/api",
|
||||
"login_form_endpoint_url": "Server Endpoint URL",
|
||||
"login_form_err_http": "Please specify http:// or https://",
|
||||
"login_form_err_invalid_email": "Invalid Email",
|
||||
"login_form_err_leading_whitespace": "Leading whitespace",
|
||||
"login_form_err_trailing_whitespace": "Trailing whitespace",
|
||||
"login_form_failed_get_oauth_server_config": "Error logging using OAuth, check server URL",
|
||||
"login_form_failed_get_oauth_server_disable": "OAuth feature is not available on this server",
|
||||
"login_form_failed_login": "Error logging you in, check server URL, email and password",
|
||||
"login_form_label_email": "Email",
|
||||
"login_form_label_password": "Password",
|
||||
"login_form_password_hint": "password",
|
||||
"login_form_save_login": "Stay logged in",
|
||||
"monthly_title_text_date_format": "MMMM y",
|
||||
"profile_drawer_app_logs": "Logs",
|
||||
"profile_drawer_client_server_up_to_date": "Client and Server are up-to-date",
|
||||
"profile_drawer_settings": "Настройки",
|
||||
"profile_drawer_sign_out": "Выйти",
|
||||
"search_bar_hint": "Search your photos",
|
||||
"search_page_no_objects": "No Objects Info Available",
|
||||
"search_page_no_places": "No Places Info Available",
|
||||
"search_page_places": "Места",
|
||||
"search_page_things": "Предметы",
|
||||
"search_result_page_new_search_hint": "Новый Поиск",
|
||||
"select_additional_user_for_sharing_page_suggestions": "Suggestions",
|
||||
"select_user_for_sharing_page_err_album": "Failed to create album",
|
||||
"select_user_for_sharing_page_share_suggestions": "Suggestions",
|
||||
"setting_image_viewer_help": "The detail viewer loads the small thumbnail first, then loads the medium-size preview (if enabled), finally loads the original (if enabled).",
|
||||
"setting_image_viewer_original_subtitle": "Enable to load the original full-resolution image (large!). Disable to reduce data usage (both network and on device cache).",
|
||||
"setting_image_viewer_original_title": "Load original image",
|
||||
"setting_image_viewer_preview_subtitle": "Enable to load a medium-resolution image. Disable to either directly load the original or only use the thumbnail.",
|
||||
"setting_image_viewer_preview_title": "Load preview image",
|
||||
"setting_notifications_notify_failures_grace_period": "Notify background backup failures: {}",
|
||||
"setting_notifications_notify_hours": "{} часов",
|
||||
"setting_notifications_notify_immediately": "немедленно",
|
||||
"setting_notifications_notify_minutes": "{} минут",
|
||||
"setting_notifications_notify_never": "никогда",
|
||||
"setting_notifications_notify_seconds": "{} seconds",
|
||||
"setting_notifications_single_progress_subtitle": "Detailed upload progress information per asset",
|
||||
"setting_notifications_single_progress_title": "Show background backup detail progress",
|
||||
"setting_notifications_subtitle": "Adjust your notification preferences",
|
||||
"setting_notifications_title": "Уведомления",
|
||||
"setting_notifications_total_progress_subtitle": "Overall upload progress (done/total assets)",
|
||||
"setting_notifications_total_progress_title": "Show background backup total progress",
|
||||
"setting_pages_app_bar_settings": "Настройки",
|
||||
"settings_require_restart": "Please restart Immich to apply this setting",
|
||||
"share_add": "Add",
|
||||
"share_add_photos": "Add photos",
|
||||
"share_add_title": "Add a title",
|
||||
"share_create_album": "Create album",
|
||||
"share_dialog_preparing": "Preparing...",
|
||||
"share_invite": "Invite to album",
|
||||
"sharing_page_album": "Shared albums",
|
||||
"sharing_page_description": "Create shared albums to share photos and videos with people in your network.",
|
||||
"sharing_page_empty_list": "EMPTY LIST",
|
||||
"sharing_silver_appbar_create_shared_album": "Create shared album",
|
||||
"sharing_silver_appbar_share_partner": "Share with partner",
|
||||
"tab_controller_nav_library": "Library",
|
||||
"tab_controller_nav_photos": "Photos",
|
||||
"tab_controller_nav_search": "Поиск",
|
||||
"tab_controller_nav_sharing": "Sharing",
|
||||
"theme_setting_asset_list_storage_indicator_title": "Show storage indicator on asset tiles",
|
||||
"theme_setting_asset_list_tiles_per_row_title": "Number of assets per row ({})",
|
||||
"theme_setting_dark_mode_switch": "Тёмная тема",
|
||||
"theme_setting_image_viewer_quality_subtitle": "Adjust the quality of the detail image viewer",
|
||||
"theme_setting_image_viewer_quality_title": "Image viewer quality",
|
||||
"theme_setting_system_theme_switch": "Автоматически (следовать системным настройкам)",
|
||||
"theme_setting_theme_subtitle": "Выберите настройки темы приложения",
|
||||
"theme_setting_theme_title": "Тема",
|
||||
"theme_setting_three_stage_loading_subtitle": "Three-stage loading might increase the loading performance but causes significantly higher network load",
|
||||
"theme_setting_three_stage_loading_title": "Enable three-stage loading",
|
||||
"version_announcement_overlay_ack": "Acknowledge",
|
||||
"version_announcement_overlay_release_notes": "release notes",
|
||||
"version_announcement_overlay_text_1": "Hi friend, there is a new release of",
|
||||
"version_announcement_overlay_text_2": "please take your time to visit the ",
|
||||
"version_announcement_overlay_text_3": " and ensure your docker-compose and .env setup is up-to-date to prevent any misconfigurations, especially if you use WatchTower or any mechanism that handles updating your server application automatically.",
|
||||
"version_announcement_overlay_title": "Доступна новая версия сервера \uD83C\uDF89"
|
||||
}
|
||||
194
mobile/assets/i18n/sk-SK.json
Normal file
194
mobile/assets/i18n/sk-SK.json
Normal file
@@ -0,0 +1,194 @@
|
||||
{
|
||||
"album_info_card_backup_album_excluded": "VYLÚČENÉ",
|
||||
"album_info_card_backup_album_included": "ZAHRNUTÉ",
|
||||
"album_thumbnail_card_item": "1 položka",
|
||||
"album_thumbnail_card_items": "{} položky",
|
||||
"album_thumbnail_card_shared": "Zdieľané",
|
||||
"album_viewer_appbar_share_delete": "odstrániť album",
|
||||
"album_viewer_appbar_share_err_delete": "Nepodarilo sa odstrániť album",
|
||||
"album_viewer_appbar_share_err_leave": "Nepodarilo sa ukončiť album",
|
||||
"album_viewer_appbar_share_err_remove": "Pri odstraňovaní súborov z albumu sa vyskytli problémy.",
|
||||
"album_viewer_appbar_share_err_title": "Nepodarilo sa zmeniť názov albumu",
|
||||
"album_viewer_appbar_share_leave": "Opustiť album",
|
||||
"album_viewer_appbar_share_remove": "Odstrániť z albumu",
|
||||
"album_viewer_page_share_add_users": "Pridať používateľov",
|
||||
"asset_list_settings_subtitle": "Nastavenia rozloženia mriežky fotografií",
|
||||
"asset_list_settings_title": "Fotografická mriežka",
|
||||
"backup_album_selection_page_albums_device": "Albumy v zariadení ({})",
|
||||
"backup_album_selection_page_albums_tap": "Ťuknutím na položku ju zahrniete, dvojitým ťuknutím ju vylúčite",
|
||||
"backup_album_selection_page_assets_scatter": "Súbory môžu byť roztrúsené vo viacerých albumoch. To umožňuje zahrnúť alebo vylúčiť albumy počas procesu zálohovania.",
|
||||
"backup_album_selection_page_select_albums": "Vybrané albumy",
|
||||
"backup_album_selection_page_selection_info": "Informácie o výbere",
|
||||
"backup_album_selection_page_total_assets": "Celkový počet jedinečných súborov",
|
||||
"backup_all": "Všetko",
|
||||
"backup_background_service_backup_failed_message": "Zálohovanie zdrojov zlyhalo. Skúšam to znova...",
|
||||
"backup_background_service_connection_failed_message": "Nepodarilo sa pripojiť k serveru. Skúšam to znova...",
|
||||
"backup_background_service_current_upload_notification": "Nahrávanie {}",
|
||||
"backup_background_service_default_notification": "Kontrola nových zdrojov {}",
|
||||
"backup_background_service_error_title": "Chyba zálohovania",
|
||||
"backup_background_service_in_progress_notification": "Vytváram kópiu vašich zdrojov...",
|
||||
"backup_background_service_upload_failure_notification": "Nepodarilo sa nahrať {}",
|
||||
"backup_controller_page_albums": "Zálohované albumy",
|
||||
"backup_controller_page_background_battery_info_link": "Ukáž mi ako",
|
||||
"backup_controller_page_background_battery_info_message": "Ak chcete dosiahnuť najlepšie výsledky pri zálohovaní na pozadí, vypnite všetky optimalizácie batérie, ktoré obmedzujú aktivitu na pozadí pre Immich vo vašom zariadení. Keďže to závisí od zariadenia, skontrolujte požadované informácie pre výrobcu vášho zariadenia.",
|
||||
"backup_controller_page_background_battery_info_ok": "OK",
|
||||
"backup_controller_page_background_battery_info_title": "Optimalizácia batérie",
|
||||
"backup_controller_page_background_charging": "Len počas nabíjania",
|
||||
"backup_controller_page_background_configure_error": "Nepodarilo sa nakonfigurovať službu na pozadí",
|
||||
"backup_controller_page_background_delay": "Oneskorenie zálohovania nových zdrojov: {}",
|
||||
"backup_controller_page_background_description": "Povoľte službu na pozadí na automatické zálohovanie všetkých nových aktív bez nutnosti otvorenia aplikácie",
|
||||
"backup_controller_page_background_is_off": "Automatické zálohovanie na pozadí je vypnuté",
|
||||
"backup_controller_page_background_is_on": "Automatické zálohovanie na pozadí je zapnuté",
|
||||
"backup_controller_page_background_turn_off": "Zakázať službu na pozadí",
|
||||
"backup_controller_page_background_turn_on": "Povoliť službu na pozadí",
|
||||
"backup_controller_page_background_wifi": "Len na WiFi",
|
||||
"backup_controller_page_backup": "Zálohovanie",
|
||||
"backup_controller_page_backup_selected": "Vybrané: ",
|
||||
"backup_controller_page_backup_sub": "Zálohovanie fotografií a videí",
|
||||
"backup_controller_page_cancel": "Zrušiť",
|
||||
"backup_controller_page_created": "Vytvorené: {}",
|
||||
"backup_controller_page_desc_backup": "Zapnite zálohovanie na popredí, aby sa nové položky automaticky nahrávali na server pri otvorení aplikácie.",
|
||||
"backup_controller_page_excluded": "Vylúčené: ",
|
||||
"backup_controller_page_failed": "Nepodarilo sa ({})",
|
||||
"backup_controller_page_filename": "Názov súboru: {} [{}]",
|
||||
"backup_controller_page_id": "ID: {}",
|
||||
"backup_controller_page_info": "Informácie o zálohovaní",
|
||||
"backup_controller_page_none_selected": "Žiadne vybrané",
|
||||
"backup_controller_page_remainder": "Zvyšok",
|
||||
"backup_controller_page_remainder_sub": "Zostávajúce fotografie a albumy, ktoré sa majú zálohovať z výberu",
|
||||
"backup_controller_page_select": "Vybrať",
|
||||
"backup_controller_page_server_storage": "Serverové úložisko",
|
||||
"backup_controller_page_start_backup": "Spustiť zálohovanie",
|
||||
"backup_controller_page_status_off": "Automatické zálohovanie na popredí je vypnuté",
|
||||
"backup_controller_page_status_on": "Automatické zálohovanie na popredí je zapnuté",
|
||||
"backup_controller_page_storage_format": "{} z {} použitých",
|
||||
"backup_controller_page_to_backup": "Albumy, ktoré sa majú zálohovať",
|
||||
"backup_controller_page_total": "Celkom",
|
||||
"backup_controller_page_total_sub": "Všetky jedinečné fotografie a videá z vybraných albumov",
|
||||
"backup_controller_page_turn_off": "Zakázať zálohovanie na popredí",
|
||||
"backup_controller_page_turn_on": "Povoliť zálohovanie na popredí",
|
||||
"backup_controller_page_uploading_file_info": "Nahrávanie informácií o súboroch",
|
||||
"backup_err_only_album": "Nie je možné odstrániť iba album",
|
||||
"backup_info_card_assets": "položky",
|
||||
"cache_settings_album_thumbnails": "Náhľady stránok knižnice (položiek {})",
|
||||
"cache_settings_clear_cache_button": "Vymazať vyrovnávaciu pamäť",
|
||||
"cache_settings_clear_cache_button_title": "Vymaže vyrovnávaciu pamäť aplikácie. To výrazne ovplyvní výkon aplikácie, kým sa vyrovnávacia pamäť neobnoví.",
|
||||
"cache_settings_image_cache_size": "Veľkosť vyrovnávacej pamäte (položiek {})",
|
||||
"cache_settings_statistics_album": "Knižnica náhľadov",
|
||||
"cache_settings_statistics_assets": "{} položky ({})",
|
||||
"cache_settings_statistics_full": "Kompletné fotografie",
|
||||
"cache_settings_statistics_shared": "Zdieľané náhľady albumov",
|
||||
"cache_settings_statistics_thumbnail": "Náhľady",
|
||||
"cache_settings_statistics_title": "Použitie vyrovnávacej pamäte",
|
||||
"cache_settings_subtitle": "Ovládanie správania mobilnej aplikácie Immich v medzipamäti",
|
||||
"cache_settings_thumbnail_size": "Veľkosť vyrovnávacej pamäte náhľadov (položiek {})",
|
||||
"cache_settings_title": "Nastavenia vyrovnávacej pamäte",
|
||||
"control_bottom_app_bar_add_to_album": "Pridať do albumu",
|
||||
"control_bottom_app_bar_album_info": "{} položky",
|
||||
"control_bottom_app_bar_album_info_shared": "{} položky - zdieľané",
|
||||
"control_bottom_app_bar_create_new_album": "Vytvoriť nový album",
|
||||
"control_bottom_app_bar_delete": "Vymazať",
|
||||
"control_bottom_app_bar_share": "Zdieľať",
|
||||
"create_album_page_untitled": "Bez názvu",
|
||||
"create_shared_album_page_create": "Vytvoriť",
|
||||
"create_shared_album_page_share": "Zdieľať",
|
||||
"create_shared_album_page_share_add_assets": "PRIDAŤ",
|
||||
"create_shared_album_page_share_select_photos": "Vybrať fotografie",
|
||||
"daily_title_text_date": "EEEE, d MMMM",
|
||||
"daily_title_text_date_year": "EEEE, d MMMM y",
|
||||
"date_format": "EEEE, d MMMM y • H:mm",
|
||||
"delete_dialog_alert": "Tieto položky budú natrvalo odstránené z Immich a z vášho zariadenia.",
|
||||
"delete_dialog_cancel": "Zrušiť",
|
||||
"delete_dialog_ok": "Vymazať",
|
||||
"delete_dialog_title": "Vymazať natrvalo",
|
||||
"exif_bottom_sheet_description": "Pridať popis...",
|
||||
"exif_bottom_sheet_details": "PODROBNOSTI",
|
||||
"exif_bottom_sheet_location": "LOKALITA",
|
||||
"experimental_settings_new_asset_list_subtitle": "Prebiehajúca práca",
|
||||
"experimental_settings_new_asset_list_title": "Povolenie experimentálnej mriežky fotografií",
|
||||
"experimental_settings_subtitle": "Používajte na vlastné riziko!",
|
||||
"experimental_settings_title": "Experimentálne",
|
||||
"home_page_add_to_album_conflicts": "Pridané {added} položky do albumu {album}. {failed} položky sú už v albume.",
|
||||
"home_page_add_to_album_success": "Pridané {added} položky do albumu {album}.",
|
||||
"library_page_albums": "Albumy",
|
||||
"library_page_new_album": "Nový album",
|
||||
"login_form_button_text": "Prihlásenie",
|
||||
"login_form_email_hint": "tvojmail@email.com",
|
||||
"login_form_endpoint_hint": "http://ip-tvojho-servera:port/api",
|
||||
"login_form_endpoint_url": "URL adresa servera",
|
||||
"login_form_err_http": "Prosím, uveďte http:// alebo https://",
|
||||
"login_form_err_invalid_email": "Neplatný e-mail",
|
||||
"login_form_err_leading_whitespace": "Úvodná medzera",
|
||||
"login_form_err_trailing_whitespace": "Koncové medzera",
|
||||
"login_form_failed_get_oauth_server_config": "Chyba prihlásenia pomocou OAuth, skontrolujte adresu URL servera",
|
||||
"login_form_failed_get_oauth_server_disable": "Funkcia OAuth nie je na tomto serveri dostupná",
|
||||
"login_form_failed_login": "Chyba prihlásenia, skontrolujte url adresu servera, e-mail a heslo.",
|
||||
"login_form_label_email": "E-mail",
|
||||
"login_form_label_password": "Heslo",
|
||||
"login_form_password_hint": "heslo",
|
||||
"login_form_save_login": "Zostať prihlásený",
|
||||
"monthly_title_text_date_format": "LLLL y",
|
||||
"profile_drawer_app_logs": "Logy",
|
||||
"profile_drawer_client_server_up_to_date": "Klient a server sú aktuálne",
|
||||
"profile_drawer_settings": "Nastavenia",
|
||||
"profile_drawer_sign_out": "Odhlásiť sa",
|
||||
"search_bar_hint": "Prehľadajte svoje obrázky",
|
||||
"search_page_no_objects": "Žiadne informácie o objektoch",
|
||||
"search_page_no_places": "Žiadne informácie o mieste",
|
||||
"search_page_places": "Miesta",
|
||||
"search_page_things": "Veci",
|
||||
"search_result_page_new_search_hint": "Nové vyhľadávanie",
|
||||
"select_additional_user_for_sharing_page_suggestions": "Návrhy",
|
||||
"select_user_for_sharing_page_err_album": "Nepodarilo sa vytvoriť album",
|
||||
"select_user_for_sharing_page_share_suggestions": "Návrhy",
|
||||
"setting_image_viewer_help": "V prehliadači detailov sa najprv načíta malá miniatúra, potom sa načíta náhľad strednej veľkosti (ak je povoleny) a nakoniec sa načíta originál (ak je povolený).",
|
||||
"setting_image_viewer_original_subtitle": "Umožňuje načítať pôvodný obrázok v plnom rozlíšení (veľký!). Zakázať pre zníženie používania dát (v sieti aj v medzipamäti zariadenia).",
|
||||
"setting_image_viewer_original_title": "Načítať pôvodný obrázok",
|
||||
"setting_image_viewer_preview_subtitle": "Umožňuje načítať obrázok so stredným rozlíšením. Zakážte, ak chcete priamo načítať originál alebo použiť iba miniatúru.",
|
||||
"setting_image_viewer_preview_title": "Načítať náhľad obrázka",
|
||||
"setting_notifications_notify_failures_grace_period": "Oznámenie o zlyhaní zálohovania na pozadí: {}",
|
||||
"setting_notifications_notify_hours": "{} hodín",
|
||||
"setting_notifications_notify_immediately": "okamžite",
|
||||
"setting_notifications_notify_minutes": "{} minút",
|
||||
"setting_notifications_notify_never": "nikdy",
|
||||
"setting_notifications_notify_seconds": "{} sekundy",
|
||||
"setting_notifications_single_progress_subtitle": "Podrobné informácie o priebehu nahrávania pre položku",
|
||||
"setting_notifications_single_progress_title": "Zobraziť priebeh detailov zálohovania na pozadí",
|
||||
"setting_notifications_subtitle": "Prispôsobenie predvolieb oznámení",
|
||||
"setting_notifications_title": "Oznámenia",
|
||||
"setting_notifications_total_progress_subtitle": "Celkový priebeh nahrávania (hotové/celkové položky)",
|
||||
"setting_notifications_total_progress_title": "Zobraziť celkový priebeh zálohovania na pozadí",
|
||||
"setting_pages_app_bar_settings": "nastavenia",
|
||||
"settings_require_restart": "Na použitie tohto nastavenia reštartujte Immich",
|
||||
"share_add": "Pridať",
|
||||
"share_add_photos": "Pridať fotografie",
|
||||
"share_add_title": "Pridať názov",
|
||||
"share_create_album": "Vytvoriť album",
|
||||
"share_dialog_preparing": "Pripravujem...",
|
||||
"share_invite": "Pozvať do albumu",
|
||||
"sharing_page_album": "Shared albums",
|
||||
"sharing_page_description": "Vytvárajte zdieľané albumy a zdieľajte fotografie a videá s ľuďmi vo vašej sieti.",
|
||||
"sharing_page_empty_list": "Prázny list",
|
||||
"sharing_silver_appbar_create_shared_album": "Vytvoriť zdieľaný album",
|
||||
"sharing_silver_appbar_share_partner": "Zdieľať s partnerom",
|
||||
"tab_controller_nav_library": "Knižnica",
|
||||
"tab_controller_nav_photos": "Fotografie",
|
||||
"tab_controller_nav_search": "Vyhľadávanie",
|
||||
"tab_controller_nav_sharing": "Zdieľanie",
|
||||
"theme_setting_asset_list_storage_indicator_title": "Zobraziť indikátor úložiska na dlaždiciach zdrojov",
|
||||
"theme_setting_asset_list_tiles_per_row_title": "Počet aktív na riadok ({})",
|
||||
"theme_setting_dark_mode_switch": "Tmavá téma",
|
||||
"theme_setting_image_viewer_quality_subtitle": "Prispôsobenie kvality prehliadača detailov",
|
||||
"theme_setting_image_viewer_quality_title": "Kvalita prehliadača obrázkov",
|
||||
"theme_setting_system_theme_switch": "Automaticky (podľa systemového nastavenia)",
|
||||
"theme_setting_theme_subtitle": "Vyberte nastavenia témy aplikácie",
|
||||
"theme_setting_theme_title": "Téma",
|
||||
"theme_setting_three_stage_loading_subtitle": "Trojstupňové načítanie môže zvýšiť výkonnosť načítania, ale vedie k výrazne vyššiemu zaťaženiu siete.",
|
||||
"theme_setting_three_stage_loading_title": "Povolenie trojstupňového načítavania",
|
||||
"version_announcement_overlay_ack": "Potvrdiť",
|
||||
"version_announcement_overlay_release_notes": "poznámky k vydaniu",
|
||||
"version_announcement_overlay_text_1": "Ahoj, je tu nová verzia",
|
||||
"version_announcement_overlay_text_2": "nájdite si čas na návštevu ",
|
||||
"version_announcement_overlay_text_3": " a uistite sa, že vaša konfigurácia docker-compose a .env je aktuálna, aby ste predišli nesprávnej konfigurácii, najmä ak používate WatchTower alebo akýkoľvek mechanizmus, ktorý podporuje automatické aktualizácie serverových aplikácií.",
|
||||
"version_announcement_overlay_title": "K dispozícii je nová verzia servera \uD83C\uDF89"
|
||||
}
|
||||
194
mobile/assets/i18n/zh-CN.json
Normal file
194
mobile/assets/i18n/zh-CN.json
Normal file
@@ -0,0 +1,194 @@
|
||||
{
|
||||
"album_info_card_backup_album_excluded": "排除",
|
||||
"album_info_card_backup_album_included": "已选",
|
||||
"album_thumbnail_card_item": "1张",
|
||||
"album_thumbnail_card_items": "{}张",
|
||||
"album_thumbnail_card_shared": "已共享",
|
||||
"album_viewer_appbar_share_delete": "删除相册",
|
||||
"album_viewer_appbar_share_err_delete": "删除相册失败",
|
||||
"album_viewer_appbar_share_err_leave": "退出相册失败",
|
||||
"album_viewer_appbar_share_err_remove": "从相册时移除出现错误",
|
||||
"album_viewer_appbar_share_err_title": "修改相册标题失败",
|
||||
"album_viewer_appbar_share_leave": "退出相册",
|
||||
"album_viewer_appbar_share_remove": "从相册中移除",
|
||||
"album_viewer_page_share_add_users": "新增用户",
|
||||
"asset_list_settings_subtitle": "照片预览设置",
|
||||
"asset_list_settings_title": "照片预览",
|
||||
"backup_album_selection_page_albums_device": "设备上的相册({})",
|
||||
"backup_album_selection_page_albums_tap": "单击选中, 双击排除",
|
||||
"backup_album_selection_page_assets_scatter": "可以从多个相册中选择数据。因此, 可以在备份过程中选中或者排除相册",
|
||||
"backup_album_selection_page_select_albums": "选择相册",
|
||||
"backup_album_selection_page_selection_info": "选择信息",
|
||||
"backup_album_selection_page_total_assets": "合计",
|
||||
"backup_all": "所有",
|
||||
"backup_background_service_backup_failed_message": "备份失败。重试中…",
|
||||
"backup_background_service_connection_failed_message": "连接时服务器失败。重试中…",
|
||||
"backup_background_service_current_upload_notification": "正在上传 {}",
|
||||
"backup_background_service_default_notification": "正在检查新数据…",
|
||||
"backup_background_service_error_title": "备份失败",
|
||||
"backup_background_service_in_progress_notification": "正在备份…",
|
||||
"backup_background_service_upload_failure_notification": "上传失败 {}",
|
||||
"backup_controller_page_albums": "备份相册",
|
||||
"backup_controller_page_background_battery_info_link": "怎么做",
|
||||
"backup_controller_page_background_battery_info_message": "为了获得最佳的后台备份体验,请禁用任何限制 Immich 后台活动的电池优化。\n\n由于这是设备相关的,因此请查找设备制造商所需的信息。",
|
||||
"backup_controller_page_background_battery_info_ok": "我知道了",
|
||||
"backup_controller_page_background_battery_info_title": "电池优化",
|
||||
"backup_controller_page_background_charging": "仅充电时",
|
||||
"backup_controller_page_background_configure_error": "配置后台服务失败",
|
||||
"backup_controller_page_background_delay": "延迟{}后备份",
|
||||
"backup_controller_page_background_description": "打开后台运行功能,不用打开应用你就能自动备份数据",
|
||||
"backup_controller_page_background_is_off": "后台自动备份已关闭",
|
||||
"backup_controller_page_background_is_on": "后台自动备份已开启",
|
||||
"backup_controller_page_background_turn_off": "关闭后台备份",
|
||||
"backup_controller_page_background_turn_on": "开启后台备份",
|
||||
"backup_controller_page_background_wifi": "仅WiFi",
|
||||
"backup_controller_page_backup": "备份",
|
||||
"backup_controller_page_backup_selected": "已选中:",
|
||||
"backup_controller_page_backup_sub": "已备份的照片和视频",
|
||||
"backup_controller_page_cancel": "取消",
|
||||
"backup_controller_page_created": "创建时间: {}",
|
||||
"backup_controller_page_desc_backup": "打开前台备份,程序运行时可以自动备份数据",
|
||||
"backup_controller_page_excluded": "已排除:",
|
||||
"backup_controller_page_failed": "失败 ({})",
|
||||
"backup_controller_page_filename": "文件名称: {} [{}]",
|
||||
"backup_controller_page_id": "ID: {}",
|
||||
"backup_controller_page_info": "备份信息",
|
||||
"backup_controller_page_none_selected": "未选择",
|
||||
"backup_controller_page_remainder": "剩余",
|
||||
"backup_controller_page_remainder_sub": "选中的数据中尚未备份的数据",
|
||||
"backup_controller_page_select": "选择",
|
||||
"backup_controller_page_server_storage": "服务器存储",
|
||||
"backup_controller_page_start_backup": "开始备份",
|
||||
"backup_controller_page_status_off": "前台自动备份已关闭",
|
||||
"backup_controller_page_status_on": "前台自动备份已开启",
|
||||
"backup_controller_page_storage_format": "{}/{} 已使用",
|
||||
"backup_controller_page_to_backup": "要备份的相册",
|
||||
"backup_controller_page_total": "合计",
|
||||
"backup_controller_page_total_sub": "选中相册中的所有不重复的视频和图片",
|
||||
"backup_controller_page_turn_off": "关闭前台备份",
|
||||
"backup_controller_page_turn_on": "开启前台备份",
|
||||
"backup_controller_page_uploading_file_info": "正在上传文件信息",
|
||||
"backup_err_only_album": "不能移除惟一的一个相册",
|
||||
"backup_info_card_assets": "张",
|
||||
"cache_settings_album_thumbnails": "图库缩略图({}张)",
|
||||
"cache_settings_clear_cache_button": "清除缓存",
|
||||
"cache_settings_clear_cache_button_title": "清除应用程序的缓存。在重新生成缓存之前,这将显著影响应用的性能。",
|
||||
"cache_settings_image_cache_size": "图片缓存大小({}张)",
|
||||
"cache_settings_statistics_album": "图库缩略图",
|
||||
"cache_settings_statistics_assets": "{} 张 ({})",
|
||||
"cache_settings_statistics_full": "完整图片",
|
||||
"cache_settings_statistics_shared": "共享相册缩略图",
|
||||
"cache_settings_statistics_thumbnail": "缩略图",
|
||||
"cache_settings_statistics_title": "缓存使用情况",
|
||||
"cache_settings_subtitle": "控制 Immich的缓存表现",
|
||||
"cache_settings_thumbnail_size": "缩略图缓存大小({}张)",
|
||||
"cache_settings_title": "缓存设置",
|
||||
"control_bottom_app_bar_add_to_album": "添加到相册",
|
||||
"control_bottom_app_bar_album_info": "{}张",
|
||||
"control_bottom_app_bar_album_info_shared": "{} 张已分享",
|
||||
"control_bottom_app_bar_create_new_album": "新建相册",
|
||||
"control_bottom_app_bar_delete": "删除",
|
||||
"control_bottom_app_bar_share": "分享",
|
||||
"create_album_page_untitled": "未命名",
|
||||
"create_shared_album_page_create": "新建",
|
||||
"create_shared_album_page_share": "分享",
|
||||
"create_shared_album_page_share_add_assets": "新增照片",
|
||||
"create_shared_album_page_share_select_photos": "选择照片",
|
||||
"daily_title_text_date": "\t\n\nE, MMM dd",
|
||||
"daily_title_text_date_year": "E, MMM dd, yyyy",
|
||||
"date_format": "E, LLL d, y • h:mm a",
|
||||
"delete_dialog_alert": "这些数据将会永久性的从Immich和你的设备上删除",
|
||||
"delete_dialog_cancel": "取消",
|
||||
"delete_dialog_ok": "删除",
|
||||
"delete_dialog_title": "永久删除",
|
||||
"exif_bottom_sheet_description": "增加描述...",
|
||||
"exif_bottom_sheet_details": "详情",
|
||||
"exif_bottom_sheet_location": "位置",
|
||||
"experimental_settings_new_asset_list_subtitle": "正在努力处理中",
|
||||
"experimental_settings_new_asset_list_title": "启用实验性的照片宫格",
|
||||
"experimental_settings_subtitle": "使用风险自负!",
|
||||
"experimental_settings_title": "实验功能",
|
||||
"home_page_add_to_album_conflicts": "添加{added}张到相册{album}。{failed} 项已经处于该相册中。",
|
||||
"home_page_add_to_album_success": "添加了{added}张到相册{album}。",
|
||||
"library_page_albums": "相册",
|
||||
"library_page_new_album": "新建相册",
|
||||
"login_form_button_text": "登录",
|
||||
"login_form_email_hint": "youremail@email.com",
|
||||
"login_form_endpoint_hint": "http://your-server-ip:port/api",
|
||||
"login_form_endpoint_url": "服务器地址",
|
||||
"login_form_err_http": "请检查http://或https://",
|
||||
"login_form_err_invalid_email": "请输入正确的邮箱",
|
||||
"login_form_err_leading_whitespace": "前面空格",
|
||||
"login_form_err_trailing_whitespace": "后面空格",
|
||||
"login_form_failed_get_oauth_server_config": "使用 OAuth 时出错,请检查服务器 地址",
|
||||
"login_form_failed_get_oauth_server_disable": "OAuth 功能在此服务器上不可用",
|
||||
"login_form_failed_login": "登录失败, 请检查邮箱、密码和服务器地址",
|
||||
"login_form_label_email": "邮箱",
|
||||
"login_form_label_password": "密码",
|
||||
"login_form_password_hint": "密码",
|
||||
"login_form_save_login": "保持登录",
|
||||
"monthly_title_text_date_format": "MMMM y",
|
||||
"profile_drawer_app_logs": "日志",
|
||||
"profile_drawer_client_server_up_to_date": "客户端和服务端都是最新的",
|
||||
"profile_drawer_settings": "设置",
|
||||
"profile_drawer_sign_out": "退出登录",
|
||||
"search_bar_hint": "搜索照片",
|
||||
"search_page_no_objects": "没有事物信息",
|
||||
"search_page_no_places": "地点信息不存在",
|
||||
"search_page_places": "地点",
|
||||
"search_page_things": "事物",
|
||||
"search_result_page_new_search_hint": "搜索新的",
|
||||
"select_additional_user_for_sharing_page_suggestions": "建议",
|
||||
"select_user_for_sharing_page_err_album": "创建相册失败",
|
||||
"select_user_for_sharing_page_share_suggestions": "建议",
|
||||
"setting_image_viewer_help": "查看大图时会首先加载缩略图,然后加载中等质量的图片(如果启用),最后加载原始质量的图片(如果启用)。",
|
||||
"setting_image_viewer_original_subtitle": "开启将会加载原图。关闭将会减少内存和网络占用。",
|
||||
"setting_image_viewer_original_title": "加载原图",
|
||||
"setting_image_viewer_preview_subtitle": "开启将会加载中等质量的图片,关闭后会加载原图或预览图。",
|
||||
"setting_image_viewer_preview_title": "加载中等质量图片",
|
||||
"setting_notifications_notify_failures_grace_period": "后台备份失败通知: {}",
|
||||
"setting_notifications_notify_hours": "{}小时",
|
||||
"setting_notifications_notify_immediately": "立即",
|
||||
"setting_notifications_notify_minutes": "{}分钟",
|
||||
"setting_notifications_notify_never": "从不",
|
||||
"setting_notifications_notify_seconds": "{} 秒",
|
||||
"setting_notifications_single_progress_subtitle": "每张图片的详细备份进度",
|
||||
"setting_notifications_single_progress_title": "总体上传进度(已完成/所有内容)",
|
||||
"setting_notifications_subtitle": "调整您的通知偏好",
|
||||
"setting_notifications_title": "通知",
|
||||
"setting_notifications_total_progress_subtitle": "总体上传进度(已完成/所有内容)",
|
||||
"setting_notifications_total_progress_title": "展示后台整体备份进度",
|
||||
"setting_pages_app_bar_settings": "设置",
|
||||
"settings_require_restart": "请重启Immich使配置生效",
|
||||
"share_add": "新增",
|
||||
"share_add_photos": "新增照片",
|
||||
"share_add_title": "新增标题",
|
||||
"share_create_album": "新建相册",
|
||||
"share_dialog_preparing": "准备中...",
|
||||
"share_invite": "邀请共享相册",
|
||||
"sharing_page_album": "共享相册",
|
||||
"sharing_page_description": "新建共享相册以分享图片和视频给你的网络中的其他人。",
|
||||
"sharing_page_empty_list": "空",
|
||||
"sharing_silver_appbar_create_shared_album": "创建共享相册",
|
||||
"sharing_silver_appbar_share_partner": "分享给同伴",
|
||||
"tab_controller_nav_library": "图库",
|
||||
"tab_controller_nav_photos": "照片",
|
||||
"tab_controller_nav_search": "搜索",
|
||||
"tab_controller_nav_sharing": "分享",
|
||||
"theme_setting_asset_list_storage_indicator_title": "在图片标题展示存储占用",
|
||||
"theme_setting_asset_list_tiles_per_row_title": "每行展示({})张图片",
|
||||
"theme_setting_dark_mode_switch": "黑暗模式",
|
||||
"theme_setting_image_viewer_quality_subtitle": "查看大图时的图片质量",
|
||||
"theme_setting_image_viewer_quality_title": "图片质量",
|
||||
"theme_setting_system_theme_switch": "自动 (跟随系统)",
|
||||
"theme_setting_theme_subtitle": "选择应用的主题",
|
||||
"theme_setting_theme_title": "主题",
|
||||
"theme_setting_three_stage_loading_subtitle": "三段式加载可能会提升加载速度,但是可能会造成更高的网络负载",
|
||||
"theme_setting_three_stage_loading_title": "启用三段式加载",
|
||||
"version_announcement_overlay_ack": "我知道啦",
|
||||
"version_announcement_overlay_release_notes": "发行说明",
|
||||
"version_announcement_overlay_text_1": "号外号外,",
|
||||
"version_announcement_overlay_text_2": "发布新版本啦!为避免缺少配置,请您抽出时间访问",
|
||||
"version_announcement_overlay_text_3": "并检查您的docker-compose和.env是否为最新的。如果您使用WatchTower或者其他自动更新程序方式,您需要更加细致的检查。",
|
||||
"version_announcement_overlay_title": "服务端有新版本啦 \uD83C\uDF89"
|
||||
}
|
||||
@@ -360,7 +360,7 @@
|
||||
CODE_SIGN_ENTITLEMENTS = Runner/RunnerProfile.entitlements;
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 74;
|
||||
CURRENT_PROJECT_VERSION = 76;
|
||||
DEVELOPMENT_TEAM = 2F67MQ8R79;
|
||||
ENABLE_BITCODE = NO;
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
@@ -495,7 +495,7 @@
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 74;
|
||||
CURRENT_PROJECT_VERSION = 76;
|
||||
DEVELOPMENT_TEAM = 2F67MQ8R79;
|
||||
ENABLE_BITCODE = NO;
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
@@ -522,7 +522,7 @@
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 74;
|
||||
CURRENT_PROJECT_VERSION = 76;
|
||||
DEVELOPMENT_TEAM = 2F67MQ8R79;
|
||||
ENABLE_BITCODE = NO;
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
|
||||
@@ -17,11 +17,11 @@
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.37.1</string>
|
||||
<string>1.39.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>74</string>
|
||||
<string>76</string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true />
|
||||
<key>MGLMapboxMetricsEnabledSettingShownInApp</key>
|
||||
@@ -58,7 +58,7 @@
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations~ipad</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
@@ -66,7 +66,7 @@
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
|
||||
|
||||
<key>UIViewControllerBasedStatusBarAppearance</key>
|
||||
<true />
|
||||
<key>io.flutter.embedded_views_preview</key>
|
||||
@@ -84,18 +84,22 @@
|
||||
|
||||
<key>CFBundleLocalizations</key>
|
||||
<array>
|
||||
<string>en</string>
|
||||
<string>de</string>
|
||||
<string>cs</string>
|
||||
<string>da</string>
|
||||
<string>de</string>
|
||||
<string>en</string>
|
||||
<string>es</string>
|
||||
<string>fi</string>
|
||||
<string>fr</string>
|
||||
<string>it</string>
|
||||
<string>fi</string>
|
||||
<string>ja</string>
|
||||
<string>ko</string>
|
||||
<string>nl</string>
|
||||
<string>pl</string>
|
||||
<string>pt</string>
|
||||
<string>ru</string>
|
||||
<string>sk</string>
|
||||
<string>zh</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -19,7 +19,7 @@ platform :ios do
|
||||
desc "iOS Beta"
|
||||
lane :beta do
|
||||
increment_version_number(
|
||||
version_number: "1.38.0"
|
||||
version_number: "1.39.0"
|
||||
)
|
||||
increment_build_number(
|
||||
build_number: latest_testflight_build_number + 1,
|
||||
|
||||
@@ -5,29 +5,32 @@
|
||||
|
||||
|
||||
|
||||
<testcase classname="fastlane.lanes" name="0: default_platform" time="0.000334">
|
||||
<testcase classname="fastlane.lanes" name="0: default_platform" time="0.000212">
|
||||
|
||||
</testcase>
|
||||
|
||||
|
||||
<testcase classname="fastlane.lanes" name="1: increment_version_number" time="1.671363">
|
||||
<testcase classname="fastlane.lanes" name="1: increment_version_number" time="1.00785">
|
||||
|
||||
</testcase>
|
||||
|
||||
|
||||
<testcase classname="fastlane.lanes" name="2: latest_testflight_build_number" time="7.167423">
|
||||
<testcase classname="fastlane.lanes" name="2: latest_testflight_build_number" time="5.724004">
|
||||
|
||||
</testcase>
|
||||
|
||||
|
||||
<testcase classname="fastlane.lanes" name="3: increment_build_number" time="0.654653">
|
||||
<testcase classname="fastlane.lanes" name="3: increment_build_number" time="0.670744">
|
||||
|
||||
</testcase>
|
||||
|
||||
|
||||
<testcase classname="fastlane.lanes" name="4: build_app" time="29.319346">
|
||||
<testcase classname="fastlane.lanes" name="4: build_app" time="85.266784">
|
||||
|
||||
<failure message="/usr/local/Cellar/fastlane/2.210.1/libexec/gems/fastlane-2.210.1/fastlane/lib/fastlane/actions/actions_helper.rb:67:in `execute_action' /usr/local/Cellar/fastlane/2.210.1/libexec/gems/fastlane-2.210.1/fastlane/lib/fastlane/runner.rb:255:in `block in execute_action' /usr/local/Cellar/fastlane/2.210.1/libexec/gems/fastlane-2.210.1/fastlane/lib/fastlane/runner.rb:229:in `chdir' /usr/local/Cellar/fastlane/2.210.1/libexec/gems/fastlane-2.210.1/fastlane/lib/fastlane/runner.rb:229:in `execute_action' /usr/local/Cellar/fastlane/2.210.1/libexec/gems/fastlane-2.210.1/fastlane/lib/fastlane/runner.rb:157:in `trigger_action_by_name' /usr/local/Cellar/fastlane/2.210.1/libexec/gems/fastlane-2.210.1/fastlane/lib/fastlane/fast_file.rb:159:in `method_missing' Fastfile:27:in `block (2 levels) in parsing_binding' /usr/local/Cellar/fastlane/2.210.1/libexec/gems/fastlane-2.210.1/fastlane/lib/fastlane/lane.rb:33:in `call' /usr/local/Cellar/fastlane/2.210.1/libexec/gems/fastlane-2.210.1/fastlane/lib/fastlane/runner.rb:49:in `block in execute' /usr/local/Cellar/fastlane/2.210.1/libexec/gems/fastlane-2.210.1/fastlane/lib/fastlane/runner.rb:45:in `chdir' /usr/local/Cellar/fastlane/2.210.1/libexec/gems/fastlane-2.210.1/fastlane/lib/fastlane/runner.rb:45:in `execute' /usr/local/Cellar/fastlane/2.210.1/libexec/gems/fastlane-2.210.1/fastlane/lib/fastlane/lane_manager.rb:47:in `cruise_lane' /usr/local/Cellar/fastlane/2.210.1/libexec/gems/fastlane-2.210.1/fastlane/lib/fastlane/command_line_handler.rb:36:in `handle' /usr/local/Cellar/fastlane/2.210.1/libexec/gems/fastlane-2.210.1/fastlane/lib/fastlane/commands_generator.rb:110:in `block (2 levels) in run' /usr/local/Cellar/fastlane/2.210.1/libexec/gems/commander-4.6.0/lib/commander/command.rb:187:in `call' /usr/local/Cellar/fastlane/2.210.1/libexec/gems/commander-4.6.0/lib/commander/command.rb:157:in `run' /usr/local/Cellar/fastlane/2.210.1/libexec/gems/commander-4.6.0/lib/commander/runner.rb:444:in `run_active_command' /usr/local/Cellar/fastlane/2.210.1/libexec/gems/fastlane-2.210.1/fastlane_core/lib/fastlane_core/ui/fastlane_runner.rb:124:in `run!' /usr/local/Cellar/fastlane/2.210.1/libexec/gems/commander-4.6.0/lib/commander/delegates.rb:18:in `run!' /usr/local/Cellar/fastlane/2.210.1/libexec/gems/fastlane-2.210.1/fastlane/lib/fastlane/commands_generator.rb:354:in `run' /usr/local/Cellar/fastlane/2.210.1/libexec/gems/fastlane-2.210.1/fastlane/lib/fastlane/commands_generator.rb:43:in `start' /usr/local/Cellar/fastlane/2.210.1/libexec/gems/fastlane-2.210.1/fastlane/lib/fastlane/cli_tools_distributor.rb:123:in `take_off' /usr/local/Cellar/fastlane/2.210.1/libexec/gems/fastlane-2.210.1/bin/fastlane:23:in `<top (required)>' /usr/local/Cellar/fastlane/2.210.1/libexec/bin/fastlane:25:in `load' /usr/local/Cellar/fastlane/2.210.1/libexec/bin/fastlane:25:in `<main>' Error building the application - see the log above" />
|
||||
</testcase>
|
||||
|
||||
|
||||
<testcase classname="fastlane.lanes" name="5: upload_to_testflight" time="59.733923">
|
||||
|
||||
</testcase>
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ const List<Locale> locales = [
|
||||
// Default locale
|
||||
Locale('en', 'US'),
|
||||
// Additional locales
|
||||
Locale('cs', 'CZ'),
|
||||
Locale('da', 'DK'),
|
||||
Locale('de', 'DE'),
|
||||
Locale('es', 'ES'),
|
||||
@@ -11,10 +12,13 @@ const List<Locale> locales = [
|
||||
Locale('fr', 'FR'),
|
||||
Locale('it', 'IT'),
|
||||
Locale('ja', 'JP'),
|
||||
Locale('ko', 'KR'),
|
||||
Locale('nl', 'NL'),
|
||||
Locale('pl', 'PL'),
|
||||
Locale('pt', 'PR'),
|
||||
Locale('ko', 'KR'),
|
||||
Locale('ru', 'RU'),
|
||||
Locale('sk', 'SK'),
|
||||
Locale('zh', 'CN'),
|
||||
];
|
||||
|
||||
const String translationsPath = 'assets/i18n';
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:immich_mobile/shared/models/asset.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
|
||||
final log = Logger('AssetGridDataStructure');
|
||||
|
||||
enum RenderAssetGridElementType {
|
||||
assetRow,
|
||||
@@ -64,46 +67,50 @@ List<RenderAssetGridElement> assetGroupsToRenderList(
|
||||
DateTime? lastDate;
|
||||
|
||||
assetGroups.forEach((groupName, assets) {
|
||||
final date = DateTime.parse(groupName);
|
||||
try {
|
||||
final date = DateTime.parse(groupName);
|
||||
|
||||
if (lastDate == null || lastDate!.month != date.month) {
|
||||
if (lastDate == null || lastDate!.month != date.month) {
|
||||
elements.add(
|
||||
RenderAssetGridElement(
|
||||
RenderAssetGridElementType.monthTitle,
|
||||
title: groupName,
|
||||
date: date,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// Add group title
|
||||
elements.add(
|
||||
RenderAssetGridElement(
|
||||
RenderAssetGridElementType.monthTitle,
|
||||
RenderAssetGridElementType.dayTitle,
|
||||
title: groupName,
|
||||
date: date,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// Add group title
|
||||
elements.add(
|
||||
RenderAssetGridElement(
|
||||
RenderAssetGridElementType.dayTitle,
|
||||
title: groupName,
|
||||
date: date,
|
||||
relatedAssetList: assets,
|
||||
),
|
||||
);
|
||||
|
||||
// Add rows
|
||||
int cursor = 0;
|
||||
while (cursor < assets.length) {
|
||||
int rowElements = min(assets.length - cursor, assetsPerRow);
|
||||
|
||||
final rowElement = RenderAssetGridElement(
|
||||
RenderAssetGridElementType.assetRow,
|
||||
date: date,
|
||||
assetRow: RenderAssetGridRow(
|
||||
assets.sublist(cursor, cursor + rowElements),
|
||||
relatedAssetList: assets,
|
||||
),
|
||||
);
|
||||
|
||||
elements.add(rowElement);
|
||||
cursor += rowElements;
|
||||
}
|
||||
// Add rows
|
||||
int cursor = 0;
|
||||
while (cursor < assets.length) {
|
||||
int rowElements = min(assets.length - cursor, assetsPerRow);
|
||||
|
||||
lastDate = date;
|
||||
final rowElement = RenderAssetGridElement(
|
||||
RenderAssetGridElementType.assetRow,
|
||||
date: date,
|
||||
assetRow: RenderAssetGridRow(
|
||||
assets.sublist(cursor, cursor + rowElements),
|
||||
),
|
||||
);
|
||||
|
||||
elements.add(rowElement);
|
||||
cursor += rowElements;
|
||||
}
|
||||
|
||||
lastDate = date;
|
||||
} catch (e, stackTrace) {
|
||||
log.severe(e, stackTrace);
|
||||
}
|
||||
});
|
||||
|
||||
return elements;
|
||||
|
||||
6
mobile/openapi/.openapi-generator/FILES
generated
6
mobile/openapi/.openapi-generator/FILES
generated
@@ -64,6 +64,8 @@ doc/SystemConfigApi.md
|
||||
doc/SystemConfigDto.md
|
||||
doc/SystemConfigFFmpegDto.md
|
||||
doc/SystemConfigOAuthDto.md
|
||||
doc/SystemConfigStorageTemplateDto.md
|
||||
doc/SystemConfigTemplateStorageOptionDto.md
|
||||
doc/TagApi.md
|
||||
doc/TagResponseDto.md
|
||||
doc/TagTypeEnum.md
|
||||
@@ -152,6 +154,8 @@ lib/model/smart_info_response_dto.dart
|
||||
lib/model/system_config_dto.dart
|
||||
lib/model/system_config_f_fmpeg_dto.dart
|
||||
lib/model/system_config_o_auth_dto.dart
|
||||
lib/model/system_config_storage_template_dto.dart
|
||||
lib/model/system_config_template_storage_option_dto.dart
|
||||
lib/model/tag_response_dto.dart
|
||||
lib/model/tag_type_enum.dart
|
||||
lib/model/thumbnail_format.dart
|
||||
@@ -227,6 +231,8 @@ test/system_config_api_test.dart
|
||||
test/system_config_dto_test.dart
|
||||
test/system_config_f_fmpeg_dto_test.dart
|
||||
test/system_config_o_auth_dto_test.dart
|
||||
test/system_config_storage_template_dto_test.dart
|
||||
test/system_config_template_storage_option_dto_test.dart
|
||||
test/tag_api_test.dart
|
||||
test/tag_response_dto_test.dart
|
||||
test/tag_type_enum_test.dart
|
||||
|
||||
5
mobile/openapi/README.md
generated
5
mobile/openapi/README.md
generated
@@ -3,7 +3,7 @@ Immich API
|
||||
|
||||
This Dart package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project:
|
||||
|
||||
- API version: 1.38.0
|
||||
- API version: 1.38.2
|
||||
- Build package: org.openapitools.codegen.languages.DartClientCodegen
|
||||
|
||||
## Requirements
|
||||
@@ -113,6 +113,7 @@ Class | Method | HTTP request | Description
|
||||
*ServerInfoApi* | [**pingServer**](doc//ServerInfoApi.md#pingserver) | **GET** /server-info/ping |
|
||||
*SystemConfigApi* | [**getConfig**](doc//SystemConfigApi.md#getconfig) | **GET** /system-config |
|
||||
*SystemConfigApi* | [**getDefaults**](doc//SystemConfigApi.md#getdefaults) | **GET** /system-config/defaults |
|
||||
*SystemConfigApi* | [**getStorageTemplateOptions**](doc//SystemConfigApi.md#getstoragetemplateoptions) | **GET** /system-config/storage-template-options |
|
||||
*SystemConfigApi* | [**updateConfig**](doc//SystemConfigApi.md#updateconfig) | **PUT** /system-config |
|
||||
*TagApi* | [**create**](doc//TagApi.md#create) | **POST** /tag |
|
||||
*TagApi* | [**delete**](doc//TagApi.md#delete) | **DELETE** /tag/{id} |
|
||||
@@ -186,6 +187,8 @@ Class | Method | HTTP request | Description
|
||||
- [SystemConfigDto](doc//SystemConfigDto.md)
|
||||
- [SystemConfigFFmpegDto](doc//SystemConfigFFmpegDto.md)
|
||||
- [SystemConfigOAuthDto](doc//SystemConfigOAuthDto.md)
|
||||
- [SystemConfigStorageTemplateDto](doc//SystemConfigStorageTemplateDto.md)
|
||||
- [SystemConfigTemplateStorageOptionDto](doc//SystemConfigTemplateStorageOptionDto.md)
|
||||
- [TagResponseDto](doc//TagResponseDto.md)
|
||||
- [TagTypeEnum](doc//TagTypeEnum.md)
|
||||
- [ThumbnailFormat](doc//ThumbnailFormat.md)
|
||||
|
||||
2
mobile/openapi/doc/AllJobStatusResponseDto.md
generated
2
mobile/openapi/doc/AllJobStatusResponseDto.md
generated
@@ -12,10 +12,12 @@ Name | Type | Description | Notes
|
||||
**metadataExtractionQueueCount** | [**JobCounts**](JobCounts.md) | |
|
||||
**videoConversionQueueCount** | [**JobCounts**](JobCounts.md) | |
|
||||
**machineLearningQueueCount** | [**JobCounts**](JobCounts.md) | |
|
||||
**storageMigrationQueueCount** | [**JobCounts**](JobCounts.md) | |
|
||||
**isThumbnailGenerationActive** | **bool** | |
|
||||
**isMetadataExtractionActive** | **bool** | |
|
||||
**isVideoConversionActive** | **bool** | |
|
||||
**isMachineLearningActive** | **bool** | |
|
||||
**isStorageMigrationActive** | **bool** | |
|
||||
|
||||
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
|
||||
|
||||
|
||||
44
mobile/openapi/doc/SystemConfigApi.md
generated
44
mobile/openapi/doc/SystemConfigApi.md
generated
@@ -11,6 +11,7 @@ Method | HTTP request | Description
|
||||
------------- | ------------- | -------------
|
||||
[**getConfig**](SystemConfigApi.md#getconfig) | **GET** /system-config |
|
||||
[**getDefaults**](SystemConfigApi.md#getdefaults) | **GET** /system-config/defaults |
|
||||
[**getStorageTemplateOptions**](SystemConfigApi.md#getstoragetemplateoptions) | **GET** /system-config/storage-template-options |
|
||||
[**updateConfig**](SystemConfigApi.md#updateconfig) | **PUT** /system-config |
|
||||
|
||||
|
||||
@@ -100,6 +101,49 @@ This endpoint does not need any parameter.
|
||||
|
||||
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
|
||||
|
||||
# **getStorageTemplateOptions**
|
||||
> SystemConfigTemplateStorageOptionDto getStorageTemplateOptions()
|
||||
|
||||
|
||||
|
||||
### Example
|
||||
```dart
|
||||
import 'package:openapi/api.dart';
|
||||
// TODO Configure HTTP Bearer authorization: bearer
|
||||
// Case 1. Use String Token
|
||||
//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken('YOUR_ACCESS_TOKEN');
|
||||
// Case 2. Use Function which generate token.
|
||||
// String yourTokenGeneratorFunction() { ... }
|
||||
//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken(yourTokenGeneratorFunction);
|
||||
|
||||
final api_instance = SystemConfigApi();
|
||||
|
||||
try {
|
||||
final result = api_instance.getStorageTemplateOptions();
|
||||
print(result);
|
||||
} catch (e) {
|
||||
print('Exception when calling SystemConfigApi->getStorageTemplateOptions: $e\n');
|
||||
}
|
||||
```
|
||||
|
||||
### Parameters
|
||||
This endpoint does not need any parameter.
|
||||
|
||||
### Return type
|
||||
|
||||
[**SystemConfigTemplateStorageOptionDto**](SystemConfigTemplateStorageOptionDto.md)
|
||||
|
||||
### Authorization
|
||||
|
||||
[bearer](../README.md#bearer)
|
||||
|
||||
### HTTP request headers
|
||||
|
||||
- **Content-Type**: Not defined
|
||||
- **Accept**: application/json
|
||||
|
||||
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
|
||||
|
||||
# **updateConfig**
|
||||
> SystemConfigDto updateConfig(systemConfigDto)
|
||||
|
||||
|
||||
1
mobile/openapi/doc/SystemConfigDto.md
generated
1
mobile/openapi/doc/SystemConfigDto.md
generated
@@ -10,6 +10,7 @@ Name | Type | Description | Notes
|
||||
------------ | ------------- | ------------- | -------------
|
||||
**ffmpeg** | [**SystemConfigFFmpegDto**](SystemConfigFFmpegDto.md) | |
|
||||
**oauth** | [**SystemConfigOAuthDto**](SystemConfigOAuthDto.md) | |
|
||||
**storageTemplate** | [**SystemConfigStorageTemplateDto**](SystemConfigStorageTemplateDto.md) | |
|
||||
|
||||
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
|
||||
|
||||
|
||||
15
mobile/openapi/doc/SystemConfigStorageTemplateDto.md
generated
Normal file
15
mobile/openapi/doc/SystemConfigStorageTemplateDto.md
generated
Normal file
@@ -0,0 +1,15 @@
|
||||
# openapi.model.SystemConfigStorageTemplateDto
|
||||
|
||||
## Load the model package
|
||||
```dart
|
||||
import 'package:openapi/api.dart';
|
||||
```
|
||||
|
||||
## Properties
|
||||
Name | Type | Description | Notes
|
||||
------------ | ------------- | ------------- | -------------
|
||||
**template** | **String** | |
|
||||
|
||||
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
|
||||
|
||||
|
||||
21
mobile/openapi/doc/SystemConfigTemplateStorageOptionDto.md
generated
Normal file
21
mobile/openapi/doc/SystemConfigTemplateStorageOptionDto.md
generated
Normal file
@@ -0,0 +1,21 @@
|
||||
# openapi.model.SystemConfigTemplateStorageOptionDto
|
||||
|
||||
## Load the model package
|
||||
```dart
|
||||
import 'package:openapi/api.dart';
|
||||
```
|
||||
|
||||
## Properties
|
||||
Name | Type | Description | Notes
|
||||
------------ | ------------- | ------------- | -------------
|
||||
**yearOptions** | **List<String>** | | [default to const []]
|
||||
**monthOptions** | **List<String>** | | [default to const []]
|
||||
**dayOptions** | **List<String>** | | [default to const []]
|
||||
**hourOptions** | **List<String>** | | [default to const []]
|
||||
**minuteOptions** | **List<String>** | | [default to const []]
|
||||
**secondOptions** | **List<String>** | | [default to const []]
|
||||
**presetOptions** | **List<String>** | | [default to const []]
|
||||
|
||||
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
|
||||
|
||||
|
||||
2
mobile/openapi/lib/api.dart
generated
2
mobile/openapi/lib/api.dart
generated
@@ -91,6 +91,8 @@ part 'model/smart_info_response_dto.dart';
|
||||
part 'model/system_config_dto.dart';
|
||||
part 'model/system_config_f_fmpeg_dto.dart';
|
||||
part 'model/system_config_o_auth_dto.dart';
|
||||
part 'model/system_config_storage_template_dto.dart';
|
||||
part 'model/system_config_template_storage_option_dto.dart';
|
||||
part 'model/tag_response_dto.dart';
|
||||
part 'model/tag_type_enum.dart';
|
||||
part 'model/thumbnail_format.dart';
|
||||
|
||||
41
mobile/openapi/lib/api/system_config_api.dart
generated
41
mobile/openapi/lib/api/system_config_api.dart
generated
@@ -98,6 +98,47 @@ class SystemConfigApi {
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Performs an HTTP 'GET /system-config/storage-template-options' operation and returns the [Response].
|
||||
Future<Response> getStorageTemplateOptionsWithHttpInfo() async {
|
||||
// ignore: prefer_const_declarations
|
||||
final path = r'/system-config/storage-template-options';
|
||||
|
||||
// ignore: prefer_final_locals
|
||||
Object? postBody;
|
||||
|
||||
final queryParams = <QueryParam>[];
|
||||
final headerParams = <String, String>{};
|
||||
final formParams = <String, String>{};
|
||||
|
||||
const contentTypes = <String>[];
|
||||
|
||||
|
||||
return apiClient.invokeAPI(
|
||||
path,
|
||||
'GET',
|
||||
queryParams,
|
||||
postBody,
|
||||
headerParams,
|
||||
formParams,
|
||||
contentTypes.isEmpty ? null : contentTypes.first,
|
||||
);
|
||||
}
|
||||
|
||||
Future<SystemConfigTemplateStorageOptionDto?> getStorageTemplateOptions() async {
|
||||
final response = await getStorageTemplateOptionsWithHttpInfo();
|
||||
if (response.statusCode >= HttpStatus.badRequest) {
|
||||
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
|
||||
}
|
||||
// When a remote server returns no body with a status of 204, we shall not decode it.
|
||||
// At the time of writing this, `dart:convert` will throw an "Unexpected end of input"
|
||||
// FormatException when trying to decode an empty string.
|
||||
if (response.body.isNotEmpty && response.statusCode != HttpStatus.noContent) {
|
||||
return await apiClient.deserializeAsync(await _decodeBodyBytes(response), 'SystemConfigTemplateStorageOptionDto',) as SystemConfigTemplateStorageOptionDto;
|
||||
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Performs an HTTP 'PUT /system-config' operation and returns the [Response].
|
||||
/// Parameters:
|
||||
///
|
||||
|
||||
4
mobile/openapi/lib/api_client.dart
generated
4
mobile/openapi/lib/api_client.dart
generated
@@ -298,6 +298,10 @@ class ApiClient {
|
||||
return SystemConfigFFmpegDto.fromJson(value);
|
||||
case 'SystemConfigOAuthDto':
|
||||
return SystemConfigOAuthDto.fromJson(value);
|
||||
case 'SystemConfigStorageTemplateDto':
|
||||
return SystemConfigStorageTemplateDto.fromJson(value);
|
||||
case 'SystemConfigTemplateStorageOptionDto':
|
||||
return SystemConfigTemplateStorageOptionDto.fromJson(value);
|
||||
case 'TagResponseDto':
|
||||
return TagResponseDto.fromJson(value);
|
||||
case 'TagTypeEnum':
|
||||
|
||||
@@ -17,10 +17,12 @@ class AllJobStatusResponseDto {
|
||||
required this.metadataExtractionQueueCount,
|
||||
required this.videoConversionQueueCount,
|
||||
required this.machineLearningQueueCount,
|
||||
required this.storageMigrationQueueCount,
|
||||
required this.isThumbnailGenerationActive,
|
||||
required this.isMetadataExtractionActive,
|
||||
required this.isVideoConversionActive,
|
||||
required this.isMachineLearningActive,
|
||||
required this.isStorageMigrationActive,
|
||||
});
|
||||
|
||||
JobCounts thumbnailGenerationQueueCount;
|
||||
@@ -31,6 +33,8 @@ class AllJobStatusResponseDto {
|
||||
|
||||
JobCounts machineLearningQueueCount;
|
||||
|
||||
JobCounts storageMigrationQueueCount;
|
||||
|
||||
bool isThumbnailGenerationActive;
|
||||
|
||||
bool isMetadataExtractionActive;
|
||||
@@ -39,16 +43,20 @@ class AllJobStatusResponseDto {
|
||||
|
||||
bool isMachineLearningActive;
|
||||
|
||||
bool isStorageMigrationActive;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) => identical(this, other) || other is AllJobStatusResponseDto &&
|
||||
other.thumbnailGenerationQueueCount == thumbnailGenerationQueueCount &&
|
||||
other.metadataExtractionQueueCount == metadataExtractionQueueCount &&
|
||||
other.videoConversionQueueCount == videoConversionQueueCount &&
|
||||
other.machineLearningQueueCount == machineLearningQueueCount &&
|
||||
other.storageMigrationQueueCount == storageMigrationQueueCount &&
|
||||
other.isThumbnailGenerationActive == isThumbnailGenerationActive &&
|
||||
other.isMetadataExtractionActive == isMetadataExtractionActive &&
|
||||
other.isVideoConversionActive == isVideoConversionActive &&
|
||||
other.isMachineLearningActive == isMachineLearningActive;
|
||||
other.isMachineLearningActive == isMachineLearningActive &&
|
||||
other.isStorageMigrationActive == isStorageMigrationActive;
|
||||
|
||||
@override
|
||||
int get hashCode =>
|
||||
@@ -57,13 +65,15 @@ class AllJobStatusResponseDto {
|
||||
(metadataExtractionQueueCount.hashCode) +
|
||||
(videoConversionQueueCount.hashCode) +
|
||||
(machineLearningQueueCount.hashCode) +
|
||||
(storageMigrationQueueCount.hashCode) +
|
||||
(isThumbnailGenerationActive.hashCode) +
|
||||
(isMetadataExtractionActive.hashCode) +
|
||||
(isVideoConversionActive.hashCode) +
|
||||
(isMachineLearningActive.hashCode);
|
||||
(isMachineLearningActive.hashCode) +
|
||||
(isStorageMigrationActive.hashCode);
|
||||
|
||||
@override
|
||||
String toString() => 'AllJobStatusResponseDto[thumbnailGenerationQueueCount=$thumbnailGenerationQueueCount, metadataExtractionQueueCount=$metadataExtractionQueueCount, videoConversionQueueCount=$videoConversionQueueCount, machineLearningQueueCount=$machineLearningQueueCount, isThumbnailGenerationActive=$isThumbnailGenerationActive, isMetadataExtractionActive=$isMetadataExtractionActive, isVideoConversionActive=$isVideoConversionActive, isMachineLearningActive=$isMachineLearningActive]';
|
||||
String toString() => 'AllJobStatusResponseDto[thumbnailGenerationQueueCount=$thumbnailGenerationQueueCount, metadataExtractionQueueCount=$metadataExtractionQueueCount, videoConversionQueueCount=$videoConversionQueueCount, machineLearningQueueCount=$machineLearningQueueCount, storageMigrationQueueCount=$storageMigrationQueueCount, isThumbnailGenerationActive=$isThumbnailGenerationActive, isMetadataExtractionActive=$isMetadataExtractionActive, isVideoConversionActive=$isVideoConversionActive, isMachineLearningActive=$isMachineLearningActive, isStorageMigrationActive=$isStorageMigrationActive]';
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final _json = <String, dynamic>{};
|
||||
@@ -71,10 +81,12 @@ class AllJobStatusResponseDto {
|
||||
_json[r'metadataExtractionQueueCount'] = metadataExtractionQueueCount;
|
||||
_json[r'videoConversionQueueCount'] = videoConversionQueueCount;
|
||||
_json[r'machineLearningQueueCount'] = machineLearningQueueCount;
|
||||
_json[r'storageMigrationQueueCount'] = storageMigrationQueueCount;
|
||||
_json[r'isThumbnailGenerationActive'] = isThumbnailGenerationActive;
|
||||
_json[r'isMetadataExtractionActive'] = isMetadataExtractionActive;
|
||||
_json[r'isVideoConversionActive'] = isVideoConversionActive;
|
||||
_json[r'isMachineLearningActive'] = isMachineLearningActive;
|
||||
_json[r'isStorageMigrationActive'] = isStorageMigrationActive;
|
||||
return _json;
|
||||
}
|
||||
|
||||
@@ -101,10 +113,12 @@ class AllJobStatusResponseDto {
|
||||
metadataExtractionQueueCount: JobCounts.fromJson(json[r'metadataExtractionQueueCount'])!,
|
||||
videoConversionQueueCount: JobCounts.fromJson(json[r'videoConversionQueueCount'])!,
|
||||
machineLearningQueueCount: JobCounts.fromJson(json[r'machineLearningQueueCount'])!,
|
||||
storageMigrationQueueCount: JobCounts.fromJson(json[r'storageMigrationQueueCount'])!,
|
||||
isThumbnailGenerationActive: mapValueOfType<bool>(json, r'isThumbnailGenerationActive')!,
|
||||
isMetadataExtractionActive: mapValueOfType<bool>(json, r'isMetadataExtractionActive')!,
|
||||
isVideoConversionActive: mapValueOfType<bool>(json, r'isVideoConversionActive')!,
|
||||
isMachineLearningActive: mapValueOfType<bool>(json, r'isMachineLearningActive')!,
|
||||
isStorageMigrationActive: mapValueOfType<bool>(json, r'isStorageMigrationActive')!,
|
||||
);
|
||||
}
|
||||
return null;
|
||||
@@ -158,10 +172,12 @@ class AllJobStatusResponseDto {
|
||||
'metadataExtractionQueueCount',
|
||||
'videoConversionQueueCount',
|
||||
'machineLearningQueueCount',
|
||||
'storageMigrationQueueCount',
|
||||
'isThumbnailGenerationActive',
|
||||
'isMetadataExtractionActive',
|
||||
'isVideoConversionActive',
|
||||
'isMachineLearningActive',
|
||||
'isStorageMigrationActive',
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
3
mobile/openapi/lib/model/job_id.dart
generated
3
mobile/openapi/lib/model/job_id.dart
generated
@@ -27,6 +27,7 @@ class JobId {
|
||||
static const metadataExtraction = JobId._(r'metadata-extraction');
|
||||
static const videoConversion = JobId._(r'video-conversion');
|
||||
static const machineLearning = JobId._(r'machine-learning');
|
||||
static const storageTemplateMigration = JobId._(r'storage-template-migration');
|
||||
|
||||
/// List of all possible values in this [enum][JobId].
|
||||
static const values = <JobId>[
|
||||
@@ -34,6 +35,7 @@ class JobId {
|
||||
metadataExtraction,
|
||||
videoConversion,
|
||||
machineLearning,
|
||||
storageTemplateMigration,
|
||||
];
|
||||
|
||||
static JobId? fromJson(dynamic value) => JobIdTypeTransformer().decode(value);
|
||||
@@ -76,6 +78,7 @@ class JobIdTypeTransformer {
|
||||
case r'metadata-extraction': return JobId.metadataExtraction;
|
||||
case r'video-conversion': return JobId.videoConversion;
|
||||
case r'machine-learning': return JobId.machineLearning;
|
||||
case r'storage-template-migration': return JobId.storageTemplateMigration;
|
||||
default:
|
||||
if (!allowNull) {
|
||||
throw ArgumentError('Unknown enum value to decode: $data');
|
||||
|
||||
14
mobile/openapi/lib/model/system_config_dto.dart
generated
14
mobile/openapi/lib/model/system_config_dto.dart
generated
@@ -15,30 +15,36 @@ class SystemConfigDto {
|
||||
SystemConfigDto({
|
||||
required this.ffmpeg,
|
||||
required this.oauth,
|
||||
required this.storageTemplate,
|
||||
});
|
||||
|
||||
SystemConfigFFmpegDto ffmpeg;
|
||||
|
||||
SystemConfigOAuthDto oauth;
|
||||
|
||||
SystemConfigStorageTemplateDto storageTemplate;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) => identical(this, other) || other is SystemConfigDto &&
|
||||
other.ffmpeg == ffmpeg &&
|
||||
other.oauth == oauth;
|
||||
other.oauth == oauth &&
|
||||
other.storageTemplate == storageTemplate;
|
||||
|
||||
@override
|
||||
int get hashCode =>
|
||||
// ignore: unnecessary_parenthesis
|
||||
(ffmpeg.hashCode) +
|
||||
(oauth.hashCode);
|
||||
(oauth.hashCode) +
|
||||
(storageTemplate.hashCode);
|
||||
|
||||
@override
|
||||
String toString() => 'SystemConfigDto[ffmpeg=$ffmpeg, oauth=$oauth]';
|
||||
String toString() => 'SystemConfigDto[ffmpeg=$ffmpeg, oauth=$oauth, storageTemplate=$storageTemplate]';
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final _json = <String, dynamic>{};
|
||||
_json[r'ffmpeg'] = ffmpeg;
|
||||
_json[r'oauth'] = oauth;
|
||||
_json[r'storageTemplate'] = storageTemplate;
|
||||
return _json;
|
||||
}
|
||||
|
||||
@@ -63,6 +69,7 @@ class SystemConfigDto {
|
||||
return SystemConfigDto(
|
||||
ffmpeg: SystemConfigFFmpegDto.fromJson(json[r'ffmpeg'])!,
|
||||
oauth: SystemConfigOAuthDto.fromJson(json[r'oauth'])!,
|
||||
storageTemplate: SystemConfigStorageTemplateDto.fromJson(json[r'storageTemplate'])!,
|
||||
);
|
||||
}
|
||||
return null;
|
||||
@@ -114,6 +121,7 @@ class SystemConfigDto {
|
||||
static const requiredKeys = <String>{
|
||||
'ffmpeg',
|
||||
'oauth',
|
||||
'storageTemplate',
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
111
mobile/openapi/lib/model/system_config_storage_template_dto.dart
generated
Normal file
111
mobile/openapi/lib/model/system_config_storage_template_dto.dart
generated
Normal file
@@ -0,0 +1,111 @@
|
||||
//
|
||||
// AUTO-GENERATED FILE, DO NOT MODIFY!
|
||||
//
|
||||
// @dart=2.12
|
||||
|
||||
// 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 SystemConfigStorageTemplateDto {
|
||||
/// Returns a new [SystemConfigStorageTemplateDto] instance.
|
||||
SystemConfigStorageTemplateDto({
|
||||
required this.template,
|
||||
});
|
||||
|
||||
String template;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) => identical(this, other) || other is SystemConfigStorageTemplateDto &&
|
||||
other.template == template;
|
||||
|
||||
@override
|
||||
int get hashCode =>
|
||||
// ignore: unnecessary_parenthesis
|
||||
(template.hashCode);
|
||||
|
||||
@override
|
||||
String toString() => 'SystemConfigStorageTemplateDto[template=$template]';
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final _json = <String, dynamic>{};
|
||||
_json[r'template'] = template;
|
||||
return _json;
|
||||
}
|
||||
|
||||
/// Returns a new [SystemConfigStorageTemplateDto] instance and imports its values from
|
||||
/// [value] if it's a [Map], null otherwise.
|
||||
// ignore: prefer_constructors_over_static_methods
|
||||
static SystemConfigStorageTemplateDto? fromJson(dynamic value) {
|
||||
if (value is Map) {
|
||||
final json = value.cast<String, dynamic>();
|
||||
|
||||
// Ensure that the map contains the required keys.
|
||||
// Note 1: the values aren't checked for validity beyond being non-null.
|
||||
// Note 2: this code is stripped in release mode!
|
||||
assert(() {
|
||||
requiredKeys.forEach((key) {
|
||||
assert(json.containsKey(key), 'Required key "SystemConfigStorageTemplateDto[$key]" is missing from JSON.');
|
||||
assert(json[key] != null, 'Required key "SystemConfigStorageTemplateDto[$key]" has a null value in JSON.');
|
||||
});
|
||||
return true;
|
||||
}());
|
||||
|
||||
return SystemConfigStorageTemplateDto(
|
||||
template: mapValueOfType<String>(json, r'template')!,
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static List<SystemConfigStorageTemplateDto>? listFromJson(dynamic json, {bool growable = false,}) {
|
||||
final result = <SystemConfigStorageTemplateDto>[];
|
||||
if (json is List && json.isNotEmpty) {
|
||||
for (final row in json) {
|
||||
final value = SystemConfigStorageTemplateDto.fromJson(row);
|
||||
if (value != null) {
|
||||
result.add(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result.toList(growable: growable);
|
||||
}
|
||||
|
||||
static Map<String, SystemConfigStorageTemplateDto> mapFromJson(dynamic json) {
|
||||
final map = <String, SystemConfigStorageTemplateDto>{};
|
||||
if (json is Map && json.isNotEmpty) {
|
||||
json = json.cast<String, dynamic>(); // ignore: parameter_assignments
|
||||
for (final entry in json.entries) {
|
||||
final value = SystemConfigStorageTemplateDto.fromJson(entry.value);
|
||||
if (value != null) {
|
||||
map[entry.key] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
// maps a json object with a list of SystemConfigStorageTemplateDto-objects as value to a dart map
|
||||
static Map<String, List<SystemConfigStorageTemplateDto>> mapListFromJson(dynamic json, {bool growable = false,}) {
|
||||
final map = <String, List<SystemConfigStorageTemplateDto>>{};
|
||||
if (json is Map && json.isNotEmpty) {
|
||||
json = json.cast<String, dynamic>(); // ignore: parameter_assignments
|
||||
for (final entry in json.entries) {
|
||||
final value = SystemConfigStorageTemplateDto.listFromJson(entry.value, growable: growable,);
|
||||
if (value != null) {
|
||||
map[entry.key] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
/// The list of required keys that must be present in a JSON.
|
||||
static const requiredKeys = <String>{
|
||||
'template',
|
||||
};
|
||||
}
|
||||
|
||||
173
mobile/openapi/lib/model/system_config_template_storage_option_dto.dart
generated
Normal file
173
mobile/openapi/lib/model/system_config_template_storage_option_dto.dart
generated
Normal file
@@ -0,0 +1,173 @@
|
||||
//
|
||||
// AUTO-GENERATED FILE, DO NOT MODIFY!
|
||||
//
|
||||
// @dart=2.12
|
||||
|
||||
// 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 SystemConfigTemplateStorageOptionDto {
|
||||
/// Returns a new [SystemConfigTemplateStorageOptionDto] instance.
|
||||
SystemConfigTemplateStorageOptionDto({
|
||||
this.yearOptions = const [],
|
||||
this.monthOptions = const [],
|
||||
this.dayOptions = const [],
|
||||
this.hourOptions = const [],
|
||||
this.minuteOptions = const [],
|
||||
this.secondOptions = const [],
|
||||
this.presetOptions = const [],
|
||||
});
|
||||
|
||||
List<String> yearOptions;
|
||||
|
||||
List<String> monthOptions;
|
||||
|
||||
List<String> dayOptions;
|
||||
|
||||
List<String> hourOptions;
|
||||
|
||||
List<String> minuteOptions;
|
||||
|
||||
List<String> secondOptions;
|
||||
|
||||
List<String> presetOptions;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) => identical(this, other) || other is SystemConfigTemplateStorageOptionDto &&
|
||||
other.yearOptions == yearOptions &&
|
||||
other.monthOptions == monthOptions &&
|
||||
other.dayOptions == dayOptions &&
|
||||
other.hourOptions == hourOptions &&
|
||||
other.minuteOptions == minuteOptions &&
|
||||
other.secondOptions == secondOptions &&
|
||||
other.presetOptions == presetOptions;
|
||||
|
||||
@override
|
||||
int get hashCode =>
|
||||
// ignore: unnecessary_parenthesis
|
||||
(yearOptions.hashCode) +
|
||||
(monthOptions.hashCode) +
|
||||
(dayOptions.hashCode) +
|
||||
(hourOptions.hashCode) +
|
||||
(minuteOptions.hashCode) +
|
||||
(secondOptions.hashCode) +
|
||||
(presetOptions.hashCode);
|
||||
|
||||
@override
|
||||
String toString() => 'SystemConfigTemplateStorageOptionDto[yearOptions=$yearOptions, monthOptions=$monthOptions, dayOptions=$dayOptions, hourOptions=$hourOptions, minuteOptions=$minuteOptions, secondOptions=$secondOptions, presetOptions=$presetOptions]';
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final _json = <String, dynamic>{};
|
||||
_json[r'yearOptions'] = yearOptions;
|
||||
_json[r'monthOptions'] = monthOptions;
|
||||
_json[r'dayOptions'] = dayOptions;
|
||||
_json[r'hourOptions'] = hourOptions;
|
||||
_json[r'minuteOptions'] = minuteOptions;
|
||||
_json[r'secondOptions'] = secondOptions;
|
||||
_json[r'presetOptions'] = presetOptions;
|
||||
return _json;
|
||||
}
|
||||
|
||||
/// Returns a new [SystemConfigTemplateStorageOptionDto] instance and imports its values from
|
||||
/// [value] if it's a [Map], null otherwise.
|
||||
// ignore: prefer_constructors_over_static_methods
|
||||
static SystemConfigTemplateStorageOptionDto? fromJson(dynamic value) {
|
||||
if (value is Map) {
|
||||
final json = value.cast<String, dynamic>();
|
||||
|
||||
// Ensure that the map contains the required keys.
|
||||
// Note 1: the values aren't checked for validity beyond being non-null.
|
||||
// Note 2: this code is stripped in release mode!
|
||||
assert(() {
|
||||
requiredKeys.forEach((key) {
|
||||
assert(json.containsKey(key), 'Required key "SystemConfigTemplateStorageOptionDto[$key]" is missing from JSON.');
|
||||
assert(json[key] != null, 'Required key "SystemConfigTemplateStorageOptionDto[$key]" has a null value in JSON.');
|
||||
});
|
||||
return true;
|
||||
}());
|
||||
|
||||
return SystemConfigTemplateStorageOptionDto(
|
||||
yearOptions: json[r'yearOptions'] is List
|
||||
? (json[r'yearOptions'] as List).cast<String>()
|
||||
: const [],
|
||||
monthOptions: json[r'monthOptions'] is List
|
||||
? (json[r'monthOptions'] as List).cast<String>()
|
||||
: const [],
|
||||
dayOptions: json[r'dayOptions'] is List
|
||||
? (json[r'dayOptions'] as List).cast<String>()
|
||||
: const [],
|
||||
hourOptions: json[r'hourOptions'] is List
|
||||
? (json[r'hourOptions'] as List).cast<String>()
|
||||
: const [],
|
||||
minuteOptions: json[r'minuteOptions'] is List
|
||||
? (json[r'minuteOptions'] as List).cast<String>()
|
||||
: const [],
|
||||
secondOptions: json[r'secondOptions'] is List
|
||||
? (json[r'secondOptions'] as List).cast<String>()
|
||||
: const [],
|
||||
presetOptions: json[r'presetOptions'] is List
|
||||
? (json[r'presetOptions'] as List).cast<String>()
|
||||
: const [],
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static List<SystemConfigTemplateStorageOptionDto>? listFromJson(dynamic json, {bool growable = false,}) {
|
||||
final result = <SystemConfigTemplateStorageOptionDto>[];
|
||||
if (json is List && json.isNotEmpty) {
|
||||
for (final row in json) {
|
||||
final value = SystemConfigTemplateStorageOptionDto.fromJson(row);
|
||||
if (value != null) {
|
||||
result.add(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result.toList(growable: growable);
|
||||
}
|
||||
|
||||
static Map<String, SystemConfigTemplateStorageOptionDto> mapFromJson(dynamic json) {
|
||||
final map = <String, SystemConfigTemplateStorageOptionDto>{};
|
||||
if (json is Map && json.isNotEmpty) {
|
||||
json = json.cast<String, dynamic>(); // ignore: parameter_assignments
|
||||
for (final entry in json.entries) {
|
||||
final value = SystemConfigTemplateStorageOptionDto.fromJson(entry.value);
|
||||
if (value != null) {
|
||||
map[entry.key] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
// maps a json object with a list of SystemConfigTemplateStorageOptionDto-objects as value to a dart map
|
||||
static Map<String, List<SystemConfigTemplateStorageOptionDto>> mapListFromJson(dynamic json, {bool growable = false,}) {
|
||||
final map = <String, List<SystemConfigTemplateStorageOptionDto>>{};
|
||||
if (json is Map && json.isNotEmpty) {
|
||||
json = json.cast<String, dynamic>(); // ignore: parameter_assignments
|
||||
for (final entry in json.entries) {
|
||||
final value = SystemConfigTemplateStorageOptionDto.listFromJson(entry.value, growable: growable,);
|
||||
if (value != null) {
|
||||
map[entry.key] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
/// The list of required keys that must be present in a JSON.
|
||||
static const requiredKeys = <String>{
|
||||
'yearOptions',
|
||||
'monthOptions',
|
||||
'dayOptions',
|
||||
'hourOptions',
|
||||
'minuteOptions',
|
||||
'secondOptions',
|
||||
'presetOptions',
|
||||
};
|
||||
}
|
||||
|
||||
@@ -36,6 +36,11 @@ void main() {
|
||||
// TODO
|
||||
});
|
||||
|
||||
// JobCounts storageMigrationQueueCount
|
||||
test('to test the property `storageMigrationQueueCount`', () async {
|
||||
// TODO
|
||||
});
|
||||
|
||||
// bool isThumbnailGenerationActive
|
||||
test('to test the property `isThumbnailGenerationActive`', () async {
|
||||
// TODO
|
||||
@@ -56,6 +61,11 @@ void main() {
|
||||
// TODO
|
||||
});
|
||||
|
||||
// bool isStorageMigrationActive
|
||||
test('to test the property `isStorageMigrationActive`', () async {
|
||||
// TODO
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
|
||||
|
||||
5
mobile/openapi/test/system_config_api_test.dart
generated
5
mobile/openapi/test/system_config_api_test.dart
generated
@@ -27,6 +27,11 @@ void main() {
|
||||
// TODO
|
||||
});
|
||||
|
||||
//Future<SystemConfigTemplateStorageOptionDto> getStorageTemplateOptions() async
|
||||
test('test getStorageTemplateOptions', () async {
|
||||
// TODO
|
||||
});
|
||||
|
||||
//Future<SystemConfigDto> updateConfig(SystemConfigDto systemConfigDto) async
|
||||
test('test updateConfig', () async {
|
||||
// TODO
|
||||
|
||||
5
mobile/openapi/test/system_config_dto_test.dart
generated
5
mobile/openapi/test/system_config_dto_test.dart
generated
@@ -26,6 +26,11 @@ void main() {
|
||||
// TODO
|
||||
});
|
||||
|
||||
// SystemConfigStorageTemplateDto storageTemplate
|
||||
test('to test the property `storageTemplate`', () async {
|
||||
// TODO
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
|
||||
|
||||
27
mobile/openapi/test/system_config_storage_template_dto_test.dart
generated
Normal file
27
mobile/openapi/test/system_config_storage_template_dto_test.dart
generated
Normal file
@@ -0,0 +1,27 @@
|
||||
//
|
||||
// AUTO-GENERATED FILE, DO NOT MODIFY!
|
||||
//
|
||||
// @dart=2.12
|
||||
|
||||
// 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
|
||||
|
||||
import 'package:openapi/api.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
// tests for SystemConfigStorageTemplateDto
|
||||
void main() {
|
||||
// final instance = SystemConfigStorageTemplateDto();
|
||||
|
||||
group('test SystemConfigStorageTemplateDto', () {
|
||||
// String template
|
||||
test('to test the property `template`', () async {
|
||||
// TODO
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
57
mobile/openapi/test/system_config_template_storage_option_dto_test.dart
generated
Normal file
57
mobile/openapi/test/system_config_template_storage_option_dto_test.dart
generated
Normal file
@@ -0,0 +1,57 @@
|
||||
//
|
||||
// AUTO-GENERATED FILE, DO NOT MODIFY!
|
||||
//
|
||||
// @dart=2.12
|
||||
|
||||
// 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
|
||||
|
||||
import 'package:openapi/api.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
// tests for SystemConfigTemplateStorageOptionDto
|
||||
void main() {
|
||||
// final instance = SystemConfigTemplateStorageOptionDto();
|
||||
|
||||
group('test SystemConfigTemplateStorageOptionDto', () {
|
||||
// List<String> yearOptions (default value: const [])
|
||||
test('to test the property `yearOptions`', () async {
|
||||
// TODO
|
||||
});
|
||||
|
||||
// List<String> monthOptions (default value: const [])
|
||||
test('to test the property `monthOptions`', () async {
|
||||
// TODO
|
||||
});
|
||||
|
||||
// List<String> dayOptions (default value: const [])
|
||||
test('to test the property `dayOptions`', () async {
|
||||
// TODO
|
||||
});
|
||||
|
||||
// List<String> hourOptions (default value: const [])
|
||||
test('to test the property `hourOptions`', () async {
|
||||
// TODO
|
||||
});
|
||||
|
||||
// List<String> minuteOptions (default value: const [])
|
||||
test('to test the property `minuteOptions`', () async {
|
||||
// TODO
|
||||
});
|
||||
|
||||
// List<String> secondOptions (default value: const [])
|
||||
test('to test the property `secondOptions`', () async {
|
||||
// TODO
|
||||
});
|
||||
|
||||
// List<String> presetOptions (default value: const [])
|
||||
test('to test the property `presetOptions`', () async {
|
||||
// TODO
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
@@ -2,7 +2,7 @@ name: immich_mobile
|
||||
description: Immich - selfhosted backup media file on mobile phone
|
||||
|
||||
publish_to: "none"
|
||||
version: 1.38.0+60
|
||||
version: 1.39.0+62
|
||||
|
||||
environment:
|
||||
sdk: ">=2.17.0 <3.0.0"
|
||||
|
||||
10
notes.md
Normal file
10
notes.md
Normal file
@@ -0,0 +1,10 @@
|
||||
# User defined storage structure
|
||||
|
||||
# Folder structure
|
||||
* Year is the top level
|
||||
* Different parsing sequence will be the second level
|
||||
|
||||
# Filename
|
||||
* Filename will always be appended by a unique ID. Maybe use https://github.com/ai/nanoid
|
||||
* Example: `notes.md` -> `notes-1234567890.md`
|
||||
* Filename will be unique in the same folder
|
||||
@@ -3,7 +3,7 @@ import { AssetAlbumEntity } from '@app/database/entities/asset-album.entity';
|
||||
import { UserAlbumEntity } from '@app/database/entities/user-album.entity';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
import { In, Repository, SelectQueryBuilder, DataSource } from 'typeorm';
|
||||
import { In, Repository, SelectQueryBuilder, DataSource, Brackets } from 'typeorm';
|
||||
import { AddAssetsDto } from './dto/add-assets.dto';
|
||||
import { AddUsersDto } from './dto/add-users.dto';
|
||||
import { CreateAlbumDto } from './dto/create-album.dto';
|
||||
@@ -286,14 +286,18 @@ export class AlbumRepository implements IAlbumRepository {
|
||||
}
|
||||
|
||||
async getSharedWithUserAlbumCount(userId: string, assetId: string): Promise<number> {
|
||||
const result = await this
|
||||
.userAlbumRepository
|
||||
.createQueryBuilder('usa')
|
||||
.select('count(aa)', 'count')
|
||||
.innerJoin('asset_album', 'aa', 'aa.albumId = usa.albumId')
|
||||
.where('aa.assetId = :assetId', { assetId })
|
||||
.andWhere('usa.sharedUserId = :userId', { userId })
|
||||
.getRawOne();
|
||||
const result = await this.userAlbumRepository
|
||||
.createQueryBuilder('usa')
|
||||
.select('count(aa)', 'count')
|
||||
.innerJoin('asset_album', 'aa', 'aa.albumId = usa.albumId')
|
||||
.innerJoin('albums', 'a', 'a.id = usa.albumId')
|
||||
.where('aa.assetId = :assetId', { assetId })
|
||||
.andWhere(
|
||||
new Brackets((qb) => {
|
||||
qb.where('a.ownerId = :userId', { userId }).orWhere('usa.sharedUserId = :userId', { userId });
|
||||
}),
|
||||
)
|
||||
.getRawOne();
|
||||
|
||||
return result.count;
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ import { CheckExistingAssetsResponseDto } from './response-dto/check-existing-as
|
||||
import { In } from 'typeorm/find-options/operator/In';
|
||||
import { UpdateAssetDto } from './dto/update-asset.dto';
|
||||
import { ITagRepository, TAG_REPOSITORY } from '../tag/tag.repository';
|
||||
import { IsNull } from 'typeorm';
|
||||
|
||||
export interface IAssetRepository {
|
||||
create(
|
||||
@@ -69,14 +70,14 @@ export class AssetRepository implements IAssetRepository {
|
||||
}
|
||||
|
||||
async getAssetWithNoThumbnail(): Promise<AssetEntity[]> {
|
||||
return await this.assetRepository
|
||||
.createQueryBuilder('asset')
|
||||
.where('asset.resizePath IS NULL')
|
||||
.andWhere('asset.isVisible = true')
|
||||
.orWhere('asset.resizePath = :resizePath', { resizePath: '' })
|
||||
.orWhere('asset.webpPath IS NULL')
|
||||
.orWhere('asset.webpPath = :webpPath', { webpPath: '' })
|
||||
.getMany();
|
||||
return await this.assetRepository.find({
|
||||
where: [
|
||||
{ resizePath: IsNull(), isVisible: true },
|
||||
{ resizePath: '', isVisible: true },
|
||||
{ webpPath: IsNull(), isVisible: true },
|
||||
{ webpPath: '', isVisible: true },
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
async getAssetWithNoEXIF(): Promise<AssetEntity[]> {
|
||||
|
||||
@@ -7,12 +7,13 @@ import { BullModule } from '@nestjs/bull';
|
||||
import { BackgroundTaskModule } from '../../modules/background-task/background-task.module';
|
||||
import { BackgroundTaskService } from '../../modules/background-task/background-task.service';
|
||||
import { CommunicationModule } from '../communication/communication.module';
|
||||
import { QueueNameEnum } from '@app/job/constants/queue-name.constant';
|
||||
import { AssetRepository, ASSET_REPOSITORY } from './asset-repository';
|
||||
import { DownloadModule } from '../../modules/download/download.module';
|
||||
import { TagModule } from '../tag/tag.module';
|
||||
import { AlbumModule } from '../album/album.module';
|
||||
import { UserModule } from '../user/user.module';
|
||||
import { StorageModule } from '@app/storage';
|
||||
import { immichSharedQueues } from '@app/job/constants/bull-queue-registration.constant';
|
||||
|
||||
const ASSET_REPOSITORY_PROVIDER = {
|
||||
provide: ASSET_REPOSITORY,
|
||||
@@ -28,23 +29,9 @@ const ASSET_REPOSITORY_PROVIDER = {
|
||||
UserModule,
|
||||
AlbumModule,
|
||||
TagModule,
|
||||
StorageModule,
|
||||
forwardRef(() => AlbumModule),
|
||||
BullModule.registerQueue({
|
||||
name: QueueNameEnum.ASSET_UPLOADED,
|
||||
defaultJobOptions: {
|
||||
attempts: 3,
|
||||
removeOnComplete: true,
|
||||
removeOnFail: false,
|
||||
},
|
||||
}),
|
||||
BullModule.registerQueue({
|
||||
name: QueueNameEnum.VIDEO_CONVERSION,
|
||||
defaultJobOptions: {
|
||||
attempts: 3,
|
||||
removeOnComplete: true,
|
||||
removeOnFail: false,
|
||||
},
|
||||
}),
|
||||
BullModule.registerQueue(...immichSharedQueues),
|
||||
],
|
||||
controllers: [AssetController],
|
||||
providers: [AssetService, BackgroundTaskService, ASSET_REPOSITORY_PROVIDER],
|
||||
|
||||
@@ -11,7 +11,8 @@ import { DownloadService } from '../../modules/download/download.service';
|
||||
import { BackgroundTaskService } from '../../modules/background-task/background-task.service';
|
||||
import { IAssetUploadedJob, IVideoTranscodeJob } from '@app/job';
|
||||
import { Queue } from 'bull';
|
||||
import { IAlbumRepository } from "../album/album-repository";
|
||||
import { IAlbumRepository } from '../album/album-repository';
|
||||
import { StorageService } from '@app/storage';
|
||||
|
||||
describe('AssetService', () => {
|
||||
let sui: AssetService;
|
||||
@@ -22,6 +23,7 @@ describe('AssetService', () => {
|
||||
let backgroundTaskServiceMock: jest.Mocked<BackgroundTaskService>;
|
||||
let assetUploadedQueueMock: jest.Mocked<Queue<IAssetUploadedJob>>;
|
||||
let videoConversionQueueMock: jest.Mocked<Queue<IVideoTranscodeJob>>;
|
||||
let storageSeriveMock: jest.Mocked<StorageService>;
|
||||
const authUser: AuthUserDto = Object.freeze({
|
||||
id: 'user_id_1',
|
||||
email: 'auth@test.com',
|
||||
@@ -139,6 +141,7 @@ describe('AssetService', () => {
|
||||
assetUploadedQueueMock,
|
||||
videoConversionQueueMock,
|
||||
downloadServiceMock as DownloadService,
|
||||
storageSeriveMock,
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
@@ -55,6 +55,7 @@ import { Queue } from 'bull';
|
||||
import { DownloadService } from '../../modules/download/download.service';
|
||||
import { DownloadDto } from './dto/download-library.dto';
|
||||
import { ALBUM_REPOSITORY, IAlbumRepository } from '../album/album-repository';
|
||||
import { StorageService } from '@app/storage';
|
||||
|
||||
const fileInfo = promisify(stat);
|
||||
|
||||
@@ -79,6 +80,8 @@ export class AssetService {
|
||||
private videoConversionQueue: Queue<IVideoTranscodeJob>,
|
||||
|
||||
private downloadService: DownloadService,
|
||||
|
||||
private storageService: StorageService,
|
||||
) {}
|
||||
|
||||
public async handleUploadedAsset(
|
||||
@@ -113,6 +116,8 @@ export class AssetService {
|
||||
throw new BadRequestException('Asset not created');
|
||||
}
|
||||
|
||||
await this.storageService.moveAsset(livePhotoAssetEntity, originalAssetData.originalname);
|
||||
|
||||
await this.videoConversionQueue.add(
|
||||
mp4ConversionProcessorName,
|
||||
{ asset: livePhotoAssetEntity },
|
||||
@@ -139,13 +144,15 @@ export class AssetService {
|
||||
throw new BadRequestException('Asset not created');
|
||||
}
|
||||
|
||||
const movedAsset = await this.storageService.moveAsset(assetEntity, originalAssetData.originalname);
|
||||
|
||||
await this.assetUploadedQueue.add(
|
||||
assetUploadedProcessorName,
|
||||
{ asset: assetEntity, fileName: originalAssetData.originalname },
|
||||
{ jobId: assetEntity.id },
|
||||
{ asset: movedAsset, fileName: originalAssetData.originalname },
|
||||
{ jobId: movedAsset.id },
|
||||
);
|
||||
|
||||
return new AssetFileUploadResponseDto(assetEntity.id);
|
||||
return new AssetFileUploadResponseDto(movedAsset.id);
|
||||
} catch (err) {
|
||||
await this.backgroundTaskService.deleteFileOnDisk([
|
||||
{
|
||||
|
||||
@@ -6,6 +6,7 @@ export enum JobId {
|
||||
METADATA_EXTRACTION = 'metadata-extraction',
|
||||
VIDEO_CONVERSION = 'video-conversion',
|
||||
MACHINE_LEARNING = 'machine-learning',
|
||||
STORAGE_TEMPLATE_MIGRATION = 'storage-template-migration',
|
||||
}
|
||||
|
||||
export class GetJobDto {
|
||||
|
||||
@@ -6,13 +6,15 @@ import { ImmichJwtModule } from '../../modules/immich-jwt/immich-jwt.module';
|
||||
import { JwtModule } from '@nestjs/jwt';
|
||||
import { jwtConfig } from '../../config/jwt.config';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
import { BullModule } from '@nestjs/bull';
|
||||
import { QueueNameEnum } from '@app/job';
|
||||
import { ExifEntity } from '@app/database/entities/exif.entity';
|
||||
import { TagModule } from '../tag/tag.module';
|
||||
import { AssetModule } from '../asset/asset.module';
|
||||
import { UserModule } from '../user/user.module';
|
||||
|
||||
import { StorageModule } from '@app/storage';
|
||||
import { BullModule } from '@nestjs/bull';
|
||||
import { immichSharedQueues } from '@app/job/constants/bull-queue-registration.constant';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
TypeOrmModule.forFeature([ExifEntity]),
|
||||
@@ -21,56 +23,8 @@ import { UserModule } from '../user/user.module';
|
||||
AssetModule,
|
||||
UserModule,
|
||||
JwtModule.register(jwtConfig),
|
||||
BullModule.registerQueue(
|
||||
{
|
||||
name: QueueNameEnum.THUMBNAIL_GENERATION,
|
||||
defaultJobOptions: {
|
||||
attempts: 3,
|
||||
removeOnComplete: true,
|
||||
removeOnFail: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: QueueNameEnum.ASSET_UPLOADED,
|
||||
defaultJobOptions: {
|
||||
attempts: 3,
|
||||
removeOnComplete: true,
|
||||
removeOnFail: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: QueueNameEnum.METADATA_EXTRACTION,
|
||||
defaultJobOptions: {
|
||||
attempts: 3,
|
||||
removeOnComplete: true,
|
||||
removeOnFail: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: QueueNameEnum.VIDEO_CONVERSION,
|
||||
defaultJobOptions: {
|
||||
attempts: 3,
|
||||
removeOnComplete: true,
|
||||
removeOnFail: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: QueueNameEnum.CHECKSUM_GENERATION,
|
||||
defaultJobOptions: {
|
||||
attempts: 3,
|
||||
removeOnComplete: true,
|
||||
removeOnFail: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: QueueNameEnum.MACHINE_LEARNING,
|
||||
defaultJobOptions: {
|
||||
attempts: 3,
|
||||
removeOnComplete: true,
|
||||
removeOnFail: false,
|
||||
},
|
||||
},
|
||||
),
|
||||
StorageModule,
|
||||
BullModule.registerQueue(...immichSharedQueues),
|
||||
],
|
||||
controllers: [JobController],
|
||||
providers: [JobService, ImmichJwtService],
|
||||
|
||||
@@ -6,6 +6,7 @@ import {
|
||||
IVideoTranscodeJob,
|
||||
MachineLearningJobNameEnum,
|
||||
QueueNameEnum,
|
||||
templateMigrationProcessorName,
|
||||
videoMetadataExtractionProcessorName,
|
||||
} from '@app/job';
|
||||
import { InjectQueue } from '@nestjs/bull';
|
||||
@@ -18,6 +19,7 @@ import { AssetType } from '@app/database/entities/asset.entity';
|
||||
import { GetJobDto, JobId } from './dto/get-job.dto';
|
||||
import { JobStatusResponseDto } from './response-dto/job-status-response.dto';
|
||||
import { IMachineLearningJob } from '@app/job/interfaces/machine-learning.interface';
|
||||
import { StorageService } from '@app/storage';
|
||||
|
||||
@Injectable()
|
||||
export class JobService {
|
||||
@@ -34,12 +36,18 @@ export class JobService {
|
||||
@InjectQueue(QueueNameEnum.MACHINE_LEARNING)
|
||||
private machineLearningQueue: Queue<IMachineLearningJob>,
|
||||
|
||||
@InjectQueue(QueueNameEnum.STORAGE_MIGRATION)
|
||||
private storageMigrationQueue: Queue,
|
||||
|
||||
@Inject(ASSET_REPOSITORY)
|
||||
private _assetRepository: IAssetRepository,
|
||||
|
||||
private storageService: StorageService,
|
||||
) {
|
||||
this.thumbnailGeneratorQueue.empty();
|
||||
this.metadataExtractionQueue.empty();
|
||||
this.videoConversionQueue.empty();
|
||||
this.storageMigrationQueue.empty();
|
||||
}
|
||||
|
||||
async startJob(jobDto: GetJobDto): Promise<number> {
|
||||
@@ -52,6 +60,8 @@ export class JobService {
|
||||
return 0;
|
||||
case JobId.MACHINE_LEARNING:
|
||||
return this.runMachineLearningPipeline();
|
||||
case JobId.STORAGE_TEMPLATE_MIGRATION:
|
||||
return this.runStorageMigration();
|
||||
default:
|
||||
throw new BadRequestException('Invalid job id');
|
||||
}
|
||||
@@ -62,6 +72,7 @@ export class JobService {
|
||||
const metadataExtractionJobCount = await this.metadataExtractionQueue.getJobCounts();
|
||||
const videoConversionJobCount = await this.videoConversionQueue.getJobCounts();
|
||||
const machineLearningJobCount = await this.machineLearningQueue.getJobCounts();
|
||||
const storageMigrationJobCount = await this.storageMigrationQueue.getJobCounts();
|
||||
|
||||
const response = new AllJobStatusResponseDto();
|
||||
response.isThumbnailGenerationActive = Boolean(thumbnailGeneratorJobCount.waiting);
|
||||
@@ -73,6 +84,9 @@ export class JobService {
|
||||
response.isMachineLearningActive = Boolean(machineLearningJobCount.waiting);
|
||||
response.machineLearningQueueCount = machineLearningJobCount;
|
||||
|
||||
response.isStorageMigrationActive = Boolean(storageMigrationJobCount.active);
|
||||
response.storageMigrationQueueCount = storageMigrationJobCount;
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
@@ -93,6 +107,11 @@ export class JobService {
|
||||
response.queueCount = await this.videoConversionQueue.getJobCounts();
|
||||
}
|
||||
|
||||
if (query.jobId === JobId.STORAGE_TEMPLATE_MIGRATION) {
|
||||
response.isActive = Boolean((await this.storageMigrationQueue.getJobCounts()).waiting);
|
||||
response.queueCount = await this.storageMigrationQueue.getJobCounts();
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
@@ -110,6 +129,9 @@ export class JobService {
|
||||
case JobId.MACHINE_LEARNING:
|
||||
this.machineLearningQueue.empty();
|
||||
return 0;
|
||||
case JobId.STORAGE_TEMPLATE_MIGRATION:
|
||||
this.storageMigrationQueue.empty();
|
||||
return 0;
|
||||
default:
|
||||
throw new BadRequestException('Invalid job id');
|
||||
}
|
||||
@@ -177,4 +199,16 @@ export class JobService {
|
||||
|
||||
return assetWithNoSmartInfo.length;
|
||||
}
|
||||
|
||||
async runStorageMigration() {
|
||||
const jobCount = await this.storageMigrationQueue.getJobCounts();
|
||||
|
||||
if (jobCount.active > 0) {
|
||||
throw new BadRequestException('Storage migration job is already running');
|
||||
}
|
||||
|
||||
await this.storageMigrationQueue.add(templateMigrationProcessorName, {}, { jobId: randomUUID() });
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ export class AllJobStatusResponseDto {
|
||||
isMetadataExtractionActive!: boolean;
|
||||
isVideoConversionActive!: boolean;
|
||||
isMachineLearningActive!: boolean;
|
||||
isStorageMigrationActive!: boolean;
|
||||
|
||||
@ApiProperty({
|
||||
type: JobCounts,
|
||||
@@ -37,4 +38,9 @@ export class AllJobStatusResponseDto {
|
||||
type: JobCounts,
|
||||
})
|
||||
machineLearningQueueCount!: JobCounts;
|
||||
|
||||
@ApiProperty({
|
||||
type: JobCounts,
|
||||
})
|
||||
storageMigrationQueueCount!: JobCounts;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
import { IsNotEmpty, IsString } from 'class-validator';
|
||||
|
||||
export class SystemConfigStorageTemplateDto {
|
||||
@IsNotEmpty()
|
||||
@IsString()
|
||||
template!: string;
|
||||
}
|
||||
@@ -2,6 +2,7 @@ import { SystemConfig } from '@app/database/entities/system-config.entity';
|
||||
import { ValidateNested } from 'class-validator';
|
||||
import { SystemConfigFFmpegDto } from './system-config-ffmpeg.dto';
|
||||
import { SystemConfigOAuthDto } from './system-config-oauth.dto';
|
||||
import { SystemConfigStorageTemplateDto } from './system-config-storage-template.dto';
|
||||
|
||||
export class SystemConfigDto {
|
||||
@ValidateNested()
|
||||
@@ -9,6 +10,9 @@ export class SystemConfigDto {
|
||||
|
||||
@ValidateNested()
|
||||
oauth!: SystemConfigOAuthDto;
|
||||
|
||||
@ValidateNested()
|
||||
storageTemplate!: SystemConfigStorageTemplateDto;
|
||||
}
|
||||
|
||||
export function mapConfig(config: SystemConfig): SystemConfigDto {
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
export class SystemConfigTemplateStorageOptionDto {
|
||||
yearOptions!: string[];
|
||||
monthOptions!: string[];
|
||||
dayOptions!: string[];
|
||||
hourOptions!: string[];
|
||||
minuteOptions!: string[];
|
||||
secondOptions!: string[];
|
||||
presetOptions!: string[];
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
import { Body, Controller, Get, Put, ValidationPipe } from '@nestjs/common';
|
||||
import { ApiBearerAuth, ApiTags } from '@nestjs/swagger';
|
||||
import { Authenticated } from '../../decorators/authenticated.decorator';
|
||||
import { SystemConfigTemplateStorageOptionDto } from './response-dto/system-config-template-storage-option.dto';
|
||||
import { SystemConfigDto } from './dto/system-config.dto';
|
||||
import { SystemConfigService } from './system-config.service';
|
||||
|
||||
@@ -25,4 +26,9 @@ export class SystemConfigController {
|
||||
public updateConfig(@Body(ValidationPipe) dto: SystemConfigDto): Promise<SystemConfigDto> {
|
||||
return this.systemConfigService.updateConfig(dto);
|
||||
}
|
||||
|
||||
@Get('storage-template-options')
|
||||
public getStorageTemplateOptions(): SystemConfigTemplateStorageOptionDto {
|
||||
return this.systemConfigService.getStorageTemplateOptions();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
import { SystemConfigEntity } from '@app/database/entities/system-config.entity';
|
||||
import { immichSharedQueues } from '@app/job/constants/bull-queue-registration.constant';
|
||||
import { BullModule } from '@nestjs/bull';
|
||||
import { Module } from '@nestjs/common';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
import { ImmichConfigModule } from 'libs/immich-config/src';
|
||||
@@ -7,7 +9,12 @@ import { SystemConfigController } from './system-config.controller';
|
||||
import { SystemConfigService } from './system-config.service';
|
||||
|
||||
@Module({
|
||||
imports: [ImmichJwtModule, ImmichConfigModule, TypeOrmModule.forFeature([SystemConfigEntity])],
|
||||
imports: [
|
||||
ImmichJwtModule,
|
||||
ImmichConfigModule,
|
||||
TypeOrmModule.forFeature([SystemConfigEntity]),
|
||||
BullModule.registerQueue(...immichSharedQueues),
|
||||
],
|
||||
controllers: [SystemConfigController],
|
||||
providers: [SystemConfigService],
|
||||
})
|
||||
|
||||
@@ -1,10 +1,28 @@
|
||||
import { QueueNameEnum, updateTemplateProcessorName } from '@app/job';
|
||||
import {
|
||||
supportedDayTokens,
|
||||
supportedHourTokens,
|
||||
supportedMinuteTokens,
|
||||
supportedMonthTokens,
|
||||
supportedPresetTokens,
|
||||
supportedSecondTokens,
|
||||
supportedYearTokens,
|
||||
} from '@app/storage/constants/supported-datetime-template';
|
||||
import { InjectQueue } from '@nestjs/bull';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { Queue } from 'bull';
|
||||
import { randomUUID } from 'crypto';
|
||||
import { ImmichConfigService } from 'libs/immich-config/src';
|
||||
import { mapConfig, SystemConfigDto } from './dto/system-config.dto';
|
||||
import { SystemConfigTemplateStorageOptionDto } from './response-dto/system-config-template-storage-option.dto';
|
||||
|
||||
@Injectable()
|
||||
export class SystemConfigService {
|
||||
constructor(private immichConfigService: ImmichConfigService) {}
|
||||
constructor(
|
||||
private immichConfigService: ImmichConfigService,
|
||||
@InjectQueue(QueueNameEnum.STORAGE_MIGRATION)
|
||||
private storageMigrationQueue: Queue,
|
||||
) {}
|
||||
|
||||
public async getConfig(): Promise<SystemConfigDto> {
|
||||
const config = await this.immichConfigService.getConfig();
|
||||
@@ -17,7 +35,22 @@ export class SystemConfigService {
|
||||
}
|
||||
|
||||
public async updateConfig(dto: SystemConfigDto): Promise<SystemConfigDto> {
|
||||
await this.immichConfigService.updateConfig(dto);
|
||||
return this.getConfig();
|
||||
const config = await this.immichConfigService.updateConfig(dto);
|
||||
this.storageMigrationQueue.add(updateTemplateProcessorName, {}, { jobId: randomUUID() });
|
||||
return mapConfig(config);
|
||||
}
|
||||
|
||||
public getStorageTemplateOptions(): SystemConfigTemplateStorageOptionDto {
|
||||
const options = new SystemConfigTemplateStorageOptionDto();
|
||||
|
||||
options.dayOptions = supportedDayTokens;
|
||||
options.monthOptions = supportedMonthTokens;
|
||||
options.yearOptions = supportedYearTokens;
|
||||
options.hourOptions = supportedHourTokens;
|
||||
options.minuteOptions = supportedMinuteTokens;
|
||||
options.secondOptions = supportedSecondTokens;
|
||||
options.presetOptions = supportedPresetTokens;
|
||||
|
||||
return options;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ describe('UserService', () => {
|
||||
email: 'immich@test.com',
|
||||
});
|
||||
|
||||
const adminUser: UserEntity = Object.freeze({
|
||||
const adminUser: UserEntity = {
|
||||
id: 'admin_id',
|
||||
email: 'admin@test.com',
|
||||
password: 'admin_password',
|
||||
@@ -32,9 +32,9 @@ describe('UserService', () => {
|
||||
profileImagePath: '',
|
||||
createdAt: '2021-01-01',
|
||||
tags: [],
|
||||
});
|
||||
};
|
||||
|
||||
const immichUser: UserEntity = Object.freeze({
|
||||
const immichUser: UserEntity = {
|
||||
id: 'immich_id',
|
||||
email: 'immich@test.com',
|
||||
password: 'immich_password',
|
||||
@@ -47,9 +47,9 @@ describe('UserService', () => {
|
||||
profileImagePath: '',
|
||||
createdAt: '2021-01-01',
|
||||
tags: [],
|
||||
});
|
||||
};
|
||||
|
||||
const updatedImmichUser: UserEntity = Object.freeze({
|
||||
const updatedImmichUser: UserEntity = {
|
||||
id: 'immich_id',
|
||||
email: 'immich@test.com',
|
||||
password: 'immich_password',
|
||||
@@ -62,7 +62,7 @@ describe('UserService', () => {
|
||||
profileImagePath: '',
|
||||
createdAt: '2021-01-01',
|
||||
tags: [],
|
||||
});
|
||||
};
|
||||
|
||||
beforeAll(() => {
|
||||
userRepositoryMock = newUserRepositoryMock();
|
||||
@@ -75,7 +75,7 @@ describe('UserService', () => {
|
||||
});
|
||||
|
||||
describe('Update user', () => {
|
||||
it('should update user', () => {
|
||||
it('should update user', async () => {
|
||||
const requestor = immichAuthUser;
|
||||
const userToUpdate = immichUser;
|
||||
|
||||
@@ -83,11 +83,11 @@ describe('UserService', () => {
|
||||
userRepositoryMock.get.mockImplementationOnce(() => Promise.resolve(userToUpdate));
|
||||
userRepositoryMock.update.mockImplementationOnce(() => Promise.resolve(updatedImmichUser));
|
||||
|
||||
const result = sui.updateUser(requestor, {
|
||||
const result = await sui.updateUser(requestor, {
|
||||
id: userToUpdate.id,
|
||||
shouldChangePassword: true,
|
||||
});
|
||||
expect(result).resolves.toBeDefined();
|
||||
expect(result.shouldChangePassword).toEqual(true);
|
||||
});
|
||||
|
||||
it('user can only update its information', () => {
|
||||
|
||||
@@ -10,7 +10,7 @@ import {
|
||||
UnauthorizedException,
|
||||
} from '@nestjs/common';
|
||||
import { Response as Res } from 'express';
|
||||
import { createReadStream } from 'fs';
|
||||
import { constants, createReadStream } from 'fs';
|
||||
import { AuthUserDto } from '../../decorators/auth-user.decorator';
|
||||
import { CreateUserDto } from './dto/create-user.dto';
|
||||
import { UpdateUserDto } from './dto/update-user.dto';
|
||||
@@ -22,6 +22,7 @@ import {
|
||||
import { mapUserCountResponse, UserCountResponseDto } from './response-dto/user-count-response.dto';
|
||||
import { mapUser, UserResponseDto } from './response-dto/user-response.dto';
|
||||
import { IUserRepository, USER_REPOSITORY } from './user-repository';
|
||||
import fs from 'fs/promises';
|
||||
|
||||
@Injectable()
|
||||
export class UserService {
|
||||
@@ -103,7 +104,14 @@ export class UserService {
|
||||
throw new NotFoundException('User not found');
|
||||
}
|
||||
try {
|
||||
const updatedUser = await this.userRepository.update(user.id, updateUserDto);
|
||||
user.password = updateUserDto.password ?? user.password;
|
||||
user.firstName = updateUserDto.firstName ?? user.firstName;
|
||||
user.lastName = updateUserDto.lastName ?? user.lastName;
|
||||
user.isAdmin = updateUserDto.isAdmin ?? user.isAdmin;
|
||||
user.shouldChangePassword = updateUserDto.shouldChangePassword ?? user.shouldChangePassword;
|
||||
user.profileImagePath = updateUserDto.profileImagePath ?? user.profileImagePath;
|
||||
|
||||
const updatedUser = await this.userRepository.update(user.id, user);
|
||||
|
||||
return mapUser(updatedUser);
|
||||
} catch (e) {
|
||||
@@ -189,6 +197,8 @@ export class UserService {
|
||||
throw new NotFoundException('User does not have a profile image');
|
||||
}
|
||||
|
||||
await fs.access(user.profileImagePath, constants.R_OK | constants.W_OK);
|
||||
|
||||
res.set({
|
||||
'Content-Type': 'image/jpeg',
|
||||
});
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { immichAppConfig } from '@app/common/config';
|
||||
import { immichAppConfig, immichBullAsyncConfig } from '@app/common/config';
|
||||
import { MiddlewareConsumer, Module, NestModule } from '@nestjs/common';
|
||||
import { UserModule } from './api-v1/user/user.module';
|
||||
import { AssetModule } from './api-v1/asset/asset.module';
|
||||
@@ -36,18 +36,7 @@ import { TagModule } from './api-v1/tag/tag.module';
|
||||
|
||||
DeviceInfoModule,
|
||||
|
||||
BullModule.forRootAsync({
|
||||
useFactory: async () => ({
|
||||
prefix: 'immich_bull',
|
||||
redis: {
|
||||
host: process.env.REDIS_HOSTNAME || 'immich_redis',
|
||||
port: parseInt(process.env.REDIS_PORT || '6379'),
|
||||
db: parseInt(process.env.REDIS_DBINDEX || '0'),
|
||||
password: process.env.REDIS_PASSWORD || undefined,
|
||||
path: process.env.REDIS_SOCKET || undefined,
|
||||
},
|
||||
}),
|
||||
}),
|
||||
BullModule.forRootAsync(immichBullAsyncConfig),
|
||||
|
||||
ServerInfoModule,
|
||||
|
||||
|
||||
@@ -10,9 +10,9 @@ export interface IServerVersion {
|
||||
|
||||
export const serverVersion: IServerVersion = {
|
||||
major: 1,
|
||||
minor: 38,
|
||||
minor: 39,
|
||||
patch: 0,
|
||||
build: 60,
|
||||
build: 61,
|
||||
};
|
||||
|
||||
export const SERVER_VERSION = `${serverVersion.major}.${serverVersion.minor}.${serverVersion.patch}`;
|
||||
|
||||
@@ -11,11 +11,6 @@ import { BackgroundTaskService } from './background-task.service';
|
||||
imports: [
|
||||
BullModule.registerQueue({
|
||||
name: 'background-task',
|
||||
defaultJobOptions: {
|
||||
attempts: 3,
|
||||
removeOnComplete: true,
|
||||
removeOnFail: false,
|
||||
},
|
||||
}),
|
||||
TypeOrmModule.forFeature([AssetEntity, ExifEntity, SmartInfoEntity]),
|
||||
],
|
||||
|
||||
@@ -3,46 +3,14 @@ import { Module } from '@nestjs/common';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
import { AssetEntity } from '@app/database/entities/asset.entity';
|
||||
import { ScheduleTasksService } from './schedule-tasks.service';
|
||||
import { QueueNameEnum } from '@app/job/constants/queue-name.constant';
|
||||
import { ExifEntity } from '@app/database/entities/exif.entity';
|
||||
import { UserEntity } from '@app/database/entities/user.entity';
|
||||
import { immichSharedQueues } from '@app/job/constants/bull-queue-registration.constant';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
TypeOrmModule.forFeature([AssetEntity, ExifEntity, UserEntity]),
|
||||
BullModule.registerQueue({
|
||||
name: QueueNameEnum.USER_DELETION,
|
||||
defaultJobOptions: {
|
||||
attempts: 3,
|
||||
removeOnComplete: true,
|
||||
removeOnFail: false,
|
||||
},
|
||||
}),
|
||||
BullModule.registerQueue({
|
||||
name: QueueNameEnum.VIDEO_CONVERSION,
|
||||
defaultJobOptions: {
|
||||
attempts: 3,
|
||||
removeOnComplete: true,
|
||||
removeOnFail: false,
|
||||
},
|
||||
}),
|
||||
BullModule.registerQueue({
|
||||
name: QueueNameEnum.THUMBNAIL_GENERATION,
|
||||
defaultJobOptions: {
|
||||
attempts: 3,
|
||||
removeOnComplete: true,
|
||||
removeOnFail: false,
|
||||
},
|
||||
}),
|
||||
|
||||
BullModule.registerQueue({
|
||||
name: QueueNameEnum.METADATA_EXTRACTION,
|
||||
defaultJobOptions: {
|
||||
attempts: 3,
|
||||
removeOnComplete: true,
|
||||
removeOnFail: false,
|
||||
},
|
||||
}),
|
||||
BullModule.registerQueue(...immichSharedQueues),
|
||||
],
|
||||
providers: [ScheduleTasksService],
|
||||
})
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { immichAppConfig } from '@app/common/config';
|
||||
import { immichAppConfig, immichBullAsyncConfig } from '@app/common/config';
|
||||
import { DatabaseModule } from '@app/database';
|
||||
import { AssetEntity } from '@app/database/entities/asset.entity';
|
||||
import { ExifEntity } from '@app/database/entities/exif.entity';
|
||||
import { SmartInfoEntity } from '@app/database/entities/smart-info.entity';
|
||||
import { UserEntity } from '@app/database/entities/user.entity';
|
||||
import { QueueNameEnum } from '@app/job/constants/queue-name.constant';
|
||||
import { StorageModule } from '@app/storage';
|
||||
import { BullModule } from '@nestjs/bull';
|
||||
import { Module } from '@nestjs/common';
|
||||
import { ConfigModule } from '@nestjs/config';
|
||||
@@ -16,8 +16,11 @@ import { AssetUploadedProcessor } from './processors/asset-uploaded.processor';
|
||||
import { GenerateChecksumProcessor } from './processors/generate-checksum.processor';
|
||||
import { MachineLearningProcessor } from './processors/machine-learning.processor';
|
||||
import { MetadataExtractionProcessor } from './processors/metadata-extraction.processor';
|
||||
import { StorageMigrationProcessor } from './processors/storage-migration.processor';
|
||||
import { ThumbnailGeneratorProcessor } from './processors/thumbnail.processor';
|
||||
import { UserDeletionProcessor } from './processors/user-deletion.processor';
|
||||
import { VideoTranscodeProcessor } from './processors/video-transcode.processor';
|
||||
import { immichSharedQueues } from '@app/job/constants/bull-queue-registration.constant';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
@@ -25,68 +28,9 @@ import { VideoTranscodeProcessor } from './processors/video-transcode.processor'
|
||||
DatabaseModule,
|
||||
ImmichConfigModule,
|
||||
TypeOrmModule.forFeature([UserEntity, ExifEntity, AssetEntity, SmartInfoEntity]),
|
||||
BullModule.forRootAsync({
|
||||
useFactory: async () => ({
|
||||
prefix: 'immich_bull',
|
||||
redis: {
|
||||
host: process.env.REDIS_HOSTNAME || 'immich_redis',
|
||||
port: parseInt(process.env.REDIS_PORT || '6379'),
|
||||
db: parseInt(process.env.REDIS_DBINDEX || '0'),
|
||||
password: process.env.REDIS_PASSWORD || undefined,
|
||||
path: process.env.REDIS_SOCKET || undefined,
|
||||
},
|
||||
}),
|
||||
}),
|
||||
BullModule.registerQueue(
|
||||
{
|
||||
name: QueueNameEnum.THUMBNAIL_GENERATION,
|
||||
defaultJobOptions: {
|
||||
attempts: 3,
|
||||
removeOnComplete: true,
|
||||
removeOnFail: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: QueueNameEnum.ASSET_UPLOADED,
|
||||
defaultJobOptions: {
|
||||
attempts: 3,
|
||||
removeOnComplete: true,
|
||||
removeOnFail: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: QueueNameEnum.METADATA_EXTRACTION,
|
||||
defaultJobOptions: {
|
||||
attempts: 3,
|
||||
removeOnComplete: true,
|
||||
removeOnFail: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: QueueNameEnum.VIDEO_CONVERSION,
|
||||
defaultJobOptions: {
|
||||
attempts: 3,
|
||||
removeOnComplete: true,
|
||||
removeOnFail: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: QueueNameEnum.CHECKSUM_GENERATION,
|
||||
defaultJobOptions: {
|
||||
attempts: 3,
|
||||
removeOnComplete: true,
|
||||
removeOnFail: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: QueueNameEnum.MACHINE_LEARNING,
|
||||
defaultJobOptions: {
|
||||
attempts: 3,
|
||||
removeOnComplete: true,
|
||||
removeOnFail: false,
|
||||
},
|
||||
},
|
||||
),
|
||||
StorageModule,
|
||||
BullModule.forRootAsync(immichBullAsyncConfig),
|
||||
BullModule.registerQueue(...immichSharedQueues),
|
||||
CommunicationModule,
|
||||
],
|
||||
controllers: [],
|
||||
@@ -98,7 +42,9 @@ import { VideoTranscodeProcessor } from './processors/video-transcode.processor'
|
||||
VideoTranscodeProcessor,
|
||||
GenerateChecksumProcessor,
|
||||
MachineLearningProcessor,
|
||||
UserDeletionProcessor,
|
||||
StorageMigrationProcessor,
|
||||
],
|
||||
exports: [],
|
||||
exports: [BullModule],
|
||||
})
|
||||
export class MicroservicesModule {}
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
import { APP_UPLOAD_LOCATION } from '@app/common';
|
||||
import { AssetEntity } from '@app/database/entities/asset.entity';
|
||||
import { ImmichConfigService } from '@app/immich-config';
|
||||
import { QueueNameEnum, templateMigrationProcessorName, updateTemplateProcessorName } from '@app/job';
|
||||
import { StorageService } from '@app/storage';
|
||||
import { Process, Processor } from '@nestjs/bull';
|
||||
import { Logger } from '@nestjs/common';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
import { Repository } from 'typeorm';
|
||||
|
||||
@Processor(QueueNameEnum.STORAGE_MIGRATION)
|
||||
export class StorageMigrationProcessor {
|
||||
readonly logger: Logger = new Logger(StorageMigrationProcessor.name);
|
||||
|
||||
constructor(
|
||||
private storageService: StorageService,
|
||||
private immichConfigService: ImmichConfigService,
|
||||
|
||||
@InjectRepository(AssetEntity)
|
||||
private assetRepository: Repository<AssetEntity>,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Migration process when a new user set a new storage template.
|
||||
* @param job
|
||||
*/
|
||||
@Process({ name: templateMigrationProcessorName, concurrency: 100 })
|
||||
async templateMigration() {
|
||||
console.time('migrating-time');
|
||||
const assets = await this.assetRepository.find({
|
||||
relations: ['exifInfo'],
|
||||
});
|
||||
|
||||
const livePhotoMap: Record<string, AssetEntity> = {};
|
||||
|
||||
for (const asset of assets) {
|
||||
if (asset.livePhotoVideoId) {
|
||||
livePhotoMap[asset.livePhotoVideoId] = asset;
|
||||
}
|
||||
}
|
||||
|
||||
for (const asset of assets) {
|
||||
const livePhotoParentAsset = livePhotoMap[asset.id];
|
||||
const filename = asset.exifInfo?.imageName || livePhotoParentAsset?.exifInfo?.imageName || asset.id;
|
||||
await this.storageService.moveAsset(asset, filename);
|
||||
}
|
||||
|
||||
await this.storageService.removeEmptyDirectories(APP_UPLOAD_LOCATION);
|
||||
console.timeEnd('migrating-time');
|
||||
}
|
||||
|
||||
/**
|
||||
* Update config when a new storage template is set.
|
||||
* This is to ensure the synchronization between processes.
|
||||
* @param job
|
||||
*/
|
||||
@Process({ name: updateTemplateProcessorName, concurrency: 1 })
|
||||
async updateTemplate() {
|
||||
await this.immichConfigService.refreshConfig();
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
import { APP_UPLOAD_LOCATION } from '@app/common';
|
||||
import { ImmichLogLevel } from '@app/common/constants/log-level.constant';
|
||||
import { AssetEntity, AssetType } from '@app/database/entities/asset.entity';
|
||||
import {
|
||||
WebpGeneratorProcessor,
|
||||
@@ -11,7 +10,6 @@ import {
|
||||
} from '@app/job';
|
||||
import { InjectQueue, Process, Processor } from '@nestjs/bull';
|
||||
import { Logger } from '@nestjs/common';
|
||||
import { ConfigService } from '@nestjs/config';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
import { mapAsset } from 'apps/immich/src/api-v1/asset/response-dto/asset-response.dto';
|
||||
import { Job, Queue } from 'bull';
|
||||
@@ -27,7 +25,7 @@ import { IMachineLearningJob } from '@app/job/interfaces/machine-learning.interf
|
||||
|
||||
@Processor(QueueNameEnum.THUMBNAIL_GENERATION)
|
||||
export class ThumbnailGeneratorProcessor {
|
||||
private logLevel: ImmichLogLevel;
|
||||
readonly logger: Logger = new Logger(ThumbnailGeneratorProcessor.name);
|
||||
|
||||
constructor(
|
||||
@InjectRepository(AssetEntity)
|
||||
@@ -40,11 +38,7 @@ export class ThumbnailGeneratorProcessor {
|
||||
|
||||
@InjectQueue(QueueNameEnum.MACHINE_LEARNING)
|
||||
private machineLearningQueue: Queue<IMachineLearningJob>,
|
||||
|
||||
private configService: ConfigService,
|
||||
) {
|
||||
this.logLevel = this.configService.get('LOG_LEVEL') || ImmichLogLevel.SIMPLE;
|
||||
}
|
||||
) {}
|
||||
|
||||
@Process({ name: generateJPEGThumbnailProcessorName, concurrency: 3 })
|
||||
async generateJPEGThumbnail(job: Job<JpegGeneratorProcessor>) {
|
||||
@@ -59,9 +53,7 @@ export class ThumbnailGeneratorProcessor {
|
||||
mkdirSync(resizePath, { recursive: true });
|
||||
}
|
||||
|
||||
const temp = asset.originalPath.split('/');
|
||||
const originalFilename = temp[temp.length - 1].split('.')[0];
|
||||
const jpegThumbnailPath = join(resizePath, `${originalFilename}.jpeg`);
|
||||
const jpegThumbnailPath = join(resizePath, `${asset.id}.jpeg`);
|
||||
|
||||
if (asset.type == AssetType.IMAGE) {
|
||||
try {
|
||||
@@ -71,12 +63,8 @@ export class ThumbnailGeneratorProcessor {
|
||||
.rotate()
|
||||
.toFile(jpegThumbnailPath);
|
||||
await this.assetRepository.update({ id: asset.id }, { resizePath: jpegThumbnailPath });
|
||||
} catch (error) {
|
||||
Logger.error('Failed to generate jpeg thumbnail for asset: ' + asset.id);
|
||||
|
||||
if (this.logLevel == ImmichLogLevel.VERBOSE) {
|
||||
console.trace('Failed to generate jpeg thumbnail for asset', error);
|
||||
}
|
||||
} catch (error: any) {
|
||||
this.logger.error('Failed to generate jpeg thumbnail for asset: ' + asset.id, error.stack);
|
||||
}
|
||||
|
||||
// Update resize path to send to generate webp queue
|
||||
@@ -141,12 +129,8 @@ export class ThumbnailGeneratorProcessor {
|
||||
try {
|
||||
await sharp(asset.resizePath, { failOnError: false }).resize(250).webp().rotate().toFile(webpPath);
|
||||
await this.assetRepository.update({ id: asset.id }, { webpPath: webpPath });
|
||||
} catch (error) {
|
||||
Logger.error('Failed to generate webp thumbnail for asset: ' + asset.id);
|
||||
|
||||
if (this.logLevel == ImmichLogLevel.VERBOSE) {
|
||||
console.trace('Failed to generate webp thumbnail for asset', error);
|
||||
}
|
||||
} catch (error: any) {
|
||||
this.logger.error('Failed to generate webp thumbnail for asset: ' + asset.id, error.stack);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,9 +26,9 @@ export class UserDeletionProcessor {
|
||||
// just for extra protection here
|
||||
if (userUtils.isReadyForDeletion(user)) {
|
||||
const basePath = APP_UPLOAD_LOCATION;
|
||||
const userAssetDir = join(basePath, user.id)
|
||||
fs.rmSync(userAssetDir, { recursive: true, force: true })
|
||||
await this.assetRepository.delete({ userId: user.id })
|
||||
const userAssetDir = join(basePath, user.id);
|
||||
fs.rmSync(userAssetDir, { recursive: true, force: true });
|
||||
await this.assetRepository.delete({ userId: user.id });
|
||||
await this.userRepository.remove(user);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2169,12 +2169,38 @@
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"/system-config/storage-template-options": {
|
||||
"get": {
|
||||
"operationId": "getStorageTemplateOptions",
|
||||
"parameters": [],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/SystemConfigTemplateStorageOptionDto"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"tags": [
|
||||
"System Config"
|
||||
],
|
||||
"security": [
|
||||
{
|
||||
"bearer": []
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"info": {
|
||||
"title": "Immich",
|
||||
"description": "Immich API",
|
||||
"version": "1.38.0",
|
||||
"version": "1.38.2",
|
||||
"contact": {}
|
||||
},
|
||||
"tags": [],
|
||||
@@ -3536,6 +3562,9 @@
|
||||
"machineLearningQueueCount": {
|
||||
"$ref": "#/components/schemas/JobCounts"
|
||||
},
|
||||
"storageMigrationQueueCount": {
|
||||
"$ref": "#/components/schemas/JobCounts"
|
||||
},
|
||||
"isThumbnailGenerationActive": {
|
||||
"type": "boolean"
|
||||
},
|
||||
@@ -3547,6 +3576,9 @@
|
||||
},
|
||||
"isMachineLearningActive": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"isStorageMigrationActive": {
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
@@ -3554,10 +3586,12 @@
|
||||
"metadataExtractionQueueCount",
|
||||
"videoConversionQueueCount",
|
||||
"machineLearningQueueCount",
|
||||
"storageMigrationQueueCount",
|
||||
"isThumbnailGenerationActive",
|
||||
"isMetadataExtractionActive",
|
||||
"isVideoConversionActive",
|
||||
"isMachineLearningActive"
|
||||
"isMachineLearningActive",
|
||||
"isStorageMigrationActive"
|
||||
]
|
||||
},
|
||||
"JobId": {
|
||||
@@ -3566,7 +3600,8 @@
|
||||
"thumbnail-generation",
|
||||
"metadata-extraction",
|
||||
"video-conversion",
|
||||
"machine-learning"
|
||||
"machine-learning",
|
||||
"storage-template-migration"
|
||||
]
|
||||
},
|
||||
"JobStatusResponseDto": {
|
||||
@@ -3664,6 +3699,17 @@
|
||||
"autoRegister"
|
||||
]
|
||||
},
|
||||
"SystemConfigStorageTemplateDto": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"template": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"template"
|
||||
]
|
||||
},
|
||||
"SystemConfigDto": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -3672,11 +3718,71 @@
|
||||
},
|
||||
"oauth": {
|
||||
"$ref": "#/components/schemas/SystemConfigOAuthDto"
|
||||
},
|
||||
"storageTemplate": {
|
||||
"$ref": "#/components/schemas/SystemConfigStorageTemplateDto"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"ffmpeg",
|
||||
"oauth"
|
||||
"oauth",
|
||||
"storageTemplate"
|
||||
]
|
||||
},
|
||||
"SystemConfigTemplateStorageOptionDto": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"yearOptions": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"monthOptions": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"dayOptions": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"hourOptions": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"minuteOptions": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"secondOptions": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"presetOptions": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"yearOptions",
|
||||
"monthOptions",
|
||||
"dayOptions",
|
||||
"hourOptions",
|
||||
"minuteOptions",
|
||||
"secondOptions",
|
||||
"presetOptions"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
19
server/libs/common/src/config/bull-queue.config.ts
Normal file
19
server/libs/common/src/config/bull-queue.config.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import { SharedBullAsyncConfiguration } from '@nestjs/bull';
|
||||
|
||||
export const immichBullAsyncConfig: SharedBullAsyncConfiguration = {
|
||||
useFactory: async () => ({
|
||||
prefix: 'immich_bull',
|
||||
redis: {
|
||||
host: process.env.REDIS_HOSTNAME || 'immich_redis',
|
||||
port: parseInt(process.env.REDIS_PORT || '6379'),
|
||||
db: parseInt(process.env.REDIS_DBINDEX || '0'),
|
||||
password: process.env.REDIS_PASSWORD || undefined,
|
||||
path: process.env.REDIS_SOCKET || undefined,
|
||||
},
|
||||
defaultJobOptions: {
|
||||
attempts: 3,
|
||||
removeOnComplete: true,
|
||||
removeOnFail: false,
|
||||
},
|
||||
}),
|
||||
};
|
||||
@@ -1 +1,2 @@
|
||||
export * from './app.config';
|
||||
export * from './bull-queue.config';
|
||||
|
||||
@@ -7,7 +7,7 @@ function createUserUtils() {
|
||||
// get this number (7 days) from some configuration perhaps ?
|
||||
const millisecondsDeleteWait = millisecondsInDay * 7;
|
||||
|
||||
const millisecondsSinceDelete = new Date().getTime() - (user.deletedAt?.getTime() ?? 0);
|
||||
const millisecondsSinceDelete = new Date().getTime() - (Date.parse(user.deletedAt.toString()) ?? 0);
|
||||
return millisecondsSinceDelete >= millisecondsDeleteWait;
|
||||
};
|
||||
return { isReadyForDeletion };
|
||||
|
||||
@@ -25,6 +25,7 @@ export enum SystemConfigKey {
|
||||
OAUTH_SCOPE = 'oauth.scope',
|
||||
OAUTH_BUTTON_TEXT = 'oauth.buttonText',
|
||||
OAUTH_AUTO_REGISTER = 'oauth.autoRegister',
|
||||
STORAGE_TEMPLATE = 'storageTemplate.template',
|
||||
}
|
||||
|
||||
export interface SystemConfig {
|
||||
@@ -44,4 +45,7 @@ export interface SystemConfig {
|
||||
buttonText: string;
|
||||
autoRegister: boolean;
|
||||
};
|
||||
storageTemplate: {
|
||||
template: string;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,11 +1,24 @@
|
||||
import { SystemConfigEntity } from '@app/database/entities/system-config.entity';
|
||||
import { Module } from '@nestjs/common';
|
||||
import { Module, Provider } from '@nestjs/common';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
import { ImmichConfigService } from './immich-config.service';
|
||||
|
||||
export const INITIAL_SYSTEM_CONFIG = 'INITIAL_SYSTEM_CONFIG';
|
||||
|
||||
const providers: Provider[] = [
|
||||
ImmichConfigService,
|
||||
{
|
||||
provide: INITIAL_SYSTEM_CONFIG,
|
||||
inject: [ImmichConfigService],
|
||||
useFactory: async (configService: ImmichConfigService) => {
|
||||
return configService.getConfig();
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
@Module({
|
||||
imports: [TypeOrmModule.forFeature([SystemConfigEntity])],
|
||||
providers: [ImmichConfigService],
|
||||
exports: [ImmichConfigService],
|
||||
providers: [...providers],
|
||||
exports: [...providers],
|
||||
})
|
||||
export class ImmichConfigModule {}
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
import { SystemConfig, SystemConfigEntity, SystemConfigKey } from '@app/database/entities/system-config.entity';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { BadRequestException, Injectable, Logger } from '@nestjs/common';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
import * as _ from 'lodash';
|
||||
import { Subject } from 'rxjs';
|
||||
import { DeepPartial, In, Repository } from 'typeorm';
|
||||
|
||||
export type SystemConfigValidator = (config: SystemConfig) => void | Promise<void>;
|
||||
|
||||
const defaults: SystemConfig = Object.freeze({
|
||||
ffmpeg: {
|
||||
crf: '23',
|
||||
@@ -21,10 +24,19 @@ const defaults: SystemConfig = Object.freeze({
|
||||
buttonText: 'Login with OAuth',
|
||||
autoRegister: true,
|
||||
},
|
||||
|
||||
storageTemplate: {
|
||||
template: '{{y}}/{{y}}-{{MM}}-{{dd}}/{{filename}}',
|
||||
},
|
||||
});
|
||||
|
||||
@Injectable()
|
||||
export class ImmichConfigService {
|
||||
private logger = new Logger(ImmichConfigService.name);
|
||||
private validators: SystemConfigValidator[] = [];
|
||||
|
||||
public config$ = new Subject<SystemConfig>();
|
||||
|
||||
constructor(
|
||||
@InjectRepository(SystemConfigEntity)
|
||||
private systemConfigRepository: Repository<SystemConfigEntity>,
|
||||
@@ -34,6 +46,10 @@ export class ImmichConfigService {
|
||||
return defaults;
|
||||
}
|
||||
|
||||
public addValidator(validator: SystemConfigValidator) {
|
||||
this.validators.push(validator);
|
||||
}
|
||||
|
||||
public async getConfig() {
|
||||
const overrides = await this.systemConfigRepository.find();
|
||||
const config: DeepPartial<SystemConfig> = {};
|
||||
@@ -45,7 +61,16 @@ export class ImmichConfigService {
|
||||
return _.defaultsDeep(config, defaults) as SystemConfig;
|
||||
}
|
||||
|
||||
public async updateConfig(config: DeepPartial<SystemConfig> | null): Promise<void> {
|
||||
public async updateConfig(config: SystemConfig): Promise<SystemConfig> {
|
||||
try {
|
||||
for (const validator of this.validators) {
|
||||
await validator(config);
|
||||
}
|
||||
} catch (e) {
|
||||
this.logger.warn(`Unable to save system config due to a validation error: ${e}`);
|
||||
throw new BadRequestException(e instanceof Error ? e.message : e);
|
||||
}
|
||||
|
||||
const updates: SystemConfigEntity[] = [];
|
||||
const deletes: SystemConfigEntity[] = [];
|
||||
|
||||
@@ -70,5 +95,17 @@ export class ImmichConfigService {
|
||||
if (deletes.length > 0) {
|
||||
await this.systemConfigRepository.delete({ key: In(deletes.map((item) => item.key)) });
|
||||
}
|
||||
|
||||
const newConfig = await this.getConfig();
|
||||
|
||||
this.config$.next(newConfig);
|
||||
|
||||
return newConfig;
|
||||
}
|
||||
|
||||
public async refreshConfig() {
|
||||
const newConfig = await this.getConfig();
|
||||
|
||||
this.config$.next(newConfig);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
import { BullModuleOptions } from '@nestjs/bull';
|
||||
import { QueueNameEnum } from './queue-name.constant';
|
||||
|
||||
/**
|
||||
* Shared queues between apps and microservices
|
||||
*/
|
||||
export const immichSharedQueues: BullModuleOptions[] = [
|
||||
{
|
||||
name: QueueNameEnum.USER_DELETION,
|
||||
},
|
||||
{
|
||||
name: QueueNameEnum.THUMBNAIL_GENERATION,
|
||||
},
|
||||
{
|
||||
name: QueueNameEnum.ASSET_UPLOADED,
|
||||
},
|
||||
{
|
||||
name: QueueNameEnum.METADATA_EXTRACTION,
|
||||
},
|
||||
{
|
||||
name: QueueNameEnum.VIDEO_CONVERSION,
|
||||
},
|
||||
{
|
||||
name: QueueNameEnum.CHECKSUM_GENERATION,
|
||||
},
|
||||
{
|
||||
name: QueueNameEnum.MACHINE_LEARNING,
|
||||
},
|
||||
{
|
||||
name: QueueNameEnum.STORAGE_MIGRATION,
|
||||
},
|
||||
];
|
||||
@@ -34,3 +34,9 @@ export enum MachineLearningJobNameEnum {
|
||||
* User deletion Queue Jobs
|
||||
*/
|
||||
export const userDeletionProcessorName = 'user-deletion';
|
||||
|
||||
/**
|
||||
* Storage Template Migration Queue Jobs
|
||||
*/
|
||||
export const templateMigrationProcessorName = 'template-migration';
|
||||
export const updateTemplateProcessorName = 'update-template';
|
||||
|
||||
@@ -6,4 +6,5 @@ export enum QueueNameEnum {
|
||||
ASSET_UPLOADED = 'asset-uploaded-queue',
|
||||
MACHINE_LEARNING = 'machine-learning-queue',
|
||||
USER_DELETION = 'user-deletion-queue',
|
||||
STORAGE_MIGRATION = 'storage-template-migration',
|
||||
}
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
export const supportedYearTokens = ['y', 'yy'];
|
||||
export const supportedMonthTokens = ['M', 'MM', 'MMM', 'MMMM'];
|
||||
export const supportedDayTokens = ['d', 'dd'];
|
||||
export const supportedHourTokens = ['h', 'hh', 'H', 'HH'];
|
||||
export const supportedMinuteTokens = ['m', 'mm'];
|
||||
export const supportedSecondTokens = ['s', 'ss'];
|
||||
export const supportedPresetTokens = [
|
||||
'{{y}}/{{y}}-{{MM}}-{{dd}}/{{filename}}',
|
||||
'{{y}}/{{MM}}-{{dd}}/{{filename}}',
|
||||
'{{y}}/{{MMMM}}-{{dd}}/{{filename}}',
|
||||
'{{y}}/{{MM}}/{{filename}}',
|
||||
'{{y}}/{{MMM}}/{{filename}}',
|
||||
'{{y}}/{{MMMM}}/{{filename}}',
|
||||
'{{y}}/{{MM}}/{{dd}}/{{filename}}',
|
||||
'{{y}}/{{MMMM}}/{{dd}}/{{filename}}',
|
||||
'{{y}}/{{y}}-{{MM}}/{{y}}-{{MM}}-{{dd}}/{{filename}}',
|
||||
'{{y}}-{{MM}}-{{dd}}/{{filename}}',
|
||||
'{{y}}-{{MMM}}-{{dd}}/{{filename}}',
|
||||
'{{y}}-{{MMMM}}-{{dd}}/{{filename}}',
|
||||
];
|
||||
2
server/libs/storage/src/index.ts
Normal file
2
server/libs/storage/src/index.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
export * from './storage.module';
|
||||
export * from './storage.service';
|
||||
@@ -0,0 +1,6 @@
|
||||
export interface IImmichStorage {
|
||||
write(): Promise<void>;
|
||||
read(): Promise<void>;
|
||||
}
|
||||
|
||||
export enum IStorageType {}
|
||||
13
server/libs/storage/src/storage.module.ts
Normal file
13
server/libs/storage/src/storage.module.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import { AssetEntity } from '@app/database/entities/asset.entity';
|
||||
import { SystemConfigEntity } from '@app/database/entities/system-config.entity';
|
||||
import { ImmichConfigModule } from '@app/immich-config';
|
||||
import { Module } from '@nestjs/common';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
import { StorageService } from './storage.service';
|
||||
|
||||
@Module({
|
||||
imports: [TypeOrmModule.forFeature([AssetEntity, SystemConfigEntity]), ImmichConfigModule],
|
||||
providers: [StorageService],
|
||||
exports: [StorageService],
|
||||
})
|
||||
export class StorageModule {}
|
||||
202
server/libs/storage/src/storage.service.ts
Normal file
202
server/libs/storage/src/storage.service.ts
Normal file
@@ -0,0 +1,202 @@
|
||||
import { APP_UPLOAD_LOCATION } from '@app/common';
|
||||
import { AssetEntity } from '@app/database/entities/asset.entity';
|
||||
import { SystemConfig } from '@app/database/entities/system-config.entity';
|
||||
import { ImmichConfigService, INITIAL_SYSTEM_CONFIG } from '@app/immich-config';
|
||||
import { Inject, Injectable, Logger } from '@nestjs/common';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
import fsPromise from 'fs/promises';
|
||||
import handlebar from 'handlebars';
|
||||
import * as luxon from 'luxon';
|
||||
import mv from 'mv';
|
||||
import { constants } from 'node:fs';
|
||||
import path from 'node:path';
|
||||
import { promisify } from 'node:util';
|
||||
import sanitize from 'sanitize-filename';
|
||||
import { Repository } from 'typeorm';
|
||||
import {
|
||||
supportedDayTokens,
|
||||
supportedHourTokens,
|
||||
supportedMinuteTokens,
|
||||
supportedMonthTokens,
|
||||
supportedSecondTokens,
|
||||
supportedYearTokens,
|
||||
} from './constants/supported-datetime-template';
|
||||
|
||||
const moveFile = promisify<string, string, mv.Options>(mv);
|
||||
|
||||
@Injectable()
|
||||
export class StorageService {
|
||||
readonly logger = new Logger(StorageService.name);
|
||||
|
||||
private storageTemplate: HandlebarsTemplateDelegate<any>;
|
||||
|
||||
constructor(
|
||||
@InjectRepository(AssetEntity)
|
||||
private assetRepository: Repository<AssetEntity>,
|
||||
private immichConfigService: ImmichConfigService,
|
||||
@Inject(INITIAL_SYSTEM_CONFIG) config: SystemConfig,
|
||||
) {
|
||||
this.storageTemplate = this.compile(config.storageTemplate.template);
|
||||
|
||||
this.immichConfigService.addValidator((config) => this.validateConfig(config));
|
||||
|
||||
this.immichConfigService.config$.subscribe((config) => {
|
||||
this.logger.debug(`Received new config, recompiling storage template: ${config.storageTemplate.template}`);
|
||||
this.storageTemplate = this.compile(config.storageTemplate.template);
|
||||
});
|
||||
}
|
||||
|
||||
public async moveAsset(asset: AssetEntity, filename: string): Promise<AssetEntity> {
|
||||
try {
|
||||
const source = asset.originalPath;
|
||||
const ext = path.extname(source).split('.').pop() as string;
|
||||
const sanitized = sanitize(path.basename(filename, `.${ext}`));
|
||||
const rootPath = path.join(APP_UPLOAD_LOCATION, asset.userId);
|
||||
const storagePath = this.render(this.storageTemplate, asset, sanitized, ext);
|
||||
const fullPath = path.normalize(path.join(rootPath, storagePath));
|
||||
let destination = `${fullPath}.${ext}`;
|
||||
|
||||
if (!fullPath.startsWith(rootPath)) {
|
||||
this.logger.warn(`Skipped attempt to access an invalid path: ${fullPath}. Path should start with ${rootPath}`);
|
||||
return asset;
|
||||
}
|
||||
|
||||
if (source === destination) {
|
||||
return asset;
|
||||
}
|
||||
|
||||
/**
|
||||
* In case of migrating duplicate filename to a new path, we need to check if it is already migrated
|
||||
* Due to the mechanism of appending +1, +2, +3, etc to the filename
|
||||
*
|
||||
* Example:
|
||||
* Source = upload/abc/def/FullSizeRender+7.heic
|
||||
* Expected Destination = upload/abc/def/FullSizeRender.heic
|
||||
*
|
||||
* The file is already at the correct location, but since there are other FullSizeRender.heic files in the
|
||||
* destination, it was renamed to FullSizeRender+7.heic.
|
||||
*
|
||||
* The lines below will be used to check if the differences between the source and destination is only the
|
||||
* +7 suffix, and if so, it will be considered as already migrated.
|
||||
*/
|
||||
if (source.startsWith(fullPath) && source.endsWith(`.${ext}`)) {
|
||||
const diff = source.replace(fullPath, '').replace(`.${ext}`, '');
|
||||
const hasDuplicationAnnotation = /^\+\d+$/.test(diff);
|
||||
if (hasDuplicationAnnotation) {
|
||||
return asset;
|
||||
}
|
||||
}
|
||||
|
||||
let duplicateCount = 0;
|
||||
|
||||
while (true) {
|
||||
const exists = await this.checkFileExist(destination);
|
||||
if (!exists) {
|
||||
break;
|
||||
}
|
||||
|
||||
duplicateCount++;
|
||||
destination = `${fullPath}+${duplicateCount}.${ext}`;
|
||||
}
|
||||
|
||||
await this.safeMove(source, destination);
|
||||
|
||||
asset.originalPath = destination;
|
||||
return await this.assetRepository.save(asset);
|
||||
} catch (error: any) {
|
||||
this.logger.error(error);
|
||||
return asset;
|
||||
}
|
||||
}
|
||||
|
||||
private safeMove(source: string, destination: string): Promise<void> {
|
||||
return moveFile(source, destination, { mkdirp: true, clobber: false });
|
||||
}
|
||||
|
||||
private async checkFileExist(path: string): Promise<boolean> {
|
||||
try {
|
||||
await fsPromise.access(path, constants.F_OK);
|
||||
return true;
|
||||
} catch (_) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private validateConfig(config: SystemConfig) {
|
||||
this.validateStorageTemplate(config.storageTemplate.template);
|
||||
}
|
||||
|
||||
private validateStorageTemplate(templateString: string) {
|
||||
try {
|
||||
const template = this.compile(templateString);
|
||||
|
||||
// test render an asset
|
||||
this.render(
|
||||
template,
|
||||
{
|
||||
createdAt: new Date().toISOString(),
|
||||
originalPath: '/upload/test/IMG_123.jpg',
|
||||
} as AssetEntity,
|
||||
'IMG_123',
|
||||
'jpg',
|
||||
);
|
||||
} catch (e) {
|
||||
this.logger.warn(`Storage template validation failed: ${e}`);
|
||||
throw new Error(`Invalid storage template: ${e}`);
|
||||
}
|
||||
}
|
||||
|
||||
private compile(template: string) {
|
||||
return handlebar.compile(template, {
|
||||
knownHelpers: undefined,
|
||||
strict: true,
|
||||
});
|
||||
}
|
||||
|
||||
private render(template: HandlebarsTemplateDelegate<any>, asset: AssetEntity, filename: string, ext: string) {
|
||||
const substitutions: Record<string, string> = {
|
||||
filename,
|
||||
ext,
|
||||
};
|
||||
|
||||
const dt = luxon.DateTime.fromISO(new Date(asset.createdAt).toISOString());
|
||||
|
||||
const dateTokens = [
|
||||
...supportedYearTokens,
|
||||
...supportedMonthTokens,
|
||||
...supportedDayTokens,
|
||||
...supportedHourTokens,
|
||||
...supportedMinuteTokens,
|
||||
...supportedSecondTokens,
|
||||
];
|
||||
|
||||
for (const token of dateTokens) {
|
||||
substitutions[token] = dt.toFormat(token);
|
||||
}
|
||||
|
||||
return template(substitutions);
|
||||
}
|
||||
|
||||
public async removeEmptyDirectories(directory: string) {
|
||||
// lstat does not follow symlinks (in contrast to stat)
|
||||
const fileStats = await fsPromise.lstat(directory);
|
||||
if (!fileStats.isDirectory()) {
|
||||
return;
|
||||
}
|
||||
let fileNames = await fsPromise.readdir(directory);
|
||||
if (fileNames.length > 0) {
|
||||
const recursiveRemovalPromises = fileNames.map((fileName) =>
|
||||
this.removeEmptyDirectories(path.join(directory, fileName)),
|
||||
);
|
||||
await Promise.all(recursiveRemovalPromises);
|
||||
|
||||
// re-evaluate fileNames; after deleting subdirectory
|
||||
// we may have parent directory empty now
|
||||
fileNames = await fsPromise.readdir(directory);
|
||||
}
|
||||
|
||||
if (fileNames.length === 0) {
|
||||
await fsPromise.rmdir(directory);
|
||||
}
|
||||
}
|
||||
}
|
||||
9
server/libs/storage/tsconfig.lib.json
Normal file
9
server/libs/storage/tsconfig.lib.json
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"declaration": true,
|
||||
"outDir": "../../dist/libs/storage"
|
||||
},
|
||||
"include": ["src/**/*"],
|
||||
"exclude": ["node_modules", "dist", "test", "**/*spec.ts"]
|
||||
}
|
||||
@@ -79,6 +79,15 @@
|
||||
"compilerOptions": {
|
||||
"tsConfigPath": "libs/immich-config/tsconfig.lib.json"
|
||||
}
|
||||
},
|
||||
"storage": {
|
||||
"type": "library",
|
||||
"root": "libs/storage",
|
||||
"entryFile": "index",
|
||||
"sourceRoot": "libs/storage/src",
|
||||
"compilerOptions": {
|
||||
"tsConfigPath": "libs/storage/tsconfig.lib.json"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
180
server/package-lock.json
generated
180
server/package-lock.json
generated
@@ -36,11 +36,13 @@
|
||||
"fdir": "^5.3.0",
|
||||
"fluent-ffmpeg": "^2.1.2",
|
||||
"geo-tz": "^7.0.2",
|
||||
"handlebars": "^4.7.7",
|
||||
"i18n-iso-countries": "^7.5.0",
|
||||
"joi": "^17.5.0",
|
||||
"local-reverse-geocoder": "^0.12.5",
|
||||
"lodash": "^4.17.21",
|
||||
"luxon": "^3.0.3",
|
||||
"mv": "^2.1.1",
|
||||
"nest-commander": "^3.3.0",
|
||||
"openid-client": "^5.2.1",
|
||||
"passport": "^0.6.0",
|
||||
@@ -76,6 +78,7 @@
|
||||
"@types/jest": "27.0.2",
|
||||
"@types/lodash": "^4.14.178",
|
||||
"@types/multer": "^1.4.7",
|
||||
"@types/mv": "^2.1.2",
|
||||
"@types/node": "^16.0.0",
|
||||
"@types/passport-jwt": "^3.0.6",
|
||||
"@types/sharp": "^0.30.2",
|
||||
@@ -2544,6 +2547,12 @@
|
||||
"@types/express": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/mv": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/mv/-/mv-2.1.2.tgz",
|
||||
"integrity": "sha512-IvAjPuiQ2exDicnTrMidt1m+tj3gZ60BM0PaoRsU0m9Cn+lrOyemuO9Tf8CvHFmXlxMjr1TVCfadi9sfwbSuKg==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "16.11.21",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.21.tgz",
|
||||
@@ -6168,6 +6177,34 @@
|
||||
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz",
|
||||
"integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ=="
|
||||
},
|
||||
"node_modules/handlebars": {
|
||||
"version": "4.7.7",
|
||||
"resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz",
|
||||
"integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==",
|
||||
"dependencies": {
|
||||
"minimist": "^1.2.5",
|
||||
"neo-async": "^2.6.0",
|
||||
"source-map": "^0.6.1",
|
||||
"wordwrap": "^1.0.0"
|
||||
},
|
||||
"bin": {
|
||||
"handlebars": "bin/handlebars"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.4.7"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"uglify-js": "^3.1.4"
|
||||
}
|
||||
},
|
||||
"node_modules/handlebars/node_modules/source-map": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
||||
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/har-schema": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
|
||||
@@ -8178,6 +8215,45 @@
|
||||
"resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz",
|
||||
"integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA=="
|
||||
},
|
||||
"node_modules/mv": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/mv/-/mv-2.1.1.tgz",
|
||||
"integrity": "sha512-at/ZndSy3xEGJ8i0ygALh8ru9qy7gWW1cmkaqBN29JmMlIvM//MEO9y1sk/avxuwnPcfhkejkLsuPxH81BrkSg==",
|
||||
"dependencies": {
|
||||
"mkdirp": "~0.5.1",
|
||||
"ncp": "~2.0.0",
|
||||
"rimraf": "~2.4.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/mv/node_modules/glob": {
|
||||
"version": "6.0.4",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-6.0.4.tgz",
|
||||
"integrity": "sha512-MKZeRNyYZAVVVG1oZeLaWie1uweH40m9AZwIwxyPbTSX4hHrVYSzLg0Ro5Z5R7XKkIX+Cc6oD1rqeDJnwsB8/A==",
|
||||
"dependencies": {
|
||||
"inflight": "^1.0.4",
|
||||
"inherits": "2",
|
||||
"minimatch": "2 || 3",
|
||||
"once": "^1.3.0",
|
||||
"path-is-absolute": "^1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/mv/node_modules/rimraf": {
|
||||
"version": "2.4.5",
|
||||
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.4.5.tgz",
|
||||
"integrity": "sha512-J5xnxTyqaiw06JjMftq7L9ouA448dw/E7dKghkP9WpKNuwmARNNg+Gk8/u5ryb9N/Yo2+z3MCwuqFK/+qPOPfQ==",
|
||||
"dependencies": {
|
||||
"glob": "^6.0.1"
|
||||
},
|
||||
"bin": {
|
||||
"rimraf": "bin.js"
|
||||
}
|
||||
},
|
||||
"node_modules/mz": {
|
||||
"version": "2.7.0",
|
||||
"resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz",
|
||||
@@ -8204,6 +8280,14 @@
|
||||
"integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/ncp": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ncp/-/ncp-2.0.0.tgz",
|
||||
"integrity": "sha512-zIdGUrPRFTUELUvr3Gmc7KZ2Sw/h1PiVM0Af/oHB6zgnV1ikqSfRk+TOufi79aHYCW3NiOXmr1BP5nWbzojLaA==",
|
||||
"bin": {
|
||||
"ncp": "bin/ncp"
|
||||
}
|
||||
},
|
||||
"node_modules/negotiator": {
|
||||
"version": "0.6.3",
|
||||
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
|
||||
@@ -8215,8 +8299,7 @@
|
||||
"node_modules/neo-async": {
|
||||
"version": "2.6.2",
|
||||
"resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz",
|
||||
"integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==",
|
||||
"dev": true
|
||||
"integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw=="
|
||||
},
|
||||
"node_modules/nest-commander": {
|
||||
"version": "3.3.0",
|
||||
@@ -11006,6 +11089,18 @@
|
||||
"node": ">=4.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/uglify-js": {
|
||||
"version": "3.17.4",
|
||||
"resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.4.tgz",
|
||||
"integrity": "sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==",
|
||||
"optional": true,
|
||||
"bin": {
|
||||
"uglifyjs": "bin/uglifyjs"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/uid2": {
|
||||
"version": "0.0.3",
|
||||
"resolved": "https://registry.npmjs.org/uid2/-/uid2-0.0.3.tgz",
|
||||
@@ -11329,6 +11424,11 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/wordwrap": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz",
|
||||
"integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q=="
|
||||
},
|
||||
"node_modules/wrap-ansi": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
|
||||
@@ -13393,6 +13493,12 @@
|
||||
"@types/express": "*"
|
||||
}
|
||||
},
|
||||
"@types/mv": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/mv/-/mv-2.1.2.tgz",
|
||||
"integrity": "sha512-IvAjPuiQ2exDicnTrMidt1m+tj3gZ60BM0PaoRsU0m9Cn+lrOyemuO9Tf8CvHFmXlxMjr1TVCfadi9sfwbSuKg==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/node": {
|
||||
"version": "16.11.21",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.21.tgz",
|
||||
@@ -16213,6 +16319,25 @@
|
||||
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz",
|
||||
"integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ=="
|
||||
},
|
||||
"handlebars": {
|
||||
"version": "4.7.7",
|
||||
"resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz",
|
||||
"integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==",
|
||||
"requires": {
|
||||
"minimist": "^1.2.5",
|
||||
"neo-async": "^2.6.0",
|
||||
"source-map": "^0.6.1",
|
||||
"uglify-js": "^3.1.4",
|
||||
"wordwrap": "^1.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"source-map": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
||||
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"har-schema": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
|
||||
@@ -17773,6 +17898,38 @@
|
||||
"resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz",
|
||||
"integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA=="
|
||||
},
|
||||
"mv": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/mv/-/mv-2.1.1.tgz",
|
||||
"integrity": "sha512-at/ZndSy3xEGJ8i0ygALh8ru9qy7gWW1cmkaqBN29JmMlIvM//MEO9y1sk/avxuwnPcfhkejkLsuPxH81BrkSg==",
|
||||
"requires": {
|
||||
"mkdirp": "~0.5.1",
|
||||
"ncp": "~2.0.0",
|
||||
"rimraf": "~2.4.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"glob": {
|
||||
"version": "6.0.4",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-6.0.4.tgz",
|
||||
"integrity": "sha512-MKZeRNyYZAVVVG1oZeLaWie1uweH40m9AZwIwxyPbTSX4hHrVYSzLg0Ro5Z5R7XKkIX+Cc6oD1rqeDJnwsB8/A==",
|
||||
"requires": {
|
||||
"inflight": "^1.0.4",
|
||||
"inherits": "2",
|
||||
"minimatch": "2 || 3",
|
||||
"once": "^1.3.0",
|
||||
"path-is-absolute": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"rimraf": {
|
||||
"version": "2.4.5",
|
||||
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.4.5.tgz",
|
||||
"integrity": "sha512-J5xnxTyqaiw06JjMftq7L9ouA448dw/E7dKghkP9WpKNuwmARNNg+Gk8/u5ryb9N/Yo2+z3MCwuqFK/+qPOPfQ==",
|
||||
"requires": {
|
||||
"glob": "^6.0.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"mz": {
|
||||
"version": "2.7.0",
|
||||
"resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz",
|
||||
@@ -17799,6 +17956,11 @@
|
||||
"integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=",
|
||||
"dev": true
|
||||
},
|
||||
"ncp": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ncp/-/ncp-2.0.0.tgz",
|
||||
"integrity": "sha512-zIdGUrPRFTUELUvr3Gmc7KZ2Sw/h1PiVM0Af/oHB6zgnV1ikqSfRk+TOufi79aHYCW3NiOXmr1BP5nWbzojLaA=="
|
||||
},
|
||||
"negotiator": {
|
||||
"version": "0.6.3",
|
||||
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
|
||||
@@ -17807,8 +17969,7 @@
|
||||
"neo-async": {
|
||||
"version": "2.6.2",
|
||||
"resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz",
|
||||
"integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==",
|
||||
"dev": true
|
||||
"integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw=="
|
||||
},
|
||||
"nest-commander": {
|
||||
"version": "3.3.0",
|
||||
@@ -19794,6 +19955,12 @@
|
||||
"integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==",
|
||||
"devOptional": true
|
||||
},
|
||||
"uglify-js": {
|
||||
"version": "3.17.4",
|
||||
"resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.4.tgz",
|
||||
"integrity": "sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==",
|
||||
"optional": true
|
||||
},
|
||||
"uid2": {
|
||||
"version": "0.0.3",
|
||||
"resolved": "https://registry.npmjs.org/uid2/-/uid2-0.0.3.tgz",
|
||||
@@ -20049,6 +20216,11 @@
|
||||
"integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==",
|
||||
"dev": true
|
||||
},
|
||||
"wordwrap": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz",
|
||||
"integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q=="
|
||||
},
|
||||
"wrap-ansi": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
|
||||
|
||||
@@ -59,11 +59,13 @@
|
||||
"fdir": "^5.3.0",
|
||||
"fluent-ffmpeg": "^2.1.2",
|
||||
"geo-tz": "^7.0.2",
|
||||
"handlebars": "^4.7.7",
|
||||
"i18n-iso-countries": "^7.5.0",
|
||||
"joi": "^17.5.0",
|
||||
"local-reverse-geocoder": "^0.12.5",
|
||||
"lodash": "^4.17.21",
|
||||
"luxon": "^3.0.3",
|
||||
"mv": "^2.1.1",
|
||||
"nest-commander": "^3.3.0",
|
||||
"openid-client": "^5.2.1",
|
||||
"passport": "^0.6.0",
|
||||
@@ -96,6 +98,7 @@
|
||||
"@types/jest": "27.0.2",
|
||||
"@types/lodash": "^4.14.178",
|
||||
"@types/multer": "^1.4.7",
|
||||
"@types/mv": "^2.1.2",
|
||||
"@types/node": "^16.0.0",
|
||||
"@types/passport-jwt": "^3.0.6",
|
||||
"@types/sharp": "^0.30.2",
|
||||
@@ -142,7 +145,8 @@
|
||||
"@app/database/config": "<rootDir>/libs/database/src/config",
|
||||
"@app/common": "<rootDir>/libs/common/src",
|
||||
"^@app/job(|/.*)$": "<rootDir>/libs/job/src/$1",
|
||||
"^@app/immich-config(|/.*)$": "<rootDir>/libs/immich-config/src/$1"
|
||||
"^@app/immich-config(|/.*)$": "<rootDir>/libs/immich-config/src/$1",
|
||||
"^@app/storage(|/.*)$": "<rootDir>/libs/storage/src/$1"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,15 +16,41 @@
|
||||
"esModuleInterop": true,
|
||||
"baseUrl": "./",
|
||||
"paths": {
|
||||
"@app/common": ["libs/common/src"],
|
||||
"@app/common/*": ["libs/common/src/*"],
|
||||
"@app/database": ["libs/database/src"],
|
||||
"@app/database/*": ["libs/database/src/*"],
|
||||
"@app/job": ["libs/job/src"],
|
||||
"@app/job/*": ["libs/job/src/*"],
|
||||
"@app/immich-config": ["libs/immich-config/src"],
|
||||
"@app/immich-config/*": ["libs/immich-config/src/*"]
|
||||
"@app/common": [
|
||||
"libs/common/src"
|
||||
],
|
||||
"@app/common/*": [
|
||||
"libs/common/src/*"
|
||||
],
|
||||
"@app/database": [
|
||||
"libs/database/src"
|
||||
],
|
||||
"@app/database/*": [
|
||||
"libs/database/src/*"
|
||||
],
|
||||
"@app/job": [
|
||||
"libs/job/src"
|
||||
],
|
||||
"@app/job/*": [
|
||||
"libs/job/src/*"
|
||||
],
|
||||
"@app/immich-config": [
|
||||
"libs/immich-config/src"
|
||||
],
|
||||
"@app/immich-config/*": [
|
||||
"libs/immich-config/src/*"
|
||||
],
|
||||
"@app/storage": [
|
||||
"libs/storage/src"
|
||||
],
|
||||
"@app/storage/*": [
|
||||
"libs/storage/src/*"
|
||||
]
|
||||
}
|
||||
},
|
||||
"exclude": ["dist", "node_modules", "upload"]
|
||||
}
|
||||
"exclude": [
|
||||
"dist",
|
||||
"node_modules",
|
||||
"upload"
|
||||
]
|
||||
}
|
||||
1724
web/package-lock.json
generated
1724
web/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -21,9 +21,9 @@
|
||||
"@babel/preset-env": "^7.19.0",
|
||||
"@babel/preset-typescript": "^7.18.6",
|
||||
"@faker-js/faker": "^7.5.0",
|
||||
"@sveltejs/adapter-auto": "next",
|
||||
"@sveltejs/adapter-node": "next",
|
||||
"@sveltejs/kit": "next",
|
||||
"@sveltejs/adapter-auto": "^1.0.0",
|
||||
"@sveltejs/adapter-node": "^1.0.0",
|
||||
"@sveltejs/kit": "^1.0.0",
|
||||
"@testing-library/jest-dom": "^5.16.5",
|
||||
"@testing-library/svelte": "^3.2.1",
|
||||
"@types/bcrypt": "^5.0.0",
|
||||
@@ -32,6 +32,7 @@
|
||||
"@types/leaflet": "^1.7.10",
|
||||
"@types/lodash": "^4.14.182",
|
||||
"@types/lodash-es": "^4.17.6",
|
||||
"@types/luxon": "^3.1.0",
|
||||
"@types/socket.io-client": "^3.0.0",
|
||||
"@typescript-eslint/eslint-plugin": "^5.27.0",
|
||||
"@typescript-eslint/parser": "^5.27.0",
|
||||
@@ -54,7 +55,7 @@
|
||||
"tailwindcss": "^3.0.24",
|
||||
"tslib": "^2.3.1",
|
||||
"typescript": "^4.7.4",
|
||||
"vite": "^3.0.0"
|
||||
"vite": "^4.0.0"
|
||||
},
|
||||
"type": "module",
|
||||
"dependencies": {
|
||||
@@ -62,9 +63,11 @@
|
||||
"cookie": "^0.4.2",
|
||||
"copy-image-clipboard": "^2.1.2",
|
||||
"exifr": "^7.1.3",
|
||||
"handlebars": "^4.7.7",
|
||||
"leaflet": "^1.8.0",
|
||||
"lodash": "^4.17.21",
|
||||
"lodash-es": "^4.17.21",
|
||||
"luxon": "^3.1.1",
|
||||
"socket.io-client": "^4.5.1",
|
||||
"svelte-keydown": "^0.5.0",
|
||||
"svelte-material-icons": "^2.0.2"
|
||||
|
||||
145
web/src/api/open-api/api.ts
generated
145
web/src/api/open-api/api.ts
generated
@@ -4,7 +4,7 @@
|
||||
* Immich
|
||||
* Immich API
|
||||
*
|
||||
* The version of the OpenAPI document: 1.38.0
|
||||
* The version of the OpenAPI document: 1.38.2
|
||||
*
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||
@@ -225,6 +225,12 @@ export interface AllJobStatusResponseDto {
|
||||
* @memberof AllJobStatusResponseDto
|
||||
*/
|
||||
'machineLearningQueueCount': JobCounts;
|
||||
/**
|
||||
*
|
||||
* @type {JobCounts}
|
||||
* @memberof AllJobStatusResponseDto
|
||||
*/
|
||||
'storageMigrationQueueCount': JobCounts;
|
||||
/**
|
||||
*
|
||||
* @type {boolean}
|
||||
@@ -249,6 +255,12 @@ export interface AllJobStatusResponseDto {
|
||||
* @memberof AllJobStatusResponseDto
|
||||
*/
|
||||
'isMachineLearningActive': boolean;
|
||||
/**
|
||||
*
|
||||
* @type {boolean}
|
||||
* @memberof AllJobStatusResponseDto
|
||||
*/
|
||||
'isStorageMigrationActive': boolean;
|
||||
}
|
||||
/**
|
||||
*
|
||||
@@ -1038,7 +1050,8 @@ export const JobId = {
|
||||
ThumbnailGeneration: 'thumbnail-generation',
|
||||
MetadataExtraction: 'metadata-extraction',
|
||||
VideoConversion: 'video-conversion',
|
||||
MachineLearning: 'machine-learning'
|
||||
MachineLearning: 'machine-learning',
|
||||
StorageTemplateMigration: 'storage-template-migration'
|
||||
} as const;
|
||||
|
||||
export type JobId = typeof JobId[keyof typeof JobId];
|
||||
@@ -1443,6 +1456,12 @@ export interface SystemConfigDto {
|
||||
* @memberof SystemConfigDto
|
||||
*/
|
||||
'oauth': SystemConfigOAuthDto;
|
||||
/**
|
||||
*
|
||||
* @type {SystemConfigStorageTemplateDto}
|
||||
* @memberof SystemConfigDto
|
||||
*/
|
||||
'storageTemplate': SystemConfigStorageTemplateDto;
|
||||
}
|
||||
/**
|
||||
*
|
||||
@@ -1530,6 +1549,68 @@ export interface SystemConfigOAuthDto {
|
||||
*/
|
||||
'autoRegister': boolean;
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @export
|
||||
* @interface SystemConfigStorageTemplateDto
|
||||
*/
|
||||
export interface SystemConfigStorageTemplateDto {
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof SystemConfigStorageTemplateDto
|
||||
*/
|
||||
'template': string;
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @export
|
||||
* @interface SystemConfigTemplateStorageOptionDto
|
||||
*/
|
||||
export interface SystemConfigTemplateStorageOptionDto {
|
||||
/**
|
||||
*
|
||||
* @type {Array<string>}
|
||||
* @memberof SystemConfigTemplateStorageOptionDto
|
||||
*/
|
||||
'yearOptions': Array<string>;
|
||||
/**
|
||||
*
|
||||
* @type {Array<string>}
|
||||
* @memberof SystemConfigTemplateStorageOptionDto
|
||||
*/
|
||||
'monthOptions': Array<string>;
|
||||
/**
|
||||
*
|
||||
* @type {Array<string>}
|
||||
* @memberof SystemConfigTemplateStorageOptionDto
|
||||
*/
|
||||
'dayOptions': Array<string>;
|
||||
/**
|
||||
*
|
||||
* @type {Array<string>}
|
||||
* @memberof SystemConfigTemplateStorageOptionDto
|
||||
*/
|
||||
'hourOptions': Array<string>;
|
||||
/**
|
||||
*
|
||||
* @type {Array<string>}
|
||||
* @memberof SystemConfigTemplateStorageOptionDto
|
||||
*/
|
||||
'minuteOptions': Array<string>;
|
||||
/**
|
||||
*
|
||||
* @type {Array<string>}
|
||||
* @memberof SystemConfigTemplateStorageOptionDto
|
||||
*/
|
||||
'secondOptions': Array<string>;
|
||||
/**
|
||||
*
|
||||
* @type {Array<string>}
|
||||
* @memberof SystemConfigTemplateStorageOptionDto
|
||||
*/
|
||||
'presetOptions': Array<string>;
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @export
|
||||
@@ -5312,6 +5393,39 @@ export const SystemConfigApiAxiosParamCreator = function (configuration?: Config
|
||||
|
||||
|
||||
|
||||
setSearchParams(localVarUrlObj, localVarQueryParameter);
|
||||
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
|
||||
localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
|
||||
|
||||
return {
|
||||
url: toPathString(localVarUrlObj),
|
||||
options: localVarRequestOptions,
|
||||
};
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
getStorageTemplateOptions: async (options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
|
||||
const localVarPath = `/system-config/storage-template-options`;
|
||||
// use dummy base URL string because the URL constructor only accepts absolute URLs.
|
||||
const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
|
||||
let baseOptions;
|
||||
if (configuration) {
|
||||
baseOptions = configuration.baseOptions;
|
||||
}
|
||||
|
||||
const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options};
|
||||
const localVarHeaderParameter = {} as any;
|
||||
const localVarQueryParameter = {} as any;
|
||||
|
||||
// authentication bearer required
|
||||
// http bearer authentication required
|
||||
await setBearerAuthToObject(localVarHeaderParameter, configuration)
|
||||
|
||||
|
||||
|
||||
setSearchParams(localVarUrlObj, localVarQueryParameter);
|
||||
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
|
||||
localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
|
||||
@@ -5388,6 +5502,15 @@ export const SystemConfigApiFp = function(configuration?: Configuration) {
|
||||
const localVarAxiosArgs = await localVarAxiosParamCreator.getDefaults(options);
|
||||
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
async getStorageTemplateOptions(options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<SystemConfigTemplateStorageOptionDto>> {
|
||||
const localVarAxiosArgs = await localVarAxiosParamCreator.getStorageTemplateOptions(options);
|
||||
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @param {SystemConfigDto} systemConfigDto
|
||||
@@ -5424,6 +5547,14 @@ export const SystemConfigApiFactory = function (configuration?: Configuration, b
|
||||
getDefaults(options?: any): AxiosPromise<SystemConfigDto> {
|
||||
return localVarFp.getDefaults(options).then((request) => request(axios, basePath));
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
getStorageTemplateOptions(options?: any): AxiosPromise<SystemConfigTemplateStorageOptionDto> {
|
||||
return localVarFp.getStorageTemplateOptions(options).then((request) => request(axios, basePath));
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @param {SystemConfigDto} systemConfigDto
|
||||
@@ -5463,6 +5594,16 @@ export class SystemConfigApi extends BaseAPI {
|
||||
return SystemConfigApiFp(this.configuration).getDefaults(options).then((request) => request(this.axios, this.basePath));
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
* @memberof SystemConfigApi
|
||||
*/
|
||||
public getStorageTemplateOptions(options?: AxiosRequestConfig) {
|
||||
return SystemConfigApiFp(this.configuration).getStorageTemplateOptions(options).then((request) => request(this.axios, this.basePath));
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {SystemConfigDto} systemConfigDto
|
||||
|
||||
2
web/src/api/open-api/base.ts
generated
2
web/src/api/open-api/base.ts
generated
@@ -4,7 +4,7 @@
|
||||
* Immich
|
||||
* Immich API
|
||||
*
|
||||
* The version of the OpenAPI document: 1.38.0
|
||||
* The version of the OpenAPI document: 1.38.2
|
||||
*
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||
|
||||
2
web/src/api/open-api/common.ts
generated
2
web/src/api/open-api/common.ts
generated
@@ -4,7 +4,7 @@
|
||||
* Immich
|
||||
* Immich API
|
||||
*
|
||||
* The version of the OpenAPI document: 1.38.0
|
||||
* The version of the OpenAPI document: 1.38.2
|
||||
*
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user